Skip to content
This repository was archived by the owner on Jul 9, 2025. It is now read-only.

Commit 47d2a2d

Browse files
committed
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
1 parent 7933f3c commit 47d2a2d

File tree

4 files changed

+64
-22
lines changed

4 files changed

+64
-22
lines changed

widget/gtk/MozContainerWayland.cpp

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* We need to wait until wl_surface of mContainer is created
3030
* and then we create and attach our wl_subsurface to it.
3131
*
32-
* wl_subsurface creation has these steps:
32+
* First wl_subsurface creation has these steps:
3333
*
3434
* 1) moz_container_wayland_size_allocate() handler is called when
3535
* mContainer size/position is known.
@@ -41,6 +41,11 @@
4141
* when wl_surface owned by mozContainer is ready.
4242
* We call initial_draw_cbs() handler and we can create our wl_subsurface
4343
* on top of wl_surface owned by mozContainer.
44+
*
45+
* When MozContainer hides/show again, moz_container_wayland_size_allocate()
46+
* handler may not be called as MozContainer size is set. So after first
47+
* show/hide sequence use moz_container_wayland_map_event() to create
48+
* wl_subsurface of MozContainer.
4449
*/
4550

4651
#include "MozContainer.h"
@@ -76,6 +81,8 @@ static void moz_container_wayland_destroy(GtkWidget* widget);
7681

7782
/* widget class methods */
7883
static void moz_container_wayland_map(GtkWidget* widget);
84+
static gboolean moz_container_wayland_map_event(GtkWidget* widget,
85+
GdkEventAny* event);
7986
static void moz_container_wayland_unmap(GtkWidget* widget);
8087
static void moz_container_wayland_size_allocate(GtkWidget* widget,
8188
GtkAllocation* allocation);
@@ -94,6 +101,22 @@ static nsWindow* moz_container_get_nsWindow(MozContainer* container) {
94101
// Imlemented in MozContainer.cpp
95102
void moz_container_realize(GtkWidget* widget);
96103

104+
// Invalidate gtk wl_surface to commit changes to wl_subsurface.
105+
// wl_subsurface changes are effective when parent surface is commited.
106+
static void moz_container_wayland_invalidate(MozContainer* container) {
107+
LOGWAYLAND(("moz_container_wayland_invalidate [%p]\n", (void*)container));
108+
109+
GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
110+
if (!window) {
111+
LOGWAYLAND((" Failed - missing GdkWindow!\n"));
112+
return;
113+
}
114+
115+
GdkRectangle rect = (GdkRectangle){0, 0, gdk_window_get_width(window),
116+
gdk_window_get_height(window)};
117+
gdk_window_invalidate_rect(window, &rect, true);
118+
}
119+
97120
static void moz_container_wayland_move_locked(MozContainer* container, int dx,
98121
int dy) {
99122
LOGWAYLAND(
@@ -110,15 +133,6 @@ static void moz_container_wayland_move_locked(MozContainer* container, int dx,
110133
wl_subsurface_set_position(wl_container->subsurface,
111134
wl_container->subsurface_dx,
112135
wl_container->subsurface_dy);
113-
114-
GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
115-
if (window) {
116-
GdkRectangle rect = (GdkRectangle){0, 0, gdk_window_get_width(window),
117-
gdk_window_get_height(window)};
118-
// wl_subsurface_set_position is actually property of parent surface
119-
// which is effective when parent surface is commited.
120-
gdk_window_invalidate_rect(window, &rect, true);
121-
}
122136
}
123137

124138
// This is called from layout/compositor code only with
@@ -140,6 +154,7 @@ void moz_container_wayland_class_init(MozContainerClass* klass) {
140154
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
141155

142156
widget_class->map = moz_container_wayland_map;
157+
widget_class->map_event = moz_container_wayland_map_event;
143158
widget_class->destroy = moz_container_wayland_destroy;
144159
widget_class->unmap = moz_container_wayland_unmap;
145160
widget_class->realize = moz_container_realize;
@@ -157,6 +172,7 @@ void moz_container_wayland_init(MozContainerWayland* container) {
157172
container->surface_needs_clear = true;
158173
container->subsurface_dx = 0;
159174
container->subsurface_dy = 0;
175+
container->before_first_size_alloc = true;
160176
container->initial_draw_cbs.clear();
161177
container->container_lock = new mozilla::Mutex("MozContainer lock");
162178
}
@@ -212,6 +228,30 @@ static void moz_container_wayland_unmap_internal(MozContainer* container) {
212228
LOGWAYLAND(("%s [%p]\n", __FUNCTION__, (void*)container));
213229
}
214230

231+
static gboolean moz_container_wayland_map_event(GtkWidget* widget,
232+
GdkEventAny* event) {
233+
MozContainerWayland* wl_container = &MOZ_CONTAINER(widget)->wl_container;
234+
LOGWAYLAND(("%s [%p]\n", __FUNCTION__, (void*)MOZ_CONTAINER(widget)));
235+
236+
// Don't create wl_subsurface in map_event when it's already created or
237+
// if we create it for the first time.
238+
if (wl_container->ready_to_draw || wl_container->before_first_size_alloc) {
239+
return FALSE;
240+
}
241+
242+
MutexAutoLock lock(*wl_container->container_lock);
243+
if (!wl_container->surface) {
244+
if (!moz_container_wayland_surface_create_locked(MOZ_CONTAINER(widget))) {
245+
return FALSE;
246+
}
247+
}
248+
249+
moz_container_wayland_set_scale_factor_locked(MOZ_CONTAINER(widget));
250+
moz_container_wayland_set_opaque_region_locked(MOZ_CONTAINER(widget));
251+
moz_container_wayland_invalidate(MOZ_CONTAINER(widget));
252+
return FALSE;
253+
}
254+
215255
void moz_container_wayland_map(GtkWidget* widget) {
216256
LOGWAYLAND(("%s [%p]\n", __FUNCTION__, (void*)widget));
217257

@@ -264,18 +304,17 @@ void moz_container_wayland_size_allocate(GtkWidget* widget,
264304
// We need to position our subsurface according to GdkWindow
265305
// when offset changes (GdkWindow is maximized for instance).
266306
// see gtk-clutter-embed.c for reference.
267-
if (gfxPlatformGtk::GetPlatform()->IsWaylandDisplay()) {
268-
MutexAutoLock lock(*container->wl_container.container_lock);
269-
if (!container->wl_container.surface) {
270-
if (!moz_container_wayland_surface_create_locked(container)) {
271-
return;
272-
}
307+
MutexAutoLock lock(*container->wl_container.container_lock);
308+
if (!container->wl_container.surface) {
309+
if (!moz_container_wayland_surface_create_locked(container)) {
310+
return;
273311
}
274-
moz_container_wayland_set_scale_factor_locked(container);
275-
moz_container_wayland_set_opaque_region_locked(container);
276-
moz_container_wayland_move_locked(container, allocation->x,
277-
allocation->y);
278312
}
313+
moz_container_wayland_set_scale_factor_locked(container);
314+
moz_container_wayland_set_opaque_region_locked(container);
315+
moz_container_wayland_move_locked(container, allocation->x, allocation->y);
316+
moz_container_wayland_invalidate(MOZ_CONTAINER(widget));
317+
container->wl_container.before_first_size_alloc = false;
279318
}
280319
}
281320

@@ -398,7 +437,7 @@ static bool moz_container_wayland_surface_create_locked(
398437
wl_surface_commit(wl_container->surface);
399438
wl_display_flush(WaylandDisplayGet()->GetDisplay());
400439

401-
LOGWAYLAND((" created surface %p ID %p\n", (void*)wl_container->surface,
440+
LOGWAYLAND((" created surface %p ID %d\n", (void*)wl_container->surface,
402441
wl_proxy_get_id((struct wl_proxy*)wl_container->surface)));
403442
return true;
404443
}

widget/gtk/MozContainerWayland.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ struct MozContainerWayland {
4242
gboolean opaque_region_fullscreen;
4343
gboolean surface_needs_clear;
4444
gboolean ready_to_draw;
45+
gboolean before_first_size_alloc;
4546
std::vector<std::function<void(void)>> initial_draw_cbs;
4647
// mozcontainer is used from Compositor and Rendering threads
4748
// so we need to control access to mozcontainer where wayland internals

widget/gtk/nsWindow.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,7 @@ void nsWindow::AddCSDDecorationSize(int* aWidth, int* aHeight) {
10801080
}
10811081
}
10821082

1083+
#ifdef MOZ_WAYLAND
10831084
bool nsWindow::GetCSDDecorationOffset(int* aDx, int* aDy) {
10841085
if (mSizeState == nsSizeMode_Normal &&
10851086
mCSDSupportLevel == GTK_DECORATION_CLIENT && mDrawInTitlebar) {
@@ -1091,6 +1092,7 @@ bool nsWindow::GetCSDDecorationOffset(int* aDx, int* aDy) {
10911092
return false;
10921093
}
10931094
}
1095+
#endif
10941096

10951097
void nsWindow::ApplySizeConstraints(void) {
10961098
if (mShell) {

widget/gtk/nsWindow.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ class nsWindow final : public nsBaseWidget {
238238
void SetProgress(unsigned long progressPercent);
239239

240240
#ifdef MOZ_WAYLAND
241+
bool GetCSDDecorationOffset(int* aDx, int* aDy);
241242
void SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize);
242243
static nsWindow* GetFocusedWindow();
243244
#endif
@@ -264,7 +265,6 @@ class nsWindow final : public nsBaseWidget {
264265

265266
void UpdateClientOffsetFromFrameExtents();
266267
void UpdateClientOffsetFromCSDWindow();
267-
bool GetCSDDecorationOffset(int* aDx, int* aDy);
268268

269269
void DispatchContextMenuEventFromMouseEvent(uint16_t domButton,
270270
GdkEventButton* aEvent);

0 commit comments

Comments
 (0)