summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2025-12-08 18:20:47 +0100
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2025-12-08 18:27:51 +0100
commit8454135d0c8918ed16441bbc08ef176cd2e02c5e (patch)
tree20839531af30da8d3bade1a25925887c7180c4ef
parent1f6fda64a8195681e385acef2ec5fba740d85489 (diff)
Wayland: add support of the "XDG dialog windows" protocol
-rw-r--r--CMake/options.cmake8
-rw-r--r--config.h.in6
-rw-r--r--src/CMakeLists.txt13
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Screen_Driver.H4
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx8
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.H4
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx40
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);
+ }
}
}