gtkwidget.c 533 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"
Elliot Lee's avatar
Elliot Lee committed
48
#include "gtkwidget.h"
Emmanuele Bassi's avatar
Emmanuele Bassi committed
49
#include "gtkwidgetprivate.h"
Matthias Clasen's avatar
Matthias Clasen committed
50
#include "gtkwindowprivate.h"
51
#include "gtkcontainerprivate.h"
Tim Janik's avatar
Tim Janik committed
52
#include "gtkbindings.h"
53
#include "gtkprivate.h"
54
#include "gtkaccessible.h"
55
#include "gtktooltipprivate.h"
56
#include "gtkinvisible.h"
Johan Dahlin's avatar
Johan Dahlin committed
57
#include "gtkbuildable.h"
58
#include "gtkbuilderprivate.h"
59
#include "gtksizerequest.h"
60
#include "gtkstylecontextprivate.h"
61
#include "gtkcssprovider.h"
Benjamin Otte's avatar
Benjamin Otte committed
62
#include "gtkcsswidgetnodeprivate.h"
63
#include "gtkmodifierstyle.h"
64
#include "gtkversion.h"
Matthias Clasen's avatar
Matthias Clasen committed
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
 * Since 3.10 GTK+ also supports baseline vertical alignment of widgets. This
240 241 242
 * 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 ## {#composite-templates}
Matthias Clasen's avatar
Matthias Clasen committed
322
 *
323
 * GtkWidget exposes some facilities to automate the procedure
324 325
 * 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
 * The interface description semantics expected in composite template descriptions
332
 * is slightly different from regular #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
 * Additionally, <object> tags can also be added before and after the initial
350
 * <template> tag in the normal way, allowing one to define auxiliary objects
351 352
 * 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 460 461
typedef struct {
  gchar               *name;           /* Name of the template automatic child */
  gboolean             internal_child; /* Whether the automatic widget should be exported as an <internal-child> */
462
  gssize               offset;         /* Instance private data offset where to set the automatic child (or 0) */
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
} 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;

479
typedef struct {
480
  GtkEventController *controller;
481
  guint grab_notify_id;
482
  guint sequence_state_changed_id;
483 484
} EventControllerData;

485 486
struct _GtkWidgetClassPrivate
{
487
  GtkWidgetTemplate *template;
488
  GType accessible_type;
489
  AtkRole accessible_role;
490
  const char *css_name;
491 492
};

Elliot Lee's avatar
Elliot Lee committed
493
enum {
494
  DESTROY,
Elliot Lee's avatar
Elliot Lee committed
495 496 497 498 499 500 501
  SHOW,
  HIDE,
  MAP,
  UNMAP,
  REALIZE,
  UNREALIZE,
  SIZE_ALLOCATE,
502
  STATE_FLAGS_CHANGED,
Elliot Lee's avatar
Elliot Lee committed
503
  STATE_CHANGED,
504
  PARENT_SET,
Owen Taylor's avatar
Owen Taylor committed
505
  HIERARCHY_CHANGED,
506
  STYLE_SET,
507
  DIRECTION_CHANGED,
508
  GRAB_NOTIFY,
Tim Janik's avatar
Tim Janik committed
509
  CHILD_NOTIFY,
Benjamin Otte's avatar
Benjamin Otte committed
510
  DRAW,
511
  MNEMONIC_ACTIVATE,
512
  GRAB_FOCUS,
513
  FOCUS,
514
  MOVE_FOCUS,
515
  KEYNAV_FAILED,
Elliot Lee's avatar
Elliot Lee committed
516
  EVENT,
517
  EVENT_AFTER,
Elliot Lee's avatar
Elliot Lee committed
518 519
  BUTTON_PRESS_EVENT,
  BUTTON_RELEASE_EVENT,
520
  SCROLL_EVENT,
Elliot Lee's avatar
Elliot Lee committed
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
  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,
537
  SELECTION_GET,
Elliot Lee's avatar
Elliot Lee committed
538 539 540
  SELECTION_RECEIVED,
  PROXIMITY_IN_EVENT,
  PROXIMITY_OUT_EVENT,
541 542 543 544
  VISIBILITY_NOTIFY_EVENT,
  WINDOW_STATE_EVENT,
  DAMAGE_EVENT,
  GRAB_BROKEN_EVENT,
545 546 547 548 549 550 551 552
  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
553
  POPUP_MENU,
554
  SHOW_HELP,
555
  ACCEL_CLOSURES_CHANGED,
Owen Taylor's avatar
Owen Taylor committed
556
  SCREEN_CHANGED,
557
  CAN_ACTIVATE_ACCEL,
Søren Sandmann's avatar
Søren Sandmann committed
558
  COMPOSITED_CHANGED,
Kristian Rietveld's avatar
Kristian Rietveld committed
559
  QUERY_TOOLTIP,
560
  DRAG_FAILED,
561
  STYLE_UPDATED,
562
  TOUCH_EVENT,
Elliot Lee's avatar
Elliot Lee committed
563 564 565
  LAST_SIGNAL
};

566
enum {
Alexander Larsson's avatar
Alexander Larsson committed
567 568 569
  PROP_0,
  PROP_NAME,
  PROP_PARENT,
Havoc Pennington's avatar
Havoc Pennington committed
570 571
  PROP_WIDTH_REQUEST,
  PROP_HEIGHT_REQUEST,
Alexander Larsson's avatar
Alexander Larsson committed
572 573 574 575 576
  PROP_VISIBLE,
  PROP_SENSITIVE,
  PROP_APP_PAINTABLE,
  PROP_CAN_FOCUS,
  PROP_HAS_FOCUS,
577
  PROP_IS_FOCUS,
578
  PROP_FOCUS_ON_CLICK,
Alexander Larsson's avatar
Alexander Larsson committed
579 580 581 582 583 584
  PROP_CAN_DEFAULT,
  PROP_HAS_DEFAULT,
  PROP_RECEIVES_DEFAULT,
  PROP_COMPOSITE_CHILD,
  PROP_STYLE,
  PROP_EVENTS,
Kristian Rietveld's avatar
Kristian Rietveld committed
585 586
  PROP_NO_SHOW_ALL,
  PROP_HAS_TOOLTIP,
587
  PROP_TOOLTIP_MARKUP,
Tim Janik's avatar
Tim Janik committed
588
  PROP_TOOLTIP_TEXT,
589
  PROP_WINDOW,
590
  PROP_OPACITY,
591
  PROP_DOUBLE_BUFFERED,
Matthias Clasen's avatar
Matthias Clasen committed
592 593
  PROP_HALIGN,
  PROP_VALIGN,
594 595
  PROP_MARGIN_LEFT,
  PROP_MARGIN_RIGHT,
596 597
  PROP_MARGIN_START,
  PROP_MARGIN_END,
598 599
  PROP_MARGIN_TOP,
  PROP_MARGIN_BOTTOM,
600 601 602 603 604
  PROP_MARGIN,
  PROP_HEXPAND,
  PROP_VEXPAND,
  PROP_HEXPAND_SET,
  PROP_VEXPAND_SET,
605
  PROP_EXPAND,
606 607
  PROP_SCALE_FACTOR,
  NUM_PROPERTIES
608 609
};

610 611
static GParamSpec *widget_props[NUM_PROPERTIES] = { NULL, };

612 613 614 615
typedef	struct	_GtkStateData	 GtkStateData;

struct _GtkStateData
{
616 617
  guint         flags_to_set;
  guint         flags_to_unset;
618
};
Elliot Lee's avatar
Elliot Lee committed
619

Tim Janik's avatar
Tim Janik committed
620
/* --- prototypes --- */
621
static void	gtk_widget_base_class_init	(gpointer            g_class);
622 623
static void	gtk_widget_class_init		(GtkWidgetClass     *klass);
static void	gtk_widget_base_class_finalize	(GtkWidgetClass     *klass);
Benjamin Otte's avatar
Benjamin Otte committed
624 625
static void     gtk_widget_init                  (GTypeInstance     *instance,
                                                  gpointer           g_class);
Tim Janik's avatar
Tim Janik committed
626
static void	gtk_widget_set_property		 (GObject           *object,
Alexander Larsson's avatar
Alexander Larsson committed
627 628 629
						  guint              prop_id,
						  const GValue      *value,
						  GParamSpec        *pspec);
Tim Janik's avatar
Tim Janik committed
630
static void	gtk_widget_get_property		 (GObject           *object,
Alexander Larsson's avatar
Alexander Larsson committed
631 632 633
						  guint              prop_id,
						  GValue            *value,
						  GParamSpec        *pspec);
634
static void	gtk_widget_constructed           (GObject	    *object);
Tim Janik's avatar
Tim Janik committed
635
static void	gtk_widget_dispose		 (GObject	    *object);
Matthias Clasen's avatar
Matthias Clasen committed
636
static void	gtk_widget_real_destroy		 (GtkWidget	    *object);
Tim Janik's avatar
Tim Janik committed
637 638 639 640 641 642 643 644
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,
645
                                                  GtkAllocation	    *allocation);
646 647 648 649
static void	gtk_widget_real_style_set        (GtkWidget         *widget,
                                                  GtkStyle          *previous_style);
static void	gtk_widget_real_direction_changed(GtkWidget         *widget,
                                                  GtkTextDirection   previous_direction);
650

Tim Janik's avatar
Tim Janik committed
651
static void	gtk_widget_real_grab_focus	 (GtkWidget         *focus_widget);
Kristian Rietveld's avatar
Kristian Rietveld committed
652 653 654 655 656
static gboolean gtk_widget_real_query_tooltip    (GtkWidget         *widget,
						  gint               x,
						  gint               y,
						  gboolean           keyboard_tip,
						  GtkTooltip        *tooltip);
657
static void     gtk_widget_real_style_updated    (GtkWidget         *widget);
658
static gboolean gtk_widget_real_show_help        (GtkWidget         *widget,
659
                                                  GtkWidgetHelpType  help_type);
660 661 662
static gboolean _gtk_widget_run_controllers      (GtkWidget           *widget,
                                                  const GdkEvent      *event,
                                                  GtkPropagationPhase  phase);
663

Tim Janik's avatar
Tim Janik committed
664 665 666
static void	gtk_widget_dispatch_child_properties_changed	(GtkWidget        *object,
								 guint             n_pspecs,
								 GParamSpec      **pspecs);
667 668 669 670
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
671 672 673 674 675 676 677 678
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);
679 680
static gboolean         gtk_widget_real_touch_event             (GtkWidget        *widget,
                                                                 GdkEventTouch    *event);
681 682
static gboolean         gtk_widget_real_grab_broken_event       (GtkWidget          *widget,
                                                                 GdkEventGrabBroken *event);
Tim Janik's avatar
Tim Janik committed
683 684
static gboolean		gtk_widget_real_focus			(GtkWidget        *widget,
								 GtkDirectionType  direction);
685 686
static void             gtk_widget_real_move_focus              (GtkWidget        *widget,
                                                                 GtkDirectionType  direction);
687 688
static gboolean		gtk_widget_real_keynav_failed		(GtkWidget        *widget,
								 GtkDirectionType  direction);
689
#ifdef G_ENABLE_CONSISTENCY_CHECKS
690 691 692 693 694 695 696 697
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
698
static PangoContext*	gtk_widget_peek_pango_context		(GtkWidget	  *widget);
699
static void     	gtk_widget_update_pango_context		(GtkWidget	  *widget);
Tim Janik's avatar
Tim Janik committed
700 701
static void		gtk_widget_propagate_state		(GtkWidget	  *widget,
								 GtkStateData 	  *data);
Alexander Larsson's avatar
Alexander Larsson committed
702 703
static void             gtk_widget_update_alpha                 (GtkWidget        *widget);

Tim Janik's avatar
Tim Janik committed
704 705 706 707
static gint		gtk_widget_event_internal		(GtkWidget	  *widget,
								 GdkEvent	  *event);
static gboolean		gtk_widget_real_mnemonic_activate	(GtkWidget	  *widget,
								 gboolean	   group_cycling);
708 709 710 711 712 713 714 715 716 717 718 719 720 721
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);
722 723
static void             gtk_widget_real_state_flags_changed     (GtkWidget        *widget,
                                                                 GtkStateFlags     old_state);
724 725
static void             gtk_widget_real_queue_draw_region       (GtkWidget         *widget,
								 const cairo_region_t *region);
Tim Janik's avatar
Tim Janik committed
726 727 728
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);
729
static void             gtk_widget_invalidate_widget_windows    (GtkWidget        *widget,
730
								 cairo_region_t        *region);
731
static GdkScreen *      gtk_widget_get_screen_unchecked         (GtkWidget        *widget);
732 733
static gboolean         gtk_widget_real_can_activate_accel      (GtkWidget *widget,
                                                                 guint      signal_id);
Kristian Rietveld's avatar
Kristian Rietveld committed
734

735
static void             gtk_widget_real_set_has_tooltip         (GtkWidget *widget,
Kristian Rietveld's avatar
Kristian Rietveld committed
736 737
								 gboolean   has_tooltip,
								 gboolean   force);
Johan Dahlin's avatar
Johan Dahlin committed
738 739 740 741
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);
742 743 744
static GObject *        gtk_widget_buildable_get_internal_child (GtkBuildable *buildable,
								 GtkBuilder   *builder,
								 const gchar  *childname);
745 746 747 748
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
749 750 751 752 753 754
static gboolean         gtk_widget_buildable_custom_tag_start   (GtkBuildable     *buildable,
                                                                 GtkBuilder       *builder,
                                                                 GObject          *child,
                                                                 const gchar      *tagname,
                                                                 GMarkupParser    *parser,
                                                                 gpointer         *data);
755
static void             gtk_widget_buildable_custom_finished    (GtkBuildable     *buildable,
Johan Dahlin's avatar
Johan Dahlin committed
756 757 758 759
                                                                 GtkBuilder       *builder,
                                                                 GObject          *child,
                                                                 const gchar      *tagname,
                                                                 gpointer          data);
760
static void             gtk_widget_buildable_parser_finished    (GtkBuildable     *buildable,
Johan Dahlin's avatar
Johan Dahlin committed
761 762
                                                                 GtkBuilder       *builder);

763
static GtkSizeRequestMode gtk_widget_real_get_request_mode      (GtkWidget         *widget);
764
static void             gtk_widget_real_get_width               (GtkWidget         *widget,
765 766
                                                                 gint              *minimum_size,
                                                                 gint              *natural_size);
767
static void             gtk_widget_real_get_height              (GtkWidget         *widget,
768 769
                                                                 gint              *minimum_size,
                                                                 gint              *natural_size);
770

Matthias Clasen's avatar
Matthias Clasen committed
771
static void             gtk_widget_queue_tooltip_query          (GtkWidget *widget);
772 773 774 775 776 777


static void             gtk_widget_real_adjust_size_request     (GtkWidget         *widget,
                                                                 GtkOrientation     orientation,
                                                                 gint              *minimum_size,
                                                                 gint              *natural_size);
778 779 780
static void             gtk_widget_real_adjust_baseline_request (GtkWidget         *widget,
								 gint              *minimum_baseline,
								 gint              *natural_baseline);
781
static void             gtk_widget_real_adjust_size_allocation  (GtkWidget         *widget,
782
                                                                 GtkOrientation     orientation,
783
                                                                 gint              *minimum_size,
784 785 786
                                                                 gint              *natural_size,
                                                                 gint              *allocated_pos,
                                                                 gint              *allocated_size);
787 788
static void             gtk_widget_real_adjust_baseline_allocation (GtkWidget         *widget,
								    gint              *baseline);
789

790
/* --- functions dealing with template data structures --- */
791 792 793 794
static AutomaticChildClass  *template_child_class_new          (const gchar          *name,
                                                                gboolean              internal_child,
                                                                gssize                offset);
static void                  template_child_class_free         (AutomaticChildClass  *child_class);
795 796 797 798 799 800 801
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);
802 803 804 805 806
static gboolean              setup_template_child              (GtkWidgetTemplate    *template_data,
                                                                GType                 class_type,
                                                                AutomaticChildClass  *child_class,
                                                                GtkWidget            *widget,
                                                                GtkBuilder           *builder);
807

808 809
static void gtk_widget_set_usize_internal (GtkWidget          *widget,
					   gint                width,
810
					   gint                height);
811

812 813 814
static void gtk_widget_add_events_internal (GtkWidget *widget,
                                            GdkDevice *device,
                                            gint       events);
815 816 817 818
static void gtk_widget_set_device_enabled_internal (GtkWidget *widget,
                                                    GdkDevice *device,
                                                    gboolean   recurse,
                                                    gboolean   enabled);
819 820 821 822

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

823
static gboolean event_window_is_still_viewable (GdkEvent *event);
Tim Janik's avatar
Tim Janik committed
824

825 826
static void gtk_widget_update_input_shape (GtkWidget *widget);

Tim Janik's avatar
Tim Janik committed
827
/* --- variables --- */
828
static gint             GtkWidget_private_offset = 0;
829
static gpointer         gtk_widget_parent_class = NULL;
830 831
static guint            widget_signals[LAST_SIGNAL] = { 0 };
static guint            composite_child_stack = 0;
832
GtkTextDirection gtk_default_direction = GTK_TEXT_DIR_LTR;
833
static GParamSpecPool  *style_property_spec_pool = NULL;
834

Tim Janik's avatar
Tim Janik committed
835
static GQuark		quark_property_parser = 0;
836 837
static GQuark		quark_accel_path = 0;
static GQuark		quark_accel_closures = 0;
Tim Janik's avatar
Tim Janik committed
838
static GQuark		quark_event_mask = 0;
839
static GQuark           quark_device_event_mask = 0;
Tim Janik's avatar
Tim Janik committed
840 841
static GQuark		quark_parent_window = 0;
static GQuark		quark_shape_info = 0;
842
static GQuark		quark_input_shape_info = 0;
Tim Janik's avatar
Tim Janik committed
843 844
static GQuark		quark_pango_context = 0;
static GQuark		quark_accessible_object = 0;
845
static GQuark		quark_mnemonic_labels = 0;
Kristian Rietveld's avatar
Kristian Rietveld committed
846 847 848
static GQuark		quark_tooltip_markup = 0;
static GQuark		quark_has_tooltip = 0;
static GQuark		quark_tooltip_window = 0;
849
static GQuark		quark_visual = 0;
850
static GQuark           quark_modifier_style = 0;
851
static GQuark           quark_enabled_devices = 0;
852
static GQuark           quark_size_groups = 0;
853
static GQuark           quark_auto_children = 0;
Matthias Clasen's avatar
Matthias Clasen committed
854
static GQuark           quark_widget_path = 0;
Matthias Clasen's avatar
Matthias Clasen committed
855
static GQuark           quark_action_muxer = 0;
Matthias Clasen's avatar
Matthias Clasen committed
856
static GQuark           quark_font_options = 0;
Matthias Clasen's avatar
Matthias Clasen committed
857
static GQuark           quark_font_map = 0;
Matthias Clasen's avatar
Matthias Clasen committed
858

Tim Janik's avatar
Tim Janik committed
859 860 861 862
GParamSpecPool         *_gtk_widget_child_property_pool = NULL;
GObjectNotifyContext   *_gtk_widget_child_property_notify_context = NULL;

/* --- functions --- */
863 864 865 866 867 868 869 870 871 872
GType
gtk_widget_get_type (void)
{
  static GType widget_type = 0;

  if (G_UNLIKELY (widget_type == 0))
    {
      const GTypeInfo widget_info =
      {
	sizeof (GtkWidgetClass),
873
	gtk_widget_base_class_init,
874 875 876 877 878 879
	(GBaseFinalizeFunc) gtk_widget_base_class_finalize,
	(GClassInitFunc) gtk_widget_class_init,
	NULL,		/* class_finalize */
	NULL,		/* class_init */
	sizeof (GtkWidget),
	0,		/* n_preallocs */
Benjamin Otte's avatar
Benjamin Otte committed
880
	gtk_widget_init,
881 882 883 884 885 886 887 888 889 890
	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
891 892 893 894 895 896 897
      const GInterfaceInfo buildable_info =
      {
	(GInterfaceInitFunc) gtk_widget_buildable_interface_init,
	(GInterfaceFinalizeFunc) NULL,
	NULL /* interface data */
      };

898 899
      widget_type = g_type_register_static (G_TYPE_INITIALLY_UNOWNED, "GtkWidget",
                                            &widget_info, G_TYPE_FLAG_ABSTRACT);
900

901 902
      g_type_add_class_private (widget_type, sizeof (GtkWidgetClassPrivate));

903 904 905
      GtkWidget_private_offset =
        g_type_add_instance_private (widget_type, sizeof (GtkWidgetPrivate));

906 907
      g_type_add_interface_static (widget_type, ATK_TYPE_IMPLEMENTOR,
                                   &accessibility_info) ;
Johan Dahlin's avatar
Johan Dahlin committed
908 909
      g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
                                   &buildable_info) ;
910 911 912 913
    }

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

915 916 917 918 919 920
static inline gpointer
gtk_widget_get_instance_private (GtkWidget *self)
{
  return (G_STRUCT_MEMBER_P (self, GtkWidget_private_offset));
}

921 922 923 924 925
static void
gtk_widget_base_class_init (gpointer g_class)
{
  GtkWidgetClass *klass = g_class;

926
  klass->priv = G_TYPE_CLASS_GET_PRIVATE (g_class, GTK_TYPE_WIDGET, GtkWidgetClassPrivate);
927
  klass->priv->template = NULL;
928 929
}

Tim Janik's avatar
Tim Janik committed
930 931 932