diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2025-12-08 18:20:47 +0100 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2025-12-08 18:27:51 +0100 |
| commit | 8454135d0c8918ed16441bbc08ef176cd2e02c5e (patch) | |
| tree | 20839531af30da8d3bade1a25925887c7180c4ef | |
| parent | 1f6fda64a8195681e385acef2ec5fba740d85489 (diff) | |
Wayland: add support of the "XDG dialog windows" protocol
| -rw-r--r-- | CMake/options.cmake | 8 | ||||
| -rw-r--r-- | config.h.in | 6 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 13 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Screen_Driver.H | 4 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx | 8 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Window_Driver.H | 4 | ||||
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx | 40 |
7 files changed, 71 insertions, 12 deletions
diff --git a/CMake/options.cmake b/CMake/options.cmake index f9855a298..063dc48b6 100644 --- a/CMake/options.cmake +++ b/CMake/options.cmake @@ -310,6 +310,14 @@ if(UNIX) endif(FLTK_BACKEND_WAYLAND) if(FLTK_USE_WAYLAND) + pkg_get_variable(PROTOCOLS wayland-protocols pkgdatadir) + string(REPLACE "//" "/" PROTOCOLS ${PROTOCOLS}) + if(EXISTS ${PROTOCOLS}/staging/xdg-dialog/xdg-dialog-v1.xml) + set(HAVE_XDG_DIALOG 1) + message(STATUS "Found dev files for Wayland protocol 'XDG dialog windows'") + else() + set(HAVE_XDG_DIALOG 0) + endif() if(FLTK_BACKEND_X11) include(FindX11) endif() diff --git a/config.h.in b/config.h.in index b74a7a1ac..a9daea791 100644 --- a/config.h.in +++ b/config.h.in @@ -343,3 +343,9 @@ */ #cmakedefine FL_CFG_NO_FILESYSTEM_SUPPORT 1 + +/* + * Can we use the "XDG TOPLEVEL DRAG" Wayland protocol? + */ + +#cmakedefine01 HAVE_XDG_DIALOG diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 62e731337..8f05995d7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -821,6 +821,19 @@ if(UNIX AND FLTK_USE_WAYLAND) list(APPEND STATIC_FILES "text-input-protocol.c") list(APPEND SHARED_FILES "text-input-protocol.c") + if(HAVE_XDG_DIALOG) + set(INFILE ${PROTOCOLS}/staging/xdg-dialog/xdg-dialog-v1.xml) + add_custom_command( + OUTPUT xdg-dialog-protocol.c xdg-dialog-client-protocol.h + COMMAND wayland-scanner private-code ${INFILE} xdg-dialog-protocol.c + COMMAND wayland-scanner client-header ${INFILE} xdg-dialog-client-protocol.h + DEPENDS ${INFILE} + VERBATIM + ) + list(APPEND STATIC_FILES "xdg-dialog-protocol.c") + list(APPEND SHARED_FILES "xdg-dialog-protocol.c") + endif() + if(STOP_REQUIRED) message(FATAL_ERROR "*** Terminating: one or more required file(s) were not found. ***") endif() diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H index 7dbf9314f..084e0c967 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H @@ -23,6 +23,7 @@ #ifndef FL_WAYLAND_SCREEN_DRIVER_H #define FL_WAYLAND_SCREEN_DRIVER_H +#include <config.h> #include "../Unix/Fl_Unix_Screen_Driver.H" #include <wayland-client.h> @@ -106,6 +107,9 @@ public: struct libdecor *libdecor_context; struct xdg_wm_base *xdg_wm_base; struct zwp_text_input_manager_v3 *text_input_base; +#if HAVE_XDG_DIALOG + struct xdg_wm_dialog_v1 *xdg_wm_dialog; +#endif // constructor Fl_Wayland_Screen_Driver(); diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx index b7204d00c..a831dbabc 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx @@ -36,6 +36,9 @@ #include <xkbcommon/xkbcommon-compose.h> #include "text-input-client-protocol.h" #include "gtk-shell-client-protocol.h" +#if HAVE_XDG_DIALOG +# include "xdg-dialog-client-protocol.h" +#endif #include <assert.h> #include <sys/mman.h> #include <poll.h> @@ -1326,6 +1329,11 @@ static void registry_handle_global(void *user_data, struct wl_registry *wl_regis scr_driver->text_input_base = (struct zwp_text_input_manager_v3 *) wl_registry_bind(wl_registry, id, &zwp_text_input_manager_v3_interface, 1); //printf("scr_driver->text_input_base=%p version=%d\n",scr_driver->text_input_base,version); +#if HAVE_XDG_DIALOG + } else if (strcmp(interface, xdg_wm_dialog_v1_interface.name) == 0) { + scr_driver->xdg_wm_dialog = (struct xdg_wm_dialog_v1 *) + wl_registry_bind(wl_registry, id, &xdg_wm_dialog_v1_interface, 1); +#endif // HAVE_XDG_DIALOG } } diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.H b/src/drivers/Wayland/Fl_Wayland_Window_Driver.H index 1cf378178..c5c1bee50 100644 --- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.H +++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.H @@ -22,6 +22,7 @@ #ifndef FL_WAYLAND_WINDOW_DRIVER_H #define FL_WAYLAND_WINDOW_DRIVER_H +#include <config.h> #include "../../Fl_Window_Driver.H" #include <FL/Fl_Plugin.H> #include "Fl_Wayland_Screen_Driver.H" @@ -157,6 +158,9 @@ struct wld_window { }; // non-null when using custom cursor struct Fl_Wayland_Window_Driver::custom_cursor *custom_cursor; +#if HAVE_XDG_DIALOG + struct xdg_dialog_v1 *xdg_dialog; +#endif enum Fl_Wayland_Window_Driver::kind kind; int configured_width; int configured_height; diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx index 1af97ebf5..c398ea1b3 100644 --- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx @@ -23,6 +23,9 @@ #include "../../../libdecor/build/fl_libdecor.h" #include "xdg-shell-client-protocol.h" #include "gtk-shell-client-protocol.h" +#if HAVE_XDG_DIALOG +# include "xdg-dialog-client-protocol.h" +#endif #include <pango/pangocairo.h> #include <FL/Fl_Overlay_Window.H> #include <FL/Fl_Tooltip.H> @@ -466,6 +469,12 @@ void Fl_Wayland_Window_Driver::hide() { wl_subsurface_destroy(wld_win->subsurface); wld_win->subsurface = NULL; } +#if HAVE_XDG_DIALOG + if (wld_win->xdg_dialog) { + xdg_dialog_v1_destroy(wld_win->xdg_dialog); + wld_win->xdg_dialog = NULL; + } +#endif if (wld_win->kind == DECORATED) { libdecor_frame_unref(wld_win->frame); wld_win->frame = NULL; @@ -1553,23 +1562,30 @@ void Fl_Wayland_Window_Driver::makeWindow() if (pWindow->modal() || pWindow->non_modal()) { if (pWindow->modal()) Fl::modal_ = pWindow; if (new_window->kind == DECORATED && first_xid && first_xid->kind == DECORATED) { - if (first_xid->frame) libdecor_frame_set_parent(new_window->frame, first_xid->frame); + if (first_xid->frame) libdecor_frame_set_parent(new_window->frame, first_xid->frame); } else if (new_window->kind == UNFRAMED && new_window->xdg_toplevel && first_xid) { Fl_Wayland_Window_Driver *top_dr = Fl_Wayland_Window_Driver::driver(first_xid->fl_win); if (top_dr->xdg_toplevel()) xdg_toplevel_set_parent(new_window->xdg_toplevel, top_dr->xdg_toplevel()); } - if (scr_driver->seat->gtk_shell && pWindow->modal() && - (new_window->kind == DECORATED || new_window->kind == UNFRAMED)) { - // Useful to position modal windows above their parent with "gnome-shell --version" ≤ 45.2, - // useless but harmless with "gnome-shell --version" ≥ 46.0. - struct gtk_surface1 *gtk_surface = gtk_shell1_get_gtk_surface(scr_driver->seat->gtk_shell, - new_window->wl_surface); - gtk_surface1_set_modal(gtk_surface); - if (gtk_surface1_get_version(gtk_surface) >= GTK_SURFACE1_RELEASE_SINCE_VERSION) - gtk_surface1_release(gtk_surface); // very necessary - else - gtk_surface1_destroy(gtk_surface); + if (new_window->kind == DECORATED || new_window->kind == UNFRAMED) { +#if HAVE_XDG_DIALOG + if (scr_driver->xdg_wm_dialog) { + new_window->xdg_dialog = xdg_wm_dialog_v1_get_xdg_dialog(scr_driver->xdg_wm_dialog, xdg_toplevel()); + if (pWindow->modal()) xdg_dialog_v1_set_modal(new_window->xdg_dialog); + } else +#endif + if (scr_driver->seat->gtk_shell && pWindow->modal()) { + // Useful to position modal windows above their parent with "gnome-shell --version" ≤ 45.2, + // useless but harmless with "gnome-shell --version" ≥ 46.0. + struct gtk_surface1 *gtk_surface = gtk_shell1_get_gtk_surface(scr_driver->seat->gtk_shell, + new_window->wl_surface); + gtk_surface1_set_modal(gtk_surface); + if (gtk_surface1_get_version(gtk_surface) >= GTK_SURFACE1_RELEASE_SINCE_VERSION) + gtk_surface1_release(gtk_surface); // very necessary + else + gtk_surface1_destroy(gtk_surface); + } } } |
