1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 #include "mozcontainer.h"
14 #include "maiRedundantObjectFactory.h"
18 static void moz_container_class_init (MozContainerClass
*klass
);
19 static void moz_container_init (MozContainer
*container
);
21 /* widget class methods */
22 static void moz_container_map (GtkWidget
*widget
);
23 static void moz_container_unmap (GtkWidget
*widget
);
24 static void moz_container_realize (GtkWidget
*widget
);
25 static void moz_container_size_allocate (GtkWidget
*widget
,
26 GtkAllocation
*allocation
);
28 /* container class methods */
29 static void moz_container_remove (GtkContainer
*container
,
30 GtkWidget
*child_widget
);
31 static void moz_container_forall (GtkContainer
*container
,
32 gboolean include_internals
,
34 gpointer callback_data
);
35 static void moz_container_add (GtkContainer
*container
,
38 typedef struct _MozContainerChild MozContainerChild
;
40 struct _MozContainerChild
{
46 static void moz_container_allocate_child (MozContainer
*container
,
47 MozContainerChild
*child
);
48 static MozContainerChild
*
49 moz_container_get_child (MozContainer
*container
, GtkWidget
*child
);
54 moz_container_get_type(void)
56 static GType moz_container_type
= 0;
58 if (!moz_container_type
) {
59 static GTypeInfo moz_container_info
= {
60 sizeof(MozContainerClass
), /* class_size */
62 NULL
, /* base_finalize */
63 (GClassInitFunc
) moz_container_class_init
, /* class_init */
64 NULL
, /* class_destroy */
65 NULL
, /* class_data */
66 sizeof(MozContainer
), /* instance_size */
68 (GInstanceInitFunc
) moz_container_init
, /* instance_init */
69 NULL
, /* value_table */
72 moz_container_type
= g_type_register_static (GTK_TYPE_CONTAINER
,
74 &moz_container_info
, 0);
76 /* Set a factory to return accessible object with ROLE_REDUNDANT for
77 * MozContainer, so that gail won't send focus notification for it */
78 atk_registry_set_factory_type(atk_get_default_registry(),
80 mai_redundant_object_factory_get_type());
84 return moz_container_type
;
88 moz_container_new (void)
90 MozContainer
*container
;
92 container
= g_object_new (MOZ_CONTAINER_TYPE
, NULL
);
94 return GTK_WIDGET(container
);
98 moz_container_put (MozContainer
*container
, GtkWidget
*child_widget
,
101 MozContainerChild
*child
;
103 child
= g_new (MozContainerChild
, 1);
105 child
->widget
= child_widget
;
109 /* printf("moz_container_put %p %p %d %d\n", (void *)container,
110 (void *)child_widget, x, y); */
112 container
->children
= g_list_append (container
->children
, child
);
114 /* we assume that the caller of this function will have already set
115 the parent GdkWindow because we can have many anonymous children. */
116 gtk_widget_set_parent(child_widget
, GTK_WIDGET(container
));
120 moz_container_move (MozContainer
*container
, GtkWidget
*child_widget
,
121 gint x
, gint y
, gint width
, gint height
)
123 MozContainerChild
*child
;
124 GtkAllocation new_allocation
;
126 child
= moz_container_get_child (container
, child_widget
);
131 new_allocation
.x
= x
;
132 new_allocation
.y
= y
;
133 new_allocation
.width
= width
;
134 new_allocation
.height
= height
;
136 /* printf("moz_container_move %p %p will allocate to %d %d %d %d\n",
137 (void *)container, (void *)child_widget,
138 new_allocation.x, new_allocation.y,
139 new_allocation.width, new_allocation.height); */
141 gtk_widget_size_allocate(child_widget
, &new_allocation
);
147 moz_container_class_init (MozContainerClass
*klass
)
149 /*GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
150 GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); */
151 GtkContainerClass
*container_class
= GTK_CONTAINER_CLASS (klass
);
152 GtkWidgetClass
*widget_class
= GTK_WIDGET_CLASS (klass
);
154 widget_class
->map
= moz_container_map
;
155 widget_class
->unmap
= moz_container_unmap
;
156 widget_class
->realize
= moz_container_realize
;
157 widget_class
->size_allocate
= moz_container_size_allocate
;
159 container_class
->remove
= moz_container_remove
;
160 container_class
->forall
= moz_container_forall
;
161 container_class
->add
= moz_container_add
;
165 moz_container_init (MozContainer
*container
)
167 gtk_widget_set_can_focus(GTK_WIDGET(container
), TRUE
);
168 gtk_container_set_resize_mode(GTK_CONTAINER(container
), GTK_RESIZE_IMMEDIATE
);
169 gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container
), FALSE
);
173 moz_container_map (GtkWidget
*widget
)
175 MozContainer
*container
;
177 GtkWidget
*tmp_child
;
179 g_return_if_fail (IS_MOZ_CONTAINER(widget
));
180 container
= MOZ_CONTAINER (widget
);
182 gtk_widget_set_mapped(widget
, TRUE
);
184 tmp_list
= container
->children
;
186 tmp_child
= ((MozContainerChild
*)tmp_list
->data
)->widget
;
188 if (gtk_widget_get_visible(tmp_child
)) {
189 if (!gtk_widget_get_mapped(tmp_child
))
190 gtk_widget_map(tmp_child
);
192 tmp_list
= tmp_list
->next
;
195 if (gtk_widget_get_has_window (widget
)) {
196 gdk_window_show (gtk_widget_get_window(widget
));
201 moz_container_unmap (GtkWidget
*widget
)
203 g_return_if_fail (IS_MOZ_CONTAINER (widget
));
205 gtk_widget_set_mapped(widget
, FALSE
);
207 if (gtk_widget_get_has_window (widget
)) {
208 gdk_window_hide (gtk_widget_get_window(widget
));
213 moz_container_realize (GtkWidget
*widget
)
215 GdkWindow
*parent
= gtk_widget_get_parent_window (widget
);
218 gtk_widget_set_realized(widget
, TRUE
);
220 if (gtk_widget_get_has_window (widget
)) {
221 GdkWindowAttr attributes
;
222 gint attributes_mask
= GDK_WA_VISUAL
| GDK_WA_X
| GDK_WA_Y
;
223 GtkAllocation allocation
;
225 gtk_widget_get_allocation (widget
, &allocation
);
226 attributes
.event_mask
= gtk_widget_get_events (widget
);
227 attributes
.x
= allocation
.x
;
228 attributes
.y
= allocation
.y
;
229 attributes
.width
= allocation
.width
;
230 attributes
.height
= allocation
.height
;
231 attributes
.wclass
= GDK_INPUT_OUTPUT
;
232 attributes
.visual
= gtk_widget_get_visual (widget
);
233 attributes
.window_type
= GDK_WINDOW_CHILD
;
235 #if (MOZ_WIDGET_GTK == 2)
236 attributes
.colormap
= gtk_widget_get_colormap (widget
);
237 attributes_mask
|= GDK_WA_COLORMAP
;
240 window
= gdk_window_new (parent
, &attributes
, attributes_mask
);
241 gdk_window_set_user_data (window
, widget
);
242 #if (MOZ_WIDGET_GTK == 2)
244 /* set the back pixmap to None so that you don't end up with the gtk
245 default which is BlackPixel */
246 gdk_window_set_back_pixmap (window
, NULL
, FALSE
);
250 g_object_ref (window
);
253 gtk_widget_set_window (widget
, window
);
255 #if (MOZ_WIDGET_GTK == 2)
256 widget
->style
= gtk_style_attach (widget
->style
, widget
->window
);
261 moz_container_size_allocate (GtkWidget
*widget
,
262 GtkAllocation
*allocation
)
264 MozContainer
*container
;
266 GtkAllocation tmp_allocation
;
267 GtkRequisition tmp_requisition
;
268 GtkWidget
*tmp_child
;
270 g_return_if_fail (IS_MOZ_CONTAINER (widget
));
272 /* printf("moz_container_size_allocate %p %d %d %d %d\n",
277 allocation->height); */
279 /* short circuit if you can */
280 container
= MOZ_CONTAINER (widget
);
281 gtk_widget_get_allocation(widget
, &tmp_allocation
);
282 if (!container
->children
&&
283 tmp_allocation
.x
== allocation
->x
&&
284 tmp_allocation
.y
== allocation
->y
&&
285 tmp_allocation
.width
== allocation
->width
&&
286 tmp_allocation
.height
== allocation
->height
) {
290 gtk_widget_set_allocation(widget
, allocation
);
292 tmp_list
= container
->children
;
295 MozContainerChild
*child
= tmp_list
->data
;
297 moz_container_allocate_child (container
, child
);
299 tmp_list
= tmp_list
->next
;
302 if (gtk_widget_get_has_window (widget
) &&
303 gtk_widget_get_realized (widget
)) {
305 gdk_window_move_resize(gtk_widget_get_window(widget
),
314 moz_container_remove (GtkContainer
*container
, GtkWidget
*child_widget
)
316 MozContainerChild
*child
;
317 MozContainer
*moz_container
;
318 GdkWindow
* parent_window
;
320 g_return_if_fail (IS_MOZ_CONTAINER(container
));
321 g_return_if_fail (GTK_IS_WIDGET(child_widget
));
323 moz_container
= MOZ_CONTAINER(container
);
325 child
= moz_container_get_child (moz_container
, child_widget
);
326 g_return_if_fail (child
);
328 /* gtk_widget_unparent will remove the parent window (as well as the
329 * parent widget), but, in Mozilla's window hierarchy, the parent window
330 * may need to be kept because it may be part of a GdkWindow sub-hierarchy
331 * that is being moved to another MozContainer.
333 * (In a conventional GtkWidget hierarchy, GdkWindows being reparented
334 * would have their own GtkWidget and that widget would be the one being
335 * reparented. In Mozilla's hierarchy, the parent_window needs to be
336 * retained so that the GdkWindow sub-hierarchy is maintained.)
338 parent_window
= gtk_widget_get_parent_window(child_widget
);
340 g_object_ref(parent_window
);
342 gtk_widget_unparent(child_widget
);
345 /* The child_widget will always still exist because g_signal_emit,
346 * which invokes this function, holds a reference.
348 * If parent_window is the container's root window then it will not be
349 * the parent_window if the child_widget is placed in another
352 if (parent_window
!= gtk_widget_get_window(GTK_WIDGET(container
)))
353 gtk_widget_set_parent_window(child_widget
, parent_window
);
355 g_object_unref(parent_window
);
358 moz_container
->children
= g_list_remove(moz_container
->children
, child
);
363 moz_container_forall (GtkContainer
*container
, gboolean include_internals
,
364 GtkCallback callback
, gpointer callback_data
)
366 MozContainer
*moz_container
;
369 g_return_if_fail (IS_MOZ_CONTAINER(container
));
370 g_return_if_fail (callback
!= NULL
);
372 moz_container
= MOZ_CONTAINER(container
);
374 tmp_list
= moz_container
->children
;
376 MozContainerChild
*child
;
377 child
= tmp_list
->data
;
378 tmp_list
= tmp_list
->next
;
379 (* callback
) (child
->widget
, callback_data
);
384 moz_container_allocate_child (MozContainer
*container
,
385 MozContainerChild
*child
)
387 GtkAllocation allocation
;
388 GtkRequisition requisition
;
390 gtk_widget_get_allocation (child
->widget
, &allocation
);
391 allocation
.x
= child
->x
;
392 allocation
.y
= child
->y
;
393 /* gtk_widget_get_child_requisition (child->widget, &requisition); */
394 /* gtk_widget_size_request (child->widget, &requisition); */
396 gtk_widget_size_allocate (child
->widget
, &allocation
);
400 moz_container_get_child (MozContainer
*container
, GtkWidget
*child_widget
)
404 tmp_list
= container
->children
;
406 MozContainerChild
*child
;
408 child
= tmp_list
->data
;
409 tmp_list
= tmp_list
->next
;
411 if (child
->widget
== child_widget
)
419 moz_container_add(GtkContainer
*container
, GtkWidget
*widget
)
421 moz_container_put(MOZ_CONTAINER(container
), widget
, 0, 0);