1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
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/. */
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+) |
16 * | --------------------------------------------------- |
17 * | | mContainer (contains wl_surface owned by Gtk+) | |
19 * | | --------------------------------------------- | |
20 * | | | wl_subsurface (attached to wl_surface | | |
21 * | | | of mContainer) | | |
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"
56 #include <wayland-egl.h>
58 #include "mozilla/gfx/gfxVars.h"
59 #include "nsGtkUtils.h"
60 #include "nsWaylandDisplay.h"
61 #include "base/task.h"
65 # include "mozilla/Logging.h"
66 # include "nsTArray.h"
68 # include "nsWindow.h"
69 extern mozilla::LazyLogModule gWidgetWaylandLog
;
70 # define LOGWAYLAND(args) \
71 MOZ_LOG(gWidgetWaylandLog, mozilla::LogLevel::Debug, args)
73 # define LOGWAYLAND(args)
74 #endif /* MOZ_LOGGING */
76 using namespace mozilla
;
77 using namespace mozilla::widget
;
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
,
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
));
105 LOGWAYLAND((" Failed - missing GdkWindow!\n"));
108 gdk_window_invalidate_rect(window
, nullptr, true);
111 // Route input to parent wl_surface owned by Gtk+ so we get input
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
,
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
)) {
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
;
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
) {
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
);
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
) {
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
);
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
) {
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
) {
310 MutexAutoLock
lock(*wl_container
->container_lock
);
311 if (!wl_container
->surface
) {
312 if (!moz_container_wayland_surface_create_locked(MOZ_CONTAINER(widget
))) {
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
));
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
) {
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
,
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
)) {
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
);
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
) {
416 if (!wl_container
->opaque_region_used
) {
417 wl_container
->opaque_region_needs_updates
= false;
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
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
));
460 int scale
= window
? window
->GdkCeiledScaleFactor() : 1;
462 if (scale
== wl_container
->buffer_scale
) {
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!"));
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));
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!"));
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!"));
521 wl_subsurface_set_desync(wl_container
->subsurface
);
523 // Try to guess subsurface offset to avoid potential flickering.
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,
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
);
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
)));
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
) {
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));
573 container
->wl_container
.container_lock
->Unlock();
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
) {
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
) {
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
;