Bug 1734943 [wpt PR 31170] - Correct scrolling contents cull rect, a=testonly
[gecko.git] / widget / gtk / MozContainerWayland.cpp
blobbed8a08bd5b8c7ecc39f7507b6c2440d0e32cdd4
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 /*
8 * MozContainerWayland is a wrapper over MozContainer which provides
9 * wl_surface for MozContainer widget.
11 * The widget scheme looks like:
13 * ---------------------------------------------------------
14 * | mShell Gtk widget (contains wl_surface owned by Gtk+) |
15 * | |
16 * | --------------------------------------------------- |
17 * | | mContainer (contains wl_surface owned by Gtk+) | |
18 * | | | |
19 * | | --------------------------------------------- | |
20 * | | | wl_subsurface (attached to wl_surface | | |
21 * | | | of mContainer) | | |
22 * | | | | | |
23 * | | | | | |
24 * | | --------------------------------------------- | |
25 * | --------------------------------------------------- |
26 * ---------------------------------------------------------
28 * We draw to wl_subsurface owned by MozContainerWayland.
29 * We need to wait until wl_surface of mContainer is created
30 * and then we create and attach our wl_subsurface to it.
32 * First wl_subsurface creation has these steps:
34 * 1) moz_container_wayland_size_allocate() handler is called when
35 * mContainer size/position is known.
36 * It calls moz_container_wayland_surface_create_locked(), registers
37 * a frame callback handler
38 * moz_container_wayland_frame_callback_handler().
40 * 2) moz_container_wayland_frame_callback_handler() is called
41 * when wl_surface owned by mozContainer is ready.
42 * We call initial_draw_cbs() handler and we can create our wl_subsurface
43 * on top of wl_surface owned by mozContainer.
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.
51 #include "MozContainer.h"
53 #include <dlfcn.h>
54 #include <glib.h>
55 #include <stdio.h>
56 #include <wayland-egl.h>
58 #include "mozilla/gfx/gfxVars.h"
59 #include "nsGtkUtils.h"
60 #include "nsWaylandDisplay.h"
61 #include "base/task.h"
63 #ifdef MOZ_LOGGING
65 # include "mozilla/Logging.h"
66 # include "nsTArray.h"
67 # include "Units.h"
68 # include "nsWindow.h"
69 extern mozilla::LazyLogModule gWidgetWaylandLog;
70 # define LOGWAYLAND(args) \
71 MOZ_LOG(gWidgetWaylandLog, mozilla::LogLevel::Debug, args)
72 #else
73 # define LOGWAYLAND(args)
74 #endif /* MOZ_LOGGING */
76 using namespace mozilla;
77 using namespace mozilla::widget;
79 /* init methods */
80 static void moz_container_wayland_destroy(GtkWidget* widget);
82 /* widget class methods */
83 static void moz_container_wayland_map(GtkWidget* widget);
84 static gboolean moz_container_wayland_map_event(GtkWidget* widget,
85 GdkEventAny* event);
86 static void moz_container_wayland_unmap(GtkWidget* widget);
87 static void moz_container_wayland_size_allocate(GtkWidget* widget,
88 GtkAllocation* allocation);
89 static bool moz_container_wayland_surface_create_locked(
90 MozContainer* container);
91 static void moz_container_wayland_set_opaque_region_locked(
92 MozContainer* container);
94 // Imlemented in MozContainer.cpp
95 void moz_container_realize(GtkWidget* widget);
97 // Invalidate gtk wl_surface to commit changes to wl_subsurface.
98 // wl_subsurface changes are effective when parent surface is commited.
99 static void moz_container_wayland_invalidate(MozContainer* container) {
100 LOGWAYLAND(("moz_container_wayland_invalidate [%p]\n",
101 (void*)moz_container_get_nsWindow(container)));
103 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
104 if (!window) {
105 LOGWAYLAND((" Failed - missing GdkWindow!\n"));
106 return;
108 gdk_window_invalidate_rect(window, nullptr, true);
111 // Route input to parent wl_surface owned by Gtk+ so we get input
112 // events from Gtk+.
113 static void moz_container_clear_input_region(MozContainer* container) {
114 struct wl_compositor* compositor = WaylandDisplayGet()->GetCompositor();
115 MozContainerWayland* wl_container = &container->wl_container;
116 wl_region* region = wl_compositor_create_region(compositor);
117 wl_surface_set_input_region(wl_container->surface, region);
118 wl_region_destroy(region);
121 static void moz_container_wayland_move_locked(MozContainer* container, int dx,
122 int dy) {
123 LOGWAYLAND(("moz_container_wayland_move [%p] %d,%d\n",
124 (void*)moz_container_get_nsWindow(container), dx, dy));
126 MozContainerWayland* wl_container = &container->wl_container;
127 if (!wl_container->subsurface || (wl_container->subsurface_dx == dx &&
128 wl_container->subsurface_dy == dy)) {
129 return;
132 wl_container->subsurface_dx = dx;
133 wl_container->subsurface_dy = dy;
134 wl_subsurface_set_position(wl_container->subsurface,
135 wl_container->subsurface_dx,
136 wl_container->subsurface_dy);
139 // This is called from layout/compositor code only with
140 // size equal to GL rendering context. Otherwise there are
141 // rendering artifacts as wl_egl_window size does not match
142 // GL rendering pipeline setup.
143 void moz_container_wayland_egl_window_set_size(MozContainer* container,
144 int width, int height) {
145 MozContainerWayland* wl_container = &container->wl_container;
146 MutexAutoLock lock(*wl_container->container_lock);
147 if (wl_container->eglwindow) {
148 wl_egl_window_resize(wl_container->eglwindow, width, height, 0, 0);
152 void moz_container_wayland_class_init(MozContainerClass* klass) {
153 /*GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
154 GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); */
155 GtkWidgetClass* widget_class = GTK_WIDGET_CLASS(klass);
157 widget_class->map = moz_container_wayland_map;
158 widget_class->map_event = moz_container_wayland_map_event;
159 widget_class->destroy = moz_container_wayland_destroy;
160 widget_class->unmap = moz_container_wayland_unmap;
161 widget_class->realize = moz_container_realize;
162 widget_class->size_allocate = moz_container_wayland_size_allocate;
165 void moz_container_wayland_init(MozContainerWayland* container) {
166 container->surface = nullptr;
167 container->subsurface = nullptr;
168 container->eglwindow = nullptr;
169 container->frame_callback_handler = nullptr;
170 container->viewport = nullptr;
171 container->ready_to_draw = false;
172 container->opaque_region_needs_updates = false;
173 container->opaque_region_subtract_corners = false;
174 container->opaque_region_used = false;
175 container->subsurface_dx = 0;
176 container->subsurface_dy = 0;
177 container->before_first_size_alloc = true;
178 container->buffer_scale = 1;
179 container->initial_draw_cbs.clear();
180 container->container_lock = new mozilla::Mutex("MozContainer lock");
181 container->commit_to_parent = false;
184 static void moz_container_wayland_destroy(GtkWidget* widget) {
185 MozContainerWayland* container = &MOZ_CONTAINER(widget)->wl_container;
186 delete container->container_lock;
187 container->container_lock = nullptr;
188 container->initial_draw_cbs.clear();
191 void moz_container_wayland_add_initial_draw_callback(
192 MozContainer* container, const std::function<void(void)>& initial_draw_cb) {
193 container->wl_container.initial_draw_cbs.push_back(initial_draw_cb);
196 static void moz_container_wayland_frame_callback_handler(
197 void* data, struct wl_callback* callback, uint32_t time) {
198 MozContainerWayland* wl_container = &MOZ_CONTAINER(data)->wl_container;
200 LOGWAYLAND(
201 ("%s [%p] frame_callback_handler %p ready_to_draw %d (set to true)"
202 " initial_draw callback %zd\n",
203 __FUNCTION__, (void*)moz_container_get_nsWindow(MOZ_CONTAINER(data)),
204 (void*)wl_container->frame_callback_handler, wl_container->ready_to_draw,
205 wl_container->initial_draw_cbs.size()));
207 g_clear_pointer(&wl_container->frame_callback_handler, wl_callback_destroy);
209 if (!wl_container->ready_to_draw) {
210 wl_container->ready_to_draw = true;
211 for (auto const& cb : wl_container->initial_draw_cbs) {
212 cb();
214 wl_container->initial_draw_cbs.clear();
218 static const struct wl_callback_listener moz_container_frame_listener = {
219 moz_container_wayland_frame_callback_handler};
221 static void after_frame_clock_after_paint(GdkFrameClock* clock,
222 MozContainer* container) {
223 struct wl_surface* surface = moz_container_wayland_surface_lock(container);
224 if (surface) {
225 wl_surface_commit(surface);
226 moz_container_wayland_surface_unlock(container, &surface);
230 static bool moz_gdk_wayland_window_add_frame_callback_surface_locked(
231 MozContainer* container) {
232 static auto sGdkWaylandWindowAddCallbackSurface =
233 (void (*)(GdkWindow*, struct wl_surface*))dlsym(
234 RTLD_DEFAULT, "gdk_wayland_window_add_frame_callback_surface");
236 if (!StaticPrefs::widget_wayland_opaque_region_enabled_AtStartup() ||
237 !sGdkWaylandWindowAddCallbackSurface) {
238 return false;
241 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
242 MozContainerWayland* wl_container = &container->wl_container;
244 sGdkWaylandWindowAddCallbackSurface(window, wl_container->surface);
246 GdkFrameClock* frame_clock = gdk_window_get_frame_clock(window);
247 g_signal_connect_after(frame_clock, "after-paint",
248 G_CALLBACK(after_frame_clock_after_paint), container);
249 return true;
252 static void moz_gdk_wayland_window_remove_frame_callback_surface_locked(
253 MozContainer* container) {
254 static auto sGdkWaylandWindowRemoveCallbackSurface =
255 (void (*)(GdkWindow*, struct wl_surface*))dlsym(
256 RTLD_DEFAULT, "gdk_wayland_window_remove_frame_callback_surface");
258 if (!sGdkWaylandWindowRemoveCallbackSurface) {
259 return;
262 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
263 MozContainerWayland* wl_container = &container->wl_container;
265 if (wl_container->surface) {
266 sGdkWaylandWindowRemoveCallbackSurface(window, wl_container->surface);
269 GdkFrameClock* frame_clock = gdk_window_get_frame_clock(window);
270 g_signal_handlers_disconnect_by_func(
271 frame_clock, FuncToGpointer(after_frame_clock_after_paint), container);
274 static void moz_container_wayland_unmap_internal(MozContainer* container) {
275 MozContainerWayland* wl_container = &container->wl_container;
276 MutexAutoLock lock(*wl_container->container_lock);
278 LOGWAYLAND(("%s [%p]\n", __FUNCTION__,
279 (void*)moz_container_get_nsWindow(container)));
281 if (wl_container->opaque_region_used) {
282 moz_gdk_wayland_window_remove_frame_callback_surface_locked(container);
284 if (wl_container->commit_to_parent) {
285 wl_container->surface = nullptr;
288 g_clear_pointer(&wl_container->eglwindow, wl_egl_window_destroy);
289 g_clear_pointer(&wl_container->subsurface, wl_subsurface_destroy);
290 g_clear_pointer(&wl_container->surface, wl_surface_destroy);
291 g_clear_pointer(&wl_container->viewport, wp_viewport_destroy);
292 g_clear_pointer(&wl_container->frame_callback_handler, wl_callback_destroy);
294 wl_container->ready_to_draw = false;
295 wl_container->buffer_scale = 1;
298 static gboolean moz_container_wayland_map_event(GtkWidget* widget,
299 GdkEventAny* event) {
300 MozContainerWayland* wl_container = &MOZ_CONTAINER(widget)->wl_container;
301 LOGWAYLAND(("%s [%p]\n", __FUNCTION__,
302 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget))));
304 // Don't create wl_subsurface in map_event when it's already created or
305 // if we create it for the first time.
306 if (wl_container->ready_to_draw || wl_container->before_first_size_alloc) {
307 return FALSE;
310 MutexAutoLock lock(*wl_container->container_lock);
311 if (!wl_container->surface) {
312 if (!moz_container_wayland_surface_create_locked(MOZ_CONTAINER(widget))) {
313 return FALSE;
317 moz_container_wayland_set_scale_factor_locked(MOZ_CONTAINER(widget));
318 moz_container_wayland_set_opaque_region_locked(MOZ_CONTAINER(widget));
319 moz_container_clear_input_region(MOZ_CONTAINER(widget));
320 moz_container_wayland_invalidate(MOZ_CONTAINER(widget));
321 return FALSE;
324 void moz_container_wayland_map(GtkWidget* widget) {
325 LOGWAYLAND(("%s [%p]\n", __FUNCTION__,
326 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget))));
328 g_return_if_fail(IS_MOZ_CONTAINER(widget));
329 gtk_widget_set_mapped(widget, TRUE);
331 if (gtk_widget_get_has_window(widget)) {
332 gdk_window_show(gtk_widget_get_window(widget));
336 void moz_container_wayland_unmap(GtkWidget* widget) {
337 LOGWAYLAND(("%s [%p]\n", __FUNCTION__,
338 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget))));
340 g_return_if_fail(IS_MOZ_CONTAINER(widget));
341 gtk_widget_set_mapped(widget, FALSE);
343 if (gtk_widget_get_has_window(widget)) {
344 gdk_window_hide(gtk_widget_get_window(widget));
345 moz_container_wayland_unmap_internal(MOZ_CONTAINER(widget));
349 void moz_container_wayland_size_allocate(GtkWidget* widget,
350 GtkAllocation* allocation) {
351 MozContainer* container;
352 GtkAllocation tmp_allocation;
354 g_return_if_fail(IS_MOZ_CONTAINER(widget));
356 LOGWAYLAND(("moz_container_wayland_size_allocate [%p] %d,%d -> %d x %d\n",
357 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget)),
358 allocation->x, allocation->y, allocation->width,
359 allocation->height));
361 /* short circuit if you can */
362 container = MOZ_CONTAINER(widget);
363 gtk_widget_get_allocation(widget, &tmp_allocation);
364 if (!container->children && tmp_allocation.x == allocation->x &&
365 tmp_allocation.y == allocation->y &&
366 tmp_allocation.width == allocation->width &&
367 tmp_allocation.height == allocation->height) {
368 return;
370 gtk_widget_set_allocation(widget, allocation);
372 if (gtk_widget_get_has_window(widget) && gtk_widget_get_realized(widget)) {
373 gdk_window_move_resize(gtk_widget_get_window(widget), allocation->x,
374 allocation->y, allocation->width,
375 allocation->height);
376 // We need to position our subsurface according to GdkWindow
377 // when offset changes (GdkWindow is maximized for instance).
378 // see gtk-clutter-embed.c for reference.
379 MutexAutoLock lock(*container->wl_container.container_lock);
380 if (!container->wl_container.surface) {
381 if (!moz_container_wayland_surface_create_locked(container)) {
382 return;
385 moz_container_wayland_set_scale_factor_locked(container);
386 moz_container_wayland_set_opaque_region_locked(container);
387 moz_container_wayland_move_locked(container, allocation->x, allocation->y);
388 moz_container_clear_input_region(container);
389 moz_container_wayland_invalidate(MOZ_CONTAINER(widget));
390 container->wl_container.before_first_size_alloc = false;
394 static wl_region* moz_container_wayland_create_opaque_region(
395 int aX, int aY, int aWidth, int aHeight, bool aSubtractCorners) {
396 struct wl_compositor* compositor = WaylandDisplayGet()->GetCompositor();
397 wl_region* region = wl_compositor_create_region(compositor);
398 wl_region_add(region, aX, aY, aWidth, aHeight);
399 if (aSubtractCorners) {
400 wl_region_subtract(region, aX, aY, TITLEBAR_SHAPE_MASK_HEIGHT,
401 TITLEBAR_SHAPE_MASK_HEIGHT);
402 wl_region_subtract(region, aX + aWidth - TITLEBAR_SHAPE_MASK_HEIGHT, aY,
403 TITLEBAR_SHAPE_MASK_HEIGHT, TITLEBAR_SHAPE_MASK_HEIGHT);
405 return region;
408 static void moz_container_wayland_set_opaque_region_locked(
409 MozContainer* container) {
410 MozContainerWayland* wl_container = &container->wl_container;
412 if (!wl_container->opaque_region_needs_updates) {
413 return;
416 if (!wl_container->opaque_region_used) {
417 wl_container->opaque_region_needs_updates = false;
418 return;
421 GtkAllocation allocation;
422 gtk_widget_get_allocation(GTK_WIDGET(container), &allocation);
424 wl_region* region = moz_container_wayland_create_opaque_region(
425 0, 0, allocation.width, allocation.height,
426 wl_container->opaque_region_subtract_corners);
427 wl_surface_set_opaque_region(wl_container->surface, region);
428 wl_region_destroy(region);
429 wl_container->opaque_region_needs_updates = false;
432 static void moz_container_wayland_set_opaque_region(MozContainer* container) {
433 MozContainerWayland* wl_container = &container->wl_container;
434 MutexAutoLock lock(*wl_container->container_lock);
435 if (wl_container->surface) {
436 moz_container_wayland_set_opaque_region_locked(container);
440 void moz_container_wayland_set_scale_factor_locked(MozContainer* container) {
441 if (gfx::gfxVars::UseWebRenderCompositor()) {
442 // the compositor backend handles scaling itself
443 return;
446 MozContainerWayland* wl_container = &container->wl_container;
447 nsWindow* window = moz_container_get_nsWindow(container);
449 if (window && window->UseFractionalScale()) {
450 if (!wl_container->viewport) {
451 wl_container->viewport = wp_viewporter_get_viewport(
452 WaylandDisplayGet()->GetViewporter(), wl_container->surface);
455 GdkWindow* gdkWindow = gtk_widget_get_window(GTK_WIDGET(container));
456 wp_viewport_set_destination(wl_container->viewport,
457 gdk_window_get_width(gdkWindow),
458 gdk_window_get_height(gdkWindow));
459 } else {
460 int scale = window ? window->GdkCeiledScaleFactor() : 1;
462 if (scale == wl_container->buffer_scale) {
463 return;
466 LOGWAYLAND(("%s [%p] scale %d\n", __FUNCTION__,
467 (void*)moz_container_get_nsWindow(container), scale));
468 wl_surface_set_buffer_scale(wl_container->surface, scale);
469 wl_container->buffer_scale = scale;
473 void moz_container_wayland_set_scale_factor(MozContainer* container) {
474 MutexAutoLock lock(*container->wl_container.container_lock);
475 if (container->wl_container.surface) {
476 moz_container_wayland_set_scale_factor_locked(container);
480 static bool moz_container_wayland_surface_create_locked(
481 MozContainer* container) {
482 MozContainerWayland* wl_container = &container->wl_container;
484 LOGWAYLAND(("%s [%p]\n", __FUNCTION__,
485 (void*)moz_container_get_nsWindow(container)));
487 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
488 wl_surface* parent_surface = gdk_wayland_window_get_wl_surface(window);
489 if (!parent_surface) {
490 LOGWAYLAND((" Failed - missing parent surface!"));
491 return false;
493 LOGWAYLAND((" gtk wl_surface %p ID %d\n", (void*)parent_surface,
494 wl_proxy_get_id((struct wl_proxy*)parent_surface)));
496 if (wl_container->commit_to_parent) {
497 LOGWAYLAND((" commit to parent"));
498 wl_container->surface = parent_surface;
499 NS_DispatchToCurrentThread(NewRunnableFunction(
500 "moz_container_wayland_frame_callback_handler",
501 &moz_container_wayland_frame_callback_handler, container, nullptr, 0));
502 return true;
505 // Available as of GTK 3.8+
506 struct wl_compositor* compositor = WaylandDisplayGet()->GetCompositor();
507 wl_container->surface = wl_compositor_create_surface(compositor);
508 if (!wl_container->surface) {
509 LOGWAYLAND((" Failed - can't create surface!"));
510 return false;
513 wl_container->subsurface =
514 wl_subcompositor_get_subsurface(WaylandDisplayGet()->GetSubcompositor(),
515 wl_container->surface, parent_surface);
516 if (!wl_container->subsurface) {
517 g_clear_pointer(&wl_container->surface, wl_surface_destroy);
518 LOGWAYLAND((" Failed - can't create sub-surface!"));
519 return false;
521 wl_subsurface_set_desync(wl_container->subsurface);
523 // Try to guess subsurface offset to avoid potential flickering.
524 int dx, dy;
525 if (moz_container_get_nsWindow(container)->GetCSDDecorationOffset(&dx, &dy)) {
526 wl_container->subsurface_dx = dx;
527 wl_container->subsurface_dy = dy;
528 wl_subsurface_set_position(wl_container->subsurface, dx, dy);
529 LOGWAYLAND((" guessing subsurface position %d %d\n", dx, dy));
532 // If there's pending frame callback it's for wrong parent surface,
533 // so delete it.
534 if (wl_container->frame_callback_handler) {
535 g_clear_pointer(&wl_container->frame_callback_handler, wl_callback_destroy);
537 wl_container->frame_callback_handler = wl_surface_frame(parent_surface);
538 wl_callback_add_listener(wl_container->frame_callback_handler,
539 &moz_container_frame_listener, container);
540 LOGWAYLAND((
541 " created frame callback ID %d\n",
542 wl_proxy_get_id((struct wl_proxy*)wl_container->frame_callback_handler)));
544 wl_surface_commit(wl_container->surface);
545 wl_display_flush(WaylandDisplayGet()->GetDisplay());
547 wl_container->opaque_region_used =
548 moz_gdk_wayland_window_add_frame_callback_surface_locked(container);
550 LOGWAYLAND((" created surface %p ID %d\n", (void*)wl_container->surface,
551 wl_proxy_get_id((struct wl_proxy*)wl_container->surface)));
552 return true;
555 struct wl_surface* moz_container_wayland_surface_lock(MozContainer* container) {
556 // LOGWAYLAND(("%s [%p] surface %p ready_to_draw %d\n", __FUNCTION__,
557 // (void*)container, (void*)container->wl_container.surface,
558 // container->wl_container.ready_to_draw));
559 if (!container->wl_container.surface ||
560 !container->wl_container.ready_to_draw) {
561 return nullptr;
563 container->wl_container.container_lock->Lock();
564 return container->wl_container.surface;
567 void moz_container_wayland_surface_unlock(MozContainer* container,
568 struct wl_surface** surface) {
569 // Temporary disabled to avoid log noise
570 // LOGWAYLAND(("%s [%p] surface %p\n", __FUNCTION__, (void*)container,
571 // (void*)container->wl_container.surface));
572 if (*surface) {
573 container->wl_container.container_lock->Unlock();
574 *surface = nullptr;
578 struct wl_surface* moz_container_wayland_get_surface_locked(
579 MozContainer* container) {
580 LOGWAYLAND(("%s [%p] surface %p ready_to_draw %d\n", __FUNCTION__,
581 (void*)moz_container_get_nsWindow(container),
582 (void*)container->wl_container.surface,
583 container->wl_container.ready_to_draw));
584 if (!container->wl_container.surface ||
585 !container->wl_container.ready_to_draw) {
586 return nullptr;
588 moz_container_wayland_set_scale_factor_locked(container);
589 return container->wl_container.surface;
592 void moz_container_wayland_lock(MozContainer* container) {
593 container->wl_container.container_lock->Lock();
596 void moz_container_wayland_unlock(MozContainer* container) {
597 container->wl_container.container_lock->Unlock();
600 struct wl_egl_window* moz_container_wayland_get_egl_window(
601 MozContainer* container, double scale) {
602 MozContainerWayland* wl_container = &container->wl_container;
604 LOGWAYLAND(("%s [%p] eglwindow %p\n", __FUNCTION__,
605 (void*)moz_container_get_nsWindow(container),
606 (void*)wl_container->eglwindow));
608 MutexAutoLock lock(*wl_container->container_lock);
609 if (!wl_container->surface || !wl_container->ready_to_draw) {
610 return nullptr;
612 if (!wl_container->eglwindow) {
613 GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
614 wl_container->eglwindow = wl_egl_window_create(
615 wl_container->surface, (int)round(gdk_window_get_width(window) * scale),
616 (int)round(gdk_window_get_height(window) * scale));
618 LOGWAYLAND(("%s [%p] created eglwindow %p\n", __FUNCTION__,
619 (void*)moz_container_get_nsWindow(container),
620 (void*)wl_container->eglwindow));
622 return wl_container->eglwindow;
625 gboolean moz_container_wayland_has_egl_window(MozContainer* container) {
626 return container->wl_container.eglwindow != nullptr;
629 void moz_container_wayland_update_opaque_region(MozContainer* container,
630 bool aSubtractCorners) {
631 MozContainerWayland* wl_container = &container->wl_container;
632 wl_container->opaque_region_needs_updates = true;
633 wl_container->opaque_region_subtract_corners = aSubtractCorners;
635 // When GL compositor / WebRender is used,
636 // moz_container_wayland_get_egl_window() is called only once when window
637 // is created or resized so update opaque region now.
638 if (moz_container_wayland_has_egl_window(container)) {
639 moz_container_wayland_set_opaque_region(container);
643 gboolean moz_container_wayland_can_draw(MozContainer* container) {
644 return container ? container->wl_container.ready_to_draw : false;
647 double moz_container_wayland_get_scale(MozContainer* container) {
648 nsWindow* window = moz_container_get_nsWindow(container);
649 return window ? window->FractionalScaleFactor() : 1;
652 void moz_container_wayland_set_commit_to_parent(MozContainer* container) {
653 MozContainerWayland* wl_container = &container->wl_container;
654 wl_container->commit_to_parent = true;
657 bool moz_container_wayland_is_commiting_to_parent(MozContainer* container) {
658 MozContainerWayland* wl_container = &container->wl_container;
659 return wl_container->commit_to_parent;