1 /* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
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 #include "MozContainer.h"
13 #include "mozilla/WidgetUtilsGtk.h"
17 # include "mozilla/Logging.h"
18 # include "nsTArray.h"
20 extern mozilla::LazyLogModule gWidgetLog
;
21 # define LOGCONTAINER(args) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, args)
23 # define LOGCONTAINER(args)
24 #endif /* MOZ_LOGGING */
27 void moz_container_class_init(MozContainerClass
* klass
);
28 static void moz_container_init(MozContainer
* container
);
30 /* widget class methods */
31 static void moz_container_map(GtkWidget
* widget
);
32 void moz_container_unmap(GtkWidget
* widget
);
33 static void moz_container_size_allocate(GtkWidget
* widget
,
34 GtkAllocation
* allocation
);
35 static void moz_container_realize(GtkWidget
* widget
);
36 static void moz_container_unrealize(GtkWidget
* widget
);
40 GType
moz_container_get_type(void) {
41 static GType moz_container_type
= 0;
43 if (!moz_container_type
) {
44 static GTypeInfo moz_container_info
= {
45 sizeof(MozContainerClass
), /* class_size */
47 NULL
, /* base_finalize */
48 (GClassInitFunc
)moz_container_class_init
, /* class_init */
49 NULL
, /* class_destroy */
50 NULL
, /* class_data */
51 sizeof(MozContainer
), /* instance_size */
53 (GInstanceInitFunc
)moz_container_init
, /* instance_init */
54 NULL
, /* value_table */
58 g_type_register_static(GTK_TYPE_CONTAINER
, "MozContainer",
59 &moz_container_info
, static_cast<GTypeFlags
>(0));
62 return moz_container_type
;
65 GtkWidget
* moz_container_new(void) {
66 MozContainer
* container
;
69 static_cast<MozContainer
*>(g_object_new(MOZ_CONTAINER_TYPE
, nullptr));
71 return GTK_WIDGET(container
);
74 static void moz_container_destroy(GtkWidget
* widget
) {
75 auto* container
= MOZ_CONTAINER(widget
);
76 if (container
->destroyed
) {
77 return; // The destroy signal may run multiple times.
79 LOGCONTAINER(("moz_container_destroy() [%p]\n",
80 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget
))));
81 container
->destroyed
= TRUE
;
82 container
->data
.~Data();
85 void moz_container_class_init(MozContainerClass
* klass
) {
86 /*GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
87 GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); */
88 GtkWidgetClass
* widget_class
= GTK_WIDGET_CLASS(klass
);
90 widget_class
->map
= moz_container_map
;
91 widget_class
->realize
= moz_container_realize
;
92 widget_class
->unrealize
= moz_container_unrealize
;
93 widget_class
->destroy
= moz_container_destroy
;
96 if (mozilla::widget::GdkIsWaylandDisplay()) {
97 widget_class
->size_allocate
= moz_container_wayland_size_allocate
;
98 widget_class
->map_event
= moz_container_wayland_map_event
;
99 widget_class
->unmap
= moz_container_wayland_unmap
;
102 widget_class
->size_allocate
= moz_container_size_allocate
;
103 widget_class
->unmap
= moz_container_unmap
;
109 void moz_container_init(MozContainer
* container
) {
110 container
->destroyed
= FALSE
;
111 new (&container
->data
) MozContainer::Data();
112 gtk_widget_set_can_focus(GTK_WIDGET(container
), TRUE
);
113 gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container
), FALSE
);
114 LOGCONTAINER(("%s [%p]\n", __FUNCTION__
,
115 (void*)moz_container_get_nsWindow(container
)));
118 void moz_container_map(GtkWidget
* widget
) {
119 MozContainer
* container
;
121 g_return_if_fail(IS_MOZ_CONTAINER(widget
));
122 container
= MOZ_CONTAINER(widget
);
124 LOGCONTAINER(("moz_container_map() [%p]",
125 (void*)moz_container_get_nsWindow(container
)));
127 gtk_widget_set_mapped(widget
, TRUE
);
129 if (gtk_widget_get_has_window(widget
)) {
130 gdk_window_show(gtk_widget_get_window(widget
));
133 // Enable rendering to nsWindow/MozContainer
134 nsWindow
* window
= moz_container_get_nsWindow(MOZ_CONTAINER(widget
));
138 void moz_container_unmap(GtkWidget
* widget
) {
139 g_return_if_fail(IS_MOZ_CONTAINER(widget
));
141 LOGCONTAINER(("moz_container_unmap() [%p]",
142 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget
))));
144 // Disable rendering to nsWindow/MozContainer before we really unmap it.
145 nsWindow
* window
= moz_container_get_nsWindow(MOZ_CONTAINER(widget
));
148 gtk_widget_set_mapped(widget
, FALSE
);
150 if (gtk_widget_get_has_window(widget
)) {
151 gdk_window_hide(gtk_widget_get_window(widget
));
155 void moz_container_realize(GtkWidget
* widget
) {
156 GdkWindow
* parent
= gtk_widget_get_parent_window(widget
);
159 gtk_widget_set_realized(widget
, TRUE
);
161 GdkWindowAttr attributes
;
162 gint attributes_mask
= GDK_WA_VISUAL
| GDK_WA_X
| GDK_WA_Y
;
163 GtkAllocation allocation
;
165 gtk_widget_get_allocation(widget
, &allocation
);
166 attributes
.event_mask
= gtk_widget_get_events(widget
);
167 attributes
.x
= allocation
.x
;
168 attributes
.y
= allocation
.y
;
169 attributes
.width
= allocation
.width
;
170 attributes
.height
= allocation
.height
;
171 attributes
.wclass
= GDK_INPUT_OUTPUT
;
172 attributes
.window_type
= GDK_WINDOW_CHILD
;
173 MozContainer
* container
= MOZ_CONTAINER(widget
);
175 container
->data
.force_default_visual
176 ? gdk_screen_get_system_visual(gtk_widget_get_screen(widget
))
177 : gtk_widget_get_visual(widget
);
179 window
= gdk_window_new(parent
, &attributes
, attributes_mask
);
181 LOGCONTAINER(("moz_container_realize() [%p] GdkWindow %p\n",
182 (void*)moz_container_get_nsWindow(container
), (void*)window
));
184 gtk_widget_register_window(widget
, window
);
185 gtk_widget_set_window(widget
, window
);
188 void moz_container_unrealize(GtkWidget
* widget
) {
189 GdkWindow
* window
= gtk_widget_get_window(widget
);
190 LOGCONTAINER(("moz_container_unrealize() [%p] GdkWindow %p\n",
191 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget
)),
194 if (gtk_widget_get_mapped(widget
)) {
195 gtk_widget_unmap(widget
);
198 gtk_widget_unregister_window(widget
, window
);
199 gtk_widget_set_window(widget
, nullptr);
200 gdk_window_destroy(window
);
201 gtk_widget_set_realized(widget
, false);
204 void moz_container_size_allocate(GtkWidget
* widget
, GtkAllocation
* allocation
) {
205 GtkAllocation tmp_allocation
;
207 g_return_if_fail(IS_MOZ_CONTAINER(widget
));
209 LOGCONTAINER(("moz_container_size_allocate [%p] %d,%d -> %d x %d\n",
210 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget
)),
211 allocation
->x
, allocation
->y
, allocation
->width
,
212 allocation
->height
));
214 /* short circuit if you can */
215 gtk_widget_get_allocation(widget
, &tmp_allocation
);
216 if (tmp_allocation
.x
== allocation
->x
&& tmp_allocation
.y
== allocation
->y
&&
217 tmp_allocation
.width
== allocation
->width
&&
218 tmp_allocation
.height
== allocation
->height
) {
222 gtk_widget_set_allocation(widget
, allocation
);
224 if (gtk_widget_get_has_window(widget
) && gtk_widget_get_realized(widget
)) {
225 gdk_window_move_resize(gtk_widget_get_window(widget
), allocation
->x
,
226 allocation
->y
, allocation
->width
,
231 void moz_container_force_default_visual(MozContainer
* container
) {
232 container
->data
.force_default_visual
= true;
235 nsWindow
* moz_container_get_nsWindow(MozContainer
* container
) {
236 gpointer user_data
= g_object_get_data(G_OBJECT(container
), "nsWindow");
237 return static_cast<nsWindow
*>(user_data
);