summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2025-03-13 15:00:21 +0100
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2025-03-13 15:00:21 +0100
commit2d9cf4d83ec9824b978925fa6c9df8ace954d88b (patch)
treecfe2d9eb1175692a60333fad6ecef5765238999b
parent8ff7895f0e6b29e0d7209c2a18ff99b55de75cb3 (diff)
Improve support of screen addition/removal while FLTK runs
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Screen_Driver.H1
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx69
2 files changed, 50 insertions, 20 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H
index 16eb750a4..b2e4db77e 100644
--- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H
+++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H
@@ -166,6 +166,7 @@ public:
// Wayland-specific member functions
void screen_count_set(int count) {num_screens = count;}
+ int screen_count_get() {return num_screens;}
void reset_cursor();
// this one is in fl_wayland_clipboard_dnd.cxx
void copy_image(const unsigned char* data, int W, int H);
diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
index b73b92682..7fbc7c140 100644
--- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx
@@ -1,7 +1,7 @@
//
// Implementation of Wayland Screen interface
//
-// Copyright 1998-2024 by Bill Spitzak and others.
+// Copyright 1998-2025 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@@ -1108,13 +1108,21 @@ static void output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data;
output->pixel_width = int(width);
output->pixel_height = int(height);
+ output->width = output->pixel_width; // until further notice
+ output->height = output->pixel_height;
//fprintf(stderr, "output_mode: [%p]=%dx%d\n",output->wl_output,width,height);
}
+static void compute_full_and_maximized_areas(Fl_Wayland_Screen_Driver::output *output,
+ int& Wfullscreen, int& Hfullscreen,
+ int& Wworkarea, int& Hworkarea,
+ bool need_workarea);
+
+
static void output_done(void *data, struct wl_output *wl_output)
{
- // Runs at startup and when desktop scale factor is changed
+ // Runs at startup and when desktop scale factor is changed or screen added
Fl_Wayland_Screen_Driver::output *output = (Fl_Wayland_Screen_Driver::output*)data;
//fprintf(stderr, "output_done output=%p\n",output);
Fl_X *xp = Fl_X::first;
@@ -1138,9 +1146,14 @@ static void output_done(void *data, struct wl_output *wl_output)
output->done = true;
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
- if (scr_driver->seat) try_update_cursor(scr_driver->seat);
- scr_driver->init_workarea();
- Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
+ 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
+ Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
+ }
}
@@ -1269,9 +1282,15 @@ static void registry_handle_global(void *user_data, struct wl_registry *wl_regis
output->gui_scale = 1.f;
wl_proxy_set_tag((struct wl_proxy *) output->wl_output, &proxy_tag);
wl_output_add_listener(output->wl_output, &output_listener, output);
- wl_list_insert(&(scr_driver->outputs), &output->link);
- scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) );
-//fprintf(stderr, "wl_output: id=%d wl_output=%p screen_count()=%d\n", id, output->wl_output, Fl::screen_count());
+ // Put new screen in list of screens, but make sure it's not in list already
+ // which may occur after having removed a screen.
+ bool found = false;
+ Fl_Wayland_Screen_Driver::output *elt;
+ wl_list_for_each(elt, &scr_driver->outputs, link) {
+ if (elt == output) found = true;
+ }
+ if (!found) wl_list_insert(&(scr_driver->outputs), &output->link);
+//fprintf(stderr, "wl_output: id=%d wl_output=%p \n", id, output->wl_output);
} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
//fprintf(stderr, "registry_handle_global interface=%s\n", interface);
@@ -1299,6 +1318,7 @@ static void registry_handle_global(void *user_data, struct wl_registry *wl_regis
output->wld_scale = 1;
output->gui_scale = 1.f;
output->width = 1440; output->height = 900;
+ output->pixel_width = 1440; output->pixel_height = 900;
output->done = true;
wl_list_insert(&(scr_driver->outputs), &output->link);
scr_driver->screen_count_set(1);
@@ -1311,10 +1331,11 @@ static void registry_handle_global(void *user_data, struct wl_registry *wl_regis
}
-static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {//TODO to be tested
+static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
Fl_Wayland_Screen_Driver::output *output, *tmp;
//fprintf(stderr, "registry_handle_global_remove data=%p id=%u\n", data, name);
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
+ bool has_removed_screen = false;
wl_list_for_each_safe(output, tmp, &(scr_driver->outputs), link) { // all screens
if (output->id == name) { // the screen being removed
again:
@@ -1331,12 +1352,16 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist
xp = xp->next;
}
wl_list_remove(&output->link);
- scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) );
wl_output_destroy(output->wl_output);
free(output);
+ has_removed_screen = true;
break;
}
}
+ if (has_removed_screen) {
+ scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) );
+ scr_driver->init_workarea();
+ }
}
@@ -1388,6 +1413,10 @@ static void sync_done(void *data, struct wl_callback *cb, uint32_t time) {
wl_list_for_each(output, &scr_driver->outputs, link) { // each screen of the system
while (!output->done) wl_display_dispatch(Fl_Wayland_Screen_Driver::wl_display);
}
+ // Now all screens have been initialized
+ scr_driver->screen_count_set( wl_list_length(&(scr_driver->outputs)) );
+ if (scr_driver->seat) try_update_cursor(scr_driver->seat);
+ if (Fl_Wayland_Screen_Driver::compositor != Fl_Wayland_Screen_Driver::OWL) scr_driver->init_workarea();
}
@@ -1576,10 +1605,9 @@ static void compute_full_and_maximized_areas(Fl_Wayland_Screen_Driver::output *o
xdg_toplevel_destroy(xdg_toplevel);
xdg_surface_destroy(xdg_surface);
wl_surface_destroy(wl_surface);
- //int H = output->pixel_height / output->wld_scale;
- //float fractional_scale = Hfullscreen / float(H);
- //printf("fullscreen=%dx%d workarea=%dx%d apparentH=%d fractional_scale=%g wld_s=%d\n",
- // Wfullscreen,Hfullscreen,Wworkarea,Hworkarea,H,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);
}
static int workarea_xywh[4] = { -1, -1, -1, -1 };
@@ -1618,16 +1646,14 @@ static int workarea_xywh[4] = { -1, -1, -1, -1 };
void Fl_Wayland_Screen_Driver::init_workarea()
{
Fl_Wayland_Screen_Driver::output *output;
- int count = 0;
- wl_list_for_each(output, &outputs, link) ++count;
- bool need_workarea = (count == 1);
+ bool need_workarea = (screen_count_get() == 1);
bool first = true;
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 returns 0 there
+ if (!Wfullscreen || !Hfullscreen) { // sway puts 0 there
output->width = output->pixel_width;
output->height = output->pixel_height;
if (first) {
@@ -1636,12 +1662,15 @@ void Fl_Wayland_Screen_Driver::init_workarea()
}
} else {
output->width = Wfullscreen * output->wld_scale; // pixels
- if (first) workarea_xywh[2] = Wworkarea * output->wld_scale; // pixels
output->height = Hfullscreen * output->wld_scale; // pixels
- if (first) workarea_xywh[3] = Hworkarea * output->wld_scale; // pixels
+ if (first) {
+ workarea_xywh[2] = Wworkarea * output->wld_scale; // pixels
+ workarea_xywh[3] = Hworkarea * output->wld_scale; // pixels
+ }
}
first = false;
}
+ Fl::handle(FL_SCREEN_CONFIGURATION_CHANGED, NULL);
}