mirror of
https://github.com/glfw/glfw.git
synced 2024-11-10 00:51:47 +00:00
Wayland: Add initial support for libdecor
This is partly based on the implementation of libdecor support in
PR #1693 by @ christianrauch.
Where available, the libdecor library is loaded at init and becomes the
preferred method for window decorations. On compositors that support
XDG decorations, libdecor in turn uses those. If not, libdecor has
a plug-in archtecture and may load additional libraries to either use
compositor-specific decorations or draw its own.
If necessary, support for libdecor can be disabled with the
GLFW_WAYLAND_LIBDECOR init hint. This is mostly in case some part of
the dynamic loading or duplication of header material added here turns
out to cause problems with future versions of libdecor-0.so.0.
Fixes #1639
Closes #1693
Related to #1725
This was adapted to 3.3-stable from
fbdb53b9ca
.
This commit is contained in:
parent
1ad5df8032
commit
0c2db4a23e
@ -123,6 +123,7 @@ information on what to include when reporting a bug.
|
|||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
- [Wayland] Added improved fallback window decorations via libdecor (#1639,#1693)
|
||||||
- [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450)
|
- [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450)
|
||||||
- [Wayland] Disabled alpha channel for opaque windows on systems lacking
|
- [Wayland] Disabled alpha channel for opaque windows on systems lacking
|
||||||
`EGL_EXT_present_opaque` (#1895)
|
`EGL_EXT_present_opaque` (#1895)
|
||||||
|
@ -122,6 +122,14 @@ wayland-protocols 1.6, and mandatory at build time. If the running compositor
|
|||||||
does not support this protocol, the screensaver may start even for full screen
|
does not support this protocol, the screensaver may start even for full screen
|
||||||
windows.
|
windows.
|
||||||
|
|
||||||
|
GLFW uses the [libdecor library](https://gitlab.freedesktop.org/libdecor/libdecor)
|
||||||
|
for window decorations, where available. This in turn provides good quality
|
||||||
|
client-side decorations (drawn by the application) on desktop systems that do
|
||||||
|
not support server-side decorations (drawn by the window manager). On systems
|
||||||
|
that do not provide either libdecor or xdg-decoration, very basic window
|
||||||
|
decorations are provided. These do not include the window title or any caption
|
||||||
|
buttons.
|
||||||
|
|
||||||
GLFW uses the [xdg-decoration
|
GLFW uses the [xdg-decoration
|
||||||
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml)
|
protocol](https://cgit.freedesktop.org/wayland/wayland-protocols/tree/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml)
|
||||||
to request decorations to be drawn around its windows. This protocol is part
|
to request decorations to be drawn around its windows. This protocol is part
|
||||||
|
@ -102,6 +102,30 @@ a nib or manually, when the first window is created, which is when AppKit is
|
|||||||
initialized. Set this with @ref glfwInitHint.
|
initialized. Set this with @ref glfwInitHint.
|
||||||
|
|
||||||
|
|
||||||
|
@subsubsection init_hints_wayland Wayland specific init hints
|
||||||
|
|
||||||
|
@anchor GLFW_WAYLAND_LIBDECOR_hint
|
||||||
|
__GLFW_WAYLAND_LIBDECOR__ specifies whether to use
|
||||||
|
[libdecor](https://gitlab.freedesktop.org/libdecor/libdecor) for window
|
||||||
|
decorations where available. Possible values are `GLFW_WAYLAND_PREFER_LIBDECOR`
|
||||||
|
and `GLFW_WAYLAND_DISABLE_LIBDECOR`. This is ignored on other platforms.
|
||||||
|
|
||||||
|
@note This init hint was added in 3.3.9 and is not present in earlier patch releases. It
|
||||||
|
is safe to attempt to set this hint on earlier versions of GLFW 3.3 but it will emit
|
||||||
|
a harmless @ref GLFW_INVALID_ENUM error. If you need to avoid causing any errors, you can
|
||||||
|
check the library version first with @ref glfwGetVersion.
|
||||||
|
|
||||||
|
@note To set this hint while also building against earlier versions of GLFW 3.3, you can
|
||||||
|
use the numerical constants directly.
|
||||||
|
|
||||||
|
@note @code
|
||||||
|
int minor, patch;
|
||||||
|
glfwGetVersion(NULL, &minor, &patch);
|
||||||
|
if (minor > 3 || (minor == 3 && patch >= 9))
|
||||||
|
glfwInitHint(0x00053001 /*GLFW_WAYLAND_LIBDECOR*/, 0x00038002 /*GLFW_WAYLAND_DISABLE_LIBDECOR*/);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
|
||||||
@subsubsection init_hints_values Supported and default values
|
@subsubsection init_hints_values Supported and default values
|
||||||
|
|
||||||
Initialization hint | Default value | Supported values
|
Initialization hint | Default value | Supported values
|
||||||
@ -109,6 +133,7 @@ Initialization hint | Default value | Supported values
|
|||||||
@ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
@ref GLFW_JOYSTICK_HAT_BUTTONS | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
@ref GLFW_COCOA_CHDIR_RESOURCES | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
@ref GLFW_COCOA_MENUBAR | `GLFW_TRUE` | `GLFW_TRUE` or `GLFW_FALSE`
|
||||||
|
@ref GLFW_WAYLAND_LIBDECOR | `GLFW_WAYLAND_PREFER_LIBDECOR` | `GLFW_WAYLAND_PREFER_LIBDECOR` or `GLFW_WAYLAND_DISABLE_LIBDECOR`
|
||||||
|
|
||||||
|
|
||||||
@subsection intro_init_terminate Terminating GLFW
|
@subsection intro_init_terminate Terminating GLFW
|
||||||
|
@ -37,6 +37,16 @@ SDK](https://vulkan.lunarg.com/).
|
|||||||
For more information see @ref vulkan_guide.
|
For more information see @ref vulkan_guide.
|
||||||
|
|
||||||
|
|
||||||
|
@subsubsection wayland_libdecor_33 Wayland libdecor decorations
|
||||||
|
|
||||||
|
GLFW now supports improved fallback window decorations via
|
||||||
|
[libdecor](https://gitlab.freedesktop.org/libdecor/libdecor).
|
||||||
|
|
||||||
|
Support for libdecor can be toggled before GLFW is initialized with the
|
||||||
|
[GLFW_WAYLAND_LIBDECOR](@ref GLFW_WAYLAND_LIBDECOR_hint) init hint. It is
|
||||||
|
enabled by default.
|
||||||
|
|
||||||
|
|
||||||
@subsubsection content_scale_33 Content scale queries for DPI-aware rendering
|
@subsubsection content_scale_33 Content scale queries for DPI-aware rendering
|
||||||
|
|
||||||
GLFW now provides content scales for windows and monitors, i.e. the ratio
|
GLFW now provides content scales for windows and monitors, i.e. the ratio
|
||||||
@ -443,6 +453,9 @@ Use Wayland or X11 instead.
|
|||||||
- @ref GLFWwindowmaximizefun
|
- @ref GLFWwindowmaximizefun
|
||||||
- @ref GLFWwindowcontentscalefun
|
- @ref GLFWwindowcontentscalefun
|
||||||
- @ref GLFWgamepadstate
|
- @ref GLFWgamepadstate
|
||||||
|
- @ref GLFW_WAYLAND_LIBDECOR
|
||||||
|
- @ref GLFW_WAYLAND_PREFER_LIBDECOR
|
||||||
|
- @ref GLFW_WAYLAND_DISABLE_LIBDECOR
|
||||||
|
|
||||||
|
|
||||||
@subsubsection constants_33 New constants in version 3.3
|
@subsubsection constants_33 New constants in version 3.3
|
||||||
|
@ -1063,6 +1063,9 @@ extern "C" {
|
|||||||
#define GLFW_EGL_CONTEXT_API 0x00036002
|
#define GLFW_EGL_CONTEXT_API 0x00036002
|
||||||
#define GLFW_OSMESA_CONTEXT_API 0x00036003
|
#define GLFW_OSMESA_CONTEXT_API 0x00036003
|
||||||
|
|
||||||
|
#define GLFW_WAYLAND_PREFER_LIBDECOR 0x00038001
|
||||||
|
#define GLFW_WAYLAND_DISABLE_LIBDECOR 0x00038002
|
||||||
|
|
||||||
/*! @defgroup shapes Standard cursor shapes
|
/*! @defgroup shapes Standard cursor shapes
|
||||||
* @brief Standard system cursor shapes.
|
* @brief Standard system cursor shapes.
|
||||||
*
|
*
|
||||||
@ -1123,6 +1126,11 @@ extern "C" {
|
|||||||
* macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint).
|
* macOS specific [init hint](@ref GLFW_COCOA_MENUBAR_hint).
|
||||||
*/
|
*/
|
||||||
#define GLFW_COCOA_MENUBAR 0x00051002
|
#define GLFW_COCOA_MENUBAR 0x00051002
|
||||||
|
/*! @brief Wayland specific init hint.
|
||||||
|
*
|
||||||
|
* Wayland specific [init hint](@ref GLFW_WAYLAND_LIBDECOR_hint).
|
||||||
|
*/
|
||||||
|
#define GLFW_WAYLAND_LIBDECOR 0x00053001
|
||||||
/*! @} */
|
/*! @} */
|
||||||
|
|
||||||
#define GLFW_DONT_CARE -1
|
#define GLFW_DONT_CARE -1
|
||||||
|
@ -54,7 +54,10 @@ static _GLFWinitconfig _glfwInitHints =
|
|||||||
{
|
{
|
||||||
GLFW_TRUE, // macOS menu bar
|
GLFW_TRUE, // macOS menu bar
|
||||||
GLFW_TRUE // macOS bundle chdir
|
GLFW_TRUE // macOS bundle chdir
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
GLFW_WAYLAND_PREFER_LIBDECOR // Wayland libdecor mode
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Terminate the library
|
// Terminate the library
|
||||||
@ -367,6 +370,9 @@ GLFWAPI void glfwInitHint(int hint, int value)
|
|||||||
case GLFW_COCOA_MENUBAR:
|
case GLFW_COCOA_MENUBAR:
|
||||||
_glfwInitHints.ns.menubar = value;
|
_glfwInitHints.ns.menubar = value;
|
||||||
return;
|
return;
|
||||||
|
case GLFW_WAYLAND_LIBDECOR:
|
||||||
|
_glfwInitHints.wl.libdecorMode = value;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfwInputError(GLFW_INVALID_ENUM,
|
_glfwInputError(GLFW_INVALID_ENUM,
|
||||||
|
@ -244,6 +244,9 @@ struct _GLFWinitconfig
|
|||||||
GLFWbool menubar;
|
GLFWbool menubar;
|
||||||
GLFWbool chdir;
|
GLFWbool chdir;
|
||||||
} ns;
|
} ns;
|
||||||
|
struct {
|
||||||
|
int libdecorMode;
|
||||||
|
} wl;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Window configuration
|
// Window configuration
|
||||||
|
119
src/wl_init.c
119
src/wl_init.c
@ -163,6 +163,20 @@ static const struct wl_registry_listener registryListener =
|
|||||||
registryHandleGlobalRemove
|
registryHandleGlobalRemove
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void libdecorHandleError(struct libdecor* context,
|
||||||
|
enum libdecor_error error,
|
||||||
|
const char* message)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: libdecor error %u: %s",
|
||||||
|
error, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct libdecor_interface libdecorInterface =
|
||||||
|
{
|
||||||
|
libdecorHandleError
|
||||||
|
};
|
||||||
|
|
||||||
// Create key code translation tables
|
// Create key code translation tables
|
||||||
//
|
//
|
||||||
static void createKeyTables(void)
|
static void createKeyTables(void)
|
||||||
@ -433,6 +447,93 @@ int _glfwPlatformInit(void)
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_glfw.hints.init.wl.libdecorMode == GLFW_WAYLAND_PREFER_LIBDECOR)
|
||||||
|
_glfw.wl.libdecor.handle = _glfw_dlopen("libdecor-0.so.0");
|
||||||
|
|
||||||
|
if (_glfw.wl.libdecor.handle)
|
||||||
|
{
|
||||||
|
_glfw.wl.libdecor.libdecor_new_ = (PFN_libdecor_new)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_new");
|
||||||
|
_glfw.wl.libdecor.libdecor_unref_ = (PFN_libdecor_unref)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_unref");
|
||||||
|
_glfw.wl.libdecor.libdecor_get_fd_ = (PFN_libdecor_get_fd)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_get_fd");
|
||||||
|
_glfw.wl.libdecor.libdecor_dispatch_ = (PFN_libdecor_dispatch)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_dispatch");
|
||||||
|
_glfw.wl.libdecor.libdecor_decorate_ = (PFN_libdecor_decorate)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_decorate");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_unref_ = (PFN_libdecor_frame_unref)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unref");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_set_app_id_ = (PFN_libdecor_frame_set_app_id)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_app_id");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_set_title_ = (PFN_libdecor_frame_set_title)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_title");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_set_minimized_ = (PFN_libdecor_frame_set_minimized)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_minimized");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_set_fullscreen_ = (PFN_libdecor_frame_set_fullscreen)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_fullscreen");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ = (PFN_libdecor_frame_unset_fullscreen)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unset_fullscreen");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_map_ = (PFN_libdecor_frame_map)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_map");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_commit_ = (PFN_libdecor_frame_commit)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_commit");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_set_min_content_size_ = (PFN_libdecor_frame_set_min_content_size)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_min_content_size");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_set_max_content_size_ = (PFN_libdecor_frame_set_max_content_size)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_max_content_size");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_set_maximized_ = (PFN_libdecor_frame_set_maximized)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_maximized");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_unset_maximized_ = (PFN_libdecor_frame_unset_maximized)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unset_maximized");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_set_capabilities_ = (PFN_libdecor_frame_set_capabilities)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_capabilities");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ = (PFN_libdecor_frame_unset_capabilities)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_unset_capabilities");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_set_visibility_ = (PFN_libdecor_frame_set_visibility)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_set_visibility");
|
||||||
|
_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ = (PFN_libdecor_frame_get_xdg_toplevel)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_frame_get_xdg_toplevel");
|
||||||
|
_glfw.wl.libdecor.libdecor_configuration_get_content_size_ = (PFN_libdecor_configuration_get_content_size)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_configuration_get_content_size");
|
||||||
|
_glfw.wl.libdecor.libdecor_configuration_get_window_state_ = (PFN_libdecor_configuration_get_window_state)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_configuration_get_window_state");
|
||||||
|
_glfw.wl.libdecor.libdecor_state_new_ = (PFN_libdecor_state_new)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_state_new");
|
||||||
|
_glfw.wl.libdecor.libdecor_state_free_ = (PFN_libdecor_state_free)
|
||||||
|
_glfw_dlsym(_glfw.wl.libdecor.handle, "libdecor_state_free");
|
||||||
|
|
||||||
|
if (!_glfw.wl.libdecor.libdecor_new_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_unref_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_get_fd_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_dispatch_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_decorate_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_unref_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_set_app_id_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_set_title_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_set_minimized_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_set_fullscreen_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_unset_fullscreen_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_map_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_commit_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_set_min_content_size_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_set_max_content_size_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_set_maximized_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_unset_maximized_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_set_capabilities_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_unset_capabilities_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_set_visibility_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_configuration_get_content_size_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_configuration_get_window_state_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_state_new_ ||
|
||||||
|
!_glfw.wl.libdecor.libdecor_state_free_)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(_glfw.wl.libdecor.handle);
|
||||||
|
memset(&_glfw.wl.libdecor, 0, sizeof(_glfw.wl.libdecor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||||
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
||||||
|
|
||||||
@ -459,6 +560,15 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
_glfwInitTimerPOSIX();
|
_glfwInitTimerPOSIX();
|
||||||
|
|
||||||
|
if (_glfw.wl.libdecor.handle)
|
||||||
|
{
|
||||||
|
_glfw.wl.libdecor.context = libdecor_new(_glfw.wl.display, &libdecorInterface);
|
||||||
|
|
||||||
|
// Allow libdecor to receive its globals before proceeding
|
||||||
|
if (_glfw.wl.libdecor.context)
|
||||||
|
libdecor_dispatch(_glfw.wl.libdecor.context, 1);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
|
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
|
||||||
if (wl_seat_get_version(_glfw.wl.seat) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
|
if (wl_seat_get_version(_glfw.wl.seat) >= WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION)
|
||||||
{
|
{
|
||||||
@ -503,6 +613,15 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfwTerminateEGL();
|
_glfwTerminateEGL();
|
||||||
_glfwTerminateOSMesa();
|
_glfwTerminateOSMesa();
|
||||||
|
|
||||||
|
if (_glfw.wl.libdecor.context)
|
||||||
|
libdecor_unref(_glfw.wl.libdecor.context);
|
||||||
|
|
||||||
|
if (_glfw.wl.libdecor.handle)
|
||||||
|
{
|
||||||
|
_glfw_dlclose(_glfw.wl.libdecor.handle);
|
||||||
|
_glfw.wl.libdecor.handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (_glfw.wl.egl.handle)
|
if (_glfw.wl.egl.handle)
|
||||||
{
|
{
|
||||||
_glfw_dlclose(_glfw.wl.egl.handle);
|
_glfw_dlclose(_glfw.wl.egl.handle);
|
||||||
|
@ -29,6 +29,8 @@
|
|||||||
#include <xkbcommon/xkbcommon-compose.h>
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
||||||
|
|
||||||
typedef struct VkWaylandSurfaceCreateInfoKHR
|
typedef struct VkWaylandSurfaceCreateInfoKHR
|
||||||
@ -146,6 +148,122 @@ typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_st
|
|||||||
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
|
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
|
||||||
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
|
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
|
||||||
|
|
||||||
|
struct libdecor;
|
||||||
|
struct libdecor_frame;
|
||||||
|
struct libdecor_state;
|
||||||
|
struct libdecor_configuration;
|
||||||
|
|
||||||
|
enum libdecor_error
|
||||||
|
{
|
||||||
|
LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
|
||||||
|
LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum libdecor_window_state
|
||||||
|
{
|
||||||
|
LIBDECOR_WINDOW_STATE_NONE = 0,
|
||||||
|
LIBDECOR_WINDOW_STATE_ACTIVE = 1,
|
||||||
|
LIBDECOR_WINDOW_STATE_MAXIMIZED = 2,
|
||||||
|
LIBDECOR_WINDOW_STATE_FULLSCREEN = 4,
|
||||||
|
LIBDECOR_WINDOW_STATE_TILED_LEFT = 8,
|
||||||
|
LIBDECOR_WINDOW_STATE_TILED_RIGHT = 16,
|
||||||
|
LIBDECOR_WINDOW_STATE_TILED_TOP = 32,
|
||||||
|
LIBDECOR_WINDOW_STATE_TILED_BOTTOM = 64
|
||||||
|
};
|
||||||
|
|
||||||
|
enum libdecor_capabilities
|
||||||
|
{
|
||||||
|
LIBDECOR_ACTION_MOVE = 1,
|
||||||
|
LIBDECOR_ACTION_RESIZE = 2,
|
||||||
|
LIBDECOR_ACTION_MINIMIZE = 4,
|
||||||
|
LIBDECOR_ACTION_FULLSCREEN = 8,
|
||||||
|
LIBDECOR_ACTION_CLOSE = 16
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libdecor_interface
|
||||||
|
{
|
||||||
|
void (* error)(struct libdecor*,enum libdecor_error,const char*);
|
||||||
|
void (* reserved0)(void);
|
||||||
|
void (* reserved1)(void);
|
||||||
|
void (* reserved2)(void);
|
||||||
|
void (* reserved3)(void);
|
||||||
|
void (* reserved4)(void);
|
||||||
|
void (* reserved5)(void);
|
||||||
|
void (* reserved6)(void);
|
||||||
|
void (* reserved7)(void);
|
||||||
|
void (* reserved8)(void);
|
||||||
|
void (* reserved9)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct libdecor_frame_interface
|
||||||
|
{
|
||||||
|
void (* configure)(struct libdecor_frame*,struct libdecor_configuration*,void*);
|
||||||
|
void (* close)(struct libdecor_frame*,void*);
|
||||||
|
void (* commit)(struct libdecor_frame*,void*);
|
||||||
|
void (* dismiss_popup)(struct libdecor_frame*,const char*,void*);
|
||||||
|
void (* reserved0)(void);
|
||||||
|
void (* reserved1)(void);
|
||||||
|
void (* reserved2)(void);
|
||||||
|
void (* reserved3)(void);
|
||||||
|
void (* reserved4)(void);
|
||||||
|
void (* reserved5)(void);
|
||||||
|
void (* reserved6)(void);
|
||||||
|
void (* reserved7)(void);
|
||||||
|
void (* reserved8)(void);
|
||||||
|
void (* reserved9)(void);
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct libdecor* (* PFN_libdecor_new)(struct wl_display*,const struct libdecor_interface*);
|
||||||
|
typedef void (* PFN_libdecor_unref)(struct libdecor*);
|
||||||
|
typedef int (* PFN_libdecor_get_fd)(struct libdecor*);
|
||||||
|
typedef int (* PFN_libdecor_dispatch)(struct libdecor*,int);
|
||||||
|
typedef struct libdecor_frame* (* PFN_libdecor_decorate)(struct libdecor*,struct wl_surface*,const struct libdecor_frame_interface*,void*);
|
||||||
|
typedef void (* PFN_libdecor_frame_unref)(struct libdecor_frame*);
|
||||||
|
typedef void (* PFN_libdecor_frame_set_app_id)(struct libdecor_frame*,const char*);
|
||||||
|
typedef void (* PFN_libdecor_frame_set_title)(struct libdecor_frame*,const char*);
|
||||||
|
typedef void (* PFN_libdecor_frame_set_minimized)(struct libdecor_frame*);
|
||||||
|
typedef void (* PFN_libdecor_frame_set_fullscreen)(struct libdecor_frame*,struct wl_output*);
|
||||||
|
typedef void (* PFN_libdecor_frame_unset_fullscreen)(struct libdecor_frame*);
|
||||||
|
typedef void (* PFN_libdecor_frame_map)(struct libdecor_frame*);
|
||||||
|
typedef void (* PFN_libdecor_frame_commit)(struct libdecor_frame*,struct libdecor_state*,struct libdecor_configuration*);
|
||||||
|
typedef void (* PFN_libdecor_frame_set_min_content_size)(struct libdecor_frame*,int,int);
|
||||||
|
typedef void (* PFN_libdecor_frame_set_max_content_size)(struct libdecor_frame*,int,int);
|
||||||
|
typedef void (* PFN_libdecor_frame_set_maximized)(struct libdecor_frame*);
|
||||||
|
typedef void (* PFN_libdecor_frame_unset_maximized)(struct libdecor_frame*);
|
||||||
|
typedef void (* PFN_libdecor_frame_set_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
|
||||||
|
typedef void (* PFN_libdecor_frame_unset_capabilities)(struct libdecor_frame*,enum libdecor_capabilities);
|
||||||
|
typedef void (* PFN_libdecor_frame_set_visibility)(struct libdecor_frame*,bool visible);
|
||||||
|
typedef struct xdg_toplevel* (* PFN_libdecor_frame_get_xdg_toplevel)(struct libdecor_frame*);
|
||||||
|
typedef bool (* PFN_libdecor_configuration_get_content_size)(struct libdecor_configuration*,struct libdecor_frame*,int*,int*);
|
||||||
|
typedef bool (* PFN_libdecor_configuration_get_window_state)(struct libdecor_configuration*,enum libdecor_window_state*);
|
||||||
|
typedef struct libdecor_state* (* PFN_libdecor_state_new)(int,int);
|
||||||
|
typedef void (* PFN_libdecor_state_free)(struct libdecor_state*);
|
||||||
|
#define libdecor_new _glfw.wl.libdecor.libdecor_new_
|
||||||
|
#define libdecor_unref _glfw.wl.libdecor.libdecor_unref_
|
||||||
|
#define libdecor_get_fd _glfw.wl.libdecor.libdecor_get_fd_
|
||||||
|
#define libdecor_dispatch _glfw.wl.libdecor.libdecor_dispatch_
|
||||||
|
#define libdecor_decorate _glfw.wl.libdecor.libdecor_decorate_
|
||||||
|
#define libdecor_frame_unref _glfw.wl.libdecor.libdecor_frame_unref_
|
||||||
|
#define libdecor_frame_set_app_id _glfw.wl.libdecor.libdecor_frame_set_app_id_
|
||||||
|
#define libdecor_frame_set_title _glfw.wl.libdecor.libdecor_frame_set_title_
|
||||||
|
#define libdecor_frame_set_minimized _glfw.wl.libdecor.libdecor_frame_set_minimized_
|
||||||
|
#define libdecor_frame_set_fullscreen _glfw.wl.libdecor.libdecor_frame_set_fullscreen_
|
||||||
|
#define libdecor_frame_unset_fullscreen _glfw.wl.libdecor.libdecor_frame_unset_fullscreen_
|
||||||
|
#define libdecor_frame_map _glfw.wl.libdecor.libdecor_frame_map_
|
||||||
|
#define libdecor_frame_commit _glfw.wl.libdecor.libdecor_frame_commit_
|
||||||
|
#define libdecor_frame_set_min_content_size _glfw.wl.libdecor.libdecor_frame_set_min_content_size_
|
||||||
|
#define libdecor_frame_set_max_content_size _glfw.wl.libdecor.libdecor_frame_set_max_content_size_
|
||||||
|
#define libdecor_frame_set_maximized _glfw.wl.libdecor.libdecor_frame_set_maximized_
|
||||||
|
#define libdecor_frame_unset_maximized _glfw.wl.libdecor.libdecor_frame_unset_maximized_
|
||||||
|
#define libdecor_frame_set_capabilities _glfw.wl.libdecor.libdecor_frame_set_capabilities_
|
||||||
|
#define libdecor_frame_unset_capabilities _glfw.wl.libdecor.libdecor_frame_unset_capabilities_
|
||||||
|
#define libdecor_frame_set_visibility _glfw.wl.libdecor.libdecor_frame_set_visibility_
|
||||||
|
#define libdecor_frame_get_xdg_toplevel _glfw.wl.libdecor.libdecor_frame_get_xdg_toplevel_
|
||||||
|
#define libdecor_configuration_get_content_size _glfw.wl.libdecor.libdecor_configuration_get_content_size_
|
||||||
|
#define libdecor_configuration_get_window_state _glfw.wl.libdecor.libdecor_configuration_get_window_state_
|
||||||
|
#define libdecor_state_new _glfw.wl.libdecor.libdecor_state_new_
|
||||||
|
#define libdecor_state_free _glfw.wl.libdecor.libdecor_state_free_
|
||||||
|
|
||||||
typedef enum _GLFWdecorationSideWayland
|
typedef enum _GLFWdecorationSideWayland
|
||||||
{
|
{
|
||||||
GLFW_MAIN_WINDOW,
|
GLFW_MAIN_WINDOW,
|
||||||
@ -208,6 +326,11 @@ typedef struct _GLFWwindowWayland
|
|||||||
uint32_t decorationMode;
|
uint32_t decorationMode;
|
||||||
} xdg;
|
} xdg;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct libdecor_frame* frame;
|
||||||
|
int mode;
|
||||||
|
} libdecor;
|
||||||
|
|
||||||
_GLFWcursor* currentCursor;
|
_GLFWcursor* currentCursor;
|
||||||
double cursorPosX, cursorPosY;
|
double cursorPosX, cursorPosY;
|
||||||
|
|
||||||
@ -340,6 +463,36 @@ typedef struct _GLFWlibraryWayland
|
|||||||
PFN_wl_egl_window_destroy window_destroy;
|
PFN_wl_egl_window_destroy window_destroy;
|
||||||
PFN_wl_egl_window_resize window_resize;
|
PFN_wl_egl_window_resize window_resize;
|
||||||
} egl;
|
} egl;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
void* handle;
|
||||||
|
struct libdecor* context;
|
||||||
|
PFN_libdecor_new libdecor_new_;
|
||||||
|
PFN_libdecor_unref libdecor_unref_;
|
||||||
|
PFN_libdecor_get_fd libdecor_get_fd_;
|
||||||
|
PFN_libdecor_dispatch libdecor_dispatch_;
|
||||||
|
PFN_libdecor_decorate libdecor_decorate_;
|
||||||
|
PFN_libdecor_frame_unref libdecor_frame_unref_;
|
||||||
|
PFN_libdecor_frame_set_app_id libdecor_frame_set_app_id_;
|
||||||
|
PFN_libdecor_frame_set_title libdecor_frame_set_title_;
|
||||||
|
PFN_libdecor_frame_set_minimized libdecor_frame_set_minimized_;
|
||||||
|
PFN_libdecor_frame_set_fullscreen libdecor_frame_set_fullscreen_;
|
||||||
|
PFN_libdecor_frame_unset_fullscreen libdecor_frame_unset_fullscreen_;
|
||||||
|
PFN_libdecor_frame_map libdecor_frame_map_;
|
||||||
|
PFN_libdecor_frame_commit libdecor_frame_commit_;
|
||||||
|
PFN_libdecor_frame_set_min_content_size libdecor_frame_set_min_content_size_;
|
||||||
|
PFN_libdecor_frame_set_max_content_size libdecor_frame_set_max_content_size_;
|
||||||
|
PFN_libdecor_frame_set_maximized libdecor_frame_set_maximized_;
|
||||||
|
PFN_libdecor_frame_unset_maximized libdecor_frame_unset_maximized_;
|
||||||
|
PFN_libdecor_frame_set_capabilities libdecor_frame_set_capabilities_;
|
||||||
|
PFN_libdecor_frame_unset_capabilities libdecor_frame_unset_capabilities_;
|
||||||
|
PFN_libdecor_frame_set_visibility libdecor_frame_set_visibility_;
|
||||||
|
PFN_libdecor_frame_get_xdg_toplevel libdecor_frame_get_xdg_toplevel_;
|
||||||
|
PFN_libdecor_configuration_get_content_size libdecor_configuration_get_content_size_;
|
||||||
|
PFN_libdecor_configuration_get_window_state libdecor_configuration_get_window_state_;
|
||||||
|
PFN_libdecor_state_new libdecor_state_new_;
|
||||||
|
PFN_libdecor_state_free libdecor_state_free_;
|
||||||
|
} libdecor;
|
||||||
} _GLFWlibraryWayland;
|
} _GLFWlibraryWayland;
|
||||||
|
|
||||||
// Wayland-specific per-monitor data
|
// Wayland-specific per-monitor data
|
||||||
|
301
src/wl_window.c
301
src/wl_window.c
@ -486,7 +486,12 @@ static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
|
|||||||
//
|
//
|
||||||
static void acquireMonitor(_GLFWwindow* window)
|
static void acquireMonitor(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.toplevel)
|
if (window->wl.libdecor.frame)
|
||||||
|
{
|
||||||
|
libdecor_frame_set_fullscreen(window->wl.libdecor.frame,
|
||||||
|
window->monitor->wl.output);
|
||||||
|
}
|
||||||
|
else if (window->wl.xdg.toplevel)
|
||||||
{
|
{
|
||||||
xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,
|
xdg_toplevel_set_fullscreen(window->wl.xdg.toplevel,
|
||||||
window->monitor->wl.output);
|
window->monitor->wl.output);
|
||||||
@ -502,12 +507,15 @@ static void acquireMonitor(_GLFWwindow* window)
|
|||||||
//
|
//
|
||||||
static void releaseMonitor(_GLFWwindow* window)
|
static void releaseMonitor(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.toplevel)
|
if (window->wl.libdecor.frame)
|
||||||
|
libdecor_frame_unset_fullscreen(window->wl.libdecor.frame);
|
||||||
|
else if (window->wl.xdg.toplevel)
|
||||||
xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
|
xdg_toplevel_unset_fullscreen(window->wl.xdg.toplevel);
|
||||||
|
|
||||||
setIdleInhibitor(window, GLFW_FALSE);
|
setIdleInhibitor(window, GLFW_FALSE);
|
||||||
|
|
||||||
if (window->wl.xdg.decorationMode != ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE)
|
if (!window->wl.libdecor.frame &&
|
||||||
|
window->wl.xdg.decorationMode != ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE)
|
||||||
{
|
{
|
||||||
if (window->decorated)
|
if (window->decorated)
|
||||||
createFallbackDecorations(window);
|
createFallbackDecorations(window);
|
||||||
@ -650,7 +658,187 @@ static const struct xdg_surface_listener xdgSurfaceListener =
|
|||||||
xdgSurfaceHandleConfigure
|
xdgSurfaceHandleConfigure
|
||||||
};
|
};
|
||||||
|
|
||||||
static GLFWbool createShellObjects(_GLFWwindow* window)
|
void libdecorFrameHandleConfigure(struct libdecor_frame* frame,
|
||||||
|
struct libdecor_configuration* config,
|
||||||
|
void* userData)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = userData;
|
||||||
|
int width, height;
|
||||||
|
|
||||||
|
enum libdecor_window_state windowState;
|
||||||
|
GLFWbool fullscreen, activated, maximized;
|
||||||
|
|
||||||
|
if (libdecor_configuration_get_window_state(config, &windowState))
|
||||||
|
{
|
||||||
|
fullscreen = (windowState & LIBDECOR_WINDOW_STATE_FULLSCREEN) != 0;
|
||||||
|
activated = (windowState & LIBDECOR_WINDOW_STATE_ACTIVE) != 0;
|
||||||
|
maximized = (windowState & LIBDECOR_WINDOW_STATE_MAXIMIZED) != 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fullscreen = window->wl.fullscreen;
|
||||||
|
activated = window->wl.activated;
|
||||||
|
maximized = window->wl.maximized;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!libdecor_configuration_get_content_size(config, frame, &width, &height))
|
||||||
|
{
|
||||||
|
width = window->wl.width;
|
||||||
|
height = window->wl.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!maximized && !fullscreen)
|
||||||
|
{
|
||||||
|
if (window->numer != GLFW_DONT_CARE && window->denom != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
const float aspectRatio = (float) width / (float) height;
|
||||||
|
const float targetRatio = (float) window->numer / (float) window->denom;
|
||||||
|
if (aspectRatio < targetRatio)
|
||||||
|
height = width / targetRatio;
|
||||||
|
else if (aspectRatio > targetRatio)
|
||||||
|
width = height * targetRatio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libdecor_state* frameState = libdecor_state_new(width, height);
|
||||||
|
libdecor_frame_commit(frame, frameState, config);
|
||||||
|
libdecor_state_free(frameState);
|
||||||
|
|
||||||
|
if (window->wl.activated != activated)
|
||||||
|
{
|
||||||
|
window->wl.activated = activated;
|
||||||
|
if (!window->wl.activated)
|
||||||
|
{
|
||||||
|
if (window->monitor && window->autoIconify)
|
||||||
|
libdecor_frame_set_minimized(window->wl.libdecor.frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->wl.maximized != maximized)
|
||||||
|
{
|
||||||
|
window->wl.maximized = maximized;
|
||||||
|
_glfwInputWindowMaximize(window, window->wl.maximized);
|
||||||
|
}
|
||||||
|
|
||||||
|
window->wl.fullscreen = fullscreen;
|
||||||
|
|
||||||
|
GLFWbool damaged = GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!window->wl.visible)
|
||||||
|
{
|
||||||
|
window->wl.visible = GLFW_TRUE;
|
||||||
|
damaged = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width != window->wl.width || height != window->wl.height)
|
||||||
|
{
|
||||||
|
window->wl.width = width;
|
||||||
|
window->wl.height = height;
|
||||||
|
resizeWindow(window);
|
||||||
|
|
||||||
|
_glfwInputWindowSize(window, width, height);
|
||||||
|
damaged = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (damaged)
|
||||||
|
_glfwInputWindowDamage(window);
|
||||||
|
else
|
||||||
|
wl_surface_commit(window->wl.surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void libdecorFrameHandleClose(struct libdecor_frame* frame, void* userData)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = userData;
|
||||||
|
_glfwInputWindowCloseRequest(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void libdecorFrameHandleCommit(struct libdecor_frame* frame, void* userData)
|
||||||
|
{
|
||||||
|
_GLFWwindow* window = userData;
|
||||||
|
wl_surface_commit(window->wl.surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
void libdecorFrameHandleDismissPopup(struct libdecor_frame* frame,
|
||||||
|
const char* seatName,
|
||||||
|
void* userData)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct libdecor_frame_interface libdecorFrameInterface =
|
||||||
|
{
|
||||||
|
libdecorFrameHandleConfigure,
|
||||||
|
libdecorFrameHandleClose,
|
||||||
|
libdecorFrameHandleCommit,
|
||||||
|
libdecorFrameHandleDismissPopup
|
||||||
|
};
|
||||||
|
|
||||||
|
static GLFWbool createLibdecorFrame(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
window->wl.libdecor.frame = libdecor_decorate(_glfw.wl.libdecor.context,
|
||||||
|
window->wl.surface,
|
||||||
|
&libdecorFrameInterface,
|
||||||
|
window);
|
||||||
|
if (!window->wl.libdecor.frame)
|
||||||
|
{
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Failed to create libdecor frame");
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(window->wl.title))
|
||||||
|
libdecor_frame_set_title(window->wl.libdecor.frame, window->wl.title);
|
||||||
|
|
||||||
|
if (window->minwidth != GLFW_DONT_CARE &&
|
||||||
|
window->minheight != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
|
||||||
|
window->minwidth,
|
||||||
|
window->minheight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->maxwidth != GLFW_DONT_CARE &&
|
||||||
|
window->maxheight != GLFW_DONT_CARE)
|
||||||
|
{
|
||||||
|
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
|
||||||
|
window->maxwidth,
|
||||||
|
window->maxheight);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!window->resizable)
|
||||||
|
{
|
||||||
|
libdecor_frame_unset_capabilities(window->wl.libdecor.frame,
|
||||||
|
LIBDECOR_ACTION_RESIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window->monitor)
|
||||||
|
{
|
||||||
|
// HACK: Allow libdecor to finish initialization of itself and its
|
||||||
|
// plugin so it will create the xdg_toplevel for the frame
|
||||||
|
// This needs to exist when setting the frame to fullscreen
|
||||||
|
while (!libdecor_frame_get_xdg_toplevel(window->wl.libdecor.frame))
|
||||||
|
_glfwPlatformWaitEvents();
|
||||||
|
|
||||||
|
libdecor_frame_set_fullscreen(window->wl.libdecor.frame,
|
||||||
|
window->monitor->wl.output);
|
||||||
|
setIdleInhibitor(window, GLFW_TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (window->wl.maximized)
|
||||||
|
libdecor_frame_set_maximized(window->wl.libdecor.frame);
|
||||||
|
|
||||||
|
if (!window->decorated)
|
||||||
|
libdecor_frame_set_visibility(window->wl.libdecor.frame, false);
|
||||||
|
|
||||||
|
setIdleInhibitor(window, GLFW_FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
libdecor_frame_map(window->wl.libdecor.frame);
|
||||||
|
wl_display_roundtrip(_glfw.wl.display);
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWbool createXdgShellObjects(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
|
window->wl.xdg.surface = xdg_wm_base_get_xdg_surface(_glfw.wl.wmBase,
|
||||||
window->wl.surface);
|
window->wl.surface);
|
||||||
@ -743,14 +931,27 @@ static GLFWbool createShellObjects(_GLFWwindow* window)
|
|||||||
|
|
||||||
wl_surface_commit(window->wl.surface);
|
wl_surface_commit(window->wl.surface);
|
||||||
wl_display_roundtrip(_glfw.wl.display);
|
wl_display_roundtrip(_glfw.wl.display);
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GLFWbool createShellObjects(_GLFWwindow* window)
|
||||||
|
{
|
||||||
|
if (_glfw.wl.libdecor.context)
|
||||||
|
{
|
||||||
|
if (createLibdecorFrame(window))
|
||||||
|
return GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return createXdgShellObjects(window);
|
||||||
|
}
|
||||||
|
|
||||||
static void destroyShellObjects(_GLFWwindow* window)
|
static void destroyShellObjects(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
destroyFallbackDecorations(window);
|
destroyFallbackDecorations(window);
|
||||||
|
|
||||||
|
if (window->wl.libdecor.frame)
|
||||||
|
libdecor_frame_unref(window->wl.libdecor.frame);
|
||||||
|
|
||||||
if (window->wl.xdg.decoration)
|
if (window->wl.xdg.decoration)
|
||||||
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
|
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
|
||||||
|
|
||||||
@ -760,6 +961,7 @@ static void destroyShellObjects(_GLFWwindow* window)
|
|||||||
if (window->wl.xdg.surface)
|
if (window->wl.xdg.surface)
|
||||||
xdg_surface_destroy(window->wl.xdg.surface);
|
xdg_surface_destroy(window->wl.xdg.surface);
|
||||||
|
|
||||||
|
window->wl.libdecor.frame = NULL;
|
||||||
window->wl.xdg.decoration = NULL;
|
window->wl.xdg.decoration = NULL;
|
||||||
window->wl.xdg.decorationMode = 0;
|
window->wl.xdg.decorationMode = 0;
|
||||||
window->wl.xdg.toplevel = NULL;
|
window->wl.xdg.toplevel = NULL;
|
||||||
@ -926,13 +1128,17 @@ static void inputText(_GLFWwindow* window, uint32_t scancode)
|
|||||||
static void handleEvents(double* timeout)
|
static void handleEvents(double* timeout)
|
||||||
{
|
{
|
||||||
GLFWbool event = GLFW_FALSE;
|
GLFWbool event = GLFW_FALSE;
|
||||||
struct pollfd fds[] =
|
struct pollfd fds[4] =
|
||||||
{
|
{
|
||||||
{ wl_display_get_fd(_glfw.wl.display), POLLIN },
|
{ wl_display_get_fd(_glfw.wl.display), POLLIN },
|
||||||
{ _glfw.wl.keyRepeatTimerfd, POLLIN },
|
{ _glfw.wl.keyRepeatTimerfd, POLLIN },
|
||||||
{ _glfw.wl.cursorTimerfd, POLLIN },
|
{ _glfw.wl.cursorTimerfd, POLLIN },
|
||||||
|
{ -1, POLLIN }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (_glfw.wl.libdecor.context)
|
||||||
|
fds[3].fd = libdecor_get_fd(_glfw.wl.libdecor.context);
|
||||||
|
|
||||||
while (!event)
|
while (!event)
|
||||||
{
|
{
|
||||||
while (wl_display_prepare_read(_glfw.wl.display) != 0)
|
while (wl_display_prepare_read(_glfw.wl.display) != 0)
|
||||||
@ -954,7 +1160,7 @@ static void handleEvents(double* timeout)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!waitForData(fds, 3, timeout))
|
if (!waitForData(fds, sizeof(fds) / sizeof(fds[0]), timeout))
|
||||||
{
|
{
|
||||||
wl_display_cancel_read(_glfw.wl.display);
|
wl_display_cancel_read(_glfw.wl.display);
|
||||||
return;
|
return;
|
||||||
@ -999,6 +1205,9 @@ static void handleEvents(double* timeout)
|
|||||||
event = GLFW_TRUE;
|
event = GLFW_TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fds[3].revents & POLLIN)
|
||||||
|
libdecor_dispatch(_glfw.wl.libdecor.context, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1942,7 +2151,10 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
|
|||||||
if (window->wl.title)
|
if (window->wl.title)
|
||||||
free(window->wl.title);
|
free(window->wl.title);
|
||||||
window->wl.title = _glfw_strdup(title);
|
window->wl.title = _glfw_strdup(title);
|
||||||
if (window->wl.xdg.toplevel)
|
|
||||||
|
if (window->wl.libdecor.frame)
|
||||||
|
libdecor_frame_set_title(window->wl.libdecor.frame, title);
|
||||||
|
else if (window->wl.xdg.toplevel)
|
||||||
xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
|
xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1990,6 +2202,13 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
|
|||||||
window->wl.height = height;
|
window->wl.height = height;
|
||||||
resizeWindow(window);
|
resizeWindow(window);
|
||||||
|
|
||||||
|
if (window->wl.libdecor.frame)
|
||||||
|
{
|
||||||
|
struct libdecor_state* frameState = libdecor_state_new(width, height);
|
||||||
|
libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
|
||||||
|
libdecor_state_free(frameState);
|
||||||
|
}
|
||||||
|
|
||||||
if (window->wl.visible)
|
if (window->wl.visible)
|
||||||
_glfwInputWindowDamage(window);
|
_glfwInputWindowDamage(window);
|
||||||
}
|
}
|
||||||
@ -1999,7 +2218,20 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
|
|||||||
int minwidth, int minheight,
|
int minwidth, int minheight,
|
||||||
int maxwidth, int maxheight)
|
int maxwidth, int maxheight)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.toplevel)
|
if (window->wl.libdecor.frame)
|
||||||
|
{
|
||||||
|
if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
|
||||||
|
minwidth = minheight = 0;
|
||||||
|
|
||||||
|
if (maxwidth == GLFW_DONT_CARE || maxheight == GLFW_DONT_CARE)
|
||||||
|
maxwidth = maxheight = 0;
|
||||||
|
|
||||||
|
libdecor_frame_set_min_content_size(window->wl.libdecor.frame,
|
||||||
|
minwidth, minheight);
|
||||||
|
libdecor_frame_set_max_content_size(window->wl.libdecor.frame,
|
||||||
|
maxwidth, maxheight);
|
||||||
|
}
|
||||||
|
else if (window->wl.xdg.toplevel)
|
||||||
{
|
{
|
||||||
if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
|
if (minwidth == GLFW_DONT_CARE || minheight == GLFW_DONT_CARE)
|
||||||
minwidth = minheight = 0;
|
minwidth = minheight = 0;
|
||||||
@ -2053,6 +2285,13 @@ void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window,
|
|||||||
window->wl.height = height;
|
window->wl.height = height;
|
||||||
resizeWindow(window);
|
resizeWindow(window);
|
||||||
|
|
||||||
|
if (window->wl.libdecor.frame)
|
||||||
|
{
|
||||||
|
struct libdecor_state* frameState = libdecor_state_new(width, height);
|
||||||
|
libdecor_frame_commit(window->wl.libdecor.frame, frameState, NULL);
|
||||||
|
libdecor_state_free(frameState);
|
||||||
|
}
|
||||||
|
|
||||||
_glfwInputWindowSize(window, width, height);
|
_glfwInputWindowSize(window, width, height);
|
||||||
|
|
||||||
if (window->wl.visible)
|
if (window->wl.visible)
|
||||||
@ -2098,7 +2337,9 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
|
|||||||
|
|
||||||
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
void _glfwPlatformIconifyWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.toplevel)
|
if (window->wl.libdecor.frame)
|
||||||
|
libdecor_frame_set_minimized(window->wl.libdecor.frame);
|
||||||
|
else if (window->wl.xdg.toplevel)
|
||||||
xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
|
xdg_toplevel_set_minimized(window->wl.xdg.toplevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2115,7 +2356,9 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
if (window->wl.maximized)
|
if (window->wl.maximized)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.toplevel)
|
if (window->wl.libdecor.frame)
|
||||||
|
libdecor_frame_unset_maximized(window->wl.libdecor.frame);
|
||||||
|
else if (window->wl.xdg.toplevel)
|
||||||
xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
|
xdg_toplevel_unset_maximized(window->wl.xdg.toplevel);
|
||||||
else
|
else
|
||||||
window->wl.maximized = GLFW_FALSE;
|
window->wl.maximized = GLFW_FALSE;
|
||||||
@ -2125,7 +2368,9 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.toplevel)
|
if (window->wl.libdecor.frame)
|
||||||
|
libdecor_frame_set_maximized(window->wl.libdecor.frame);
|
||||||
|
else if (window->wl.xdg.toplevel)
|
||||||
xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
|
xdg_toplevel_set_maximized(window->wl.xdg.toplevel);
|
||||||
else
|
else
|
||||||
window->wl.maximized = GLFW_TRUE;
|
window->wl.maximized = GLFW_TRUE;
|
||||||
@ -2133,7 +2378,7 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
void _glfwPlatformShowWindow(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
if (!window->wl.xdg.toplevel)
|
if (!window->wl.libdecor.frame && !window->wl.xdg.toplevel)
|
||||||
{
|
{
|
||||||
// NOTE: The XDG/shell surface is created here so command-line applications
|
// NOTE: The XDG/shell surface is created here so command-line applications
|
||||||
// with off-screen windows do not appear in for example the Unity dock
|
// with off-screen windows do not appear in for example the Unity dock
|
||||||
@ -2224,14 +2469,34 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
|||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
{
|
{
|
||||||
// TODO
|
if (window->wl.libdecor.frame)
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
{
|
||||||
"Wayland: Window attribute setting not implemented yet");
|
if (enabled)
|
||||||
|
{
|
||||||
|
libdecor_frame_set_capabilities(window->wl.libdecor.frame,
|
||||||
|
LIBDECOR_ACTION_RESIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
libdecor_frame_unset_capabilities(window->wl.libdecor.frame,
|
||||||
|
LIBDECOR_ACTION_RESIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR,
|
||||||
|
"Wayland: Window attribute setting not implemented yet");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
||||||
{
|
{
|
||||||
if (window->wl.xdg.decoration)
|
if (window->wl.libdecor.frame)
|
||||||
|
{
|
||||||
|
libdecor_frame_set_visibility(window->wl.libdecor.frame, enabled);
|
||||||
|
}
|
||||||
|
else if (window->wl.xdg.decoration)
|
||||||
{
|
{
|
||||||
uint32_t mode;
|
uint32_t mode;
|
||||||
|
|
||||||
@ -2242,7 +2507,7 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, GLFWbool enabled)
|
|||||||
|
|
||||||
zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode);
|
zxdg_toplevel_decoration_v1_set_mode(window->wl.xdg.decoration, mode);
|
||||||
}
|
}
|
||||||
else
|
else if (window->wl.xdg.toplevel)
|
||||||
{
|
{
|
||||||
if (enabled)
|
if (enabled)
|
||||||
createFallbackDecorations(window);
|
createFallbackDecorations(window);
|
||||||
|
Loading…
Reference in New Issue
Block a user