summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-12-28 09:59:51 +0100
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-12-28 09:59:51 +0100
commit614376488568e3eae2289e7d15e453ad6d7285af (patch)
tree011760c3feead3ea35092ab8aae21cae0874f5fc
parent73bd4a53dd54c300ffa539f23a521083172d6253 (diff)
Fix for bug in Mutter Wayland compositor (#878)
Mutter implements too strictly this rule expected from compositors about "frame callbacks" : "A server should avoid signaling the frame callbacks if the surface is not visible in any way, e.g. the surface is off-screen, or completely obscured by other opaque surfaces." When a window is being interactively resized, it makes no sense to create a frame callback for an entirely covered surface but then never signal the surface can be redrawn, because this blocks the resize operation. Neither KWin nor Weston have this problem.
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx6
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.H1
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx28
3 files changed, 33 insertions, 2 deletions
diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
index b2def3703..3ec0ffd38 100644
--- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
@@ -176,8 +176,10 @@ void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window, struct
wl_surface_attach(window->wl_surface, window->buffer->wl_buffer, 0, 0);
wl_surface_set_buffer_scale( window->wl_surface,
Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale() );
- window->buffer->cb = wl_surface_frame(window->wl_surface);
- wl_callback_add_listener(window->buffer->cb, &surface_frame_listener, window);
+ if (!window->covered) { // see issue #878
+ window->buffer->cb = wl_surface_frame(window->wl_surface);
+ wl_callback_add_listener(window->buffer->cb, &surface_frame_listener, window);
+ }
wl_surface_commit(window->wl_surface);
window->buffer->draw_buffer_needs_commit = false;
}
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.H b/src/drivers/Wayland/Fl_Wayland_Window_Driver.H
index 30e19e184..b3d530f00 100644
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.H
+++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.H
@@ -163,6 +163,7 @@ struct wld_window {
int floating_width;
int floating_height;
int state;
+ bool covered;
};
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
index 1345c17a2..637d47486 100644
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
@@ -1790,6 +1790,29 @@ int Fl_Wayland_Window_Driver::set_cursor_4args(const Fl_RGB_Image *rgb, int hotx
}
+// does win entirely cover its parent ?
+static void does_window_cover_parent(Fl_Window *win) {
+ if (win->parent()) {
+ Fl_Window *parent = win->window();
+ if (win->x() <= 0 && win->y() <= 0 && win->w() >= parent->w() &&
+ win->h() >= parent->h()) {
+ struct wld_window *xid = fl_wl_xid(parent);
+ xid->covered = true;
+ }
+ }
+}
+
+
+// recursively explore all subwindows in a window
+static void scan_subwindows(Fl_Group *g, void (*f)(Fl_Window *)) {
+ for (int i = 0; i < g->children(); i++) {
+ Fl_Widget *o = g->child(i);
+ if (o->as_window()) f(o->as_window());
+ if (o->as_group()) scan_subwindows(o->as_group(), f);
+ }
+}
+
+
void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
struct wld_window *fl_win = fl_wl_xid(pWindow);
if (fl_win && fl_win->kind == DECORATED && !xdg_toplevel()) {
@@ -1885,6 +1908,11 @@ void Fl_Wayland_Window_Driver::resize(int X, int Y, int W, int H) {
if (fl_win && fl_win->kind == SUBWINDOW && fl_win->subsurface)
checkSubwindowFrame(); // make sure subwindow doesn't leak outside parent
+
+ if (Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::MUTTER &&
+ !pWindow->parent()) { // fix for MUTTER bug described in issue #878
+ scan_subwindows(pWindow, does_window_cover_parent);
+ }
}