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

     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/. */
     8 #include "mozcontainer.h"
     9 #include <gtk/gtk.h>
    10 #include <stdio.h>
    12 #ifdef ACCESSIBILITY
    13 #include <atk/atk.h>
    14 #include "maiRedundantObjectFactory.h"
    15 #endif 
    17 /* init methods */
    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,
    33                                        GtkCallback        callback,
    34                                        gpointer           callback_data);
    35 static void moz_container_add         (GtkContainer      *container,
    36                                         GtkWidget        *widget);
    38 typedef struct _MozContainerChild MozContainerChild;
    40 struct _MozContainerChild {
    41     GtkWidget *widget;
    42     gint x;
    43     gint y;
    44 };
    46 static void moz_container_allocate_child (MozContainer      *container,
    47                                           MozContainerChild *child);
    48 static MozContainerChild *
    49 moz_container_get_child (MozContainer *container, GtkWidget *child);
    51 /* public methods */
    53 GType
    54 moz_container_get_type(void)
    55 {
    56     static GType moz_container_type = 0;
    58     if (!moz_container_type) {
    59         static GTypeInfo moz_container_info = {
    60             sizeof(MozContainerClass), /* class_size */
    61             NULL, /* base_init */
    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 */
    67             0, /* n_preallocs */
    68             (GInstanceInitFunc) moz_container_init, /* instance_init */
    69             NULL, /* value_table */
    70         };
    72         moz_container_type = g_type_register_static (GTK_TYPE_CONTAINER,
    73                                                      "MozContainer",
    74                                                      &moz_container_info, 0);
    75 #ifdef ACCESSIBILITY
    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(),
    79                                       moz_container_type,
    80                                       mai_redundant_object_factory_get_type());
    81 #endif
    82     }
    84     return moz_container_type;
    85 }
    87 GtkWidget *
    88 moz_container_new (void)
    89 {
    90     MozContainer *container;
    92     container = g_object_new (MOZ_CONTAINER_TYPE, NULL);
    94     return GTK_WIDGET(container);
    95 }
    97 void
    98 moz_container_put (MozContainer *container, GtkWidget *child_widget,
    99                    gint x, gint y)
   100 {
   101     MozContainerChild *child;
   103     child = g_new (MozContainerChild, 1);
   105     child->widget = child_widget;
   106     child->x = x;
   107     child->y = y;
   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));
   117 }
   119 void
   120 moz_container_move (MozContainer *container, GtkWidget *child_widget,
   121                     gint x, gint y, gint width, gint height)
   122 {
   123     MozContainerChild *child;
   124     GtkAllocation new_allocation;
   126     child = moz_container_get_child (container, child_widget);
   128     child->x = x;
   129     child->y = y;
   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);
   142 }
   144 /* static methods */
   146 void
   147 moz_container_class_init (MozContainerClass *klass)
   148 {
   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;
   162 }
   164 void
   165 moz_container_init (MozContainer *container)
   166 {
   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);
   170 }
   172 void
   173 moz_container_map (GtkWidget *widget)
   174 {
   175     MozContainer *container;
   176     GList *tmp_list;
   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;
   185     while (tmp_list) {
   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);
   191         }
   192         tmp_list = tmp_list->next;
   193     }
   195     if (gtk_widget_get_has_window (widget)) {
   196         gdk_window_show (gtk_widget_get_window(widget));
   197     }
   198 }
   200 void
   201 moz_container_unmap (GtkWidget *widget)
   202 {
   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));
   209     }
   210 }
   212 void
   213 moz_container_realize (GtkWidget *widget)
   214 {
   215     GdkWindow *parent = gtk_widget_get_parent_window (widget);
   216     GdkWindow *window;
   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;
   238 #endif
   240         window = gdk_window_new (parent, &attributes, attributes_mask);
   241         gdk_window_set_user_data (window, widget);
   242 #if (MOZ_WIDGET_GTK == 2)
   243         /* TODO GTK3? */
   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);
   247 #endif
   248     } else {
   249         window = parent;
   250         g_object_ref (window);
   251     }
   253     gtk_widget_set_window (widget, window);
   255 #if (MOZ_WIDGET_GTK == 2)
   256     widget->style = gtk_style_attach (widget->style, widget->window);
   257 #endif
   258 }
   260 void
   261 moz_container_size_allocate (GtkWidget     *widget,
   262                              GtkAllocation *allocation)
   263 {
   264     MozContainer   *container;
   265     GList          *tmp_list;
   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",
   273         (void *)widget,
   274         allocation->x,
   275         allocation->y,
   276         allocation->width,
   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) {
   287         return;
   288     }
   290     gtk_widget_set_allocation(widget, allocation);
   292     tmp_list = container->children;
   294     while (tmp_list) {
   295         MozContainerChild *child = tmp_list->data;
   297         moz_container_allocate_child (container, child);
   299         tmp_list = tmp_list->next;
   300     }
   302     if (gtk_widget_get_has_window (widget) &&
   303         gtk_widget_get_realized (widget)) {
   305         gdk_window_move_resize(gtk_widget_get_window(widget),
   306                                allocation->x,
   307                                allocation->y,
   308                                allocation->width,
   309                                allocation->height);
   310     }
   311 }
   313 void
   314 moz_container_remove (GtkContainer *container, GtkWidget *child_widget)
   315 {
   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.
   332      *
   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.)
   337      */
   338     parent_window = gtk_widget_get_parent_window(child_widget);
   339     if (parent_window)
   340         g_object_ref(parent_window);
   342     gtk_widget_unparent(child_widget);
   344     if (parent_window) {
   345         /* The child_widget will always still exist because g_signal_emit,
   346          * which invokes this function, holds a reference.
   347          *
   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
   350          * container.
   351          */
   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);
   356     }
   358     moz_container->children = g_list_remove(moz_container->children, child);
   359     g_free(child);
   360 }
   362 void
   363 moz_container_forall (GtkContainer *container, gboolean include_internals,
   364                       GtkCallback  callback, gpointer callback_data)
   365 {
   366     MozContainer *moz_container;
   367     GList *tmp_list;
   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;
   375     while (tmp_list) {
   376         MozContainerChild *child;
   377         child = tmp_list->data;
   378         tmp_list = tmp_list->next;
   379         (* callback) (child->widget, callback_data);
   380     }
   381 }
   383 static void
   384 moz_container_allocate_child (MozContainer *container,
   385                               MozContainerChild *child)
   386 {
   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);
   397 }
   399 MozContainerChild *
   400 moz_container_get_child (MozContainer *container, GtkWidget *child_widget)
   401 {
   402     GList *tmp_list;
   404     tmp_list = container->children;
   405     while (tmp_list) {
   406         MozContainerChild *child;
   408         child = tmp_list->data;
   409         tmp_list = tmp_list->next;
   411         if (child->widget == child_widget)
   412             return child;
   413     }
   415     return NULL;
   416 }
   418 static void 
   419 moz_container_add(GtkContainer *container, GtkWidget *widget)
   420 {
   421     moz_container_put(MOZ_CONTAINER(container), widget, 0, 0);
   422 }

mercurial