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"
16 # include "WaylandSurface.h"
20 # include "mozilla/Logging.h"
21 # include "nsTArray.h"
23 extern mozilla::LazyLogModule gWidgetLog
;
24 # define LOGCONTAINER(args) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, args)
26 # define LOGCONTAINER(args)
27 #endif /* MOZ_LOGGING */
30 void moz_container_class_init(MozContainerClass
* klass
);
31 static void moz_container_init(MozContainer
* container
);
33 /* widget class methods */
34 static void moz_container_map(GtkWidget
* widget
);
35 void moz_container_unmap(GtkWidget
* widget
);
36 static void moz_container_size_allocate(GtkWidget
* widget
,
37 GtkAllocation
* allocation
);
38 static void moz_container_realize(GtkWidget
* widget
);
39 static void moz_container_unrealize(GtkWidget
* widget
);
40 static void moz_container_destroy(GtkWidget
* widget
);
44 GType
moz_container_get_type(void) {
45 static GType moz_container_type
= 0;
47 if (!moz_container_type
) {
48 static GTypeInfo moz_container_info
= {
49 sizeof(MozContainerClass
), /* class_size */
51 NULL
, /* base_finalize */
52 (GClassInitFunc
)moz_container_class_init
, /* class_init */
53 NULL
, /* class_destroy */
54 NULL
, /* class_data */
55 sizeof(MozContainer
), /* instance_size */
57 (GInstanceInitFunc
)moz_container_init
, /* instance_init */
58 NULL
, /* value_table */
62 g_type_register_static(GTK_TYPE_CONTAINER
, "MozContainer",
63 &moz_container_info
, static_cast<GTypeFlags
>(0));
66 return moz_container_type
;
69 GtkWidget
* moz_container_new(void* aWindow
,
70 mozilla::widget::WaylandSurface
* aSurface
) {
71 MozContainer
* container
;
73 static_cast<MozContainer
*>(g_object_new(MOZ_CONTAINER_TYPE
, nullptr));
76 container
->wl
= new MozContainerWayland(aSurface
);
77 MOZ_WL_CONTAINER(container
)->mSurface
->SetLoggingWidget(aWindow
);
80 return GTK_WIDGET(container
);
83 void moz_container_class_init(MozContainerClass
* klass
) {
84 /*GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
85 GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); */
86 GtkWidgetClass
* widget_class
= GTK_WIDGET_CLASS(klass
);
88 widget_class
->map
= moz_container_map
;
89 widget_class
->realize
= moz_container_realize
;
90 widget_class
->unrealize
= moz_container_unrealize
;
91 widget_class
->destroy
= moz_container_destroy
;
94 if (mozilla::widget::GdkIsWaylandDisplay()) {
95 widget_class
->size_allocate
= moz_container_wayland_size_allocate
;
96 widget_class
->map_event
= moz_container_wayland_map_event
;
97 widget_class
->unmap
= moz_container_wayland_unmap
;
100 widget_class
->size_allocate
= moz_container_size_allocate
;
101 widget_class
->unmap
= moz_container_unmap
;
107 void moz_container_init(MozContainer
* container
) {
108 LOGCONTAINER(("%s", __FUNCTION__
));
109 container
->destroyed
= FALSE
;
111 container
->wl
= nullptr;
113 gtk_widget_set_can_focus(GTK_WIDGET(container
), TRUE
);
114 gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container
), FALSE
);
117 static void moz_container_destroy(GtkWidget
* widget
) {
118 auto* container
= MOZ_CONTAINER(widget
);
119 if (container
->destroyed
) {
120 return; // The destroy signal may run multiple times.
122 LOGCONTAINER(("moz_container_destroy() [%p]\n",
123 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget
))));
124 container
->destroyed
= TRUE
;
127 delete container
->wl
;
128 container
->wl
= nullptr;
133 void moz_container_map(GtkWidget
* widget
) {
134 MozContainer
* container
;
136 g_return_if_fail(IS_MOZ_CONTAINER(widget
));
137 container
= MOZ_CONTAINER(widget
);
139 LOGCONTAINER(("moz_container_map() [%p]",
140 (void*)moz_container_get_nsWindow(container
)));
142 gtk_widget_set_mapped(widget
, TRUE
);
144 if (gtk_widget_get_has_window(widget
)) {
145 gdk_window_show(gtk_widget_get_window(widget
));
148 // Enable rendering to nsWindow/MozContainer
149 nsWindow
* window
= moz_container_get_nsWindow(MOZ_CONTAINER(widget
));
153 void moz_container_unmap(GtkWidget
* widget
) {
154 g_return_if_fail(IS_MOZ_CONTAINER(widget
));
156 LOGCONTAINER(("moz_container_unmap() [%p]",
157 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget
))));
159 // Disable rendering to nsWindow/MozContainer before we really unmap it.
160 nsWindow
* window
= moz_container_get_nsWindow(MOZ_CONTAINER(widget
));
163 gtk_widget_set_mapped(widget
, FALSE
);
165 if (gtk_widget_get_has_window(widget
)) {
166 gdk_window_hide(gtk_widget_get_window(widget
));
170 void moz_container_realize(GtkWidget
* widget
) {
171 GdkWindow
* parent
= gtk_widget_get_parent_window(widget
);
174 gtk_widget_set_realized(widget
, TRUE
);
176 GdkWindowAttr attributes
;
177 gint attributes_mask
= GDK_WA_VISUAL
| GDK_WA_X
| GDK_WA_Y
;
178 GtkAllocation allocation
;
180 gtk_widget_get_allocation(widget
, &allocation
);
181 attributes
.event_mask
= gtk_widget_get_events(widget
);
182 attributes
.x
= allocation
.x
;
183 attributes
.y
= allocation
.y
;
184 attributes
.width
= allocation
.width
;
185 attributes
.height
= allocation
.height
;
186 attributes
.wclass
= GDK_INPUT_OUTPUT
;
187 attributes
.window_type
= GDK_WINDOW_CHILD
;
188 MozContainer
* container
= MOZ_CONTAINER(widget
);
189 attributes
.visual
= gtk_widget_get_visual(widget
);
191 window
= gdk_window_new(parent
, &attributes
, attributes_mask
);
193 LOGCONTAINER(("moz_container_realize() [%p] GdkWindow %p\n",
194 (void*)moz_container_get_nsWindow(container
), (void*)window
));
196 gtk_widget_register_window(widget
, window
);
197 gtk_widget_set_window(widget
, window
);
200 void moz_container_unrealize(GtkWidget
* widget
) {
201 GdkWindow
* window
= gtk_widget_get_window(widget
);
202 LOGCONTAINER(("moz_container_unrealize() [%p] GdkWindow %p\n",
203 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget
)),
206 if (gtk_widget_get_mapped(widget
)) {
207 gtk_widget_unmap(widget
);
210 gtk_widget_unregister_window(widget
, window
);
211 gtk_widget_set_window(widget
, nullptr);
212 gdk_window_destroy(window
);
213 gtk_widget_set_realized(widget
, false);
216 void moz_container_size_allocate(GtkWidget
* widget
, GtkAllocation
* allocation
) {
217 GtkAllocation tmp_allocation
;
219 g_return_if_fail(IS_MOZ_CONTAINER(widget
));
221 LOGCONTAINER(("moz_container_size_allocate [%p] %d,%d -> %d x %d\n",
222 (void*)moz_container_get_nsWindow(MOZ_CONTAINER(widget
)),
223 allocation
->x
, allocation
->y
, allocation
->width
,
224 allocation
->height
));
226 /* short circuit if you can */
227 gtk_widget_get_allocation(widget
, &tmp_allocation
);
228 if (tmp_allocation
.x
== allocation
->x
&& tmp_allocation
.y
== allocation
->y
&&
229 tmp_allocation
.width
== allocation
->width
&&
230 tmp_allocation
.height
== allocation
->height
) {
234 gtk_widget_set_allocation(widget
, allocation
);
236 if (gtk_widget_get_has_window(widget
) && gtk_widget_get_realized(widget
)) {
237 gdk_window_move_resize(gtk_widget_get_window(widget
), allocation
->x
,
238 allocation
->y
, allocation
->width
,
243 nsWindow
* moz_container_get_nsWindow(MozContainer
* container
) {
244 gpointer user_data
= g_object_get_data(G_OBJECT(container
), "nsWindow");
245 return static_cast<nsWindow
*>(user_data
);