diff --git a/src/wl_init.c b/src/wl_init.c index 8b4b33e4..bc786677 100644 --- a/src/wl_init.c +++ b/src/wl_init.c @@ -40,6 +40,7 @@ #include #include #include +#include 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); diff --git a/src/wl_platform.h b/src/wl_platform.h index 4392dced..8affdd16 100644 --- a/src/wl_platform.h +++ b/src/wl_platform.h @@ -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_; diff --git a/src/wl_window.c b/src/wl_window.c index d3493d11..a9c71b6e 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -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);