mirror of
https://github.com/glfw/glfw.git
synced 2024-11-24 21:54:35 +00:00
Wayland: Use Wayland to wait for libdecor to init
Much of libdecor is initialized only after certain events have been
received from the compositor and some parts of libdecor 0.1 are unsafe
to use until this delayed initialization has completed.
Since libdecor does not provide an API to query if or be notified when
this has happened, GLFW processed events until its newly created
libdecor frame had created its XDG shell objects.
This commit switches to using a generic Wayland sync point created just
after libdecor (and presumably its plugin) has set up its delayed
initialization, instead of relying on the more specific implementation
detail mentioned above.
It also makes this wait mandatory before the first libdecor frame is
created instead of a pre-condition for certain libdecor frame calls,
hopefully removing even more dependence on implementation details.
(cherry picked from commit 9fdc425931
)
This commit is contained in:
parent
89b149a56f
commit
7cc8879ab9
@ -40,6 +40,7 @@
|
||||
#include <sys/timerfd.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-client.h>
|
||||
#include <assert.h>
|
||||
|
||||
static void wmBaseHandlePing(void* userData,
|
||||
struct xdg_wm_base* wmBase,
|
||||
@ -177,6 +178,22 @@ static const struct libdecor_interface libdecorInterface =
|
||||
libdecorHandleError
|
||||
};
|
||||
|
||||
static void libdecorReadyCallback(void* userData,
|
||||
struct wl_callback* callback,
|
||||
uint32_t time)
|
||||
{
|
||||
_glfw.wl.libdecor.ready = GLFW_TRUE;
|
||||
|
||||
assert(_glfw.wl.libdecor.callback == callback);
|
||||
wl_callback_destroy(_glfw.wl.libdecor.callback);
|
||||
_glfw.wl.libdecor.callback = NULL;
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener libdecorReadyListener =
|
||||
{
|
||||
libdecorReadyCallback
|
||||
};
|
||||
|
||||
// Create key code translation tables
|
||||
//
|
||||
static void createKeyTables(void)
|
||||
@ -563,10 +580,17 @@ int _glfwPlatformInit(void)
|
||||
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);
|
||||
{
|
||||
// Perform an initial dispatch and flush to get the init started
|
||||
libdecor_dispatch(_glfw.wl.libdecor.context, 0);
|
||||
|
||||
// Create sync point to "know" when libdecor is ready for use
|
||||
_glfw.wl.libdecor.callback = wl_display_sync(_glfw.wl.display);
|
||||
wl_callback_add_listener(_glfw.wl.libdecor.callback,
|
||||
&libdecorReadyListener,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
|
||||
@ -613,6 +637,8 @@ void _glfwPlatformTerminate(void)
|
||||
_glfwTerminateEGL();
|
||||
_glfwTerminateOSMesa();
|
||||
|
||||
if (_glfw.wl.libdecor.callback)
|
||||
wl_callback_destroy(_glfw.wl.libdecor.callback);
|
||||
if (_glfw.wl.libdecor.context)
|
||||
libdecor_unref(_glfw.wl.libdecor.context);
|
||||
|
||||
|
@ -467,6 +467,8 @@ typedef struct _GLFWlibraryWayland
|
||||
struct {
|
||||
void* handle;
|
||||
struct libdecor* context;
|
||||
struct wl_callback* callback;
|
||||
GLFWbool ready;
|
||||
PFN_libdecor_new libdecor_new_;
|
||||
PFN_libdecor_unref libdecor_unref_;
|
||||
PFN_libdecor_get_fd libdecor_get_fd_;
|
||||
|
@ -774,6 +774,10 @@ static const struct libdecor_frame_interface libdecorFrameInterface =
|
||||
|
||||
static GLFWbool createLibdecorFrame(_GLFWwindow* window)
|
||||
{
|
||||
// Allow libdecor to finish initialization of itself and its plugin
|
||||
while (!_glfw.wl.libdecor.ready)
|
||||
_glfwPlatformWaitEvents();
|
||||
|
||||
window->wl.libdecor.frame = libdecor_decorate(_glfw.wl.libdecor.context,
|
||||
window->wl.surface,
|
||||
&libdecorFrameInterface,
|
||||
@ -812,12 +816,6 @@ static GLFWbool createLibdecorFrame(_GLFWwindow* window)
|
||||
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user