Bug 1667851 [Wayland] Use map_event to create wl_subsurface of MozContainer when it's size is already allocated, r=jhorak

- Recently we use size allocation event to create wl_subsurface of MozContainer. Unfortunately size allocation event
  is not called when a window is opened second time, as its size is already set. Use map_event to create
  wl_subsurface in this case.

Depends on D104550

Differential Revision: https://phabricator.services.mozilla.com/D104551
This commit is contained in:
stransky
2021-02-09 19:41:10 +00:00
parent 00be9a0257
commit 01a743d096
4 changed files with 64 additions and 22 deletions

View File

@@ -29,7 +29,7 @@
* We need to wait until wl_surface of mContainer is created * We need to wait until wl_surface of mContainer is created
* and then we create and attach our wl_subsurface to it. * and then we create and attach our wl_subsurface to it.
* *
* wl_subsurface creation has these steps: * First wl_subsurface creation has these steps:
* *
* 1) moz_container_wayland_size_allocate() handler is called when * 1) moz_container_wayland_size_allocate() handler is called when
* mContainer size/position is known. * mContainer size/position is known.
@@ -41,6 +41,11 @@
* when wl_surface owned by mozContainer is ready. * when wl_surface owned by mozContainer is ready.
* We call initial_draw_cbs() handler and we can create our wl_subsurface * We call initial_draw_cbs() handler and we can create our wl_subsurface
* on top of wl_surface owned by mozContainer. * on top of wl_surface owned by mozContainer.
*
* When MozContainer hides/show again, moz_container_wayland_size_allocate()
* handler may not be called as MozContainer size is set. So after first
* show/hide sequence use moz_container_wayland_map_event() to create
* wl_subsurface of MozContainer.
*/ */
#include "MozContainer.h" #include "MozContainer.h"
@@ -76,6 +81,8 @@ static void moz_container_wayland_destroy(GtkWidget* widget);
/* widget class methods */ /* widget class methods */
static void moz_container_wayland_map(GtkWidget* widget); static void moz_container_wayland_map(GtkWidget* widget);
static gboolean moz_container_wayland_map_event(GtkWidget* widget,
GdkEventAny* event);
static void moz_container_wayland_unmap(GtkWidget* widget); static void moz_container_wayland_unmap(GtkWidget* widget);
static void moz_container_wayland_size_allocate(GtkWidget* widget, static void moz_container_wayland_size_allocate(GtkWidget* widget,
GtkAllocation* allocation); GtkAllocation* allocation);
@@ -94,6 +101,22 @@ static nsWindow* moz_container_get_nsWindow(MozContainer* container) {
// Imlemented in MozContainer.cpp // Imlemented in MozContainer.cpp
void moz_container_realize(GtkWidget* widget); void moz_container_realize(GtkWidget* widget);
// Invalidate gtk wl_surface to commit changes to wl_subsurface.
// wl_subsurface changes are effective when parent surface is commited.
static void moz_container_wayland_invalidate(MozContainer* container) {
LOGWAYLAND(("moz_container_wayland_invalidate [%p]\n", (void*)container));
GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
if (!window) {
LOGWAYLAND((" Failed - missing GdkWindow!\n"));
return;
}
GdkRectangle rect = (GdkRectangle){0, 0, gdk_window_get_width(window),
gdk_window_get_height(window)};
gdk_window_invalidate_rect(window, &rect, true);
}
static void moz_container_wayland_move_locked(MozContainer* container, int dx, static void moz_container_wayland_move_locked(MozContainer* container, int dx,
int dy) { int dy) {
LOGWAYLAND( LOGWAYLAND(
@@ -110,15 +133,6 @@ static void moz_container_wayland_move_locked(MozContainer* container, int dx,
wl_subsurface_set_position(wl_container->subsurface, wl_subsurface_set_position(wl_container->subsurface,
wl_container->subsurface_dx, wl_container->subsurface_dx,
wl_container->subsurface_dy); wl_container->subsurface_dy);
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)};
// wl_subsurface_set_position is actually property of parent surface
// which is effective when parent surface is commited.
gdk_window_invalidate_rect(window, &rect, true);
}
} }
// This is called from layout/compositor code only with // This is called from layout/compositor code only with
@@ -140,6 +154,7 @@ void moz_container_wayland_class_init(MozContainerClass* klass) {
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass); GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
widget_class->map = moz_container_wayland_map; widget_class->map = moz_container_wayland_map;
widget_class->map_event = moz_container_wayland_map_event;
widget_class->destroy = moz_container_wayland_destroy; widget_class->destroy = moz_container_wayland_destroy;
widget_class->unmap = moz_container_wayland_unmap; widget_class->unmap = moz_container_wayland_unmap;
widget_class->realize = moz_container_realize; widget_class->realize = moz_container_realize;
@@ -157,6 +172,7 @@ void moz_container_wayland_init(MozContainerWayland* container) {
container->surface_needs_clear = true; container->surface_needs_clear = true;
container->subsurface_dx = 0; container->subsurface_dx = 0;
container->subsurface_dy = 0; container->subsurface_dy = 0;
container->before_first_size_alloc = true;
container->initial_draw_cbs.clear(); container->initial_draw_cbs.clear();
container->container_lock = new mozilla::Mutex("MozContainer lock"); container->container_lock = new mozilla::Mutex("MozContainer lock");
} }
@@ -212,6 +228,30 @@ static void moz_container_wayland_unmap_internal(MozContainer* container) {
LOGWAYLAND(("%s [%p]\n", __FUNCTION__, (void*)container)); LOGWAYLAND(("%s [%p]\n", __FUNCTION__, (void*)container));
} }
static gboolean moz_container_wayland_map_event(GtkWidget* widget,
GdkEventAny* event) {
MozContainerWayland* wl_container = &MOZ_CONTAINER(widget)->wl_container;
LOGWAYLAND(("%s [%p]\n", __FUNCTION__, (void*)MOZ_CONTAINER(widget)));
// Don't create wl_subsurface in map_event when it's already created or
// if we create it for the first time.
if (wl_container->ready_to_draw || wl_container->before_first_size_alloc) {
return FALSE;
}
MutexAutoLock lock(*wl_container->container_lock);
if (!wl_container->surface) {
if (!moz_container_wayland_surface_create_locked(MOZ_CONTAINER(widget))) {
return FALSE;
}
}
moz_container_wayland_set_scale_factor_locked(MOZ_CONTAINER(widget));
moz_container_wayland_set_opaque_region_locked(MOZ_CONTAINER(widget));
moz_container_wayland_invalidate(MOZ_CONTAINER(widget));
return FALSE;
}
void moz_container_wayland_map(GtkWidget* widget) { void moz_container_wayland_map(GtkWidget* widget) {
LOGWAYLAND(("%s [%p]\n", __FUNCTION__, (void*)widget)); LOGWAYLAND(("%s [%p]\n", __FUNCTION__, (void*)widget));
@@ -264,7 +304,6 @@ void moz_container_wayland_size_allocate(GtkWidget* widget,
// We need to position our subsurface according to GdkWindow // We need to position our subsurface according to GdkWindow
// when offset changes (GdkWindow is maximized for instance). // when offset changes (GdkWindow is maximized for instance).
// see gtk-clutter-embed.c for reference. // see gtk-clutter-embed.c for reference.
if (gfxPlatformGtk::GetPlatform()->IsWaylandDisplay()) {
MutexAutoLock lock(*container->wl_container.container_lock); MutexAutoLock lock(*container->wl_container.container_lock);
if (!container->wl_container.surface) { if (!container->wl_container.surface) {
if (!moz_container_wayland_surface_create_locked(container)) { if (!moz_container_wayland_surface_create_locked(container)) {
@@ -273,9 +312,9 @@ void moz_container_wayland_size_allocate(GtkWidget* widget,
} }
moz_container_wayland_set_scale_factor_locked(container); moz_container_wayland_set_scale_factor_locked(container);
moz_container_wayland_set_opaque_region_locked(container); moz_container_wayland_set_opaque_region_locked(container);
moz_container_wayland_move_locked(container, allocation->x, moz_container_wayland_move_locked(container, allocation->x, allocation->y);
allocation->y); moz_container_wayland_invalidate(MOZ_CONTAINER(widget));
} container->wl_container.before_first_size_alloc = false;
} }
} }
@@ -398,7 +437,7 @@ static bool moz_container_wayland_surface_create_locked(
wl_surface_commit(wl_container->surface); wl_surface_commit(wl_container->surface);
wl_display_flush(WaylandDisplayGet()->GetDisplay()); wl_display_flush(WaylandDisplayGet()->GetDisplay());
LOGWAYLAND((" created surface %p ID %p\n", (void*)wl_container->surface, LOGWAYLAND((" created surface %p ID %d\n", (void*)wl_container->surface,
wl_proxy_get_id((struct wl_proxy*)wl_container->surface))); wl_proxy_get_id((struct wl_proxy*)wl_container->surface)));
return true; return true;
} }

View File

@@ -42,6 +42,7 @@ struct MozContainerWayland {
gboolean opaque_region_fullscreen; gboolean opaque_region_fullscreen;
gboolean surface_needs_clear; gboolean surface_needs_clear;
gboolean ready_to_draw; gboolean ready_to_draw;
gboolean before_first_size_alloc;
std::vector<std::function<void(void)>> initial_draw_cbs; std::vector<std::function<void(void)>> initial_draw_cbs;
// mozcontainer is used from Compositor and Rendering threads // mozcontainer is used from Compositor and Rendering threads
// so we need to control access to mozcontainer where wayland internals // so we need to control access to mozcontainer where wayland internals

View File

@@ -1080,6 +1080,7 @@ void nsWindow::AddCSDDecorationSize(int* aWidth, int* aHeight) {
} }
} }
#ifdef MOZ_WAYLAND
bool nsWindow::GetCSDDecorationOffset(int* aDx, int* aDy) { bool nsWindow::GetCSDDecorationOffset(int* aDx, int* aDy) {
if (mSizeState == nsSizeMode_Normal && if (mSizeState == nsSizeMode_Normal &&
mCSDSupportLevel == GTK_DECORATION_CLIENT && mDrawInTitlebar) { mCSDSupportLevel == GTK_DECORATION_CLIENT && mDrawInTitlebar) {
@@ -1091,6 +1092,7 @@ bool nsWindow::GetCSDDecorationOffset(int* aDx, int* aDy) {
return false; return false;
} }
} }
#endif
void nsWindow::ApplySizeConstraints(void) { void nsWindow::ApplySizeConstraints(void) {
if (mShell) { if (mShell) {

View File

@@ -238,6 +238,7 @@ class nsWindow final : public nsBaseWidget {
void SetProgress(unsigned long progressPercent); void SetProgress(unsigned long progressPercent);
#ifdef MOZ_WAYLAND #ifdef MOZ_WAYLAND
bool GetCSDDecorationOffset(int* aDx, int* aDy);
void SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize); void SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize);
static nsWindow* GetFocusedWindow(); static nsWindow* GetFocusedWindow();
#endif #endif
@@ -264,7 +265,6 @@ class nsWindow final : public nsBaseWidget {
void UpdateClientOffsetFromFrameExtents(); void UpdateClientOffsetFromFrameExtents();
void UpdateClientOffsetFromCSDWindow(); void UpdateClientOffsetFromCSDWindow();
bool GetCSDDecorationOffset(int* aDx, int* aDy);
void DispatchContextMenuEventFromMouseEvent(uint16_t domButton, void DispatchContextMenuEventFromMouseEvent(uint16_t domButton,
GdkEventButton* aEvent); GdkEventButton* aEvent);