summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-07-13 18:19:01 +0200
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-07-13 18:19:01 +0200
commit6f05af3c121482e03d0f6067dc8190c72bd6aeb5 (patch)
treef35da304c8a14c63f2091405e1b7e997224f119b
parent580a531ef511c1b80c30fa61b27e0209ff693f96 (diff)
Wayland: add control of targeted screen by fullscreen windows
-rw-r--r--documentation/src/wayland.dox8
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx37
2 files changed, 43 insertions, 2 deletions
diff --git a/documentation/src/wayland.dox b/documentation/src/wayland.dox
index c873c17fd..5aa881252 100644
--- a/documentation/src/wayland.dox
+++ b/documentation/src/wayland.dox
@@ -382,6 +382,14 @@ to detect that Wayland needs be informed of the desired size change, which gets
to \c libdecor_frame_commit(). Wayland later calls \c handle_configure() and events described
above unfold.
+Wayland generally does not provide a way to control where the compositor should map a window
+in the system displays. Nevertheless, for multi-display systems, Wayland allows to control
+on what display should the compositor map a fullscreen window. That is done inside function
+\c handle_configure() which calls \c libdecor_frame_set_fullscreen() for DECORATED windows
+and inside function \c xdg_toplevel_configure() which calls \c xdg_toplevel_set_fullscreen()
+for UNFRAMED. The <tt>struct wl_output</tt> pointer for the targetted display is transmitted
+as 2nd argument of these calls.
+
\section menu-windows Menu windows and other popups
Menu windows, tiny menu title windows, and tooltip windows are implemented using Wayland's
popup mechanism which allows to position a popup window relatively to a previously mapped
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
index 9c144aec4..52080c705 100644
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
@@ -749,6 +749,17 @@ Fl_Window *Fl_Wayland_Window_Driver::surface_to_window(struct wl_surface *surfac
}
+static struct Fl_Wayland_Screen_Driver::output *screen_num_to_output(int num_screen) {
+ Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
+ int i = 0;
+ Fl_Wayland_Screen_Driver::output *output;
+ wl_list_for_each(output, &(scr_driver->outputs), link) { // all screens of the system
+ if (i++ == num_screen) return output;
+ }
+ return NULL;
+}
+
+
static void handle_configure(struct libdecor_frame *frame,
struct libdecor_configuration *configuration, void *user_data)
{
@@ -766,9 +777,14 @@ static void handle_configure(struct libdecor_frame *frame,
if (!window->xdg_surface) window->xdg_surface = libdecor_frame_get_xdg_surface(frame);
+ struct wl_output *wl_output = NULL;
if (window->fl_win->fullscreen_active()) {
if (!(window->state & LIBDECOR_WINDOW_STATE_FULLSCREEN)) {
- libdecor_frame_set_fullscreen(window->frame, NULL);
+ if (Fl_Window_Driver::driver(window->fl_win)->force_position()) {
+ struct Fl_Wayland_Screen_Driver::output *output = screen_num_to_output(window->fl_win->screen_num());
+ if (output) wl_output = output->wl_output;
+ }
+ libdecor_frame_set_fullscreen(window->frame, wl_output);
}
} else if (driver->show_iconic()) {
libdecor_frame_set_minimized(window->frame);
@@ -799,6 +815,13 @@ static void handle_configure(struct libdecor_frame *frame,
} else { width = height = 0; }
}
+ if (window->fl_win->fullscreen_active() &&
+ Fl_Window_Driver::driver(window->fl_win)->force_position()) {
+ int X, Y, W, H;
+ Fl::screen_xywh(X, Y, W, H, window->fl_win->screen_num());
+ width = W * f; height = H * f;
+ }
+
if (width == 0) {
width = window->floating_width;
height = window->floating_height;
@@ -808,6 +831,7 @@ static void handle_configure(struct libdecor_frame *frame,
driver->in_handle_configure = true;
window->fl_win->resize(0, 0, ceil(width / f), ceil(height / f));
driver->in_handle_configure = false;
+ if (wl_output) window->fl_win->redraw();
if (ceil(width / f) != window->configured_width || ceil(height / f) != window->configured_height) {
if (window->buffer) {
@@ -956,7 +980,16 @@ static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel
struct wld_window *window = (struct wld_window*)data;
//fprintf(stderr, "xdg_toplevel_configure: surface=%p size: %dx%d\n", window->wl_surface, width, height);
if (window->fl_win->fullscreen_active() && !parse_states_fullscreen(states)) {
- xdg_toplevel_set_fullscreen(xdg_toplevel, NULL);
+ struct wl_output *wl_output = NULL;
+ if (Fl_Window_Driver::driver(window->fl_win)->force_position()) {
+ struct Fl_Wayland_Screen_Driver::output *output = screen_num_to_output(window->fl_win->screen_num());
+ if (output) wl_output = output->wl_output;
+ }
+ xdg_toplevel_set_fullscreen(xdg_toplevel, wl_output);
+ if (wl_output) {
+ int X, Y;
+ Fl::screen_xywh(X, Y, width, height, window->fl_win->screen_num());
+ }
}
if (window->configured_width) Fl_Window_Driver::driver(window->fl_win)->wait_for_expose_value = 0;
float f = Fl::screen_scale(window->fl_win->screen_num());