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.
This commit is contained in:
ManoloFLTK 2023-12-28 09:59:51 +01:00
parent 73bd4a53dd
commit 6143764885
3 changed files with 33 additions and 2 deletions

View File

@ -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;
}

View File

@ -163,6 +163,7 @@ struct wld_window {
int floating_width;
int floating_height;
int state;
bool covered;
};

View File

@ -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);
}
}