diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2025-03-15 17:24:57 +0100 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2025-03-17 14:49:17 +0100 |
| commit | ed4fded9d94f05b8f4e55c818de5b21ffd885278 (patch) | |
| tree | e9d2ff676bbd7641cab08df0cd96e071cf4bbe47 /src | |
| parent | 51a55bc73660f64e8f4b32b8b4d3858f2a786f7b (diff) | |
Wayland: compute work area size under MUTTER or when single display
Diffstat (limited to 'src')
| -rw-r--r-- | src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx | 134 |
1 files changed, 85 insertions, 49 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx index 7fbc7c140..304395936 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx @@ -1114,10 +1114,9 @@ static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags, } -static void compute_full_and_maximized_areas(Fl_Wayland_Screen_Driver::output *output, +static bool compute_full_and_maximized_areas(Fl_Wayland_Screen_Driver::output *output, int& Wfullscreen, int& Hfullscreen, - int& Wworkarea, int& Hworkarea, - bool need_workarea); + int& Wworkarea, int& Hworkarea); static void output_done(void *data, struct wl_output *wl_output) @@ -1149,9 +1148,11 @@ static void output_done(void *data, struct wl_output *wl_output) if (scr_driver->screen_count_get() > 0) { // true when output_done runs after initial screen dectection scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) ); int Wfullscreen, Hfullscreen, Wworkarea, Hworkarea; - compute_full_and_maximized_areas(output, Wfullscreen, Hfullscreen, Wworkarea, Hworkarea, false); - output->width = Wfullscreen * output->wld_scale; // pixels - output->height = Hfullscreen * output->wld_scale; // pixels + compute_full_and_maximized_areas(output, Wfullscreen, Hfullscreen, Wworkarea, Hworkarea); + if (Wfullscreen && Hfullscreen) { + output->width = Wfullscreen * output->wld_scale; // pixels + output->height = Hfullscreen * output->wld_scale; // pixels + } Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL); } } @@ -1569,45 +1570,70 @@ static void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel pair->H = height; } -static void xdg_toplevel_close(void *data, struct xdg_toplevel *toplevel) {} - static const struct xdg_toplevel_listener xdg_toplevel_listener = { .configure = xdg_toplevel_configure, - .close = xdg_toplevel_close, }; +static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) +{ + xdg_surface_ack_configure(xdg_surface, serial); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + .configure = xdg_surface_configure, +}; -static void compute_full_and_maximized_areas(Fl_Wayland_Screen_Driver::output *output, +static bool compute_full_and_maximized_areas(Fl_Wayland_Screen_Driver::output *output, int& Wfullscreen, int& Hfullscreen, - int& Wworkarea, int& Hworkarea, - bool need_workarea) { + int& Wworkarea, int& Hworkarea) { + bool found_workarea = false; Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); struct wl_surface *wl_surface = wl_compositor_create_surface(scr_driver->wl_compositor); wl_surface_set_opaque_region(wl_surface, NULL); struct xdg_surface *xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, wl_surface); + xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, NULL); struct xdg_toplevel *xdg_toplevel = xdg_surface_get_toplevel(xdg_surface); struct pair_s pair = {0, -1}; xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, &pair); xdg_toplevel_set_fullscreen(xdg_toplevel, output->wl_output); wl_surface_commit(wl_surface); while (pair.H < 0) wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display); + pair.H = -1; + xdg_toplevel_set_fullscreen(xdg_toplevel, output->wl_output); + wl_surface_commit(wl_surface); + while (pair.H < 0) wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display); Wfullscreen = pair.W; Hfullscreen = pair.H; - if (need_workarea && Wfullscreen && Hfullscreen) { - xdg_toplevel_unset_fullscreen(xdg_toplevel); - xdg_toplevel_set_maximized(xdg_toplevel); - pair.H = -1; - wl_surface_commit(wl_surface); - while (pair.H < 0) wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display); - } - Wworkarea = pair.W; - Hworkarea = pair.H; + if (Wfullscreen && Hfullscreen && (Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::MUTTER || + wl_list_length(&scr_driver->outputs) == 1)) { + struct wl_surface *wl_surface2 = wl_compositor_create_surface(scr_driver->wl_compositor); + struct xdg_surface *xdg_surface2 = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, wl_surface2); + struct xdg_toplevel *xdg_toplevel2 = xdg_surface_get_toplevel(xdg_surface2); + struct pair_s pair2 = {0, -1}; + xdg_toplevel_add_listener(xdg_toplevel2, &xdg_toplevel_listener, &pair2); + xdg_toplevel_set_parent(xdg_toplevel2, xdg_toplevel); + xdg_toplevel_set_maximized(xdg_toplevel2); + pair2.H = -1; + wl_surface_commit(wl_surface2); + while (pair2.H < 0) wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display); + Wworkarea = pair2.W; + Hworkarea = pair2.H; + xdg_toplevel_destroy(xdg_toplevel2); + xdg_surface_destroy(xdg_surface2); + wl_surface_destroy(wl_surface2); + if (Wworkarea == Wfullscreen && Hworkarea < Hfullscreen && Hworkarea > Hfullscreen - 80) + found_workarea = true; + } else { + Wworkarea = Wfullscreen; + Hworkarea = Hfullscreen; + } xdg_toplevel_destroy(xdg_toplevel); xdg_surface_destroy(xdg_surface); wl_surface_destroy(wl_surface); - //int fractional_scale = int(100 * (output->pixel_width / float(Wfullscreen))); - //printf("fullscreen=%dx%d workarea=%dx%d fractional_scale=%d%% wld_s=%d\n", - // Wfullscreen,Hfullscreen,Wworkarea,Hworkarea,fractional_scale,output->wld_scale); + /*int fractional_scale = int(100 * (output->pixel_width / float(Wfullscreen))); + printf("fullscreen=%dx%d workarea=%dx%d fractional_scale=%d%% wld_s=%d\n", + Wfullscreen,Hfullscreen,Wworkarea,Hworkarea,fractional_scale,output->wld_scale);*/ + return found_workarea; } static int workarea_xywh[4] = { -1, -1, -1, -1 }; @@ -1630,45 +1656,55 @@ static int workarea_xywh[4] = { -1, -1, -1, -1 }; One way for a client to discover that fractional scaling is active on a given display is to ask for a fullscreen window on that display, get its configured size and compare - it to the display pixel size. That's what function compute_full_and_maximized_areas() does. + it to that display's pixel size. That's what function compute_full_and_maximized_areas() does. - One way for a client to discover the work area size is to get the configured size - of a maximized window on a given display. But it's not possible to control on what display - the compositor puts the maximized window. Therefore, FLTK computes an exact work area size - only when the system contains a single display. That's also done by function - compute_full_and_maximized_areas(). + One way for a client to discover the work area size of a display is to get the configured size + of a maximized window on that display. FLTK didn't find a way to control in general + on what display the compositor puts a maximized window. One procedure which works + under Mutter or with a single display was found. In this procedure, we create first a fullscreen + window on a given display and then we create a maximized window made a child of the + fullscreen one. Under mutter, this puts reliably the maximized window on the same + display as the fullscreen one, giving the size of that display's work area. + Therefore, FLTK computes an exact work area size only with MUTTER or when the system + contains a single display. That's also done by function compute_full_and_maximized_areas(). - FLTK didn't find how to recognize the primary display within the list of displays - received from the compositor. That's another reason why FLTK doesn't attempt - to compute work area sizes when there are multiple displays. + The procedure to compute the work area size also reveals which display is primary: + that with a work area vertically smaller than the display's pixel height. This allows + to place the primary display as FLTK display #0. Again, FLTK guarantees to identify + the primary display only under MUTTER. */ void Fl_Wayland_Screen_Driver::init_workarea() { - Fl_Wayland_Screen_Driver::output *output; - bool need_workarea = (screen_count_get() == 1); - bool first = true; + Fl_Wayland_Screen_Driver::output *output, *mainscreen = NULL; wl_list_for_each(output, &outputs, link) { - if (first) workarea_xywh[0] = output->x; // pixels - if (first) workarea_xywh[1] = output->y; // pixels int Wfullscreen, Hfullscreen, Wworkarea, Hworkarea; - compute_full_and_maximized_areas(output, Wfullscreen, Hfullscreen, Wworkarea, Hworkarea, need_workarea); - if (!Wfullscreen || !Hfullscreen) { // sway puts 0 there - output->width = output->pixel_width; - output->height = output->pixel_height; - if (first) { - workarea_xywh[2] = output->width; - workarea_xywh[3] = output->height; - } - } else { + bool found_workarea = compute_full_and_maximized_areas(output, Wfullscreen, Hfullscreen, Wworkarea, Hworkarea); + if (found_workarea && !mainscreen) { + mainscreen = output; + } else found_workarea = false; + if (Wfullscreen && Hfullscreen) { // skip sway which puts 0 there output->width = Wfullscreen * output->wld_scale; // pixels output->height = Hfullscreen * output->wld_scale; // pixels - if (first) { + if (found_workarea) { + workarea_xywh[0] = output->x; // pixels + workarea_xywh[1] = output->y; // pixels workarea_xywh[2] = Wworkarea * output->wld_scale; // pixels workarea_xywh[3] = Hworkarea * output->wld_scale; // pixels } } - first = false; + } + if (mainscreen) { // put mainscreen first in list of screens + wl_list_remove(&mainscreen->link); + wl_list_insert(&outputs, &mainscreen->link); + } else { + wl_list_for_each(output, &outputs, link) { // find first screen in list + workarea_xywh[0] = output->x; // pixels + workarea_xywh[1] = output->y; // pixels + workarea_xywh[2] = output->width; // pixels + workarea_xywh[3] = output->height; // pixels + break; + } } Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL); } |
