Bug 1609538 - Workarounds for Mutter 3.36, r=jhorak

This is based on a patch by robert.mader

This is supposed to be a minimal patchset to make Firefox work on
Mutter 3.36 in a similar fassion as on 3.34. The changes should
be compatible with any Wayland compositor, especially those that
do similar agressive culling and frame callback reduction.
While technically non-optimal, they should work as a short time
solution.

1.: Do not commit the toplevel surface in moz_container_move. Instead
use gdk_window_invalidate_rect, which (hopefully) triggers a surface
commit as well while not interfering in the order of commands. The is
necessary as the previous commit would commit invalid state in certain
scenarios (like fullscreening).
This fixes broken fullscreening.

2.: Do not set an opaque region on containers if that would cover the
whole toplevel surface. This works around problems concerning mouse
input responsiveness, as a completely covered toplevel surface might
not get frame callbacks any more, but we currently rely on it to process
input events like mouse movements.

3.: Only set an opaque region on the toplevel surface when maximized.
While the toplevel opaque region is actually redundant as long as the
content surface has an opaque region set, we need it for workaround 2.
But we want to unset it when not needed as occasianally it is not in
sync, creating glitches when e.g. unmaximizing.

Differential Revision: https://phabricator.services.mozilla.com/D65476

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Martin Stransky 2020-03-05 09:02:02 +00:00
Родитель 96fbe7cabc
Коммит 3e893cfd93
3 изменённых файлов: 39 добавлений и 20 удалений

Просмотреть файл

@ -164,13 +164,15 @@ void moz_container_move(MozContainer* container, int dx, int dy) {
// wl_subsurface_set_position is actually property of parent surface
// which is effective when parent surface is commited.
wl_surface* parent_surface =
moz_gtk_widget_get_wl_surface(GTK_WIDGET(container));
if (parent_surface) {
wl_subsurface_set_position(container->subsurface, container->subsurface_dx,
container->subsurface_dy);
wl_surface_commit(parent_surface);
container->surface_position_needs_update = false;
wl_subsurface_set_position(container->subsurface, container->subsurface_dx,
container->subsurface_dy);
container->surface_position_needs_update = false;
GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
if (window) {
GdkRectangle rect = (GdkRectangle){0, 0, gdk_window_get_width(window),
gdk_window_get_height(window)};
gdk_window_invalidate_rect(window, &rect, false);
}
}
@ -222,6 +224,7 @@ void moz_container_init(MozContainer* container) {
container->ready_to_draw = gfxPlatformGtk::GetPlatform()->IsX11Display();
container->opaque_region_needs_update = false;
container->opaque_region_subtract_corners = false;
container->opaque_region_fullscreen = false;
container->surface_needs_clear = true;
container->subsurface_dx = 0;
container->subsurface_dy = 0;
@ -579,12 +582,17 @@ static void moz_container_set_opaque_region(MozContainer* container) {
GtkAllocation allocation;
gtk_widget_get_allocation(GTK_WIDGET(container), &allocation);
// Set region to mozcontainer which does not have any offset
wl_region* region =
CreateOpaqueRegionWayland(0, 0, allocation.width, allocation.height,
container->opaque_region_subtract_corners);
wl_surface_set_opaque_region(container->surface, region);
wl_region_destroy(region);
// Set region to mozcontainer for normal state only
if (!container->opaque_region_fullscreen) {
wl_region* region =
CreateOpaqueRegionWayland(0, 0, allocation.width, allocation.height,
container->opaque_region_subtract_corners);
wl_surface_set_opaque_region(container->surface, region);
wl_region_destroy(region);
} else {
wl_surface_set_opaque_region(container->surface, nullptr);
}
container->opaque_region_needs_update = false;
}
@ -677,9 +685,11 @@ gboolean moz_container_surface_needs_clear(MozContainer* container) {
}
void moz_container_update_opaque_region(MozContainer* container,
bool aSubtractCorners) {
bool aSubtractCorners,
bool aFullScreen) {
container->opaque_region_needs_update = true;
container->opaque_region_subtract_corners = aSubtractCorners;
container->opaque_region_fullscreen = aFullScreen;
// When GL compositor / WebRender is used,
// moz_container_get_wl_egl_window() is called only once when window

Просмотреть файл

@ -82,6 +82,7 @@ struct _MozContainer {
int frame_callback_handler_surface_id;
gboolean opaque_region_needs_update;
gboolean opaque_region_subtract_corners;
gboolean opaque_region_fullscreen;
gboolean surface_position_needs_update;
gboolean surface_needs_clear;
gboolean ready_to_draw;
@ -118,7 +119,8 @@ void moz_container_add_initial_draw_callback(
MozContainer* container, const std::function<void(void)>& initial_draw_cb);
wl_surface* moz_gtk_widget_get_wl_surface(GtkWidget* aWidget);
void moz_container_update_opaque_region(MozContainer* container,
bool aSubtractCorners);
bool aSubtractCorners,
bool aFullScreen);
void moz_container_set_accelerated(MozContainer* container);
#endif

Просмотреть файл

@ -4941,17 +4941,24 @@ void nsWindow::UpdateTopLevelOpaqueRegionWayland(bool aSubtractCorners) {
return;
}
wl_region* region =
CreateOpaqueRegionWayland(x, y, width, height, aSubtractCorners);
wl_surface_set_opaque_region(surface, region);
wl_region_destroy(region);
// Set opaque region to toplevel window only in fullscreen mode.
bool fullScreen = mSizeState != nsSizeMode_Normal && !mIsTiled;
if (fullScreen) {
wl_region* region =
CreateOpaqueRegionWayland(x, y, width, height, aSubtractCorners);
wl_surface_set_opaque_region(surface, region);
wl_region_destroy(region);
} else {
wl_surface_set_opaque_region(surface, nullptr);
}
// TODO -> create a function for it
GdkWindow* window = gtk_widget_get_window(mShell);
if (window) {
gdk_window_invalidate_rect(window, &rect, false);
}
moz_container_update_opaque_region(mContainer, aSubtractCorners);
moz_container_update_opaque_region(mContainer, aSubtractCorners, fullScreen);
}
#endif