gtkwidget.c 525 KB
Newer Older
Cody Russell's avatar
Cody Russell committed
1
/* GTK - The GIMP Toolkit
Elliot Lee's avatar
Elliot Lee committed
2 3 4
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
 *
 * This library is free software; you can redistribute it and/or
5
 * modify it under the terms of the GNU Lesser General Public
Elliot Lee's avatar
Elliot Lee committed
6 7 8 9 10
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
12
 * Lesser General Public License for more details.
Elliot Lee's avatar
Elliot Lee committed
13
 *
14
 * You should have received a copy of the GNU Lesser General Public
Javier Jardón's avatar
Javier Jardón committed
15
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
Elliot Lee's avatar
Elliot Lee committed
16
 */
17 18

/*
19
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
20 21
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 * files for a list of changes.  These files are distributed with
22
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
23 24
 */

25
#include "config.h"
26

Elliot Lee's avatar
Elliot Lee committed
27 28
#include <stdarg.h>
#include <string.h>
29
#include <locale.h>
30
#include <math.h>
31 32 33 34 35

#include <gobject/gvaluecollector.h>
#include <gobject/gobjectnotifyqueue.c>
#include <cairo-gobject.h>

Elliot Lee's avatar
Elliot Lee committed
36
#include "gtkcontainer.h"
37
#include "gtkaccelmapprivate.h"
Matthias Clasen's avatar
Matthias Clasen committed
38
#include "gtkaccelgroupprivate.h"
39
#include "gtkclipboard.h"
40
#include "gtkcssstylepropertyprivate.h"
Alexander Larsson's avatar
Alexander Larsson committed
41
#include "gtkcssnumbervalueprivate.h"
42
#include "gtkcssshadowsvalueprivate.h"
43
#include "gtkintl.h"
44
#include "gtkmarshalers.h"
45
#include "gtkselectionprivate.h"
46
#include "gtksettingsprivate.h"
47
#include "gtksizegroup-private.h"
48
#include "gtksizerequestcacheprivate.h"
Elliot Lee's avatar
Elliot Lee committed
49
#include "gtkwidget.h"
Emmanuele Bassi's avatar
Emmanuele Bassi committed
50
#include "gtkwidgetprivate.h"
51
#include "gtkwindowprivate.h"
52
#include "gtkcontainerprivate.h"
Tim Janik's avatar
Tim Janik committed
53
#include "gtkbindings.h"
54
#include "gtkprivate.h"
55
#include "gtkaccessible.h"
56
#include "gtktooltipprivate.h"
57
#include "gtkinvisible.h"
Johan Dahlin's avatar
Johan Dahlin committed
58
#include "gtkbuildable.h"
59
#include "gtkbuilderprivate.h"
60
#include "gtksizerequest.h"
61
#include "gtkstylecontextprivate.h"
62
#include "gtkcssprovider.h"
63
#include "gtkmodifierstyle.h"
64
#include "gtkversion.h"
65
#include "gtkdebug.h"
66
#include "gtkplug.h"
67
#include "gtktypebuiltins.h"
68
#include "a11y/gtkwidgetaccessible.h"
69
#include "gtkapplicationprivate.h"
70
#include "gtkgestureprivate.h"
Elliot Lee's avatar
Elliot Lee committed
71

72 73 74
/* for the use of round() */
#include "fallback-c89.c"

75 76 77 78 79 80 81
/**
 * SECTION:gtkwidget
 * @Short_description: Base class for all widgets
 * @Title: GtkWidget
 *
 * GtkWidget is the base class all widgets in GTK+ derive from. It manages the
 * widget lifecycle, states and style.
82
 *
83
 * # Height-for-width Geometry Management # {#geometry-management}
Matthias Clasen's avatar
Matthias Clasen committed
84
 *
85
 * GTK+ uses a height-for-width (and width-for-height) geometry management
86
 * system. Height-for-width means that a widget can change how much
87 88 89
 * vertical space it needs, depending on the amount of horizontal space
 * that it is given (and similar for width-for-height). The most common
 * example is a label that reflows to fill up the available width, wraps
90
 * to fewer lines, and therefore needs less height.
91
 *
92
 * Height-for-width geometry management is implemented in GTK+ by way
93
 * of five virtual methods:
94
 *
Matthias Clasen's avatar
Matthias Clasen committed
95 96 97 98 99 100
 * - #GtkWidgetClass.get_request_mode()
 * - #GtkWidgetClass.get_preferred_width()
 * - #GtkWidgetClass.get_preferred_height()
 * - #GtkWidgetClass.get_preferred_height_for_width()
 * - #GtkWidgetClass.get_preferred_width_for_height()
 * - #GtkWidgetClass.get_preferred_height_and_baseline_for_width()
101 102 103 104 105
 *
 * There are some important things to keep in mind when implementing
 * height-for-width and when using it in container implementations.
 *
 * The geometry management system will query a widget hierarchy in
106
 * only one orientation at a time. When widgets are initially queried
107 108 109
 * for their minimum sizes it is generally done in two initial passes
 * in the #GtkSizeRequestMode chosen by the toplevel.
 *
110
 * For example, when queried in the normal
111 112
 * %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH mode:
 * First, the default minimum and natural width for each widget
113
 * in the interface will be computed using gtk_widget_get_preferred_width().
114 115
 * Because the preferred widths for each container depend on the preferred
 * widths of their children, this information propagates up the hierarchy,
116
 * and finally a minimum and natural width is determined for the entire
117 118 119 120 121
 * toplevel. Next, the toplevel will use the minimum width to query for the
 * minimum height contextual to that width using
 * gtk_widget_get_preferred_height_for_width(), which will also be a highly
 * recursive operation. The minimum height for the minimum width is normally
 * used to set the minimum size constraint on the toplevel
122 123
 * (unless gtk_window_set_geometry_hints() is explicitly used instead).
 *
124
 * After the toplevel window has initially requested its size in both
125 126
 * dimensions it can go on to allocate itself a reasonable size (or a size
 * previously specified with gtk_window_set_default_size()). During the
127
 * recursive allocation process it’s important to note that request cycles
128
 * will be recursively executed while container widgets allocate their children.
129
 * Each container widget, once allocated a size, will go on to first share the
130
 * space in one orientation among its children and then request each child's
131
 * height for its target allocated width or its width for allocated height,
132
 * depending. In this way a #GtkWidget will typically be requested its size
133 134 135
 * a number of times before actually being allocated a size. The size a
 * widget is finally allocated can of course differ from the size it has
 * requested. For this reason, #GtkWidget caches a  small number of results
136 137
 * to avoid re-querying for the same sizes in one allocation cycle.
 *
138
 * See
139
 * [GtkContainer’s geometry management section][container-geometry-management]
140
 * to learn more about how height-for-width allocations are performed
141
 * by container widgets.
142
 *
143 144
 * If a widget does move content around to intelligently use up the
 * allocated size then it must support the request in both
145
 * #GtkSizeRequestModes even if the widget in question only
146
 * trades sizes in a single orientation.
147
 *
148
 * For instance, a #GtkLabel that does height-for-width word wrapping
149 150
 * will not expect to have #GtkWidgetClass.get_preferred_height() called
 * because that call is specific to a width-for-height request. In this
151
 * case the label must return the height required for its own minimum
152 153
 * possible width. By following this rule any widget that handles
 * height-for-width or width-for-height requests will always be allocated
154 155 156 157 158
 * at least enough space to fit its own content.
 *
 * Here are some examples of how a %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH widget
 * generally deals with width-for-height requests, for #GtkWidgetClass.get_preferred_height()
 * it will do:
159
 *
160
 * |[<!-- language="C" -->
161
 * static void
162 163 164
 * foo_widget_get_preferred_height (GtkWidget *widget,
 *                                  gint *min_height,
 *                                  gint *nat_height)
165 166 167
 * {
 *    if (i_am_in_height_for_width_mode)
 *      {
Matthias Clasen's avatar
Matthias Clasen committed
168
 *        gint min_width, nat_width;
169
 *
170 171
 *        GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget,
 *                                                            &min_width,
Matthias Clasen's avatar
Matthias Clasen committed
172
 *                                                            &nat_width);
173 174 175 176 177
 *        GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width
 *                                                           (widget,
 *                                                            min_width,
 *                                                            min_height,
 *                                                            nat_height);
178 179 180
 *      }
 *    else
 *      {
181 182 183
 *         ... some widgets do both. For instance, if a GtkLabel is
 *         rotated to 90 degrees it will return the minimum and
 *         natural height for the rotated label here.
184 185
 *      }
 * }
186
 * ]|
187
 *
188 189
 * And in #GtkWidgetClass.get_preferred_width_for_height() it will simply return
 * the minimum and natural width:
190
 * |[<!-- language="C" -->
191
 * static void
192 193 194 195
 * foo_widget_get_preferred_width_for_height (GtkWidget *widget,
 *                                            gint for_height,
 *                                            gint *min_width,
 *                                            gint *nat_width)
196 197 198
 * {
 *    if (i_am_in_height_for_width_mode)
 *      {
199 200 201
 *        GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget,
 *                                                            min_width,
 *                                                            nat_width);
202 203 204
 *      }
 *    else
 *      {
205 206 207
 *         ... again if a widget is sometimes operating in
 *         width-for-height mode (like a rotated GtkLabel) it can go
 *         ahead and do its real width for height calculation here.
208 209
 *      }
 * }
210
 * ]|
211 212
 *
 * Often a widget needs to get its own request during size request or
213 214
 * allocation. For example, when computing height it may need to also
 * compute width. Or when deciding how to use an allocation, the widget
215
 * may need to know its natural size. In these cases, the widget should
216
 * be careful to call its virtual methods directly, like this:
217
 *
Matthias Clasen's avatar
Matthias Clasen committed
218
 * |[<!-- language="C" -->
219 220 221
 * GTK_WIDGET_GET_CLASS(widget)->get_preferred_width (widget,
 *                                                    &min,
 *                                                    &natural);
Matthias Clasen's avatar
Matthias Clasen committed
222
 * ]|
223 224
 *
 * It will not work to use the wrapper functions, such as
225
 * gtk_widget_get_preferred_width() inside your own size request
226
 * implementation. These return a request adjusted by #GtkSizeGroup
227
 * and by the #GtkWidgetClass.adjust_size_request() virtual method. If a
228 229 230 231 232 233
 * widget used the wrappers inside its virtual method implementations,
 * then the adjustments (such as widget margins) would be applied
 * twice. GTK+ therefore does not allow this and will warn if you try
 * to do it.
 *
 * Of course if you are getting the size request for
234 235
 * another widget, such as a child of a
 * container, you must use the wrapper APIs.
236
 * Otherwise, you would not properly consider widget margins,
237
 * #GtkSizeGroup, and so forth.
238 239 240 241 242
 *
 * Since 3.10 Gtk+ also supports baseline vertical alignment of widgets. This
 * means that widgets are positioned such that the typographical baseline of
 * widgets in the same row are aligned. This happens if a widget supports baselines,
 * has a vertical alignment of %GTK_ALIGN_BASELINE, and is inside a container
William Jon McCann's avatar
William Jon McCann committed
243
 * that supports baselines and has a natural “row” that it aligns to the baseline,
244 245 246 247 248 249 250
 * or a baseline assigned to it by the grandparent.
 *
 * Baseline alignment support for a widget is done by the #GtkWidgetClass.get_preferred_height_and_baseline_for_width()
 * virtual function. It allows you to report a baseline in combination with the
 * minimum and natural height. If there is no baseline you can return -1 to indicate
 * this. The default implementation of this virtual function calls into the
 * #GtkWidgetClass.get_preferred_height() and #GtkWidgetClass.get_preferred_height_for_width(),
251
 * so if baselines are not supported it doesn’t need to be implemented.
252 253 254 255 256 257
 *
 * If a widget ends up baseline aligned it will be allocated all the space in the parent
 * as if it was %GTK_ALIGN_FILL, but the selected baseline can be found via gtk_widget_get_allocated_baseline().
 * If this has a value other than -1 you need to align the widget such that the baseline
 * appears at the position.
 *
258
 * # Style Properties
Matthias Clasen's avatar
Matthias Clasen committed
259
 *
260 261
 * #GtkWidget introduces “style
 * properties” - these are basically object properties that are stored
262
 * not on the object, but in the style object associated to the widget. Style
263
 * properties are set in [resource files][gtk3-Resource-Files].
264 265 266
 * This mechanism is used for configuring such things as the location of the
 * scrollbar arrows through the theme, giving theme authors more control over the
 * look of applications without the need to write a theme engine in C.
Matthias Clasen's avatar
Matthias Clasen committed
267
 *
268 269 270 271 272
 * Use gtk_widget_class_install_style_property() to install style properties for
 * a widget class, gtk_widget_class_find_style_property() or
 * gtk_widget_class_list_style_properties() to get information about existing
 * style properties and gtk_widget_style_get_property(), gtk_widget_style_get() or
 * gtk_widget_style_get_valist() to obtain the value of a style property.
Matthias Clasen's avatar
Matthias Clasen committed
273
 *
274
 * # GtkWidget as GtkBuildable
Matthias Clasen's avatar
Matthias Clasen committed
275
 *
276
 * The GtkWidget implementation of the GtkBuildable interface supports a
277 278
 * custom <accelerator> element, which has attributes named ”key”, ”modifiers”
 * and ”signal” and allows to specify accelerators.
Matthias Clasen's avatar
Matthias Clasen committed
279 280
 *
 * An example of a UI definition fragment specifying an accelerator:
281
 * |[
282 283 284
 * <object class="GtkButton">
 *   <accelerator key="q" modifiers="GDK_CONTROL_MASK" signal="clicked"/>
 * </object>
285
 * ]|
Matthias Clasen's avatar
Matthias Clasen committed
286
 *
287 288 289 290
 * In addition to accelerators, GtkWidget also support a custom <accessible>
 * element, which supports actions and relations. Properties on the accessible
 * implementation of an object can be set by accessing the internal child
 * “accessible” of a #GtkWidget.
Matthias Clasen's avatar
Matthias Clasen committed
291 292
 *
 * An example of a UI definition fragment specifying an accessible:
293
 * |[
294 295 296 297 298 299 300 301 302 303
 * <object class="GtkButton" id="label1"/>
 *   <property name="label">I am a Label for a Button</property>
 * </object>
 * <object class="GtkButton" id="button1">
 *   <accessibility>
 *     <action action_name="click" translatable="yes">Click the button.</action>
 *     <relation target="label1" type="labelled-by"/>
 *   </accessibility>
 *   <child internal-child="accessible">
 *     <object class="AtkObject" id="a11y-button1">
304
 *       <property name="accessible-name">Clickable Button</property>
305 306 307
 *     </object>
 *   </child>
 * </object>
308
 * ]|
Matthias Clasen's avatar
Matthias Clasen committed
309
 *
310
 * Finally, GtkWidget allows style information such as style classes to
311
 * be associated with widgets, using the custom <style> element:
312
 * |[
313 314 315 316 317 318
 * <object class="GtkButton" id="button1">
 *   <style>
 *     <class name="my-special-button-class"/>
 *     <class name="dark-button"/>
 *   </style>
 * </object>
319
 * ]|
Matthias Clasen's avatar
Matthias Clasen committed
320
 *
321
 * # Building composite widgets from template XML
Matthias Clasen's avatar
Matthias Clasen committed
322
 *
323 324 325
 * GtkWidget exposes some facilities to automate the proceedure
 * of creating composite widgets using #GtkBuilder interface description
 * language.
Matthias Clasen's avatar
Matthias Clasen committed
326
 *
327 328 329
 * To create composite widgets with #GtkBuilder XML, one must associate
 * the interface description with the widget class at class initialization
 * time using gtk_widget_class_set_template().
Matthias Clasen's avatar
Matthias Clasen committed
330
 *
331 332
 * The interface description semantics expected in composite template descriptions
 * is slightly different from regulare #GtkBuilder XML.
Matthias Clasen's avatar
Matthias Clasen committed
333
 *
334 335 336 337 338 339
 * Unlike regular interface descriptions, gtk_widget_class_set_template() will
 * expect a <template> tag as a direct child of the toplevel <interface>
 * tag. The <template> tag must specify the “class” attribute which must be
 * the type name of the widget. Optionally, the “parent” attribute may be
 * specified to specify the direct parent type of the widget type, this is
 * ignored by the GtkBuilder but required for Glade to introspect what kind
340 341
 * of properties and internal children exist for a given type when the actual
 * type does not exist.
Matthias Clasen's avatar
Matthias Clasen committed
342
 *
343 344 345 346 347
 * The XML which is contained inside the <template> tag behaves as if it were
 * added to the <object> tag defining @widget itself. You may set properties
 * on @widget by inserting <property> tags into the <template> tag, and also
 * add <child> tags to add children and extend @widget in the normal way you
 * would with <object> tags.
Matthias Clasen's avatar
Matthias Clasen committed
348
 *
349 350 351 352
 * Additionally, <object> tags can also be added before and after the initial
 * <template> tag in the normal way, allowing one to define auxilary objects
 * which might be referenced by other widgets declared as children of the
 * <template> tag.
Matthias Clasen's avatar
Matthias Clasen committed
353 354
 *
 * An example of a GtkBuilder Template Definition:
355
 * |[
356 357 358 359 360 361 362
 * <interface>
 *   <template class="FooWidget" parent="GtkBox">
 *     <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
 *     <property name="spacing">4</property>
 *     <child>
 *       <object class="GtkButton" id="hello_button">
 *         <property name="label">Hello World</property>
363
 *         <signal name="clicked" handler="hello_button_clicked" object="FooWidget" swapped="yes"/>
364 365 366 367 368 369 370 371 372
 *       </object>
 *     </child>
 *     <child>
 *       <object class="GtkButton" id="goodbye_button">
 *         <property name="label">Goodbye World</property>
 *       </object>
 *     </child>
 *   </template>
 * </interface>
373
 * ]|
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
 *
 * Typically, you'll place the template fragment into a file that is
 * bundled with your project, using #GResource. In order to load the
 * template, you need to call gtk_widget_class_set_template_from_resource()
 * from the class initialization of your #GtkWidget type:
 *
 * |[<!-- language="C" -->
 * static void
 * foo_widget_class_init (FooWidgetClass *klass)
 * {
 *   // ...
 *
 *   gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
 *                                                "/com/example/ui/foowidget.ui");
 * }
 * ]|
 *
 * You will also need to call gtk_widget_init_template() from the instance
 * initialization function:
 *
 * |[<!-- language="C" -->
 * static void
 * foo_widget_init (FooWidget *self)
 * {
 *   // ...
 *   gtk_widget_init_template (GTK_WIDGET (self));
 * }
 * ]|
 *
 * You can access widgets defined in the template using the
 * gtk_widget_get_template_child() function, but you will typically declare
 * a pointer in the instance private data structure of your type using the same
 * name as the widget in the template definition, and call
 * gtk_widget_class_bind_template_child_private() with that name, e.g.
 *
 * |[<!-- language="C" -->
 * typedef struct {
 *   GtkWidget *hello_button;
 *   GtkWidget *goodbye_button;
 * } FooWidgetPrivate;
 *
 * G_DEFINE_TYPE_WITH_PRIVATE (FooWidget, foo_widget, GTK_TYPE_BOX)
 *
 * static void
 * foo_widget_class_init (FooWidgetClass *klass)
 * {
 *   // ...
 *   gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
 *                                                "/com/example/ui/foowidget.ui");
 *   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass),
 *                                                 FooWidget, hello_button);
 *   gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass),
 *                                                 FooWidget, goodbye_button);
 * }
 * ]|
 *
 * You can also use gtk_widget_class_bind_template_callback() to connect a signal
 * callback defined in the template with a function visible in the scope of the
 * class, e.g.
 *
 * |[<!-- language="C" -->
 * // the signal handler has the instance and user data swapped
 * // because of the swapped="yes" attribute in the template XML
 * static void
 * hello_button_clicked (FooWidget *self,
 *                       GtkButton *button)
 * {
 *   g_print ("Hello, world!\n");
 * }
 *
 * static void
 * foo_widget_class_init (FooWidgetClass *klass)
 * {
 *   // ...
 *   gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
 *                                                "/com/example/ui/foowidget.ui");
 *   gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), hello_button_clicked);
 * }
 * ]|
453 454
 */

455
#define GTK_STATE_FLAGS_DO_PROPAGATE (GTK_STATE_FLAG_INSENSITIVE|GTK_STATE_FLAG_BACKDROP)
456

457
#define WIDGET_CLASS(w)	 GTK_WIDGET_GET_CLASS (w)
Elliot Lee's avatar
Elliot Lee committed
458

459
#define GTK_STATE_FLAGS_BITS 12
460

461 462 463
typedef struct {
  gchar               *name;           /* Name of the template automatic child */
  gboolean             internal_child; /* Whether the automatic widget should be exported as an <internal-child> */
464
  gssize               offset;         /* Instance private data offset where to set the automatic child (or 0) */
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
} AutomaticChildClass;

typedef struct {
  gchar     *callback_name;
  GCallback  callback_symbol;
} CallbackSymbol;

typedef struct {
  GBytes               *data;
  GSList               *children;
  GSList               *callbacks;
  GtkBuilderConnectFunc connect_func;
  gpointer              connect_data;
  GDestroyNotify        destroy_notify;
} GtkWidgetTemplate;

481
typedef struct {
482
  GtkEventController *controller;
483
  guint evmask_notify_id;
484
  guint grab_notify_id;
485
  guint sequence_state_changed_id;
486 487
} EventControllerData;

488 489
struct _GtkWidgetPrivate
{
490 491
  /* The state of the widget. Needs to be able to hold all GtkStateFlags bits
   * (defined in "gtkenums.h").
492
   */
493
  guint state_flags : GTK_STATE_FLAGS_BITS;
494

495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
  guint direction             : 2;

  guint in_destruction        : 1;
  guint toplevel              : 1;
  guint anchored              : 1;
  guint composite_child       : 1;
  guint no_window             : 1;
  guint realized              : 1;
  guint mapped                : 1;
  guint visible               : 1;
  guint sensitive             : 1;
  guint can_focus             : 1;
  guint has_focus             : 1;
  guint can_default           : 1;
  guint has_default           : 1;
  guint receives_default      : 1;
  guint has_grab              : 1;
  guint shadowed              : 1;
513
  guint style_update_pending  : 1;
514
  guint app_paintable         : 1;
515
  guint double_buffered       : 1;
516 517 518 519 520 521
  guint redraw_on_alloc       : 1;
  guint no_show_all           : 1;
  guint child_visible         : 1;
  guint multidevice           : 1;
  guint has_shape_mask        : 1;
  guint in_reparent           : 1;
522
  guint supports_clip         : 1;
523 524

  /* Queue-resize related flags */
525
  guint alloc_needed          : 1;
526

527 528 529 530 531 532 533 534 535
  /* Expand-related flags */
  guint need_compute_expand   : 1; /* Need to recompute computed_[hv]_expand */
  guint computed_hexpand      : 1; /* computed results (composite of child flags) */
  guint computed_vexpand      : 1;
  guint hexpand               : 1; /* application-forced expand */
  guint vexpand               : 1;
  guint hexpand_set           : 1; /* whether to use application-forced  */
  guint vexpand_set           : 1; /* instead of computing from children */

536 537 538
  /* SizeGroup related flags */
  guint have_size_groups      : 1;

539
  guint8 alpha;
Alexander Larsson's avatar
Alexander Larsson committed
540
  guint8 user_alpha;
541

542
  /* The widget's name. If the widget does not have a name
543 544
   * (the name is NULL), then its name (as returned by
   * "gtk_widget_get_name") is its class's name.
545
   * Among other things, the widget name is used to determine
546
   * the style to use for a widget.
547 548 549
   */
  gchar *name;

550 551 552 553 554
  /* The list of attached windows to this widget.
   * We keep a list in order to call reset_style to all of them,
   * recursively. */
  GList *attached_windows; 

555
  /* The style for the widget. The style contains the
556 557 558
   * colors the widget should be drawn in for each state
   * along with graphics contexts used to draw with and
   * the font to use for text.
559 560
   */
  GtkStyle *style;
561
  GtkStyleContext *context;
562

563 564 565 566
  /* Widget's path for styling */
  GtkWidgetPath *path;

  /* The widget's allocated size */
567
  GtkAllocation allocation;
568
  gint allocated_baseline;
569
  GtkAllocation clip;
570

571 572 573
  /* The widget's requested sizes */
  SizeRequestCache requests;

574
  /* actions attached to this or any parent widget */
575
  GtkActionMuxer *muxer;
576

577
  /* The widget's window or its parent window if it does
578 579
   * not have a window. (Which will be indicated by the
   * GTK_NO_WINDOW flag being set).
580 581
   */
  GdkWindow *window;
582
  GList *registered_windows;
583

584
  /* The widget's parent */
585
  GtkWidget *parent;
586

587
  /* Animations and other things to update on clock ticks */
588
  GList *tick_callbacks;
589
  guint clock_tick_id;
590

591 592 593 594
  /* A hash by GType key, containing hash tables by widget name
   */
  GHashTable *auto_children;

595 596 597 598
#ifdef G_ENABLE_DEBUG
  /* Number of gtk_widget_push_verify_invariants () */
  guint verifying_invariants_count;
#endif /* G_ENABLE_DEBUG */
599 600

  GList *event_controllers;
601
};
Elliot Lee's avatar
Elliot Lee committed
602

603 604
struct _GtkWidgetClassPrivate
{
605
  GtkWidgetTemplate *template;
606
  GType accessible_type;
607
  AtkRole accessible_role;
608 609
};

Elliot Lee's avatar
Elliot Lee committed
610
enum {
611
  DESTROY,
Elliot Lee's avatar
Elliot Lee committed
612 613 614 615 616 617 618
  SHOW,
  HIDE,
  MAP,
  UNMAP,
  REALIZE,
  UNREALIZE,
  SIZE_ALLOCATE,
619
  STATE_FLAGS_CHANGED,
Elliot Lee's avatar
Elliot Lee committed
620
  STATE_CHANGED,
621
  PARENT_SET,
Owen Taylor's avatar
Owen Taylor committed
622
  HIERARCHY_CHANGED,
623
  STYLE_SET,
624
  DIRECTION_CHANGED,
625
  GRAB_NOTIFY,
Tim Janik's avatar
Tim Janik committed
626
  CHILD_NOTIFY,
Benjamin Otte's avatar
Benjamin Otte committed
627
  DRAW,
628
  MNEMONIC_ACTIVATE,
629
  GRAB_FOCUS,
630
  FOCUS,
631
  MOVE_FOCUS,
632
  KEYNAV_FAILED,
Elliot Lee's avatar
Elliot Lee committed
633
  EVENT,
634
  EVENT_AFTER,
Elliot Lee's avatar
Elliot Lee committed
635 636
  BUTTON_PRESS_EVENT,
  BUTTON_RELEASE_EVENT,
637
  SCROLL_EVENT,
Elliot Lee's avatar
Elliot Lee committed
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653
  MOTION_NOTIFY_EVENT,
  DELETE_EVENT,
  DESTROY_EVENT,
  KEY_PRESS_EVENT,
  KEY_RELEASE_EVENT,
  ENTER_NOTIFY_EVENT,
  LEAVE_NOTIFY_EVENT,
  CONFIGURE_EVENT,
  FOCUS_IN_EVENT,
  FOCUS_OUT_EVENT,
  MAP_EVENT,
  UNMAP_EVENT,
  PROPERTY_NOTIFY_EVENT,
  SELECTION_CLEAR_EVENT,
  SELECTION_REQUEST_EVENT,
  SELECTION_NOTIFY_EVENT,
654
  SELECTION_GET,
Elliot Lee's avatar
Elliot Lee committed
655 656 657
  SELECTION_RECEIVED,
  PROXIMITY_IN_EVENT,
  PROXIMITY_OUT_EVENT,
658 659 660 661
  VISIBILITY_NOTIFY_EVENT,
  WINDOW_STATE_EVENT,
  DAMAGE_EVENT,
  GRAB_BROKEN_EVENT,
662 663 664 665 666 667 668 669
  DRAG_BEGIN,
  DRAG_END,
  DRAG_DATA_DELETE,
  DRAG_LEAVE,
  DRAG_MOTION,
  DRAG_DROP,
  DRAG_DATA_GET,
  DRAG_DATA_RECEIVED,
Owen Taylor's avatar
Owen Taylor committed
670
  POPUP_MENU,
671
  SHOW_HELP,
672
  ACCEL_CLOSURES_CHANGED,
Owen Taylor's avatar
Owen Taylor committed
673
  SCREEN_CHANGED,
674
  CAN_ACTIVATE_ACCEL,
Søren Sandmann's avatar
Søren Sandmann committed
675
  COMPOSITED_CHANGED,
Kristian Rietveld's avatar
Kristian Rietveld committed
676
  QUERY_TOOLTIP,
677
  DRAG_FAILED,
678
  STYLE_UPDATED,
679
  TOUCH_EVENT,
Elliot Lee's avatar
Elliot Lee committed
680 681 682
  LAST_SIGNAL
};

683
enum {
Alexander Larsson's avatar
Alexander Larsson committed
684 685 686
  PROP_0,
  PROP_NAME,
  PROP_PARENT,
Havoc Pennington's avatar
Havoc Pennington committed
687 688
  PROP_WIDTH_REQUEST,
  PROP_HEIGHT_REQUEST,
Alexander Larsson's avatar
Alexander Larsson committed
689 690 691 692 693
  PROP_VISIBLE,
  PROP_SENSITIVE,
  PROP_APP_PAINTABLE,
  PROP_CAN_FOCUS,
  PROP_HAS_FOCUS,
694
  PROP_IS_FOCUS,
Alexander Larsson's avatar
Alexander Larsson committed
695 696 697 698 699 700
  PROP_CAN_DEFAULT,
  PROP_HAS_DEFAULT,
  PROP_RECEIVES_DEFAULT,
  PROP_COMPOSITE_CHILD,
  PROP_STYLE,
  PROP_EVENTS,
Kristian Rietveld's avatar
Kristian Rietveld committed
701 702
  PROP_NO_SHOW_ALL,
  PROP_HAS_TOOLTIP,
703
  PROP_TOOLTIP_MARKUP,
Tim Janik's avatar
Tim Janik committed
704
  PROP_TOOLTIP_TEXT,
705
  PROP_WINDOW,
706
  PROP_OPACITY,
707
  PROP_DOUBLE_BUFFERED,
708 709
  PROP_HALIGN,
  PROP_VALIGN,
710 711
  PROP_MARGIN_LEFT,
  PROP_MARGIN_RIGHT,
712 713
  PROP_MARGIN_START,
  PROP_MARGIN_END,
714 715
  PROP_MARGIN_TOP,
  PROP_MARGIN_BOTTOM,
716 717 718 719 720
  PROP_MARGIN,
  PROP_HEXPAND,
  PROP_VEXPAND,
  PROP_HEXPAND_SET,
  PROP_VEXPAND_SET,
721 722
  PROP_EXPAND,
  PROP_SCALE_FACTOR
723 724
};

725 726 727 728
typedef	struct	_GtkStateData	 GtkStateData;

struct _GtkStateData
{
729 730
  guint         flags_to_set;
  guint         flags_to_unset;
731
};
Elliot Lee's avatar
Elliot Lee committed
732

Tim Janik's avatar
Tim Janik committed
733
/* --- prototypes --- */
734
static void	gtk_widget_base_class_init	(gpointer            g_class);
735 736 737
static void	gtk_widget_class_init		(GtkWidgetClass     *klass);
static void	gtk_widget_base_class_finalize	(GtkWidgetClass     *klass);
static void	gtk_widget_init			(GtkWidget          *widget);
Tim Janik's avatar
Tim Janik committed
738
static void	gtk_widget_set_property		 (GObject           *object,
Alexander Larsson's avatar
Alexander Larsson committed
739 740 741
						  guint              prop_id,
						  const GValue      *value,
						  GParamSpec        *pspec);
Tim Janik's avatar
Tim Janik committed
742
static void	gtk_widget_get_property		 (GObject           *object,
Alexander Larsson's avatar
Alexander Larsson committed
743 744 745
						  guint              prop_id,
						  GValue            *value,
						  GParamSpec        *pspec);
746
static void	gtk_widget_constructed           (GObject	    *object);
Tim Janik's avatar
Tim Janik committed
747
static void	gtk_widget_dispose		 (GObject	    *object);
748
static void	gtk_widget_real_destroy		 (GtkWidget	    *object);
Tim Janik's avatar
Tim Janik committed
749 750 751 752 753 754 755 756
static void	gtk_widget_finalize		 (GObject	    *object);
static void	gtk_widget_real_show		 (GtkWidget	    *widget);
static void	gtk_widget_real_hide		 (GtkWidget	    *widget);
static void	gtk_widget_real_map		 (GtkWidget	    *widget);
static void	gtk_widget_real_unmap		 (GtkWidget	    *widget);
static void	gtk_widget_real_realize		 (GtkWidget	    *widget);
static void	gtk_widget_real_unrealize	 (GtkWidget	    *widget);
static void	gtk_widget_real_size_allocate	 (GtkWidget	    *widget,
757
                                                  GtkAllocation	    *allocation);
758 759 760 761
static void	gtk_widget_real_style_set        (GtkWidget         *widget,
                                                  GtkStyle          *previous_style);
static void	gtk_widget_real_direction_changed(GtkWidget         *widget,
                                                  GtkTextDirection   previous_direction);
762

Tim Janik's avatar
Tim Janik committed
763
static void	gtk_widget_real_grab_focus	 (GtkWidget         *focus_widget);
Kristian Rietveld's avatar
Kristian Rietveld committed
764 765 766 767 768
static gboolean gtk_widget_real_query_tooltip    (GtkWidget         *widget,
						  gint               x,
						  gint               y,
						  gboolean           keyboard_tip,
						  GtkTooltip        *tooltip);
769
static void     gtk_widget_real_style_updated    (GtkWidget         *widget);
770
static gboolean gtk_widget_real_show_help        (GtkWidget         *widget,
771
                                                  GtkWidgetHelpType  help_type);
772 773 774
static gboolean _gtk_widget_run_controllers      (GtkWidget           *widget,
                                                  const GdkEvent      *event,
                                                  GtkPropagationPhase  phase);
775

Tim Janik's avatar
Tim Janik committed
776 777 778
static void	gtk_widget_dispatch_child_properties_changed	(GtkWidget        *object,
								 guint             n_pspecs,
								 GParamSpec      **pspecs);
779 780 781 782
static gboolean         gtk_widget_real_button_event            (GtkWidget        *widget,
                                                                 GdkEventButton   *event);
static gboolean         gtk_widget_real_motion_event            (GtkWidget        *widget,
                                                                 GdkEventMotion   *event);
Tim Janik's avatar
Tim Janik committed
783 784 785 786 787 788 789 790
static gboolean		gtk_widget_real_key_press_event   	(GtkWidget        *widget,
								 GdkEventKey      *event);
static gboolean		gtk_widget_real_key_release_event 	(GtkWidget        *widget,
								 GdkEventKey      *event);
static gboolean		gtk_widget_real_focus_in_event   	 (GtkWidget       *widget,
								  GdkEventFocus   *event);
static gboolean		gtk_widget_real_focus_out_event   	(GtkWidget        *widget,
								 GdkEventFocus    *event);
791 792
static gboolean         gtk_widget_real_touch_event             (GtkWidget        *widget,
                                                                 GdkEventTouch    *event);
793 794
static gboolean         gtk_widget_real_grab_broken_event       (GtkWidget          *widget,
                                                                 GdkEventGrabBroken *event);
Tim Janik's avatar
Tim Janik committed
795 796
static gboolean		gtk_widget_real_focus			(GtkWidget        *widget,
								 GtkDirectionType  direction);
797 798
static void             gtk_widget_real_move_focus              (GtkWidget        *widget,
                                                                 GtkDirectionType  direction);
799 800
static gboolean		gtk_widget_real_keynav_failed		(GtkWidget        *widget,
								 GtkDirectionType  direction);
801 802 803 804 805 806 807 808 809
#ifdef G_ENABLE_DEBUG
static void             gtk_widget_verify_invariants            (GtkWidget        *widget);
static void             gtk_widget_push_verify_invariants       (GtkWidget        *widget);
static void             gtk_widget_pop_verify_invariants        (GtkWidget        *widget);
#else
#define                 gtk_widget_verify_invariants(widget)
#define                 gtk_widget_push_verify_invariants(widget)
#define                 gtk_widget_pop_verify_invariants(widget)
#endif
Tim Janik's avatar
Tim Janik committed
810
static PangoContext*	gtk_widget_peek_pango_context		(GtkWidget	  *widget);
811
static void     	gtk_widget_update_pango_context		(GtkWidget	  *widget);
Tim Janik's avatar
Tim Janik committed
812 813
static void		gtk_widget_propagate_state		(GtkWidget	  *widget,
								 GtkStateData 	  *data);
Alexander Larsson's avatar
Alexander Larsson committed
814 815
static void             gtk_widget_update_alpha                 (GtkWidget        *widget);

Tim Janik's avatar
Tim Janik committed
816 817 818 819
static gint		gtk_widget_event_internal		(GtkWidget	  *widget,
								 GdkEvent	  *event);
static gboolean		gtk_widget_real_mnemonic_activate	(GtkWidget	  *widget,
								 gboolean	   group_cycling);
820 821 822 823 824 825 826 827 828 829 830 831 832 833
static void             gtk_widget_real_get_width               (GtkWidget        *widget,
                                                                 gint             *minimum_size,
                                                                 gint             *natural_size);
static void             gtk_widget_real_get_height              (GtkWidget        *widget,
                                                                 gint             *minimum_size,
                                                                 gint             *natural_size);
static void             gtk_widget_real_get_height_for_width    (GtkWidget        *widget,
                                                                 gint              width,
                                                                 gint             *minimum_height,
                                                                 gint             *natural_height);
static void             gtk_widget_real_get_width_for_height    (GtkWidget        *widget,
                                                                 gint              height,
                                                                 gint             *minimum_width,
                                                                 gint             *natural_width);
834 835
static void             gtk_widget_real_state_flags_changed     (GtkWidget        *widget,
                                                                 GtkStateFlags     old_state);
836 837
static void             gtk_widget_real_queue_draw_region       (GtkWidget         *widget,
								 const cairo_region_t *region);
838
static const GtkWidgetAuxInfo* _gtk_widget_get_aux_info_or_defaults (GtkWidget *widget);
839 840
static GtkWidgetAuxInfo* gtk_widget_get_aux_info                (GtkWidget        *widget,
                                                                 gboolean          create);
Tim Janik's avatar
Tim Janik committed
841 842 843 844
static void		gtk_widget_aux_info_destroy		(GtkWidgetAuxInfo *aux_info);
static AtkObject*	gtk_widget_real_get_accessible		(GtkWidget	  *widget);
static void		gtk_widget_accessible_interface_init	(AtkImplementorIface *iface);
static AtkObject*	gtk_widget_ref_accessible		(AtkImplementor *implementor);
845
static void             gtk_widget_invalidate_widget_windows    (GtkWidget        *widget,
846
								 cairo_region_t        *region);
847
static GdkScreen *      gtk_widget_get_screen_unchecked         (GtkWidget        *widget);
848 849
static gboolean         gtk_widget_real_can_activate_accel      (GtkWidget *widget,
                                                                 guint      signal_id);
Kristian Rietveld's avatar
Kristian Rietveld committed
850

851
static void             gtk_widget_real_set_has_tooltip         (GtkWidget *widget,
Kristian Rietveld's avatar
Kristian Rietveld committed
852 853
								 gboolean   has_tooltip,
								 gboolean   force);
Johan Dahlin's avatar
Johan Dahlin committed
854 855 856 857
static void             gtk_widget_buildable_interface_init     (GtkBuildableIface *iface);
static void             gtk_widget_buildable_set_name           (GtkBuildable     *buildable,
                                                                 const gchar      *name);
static const gchar *    gtk_widget_buildable_get_name           (GtkBuildable     *buildable);
858 859 860
static GObject *        gtk_widget_buildable_get_internal_child (GtkBuildable *buildable,
								 GtkBuilder   *builder,
								 const gchar  *childname);
861 862 863 864
static void             gtk_widget_buildable_set_buildable_property (GtkBuildable     *buildable,
								     GtkBuilder       *builder,
								     const gchar      *name,
								     const GValue     *value);
Johan Dahlin's avatar
Johan Dahlin committed
865 866 867 868 869 870
static gboolean         gtk_widget_buildable_custom_tag_start   (GtkBuildable     *buildable,
                                                                 GtkBuilder       *builder,
                                                                 GObject          *child,
                                                                 const gchar      *tagname,
                                                                 GMarkupParser    *parser,
                                                                 gpointer         *data);
871
static void             gtk_widget_buildable_custom_finished    (GtkBuildable     *buildable,
Johan Dahlin's avatar
Johan Dahlin committed
872 873 874 875
                                                                 GtkBuilder       *builder,
                                                                 GObject          *child,
                                                                 const gchar      *tagname,
                                                                 gpointer          data);
876
static void             gtk_widget_buildable_parser_finished    (GtkBuildable     *buildable,
Johan Dahlin's avatar
Johan Dahlin committed
877 878
                                                                 GtkBuilder       *builder);

879
static GtkSizeRequestMode gtk_widget_real_get_request_mode      (GtkWidget         *widget);
880
static void             gtk_widget_real_get_width               (GtkWidget         *widget,
881 882
                                                                 gint              *minimum_size,
                                                                 gint              *natural_size);
883
static void             gtk_widget_real_get_height              (GtkWidget         *widget,
884 885
                                                                 gint              *minimum_size,
                                                                 gint              *natural_size);
886

Matthias Clasen's avatar
Matthias Clasen committed
887
static void             gtk_widget_queue_tooltip_query          (GtkWidget *widget);
888 889 890 891 892 893


static void             gtk_widget_real_adjust_size_request     (GtkWidget         *widget,
                                                                 GtkOrientation     orientation,
                                                                 gint              *minimum_size,
                                                                 gint              *natural_size);
894 895 896
static void             gtk_widget_real_adjust_baseline_request (GtkWidget         *widget,
								 gint              *minimum_baseline,
								 gint              *natural_baseline);
897
static void             gtk_widget_real_adjust_size_allocation  (GtkWidget         *widget,
898
                                                                 GtkOrientation     orientation,
899
                                                                 gint              *minimum_size,
900 901 902
                                                                 gint              *natural_size,
                                                                 gint              *allocated_pos,
                                                                 gint              *allocated_size);
903 904
static void             gtk_widget_real_adjust_baseline_allocation (GtkWidget         *widget,
								    gint              *baseline);
905

906
/* --- functions dealing with template data structures --- */
907 908 909 910
static AutomaticChildClass  *template_child_class_new          (const gchar          *name,
                                                                gboolean              internal_child,
                                                                gssize                offset);
static void                  template_child_class_free         (AutomaticChildClass  *child_class);
911 912 913 914 915 916 917
static CallbackSymbol       *callback_symbol_new                (const gchar          *name,
								 GCallback             callback);
static void                  callback_symbol_free               (CallbackSymbol       *callback);
static void                  template_data_free                 (GtkWidgetTemplate    *template_data);
static GHashTable           *get_auto_child_hash                (GtkWidget            *widget,
								 GType                 type,
								 gboolean              create);
918 919 920 921 922
static gboolean              setup_template_child              (GtkWidgetTemplate    *template_data,
                                                                GType                 class_type,
                                                                AutomaticChildClass  *child_class,
                                                                GtkWidget            *widget,
                                                                GtkBuilder           *builder);
923

924 925 926 927
static void gtk_widget_set_usize_internal (GtkWidget          *widget,
					   gint                width,
					   gint                height,
					   GtkQueueResizeFlags flags);
928

929 930 931
static void gtk_widget_add_events_internal (GtkWidget *widget,
                                            GdkDevice *device,
                                            gint       events);
932 933 934 935
static void gtk_widget_set_device_enabled_internal (GtkWidget *widget,
                                                    GdkDevice *device,
                                                    gboolean   recurse,
                                                    gboolean   enabled);
936 937 938 939

static void gtk_widget_on_frame_clock_update (GdkFrameClock *frame_clock,
                                              GtkWidget     *widget);

940
static gboolean event_window_is_still_viewable (GdkEvent *event);
941 942
static void gtk_cairo_set_event_window (cairo_t        *cr,
					GdkWindow *window);
943 944
static void gtk_cairo_set_event (cairo_t        *cr,
				 GdkEventExpose *event);
Tim Janik's avatar
Tim Janik committed
945

946 947
static void gtk_widget_update_input_shape (GtkWidget *widget);

Tim Janik's avatar
Tim Janik committed
948
/* --- variables --- */
949
static gint             GtkWidget_private_offset = 0;
950
static gpointer         gtk_widget_parent_class = NULL;
951 952 953 954
static guint            widget_signals[LAST_SIGNAL] = { 0 };
static guint            composite_child_stack = 0;
static GtkTextDirection gtk_default_direction = GTK_TEXT_DIR_LTR;
static GParamSpecPool  *style_property_spec_pool = NULL;
955

Tim Janik's avatar
Tim Janik committed
956 957
static GQuark		quark_property_parser = 0;
static GQuark		quark_aux_info = 0;
958 959
static GQuark		quark_accel_path = 0;
static GQuark		quark_accel_closures = 0;
Tim Janik's avatar
Tim Janik committed
960
static GQuark		quark_event_mask = 0;
961
static GQuark           quark_device_event_mask = 0;
Tim Janik's avatar
Tim Janik committed
962 963
static GQuark		quark_parent_window = 0;
static GQuark		quark_shape_info = 0;
964
static GQuark		quark_input_shape_info = 0;
Tim Janik's avatar
Tim Janik committed
965 966
static GQuark		quark_pango_context = 0;
static GQuark		quark_accessible_object = 0;
967
static GQuark		quark_mnemonic_labels = 0;
Kristian Rietveld's avatar
Kristian Rietveld committed
968 969 970
static GQuark		quark_tooltip_markup = 0;
static GQuark		quark_has_tooltip = 0;
static GQuark		quark_tooltip_window = 0;
971
static GQuark		quark_visual = 0;
972
static GQuark           quark_modifier_style = 0;
973
static GQuark           quark_enabled_devices = 0;
974
static GQuark           quark_size_groups = 0;
Tim Janik's avatar
Tim Janik committed
975 976 977 978
GParamSpecPool         *_gtk_widget_child_property_pool = NULL;
GObjectNotifyContext   *_gtk_widget_child_property_notify_context = NULL;

/* --- functions --- */
979 980 981 982 983 984 985 986 987 988
GType
gtk_widget_get_type (void)
{
  static GType widget_type = 0;

  if (G_UNLIKELY (widget_type == 0))
    {
      const GTypeInfo widget_info =
      {
	sizeof (GtkWidgetClass),
989
	gtk_widget_base_class_init,
990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006
	(GBaseFinalizeFunc) gtk_widget_base_class_finalize,
	(GClassInitFunc) gtk_widget_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_init */
	sizeof (GtkWidget),
	0,		/* n_preallocs */
	(GInstanceInitFunc) gtk_widget_init,
	NULL,		/* value_table */
      };

      const GInterfaceInfo accessibility_info =
      {
	(GInterfaceInitFunc) gtk_widget_accessible_interface_init,
	(GInterfaceFinalizeFunc) NULL,
	NULL /* interface data */
      };

Johan Dahlin's avatar
Johan Dahlin committed
1007 1008 1009 1010 1011 1012 1013
      const GInterfaceInfo buildable_info =
      {
	(GInterfaceInitFunc) gtk_widget_buildable_interface_init,
	(GInterfaceFinalizeFunc) NULL,
	NULL /* interface data */
      };

1014 1015
      widget_type = g_type_register_static (G_TYPE_INITIALLY_UNOWNED, "GtkWidget",
                                            &widget_info, G_TYPE_FLAG_ABSTRACT);
1016

1017 1018
      g_type_add_class_private (widget_type, sizeof (GtkWidgetClassPrivate));

1019 1020 1021
      GtkWidget_private_offset =
        g_type_add_instance_private (widget_type, sizeof (GtkWidgetPrivate));

1022 1023
      g_type_add_interface_static (widget_type, ATK_TYPE_IMPLEMENTOR,
                                   &accessibility_info) ;
Johan Dahlin's avatar
Johan Dahlin committed
1024 1025
      g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
                                   &buildable_info) ;
1026 1027 1028 1029
    }

  return widget_type;
}
Elliot Lee's avatar
Elliot Lee committed
1030

1031 1032 1033 1034 1035 1036
static inline gpointer
gtk_widget_get_instance_private (GtkWidget *self)
{
  return (G_STRUCT_MEMBER_P (self, GtkWidget_private_offset));
}

1037 1038 1039 1040 1041
static void
gtk_widget_base_class_init (gpointer g_class)
{
  GtkWidgetClass *klass = g_class;

1042
  klass->priv = G_TYPE_CLASS_GET_PRIVATE (g_class, GTK_TYPE_WIDGET, GtkWidgetClassPrivate);
1043
  klass->priv->template = NULL;
1044 1045
}

Tim Janik's avatar
Tim Janik committed
1046 1047 1048 1049 1050 1051 1052 1053
static void
child_property_notify_dispatcher (GObject     *object,
				  guint        n_pspecs,
				  GParamSpec **pspecs)
{
  GTK_WIDGET_GET_CLASS (object)->dispatch_child_properties_changed (GTK_WIDGET (object), n_pspecs, pspecs);
}

1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111
/* We guard against the draw signal callbacks modifying the state of the
 * cairo context by surounding it with save/restore.
 * Maybe we should also cairo_new_path() just to be sure?
 */
static void
gtk_widget_draw_marshaller (GClosure     *closure,
                            GValue       *return_value,
                            guint         n_param_values,
                            const GValue *param_values,
                            gpointer      invocation_hint,
                            gpointer      marshal_data)
{
  cairo_t *cr = g_value_get_boxed (&param_values[1]);

  cairo_save (cr);

  _gtk_marshal_BOOLEAN__BOXED (closure,
                               return_value,
                               n_param_values,
                               param_values,
                               invocation_hint,
                               marshal_data);


  cairo_restore (cr);
}

static void
gtk_widget_draw_marshallerv (GClosure     *closure,
			     GValue       *return_value,
			     gpointer      instance,
			     va_list       args,
			     gpointer      marshal_data,
			     int           n_params,
			     GType        *param_types)
{
  cairo_t *cr;
  va_list args_copy;

  G_VA_COPY (args_copy, args);
  cr = va_arg (args_copy, gpointer);

  cairo_save (cr);

  _gtk_marshal_BOOLEAN__BOXEDv (closure,
				return_value,
				instance,
				args,
				marshal_data,
				n_params,
				param_types);


  cairo_restore (cr);

  va_end (args_copy);
}

Elliot Lee's avatar
Elliot Lee committed
1112 1113 1114
static void
gtk_widget_class_init (GtkWidgetClass *klass)
{
Tim Janik's avatar
Tim Janik committed
1115
  static GObjectNotifyContext cpn_context = { 0, NULL, NULL };
1116
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
Owen Taylor's avatar
Owen Taylor committed
1117
  GtkBindingSet *binding_set;
1118

1119
  g_type_class_adjust_private_offset (klass, &GtkWidget_private_offset);
1120 1121
  gtk_widget_parent_class = g_type_class_peek_parent (klass);

Tim Janik's avatar
Tim Janik committed
1122 1123
  quark_property_parser = g_quark_from_static_string ("gtk-rc-property-parser");
  quark_aux_info = g_quark_from_static_string ("gtk-aux-info");
1124 1125
  quark_accel_path = g_quark_from_static_string ("gtk-accel-path");
  quark_accel_closures = g_quark_from_static_string ("gtk-accel-closures");
Tim Janik's avatar
Tim Janik committed
1126
  quark_event_mask = g_quark_from_static_string ("gtk-event-mask");
1127
  quark_device_event_mask = g_quark_from_static_string ("gtk-device-event-mask");
Tim Janik's avatar
Tim Janik committed
1128 1129
  quark_parent_window = g_quark_from_static_string ("gtk-parent-window");
  quark_shape_info = g_quark_from_static_string ("gtk-shape-info");
1130
  quark_input_shape_info = g_quark_from_static_string ("gtk-input-shape-info");
Tim Janik's avatar
Tim Janik committed
1131 1132
  quark_pango_context = g_quark_from_static_string ("gtk-pango-context");
  quark_accessible_object = g_quark_from_static_string ("gtk-accessible-object");
1133
  quark_mnemonic_labels = g_quark_from_static_string ("gtk-mnemonic-labels");
Kristian Rietveld's avatar
Kristian Rietveld committed
1134 1135 1136
  quark_tooltip_markup = g_quark_from_static_string ("gtk-tooltip-markup");
  quark_has_tooltip = g_quark_from_static_string ("gtk-has-tooltip");
  quark_tooltip_window = g_quark_from_static_string ("gtk-tooltip-window");