widget/gtk/mozcontainer.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
michael@0 2 /* vim:expandtab:shiftwidth=4:tabstop=4:
michael@0 3 */
michael@0 4 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7
michael@0 8 #include "mozcontainer.h"
michael@0 9 #include <gtk/gtk.h>
michael@0 10 #include <stdio.h>
michael@0 11
michael@0 12 #ifdef ACCESSIBILITY
michael@0 13 #include <atk/atk.h>
michael@0 14 #include "maiRedundantObjectFactory.h"
michael@0 15 #endif
michael@0 16
michael@0 17 /* init methods */
michael@0 18 static void moz_container_class_init (MozContainerClass *klass);
michael@0 19 static void moz_container_init (MozContainer *container);
michael@0 20
michael@0 21 /* widget class methods */
michael@0 22 static void moz_container_map (GtkWidget *widget);
michael@0 23 static void moz_container_unmap (GtkWidget *widget);
michael@0 24 static void moz_container_realize (GtkWidget *widget);
michael@0 25 static void moz_container_size_allocate (GtkWidget *widget,
michael@0 26 GtkAllocation *allocation);
michael@0 27
michael@0 28 /* container class methods */
michael@0 29 static void moz_container_remove (GtkContainer *container,
michael@0 30 GtkWidget *child_widget);
michael@0 31 static void moz_container_forall (GtkContainer *container,
michael@0 32 gboolean include_internals,
michael@0 33 GtkCallback callback,
michael@0 34 gpointer callback_data);
michael@0 35 static void moz_container_add (GtkContainer *container,
michael@0 36 GtkWidget *widget);
michael@0 37
michael@0 38 typedef struct _MozContainerChild MozContainerChild;
michael@0 39
michael@0 40 struct _MozContainerChild {
michael@0 41 GtkWidget *widget;
michael@0 42 gint x;
michael@0 43 gint y;
michael@0 44 };
michael@0 45
michael@0 46 static void moz_container_allocate_child (MozContainer *container,
michael@0 47 MozContainerChild *child);
michael@0 48 static MozContainerChild *
michael@0 49 moz_container_get_child (MozContainer *container, GtkWidget *child);
michael@0 50
michael@0 51 /* public methods */
michael@0 52
michael@0 53 GType
michael@0 54 moz_container_get_type(void)
michael@0 55 {
michael@0 56 static GType moz_container_type = 0;
michael@0 57
michael@0 58 if (!moz_container_type) {
michael@0 59 static GTypeInfo moz_container_info = {
michael@0 60 sizeof(MozContainerClass), /* class_size */
michael@0 61 NULL, /* base_init */
michael@0 62 NULL, /* base_finalize */
michael@0 63 (GClassInitFunc) moz_container_class_init, /* class_init */
michael@0 64 NULL, /* class_destroy */
michael@0 65 NULL, /* class_data */
michael@0 66 sizeof(MozContainer), /* instance_size */
michael@0 67 0, /* n_preallocs */
michael@0 68 (GInstanceInitFunc) moz_container_init, /* instance_init */
michael@0 69 NULL, /* value_table */
michael@0 70 };
michael@0 71
michael@0 72 moz_container_type = g_type_register_static (GTK_TYPE_CONTAINER,
michael@0 73 "MozContainer",
michael@0 74 &moz_container_info, 0);
michael@0 75 #ifdef ACCESSIBILITY
michael@0 76 /* Set a factory to return accessible object with ROLE_REDUNDANT for
michael@0 77 * MozContainer, so that gail won't send focus notification for it */
michael@0 78 atk_registry_set_factory_type(atk_get_default_registry(),
michael@0 79 moz_container_type,
michael@0 80 mai_redundant_object_factory_get_type());
michael@0 81 #endif
michael@0 82 }
michael@0 83
michael@0 84 return moz_container_type;
michael@0 85 }
michael@0 86
michael@0 87 GtkWidget *
michael@0 88 moz_container_new (void)
michael@0 89 {
michael@0 90 MozContainer *container;
michael@0 91
michael@0 92 container = g_object_new (MOZ_CONTAINER_TYPE, NULL);
michael@0 93
michael@0 94 return GTK_WIDGET(container);
michael@0 95 }
michael@0 96
michael@0 97 void
michael@0 98 moz_container_put (MozContainer *container, GtkWidget *child_widget,
michael@0 99 gint x, gint y)
michael@0 100 {
michael@0 101 MozContainerChild *child;
michael@0 102
michael@0 103 child = g_new (MozContainerChild, 1);
michael@0 104
michael@0 105 child->widget = child_widget;
michael@0 106 child->x = x;
michael@0 107 child->y = y;
michael@0 108
michael@0 109 /* printf("moz_container_put %p %p %d %d\n", (void *)container,
michael@0 110 (void *)child_widget, x, y); */
michael@0 111
michael@0 112 container->children = g_list_append (container->children, child);
michael@0 113
michael@0 114 /* we assume that the caller of this function will have already set
michael@0 115 the parent GdkWindow because we can have many anonymous children. */
michael@0 116 gtk_widget_set_parent(child_widget, GTK_WIDGET(container));
michael@0 117 }
michael@0 118
michael@0 119 void
michael@0 120 moz_container_move (MozContainer *container, GtkWidget *child_widget,
michael@0 121 gint x, gint y, gint width, gint height)
michael@0 122 {
michael@0 123 MozContainerChild *child;
michael@0 124 GtkAllocation new_allocation;
michael@0 125
michael@0 126 child = moz_container_get_child (container, child_widget);
michael@0 127
michael@0 128 child->x = x;
michael@0 129 child->y = y;
michael@0 130
michael@0 131 new_allocation.x = x;
michael@0 132 new_allocation.y = y;
michael@0 133 new_allocation.width = width;
michael@0 134 new_allocation.height = height;
michael@0 135
michael@0 136 /* printf("moz_container_move %p %p will allocate to %d %d %d %d\n",
michael@0 137 (void *)container, (void *)child_widget,
michael@0 138 new_allocation.x, new_allocation.y,
michael@0 139 new_allocation.width, new_allocation.height); */
michael@0 140
michael@0 141 gtk_widget_size_allocate(child_widget, &new_allocation);
michael@0 142 }
michael@0 143
michael@0 144 /* static methods */
michael@0 145
michael@0 146 void
michael@0 147 moz_container_class_init (MozContainerClass *klass)
michael@0 148 {
michael@0 149 /*GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
michael@0 150 GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass); */
michael@0 151 GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
michael@0 152 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
michael@0 153
michael@0 154 widget_class->map = moz_container_map;
michael@0 155 widget_class->unmap = moz_container_unmap;
michael@0 156 widget_class->realize = moz_container_realize;
michael@0 157 widget_class->size_allocate = moz_container_size_allocate;
michael@0 158
michael@0 159 container_class->remove = moz_container_remove;
michael@0 160 container_class->forall = moz_container_forall;
michael@0 161 container_class->add = moz_container_add;
michael@0 162 }
michael@0 163
michael@0 164 void
michael@0 165 moz_container_init (MozContainer *container)
michael@0 166 {
michael@0 167 gtk_widget_set_can_focus(GTK_WIDGET(container), TRUE);
michael@0 168 gtk_container_set_resize_mode(GTK_CONTAINER(container), GTK_RESIZE_IMMEDIATE);
michael@0 169 gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container), FALSE);
michael@0 170 }
michael@0 171
michael@0 172 void
michael@0 173 moz_container_map (GtkWidget *widget)
michael@0 174 {
michael@0 175 MozContainer *container;
michael@0 176 GList *tmp_list;
michael@0 177 GtkWidget *tmp_child;
michael@0 178
michael@0 179 g_return_if_fail (IS_MOZ_CONTAINER(widget));
michael@0 180 container = MOZ_CONTAINER (widget);
michael@0 181
michael@0 182 gtk_widget_set_mapped(widget, TRUE);
michael@0 183
michael@0 184 tmp_list = container->children;
michael@0 185 while (tmp_list) {
michael@0 186 tmp_child = ((MozContainerChild *)tmp_list->data)->widget;
michael@0 187
michael@0 188 if (gtk_widget_get_visible(tmp_child)) {
michael@0 189 if (!gtk_widget_get_mapped(tmp_child))
michael@0 190 gtk_widget_map(tmp_child);
michael@0 191 }
michael@0 192 tmp_list = tmp_list->next;
michael@0 193 }
michael@0 194
michael@0 195 if (gtk_widget_get_has_window (widget)) {
michael@0 196 gdk_window_show (gtk_widget_get_window(widget));
michael@0 197 }
michael@0 198 }
michael@0 199
michael@0 200 void
michael@0 201 moz_container_unmap (GtkWidget *widget)
michael@0 202 {
michael@0 203 g_return_if_fail (IS_MOZ_CONTAINER (widget));
michael@0 204
michael@0 205 gtk_widget_set_mapped(widget, FALSE);
michael@0 206
michael@0 207 if (gtk_widget_get_has_window (widget)) {
michael@0 208 gdk_window_hide (gtk_widget_get_window(widget));
michael@0 209 }
michael@0 210 }
michael@0 211
michael@0 212 void
michael@0 213 moz_container_realize (GtkWidget *widget)
michael@0 214 {
michael@0 215 GdkWindow *parent = gtk_widget_get_parent_window (widget);
michael@0 216 GdkWindow *window;
michael@0 217
michael@0 218 gtk_widget_set_realized(widget, TRUE);
michael@0 219
michael@0 220 if (gtk_widget_get_has_window (widget)) {
michael@0 221 GdkWindowAttr attributes;
michael@0 222 gint attributes_mask = GDK_WA_VISUAL | GDK_WA_X | GDK_WA_Y;
michael@0 223 GtkAllocation allocation;
michael@0 224
michael@0 225 gtk_widget_get_allocation (widget, &allocation);
michael@0 226 attributes.event_mask = gtk_widget_get_events (widget);
michael@0 227 attributes.x = allocation.x;
michael@0 228 attributes.y = allocation.y;
michael@0 229 attributes.width = allocation.width;
michael@0 230 attributes.height = allocation.height;
michael@0 231 attributes.wclass = GDK_INPUT_OUTPUT;
michael@0 232 attributes.visual = gtk_widget_get_visual (widget);
michael@0 233 attributes.window_type = GDK_WINDOW_CHILD;
michael@0 234
michael@0 235 #if (MOZ_WIDGET_GTK == 2)
michael@0 236 attributes.colormap = gtk_widget_get_colormap (widget);
michael@0 237 attributes_mask |= GDK_WA_COLORMAP;
michael@0 238 #endif
michael@0 239
michael@0 240 window = gdk_window_new (parent, &attributes, attributes_mask);
michael@0 241 gdk_window_set_user_data (window, widget);
michael@0 242 #if (MOZ_WIDGET_GTK == 2)
michael@0 243 /* TODO GTK3? */
michael@0 244 /* set the back pixmap to None so that you don't end up with the gtk
michael@0 245 default which is BlackPixel */
michael@0 246 gdk_window_set_back_pixmap (window, NULL, FALSE);
michael@0 247 #endif
michael@0 248 } else {
michael@0 249 window = parent;
michael@0 250 g_object_ref (window);
michael@0 251 }
michael@0 252
michael@0 253 gtk_widget_set_window (widget, window);
michael@0 254
michael@0 255 #if (MOZ_WIDGET_GTK == 2)
michael@0 256 widget->style = gtk_style_attach (widget->style, widget->window);
michael@0 257 #endif
michael@0 258 }
michael@0 259
michael@0 260 void
michael@0 261 moz_container_size_allocate (GtkWidget *widget,
michael@0 262 GtkAllocation *allocation)
michael@0 263 {
michael@0 264 MozContainer *container;
michael@0 265 GList *tmp_list;
michael@0 266 GtkAllocation tmp_allocation;
michael@0 267 GtkRequisition tmp_requisition;
michael@0 268 GtkWidget *tmp_child;
michael@0 269
michael@0 270 g_return_if_fail (IS_MOZ_CONTAINER (widget));
michael@0 271
michael@0 272 /* printf("moz_container_size_allocate %p %d %d %d %d\n",
michael@0 273 (void *)widget,
michael@0 274 allocation->x,
michael@0 275 allocation->y,
michael@0 276 allocation->width,
michael@0 277 allocation->height); */
michael@0 278
michael@0 279 /* short circuit if you can */
michael@0 280 container = MOZ_CONTAINER (widget);
michael@0 281 gtk_widget_get_allocation(widget, &tmp_allocation);
michael@0 282 if (!container->children &&
michael@0 283 tmp_allocation.x == allocation->x &&
michael@0 284 tmp_allocation.y == allocation->y &&
michael@0 285 tmp_allocation.width == allocation->width &&
michael@0 286 tmp_allocation.height == allocation->height) {
michael@0 287 return;
michael@0 288 }
michael@0 289
michael@0 290 gtk_widget_set_allocation(widget, allocation);
michael@0 291
michael@0 292 tmp_list = container->children;
michael@0 293
michael@0 294 while (tmp_list) {
michael@0 295 MozContainerChild *child = tmp_list->data;
michael@0 296
michael@0 297 moz_container_allocate_child (container, child);
michael@0 298
michael@0 299 tmp_list = tmp_list->next;
michael@0 300 }
michael@0 301
michael@0 302 if (gtk_widget_get_has_window (widget) &&
michael@0 303 gtk_widget_get_realized (widget)) {
michael@0 304
michael@0 305 gdk_window_move_resize(gtk_widget_get_window(widget),
michael@0 306 allocation->x,
michael@0 307 allocation->y,
michael@0 308 allocation->width,
michael@0 309 allocation->height);
michael@0 310 }
michael@0 311 }
michael@0 312
michael@0 313 void
michael@0 314 moz_container_remove (GtkContainer *container, GtkWidget *child_widget)
michael@0 315 {
michael@0 316 MozContainerChild *child;
michael@0 317 MozContainer *moz_container;
michael@0 318 GdkWindow* parent_window;
michael@0 319
michael@0 320 g_return_if_fail (IS_MOZ_CONTAINER(container));
michael@0 321 g_return_if_fail (GTK_IS_WIDGET(child_widget));
michael@0 322
michael@0 323 moz_container = MOZ_CONTAINER(container);
michael@0 324
michael@0 325 child = moz_container_get_child (moz_container, child_widget);
michael@0 326 g_return_if_fail (child);
michael@0 327
michael@0 328 /* gtk_widget_unparent will remove the parent window (as well as the
michael@0 329 * parent widget), but, in Mozilla's window hierarchy, the parent window
michael@0 330 * may need to be kept because it may be part of a GdkWindow sub-hierarchy
michael@0 331 * that is being moved to another MozContainer.
michael@0 332 *
michael@0 333 * (In a conventional GtkWidget hierarchy, GdkWindows being reparented
michael@0 334 * would have their own GtkWidget and that widget would be the one being
michael@0 335 * reparented. In Mozilla's hierarchy, the parent_window needs to be
michael@0 336 * retained so that the GdkWindow sub-hierarchy is maintained.)
michael@0 337 */
michael@0 338 parent_window = gtk_widget_get_parent_window(child_widget);
michael@0 339 if (parent_window)
michael@0 340 g_object_ref(parent_window);
michael@0 341
michael@0 342 gtk_widget_unparent(child_widget);
michael@0 343
michael@0 344 if (parent_window) {
michael@0 345 /* The child_widget will always still exist because g_signal_emit,
michael@0 346 * which invokes this function, holds a reference.
michael@0 347 *
michael@0 348 * If parent_window is the container's root window then it will not be
michael@0 349 * the parent_window if the child_widget is placed in another
michael@0 350 * container.
michael@0 351 */
michael@0 352 if (parent_window != gtk_widget_get_window(GTK_WIDGET(container)))
michael@0 353 gtk_widget_set_parent_window(child_widget, parent_window);
michael@0 354
michael@0 355 g_object_unref(parent_window);
michael@0 356 }
michael@0 357
michael@0 358 moz_container->children = g_list_remove(moz_container->children, child);
michael@0 359 g_free(child);
michael@0 360 }
michael@0 361
michael@0 362 void
michael@0 363 moz_container_forall (GtkContainer *container, gboolean include_internals,
michael@0 364 GtkCallback callback, gpointer callback_data)
michael@0 365 {
michael@0 366 MozContainer *moz_container;
michael@0 367 GList *tmp_list;
michael@0 368
michael@0 369 g_return_if_fail (IS_MOZ_CONTAINER(container));
michael@0 370 g_return_if_fail (callback != NULL);
michael@0 371
michael@0 372 moz_container = MOZ_CONTAINER(container);
michael@0 373
michael@0 374 tmp_list = moz_container->children;
michael@0 375 while (tmp_list) {
michael@0 376 MozContainerChild *child;
michael@0 377 child = tmp_list->data;
michael@0 378 tmp_list = tmp_list->next;
michael@0 379 (* callback) (child->widget, callback_data);
michael@0 380 }
michael@0 381 }
michael@0 382
michael@0 383 static void
michael@0 384 moz_container_allocate_child (MozContainer *container,
michael@0 385 MozContainerChild *child)
michael@0 386 {
michael@0 387 GtkAllocation allocation;
michael@0 388 GtkRequisition requisition;
michael@0 389
michael@0 390 gtk_widget_get_allocation (child->widget, &allocation);
michael@0 391 allocation.x = child->x;
michael@0 392 allocation.y = child->y;
michael@0 393 /* gtk_widget_get_child_requisition (child->widget, &requisition); */
michael@0 394 /* gtk_widget_size_request (child->widget, &requisition); */
michael@0 395
michael@0 396 gtk_widget_size_allocate (child->widget, &allocation);
michael@0 397 }
michael@0 398
michael@0 399 MozContainerChild *
michael@0 400 moz_container_get_child (MozContainer *container, GtkWidget *child_widget)
michael@0 401 {
michael@0 402 GList *tmp_list;
michael@0 403
michael@0 404 tmp_list = container->children;
michael@0 405 while (tmp_list) {
michael@0 406 MozContainerChild *child;
michael@0 407
michael@0 408 child = tmp_list->data;
michael@0 409 tmp_list = tmp_list->next;
michael@0 410
michael@0 411 if (child->widget == child_widget)
michael@0 412 return child;
michael@0 413 }
michael@0 414
michael@0 415 return NULL;
michael@0 416 }
michael@0 417
michael@0 418 static void
michael@0 419 moz_container_add(GtkContainer *container, GtkWidget *widget)
michael@0 420 {
michael@0 421 moz_container_put(MOZ_CONTAINER(container), widget, 0, 0);
michael@0 422 }
michael@0 423

mercurial