diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx index 32fdd0953..a81370768 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx @@ -1352,30 +1352,30 @@ static const struct wl_registry_listener registry_listener = { }; -extern int fl_send_system_handlers(void *); - - -static void wayland_socket_callback(int fd, struct wl_display *display) { - if (fl_send_system_handlers(NULL)) return; - struct pollfd fds = (struct pollfd) { fd, POLLIN, 0 }; - do { - if (wl_display_dispatch(display) == -1) { - int err = wl_display_get_error(display); - if (err == EPROTO) { - const struct wl_interface *interface; - int code = wl_display_get_protocol_error(display, &interface, NULL); - Fl::fatal("Fatal error no %d in Wayland protocol: %s", code, - (interface ? interface->name : "unknown") ); - } else { - Fl::fatal("Fatal error while communicating with the Wayland server: %s", - strerror(errno)); - } - } +static void libdecor_fd_callback(int fd, struct libdecor *libdecor_context) { + if (libdecor_dispatch(libdecor_context, 0) >= 0) return; + if (wl_display_get_error(Fl_Wayland_Screen_Driver::wl_display) == EPROTO) { + const struct wl_interface *interface; + int code = wl_display_get_protocol_error(Fl_Wayland_Screen_Driver::wl_display, &interface, NULL); + Fl::fatal("Fatal error no %d in Wayland protocol: %s", code, + (interface ? interface->name : "unknown") ); + } else { + Fl::fatal("Fatal error while communicating with the Wayland server: %s", + strerror(errno)); } - while (poll(&fds, 1, 0) > 0); } +static void handle_error(struct libdecor *libdecor_context, enum libdecor_error error, const char *message) +{ + Fl::fatal("Caught error (%d): %s\n", error, message); +} + +static struct libdecor_interface libdecor_iface = { + .error = handle_error, +}; + + Fl_Wayland_Screen_Driver::Fl_Wayland_Screen_Driver() : Fl_Unix_Screen_Driver() { libdecor_context = NULL; seat = NULL; @@ -1404,8 +1404,11 @@ static const struct wl_callback_listener sync_listener = { static void do_atexit() { - if (Fl_Wayland_Screen_Driver::wl_display) { - wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); + // Issue #821 no longer seems to require extra operations under gnome version < 44. + Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); + if (scr_driver->libdecor_context) { // libdecor recommends a call to libdecor_unref() + libdecor_unref(scr_driver->libdecor_context); + scr_driver->libdecor_context = NULL; } } @@ -1431,15 +1434,10 @@ void Fl_Wayland_Screen_Driver::open_display_platform() { struct wl_callback *registry_cb = wl_display_sync(wl_display); wl_callback_add_listener(registry_cb, &sync_listener, ®istry_cb); while (registry_cb) wl_display_dispatch(wl_display); - Fl::add_fd(wl_display_get_fd(wl_display), FL_READ, (Fl_FD_Handler)wayland_socket_callback, - wl_display); + libdecor_context = libdecor_new(wl_display, &libdecor_iface); + Fl::add_fd(libdecor_get_fd(libdecor_context), FL_READ, (Fl_FD_Handler)libdecor_fd_callback, + libdecor_context); fl_create_print_window(); - /* This is useful to avoid crash of the Wayland compositor after - FLTK apps terminate in certain situations: - - gnome-shell version < 44 (e.g. version 42.9) - - focus set to "follow-mouse" - See issue #821 for details. - */ atexit(do_atexit); } @@ -1519,21 +1517,20 @@ void Fl_Wayland_Screen_Driver::close_display() { wl_seat_destroy(seat->wl_seat); seat->wl_seat = NULL; if (seat->name) free(seat->name); free(seat); seat = NULL; - if (libdecor_context) { - libdecor_unref(libdecor_context); - libdecor_context = NULL; - } xdg_wm_base_destroy(xdg_wm_base); xdg_wm_base = NULL; Fl_Wayland_Plugin *plugin = Fl_Wayland_Window_Driver::gl_plugin(); if (plugin) plugin->terminate(); - Fl::remove_fd(wl_display_get_fd(Fl_Wayland_Screen_Driver::wl_display)); + if (libdecor_context) { + Fl::remove_fd(libdecor_get_fd(libdecor_context)); + libdecor_unref(libdecor_context); + libdecor_context = NULL; + } wl_registry_destroy(wl_registry); wl_registry = NULL; wl_display_disconnect(Fl_Wayland_Screen_Driver::wl_display); Fl_Wayland_Screen_Driver::wl_display = NULL; delete Fl_Display_Device::display_device()->driver(); delete Fl_Display_Device::display_device(); - delete Fl::system_driver(); delete this; } diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx index 2aad8f0c6..3382bf609 100644 --- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx @@ -648,17 +648,6 @@ int Fl_Wayland_Window_Driver::scroll(int src_x, int src_y, int src_w, int src_h, } -static void handle_error(struct libdecor *libdecor_context, enum libdecor_error error, const char *message) -{ - Fl::fatal("Caught error (%d): %s\n", error, message); -} - - -static struct libdecor_interface libdecor_iface = { - .error = handle_error, -}; - - void change_scale(Fl_Wayland_Screen_Driver::output *output, struct wld_window *window, float pre_scale) { Fl_Wayland_Window_Driver *win_driver = Fl_Wayland_Window_Driver::driver(window->fl_win); @@ -1007,11 +996,12 @@ void Fl_Wayland_Window_Driver::wait_for_expose() Fl_Window_Driver::wait_for_expose(); struct wld_window * xid = fl_wl_xid(pWindow); if (!xid) return; + Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); if (pWindow->fullscreen_active()) { if (xid->kind == DECORATED) { while (!(xid->state & LIBDECOR_WINDOW_STATE_FULLSCREEN) || !(xid->state & LIBDECOR_WINDOW_STATE_ACTIVE)) { - wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display); + libdecor_dispatch(scr_driver->libdecor_context, 0); } } else if (xid->kind == UNFRAMED) { wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); @@ -1019,7 +1009,7 @@ void Fl_Wayland_Window_Driver::wait_for_expose() } else if (xid->kind == DECORATED) { // necessary for the windowfocus demo program with recent Wayland versions if (!(xid->state & LIBDECOR_WINDOW_STATE_ACTIVE)) { - wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display); + libdecor_dispatch(scr_driver->libdecor_context, 0); } } } @@ -1465,9 +1455,6 @@ void Fl_Wayland_Window_Driver::makeWindow() } else if (pWindow->border() && !pWindow->parent() ) { // a decorated window new_window->kind = DECORATED; - if (!scr_driver->libdecor_context) - scr_driver->libdecor_context = libdecor_new(Fl_Wayland_Screen_Driver::wl_display, - &libdecor_iface); new_window->frame = libdecor_decorate(scr_driver->libdecor_context, new_window->wl_surface, &libdecor_frame_iface, new_window); // appears in the Gnome desktop menu bar