/src/mozilla-central/widget/gtk/mozcontainer.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
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 | | #include "mozcontainer.h" |
9 | | #include <gtk/gtk.h> |
10 | | #ifdef MOZ_WAYLAND |
11 | | #include <gdk/gdkx.h> |
12 | | #include <gdk/gdkwayland.h> |
13 | | #include <wayland-egl.h> |
14 | | #endif |
15 | | #include <stdio.h> |
16 | | #include <dlfcn.h> |
17 | | |
18 | | #ifdef ACCESSIBILITY |
19 | | #include <atk/atk.h> |
20 | | #include "maiRedundantObjectFactory.h" |
21 | | #endif |
22 | | |
23 | | /* init methods */ |
24 | | static void moz_container_class_init (MozContainerClass *klass); |
25 | | static void moz_container_init (MozContainer *container); |
26 | | |
27 | | /* widget class methods */ |
28 | | static void moz_container_map (GtkWidget *widget); |
29 | | static void moz_container_unmap (GtkWidget *widget); |
30 | | static void moz_container_realize (GtkWidget *widget); |
31 | | static void moz_container_size_allocate (GtkWidget *widget, |
32 | | GtkAllocation *allocation); |
33 | | |
34 | | /* container class methods */ |
35 | | static void moz_container_remove (GtkContainer *container, |
36 | | GtkWidget *child_widget); |
37 | | static void moz_container_forall (GtkContainer *container, |
38 | | gboolean include_internals, |
39 | | GtkCallback callback, |
40 | | gpointer callback_data); |
41 | | static void moz_container_add (GtkContainer *container, |
42 | | GtkWidget *widget); |
43 | | |
44 | | typedef struct _MozContainerChild MozContainerChild; |
45 | | |
46 | | struct _MozContainerChild { |
47 | | GtkWidget *widget; |
48 | | gint x; |
49 | | gint y; |
50 | | }; |
51 | | |
52 | | static void moz_container_allocate_child (MozContainer *container, |
53 | | MozContainerChild *child); |
54 | | static MozContainerChild * |
55 | | moz_container_get_child (MozContainer *container, GtkWidget *child); |
56 | | |
57 | | /* public methods */ |
58 | | |
59 | | GType |
60 | | moz_container_get_type(void) |
61 | 0 | { |
62 | 0 | static GType moz_container_type = 0; |
63 | 0 |
|
64 | 0 | if (!moz_container_type) { |
65 | 0 | static GTypeInfo moz_container_info = { |
66 | 0 | sizeof(MozContainerClass), /* class_size */ |
67 | 0 | NULL, /* base_init */ |
68 | 0 | NULL, /* base_finalize */ |
69 | 0 | (GClassInitFunc) moz_container_class_init, /* class_init */ |
70 | 0 | NULL, /* class_destroy */ |
71 | 0 | NULL, /* class_data */ |
72 | 0 | sizeof(MozContainer), /* instance_size */ |
73 | 0 | 0, /* n_preallocs */ |
74 | 0 | (GInstanceInitFunc) moz_container_init, /* instance_init */ |
75 | 0 | NULL, /* value_table */ |
76 | 0 | }; |
77 | 0 |
|
78 | 0 | moz_container_type = g_type_register_static (GTK_TYPE_CONTAINER, |
79 | 0 | "MozContainer", |
80 | 0 | &moz_container_info, |
81 | 0 | static_cast<GTypeFlags>(0)); |
82 | 0 | #ifdef ACCESSIBILITY |
83 | 0 | /* Set a factory to return accessible object with ROLE_REDUNDANT for |
84 | 0 | * MozContainer, so that gail won't send focus notification for it */ |
85 | 0 | atk_registry_set_factory_type(atk_get_default_registry(), |
86 | 0 | moz_container_type, |
87 | 0 | mai_redundant_object_factory_get_type()); |
88 | 0 | #endif |
89 | 0 | } |
90 | 0 |
|
91 | 0 | return moz_container_type; |
92 | 0 | } |
93 | | |
94 | | GtkWidget * |
95 | | moz_container_new (void) |
96 | 0 | { |
97 | 0 | MozContainer *container; |
98 | 0 |
|
99 | 0 | container = static_cast<MozContainer*>(g_object_new (MOZ_CONTAINER_TYPE, nullptr)); |
100 | 0 |
|
101 | 0 | return GTK_WIDGET(container); |
102 | 0 | } |
103 | | |
104 | | void |
105 | | moz_container_put (MozContainer *container, GtkWidget *child_widget, |
106 | | gint x, gint y) |
107 | 0 | { |
108 | 0 | MozContainerChild *child; |
109 | 0 |
|
110 | 0 | child = g_new (MozContainerChild, 1); |
111 | 0 |
|
112 | 0 | child->widget = child_widget; |
113 | 0 | child->x = x; |
114 | 0 | child->y = y; |
115 | 0 |
|
116 | 0 | /* printf("moz_container_put %p %p %d %d\n", (void *)container, |
117 | 0 | (void *)child_widget, x, y); */ |
118 | 0 |
|
119 | 0 | container->children = g_list_append (container->children, child); |
120 | 0 |
|
121 | 0 | /* we assume that the caller of this function will have already set |
122 | 0 | the parent GdkWindow because we can have many anonymous children. */ |
123 | 0 | gtk_widget_set_parent(child_widget, GTK_WIDGET(container)); |
124 | 0 | } |
125 | | |
126 | | void |
127 | | moz_container_move (MozContainer *container, GtkWidget *child_widget, |
128 | | gint x, gint y, gint width, gint height) |
129 | 0 | { |
130 | 0 | MozContainerChild *child; |
131 | 0 | GtkAllocation new_allocation; |
132 | 0 |
|
133 | 0 | child = moz_container_get_child (container, child_widget); |
134 | 0 |
|
135 | 0 | child->x = x; |
136 | 0 | child->y = y; |
137 | 0 |
|
138 | 0 | new_allocation.x = x; |
139 | 0 | new_allocation.y = y; |
140 | 0 | new_allocation.width = width; |
141 | 0 | new_allocation.height = height; |
142 | 0 |
|
143 | 0 | /* printf("moz_container_move %p %p will allocate to %d %d %d %d\n", |
144 | 0 | (void *)container, (void *)child_widget, |
145 | 0 | new_allocation.x, new_allocation.y, |
146 | 0 | new_allocation.width, new_allocation.height); */ |
147 | 0 |
|
148 | 0 | gtk_widget_size_allocate(child_widget, &new_allocation); |
149 | 0 | } |
150 | | |
151 | | /* static methods */ |
152 | | |
153 | | void |
154 | | moz_container_class_init (MozContainerClass *klass) |
155 | 0 | { |
156 | 0 | /*GObjectClass *gobject_class = G_OBJECT_CLASS (klass); |
157 | 0 | GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); */ |
158 | 0 | GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass); |
159 | 0 | GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); |
160 | 0 |
|
161 | 0 | widget_class->map = moz_container_map; |
162 | 0 | widget_class->unmap = moz_container_unmap; |
163 | 0 | widget_class->realize = moz_container_realize; |
164 | 0 | widget_class->size_allocate = moz_container_size_allocate; |
165 | 0 |
|
166 | 0 | container_class->remove = moz_container_remove; |
167 | 0 | container_class->forall = moz_container_forall; |
168 | 0 | container_class->add = moz_container_add; |
169 | 0 | } |
170 | | |
171 | | #if defined(MOZ_WAYLAND) |
172 | | static void |
173 | | registry_handle_global (void *data, |
174 | | struct wl_registry *registry, |
175 | | uint32_t name, |
176 | | const char *interface, |
177 | | uint32_t version) |
178 | | { |
179 | | MozContainer *container = MOZ_CONTAINER(data); |
180 | | if(strcmp(interface, "wl_subcompositor") == 0) { |
181 | | container->subcompositor = |
182 | | static_cast<wl_subcompositor*>(wl_registry_bind(registry, |
183 | | name, |
184 | | &wl_subcompositor_interface, |
185 | | 1)); |
186 | | } |
187 | | } |
188 | | |
189 | | static void |
190 | | registry_handle_global_remove (void *data, |
191 | | struct wl_registry *registry, |
192 | | uint32_t name) |
193 | | { |
194 | | } |
195 | | |
196 | | static const struct wl_registry_listener registry_listener = { |
197 | | registry_handle_global, |
198 | | registry_handle_global_remove |
199 | | }; |
200 | | #endif |
201 | | |
202 | | void |
203 | | moz_container_init (MozContainer *container) |
204 | 0 | { |
205 | 0 | gtk_widget_set_can_focus(GTK_WIDGET(container), TRUE); |
206 | 0 | gtk_container_set_resize_mode(GTK_CONTAINER(container), GTK_RESIZE_IMMEDIATE); |
207 | 0 | gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container), FALSE); |
208 | 0 |
|
209 | | #if defined(MOZ_WAYLAND) |
210 | | { |
211 | | container->subcompositor = nullptr; |
212 | | container->surface = nullptr; |
213 | | container->subsurface = nullptr; |
214 | | container->eglwindow = nullptr; |
215 | | container->parent_surface_committed = false; |
216 | | |
217 | | GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container)); |
218 | | if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) { |
219 | | // Available as of GTK 3.8+ |
220 | | static auto sGdkWaylandDisplayGetWlDisplay = |
221 | | (wl_display *(*)(GdkDisplay *)) |
222 | | dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display"); |
223 | | |
224 | | wl_display* display = sGdkWaylandDisplayGetWlDisplay(gdk_display); |
225 | | wl_registry* registry = wl_display_get_registry(display); |
226 | | wl_registry_add_listener(registry, ®istry_listener, container); |
227 | | wl_display_dispatch(display); |
228 | | wl_display_roundtrip(display); |
229 | | } |
230 | | } |
231 | | #endif |
232 | | } |
233 | | |
234 | | #if defined(MOZ_WAYLAND) |
235 | | static void |
236 | | moz_container_commited_handler(GdkFrameClock *clock, MozContainer *container) |
237 | | { |
238 | | container->parent_surface_committed = true; |
239 | | g_signal_handler_disconnect(clock, |
240 | | container->parent_surface_committed_handler); |
241 | | container->parent_surface_committed_handler = 0; |
242 | | } |
243 | | |
244 | | /* We want to draw to GdkWindow owned by mContainer from Compositor thread but |
245 | | * Gtk+ can be used in main thread only. So we create wayland wl_surface |
246 | | * and attach it as an overlay to GdkWindow. |
247 | | * |
248 | | * see gtk_clutter_embed_ensure_subsurface() at gtk-clutter-embed.c |
249 | | * for reference. |
250 | | */ |
251 | | static gboolean |
252 | | moz_container_map_surface(MozContainer *container) |
253 | | { |
254 | | // Available as of GTK 3.8+ |
255 | | static auto sGdkWaylandDisplayGetWlCompositor = |
256 | | (wl_compositor *(*)(GdkDisplay *)) |
257 | | dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_compositor"); |
258 | | static auto sGdkWaylandWindowGetWlSurface = |
259 | | (wl_surface *(*)(GdkWindow *)) |
260 | | dlsym(RTLD_DEFAULT, "gdk_wayland_window_get_wl_surface"); |
261 | | static auto sGdkWindowGetFrameClock = |
262 | | (GdkFrameClock *(*)(GdkWindow *)) |
263 | | dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock"); |
264 | | |
265 | | GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container)); |
266 | | if (GDK_IS_X11_DISPLAY(display)) |
267 | | return false; |
268 | | |
269 | | if (container->subsurface && container->surface) |
270 | | return true; |
271 | | |
272 | | if (!container->parent_surface_committed) { |
273 | | if (!container->parent_surface_committed_handler) { |
274 | | GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); |
275 | | GdkFrameClock *clock = sGdkWindowGetFrameClock(window); |
276 | | container->parent_surface_committed_handler = |
277 | | g_signal_connect_after(clock, "after-paint", |
278 | | G_CALLBACK(moz_container_commited_handler), |
279 | | container); |
280 | | } |
281 | | return false; |
282 | | } |
283 | | |
284 | | if (!container->surface) { |
285 | | struct wl_compositor *compositor; |
286 | | compositor = sGdkWaylandDisplayGetWlCompositor(display); |
287 | | container->surface = wl_compositor_create_surface(compositor); |
288 | | } |
289 | | |
290 | | if (!container->subsurface) { |
291 | | GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); |
292 | | wl_surface* gtk_surface = sGdkWaylandWindowGetWlSurface(window); |
293 | | if (!gtk_surface) { |
294 | | // We requested the underlying wl_surface too early when container |
295 | | // is not realized yet. We'll try again before first rendering |
296 | | // to mContainer. |
297 | | return false; |
298 | | } |
299 | | |
300 | | container->subsurface = |
301 | | wl_subcompositor_get_subsurface (container->subcompositor, |
302 | | container->surface, |
303 | | gtk_surface); |
304 | | gint x, y; |
305 | | gdk_window_get_position(window, &x, &y); |
306 | | wl_subsurface_set_position(container->subsurface, x, y); |
307 | | wl_subsurface_set_desync(container->subsurface); |
308 | | |
309 | | // Route input to parent wl_surface owned by Gtk+ so we get input |
310 | | // events from Gtk+. |
311 | | GdkDisplay* display = gtk_widget_get_display(GTK_WIDGET (container)); |
312 | | wl_compositor* compositor = sGdkWaylandDisplayGetWlCompositor(display); |
313 | | wl_region* region = wl_compositor_create_region(compositor); |
314 | | wl_surface_set_input_region(container->surface, region); |
315 | | wl_region_destroy(region); |
316 | | } |
317 | | return true; |
318 | | } |
319 | | |
320 | | static void |
321 | | moz_container_unmap_surface(MozContainer *container) |
322 | | { |
323 | | g_clear_pointer(&container->eglwindow, wl_egl_window_destroy); |
324 | | g_clear_pointer(&container->subsurface, wl_subsurface_destroy); |
325 | | g_clear_pointer(&container->surface, wl_surface_destroy); |
326 | | |
327 | | if (container->parent_surface_committed_handler) { |
328 | | static auto sGdkWindowGetFrameClock = |
329 | | (GdkFrameClock *(*)(GdkWindow *)) |
330 | | dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock"); |
331 | | GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); |
332 | | GdkFrameClock *clock = sGdkWindowGetFrameClock(window); |
333 | | |
334 | | g_signal_handler_disconnect(clock, |
335 | | container->parent_surface_committed_handler); |
336 | | container->parent_surface_committed_handler = 0; |
337 | | } |
338 | | container->parent_surface_committed = false; |
339 | | } |
340 | | |
341 | | #endif |
342 | | |
343 | | void |
344 | | moz_container_map (GtkWidget *widget) |
345 | 0 | { |
346 | 0 | MozContainer *container; |
347 | 0 | GList *tmp_list; |
348 | 0 | GtkWidget *tmp_child; |
349 | 0 |
|
350 | 0 | g_return_if_fail (IS_MOZ_CONTAINER(widget)); |
351 | 0 | container = MOZ_CONTAINER (widget); |
352 | 0 |
|
353 | 0 | gtk_widget_set_mapped(widget, TRUE); |
354 | 0 |
|
355 | 0 | tmp_list = container->children; |
356 | 0 | while (tmp_list) { |
357 | 0 | tmp_child = ((MozContainerChild *)tmp_list->data)->widget; |
358 | 0 |
|
359 | 0 | if (gtk_widget_get_visible(tmp_child)) { |
360 | 0 | if (!gtk_widget_get_mapped(tmp_child)) |
361 | 0 | gtk_widget_map(tmp_child); |
362 | 0 | } |
363 | 0 | tmp_list = tmp_list->next; |
364 | 0 | } |
365 | 0 |
|
366 | 0 | if (gtk_widget_get_has_window (widget)) { |
367 | 0 | gdk_window_show (gtk_widget_get_window(widget)); |
368 | | #if defined(MOZ_WAYLAND) |
369 | | moz_container_map_surface(MOZ_CONTAINER(widget)); |
370 | | #endif |
371 | | } |
372 | 0 | } |
373 | | |
374 | | void |
375 | | moz_container_unmap (GtkWidget *widget) |
376 | | { |
377 | | g_return_if_fail (IS_MOZ_CONTAINER (widget)); |
378 | | |
379 | | gtk_widget_set_mapped(widget, FALSE); |
380 | | |
381 | | if (gtk_widget_get_has_window (widget)) { |
382 | | gdk_window_hide (gtk_widget_get_window(widget)); |
383 | | #if defined(MOZ_WAYLAND) |
384 | | moz_container_unmap_surface(MOZ_CONTAINER(widget)); |
385 | | #endif |
386 | | } |
387 | | } |
388 | | |
389 | | void |
390 | | moz_container_realize (GtkWidget *widget) |
391 | 0 | { |
392 | 0 | GdkWindow *parent = gtk_widget_get_parent_window (widget); |
393 | 0 | GdkWindow *window; |
394 | 0 |
|
395 | 0 | gtk_widget_set_realized(widget, TRUE); |
396 | 0 |
|
397 | 0 | if (gtk_widget_get_has_window (widget)) { |
398 | 0 | GdkWindowAttr attributes; |
399 | 0 | gint attributes_mask = GDK_WA_VISUAL | GDK_WA_X | GDK_WA_Y; |
400 | 0 | GtkAllocation allocation; |
401 | 0 |
|
402 | 0 | gtk_widget_get_allocation (widget, &allocation); |
403 | 0 | attributes.event_mask = gtk_widget_get_events (widget); |
404 | 0 | attributes.x = allocation.x; |
405 | 0 | attributes.y = allocation.y; |
406 | 0 | attributes.width = allocation.width; |
407 | 0 | attributes.height = allocation.height; |
408 | 0 | attributes.wclass = GDK_INPUT_OUTPUT; |
409 | 0 | attributes.visual = gtk_widget_get_visual (widget); |
410 | 0 | attributes.window_type = GDK_WINDOW_CHILD; |
411 | 0 |
|
412 | 0 | window = gdk_window_new (parent, &attributes, attributes_mask); |
413 | 0 | gdk_window_set_user_data (window, widget); |
414 | 0 | } else { |
415 | 0 | window = parent; |
416 | 0 | g_object_ref (window); |
417 | 0 | } |
418 | 0 |
|
419 | 0 | gtk_widget_set_window (widget, window); |
420 | 0 |
|
421 | 0 | } |
422 | | |
423 | | void |
424 | | moz_container_size_allocate (GtkWidget *widget, |
425 | | GtkAllocation *allocation) |
426 | 0 | { |
427 | 0 | MozContainer *container; |
428 | 0 | GList *tmp_list; |
429 | 0 | GtkAllocation tmp_allocation; |
430 | 0 |
|
431 | 0 | g_return_if_fail (IS_MOZ_CONTAINER (widget)); |
432 | 0 |
|
433 | 0 | /* printf("moz_container_size_allocate %p %d %d %d %d\n", |
434 | 0 | (void *)widget, |
435 | 0 | allocation->x, |
436 | 0 | allocation->y, |
437 | 0 | allocation->width, |
438 | 0 | allocation->height); */ |
439 | 0 |
|
440 | 0 | /* short circuit if you can */ |
441 | 0 | container = MOZ_CONTAINER (widget); |
442 | 0 | gtk_widget_get_allocation(widget, &tmp_allocation); |
443 | 0 | if (!container->children && |
444 | 0 | tmp_allocation.x == allocation->x && |
445 | 0 | tmp_allocation.y == allocation->y && |
446 | 0 | tmp_allocation.width == allocation->width && |
447 | 0 | tmp_allocation.height == allocation->height) { |
448 | 0 | return; |
449 | 0 | } |
450 | 0 | |
451 | 0 | gtk_widget_set_allocation(widget, allocation); |
452 | 0 |
|
453 | 0 | tmp_list = container->children; |
454 | 0 |
|
455 | 0 | while (tmp_list) { |
456 | 0 | MozContainerChild *child = static_cast<MozContainerChild*>(tmp_list->data); |
457 | 0 |
|
458 | 0 | moz_container_allocate_child (container, child); |
459 | 0 |
|
460 | 0 | tmp_list = tmp_list->next; |
461 | 0 | } |
462 | 0 |
|
463 | 0 | if (gtk_widget_get_has_window (widget) && |
464 | 0 | gtk_widget_get_realized (widget)) { |
465 | 0 |
|
466 | 0 | gdk_window_move_resize(gtk_widget_get_window(widget), |
467 | 0 | allocation->x, |
468 | 0 | allocation->y, |
469 | 0 | allocation->width, |
470 | 0 | allocation->height); |
471 | 0 | } |
472 | 0 |
|
473 | | #if defined(MOZ_WAYLAND) |
474 | | // We need to position our subsurface according to GdkWindow |
475 | | // when offset changes (GdkWindow is maximized for instance). |
476 | | // see gtk-clutter-embed.c for reference. |
477 | | if (container->subsurface) { |
478 | | gint x, y; |
479 | | gdk_window_get_position(gtk_widget_get_window(widget), &x, &y); |
480 | | wl_subsurface_set_position(container->subsurface, x, y); |
481 | | } |
482 | | if (container->eglwindow) { |
483 | | wl_egl_window_resize(container->eglwindow, |
484 | | allocation->width, allocation->height, |
485 | | 0, 0); |
486 | | } |
487 | | #endif |
488 | | } |
489 | | |
490 | | void |
491 | | moz_container_remove (GtkContainer *container, GtkWidget *child_widget) |
492 | | { |
493 | | MozContainerChild *child; |
494 | | MozContainer *moz_container; |
495 | | GdkWindow* parent_window; |
496 | | |
497 | | g_return_if_fail (IS_MOZ_CONTAINER(container)); |
498 | | g_return_if_fail (GTK_IS_WIDGET(child_widget)); |
499 | | |
500 | | moz_container = MOZ_CONTAINER(container); |
501 | | |
502 | | child = moz_container_get_child (moz_container, child_widget); |
503 | | g_return_if_fail (child); |
504 | | |
505 | | /* gtk_widget_unparent will remove the parent window (as well as the |
506 | | * parent widget), but, in Mozilla's window hierarchy, the parent window |
507 | | * may need to be kept because it may be part of a GdkWindow sub-hierarchy |
508 | | * that is being moved to another MozContainer. |
509 | | * |
510 | | * (In a conventional GtkWidget hierarchy, GdkWindows being reparented |
511 | | * would have their own GtkWidget and that widget would be the one being |
512 | | * reparented. In Mozilla's hierarchy, the parent_window needs to be |
513 | | * retained so that the GdkWindow sub-hierarchy is maintained.) |
514 | | */ |
515 | | parent_window = gtk_widget_get_parent_window(child_widget); |
516 | | if (parent_window) |
517 | | g_object_ref(parent_window); |
518 | | |
519 | | gtk_widget_unparent(child_widget); |
520 | | |
521 | | if (parent_window) { |
522 | | /* The child_widget will always still exist because g_signal_emit, |
523 | | * which invokes this function, holds a reference. |
524 | | * |
525 | | * If parent_window is the container's root window then it will not be |
526 | | * the parent_window if the child_widget is placed in another |
527 | | * container. |
528 | | */ |
529 | | if (parent_window != gtk_widget_get_window(GTK_WIDGET(container))) |
530 | | gtk_widget_set_parent_window(child_widget, parent_window); |
531 | | |
532 | | g_object_unref(parent_window); |
533 | | } |
534 | | |
535 | | moz_container->children = g_list_remove(moz_container->children, child); |
536 | | g_free(child); |
537 | | } |
538 | | |
539 | | void |
540 | | moz_container_forall (GtkContainer *container, gboolean include_internals, |
541 | | GtkCallback callback, gpointer callback_data) |
542 | | { |
543 | | MozContainer *moz_container; |
544 | | GList *tmp_list; |
545 | | |
546 | | g_return_if_fail (IS_MOZ_CONTAINER(container)); |
547 | | g_return_if_fail (callback != NULL); |
548 | | |
549 | | moz_container = MOZ_CONTAINER(container); |
550 | | |
551 | | tmp_list = moz_container->children; |
552 | | while (tmp_list) { |
553 | | MozContainerChild *child; |
554 | | child = static_cast<MozContainerChild*>(tmp_list->data); |
555 | | tmp_list = tmp_list->next; |
556 | | (* callback) (child->widget, callback_data); |
557 | | } |
558 | | } |
559 | | |
560 | | static void |
561 | | moz_container_allocate_child (MozContainer *container, |
562 | | MozContainerChild *child) |
563 | 0 | { |
564 | 0 | GtkAllocation allocation; |
565 | 0 |
|
566 | 0 | gtk_widget_get_allocation (child->widget, &allocation); |
567 | 0 | allocation.x = child->x; |
568 | 0 | allocation.y = child->y; |
569 | 0 |
|
570 | 0 | gtk_widget_size_allocate (child->widget, &allocation); |
571 | 0 | } |
572 | | |
573 | | MozContainerChild * |
574 | | moz_container_get_child (MozContainer *container, GtkWidget *child_widget) |
575 | 0 | { |
576 | 0 | GList *tmp_list; |
577 | 0 |
|
578 | 0 | tmp_list = container->children; |
579 | 0 | while (tmp_list) { |
580 | 0 | MozContainerChild *child; |
581 | 0 |
|
582 | 0 | child = static_cast<MozContainerChild*>(tmp_list->data); |
583 | 0 | tmp_list = tmp_list->next; |
584 | 0 |
|
585 | 0 | if (child->widget == child_widget) |
586 | 0 | return child; |
587 | 0 | } |
588 | 0 |
|
589 | 0 | return NULL; |
590 | 0 | } |
591 | | |
592 | | static void |
593 | | moz_container_add(GtkContainer *container, GtkWidget *widget) |
594 | 0 | { |
595 | 0 | moz_container_put(MOZ_CONTAINER(container), widget, 0, 0); |
596 | 0 | } |
597 | | |
598 | | #ifdef MOZ_WAYLAND |
599 | | struct wl_surface* |
600 | | moz_container_get_wl_surface(MozContainer *container) |
601 | | { |
602 | | if (!container->subsurface || !container->surface) { |
603 | | GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container)); |
604 | | if (!gdk_window_is_visible(window)) |
605 | | return nullptr; |
606 | | |
607 | | moz_container_map_surface(container); |
608 | | // Set the scale factor for the buffer right after we create it. |
609 | | if (container->surface) { |
610 | | static auto sGdkWindowGetScaleFactorPtr = (gint (*)(GdkWindow*)) |
611 | | dlsym(RTLD_DEFAULT, "gdk_window_get_scale_factor"); |
612 | | if (sGdkWindowGetScaleFactorPtr && window) { |
613 | | gint scaleFactor = (*sGdkWindowGetScaleFactorPtr)(window); |
614 | | wl_surface_set_buffer_scale(container->surface, scaleFactor); |
615 | | } |
616 | | } |
617 | | } |
618 | | |
619 | | return container->surface; |
620 | | } |
621 | | |
622 | | struct wl_egl_window * |
623 | | moz_container_get_wl_egl_window(MozContainer *container) |
624 | | { |
625 | | if (!container->eglwindow) { |
626 | | struct wl_surface *wlsurf = moz_container_get_wl_surface(container); |
627 | | if (!wlsurf) |
628 | | return nullptr; |
629 | | |
630 | | GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container)); |
631 | | container->eglwindow |
632 | | = wl_egl_window_create(wlsurf, |
633 | | gdk_window_get_width(window), |
634 | | gdk_window_get_height(window)); |
635 | | } |
636 | | return container->eglwindow; |
637 | | } |
638 | | |
639 | | gboolean |
640 | | moz_container_has_wl_egl_window(MozContainer *container) |
641 | | { |
642 | | return container->eglwindow ? true : false; |
643 | | } |
644 | | #endif |