1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * 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.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
20 * file for a list of people on the GTK+ Team. See the ChangeLog
21 * 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
27 #include <stdarg.h>
28 #include <string.h>
29 #include <locale.h>
30 #include <math.h>
31
32 #include <gobject/gvaluecollector.h>
33 #include <gobject/gobjectnotifyqueue.c>
34 #include <cairo-gobject.h>
35
36 #include "gtkcontainer.h"
37 #include "gtkaccelmapprivate.h"
38 #include "gtkaccelgroupprivate.h"
39 #include "gtkclipboard.h"
40 #include "gtkcssstylepropertyprivate.h"
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 "gtkwidget.h"
49 #include "gtkwidgetprivate.h"
50 #include "gtkwindowprivate.h"
51 #include "gtkcontainerprivate.h"
52 #include "gtkbindings.h"
53 #include "gtkprivate.h"
54 #include "gtkaccessible.h"
55 #include "gtktooltipprivate.h"
56 #include "gtkinvisible.h"
57 #include "gtkbuildable.h"
58 #include "gtkbuilderprivate.h"
59 #include "gtksizerequest.h"
60 #include "gtkstylecontextprivate.h"
61 #include "gtkcssprovider.h"
62 #include "gtkcsswidgetnodeprivate.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"
71 #include "gtkwidgetpathprivate.h"
72
73 /* for the use of round() */
74 #include "fallback-c89.c"
75
76 /**
77 * SECTION:gtkwidget
78 * @Short_description: Base class for all widgets
79 * @Title: GtkWidget
80 *
81 * GtkWidget is the base class all widgets in GTK+ derive from. It manages the
82 * widget lifecycle, states and style.
83 *
84 * # Height-for-width Geometry Management # {#geometry-management}
85 *
86 * GTK+ uses a height-for-width (and width-for-height) geometry management
87 * system. Height-for-width means that a widget can change how much
88 * vertical space it needs, depending on the amount of horizontal space
89 * that it is given (and similar for width-for-height). The most common
90 * example is a label that reflows to fill up the available width, wraps
91 * to fewer lines, and therefore needs less height.
92 *
93 * Height-for-width geometry management is implemented in GTK+ by way
94 * of five virtual methods:
95 *
96 * - #GtkWidgetClass.get_request_mode()
97 * - #GtkWidgetClass.get_preferred_width()
98 * - #GtkWidgetClass.get_preferred_height()
99 * - #GtkWidgetClass.get_preferred_height_for_width()
100 * - #GtkWidgetClass.get_preferred_width_for_height()
101 * - #GtkWidgetClass.get_preferred_height_and_baseline_for_width()
102 *
103 * There are some important things to keep in mind when implementing
104 * height-for-width and when using it in container implementations.
105 *
106 * The geometry management system will query a widget hierarchy in
107 * only one orientation at a time. When widgets are initially queried
108 * for their minimum sizes it is generally done in two initial passes
109 * in the #GtkSizeRequestMode chosen by the toplevel.
110 *
111 * For example, when queried in the normal
112 * %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH mode:
113 * First, the default minimum and natural width for each widget
114 * in the interface will be computed using gtk_widget_get_preferred_width().
115 * Because the preferred widths for each container depend on the preferred
116 * widths of their children, this information propagates up the hierarchy,
117 * and finally a minimum and natural width is determined for the entire
118 * toplevel. Next, the toplevel will use the minimum width to query for the
119 * minimum height contextual to that width using
120 * gtk_widget_get_preferred_height_for_width(), which will also be a highly
121 * recursive operation. The minimum height for the minimum width is normally
122 * used to set the minimum size constraint on the toplevel
123 * (unless gtk_window_set_geometry_hints() is explicitly used instead).
124 *
125 * After the toplevel window has initially requested its size in both
126 * dimensions it can go on to allocate itself a reasonable size (or a size
127 * previously specified with gtk_window_set_default_size()). During the
128 * recursive allocation process it’s important to note that request cycles
129 * will be recursively executed while container widgets allocate their children.
130 * Each container widget, once allocated a size, will go on to first share the
131 * space in one orientation among its children and then request each child's
132 * height for its target allocated width or its width for allocated height,
133 * depending. In this way a #GtkWidget will typically be requested its size
134 * a number of times before actually being allocated a size. The size a
135 * widget is finally allocated can of course differ from the size it has
136 * requested. For this reason, #GtkWidget caches a small number of results
137 * to avoid re-querying for the same sizes in one allocation cycle.
138 *
139 * See
140 * [GtkContainer’s geometry management section][container-geometry-management]
141 * to learn more about how height-for-width allocations are performed
142 * by container widgets.
143 *
144 * If a widget does move content around to intelligently use up the
145 * allocated size then it must support the request in both
146 * #GtkSizeRequestModes even if the widget in question only
147 * trades sizes in a single orientation.
148 *
149 * For instance, a #GtkLabel that does height-for-width word wrapping
150 * will not expect to have #GtkWidgetClass.get_preferred_height() called
151 * because that call is specific to a width-for-height request. In this
152 * case the label must return the height required for its own minimum
153 * possible width. By following this rule any widget that handles
154 * height-for-width or width-for-height requests will always be allocated
155 * at least enough space to fit its own content.
156 *
157 * Here are some examples of how a %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH widget
158 * generally deals with width-for-height requests, for #GtkWidgetClass.get_preferred_height()
159 * it will do:
160 *
161 * |[<!-- language="C" -->
162 * static void
163 * foo_widget_get_preferred_height (GtkWidget *widget,
164 * gint *min_height,
165 * gint *nat_height)
166 * {
167 * if (i_am_in_height_for_width_mode)
168 * {
169 * gint min_width, nat_width;
170 *
171 * GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget,
172 * &min_width,
173 * &nat_width);
174 * GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width
175 * (widget,
176 * min_width,
177 * min_height,
178 * nat_height);
179 * }
180 * else
181 * {
182 * ... some widgets do both. For instance, if a GtkLabel is
183 * rotated to 90 degrees it will return the minimum and
184 * natural height for the rotated label here.
185 * }
186 * }
187 * ]|
188 *
189 * And in #GtkWidgetClass.get_preferred_width_for_height() it will simply return
190 * the minimum and natural width:
191 * |[<!-- language="C" -->
192 * static void
193 * foo_widget_get_preferred_width_for_height (GtkWidget *widget,
194 * gint for_height,
195 * gint *min_width,
196 * gint *nat_width)
197 * {
198 * if (i_am_in_height_for_width_mode)
199 * {
200 * GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget,
201 * min_width,
202 * nat_width);
203 * }
204 * else
205 * {
206 * ... again if a widget is sometimes operating in
207 * width-for-height mode (like a rotated GtkLabel) it can go
208 * ahead and do its real width for height calculation here.
209 * }
210 * }
211 * ]|
212 *
213 * Often a widget needs to get its own request during size request or
214 * allocation. For example, when computing height it may need to also
215 * compute width. Or when deciding how to use an allocation, the widget
216 * may need to know its natural size. In these cases, the widget should
217 * be careful to call its virtual methods directly, like this:
218 *
219 * |[<!-- language="C" -->
220 * GTK_WIDGET_GET_CLASS(widget)->get_preferred_width (widget,
221 * &min,
222 * &natural);
223 * ]|
224 *
225 * It will not work to use the wrapper functions, such as
226 * gtk_widget_get_preferred_width() inside your own size request
227 * implementation. These return a request adjusted by #GtkSizeGroup
228 * and by the #GtkWidgetClass.adjust_size_request() virtual method. If a
229 * widget used the wrappers inside its virtual method implementations,
230 * then the adjustments (such as widget margins) would be applied
231 * twice. GTK+ therefore does not allow this and will warn if you try
232 * to do it.
233 *
234 * Of course if you are getting the size request for
235 * another widget, such as a child of a
236 * container, you must use the wrapper APIs.
237 * Otherwise, you would not properly consider widget margins,
238 * #GtkSizeGroup, and so forth.
239 *
240 * Since 3.10 GTK+ also supports baseline vertical alignment of widgets. This
241 * means that widgets are positioned such that the typographical baseline of
242 * widgets in the same row are aligned. This happens if a widget supports baselines,
243 * has a vertical alignment of %GTK_ALIGN_BASELINE, and is inside a container
244 * that supports baselines and has a natural “row” that it aligns to the baseline,
245 * or a baseline assigned to it by the grandparent.
246 *
247 * Baseline alignment support for a widget is done by the #GtkWidgetClass.get_preferred_height_and_baseline_for_width()
248 * virtual function. It allows you to report a baseline in combination with the
249 * minimum and natural height. If there is no baseline you can return -1 to indicate
250 * this. The default implementation of this virtual function calls into the
251 * #GtkWidgetClass.get_preferred_height() and #GtkWidgetClass.get_preferred_height_for_width(),
252 * so if baselines are not supported it doesn’t need to be implemented.
253 *
254 * If a widget ends up baseline aligned it will be allocated all the space in the parent
255 * as if it was %GTK_ALIGN_FILL, but the selected baseline can be found via gtk_widget_get_allocated_baseline().
256 * If this has a value other than -1 you need to align the widget such that the baseline
257 * appears at the position.
258 *
259 * # Style Properties
260 *
261 * #GtkWidget introduces “style
262 * properties” - these are basically object properties that are stored
263 * not on the object, but in the style object associated to the widget. Style
264 * properties are set in [resource files][gtk3-Resource-Files].
265 * This mechanism is used for configuring such things as the location of the
266 * scrollbar arrows through the theme, giving theme authors more control over the
267 * look of applications without the need to write a theme engine in C.
268 *
269 * Use gtk_widget_class_install_style_property() to install style properties for
270 * a widget class, gtk_widget_class_find_style_property() or
271 * gtk_widget_class_list_style_properties() to get information about existing
272 * style properties and gtk_widget_style_get_property(), gtk_widget_style_get() or
273 * gtk_widget_style_get_valist() to obtain the value of a style property.
274 *
275 * # GtkWidget as GtkBuildable
276 *
277 * The GtkWidget implementation of the GtkBuildable interface supports a
278 * custom `<accelerator>` element, which has attributes named ”key”, ”modifiers”
279 * and ”signal” and allows to specify accelerators.
280 *
281 * An example of a UI definition fragment specifying an accelerator:
282 *
283 * |[<!-- language="xml" -->
284 * <object class="GtkButton">
285 * <accelerator key="q" modifiers="GDK_CONTROL_MASK" signal="clicked"/>
286 * </object>
287 * ]|
288 *
289 * In addition to accelerators, GtkWidget also support a custom `<accessible>`
290 * element, which supports actions and relations. Properties on the accessible
291 * implementation of an object can be set by accessing the internal child
292 * “accessible” of a #GtkWidget.
293 *
294 * An example of a UI definition fragment specifying an accessible:
295 *
296 * |[<!-- language="xml" -->
297 * <object class="GtkLabel" id="label1"/>
298 * <property name="label">I am a Label for a Button</property>
299 * </object>
300 * <object class="GtkButton" id="button1">
301 * <accessibility>
302 * <action action_name="click" translatable="yes">Click the button.</action>
303 * <relation target="label1" type="labelled-by"/>
304 * </accessibility>
305 * <child internal-child="accessible">
306 * <object class="AtkObject" id="a11y-button1">
307 * <property name="accessible-name">Clickable Button</property>
308 * </object>
309 * </child>
310 * </object>
311 * ]|
312 *
313 * Finally, GtkWidget allows style information such as style classes to
314 * be associated with widgets, using the custom `<style>` element:
315 *
316 * |[<!-- language="xml" -->
317 * <object class="GtkButton" id="button1">
318 * <style>
319 * <class name="my-special-button-class"/>
320 * <class name="dark-button"/>
321 * </style>
322 * </object>
323 * ]|
324 *
325 * # Building composite widgets from template XML ## {#composite-templates}
326 *
327 * GtkWidget exposes some facilities to automate the procedure
328 * of creating composite widgets using #GtkBuilder interface description
329 * language.
330 *
331 * To create composite widgets with #GtkBuilder XML, one must associate
332 * the interface description with the widget class at class initialization
333 * time using gtk_widget_class_set_template().
334 *
335 * The interface description semantics expected in composite template descriptions
336 * is slightly different from regular #GtkBuilder XML.
337 *
338 * Unlike regular interface descriptions, gtk_widget_class_set_template() will
339 * expect a `<template>` tag as a direct child of the toplevel `<interface>`
340 * tag. The `<template>` tag must specify the “class” attribute which must be
341 * the type name of the widget. Optionally, the “parent” attribute may be
342 * specified to specify the direct parent type of the widget type, this is
343 * ignored by the GtkBuilder but required for Glade to introspect what kind
344 * of properties and internal children exist for a given type when the actual
345 * type does not exist.
346 *
347 * The XML which is contained inside the `<template>` tag behaves as if it were
348 * added to the `<object>` tag defining "widget" itself. You may set properties
349 * on @widget by inserting `<property>` tags into the `<template>` tag, and also
350 * add `<child>` tags to add children and extend "widget" in the normal way you
351 * would with `<object>` tags.
352 *
353 * Additionally, `<object>` tags can also be added before and after the initial
354 * `<template>` tag in the normal way, allowing one to define auxiliary objects
355 * which might be referenced by other widgets declared as children of the
356 * `<template>` tag.
357 *
358 * An example of a GtkBuilder Template Definition:
359 *
360 * |[<!-- language="xml" -->
361 * <interface>
362 * <template class="FooWidget" parent="GtkBox">
363 * <property name="orientation">GTK_ORIENTATION_HORIZONTAL</property>
364 * <property name="spacing">4</property>
365 * <child>
366 * <object class="GtkButton" id="hello_button">
367 * <property name="label">Hello World</property>
368 * <signal name="clicked" handler="hello_button_clicked" object="FooWidget" swapped="yes"/>
369 * </object>
370 * </child>
371 * <child>
372 * <object class="GtkButton" id="goodbye_button">
373 * <property name="label">Goodbye World</property>
374 * </object>
375 * </child>
376 * </template>
377 * </interface>
378 * ]|
379 *
380 * Typically, you'll place the template fragment into a file that is
381 * bundled with your project, using #GResource. In order to load the
382 * template, you need to call gtk_widget_class_set_template_from_resource()
383 * from the class initialization of your #GtkWidget type:
384 *
385 * |[<!-- language="C" -->
386 * static void
387 * foo_widget_class_init (FooWidgetClass *klass)
388 * {
389 * // ...
390 *
391 * gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
392 * "/com/example/ui/foowidget.ui");
393 * }
394 * ]|
395 *
396 * You will also need to call gtk_widget_init_template() from the instance
397 * initialization function:
398 *
399 * |[<!-- language="C" -->
400 * static void
401 * foo_widget_init (FooWidget *self)
402 * {
403 * // ...
404 * gtk_widget_init_template (GTK_WIDGET (self));
405 * }
406 * ]|
407 *
408 * You can access widgets defined in the template using the
409 * gtk_widget_get_template_child() function, but you will typically declare
410 * a pointer in the instance private data structure of your type using the same
411 * name as the widget in the template definition, and call
412 * gtk_widget_class_bind_template_child_private() with that name, e.g.
413 *
414 * |[<!-- language="C" -->
415 * typedef struct {
416 * GtkWidget *hello_button;
417 * GtkWidget *goodbye_button;
418 * } FooWidgetPrivate;
419 *
420 * G_DEFINE_TYPE_WITH_PRIVATE (FooWidget, foo_widget, GTK_TYPE_BOX)
421 *
422 * static void
423 * foo_widget_class_init (FooWidgetClass *klass)
424 * {
425 * // ...
426 * gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
427 * "/com/example/ui/foowidget.ui");
428 * gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass),
429 * FooWidget, hello_button);
430 * gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (klass),
431 * FooWidget, goodbye_button);
432 * }
433 *
434 * static void
435 * foo_widget_init (FooWidget *widget)
436 * {
437 *
438 * }
439 * ]|
440 *
441 * You can also use gtk_widget_class_bind_template_callback() to connect a signal
442 * callback defined in the template with a function visible in the scope of the
443 * class, e.g.
444 *
445 * |[<!-- language="C" -->
446 * // the signal handler has the instance and user data swapped
447 * // because of the swapped="yes" attribute in the template XML
448 * static void
449 * hello_button_clicked (FooWidget *self,
450 * GtkButton *button)
451 * {
452 * g_print ("Hello, world!\n");
453 * }
454 *
455 * static void
456 * foo_widget_class_init (FooWidgetClass *klass)
457 * {
458 * // ...
459 * gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (klass),
460 * "/com/example/ui/foowidget.ui");
461 * gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (klass), hello_button_clicked);
462 * }
463 * ]|
464 */
465
466 #define GTK_STATE_FLAGS_DO_PROPAGATE (GTK_STATE_FLAG_INSENSITIVE|GTK_STATE_FLAG_BACKDROP)
467
468 #define WIDGET_CLASS(w) GTK_WIDGET_GET_CLASS (w)
469
470 typedef struct {
471 gchar *name; /* Name of the template automatic child */
472 gboolean internal_child; /* Whether the automatic widget should be exported as an <internal-child> */
473 gssize offset; /* Instance private data offset where to set the automatic child (or 0) */
474 } AutomaticChildClass;
475
476 typedef struct {
477 gchar *callback_name;
478 GCallback callback_symbol;
479 } CallbackSymbol;
480
481 typedef struct {
482 GBytes *data;
483 GSList *children;
484 GSList *callbacks;
485 GtkBuilderConnectFunc connect_func;
486 gpointer connect_data;
487 GDestroyNotify destroy_notify;
488 } GtkWidgetTemplate;
489
490 typedef struct {
491 GtkEventController *controller;
492 guint grab_notify_id;
493 guint sequence_state_changed_id;
494 } EventControllerData;
495
496 struct _GtkWidgetClassPrivate
497 {
498 GtkWidgetTemplate *template;
499 GType accessible_type;
500 AtkRole accessible_role;
501 const char *css_name;
502 };
503
504 enum {
505 DESTROY,
506 SHOW,
507 HIDE,
508 MAP,
509 UNMAP,
510 REALIZE,
511 UNREALIZE,
512 SIZE_ALLOCATE,
513 STATE_FLAGS_CHANGED,
514 STATE_CHANGED,
515 PARENT_SET,
516 HIERARCHY_CHANGED,
517 STYLE_SET,
518 DIRECTION_CHANGED,
519 GRAB_NOTIFY,
520 CHILD_NOTIFY,
521 DRAW,
522 MNEMONIC_ACTIVATE,
523 GRAB_FOCUS,
524 FOCUS,
525 MOVE_FOCUS,
526 KEYNAV_FAILED,
527 EVENT,
528 EVENT_AFTER,
529 BUTTON_PRESS_EVENT,
530 BUTTON_RELEASE_EVENT,
531 SCROLL_EVENT,
532 MOTION_NOTIFY_EVENT,
533 DELETE_EVENT,
534 DESTROY_EVENT,
535 KEY_PRESS_EVENT,
536 KEY_RELEASE_EVENT,
537 ENTER_NOTIFY_EVENT,
538 LEAVE_NOTIFY_EVENT,
539 CONFIGURE_EVENT,
540 FOCUS_IN_EVENT,
541 FOCUS_OUT_EVENT,
542 MAP_EVENT,
543 UNMAP_EVENT,
544 PROPERTY_NOTIFY_EVENT,
545 SELECTION_CLEAR_EVENT,
546 SELECTION_REQUEST_EVENT,
547 SELECTION_NOTIFY_EVENT,
548 SELECTION_GET,
549 SELECTION_RECEIVED,
550 PROXIMITY_IN_EVENT,
551 PROXIMITY_OUT_EVENT,
552 VISIBILITY_NOTIFY_EVENT,
553 WINDOW_STATE_EVENT,
554 DAMAGE_EVENT,
555 GRAB_BROKEN_EVENT,
556 DRAG_BEGIN,
557 DRAG_END,
558 DRAG_DATA_DELETE,
559 DRAG_LEAVE,
560 DRAG_MOTION,
561 DRAG_DROP,
562 DRAG_DATA_GET,
563 DRAG_DATA_RECEIVED,
564 POPUP_MENU,
565 SHOW_HELP,
566 ACCEL_CLOSURES_CHANGED,
567 SCREEN_CHANGED,
568 CAN_ACTIVATE_ACCEL,
569 COMPOSITED_CHANGED,
570 QUERY_TOOLTIP,
571 DRAG_FAILED,
572 STYLE_UPDATED,
573 TOUCH_EVENT,
574 LAST_SIGNAL
575 };
576
577 enum {
578 PROP_0,
579 PROP_NAME,
580 PROP_PARENT,
581 PROP_WIDTH_REQUEST,
582 PROP_HEIGHT_REQUEST,
583 PROP_VISIBLE,
584 PROP_SENSITIVE,
585 PROP_APP_PAINTABLE,
586 PROP_CAN_FOCUS,
587 PROP_HAS_FOCUS,
588 PROP_IS_FOCUS,
589 PROP_FOCUS_ON_CLICK,
590 PROP_CAN_DEFAULT,
591 PROP_HAS_DEFAULT,
592 PROP_RECEIVES_DEFAULT,
593 PROP_COMPOSITE_CHILD,
594 PROP_STYLE,
595 PROP_EVENTS,
596 PROP_NO_SHOW_ALL,
597 PROP_HAS_TOOLTIP,
598 PROP_TOOLTIP_MARKUP,
599 PROP_TOOLTIP_TEXT,
600 PROP_WINDOW,
601 PROP_OPACITY,
602 PROP_DOUBLE_BUFFERED,
603 PROP_HALIGN,
604 PROP_VALIGN,
605 PROP_MARGIN_LEFT,
606 PROP_MARGIN_RIGHT,
607 PROP_MARGIN_START,
608 PROP_MARGIN_END,
609 PROP_MARGIN_TOP,
610 PROP_MARGIN_BOTTOM,
611 PROP_MARGIN,
612 PROP_HEXPAND,
613 PROP_VEXPAND,
614 PROP_HEXPAND_SET,
615 PROP_VEXPAND_SET,
616 PROP_EXPAND,
617 PROP_SCALE_FACTOR,
618 NUM_PROPERTIES
619 };
620
621 static GParamSpec *widget_props[NUM_PROPERTIES] = { NULL, };
622
623 typedef struct _GtkStateData GtkStateData;
624
625 struct _GtkStateData
626 {
627 guint flags_to_set;
628 guint flags_to_unset;
629
630 gint old_scale_factor;
631 };
632
633 /* --- prototypes --- */
634 static void gtk_widget_base_class_init (gpointer g_class);
635 static void gtk_widget_class_init (GtkWidgetClass *klass);
636 static void gtk_widget_base_class_finalize (GtkWidgetClass *klass);
637 static void gtk_widget_init (GTypeInstance *instance,
638 gpointer g_class);
639 static void gtk_widget_set_property (GObject *object,
640 guint prop_id,
641 const GValue *value,
642 GParamSpec *pspec);
643 static void gtk_widget_get_property (GObject *object,
644 guint prop_id,
645 GValue *value,
646 GParamSpec *pspec);
647 static void gtk_widget_constructed (GObject *object);
648 static void gtk_widget_dispose (GObject *object);
649 static void gtk_widget_real_destroy (GtkWidget *object);
650 static void gtk_widget_finalize (GObject *object);
651 static void gtk_widget_real_show (GtkWidget *widget);
652 static void gtk_widget_real_hide (GtkWidget *widget);
653 static void gtk_widget_real_map (GtkWidget *widget);
654 static void gtk_widget_real_unmap (GtkWidget *widget);
655 static void gtk_widget_real_realize (GtkWidget *widget);
656 static void gtk_widget_real_unrealize (GtkWidget *widget);
657 static void gtk_widget_real_size_allocate (GtkWidget *widget,
658 GtkAllocation *allocation);
659 static void gtk_widget_real_style_set (GtkWidget *widget,
660 GtkStyle *previous_style);
661 static void gtk_widget_real_direction_changed(GtkWidget *widget,
662 GtkTextDirection previous_direction);
663
664 static void gtk_widget_real_grab_focus (GtkWidget *focus_widget);
665 static gboolean gtk_widget_real_query_tooltip (GtkWidget *widget,
666 gint x,
667 gint y,
668 gboolean keyboard_tip,
669 GtkTooltip *tooltip);
670 static void gtk_widget_real_style_updated (GtkWidget *widget);
671 static gboolean gtk_widget_real_show_help (GtkWidget *widget,
672 GtkWidgetHelpType help_type);
673 static gboolean _gtk_widget_run_controllers (GtkWidget *widget,
674 const GdkEvent *event,
675 GtkPropagationPhase phase);
676
677 static void gtk_widget_dispatch_child_properties_changed (GtkWidget *object,
678 guint n_pspecs,
679 GParamSpec **pspecs);
680 static gboolean gtk_widget_real_scroll_event (GtkWidget *widget,
681 GdkEventScroll *event);
682 static gboolean gtk_widget_real_button_event (GtkWidget *widget,
683 GdkEventButton *event);
684 static gboolean gtk_widget_real_motion_event (GtkWidget *widget,
685 GdkEventMotion *event);
686 static gboolean gtk_widget_real_key_press_event (GtkWidget *widget,
687 GdkEventKey *event);
688 static gboolean gtk_widget_real_key_release_event (GtkWidget *widget,
689 GdkEventKey *event);
690 static gboolean gtk_widget_real_focus_in_event (GtkWidget *widget,
691 GdkEventFocus *event);
692 static gboolean gtk_widget_real_focus_out_event (GtkWidget *widget,
693 GdkEventFocus *event);
694 static gboolean gtk_widget_real_touch_event (GtkWidget *widget,
695 GdkEventTouch *event);
696 static gboolean gtk_widget_real_grab_broken_event (GtkWidget *widget,
697 GdkEventGrabBroken *event);
698 static gboolean gtk_widget_real_focus (GtkWidget *widget,
699 GtkDirectionType direction);
700 static void gtk_widget_real_move_focus (GtkWidget *widget,
701 GtkDirectionType direction);
702 static gboolean gtk_widget_real_keynav_failed (GtkWidget *widget,
703 GtkDirectionType direction);
704 #ifdef G_ENABLE_CONSISTENCY_CHECKS
705 static void gtk_widget_verify_invariants (GtkWidget *widget);
706 static void gtk_widget_push_verify_invariants (GtkWidget *widget);
707 static void gtk_widget_pop_verify_invariants (GtkWidget *widget);
708 #else
709 #define gtk_widget_verify_invariants(widget)
710 #define gtk_widget_push_verify_invariants(widget)
711 #define gtk_widget_pop_verify_invariants(widget)
712 #endif
713 static PangoContext* gtk_widget_peek_pango_context (GtkWidget *widget);
714 static void gtk_widget_update_pango_context (GtkWidget *widget);
715 static void gtk_widget_propagate_state (GtkWidget *widget,
716 GtkStateData *data);
717 static void gtk_widget_update_alpha (GtkWidget *widget);
718
719 static gint gtk_widget_event_internal (GtkWidget *widget,
720 GdkEvent *event);
721 static gboolean gtk_widget_real_mnemonic_activate (GtkWidget *widget,
722 gboolean group_cycling);
723 static void gtk_widget_real_get_width (GtkWidget *widget,
724 gint *minimum_size,
725 gint *natural_size);
726 static void gtk_widget_real_get_height (GtkWidget *widget,
727 gint *minimum_size,
728 gint *natural_size);
729 static void gtk_widget_real_get_height_for_width (GtkWidget *widget,
730 gint width,
731 gint *minimum_height,
732 gint *natural_height);
733 static void gtk_widget_real_get_width_for_height (GtkWidget *widget,
734 gint height,
735 gint *minimum_width,
736 gint *natural_width);
737 static void gtk_widget_real_state_flags_changed (GtkWidget *widget,
738 GtkStateFlags old_state);
739 static void gtk_widget_real_queue_draw_region (GtkWidget *widget,
740 const cairo_region_t *region);
741 static AtkObject* gtk_widget_real_get_accessible (GtkWidget *widget);
742 static void gtk_widget_accessible_interface_init (AtkImplementorIface *iface);
743 static AtkObject* gtk_widget_ref_accessible (AtkImplementor *implementor);
744 static void gtk_widget_invalidate_widget_windows (GtkWidget *widget,
745 cairo_region_t *region);
746 static GdkScreen * gtk_widget_get_screen_unchecked (GtkWidget *widget);
747 static gboolean gtk_widget_real_can_activate_accel (GtkWidget *widget,
748 guint signal_id);
749
750 static void gtk_widget_real_set_has_tooltip (GtkWidget *widget,
751 gboolean has_tooltip,
752 gboolean force);
753 static void gtk_widget_buildable_interface_init (GtkBuildableIface *iface);
754 static void gtk_widget_buildable_set_name (GtkBuildable *buildable,
755 const gchar *name);
756 static const gchar * gtk_widget_buildable_get_name (GtkBuildable *buildable);
757 static GObject * gtk_widget_buildable_get_internal_child (GtkBuildable *buildable,
758 GtkBuilder *builder,
759 const gchar *childname);
760 static void gtk_widget_buildable_set_buildable_property (GtkBuildable *buildable,
761 GtkBuilder *builder,
762 const gchar *name,
763 const GValue *value);
764 static gboolean gtk_widget_buildable_custom_tag_start (GtkBuildable *buildable,
765 GtkBuilder *builder,
766 GObject *child,
767 const gchar *tagname,
768 GMarkupParser *parser,
769 gpointer *data);
770 static void gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
771 GtkBuilder *builder,
772 GObject *child,
773 const gchar *tagname,
774 gpointer data);
775 static void gtk_widget_buildable_parser_finished (GtkBuildable *buildable,
776 GtkBuilder *builder);
777
778 static GtkSizeRequestMode gtk_widget_real_get_request_mode (GtkWidget *widget);
779 static void gtk_widget_real_get_width (GtkWidget *widget,
780 gint *minimum_size,
781 gint *natural_size);
782 static void gtk_widget_real_get_height (GtkWidget *widget,
783 gint *minimum_size,
784 gint *natural_size);
785
786 static void gtk_widget_queue_tooltip_query (GtkWidget *widget);
787
788
789 static void gtk_widget_real_adjust_size_request (GtkWidget *widget,
790 GtkOrientation orientation,
791 gint *minimum_size,
792 gint *natural_size);
793 static void gtk_widget_real_adjust_baseline_request (GtkWidget *widget,
794 gint *minimum_baseline,
795 gint *natural_baseline);
796 static void gtk_widget_real_adjust_size_allocation (GtkWidget *widget,
797 GtkOrientation orientation,
798 gint *minimum_size,
799 gint *natural_size,
800 gint *allocated_pos,
801 gint *allocated_size);
802 static void gtk_widget_real_adjust_baseline_allocation (GtkWidget *widget,
803 gint *baseline);
804
805 static void template_data_free (GtkWidgetTemplate *template_data);
806
807 static void gtk_widget_set_usize_internal (GtkWidget *widget,
808 gint width,
809 gint height);
810
811 static void gtk_widget_add_events_internal (GtkWidget *widget,
812 GdkDevice *device,
813 gint events);
814 static void gtk_widget_set_device_enabled_internal (GtkWidget *widget,
815 GdkDevice *device,
816 gboolean recurse,
817 gboolean enabled);
818
819 static void gtk_widget_on_frame_clock_update (GdkFrameClock *frame_clock,
820 GtkWidget *widget);
821
822 static gboolean event_window_is_still_viewable (GdkEvent *event);
823
824 static void gtk_widget_update_input_shape (GtkWidget *widget);
825
826 /* --- variables --- */
827 static gint GtkWidget_private_offset = 0;
828 static gpointer gtk_widget_parent_class = NULL;
829 static guint widget_signals[LAST_SIGNAL] = { 0 };
830 static guint composite_child_stack = 0;
831 GtkTextDirection gtk_default_direction = GTK_TEXT_DIR_LTR;
832 static GParamSpecPool *style_property_spec_pool = NULL;
833
834 static GQuark quark_property_parser = 0;
835 static GQuark quark_accel_path = 0;
836 static GQuark quark_accel_closures = 0;
837 static GQuark quark_event_mask = 0;
838 static GQuark quark_device_event_mask = 0;
839 static GQuark quark_parent_window = 0;
840 static GQuark quark_shape_info = 0;
841 static GQuark quark_input_shape_info = 0;
842 static GQuark quark_pango_context = 0;
843 static GQuark quark_mnemonic_labels = 0;
844 static GQuark quark_tooltip_markup = 0;
845 static GQuark quark_tooltip_window = 0;
846 static GQuark quark_visual = 0;
847 static GQuark quark_modifier_style = 0;
848 static GQuark quark_enabled_devices = 0;
849 static GQuark quark_size_groups = 0;
850 static GQuark quark_auto_children = 0;
851 static GQuark quark_widget_path = 0;
852 static GQuark quark_action_muxer = 0;
853 static GQuark quark_font_options = 0;
854 static GQuark quark_font_map = 0;
855
856 GParamSpecPool *_gtk_widget_child_property_pool = NULL;
857 GObjectNotifyContext *_gtk_widget_child_property_notify_context = NULL;
858
859 /* --- functions --- */
860 GType
gtk_widget_get_type(void)861 gtk_widget_get_type (void)
862 {
863 static GType widget_type = 0;
864
865 if (G_UNLIKELY (widget_type == 0))
866 {
867 const GTypeInfo widget_info =
868 {
869 sizeof (GtkWidgetClass),
870 gtk_widget_base_class_init,
871 (GBaseFinalizeFunc) gtk_widget_base_class_finalize,
872 (GClassInitFunc) gtk_widget_class_init,
873 NULL, /* class_finalize */
874 NULL, /* class_init */
875 sizeof (GtkWidget),
876 0, /* n_preallocs */
877 gtk_widget_init,
878 NULL, /* value_table */
879 };
880
881 const GInterfaceInfo accessibility_info =
882 {
883 (GInterfaceInitFunc) gtk_widget_accessible_interface_init,
884 (GInterfaceFinalizeFunc) NULL,
885 NULL /* interface data */
886 };
887
888 const GInterfaceInfo buildable_info =
889 {
890 (GInterfaceInitFunc) gtk_widget_buildable_interface_init,
891 (GInterfaceFinalizeFunc) NULL,
892 NULL /* interface data */
893 };
894
895 widget_type = g_type_register_static (G_TYPE_INITIALLY_UNOWNED, "GtkWidget",
896 &widget_info, G_TYPE_FLAG_ABSTRACT);
897
898 g_type_add_class_private (widget_type, sizeof (GtkWidgetClassPrivate));
899
900 GtkWidget_private_offset =
901 g_type_add_instance_private (widget_type, sizeof (GtkWidgetPrivate));
902
903 g_type_add_interface_static (widget_type, ATK_TYPE_IMPLEMENTOR,
904 &accessibility_info) ;
905 g_type_add_interface_static (widget_type, GTK_TYPE_BUILDABLE,
906 &buildable_info) ;
907 }
908
909 return widget_type;
910 }
911
912 static inline gpointer
gtk_widget_get_instance_private(GtkWidget * self)913 gtk_widget_get_instance_private (GtkWidget *self)
914 {
915 return (G_STRUCT_MEMBER_P (self, GtkWidget_private_offset));
916 }
917
918 static void
gtk_widget_base_class_init(gpointer g_class)919 gtk_widget_base_class_init (gpointer g_class)
920 {
921 GtkWidgetClass *klass = g_class;
922
923 klass->priv = G_TYPE_CLASS_GET_PRIVATE (g_class, GTK_TYPE_WIDGET, GtkWidgetClassPrivate);
924 klass->priv->template = NULL;
925 }
926
927 static void
child_property_notify_dispatcher(GObject * object,guint n_pspecs,GParamSpec ** pspecs)928 child_property_notify_dispatcher (GObject *object,
929 guint n_pspecs,
930 GParamSpec **pspecs)
931 {
932 GTK_WIDGET_GET_CLASS (object)->dispatch_child_properties_changed (GTK_WIDGET (object), n_pspecs, pspecs);
933 }
934
935 /* We guard against the draw signal callbacks modifying the state of the
936 * cairo context by surrounding it with save/restore.
937 * Maybe we should also cairo_new_path() just to be sure?
938 */
939 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)940 gtk_widget_draw_marshaller (GClosure *closure,
941 GValue *return_value,
942 guint n_param_values,
943 const GValue *param_values,
944 gpointer invocation_hint,
945 gpointer marshal_data)
946 {
947 cairo_t *cr = g_value_get_boxed (¶m_values[1]);
948
949 cairo_save (cr);
950
951 _gtk_marshal_BOOLEAN__BOXED (closure,
952 return_value,
953 n_param_values,
954 param_values,
955 invocation_hint,
956 marshal_data);
957
958
959 cairo_restore (cr);
960 }
961
962 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)963 gtk_widget_draw_marshallerv (GClosure *closure,
964 GValue *return_value,
965 gpointer instance,
966 va_list args,
967 gpointer marshal_data,
968 int n_params,
969 GType *param_types)
970 {
971 cairo_t *cr;
972 va_list args_copy;
973
974 G_VA_COPY (args_copy, args);
975 cr = va_arg (args_copy, gpointer);
976
977 cairo_save (cr);
978
979 _gtk_marshal_BOOLEAN__BOXEDv (closure,
980 return_value,
981 instance,
982 args,
983 marshal_data,
984 n_params,
985 param_types);
986
987
988 cairo_restore (cr);
989
990 va_end (args_copy);
991 }
992
993 static void
gtk_widget_class_init(GtkWidgetClass * klass)994 gtk_widget_class_init (GtkWidgetClass *klass)
995 {
996 static GObjectNotifyContext cpn_context = { 0, NULL, NULL };
997 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
998 GtkBindingSet *binding_set;
999
1000 g_type_class_adjust_private_offset (klass, &GtkWidget_private_offset);
1001 gtk_widget_parent_class = g_type_class_peek_parent (klass);
1002
1003 quark_property_parser = g_quark_from_static_string ("gtk-rc-property-parser");
1004 quark_accel_path = g_quark_from_static_string ("gtk-accel-path");
1005 quark_accel_closures = g_quark_from_static_string ("gtk-accel-closures");
1006 quark_event_mask = g_quark_from_static_string ("gtk-event-mask");
1007 quark_device_event_mask = g_quark_from_static_string ("gtk-device-event-mask");
1008 quark_parent_window = g_quark_from_static_string ("gtk-parent-window");
1009 quark_shape_info = g_quark_from_static_string ("gtk-shape-info");
1010 quark_input_shape_info = g_quark_from_static_string ("gtk-input-shape-info");
1011 quark_pango_context = g_quark_from_static_string ("gtk-pango-context");
1012 quark_mnemonic_labels = g_quark_from_static_string ("gtk-mnemonic-labels");
1013 quark_tooltip_markup = g_quark_from_static_string ("gtk-tooltip-markup");
1014 quark_tooltip_window = g_quark_from_static_string ("gtk-tooltip-window");
1015 quark_visual = g_quark_from_static_string ("gtk-widget-visual");
1016 quark_modifier_style = g_quark_from_static_string ("gtk-widget-modifier-style");
1017 quark_enabled_devices = g_quark_from_static_string ("gtk-widget-enabled-devices");
1018 quark_size_groups = g_quark_from_static_string ("gtk-widget-size-groups");
1019 quark_auto_children = g_quark_from_static_string ("gtk-widget-auto-children");
1020 quark_widget_path = g_quark_from_static_string ("gtk-widget-path");
1021 quark_action_muxer = g_quark_from_static_string ("gtk-widget-action-muxer");
1022 quark_font_options = g_quark_from_static_string ("gtk-widget-font-options");
1023 quark_font_map = g_quark_from_static_string ("gtk-widget-font-map");
1024
1025 style_property_spec_pool = g_param_spec_pool_new (FALSE);
1026 _gtk_widget_child_property_pool = g_param_spec_pool_new (TRUE);
1027 cpn_context.quark_notify_queue = g_quark_from_static_string ("GtkWidget-child-property-notify-queue");
1028 cpn_context.dispatcher = child_property_notify_dispatcher;
1029 _gtk_widget_child_property_notify_context = &cpn_context;
1030
1031 gobject_class->constructed = gtk_widget_constructed;
1032 gobject_class->dispose = gtk_widget_dispose;
1033 gobject_class->finalize = gtk_widget_finalize;
1034 gobject_class->set_property = gtk_widget_set_property;
1035 gobject_class->get_property = gtk_widget_get_property;
1036
1037 klass->destroy = gtk_widget_real_destroy;
1038
1039 klass->activate_signal = 0;
1040 klass->dispatch_child_properties_changed = gtk_widget_dispatch_child_properties_changed;
1041 klass->show = gtk_widget_real_show;
1042 klass->show_all = gtk_widget_show;
1043 klass->hide = gtk_widget_real_hide;
1044 klass->map = gtk_widget_real_map;
1045 klass->unmap = gtk_widget_real_unmap;
1046 klass->realize = gtk_widget_real_realize;
1047 klass->unrealize = gtk_widget_real_unrealize;
1048 klass->size_allocate = gtk_widget_real_size_allocate;
1049 klass->get_request_mode = gtk_widget_real_get_request_mode;
1050 klass->get_preferred_width = gtk_widget_real_get_width;
1051 klass->get_preferred_height = gtk_widget_real_get_height;
1052 klass->get_preferred_width_for_height = gtk_widget_real_get_width_for_height;
1053 klass->get_preferred_height_for_width = gtk_widget_real_get_height_for_width;
1054 klass->get_preferred_height_and_baseline_for_width = NULL;
1055 klass->state_changed = NULL;
1056 klass->state_flags_changed = gtk_widget_real_state_flags_changed;
1057 klass->parent_set = NULL;
1058 klass->hierarchy_changed = NULL;
1059 klass->style_set = gtk_widget_real_style_set;
1060 klass->direction_changed = gtk_widget_real_direction_changed;
1061 klass->grab_notify = NULL;
1062 klass->child_notify = NULL;
1063 klass->draw = NULL;
1064 klass->mnemonic_activate = gtk_widget_real_mnemonic_activate;
1065 klass->grab_focus = gtk_widget_real_grab_focus;
1066 klass->focus = gtk_widget_real_focus;
1067 klass->move_focus = gtk_widget_real_move_focus;
1068 klass->keynav_failed = gtk_widget_real_keynav_failed;
1069 klass->event = NULL;
1070 klass->scroll_event = gtk_widget_real_scroll_event;
1071 klass->button_press_event = gtk_widget_real_button_event;
1072 klass->button_release_event = gtk_widget_real_button_event;
1073 klass->motion_notify_event = gtk_widget_real_motion_event;
1074 klass->touch_event = gtk_widget_real_touch_event;
1075 klass->delete_event = NULL;
1076 klass->destroy_event = NULL;
1077 klass->key_press_event = gtk_widget_real_key_press_event;
1078 klass->key_release_event = gtk_widget_real_key_release_event;
1079 klass->enter_notify_event = NULL;
1080 klass->leave_notify_event = NULL;
1081 klass->configure_event = NULL;
1082 klass->focus_in_event = gtk_widget_real_focus_in_event;
1083 klass->focus_out_event = gtk_widget_real_focus_out_event;
1084 klass->map_event = NULL;
1085 klass->unmap_event = NULL;
1086 klass->window_state_event = NULL;
1087 klass->property_notify_event = _gtk_selection_property_notify;
1088 klass->selection_clear_event = _gtk_selection_clear;
1089 klass->selection_request_event = _gtk_selection_request;
1090 klass->selection_notify_event = _gtk_selection_notify;
1091 klass->selection_received = NULL;
1092 klass->proximity_in_event = NULL;
1093 klass->proximity_out_event = NULL;
1094 klass->drag_begin = NULL;
1095 klass->drag_end = NULL;
1096 klass->drag_data_delete = NULL;
1097 klass->drag_leave = NULL;
1098 klass->drag_motion = NULL;
1099 klass->drag_drop = NULL;
1100 klass->drag_data_received = NULL;
1101 klass->screen_changed = NULL;
1102 klass->can_activate_accel = gtk_widget_real_can_activate_accel;
1103 klass->grab_broken_event = gtk_widget_real_grab_broken_event;
1104 klass->query_tooltip = gtk_widget_real_query_tooltip;
1105 klass->style_updated = gtk_widget_real_style_updated;
1106
1107 klass->show_help = gtk_widget_real_show_help;
1108
1109 /* Accessibility support */
1110 klass->priv->accessible_type = GTK_TYPE_ACCESSIBLE;
1111 klass->priv->accessible_role = ATK_ROLE_INVALID;
1112 klass->get_accessible = gtk_widget_real_get_accessible;
1113
1114 klass->adjust_size_request = gtk_widget_real_adjust_size_request;
1115 klass->adjust_baseline_request = gtk_widget_real_adjust_baseline_request;
1116 klass->adjust_size_allocation = gtk_widget_real_adjust_size_allocation;
1117 klass->adjust_baseline_allocation = gtk_widget_real_adjust_baseline_allocation;
1118 klass->queue_draw_region = gtk_widget_real_queue_draw_region;
1119
1120 widget_props[PROP_NAME] =
1121 g_param_spec_string ("name",
1122 P_("Widget name"),
1123 P_("The name of the widget"),
1124 NULL,
1125 GTK_PARAM_READWRITE);
1126
1127 widget_props[PROP_PARENT] =
1128 g_param_spec_object ("parent",
1129 P_("Parent widget"),
1130 P_("The parent widget of this widget. Must be a Container widget"),
1131 GTK_TYPE_CONTAINER,
1132 GTK_PARAM_READWRITE);
1133
1134 widget_props[PROP_WIDTH_REQUEST] =
1135 g_param_spec_int ("width-request",
1136 P_("Width request"),
1137 P_("Override for width request of the widget, or -1 if natural request should be used"),
1138 -1, G_MAXINT,
1139 -1,
1140 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1141
1142 widget_props[PROP_HEIGHT_REQUEST] =
1143 g_param_spec_int ("height-request",
1144 P_("Height request"),
1145 P_("Override for height request of the widget, or -1 if natural request should be used"),
1146 -1, G_MAXINT,
1147 -1,
1148 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1149
1150 widget_props[PROP_VISIBLE] =
1151 g_param_spec_boolean ("visible",
1152 P_("Visible"),
1153 P_("Whether the widget is visible"),
1154 FALSE,
1155 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1156
1157 widget_props[PROP_SENSITIVE] =
1158 g_param_spec_boolean ("sensitive",
1159 P_("Sensitive"),
1160 P_("Whether the widget responds to input"),
1161 TRUE,
1162 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1163
1164 widget_props[PROP_APP_PAINTABLE] =
1165 g_param_spec_boolean ("app-paintable",
1166 P_("Application paintable"),
1167 P_("Whether the application will paint directly on the widget"),
1168 FALSE,
1169 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1170
1171 widget_props[PROP_CAN_FOCUS] =
1172 g_param_spec_boolean ("can-focus",
1173 P_("Can focus"),
1174 P_("Whether the widget can accept the input focus"),
1175 FALSE,
1176 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1177
1178 widget_props[PROP_HAS_FOCUS] =
1179 g_param_spec_boolean ("has-focus",
1180 P_("Has focus"),
1181 P_("Whether the widget has the input focus"),
1182 FALSE,
1183 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1184
1185 widget_props[PROP_IS_FOCUS] =
1186 g_param_spec_boolean ("is-focus",
1187 P_("Is focus"),
1188 P_("Whether the widget is the focus widget within the toplevel"),
1189 FALSE,
1190 GTK_PARAM_READWRITE);
1191
1192 /**
1193 * GtkWidget:focus-on-click:
1194 *
1195 * Whether the widget should grab focus when it is clicked with the mouse.
1196 *
1197 * This property is only relevant for widgets that can take focus.
1198 *
1199 * Before 3.20, several widgets (GtkButton, GtkFileChooserButton,
1200 * GtkComboBox) implemented this property individually.
1201 *
1202 * Since: 3.20
1203 */
1204 widget_props[PROP_FOCUS_ON_CLICK] =
1205 g_param_spec_boolean ("focus-on-click",
1206 P_("Focus on click"),
1207 P_("Whether the widget should grab focus when it is clicked with the mouse"),
1208 TRUE,
1209 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1210
1211 widget_props[PROP_CAN_DEFAULT] =
1212 g_param_spec_boolean ("can-default",
1213 P_("Can default"),
1214 P_("Whether the widget can be the default widget"),
1215 FALSE,
1216 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1217
1218 widget_props[PROP_HAS_DEFAULT] =
1219 g_param_spec_boolean ("has-default",
1220 P_("Has default"),
1221 P_("Whether the widget is the default widget"),
1222 FALSE,
1223 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1224
1225 widget_props[PROP_RECEIVES_DEFAULT] =
1226 g_param_spec_boolean ("receives-default",
1227 P_("Receives default"),
1228 P_("If TRUE, the widget will receive the default action when it is focused"),
1229 FALSE,
1230 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1231
1232 widget_props[PROP_COMPOSITE_CHILD] =
1233 g_param_spec_boolean ("composite-child",
1234 P_("Composite child"),
1235 P_("Whether the widget is part of a composite widget"),
1236 FALSE,
1237 GTK_PARAM_READABLE);
1238
1239 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1240
1241 /**
1242 * GtkWidget:style:
1243 *
1244 * The style of the widget, which contains information about how it will look (colors, etc).
1245 *
1246 * Deprecated: Use #GtkStyleContext instead
1247 */
1248 widget_props[PROP_STYLE] =
1249 g_param_spec_object ("style",
1250 P_("Style"),
1251 P_("The style of the widget, which contains information about how it will look (colors etc)"),
1252 GTK_TYPE_STYLE,
1253 GTK_PARAM_READWRITE|G_PARAM_DEPRECATED);
1254
1255 G_GNUC_END_IGNORE_DEPRECATIONS
1256
1257 widget_props[PROP_EVENTS] =
1258 g_param_spec_flags ("events",
1259 P_("Events"),
1260 P_("The event mask that decides what kind of GdkEvents this widget gets"),
1261 GDK_TYPE_EVENT_MASK,
1262 GDK_STRUCTURE_MASK,
1263 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1264
1265 widget_props[PROP_NO_SHOW_ALL] =
1266 g_param_spec_boolean ("no-show-all",
1267 P_("No show all"),
1268 P_("Whether gtk_widget_show_all() should not affect this widget"),
1269 FALSE,
1270 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1271
1272 /**
1273 * GtkWidget:has-tooltip:
1274 *
1275 * Enables or disables the emission of #GtkWidget::query-tooltip on @widget.
1276 * A value of %TRUE indicates that @widget can have a tooltip, in this case
1277 * the widget will be queried using #GtkWidget::query-tooltip to determine
1278 * whether it will provide a tooltip or not.
1279 *
1280 * Note that setting this property to %TRUE for the first time will change
1281 * the event masks of the GdkWindows of this widget to include leave-notify
1282 * and motion-notify events. This cannot and will not be undone when the
1283 * property is set to %FALSE again.
1284 *
1285 * Since: 2.12
1286 */
1287 widget_props[PROP_HAS_TOOLTIP] =
1288 g_param_spec_boolean ("has-tooltip",
1289 P_("Has tooltip"),
1290 P_("Whether this widget has a tooltip"),
1291 FALSE,
1292 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1293
1294 /**
1295 * GtkWidget:tooltip-text:
1296 *
1297 * Sets the text of tooltip to be the given string.
1298 *
1299 * Also see gtk_tooltip_set_text().
1300 *
1301 * This is a convenience property which will take care of getting the
1302 * tooltip shown if the given string is not %NULL: #GtkWidget:has-tooltip
1303 * will automatically be set to %TRUE and there will be taken care of
1304 * #GtkWidget::query-tooltip in the default signal handler.
1305 *
1306 * Note that if both #GtkWidget:tooltip-text and #GtkWidget:tooltip-markup
1307 * are set, the last one wins.
1308 *
1309 * Since: 2.12
1310 */
1311 widget_props[PROP_TOOLTIP_TEXT] =
1312 g_param_spec_string ("tooltip-text",
1313 P_("Tooltip Text"),
1314 P_("The contents of the tooltip for this widget"),
1315 NULL,
1316 GTK_PARAM_READWRITE);
1317
1318 /**
1319 * GtkWidget:tooltip-markup:
1320 *
1321 * Sets the text of tooltip to be the given string, which is marked up
1322 * with the [Pango text markup language][PangoMarkupFormat].
1323 * Also see gtk_tooltip_set_markup().
1324 *
1325 * This is a convenience property which will take care of getting the
1326 * tooltip shown if the given string is not %NULL: #GtkWidget:has-tooltip
1327 * will automatically be set to %TRUE and there will be taken care of
1328 * #GtkWidget::query-tooltip in the default signal handler.
1329 *
1330 * Note that if both #GtkWidget:tooltip-text and #GtkWidget:tooltip-markup
1331 * are set, the last one wins.
1332 *
1333 * Since: 2.12
1334 */
1335 widget_props[PROP_TOOLTIP_MARKUP] =
1336 g_param_spec_string ("tooltip-markup",
1337 P_("Tooltip markup"),
1338 P_("The contents of the tooltip for this widget"),
1339 NULL,
1340 GTK_PARAM_READWRITE);
1341
1342 /**
1343 * GtkWidget:window:
1344 *
1345 * The widget's window if it is realized, %NULL otherwise.
1346 *
1347 * Since: 2.14
1348 */
1349 widget_props[PROP_WINDOW] =
1350 g_param_spec_object ("window",
1351 P_("Window"),
1352 P_("The widget's window if it is realized"),
1353 GDK_TYPE_WINDOW,
1354 GTK_PARAM_READABLE);
1355
1356 /**
1357 * GtkWidget:double-buffered:
1358 *
1359 * Whether the widget is double buffered.
1360 *
1361 * Since: 2.18
1362 *
1363 * Deprecated: 3.14: Widgets should not use this property.
1364 */
1365 widget_props[PROP_DOUBLE_BUFFERED] =
1366 g_param_spec_boolean ("double-buffered",
1367 P_("Double Buffered"),
1368 P_("Whether the widget is double buffered"),
1369 TRUE,
1370 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_DEPRECATED);
1371
1372 /**
1373 * GtkWidget:halign:
1374 *
1375 * How to distribute horizontal space if widget gets extra space, see #GtkAlign
1376 *
1377 * Since: 3.0
1378 */
1379 widget_props[PROP_HALIGN] =
1380 g_param_spec_enum ("halign",
1381 P_("Horizontal Alignment"),
1382 P_("How to position in extra horizontal space"),
1383 GTK_TYPE_ALIGN,
1384 GTK_ALIGN_FILL,
1385 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1386
1387 /**
1388 * GtkWidget:valign:
1389 *
1390 * How to distribute vertical space if widget gets extra space, see #GtkAlign
1391 *
1392 * Since: 3.0
1393 */
1394 widget_props[PROP_VALIGN] =
1395 g_param_spec_enum ("valign",
1396 P_("Vertical Alignment"),
1397 P_("How to position in extra vertical space"),
1398 GTK_TYPE_ALIGN,
1399 GTK_ALIGN_FILL,
1400 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1401
1402 /**
1403 * GtkWidget:margin-left:
1404 *
1405 * Margin on left side of widget.
1406 *
1407 * This property adds margin outside of the widget's normal size
1408 * request, the margin will be added in addition to the size from
1409 * gtk_widget_set_size_request() for example.
1410 *
1411 * Deprecated: 3.12: Use #GtkWidget:margin-start instead.
1412 *
1413 * Since: 3.0
1414 */
1415 widget_props[PROP_MARGIN_LEFT] =
1416 g_param_spec_int ("margin-left",
1417 P_("Margin on Left"),
1418 P_("Pixels of extra space on the left side"),
1419 0, G_MAXINT16,
1420 0,
1421 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_DEPRECATED);
1422
1423 /**
1424 * GtkWidget:margin-right:
1425 *
1426 * Margin on right side of widget.
1427 *
1428 * This property adds margin outside of the widget's normal size
1429 * request, the margin will be added in addition to the size from
1430 * gtk_widget_set_size_request() for example.
1431 *
1432 * Deprecated: 3.12: Use #GtkWidget:margin-end instead.
1433 *
1434 * Since: 3.0
1435 */
1436 widget_props[PROP_MARGIN_RIGHT] =
1437 g_param_spec_int ("margin-right",
1438 P_("Margin on Right"),
1439 P_("Pixels of extra space on the right side"),
1440 0, G_MAXINT16,
1441 0,
1442 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_DEPRECATED);
1443
1444 /**
1445 * GtkWidget:margin-start:
1446 *
1447 * Margin on start of widget, horizontally. This property supports
1448 * left-to-right and right-to-left text directions.
1449 *
1450 * This property adds margin outside of the widget's normal size
1451 * request, the margin will be added in addition to the size from
1452 * gtk_widget_set_size_request() for example.
1453 *
1454 * Since: 3.12
1455 */
1456 widget_props[PROP_MARGIN_START] =
1457 g_param_spec_int ("margin-start",
1458 P_("Margin on Start"),
1459 P_("Pixels of extra space on the start"),
1460 0, G_MAXINT16,
1461 0,
1462 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1463
1464 /**
1465 * GtkWidget:margin-end:
1466 *
1467 * Margin on end of widget, horizontally. This property supports
1468 * left-to-right and right-to-left text directions.
1469 *
1470 * This property adds margin outside of the widget's normal size
1471 * request, the margin will be added in addition to the size from
1472 * gtk_widget_set_size_request() for example.
1473 *
1474 * Since: 3.12
1475 */
1476 widget_props[PROP_MARGIN_END] =
1477 g_param_spec_int ("margin-end",
1478 P_("Margin on End"),
1479 P_("Pixels of extra space on the end"),
1480 0, G_MAXINT16,
1481 0,
1482 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1483
1484 /**
1485 * GtkWidget:margin-top:
1486 *
1487 * Margin on top side of widget.
1488 *
1489 * This property adds margin outside of the widget's normal size
1490 * request, the margin will be added in addition to the size from
1491 * gtk_widget_set_size_request() for example.
1492 *
1493 * Since: 3.0
1494 */
1495 widget_props[PROP_MARGIN_TOP] =
1496 g_param_spec_int ("margin-top",
1497 P_("Margin on Top"),
1498 P_("Pixels of extra space on the top side"),
1499 0, G_MAXINT16,
1500 0,
1501 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1502
1503 /**
1504 * GtkWidget:margin-bottom:
1505 *
1506 * Margin on bottom side of widget.
1507 *
1508 * This property adds margin outside of the widget's normal size
1509 * request, the margin will be added in addition to the size from
1510 * gtk_widget_set_size_request() for example.
1511 *
1512 * Since: 3.0
1513 */
1514 widget_props[PROP_MARGIN_BOTTOM] =
1515 g_param_spec_int ("margin-bottom",
1516 P_("Margin on Bottom"),
1517 P_("Pixels of extra space on the bottom side"),
1518 0, G_MAXINT16,
1519 0,
1520 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1521
1522 /**
1523 * GtkWidget:margin:
1524 *
1525 * Sets all four sides' margin at once. If read, returns max
1526 * margin on any side.
1527 *
1528 * Since: 3.0
1529 */
1530 widget_props[PROP_MARGIN] =
1531 g_param_spec_int ("margin",
1532 P_("All Margins"),
1533 P_("Pixels of extra space on all four sides"),
1534 0, G_MAXINT16,
1535 0,
1536 GTK_PARAM_READWRITE);
1537
1538 /**
1539 * GtkWidget:hexpand:
1540 *
1541 * Whether to expand horizontally. See gtk_widget_set_hexpand().
1542 *
1543 * Since: 3.0
1544 */
1545 widget_props[PROP_HEXPAND] =
1546 g_param_spec_boolean ("hexpand",
1547 P_("Horizontal Expand"),
1548 P_("Whether widget wants more horizontal space"),
1549 FALSE,
1550 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1551
1552 /**
1553 * GtkWidget:hexpand-set:
1554 *
1555 * Whether to use the #GtkWidget:hexpand property. See gtk_widget_get_hexpand_set().
1556 *
1557 * Since: 3.0
1558 */
1559 widget_props[PROP_HEXPAND_SET] =
1560 g_param_spec_boolean ("hexpand-set",
1561 P_("Horizontal Expand Set"),
1562 P_("Whether to use the hexpand property"),
1563 FALSE,
1564 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1565
1566 /**
1567 * GtkWidget:vexpand:
1568 *
1569 * Whether to expand vertically. See gtk_widget_set_vexpand().
1570 *
1571 * Since: 3.0
1572 */
1573 widget_props[PROP_VEXPAND] =
1574 g_param_spec_boolean ("vexpand",
1575 P_("Vertical Expand"),
1576 P_("Whether widget wants more vertical space"),
1577 FALSE,
1578 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1579
1580 /**
1581 * GtkWidget:vexpand-set:
1582 *
1583 * Whether to use the #GtkWidget:vexpand property. See gtk_widget_get_vexpand_set().
1584 *
1585 * Since: 3.0
1586 */
1587 widget_props[PROP_VEXPAND_SET] =
1588 g_param_spec_boolean ("vexpand-set",
1589 P_("Vertical Expand Set"),
1590 P_("Whether to use the vexpand property"),
1591 FALSE,
1592 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1593
1594 /**
1595 * GtkWidget:expand:
1596 *
1597 * Whether to expand in both directions. Setting this sets both #GtkWidget:hexpand and #GtkWidget:vexpand
1598 *
1599 * Since: 3.0
1600 */
1601 widget_props[PROP_EXPAND] =
1602 g_param_spec_boolean ("expand",
1603 P_("Expand Both"),
1604 P_("Whether widget wants to expand in both directions"),
1605 FALSE,
1606 GTK_PARAM_READWRITE);
1607
1608 /**
1609 * GtkWidget:opacity:
1610 *
1611 * The requested opacity of the widget. See gtk_widget_set_opacity() for
1612 * more details about window opacity.
1613 *
1614 * Before 3.8 this was only available in GtkWindow
1615 *
1616 * Since: 3.8
1617 */
1618 widget_props[PROP_OPACITY] =
1619 g_param_spec_double ("opacity",
1620 P_("Opacity for Widget"),
1621 P_("The opacity of the widget, from 0 to 1"),
1622 0.0, 1.0,
1623 1.0,
1624 GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY);
1625
1626 /**
1627 * GtkWidget:scale-factor:
1628 *
1629 * The scale factor of the widget. See gtk_widget_get_scale_factor() for
1630 * more details about widget scaling.
1631 *
1632 * Since: 3.10
1633 */
1634 widget_props[PROP_SCALE_FACTOR] =
1635 g_param_spec_int ("scale-factor",
1636 P_("Scale factor"),
1637 P_("The scaling factor of the window"),
1638 1, G_MAXINT,
1639 1,
1640 GTK_PARAM_READABLE);
1641
1642 g_object_class_install_properties (gobject_class, NUM_PROPERTIES, widget_props);
1643
1644 /**
1645 * GtkWidget::destroy:
1646 * @object: the object which received the signal
1647 *
1648 * Signals that all holders of a reference to the widget should release
1649 * the reference that they hold. May result in finalization of the widget
1650 * if all references are released.
1651 *
1652 * This signal is not suitable for saving widget state.
1653 */
1654 widget_signals[DESTROY] =
1655 g_signal_new (I_("destroy"),
1656 G_TYPE_FROM_CLASS (gobject_class),
1657 G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
1658 G_STRUCT_OFFSET (GtkWidgetClass, destroy),
1659 NULL, NULL,
1660 NULL,
1661 G_TYPE_NONE, 0);
1662
1663 /**
1664 * GtkWidget::show:
1665 * @widget: the object which received the signal.
1666 *
1667 * The ::show signal is emitted when @widget is shown, for example with
1668 * gtk_widget_show().
1669 */
1670 widget_signals[SHOW] =
1671 g_signal_new (I_("show"),
1672 G_TYPE_FROM_CLASS (gobject_class),
1673 G_SIGNAL_RUN_FIRST,
1674 G_STRUCT_OFFSET (GtkWidgetClass, show),
1675 NULL, NULL,
1676 NULL,
1677 G_TYPE_NONE, 0);
1678
1679 /**
1680 * GtkWidget::hide:
1681 * @widget: the object which received the signal.
1682 *
1683 * The ::hide signal is emitted when @widget is hidden, for example with
1684 * gtk_widget_hide().
1685 */
1686 widget_signals[HIDE] =
1687 g_signal_new (I_("hide"),
1688 G_TYPE_FROM_CLASS (gobject_class),
1689 G_SIGNAL_RUN_FIRST,
1690 G_STRUCT_OFFSET (GtkWidgetClass, hide),
1691 NULL, NULL,
1692 NULL,
1693 G_TYPE_NONE, 0);
1694
1695 /**
1696 * GtkWidget::map:
1697 * @widget: the object which received the signal.
1698 *
1699 * The ::map signal is emitted when @widget is going to be mapped, that is
1700 * when the widget is visible (which is controlled with
1701 * gtk_widget_set_visible()) and all its parents up to the toplevel widget
1702 * are also visible. Once the map has occurred, #GtkWidget::map-event will
1703 * be emitted.
1704 *
1705 * The ::map signal can be used to determine whether a widget will be drawn,
1706 * for instance it can resume an animation that was stopped during the
1707 * emission of #GtkWidget::unmap.
1708 */
1709 widget_signals[MAP] =
1710 g_signal_new (I_("map"),
1711 G_TYPE_FROM_CLASS (gobject_class),
1712 G_SIGNAL_RUN_FIRST,
1713 G_STRUCT_OFFSET (GtkWidgetClass, map),
1714 NULL, NULL,
1715 NULL,
1716 G_TYPE_NONE, 0);
1717
1718 /**
1719 * GtkWidget::unmap:
1720 * @widget: the object which received the signal.
1721 *
1722 * The ::unmap signal is emitted when @widget is going to be unmapped, which
1723 * means that either it or any of its parents up to the toplevel widget have
1724 * been set as hidden.
1725 *
1726 * As ::unmap indicates that a widget will not be shown any longer, it can be
1727 * used to, for example, stop an animation on the widget.
1728 */
1729 widget_signals[UNMAP] =
1730 g_signal_new (I_("unmap"),
1731 G_TYPE_FROM_CLASS (gobject_class),
1732 G_SIGNAL_RUN_FIRST,
1733 G_STRUCT_OFFSET (GtkWidgetClass, unmap),
1734 NULL, NULL,
1735 NULL,
1736 G_TYPE_NONE, 0);
1737
1738 /**
1739 * GtkWidget::realize:
1740 * @widget: the object which received the signal.
1741 *
1742 * The ::realize signal is emitted when @widget is associated with a
1743 * #GdkWindow, which means that gtk_widget_realize() has been called or the
1744 * widget has been mapped (that is, it is going to be drawn).
1745 */
1746 widget_signals[REALIZE] =
1747 g_signal_new (I_("realize"),
1748 G_TYPE_FROM_CLASS (gobject_class),
1749 G_SIGNAL_RUN_FIRST,
1750 G_STRUCT_OFFSET (GtkWidgetClass, realize),
1751 NULL, NULL,
1752 NULL,
1753 G_TYPE_NONE, 0);
1754
1755 /**
1756 * GtkWidget::unrealize:
1757 * @widget: the object which received the signal.
1758 *
1759 * The ::unrealize signal is emitted when the #GdkWindow associated with
1760 * @widget is destroyed, which means that gtk_widget_unrealize() has been
1761 * called or the widget has been unmapped (that is, it is going to be
1762 * hidden).
1763 */
1764 widget_signals[UNREALIZE] =
1765 g_signal_new (I_("unrealize"),
1766 G_TYPE_FROM_CLASS (gobject_class),
1767 G_SIGNAL_RUN_LAST,
1768 G_STRUCT_OFFSET (GtkWidgetClass, unrealize),
1769 NULL, NULL,
1770 NULL,
1771 G_TYPE_NONE, 0);
1772
1773 /**
1774 * GtkWidget::size-allocate:
1775 * @widget: the object which received the signal.
1776 * @allocation: (type Gtk.Allocation): the region which has been
1777 * allocated to the widget.
1778 */
1779 widget_signals[SIZE_ALLOCATE] =
1780 g_signal_new (I_("size-allocate"),
1781 G_TYPE_FROM_CLASS (gobject_class),
1782 G_SIGNAL_RUN_FIRST,
1783 G_STRUCT_OFFSET (GtkWidgetClass, size_allocate),
1784 NULL, NULL,
1785 NULL,
1786 G_TYPE_NONE, 1,
1787 GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
1788
1789 /**
1790 * GtkWidget::state-changed:
1791 * @widget: the object which received the signal.
1792 * @state: the previous state
1793 *
1794 * The ::state-changed signal is emitted when the widget state changes.
1795 * See gtk_widget_get_state().
1796 *
1797 * Deprecated: 3.0: Use #GtkWidget::state-flags-changed instead.
1798 */
1799 widget_signals[STATE_CHANGED] =
1800 g_signal_new (I_("state-changed"),
1801 G_TYPE_FROM_CLASS (gobject_class),
1802 G_SIGNAL_RUN_FIRST | G_SIGNAL_DEPRECATED,
1803 G_STRUCT_OFFSET (GtkWidgetClass, state_changed),
1804 NULL, NULL,
1805 NULL,
1806 G_TYPE_NONE, 1,
1807 GTK_TYPE_STATE_TYPE);
1808
1809 /**
1810 * GtkWidget::state-flags-changed:
1811 * @widget: the object which received the signal.
1812 * @flags: The previous state flags.
1813 *
1814 * The ::state-flags-changed signal is emitted when the widget state
1815 * changes, see gtk_widget_get_state_flags().
1816 *
1817 * Since: 3.0
1818 */
1819 widget_signals[STATE_FLAGS_CHANGED] =
1820 g_signal_new (I_("state-flags-changed"),
1821 G_TYPE_FROM_CLASS (gobject_class),
1822 G_SIGNAL_RUN_FIRST,
1823 G_STRUCT_OFFSET (GtkWidgetClass, state_flags_changed),
1824 NULL, NULL,
1825 NULL,
1826 G_TYPE_NONE, 1,
1827 GTK_TYPE_STATE_FLAGS);
1828
1829 /**
1830 * GtkWidget::parent-set:
1831 * @widget: the object on which the signal is emitted
1832 * @old_parent: (allow-none): the previous parent, or %NULL if the widget
1833 * just got its initial parent.
1834 *
1835 * The ::parent-set signal is emitted when a new parent
1836 * has been set on a widget.
1837 */
1838 widget_signals[PARENT_SET] =
1839 g_signal_new (I_("parent-set"),
1840 G_TYPE_FROM_CLASS (gobject_class),
1841 G_SIGNAL_RUN_FIRST,
1842 G_STRUCT_OFFSET (GtkWidgetClass, parent_set),
1843 NULL, NULL,
1844 NULL,
1845 G_TYPE_NONE, 1,
1846 GTK_TYPE_WIDGET);
1847
1848 /**
1849 * GtkWidget::hierarchy-changed:
1850 * @widget: the object on which the signal is emitted
1851 * @previous_toplevel: (allow-none): the previous toplevel ancestor, or %NULL
1852 * if the widget was previously unanchored
1853 *
1854 * The ::hierarchy-changed signal is emitted when the
1855 * anchored state of a widget changes. A widget is
1856 * “anchored” when its toplevel
1857 * ancestor is a #GtkWindow. This signal is emitted when
1858 * a widget changes from un-anchored to anchored or vice-versa.
1859 */
1860 widget_signals[HIERARCHY_CHANGED] =
1861 g_signal_new (I_("hierarchy-changed"),
1862 G_TYPE_FROM_CLASS (gobject_class),
1863 G_SIGNAL_RUN_LAST,
1864 G_STRUCT_OFFSET (GtkWidgetClass, hierarchy_changed),
1865 NULL, NULL,
1866 NULL,
1867 G_TYPE_NONE, 1,
1868 GTK_TYPE_WIDGET);
1869
1870 /**
1871 * GtkWidget::style-set:
1872 * @widget: the object on which the signal is emitted
1873 * @previous_style: (allow-none): the previous style, or %NULL if the widget
1874 * just got its initial style
1875 *
1876 * The ::style-set signal is emitted when a new style has been set
1877 * on a widget. Note that style-modifying functions like
1878 * gtk_widget_modify_base() also cause this signal to be emitted.
1879 *
1880 * Note that this signal is emitted for changes to the deprecated
1881 * #GtkStyle. To track changes to the #GtkStyleContext associated
1882 * with a widget, use the #GtkWidget::style-updated signal.
1883 *
1884 * Deprecated:3.0: Use the #GtkWidget::style-updated signal
1885 */
1886
1887 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
1888
1889 widget_signals[STYLE_SET] =
1890 g_signal_new (I_("style-set"),
1891 G_TYPE_FROM_CLASS (gobject_class),
1892 G_SIGNAL_RUN_FIRST | G_SIGNAL_DEPRECATED,
1893 G_STRUCT_OFFSET (GtkWidgetClass, style_set),
1894 NULL, NULL,
1895 NULL,
1896 G_TYPE_NONE, 1,
1897 GTK_TYPE_STYLE);
1898
1899 G_GNUC_END_IGNORE_DEPRECATIONS
1900
1901 /**
1902 * GtkWidget::style-updated:
1903 * @widget: the object on which the signal is emitted
1904 *
1905 * The ::style-updated signal is a convenience signal that is emitted when the
1906 * #GtkStyleContext::changed signal is emitted on the @widget's associated
1907 * #GtkStyleContext as returned by gtk_widget_get_style_context().
1908 *
1909 * Note that style-modifying functions like gtk_widget_override_color() also
1910 * cause this signal to be emitted.
1911 *
1912 * Since: 3.0
1913 */
1914 widget_signals[STYLE_UPDATED] =
1915 g_signal_new (I_("style-updated"),
1916 G_TYPE_FROM_CLASS (gobject_class),
1917 G_SIGNAL_RUN_FIRST,
1918 G_STRUCT_OFFSET (GtkWidgetClass, style_updated),
1919 NULL, NULL,
1920 NULL,
1921 G_TYPE_NONE, 0);
1922
1923 /**
1924 * GtkWidget::direction-changed:
1925 * @widget: the object on which the signal is emitted
1926 * @previous_direction: the previous text direction of @widget
1927 *
1928 * The ::direction-changed signal is emitted when the text direction
1929 * of a widget changes.
1930 */
1931 widget_signals[DIRECTION_CHANGED] =
1932 g_signal_new (I_("direction-changed"),
1933 G_TYPE_FROM_CLASS (gobject_class),
1934 G_SIGNAL_RUN_FIRST,
1935 G_STRUCT_OFFSET (GtkWidgetClass, direction_changed),
1936 NULL, NULL,
1937 NULL,
1938 G_TYPE_NONE, 1,
1939 GTK_TYPE_TEXT_DIRECTION);
1940
1941 /**
1942 * GtkWidget::grab-notify:
1943 * @widget: the object which received the signal
1944 * @was_grabbed: %FALSE if the widget becomes shadowed, %TRUE
1945 * if it becomes unshadowed
1946 *
1947 * The ::grab-notify signal is emitted when a widget becomes
1948 * shadowed by a GTK+ grab (not a pointer or keyboard grab) on
1949 * another widget, or when it becomes unshadowed due to a grab
1950 * being removed.
1951 *
1952 * A widget is shadowed by a gtk_grab_add() when the topmost
1953 * grab widget in the grab stack of its window group is not
1954 * its ancestor.
1955 */
1956 widget_signals[GRAB_NOTIFY] =
1957 g_signal_new (I_("grab-notify"),
1958 G_TYPE_FROM_CLASS (gobject_class),
1959 G_SIGNAL_RUN_FIRST,
1960 G_STRUCT_OFFSET (GtkWidgetClass, grab_notify),
1961 NULL, NULL,
1962 NULL,
1963 G_TYPE_NONE, 1,
1964 G_TYPE_BOOLEAN);
1965
1966 /**
1967 * GtkWidget::child-notify:
1968 * @widget: the object which received the signal
1969 * @child_property: the #GParamSpec of the changed child property
1970 *
1971 * The ::child-notify signal is emitted for each
1972 * [child property][child-properties] that has
1973 * changed on an object. The signal's detail holds the property name.
1974 */
1975 widget_signals[CHILD_NOTIFY] =
1976 g_signal_new (I_("child-notify"),
1977 G_TYPE_FROM_CLASS (gobject_class),
1978 G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE | G_SIGNAL_DETAILED | G_SIGNAL_NO_HOOKS,
1979 G_STRUCT_OFFSET (GtkWidgetClass, child_notify),
1980 NULL, NULL,
1981 NULL,
1982 G_TYPE_NONE, 1,
1983 G_TYPE_PARAM);
1984
1985 /**
1986 * GtkWidget::draw:
1987 * @widget: the object which received the signal
1988 * @cr: the cairo context to draw to
1989 *
1990 * This signal is emitted when a widget is supposed to render itself.
1991 * The @widget's top left corner must be painted at the origin of
1992 * the passed in context and be sized to the values returned by
1993 * gtk_widget_get_allocated_width() and
1994 * gtk_widget_get_allocated_height().
1995 *
1996 * Signal handlers connected to this signal can modify the cairo
1997 * context passed as @cr in any way they like and don't need to
1998 * restore it. The signal emission takes care of calling cairo_save()
1999 * before and cairo_restore() after invoking the handler.
2000 *
2001 * The signal handler will get a @cr with a clip region already set to the
2002 * widget's dirty region, i.e. to the area that needs repainting. Complicated
2003 * widgets that want to avoid redrawing themselves completely can get the full
2004 * extents of the clip region with gdk_cairo_get_clip_rectangle(), or they can
2005 * get a finer-grained representation of the dirty region with
2006 * cairo_copy_clip_rectangle_list().
2007 *
2008 * Returns: %TRUE to stop other handlers from being invoked for the event.
2009 * %FALSE to propagate the event further.
2010 *
2011 * Since: 3.0
2012 */
2013 widget_signals[DRAW] =
2014 g_signal_new (I_("draw"),
2015 G_TYPE_FROM_CLASS (gobject_class),
2016 G_SIGNAL_RUN_LAST,
2017 G_STRUCT_OFFSET (GtkWidgetClass, draw),
2018 _gtk_boolean_handled_accumulator, NULL,
2019 gtk_widget_draw_marshaller,
2020 G_TYPE_BOOLEAN, 1,
2021 CAIRO_GOBJECT_TYPE_CONTEXT);
2022 g_signal_set_va_marshaller (widget_signals[DRAW], G_TYPE_FROM_CLASS (klass),
2023 gtk_widget_draw_marshallerv);
2024
2025 /**
2026 * GtkWidget::mnemonic-activate:
2027 * @widget: the object which received the signal.
2028 * @group_cycling: %TRUE if there are other widgets with the same mnemonic
2029 *
2030 * The default handler for this signal activates @widget if @group_cycling
2031 * is %FALSE, or just makes @widget grab focus if @group_cycling is %TRUE.
2032 *
2033 * Returns: %TRUE to stop other handlers from being invoked for the event.
2034 * %FALSE to propagate the event further.
2035 */
2036 widget_signals[MNEMONIC_ACTIVATE] =
2037 g_signal_new (I_("mnemonic-activate"),
2038 G_TYPE_FROM_CLASS (gobject_class),
2039 G_SIGNAL_RUN_LAST,
2040 G_STRUCT_OFFSET (GtkWidgetClass, mnemonic_activate),
2041 _gtk_boolean_handled_accumulator, NULL,
2042 _gtk_marshal_BOOLEAN__BOOLEAN,
2043 G_TYPE_BOOLEAN, 1,
2044 G_TYPE_BOOLEAN);
2045 g_signal_set_va_marshaller (widget_signals[MNEMONIC_ACTIVATE],
2046 G_TYPE_FROM_CLASS (gobject_class),
2047 _gtk_marshal_BOOLEAN__BOOLEANv);
2048
2049 /**
2050 * GtkWidget::grab-focus:
2051 * @widget: the object which received the signal.
2052 */
2053 widget_signals[GRAB_FOCUS] =
2054 g_signal_new (I_("grab-focus"),
2055 G_TYPE_FROM_CLASS (gobject_class),
2056 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2057 G_STRUCT_OFFSET (GtkWidgetClass, grab_focus),
2058 NULL, NULL,
2059 NULL,
2060 G_TYPE_NONE, 0);
2061
2062 /**
2063 * GtkWidget::focus:
2064 * @widget: the object which received the signal.
2065 * @direction:
2066 *
2067 * Returns: %TRUE to stop other handlers from being invoked for the event. %FALSE to propagate the event further.
2068 */
2069 widget_signals[FOCUS] =
2070 g_signal_new (I_("focus"),
2071 G_TYPE_FROM_CLASS (klass),
2072 G_SIGNAL_RUN_LAST,
2073 G_STRUCT_OFFSET (GtkWidgetClass, focus),
2074 _gtk_boolean_handled_accumulator, NULL,
2075 _gtk_marshal_BOOLEAN__ENUM,
2076 G_TYPE_BOOLEAN, 1,
2077 GTK_TYPE_DIRECTION_TYPE);
2078 g_signal_set_va_marshaller (widget_signals[FOCUS],
2079 G_TYPE_FROM_CLASS (gobject_class),
2080 _gtk_marshal_BOOLEAN__ENUMv);
2081
2082 /**
2083 * GtkWidget::move-focus:
2084 * @widget: the object which received the signal.
2085 * @direction:
2086 */
2087 widget_signals[MOVE_FOCUS] =
2088 g_signal_new (I_("move-focus"),
2089 G_TYPE_FROM_CLASS (klass),
2090 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
2091 G_STRUCT_OFFSET (GtkWidgetClass, move_focus),
2092 NULL, NULL,
2093 NULL,
2094 G_TYPE_NONE,
2095 1,
2096 GTK_TYPE_DIRECTION_TYPE);
2097
2098 /**
2099 * GtkWidget::keynav-failed:
2100 * @widget: the object which received the signal
2101 * @direction: the direction of movement
2102 *
2103 * Gets emitted if keyboard navigation fails.
2104 * See gtk_widget_keynav_failed() for details.
2105 *
2106 * Returns: %TRUE if stopping keyboard navigation is fine, %FALSE
2107 * if the emitting widget should try to handle the keyboard
2108 * navigation attempt in its parent container(s).
2109 *
2110 * Since: 2.12
2111 **/
2112 widget_signals[KEYNAV_FAILED] =
2113 g_signal_new (I_("keynav-failed"),
2114 G_TYPE_FROM_CLASS (klass),
2115 G_SIGNAL_RUN_LAST,
2116 G_STRUCT_OFFSET (GtkWidgetClass, keynav_failed),
2117 _gtk_boolean_handled_accumulator, NULL,
2118 _gtk_marshal_BOOLEAN__ENUM,
2119 G_TYPE_BOOLEAN, 1,
2120 GTK_TYPE_DIRECTION_TYPE);
2121 g_signal_set_va_marshaller (widget_signals[KEYNAV_FAILED],
2122 G_TYPE_FROM_CLASS (klass),
2123 _gtk_marshal_BOOLEAN__ENUMv);
2124
2125 /**
2126 * GtkWidget::event:
2127 * @widget: the object which received the signal.
2128 * @event: the #GdkEvent which triggered this signal
2129 *
2130 * The GTK+ main loop will emit three signals for each GDK event delivered
2131 * to a widget: one generic ::event signal, another, more specific,
2132 * signal that matches the type of event delivered (e.g.
2133 * #GtkWidget::key-press-event) and finally a generic
2134 * #GtkWidget::event-after signal.
2135 *
2136 * Returns: %TRUE to stop other handlers from being invoked for the event
2137 * and to cancel the emission of the second specific ::event signal.
2138 * %FALSE to propagate the event further and to allow the emission of
2139 * the second signal. The ::event-after signal is emitted regardless of
2140 * the return value.
2141 */
2142 widget_signals[EVENT] =
2143 g_signal_new (I_("event"),
2144 G_TYPE_FROM_CLASS (klass),
2145 G_SIGNAL_RUN_LAST,
2146 G_STRUCT_OFFSET (GtkWidgetClass, event),
2147 _gtk_boolean_handled_accumulator, NULL,
2148 _gtk_marshal_BOOLEAN__BOXED,
2149 G_TYPE_BOOLEAN, 1,
2150 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2151 g_signal_set_va_marshaller (widget_signals[EVENT], G_TYPE_FROM_CLASS (klass),
2152 _gtk_marshal_BOOLEAN__BOXEDv);
2153
2154 /**
2155 * GtkWidget::event-after:
2156 * @widget: the object which received the signal.
2157 * @event: the #GdkEvent which triggered this signal
2158 *
2159 * After the emission of the #GtkWidget::event signal and (optionally)
2160 * the second more specific signal, ::event-after will be emitted
2161 * regardless of the previous two signals handlers return values.
2162 *
2163 */
2164 widget_signals[EVENT_AFTER] =
2165 g_signal_new (I_("event-after"),
2166 G_TYPE_FROM_CLASS (klass),
2167 0,
2168 0,
2169 NULL, NULL,
2170 NULL,
2171 G_TYPE_NONE, 1,
2172 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2173
2174 /**
2175 * GtkWidget::button-press-event:
2176 * @widget: the object which received the signal.
2177 * @event: (type Gdk.EventButton): the #GdkEventButton which triggered
2178 * this signal.
2179 *
2180 * The ::button-press-event signal will be emitted when a button
2181 * (typically from a mouse) is pressed.
2182 *
2183 * To receive this signal, the #GdkWindow associated to the
2184 * widget needs to enable the #GDK_BUTTON_PRESS_MASK mask.
2185 *
2186 * This signal will be sent to the grab widget if there is one.
2187 *
2188 * Returns: %TRUE to stop other handlers from being invoked for the event.
2189 * %FALSE to propagate the event further.
2190 */
2191 widget_signals[BUTTON_PRESS_EVENT] =
2192 g_signal_new (I_("button-press-event"),
2193 G_TYPE_FROM_CLASS (klass),
2194 G_SIGNAL_RUN_LAST,
2195 G_STRUCT_OFFSET (GtkWidgetClass, button_press_event),
2196 _gtk_boolean_handled_accumulator, NULL,
2197 _gtk_marshal_BOOLEAN__BOXED,
2198 G_TYPE_BOOLEAN, 1,
2199 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2200 g_signal_set_va_marshaller (widget_signals[BUTTON_PRESS_EVENT], G_TYPE_FROM_CLASS (klass),
2201 _gtk_marshal_BOOLEAN__BOXEDv);
2202
2203 /**
2204 * GtkWidget::button-release-event:
2205 * @widget: the object which received the signal.
2206 * @event: (type Gdk.EventButton): the #GdkEventButton which triggered
2207 * this signal.
2208 *
2209 * The ::button-release-event signal will be emitted when a button
2210 * (typically from a mouse) is released.
2211 *
2212 * To receive this signal, the #GdkWindow associated to the
2213 * widget needs to enable the #GDK_BUTTON_RELEASE_MASK mask.
2214 *
2215 * This signal will be sent to the grab widget if there is one.
2216 *
2217 * Returns: %TRUE to stop other handlers from being invoked for the event.
2218 * %FALSE to propagate the event further.
2219 */
2220 widget_signals[BUTTON_RELEASE_EVENT] =
2221 g_signal_new (I_("button-release-event"),
2222 G_TYPE_FROM_CLASS (klass),
2223 G_SIGNAL_RUN_LAST,
2224 G_STRUCT_OFFSET (GtkWidgetClass, button_release_event),
2225 _gtk_boolean_handled_accumulator, NULL,
2226 _gtk_marshal_BOOLEAN__BOXED,
2227 G_TYPE_BOOLEAN, 1,
2228 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2229 g_signal_set_va_marshaller (widget_signals[BUTTON_RELEASE_EVENT], G_TYPE_FROM_CLASS (klass),
2230 _gtk_marshal_BOOLEAN__BOXEDv);
2231
2232 widget_signals[TOUCH_EVENT] =
2233 g_signal_new (I_("touch-event"),
2234 G_TYPE_FROM_CLASS (klass),
2235 G_SIGNAL_RUN_LAST,
2236 G_STRUCT_OFFSET (GtkWidgetClass, touch_event),
2237 _gtk_boolean_handled_accumulator, NULL,
2238 _gtk_marshal_BOOLEAN__BOXED,
2239 G_TYPE_BOOLEAN, 1,
2240 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2241 g_signal_set_va_marshaller (widget_signals[TOUCH_EVENT], G_TYPE_FROM_CLASS (klass),
2242 _gtk_marshal_BOOLEAN__BOXEDv);
2243
2244 /**
2245 * GtkWidget::scroll-event:
2246 * @widget: the object which received the signal.
2247 * @event: (type Gdk.EventScroll): the #GdkEventScroll which triggered
2248 * this signal.
2249 *
2250 * The ::scroll-event signal is emitted when a button in the 4 to 7
2251 * range is pressed. Wheel mice are usually configured to generate
2252 * button press events for buttons 4 and 5 when the wheel is turned.
2253 *
2254 * To receive this signal, the #GdkWindow associated to the widget needs
2255 * to enable the #GDK_SCROLL_MASK mask.
2256 *
2257 * This signal will be sent to the grab widget if there is one.
2258 *
2259 * Returns: %TRUE to stop other handlers from being invoked for the event.
2260 * %FALSE to propagate the event further.
2261 */
2262 widget_signals[SCROLL_EVENT] =
2263 g_signal_new (I_("scroll-event"),
2264 G_TYPE_FROM_CLASS (klass),
2265 G_SIGNAL_RUN_LAST,
2266 G_STRUCT_OFFSET (GtkWidgetClass, scroll_event),
2267 _gtk_boolean_handled_accumulator, NULL,
2268 _gtk_marshal_BOOLEAN__BOXED,
2269 G_TYPE_BOOLEAN, 1,
2270 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2271 g_signal_set_va_marshaller (widget_signals[SCROLL_EVENT], G_TYPE_FROM_CLASS (klass),
2272 _gtk_marshal_BOOLEAN__BOXEDv);
2273
2274 /**
2275 * GtkWidget::motion-notify-event:
2276 * @widget: the object which received the signal.
2277 * @event: (type Gdk.EventMotion): the #GdkEventMotion which triggered
2278 * this signal.
2279 *
2280 * The ::motion-notify-event signal is emitted when the pointer moves
2281 * over the widget's #GdkWindow.
2282 *
2283 * To receive this signal, the #GdkWindow associated to the widget
2284 * needs to enable the #GDK_POINTER_MOTION_MASK mask.
2285 *
2286 * This signal will be sent to the grab widget if there is one.
2287 *
2288 * Returns: %TRUE to stop other handlers from being invoked for the event.
2289 * %FALSE to propagate the event further.
2290 */
2291 widget_signals[MOTION_NOTIFY_EVENT] =
2292 g_signal_new (I_("motion-notify-event"),
2293 G_TYPE_FROM_CLASS (klass),
2294 G_SIGNAL_RUN_LAST,
2295 G_STRUCT_OFFSET (GtkWidgetClass, motion_notify_event),
2296 _gtk_boolean_handled_accumulator, NULL,
2297 _gtk_marshal_BOOLEAN__BOXED,
2298 G_TYPE_BOOLEAN, 1,
2299 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2300 g_signal_set_va_marshaller (widget_signals[MOTION_NOTIFY_EVENT], G_TYPE_FROM_CLASS (klass),
2301 _gtk_marshal_BOOLEAN__BOXEDv);
2302
2303 /**
2304 * GtkWidget::composited-changed:
2305 * @widget: the object on which the signal is emitted
2306 *
2307 * The ::composited-changed signal is emitted when the composited
2308 * status of @widgets screen changes.
2309 * See gdk_screen_is_composited().
2310 *
2311 * Deprecated: 3.22: Use GdkScreen::composited-changed instead.
2312 */
2313 widget_signals[COMPOSITED_CHANGED] =
2314 g_signal_new (I_("composited-changed"),
2315 G_TYPE_FROM_CLASS (klass),
2316 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION | G_SIGNAL_DEPRECATED,
2317 G_STRUCT_OFFSET (GtkWidgetClass, composited_changed),
2318 NULL, NULL,
2319 NULL,
2320 G_TYPE_NONE, 0);
2321
2322 /**
2323 * GtkWidget::delete-event:
2324 * @widget: the object which received the signal
2325 * @event: the event which triggered this signal
2326 *
2327 * The ::delete-event signal is emitted if a user requests that
2328 * a toplevel window is closed. The default handler for this signal
2329 * destroys the window. Connecting gtk_widget_hide_on_delete() to
2330 * this signal will cause the window to be hidden instead, so that
2331 * it can later be shown again without reconstructing it.
2332 *
2333 * Returns: %TRUE to stop other handlers from being invoked for the event.
2334 * %FALSE to propagate the event further.
2335 */
2336 widget_signals[DELETE_EVENT] =
2337 g_signal_new (I_("delete-event"),
2338 G_TYPE_FROM_CLASS (klass),
2339 G_SIGNAL_RUN_LAST,
2340 G_STRUCT_OFFSET (GtkWidgetClass, delete_event),
2341 _gtk_boolean_handled_accumulator, NULL,
2342 _gtk_marshal_BOOLEAN__BOXED,
2343 G_TYPE_BOOLEAN, 1,
2344 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2345 g_signal_set_va_marshaller (widget_signals[DELETE_EVENT], G_TYPE_FROM_CLASS (klass),
2346 _gtk_marshal_BOOLEAN__BOXEDv);
2347
2348 /**
2349 * GtkWidget::destroy-event:
2350 * @widget: the object which received the signal.
2351 * @event: the event which triggered this signal
2352 *
2353 * The ::destroy-event signal is emitted when a #GdkWindow is destroyed.
2354 * You rarely get this signal, because most widgets disconnect themselves
2355 * from their window before they destroy it, so no widget owns the
2356 * window at destroy time.
2357 *
2358 * To receive this signal, the #GdkWindow associated to the widget needs
2359 * to enable the #GDK_STRUCTURE_MASK mask. GDK will enable this mask
2360 * automatically for all new windows.
2361 *
2362 * Returns: %TRUE to stop other handlers from being invoked for the event.
2363 * %FALSE to propagate the event further.
2364 */
2365 widget_signals[DESTROY_EVENT] =
2366 g_signal_new (I_("destroy-event"),
2367 G_TYPE_FROM_CLASS (klass),
2368 G_SIGNAL_RUN_LAST,
2369 G_STRUCT_OFFSET (GtkWidgetClass, destroy_event),
2370 _gtk_boolean_handled_accumulator, NULL,
2371 _gtk_marshal_BOOLEAN__BOXED,
2372 G_TYPE_BOOLEAN, 1,
2373 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2374 g_signal_set_va_marshaller (widget_signals[DESTROY_EVENT], G_TYPE_FROM_CLASS (klass),
2375 _gtk_marshal_BOOLEAN__BOXEDv);
2376
2377 /**
2378 * GtkWidget::key-press-event:
2379 * @widget: the object which received the signal
2380 * @event: (type Gdk.EventKey): the #GdkEventKey which triggered this signal.
2381 *
2382 * The ::key-press-event signal is emitted when a key is pressed. The signal
2383 * emission will reoccur at the key-repeat rate when the key is kept pressed.
2384 *
2385 * To receive this signal, the #GdkWindow associated to the widget needs
2386 * to enable the #GDK_KEY_PRESS_MASK mask.
2387 *
2388 * This signal will be sent to the grab widget if there is one.
2389 *
2390 * Returns: %TRUE to stop other handlers from being invoked for the event.
2391 * %FALSE to propagate the event further.
2392 */
2393 widget_signals[KEY_PRESS_EVENT] =
2394 g_signal_new (I_("key-press-event"),
2395 G_TYPE_FROM_CLASS (klass),
2396 G_SIGNAL_RUN_LAST,
2397 G_STRUCT_OFFSET (GtkWidgetClass, key_press_event),
2398 _gtk_boolean_handled_accumulator, NULL,
2399 _gtk_marshal_BOOLEAN__BOXED,
2400 G_TYPE_BOOLEAN, 1,
2401 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2402 g_signal_set_va_marshaller (widget_signals[KEY_PRESS_EVENT], G_TYPE_FROM_CLASS (klass),
2403 _gtk_marshal_BOOLEAN__BOXEDv);
2404
2405 /**
2406 * GtkWidget::key-release-event:
2407 * @widget: the object which received the signal
2408 * @event: (type Gdk.EventKey): the #GdkEventKey which triggered this signal.
2409 *
2410 * The ::key-release-event signal is emitted when a key is released.
2411 *
2412 * To receive this signal, the #GdkWindow associated to the widget needs
2413 * to enable the #GDK_KEY_RELEASE_MASK mask.
2414 *
2415 * This signal will be sent to the grab widget if there is one.
2416 *
2417 * Returns: %TRUE to stop other handlers from being invoked for the event.
2418 * %FALSE to propagate the event further.
2419 */
2420 widget_signals[KEY_RELEASE_EVENT] =
2421 g_signal_new (I_("key-release-event"),
2422 G_TYPE_FROM_CLASS (klass),
2423 G_SIGNAL_RUN_LAST,
2424 G_STRUCT_OFFSET (GtkWidgetClass, key_release_event),
2425 _gtk_boolean_handled_accumulator, NULL,
2426 _gtk_marshal_BOOLEAN__BOXED,
2427 G_TYPE_BOOLEAN, 1,
2428 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2429 g_signal_set_va_marshaller (widget_signals[KEY_RELEASE_EVENT], G_TYPE_FROM_CLASS (klass),
2430 _gtk_marshal_BOOLEAN__BOXEDv);
2431
2432 /**
2433 * GtkWidget::enter-notify-event:
2434 * @widget: the object which received the signal
2435 * @event: (type Gdk.EventCrossing): the #GdkEventCrossing which triggered
2436 * this signal.
2437 *
2438 * The ::enter-notify-event will be emitted when the pointer enters
2439 * the @widget's window.
2440 *
2441 * To receive this signal, the #GdkWindow associated to the widget needs
2442 * to enable the #GDK_ENTER_NOTIFY_MASK mask.
2443 *
2444 * This signal will be sent to the grab widget if there is one.
2445 *
2446 * Returns: %TRUE to stop other handlers from being invoked for the event.
2447 * %FALSE to propagate the event further.
2448 */
2449 widget_signals[ENTER_NOTIFY_EVENT] =
2450 g_signal_new (I_("enter-notify-event"),
2451 G_TYPE_FROM_CLASS (klass),
2452 G_SIGNAL_RUN_LAST,
2453 G_STRUCT_OFFSET (GtkWidgetClass, enter_notify_event),
2454 _gtk_boolean_handled_accumulator, NULL,
2455 _gtk_marshal_BOOLEAN__BOXED,
2456 G_TYPE_BOOLEAN, 1,
2457 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2458 g_signal_set_va_marshaller (widget_signals[ENTER_NOTIFY_EVENT], G_TYPE_FROM_CLASS (klass),
2459 _gtk_marshal_BOOLEAN__BOXEDv);
2460
2461 /**
2462 * GtkWidget::leave-notify-event:
2463 * @widget: the object which received the signal
2464 * @event: (type Gdk.EventCrossing): the #GdkEventCrossing which triggered
2465 * this signal.
2466 *
2467 * The ::leave-notify-event will be emitted when the pointer leaves
2468 * the @widget's window.
2469 *
2470 * To receive this signal, the #GdkWindow associated to the widget needs
2471 * to enable the #GDK_LEAVE_NOTIFY_MASK mask.
2472 *
2473 * This signal will be sent to the grab widget if there is one.
2474 *
2475 * Returns: %TRUE to stop other handlers from being invoked for the event.
2476 * %FALSE to propagate the event further.
2477 */
2478 widget_signals[LEAVE_NOTIFY_EVENT] =
2479 g_signal_new (I_("leave-notify-event"),
2480 G_TYPE_FROM_CLASS (klass),
2481 G_SIGNAL_RUN_LAST,
2482 G_STRUCT_OFFSET (GtkWidgetClass, leave_notify_event),
2483 _gtk_boolean_handled_accumulator, NULL,
2484 _gtk_marshal_BOOLEAN__BOXED,
2485 G_TYPE_BOOLEAN, 1,
2486 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2487 g_signal_set_va_marshaller (widget_signals[LEAVE_NOTIFY_EVENT], G_TYPE_FROM_CLASS (klass),
2488 _gtk_marshal_BOOLEAN__BOXEDv);
2489
2490 /**
2491 * GtkWidget::configure-event:
2492 * @widget: the object which received the signal
2493 * @event: (type Gdk.EventConfigure): the #GdkEventConfigure which triggered
2494 * this signal.
2495 *
2496 * The ::configure-event signal will be emitted when the size, position or
2497 * stacking of the @widget's window has changed.
2498 *
2499 * To receive this signal, the #GdkWindow associated to the widget needs
2500 * to enable the #GDK_STRUCTURE_MASK mask. GDK will enable this mask
2501 * automatically for all new windows.
2502 *
2503 * Returns: %TRUE to stop other handlers from being invoked for the event.
2504 * %FALSE to propagate the event further.
2505 */
2506 widget_signals[CONFIGURE_EVENT] =
2507 g_signal_new (I_("configure-event"),
2508 G_TYPE_FROM_CLASS (klass),
2509 G_SIGNAL_RUN_LAST,
2510 G_STRUCT_OFFSET (GtkWidgetClass, configure_event),
2511 _gtk_boolean_handled_accumulator, NULL,
2512 _gtk_marshal_BOOLEAN__BOXED,
2513 G_TYPE_BOOLEAN, 1,
2514 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2515 g_signal_set_va_marshaller (widget_signals[CONFIGURE_EVENT], G_TYPE_FROM_CLASS (klass),
2516 _gtk_marshal_BOOLEAN__BOXEDv);
2517
2518 /**
2519 * GtkWidget::focus-in-event:
2520 * @widget: the object which received the signal
2521 * @event: (type Gdk.EventFocus): the #GdkEventFocus which triggered
2522 * this signal.
2523 *
2524 * The ::focus-in-event signal will be emitted when the keyboard focus
2525 * enters the @widget's window.
2526 *
2527 * To receive this signal, the #GdkWindow associated to the widget needs
2528 * to enable the #GDK_FOCUS_CHANGE_MASK mask.
2529 *
2530 * Returns: %TRUE to stop other handlers from being invoked for the event.
2531 * %FALSE to propagate the event further.
2532 */
2533 widget_signals[FOCUS_IN_EVENT] =
2534 g_signal_new (I_("focus-in-event"),
2535 G_TYPE_FROM_CLASS (klass),
2536 G_SIGNAL_RUN_LAST,
2537 G_STRUCT_OFFSET (GtkWidgetClass, focus_in_event),
2538 _gtk_boolean_handled_accumulator, NULL,
2539 _gtk_marshal_BOOLEAN__BOXED,
2540 G_TYPE_BOOLEAN, 1,
2541 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2542 g_signal_set_va_marshaller (widget_signals[FOCUS_IN_EVENT], G_TYPE_FROM_CLASS (klass),
2543 _gtk_marshal_BOOLEAN__BOXEDv);
2544
2545 /**
2546 * GtkWidget::focus-out-event:
2547 * @widget: the object which received the signal
2548 * @event: (type Gdk.EventFocus): the #GdkEventFocus which triggered this
2549 * signal.
2550 *
2551 * The ::focus-out-event signal will be emitted when the keyboard focus
2552 * leaves the @widget's window.
2553 *
2554 * To receive this signal, the #GdkWindow associated to the widget needs
2555 * to enable the #GDK_FOCUS_CHANGE_MASK mask.
2556 *
2557 * Returns: %TRUE to stop other handlers from being invoked for the event.
2558 * %FALSE to propagate the event further.
2559 */
2560 widget_signals[FOCUS_OUT_EVENT] =
2561 g_signal_new (I_("focus-out-event"),
2562 G_TYPE_FROM_CLASS (klass),
2563 G_SIGNAL_RUN_LAST,
2564 G_STRUCT_OFFSET (GtkWidgetClass, focus_out_event),
2565 _gtk_boolean_handled_accumulator, NULL,
2566 _gtk_marshal_BOOLEAN__BOXED,
2567 G_TYPE_BOOLEAN, 1,
2568 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2569 g_signal_set_va_marshaller (widget_signals[FOCUS_OUT_EVENT], G_TYPE_FROM_CLASS (klass),
2570 _gtk_marshal_BOOLEAN__BOXEDv);
2571
2572 /**
2573 * GtkWidget::map-event:
2574 * @widget: the object which received the signal
2575 * @event: (type Gdk.EventAny): the #GdkEventAny which triggered this signal.
2576 *
2577 * The ::map-event signal will be emitted when the @widget's window is
2578 * mapped. A window is mapped when it becomes visible on the screen.
2579 *
2580 * To receive this signal, the #GdkWindow associated to the widget needs
2581 * to enable the #GDK_STRUCTURE_MASK mask. GDK will enable this mask
2582 * automatically for all new windows.
2583 *
2584 * Returns: %TRUE to stop other handlers from being invoked for the event.
2585 * %FALSE to propagate the event further.
2586 */
2587 widget_signals[MAP_EVENT] =
2588 g_signal_new (I_("map-event"),
2589 G_TYPE_FROM_CLASS (klass),
2590 G_SIGNAL_RUN_LAST,
2591 G_STRUCT_OFFSET (GtkWidgetClass, map_event),
2592 _gtk_boolean_handled_accumulator, NULL,
2593 _gtk_marshal_BOOLEAN__BOXED,
2594 G_TYPE_BOOLEAN, 1,
2595 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2596 g_signal_set_va_marshaller (widget_signals[MAP_EVENT], G_TYPE_FROM_CLASS (klass),
2597 _gtk_marshal_BOOLEAN__BOXEDv);
2598
2599 /**
2600 * GtkWidget::unmap-event:
2601 * @widget: the object which received the signal
2602 * @event: (type Gdk.EventAny): the #GdkEventAny which triggered this signal
2603 *
2604 * The ::unmap-event signal will be emitted when the @widget's window is
2605 * unmapped. A window is unmapped when it becomes invisible on the screen.
2606 *
2607 * To receive this signal, the #GdkWindow associated to the widget needs
2608 * to enable the #GDK_STRUCTURE_MASK mask. GDK will enable this mask
2609 * automatically for all new windows.
2610 *
2611 * Returns: %TRUE to stop other handlers from being invoked for the event.
2612 * %FALSE to propagate the event further.
2613 */
2614 widget_signals[UNMAP_EVENT] =
2615 g_signal_new (I_("unmap-event"),
2616 G_TYPE_FROM_CLASS (klass),
2617 G_SIGNAL_RUN_LAST,
2618 G_STRUCT_OFFSET (GtkWidgetClass, unmap_event),
2619 _gtk_boolean_handled_accumulator, NULL,
2620 _gtk_marshal_BOOLEAN__BOXED,
2621 G_TYPE_BOOLEAN, 1,
2622 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2623 g_signal_set_va_marshaller (widget_signals[UNMAP_EVENT], G_TYPE_FROM_CLASS (klass),
2624 _gtk_marshal_BOOLEAN__BOXEDv);
2625
2626 /**
2627 * GtkWidget::property-notify-event:
2628 * @widget: the object which received the signal
2629 * @event: (type Gdk.EventProperty): the #GdkEventProperty which triggered
2630 * this signal.
2631 *
2632 * The ::property-notify-event signal will be emitted when a property on
2633 * the @widget's window has been changed or deleted.
2634 *
2635 * To receive this signal, the #GdkWindow associated to the widget needs
2636 * to enable the #GDK_PROPERTY_CHANGE_MASK mask.
2637 *
2638 * Returns: %TRUE to stop other handlers from being invoked for the event.
2639 * %FALSE to propagate the event further.
2640 */
2641 widget_signals[PROPERTY_NOTIFY_EVENT] =
2642 g_signal_new (I_("property-notify-event"),
2643 G_TYPE_FROM_CLASS (klass),
2644 G_SIGNAL_RUN_LAST,
2645 G_STRUCT_OFFSET (GtkWidgetClass, property_notify_event),
2646 _gtk_boolean_handled_accumulator, NULL,
2647 _gtk_marshal_BOOLEAN__BOXED,
2648 G_TYPE_BOOLEAN, 1,
2649 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2650 g_signal_set_va_marshaller (widget_signals[PROPERTY_NOTIFY_EVENT], G_TYPE_FROM_CLASS (klass),
2651 _gtk_marshal_BOOLEAN__BOXEDv);
2652
2653 /**
2654 * GtkWidget::selection-clear-event:
2655 * @widget: the object which received the signal
2656 * @event: (type Gdk.EventSelection): the #GdkEventSelection which triggered
2657 * this signal.
2658 *
2659 * The ::selection-clear-event signal will be emitted when the
2660 * the @widget's window has lost ownership of a selection.
2661 *
2662 * Returns: %TRUE to stop other handlers from being invoked for the event.
2663 * %FALSE to propagate the event further.
2664 */
2665 widget_signals[SELECTION_CLEAR_EVENT] =
2666 g_signal_new (I_("selection-clear-event"),
2667 G_TYPE_FROM_CLASS (klass),
2668 G_SIGNAL_RUN_LAST,
2669 G_STRUCT_OFFSET (GtkWidgetClass, selection_clear_event),
2670 _gtk_boolean_handled_accumulator, NULL,
2671 _gtk_marshal_BOOLEAN__BOXED,
2672 G_TYPE_BOOLEAN, 1,
2673 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2674 g_signal_set_va_marshaller (widget_signals[SELECTION_CLEAR_EVENT], G_TYPE_FROM_CLASS (klass),
2675 _gtk_marshal_BOOLEAN__BOXEDv);
2676
2677 /**
2678 * GtkWidget::selection-request-event:
2679 * @widget: the object which received the signal
2680 * @event: (type Gdk.EventSelection): the #GdkEventSelection which triggered
2681 * this signal.
2682 *
2683 * The ::selection-request-event signal will be emitted when
2684 * another client requests ownership of the selection owned by
2685 * the @widget's window.
2686 *
2687 * Returns: %TRUE to stop other handlers from being invoked for the event.
2688 * %FALSE to propagate the event further.
2689 */
2690 widget_signals[SELECTION_REQUEST_EVENT] =
2691 g_signal_new (I_("selection-request-event"),
2692 G_TYPE_FROM_CLASS (klass),
2693 G_SIGNAL_RUN_LAST,
2694 G_STRUCT_OFFSET (GtkWidgetClass, selection_request_event),
2695 _gtk_boolean_handled_accumulator, NULL,
2696 _gtk_marshal_BOOLEAN__BOXED,
2697 G_TYPE_BOOLEAN, 1,
2698 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2699 g_signal_set_va_marshaller (widget_signals[SELECTION_REQUEST_EVENT], G_TYPE_FROM_CLASS (klass),
2700 _gtk_marshal_BOOLEAN__BOXEDv);
2701
2702 /**
2703 * GtkWidget::selection-notify-event:
2704 * @widget: the object which received the signal.
2705 * @event: (type Gdk.EventSelection):
2706 *
2707 * Returns: %TRUE to stop other handlers from being invoked for the event. %FALSE to propagate the event further.
2708 */
2709 widget_signals[SELECTION_NOTIFY_EVENT] =
2710 g_signal_new (I_("selection-notify-event"),
2711 G_TYPE_FROM_CLASS (klass),
2712 G_SIGNAL_RUN_LAST,
2713 G_STRUCT_OFFSET (GtkWidgetClass, selection_notify_event),
2714 _gtk_boolean_handled_accumulator, NULL,
2715 _gtk_marshal_BOOLEAN__BOXED,
2716 G_TYPE_BOOLEAN, 1,
2717 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2718 g_signal_set_va_marshaller (widget_signals[SELECTION_NOTIFY_EVENT], G_TYPE_FROM_CLASS (klass),
2719 _gtk_marshal_BOOLEAN__BOXEDv);
2720
2721 /**
2722 * GtkWidget::selection-received:
2723 * @widget: the object which received the signal.
2724 * @data:
2725 * @time:
2726 */
2727 widget_signals[SELECTION_RECEIVED] =
2728 g_signal_new (I_("selection-received"),
2729 G_TYPE_FROM_CLASS (klass),
2730 G_SIGNAL_RUN_LAST,
2731 G_STRUCT_OFFSET (GtkWidgetClass, selection_received),
2732 NULL, NULL,
2733 _gtk_marshal_VOID__BOXED_UINT,
2734 G_TYPE_NONE, 2,
2735 GTK_TYPE_SELECTION_DATA | G_SIGNAL_TYPE_STATIC_SCOPE,
2736 G_TYPE_UINT);
2737 g_signal_set_va_marshaller (widget_signals[SELECTION_RECEIVED],
2738 G_TYPE_FROM_CLASS (klass),
2739 _gtk_marshal_VOID__BOXED_UINTv);
2740
2741 /**
2742 * GtkWidget::selection-get:
2743 * @widget: the object which received the signal.
2744 * @data:
2745 * @info:
2746 * @time:
2747 */
2748 widget_signals[SELECTION_GET] =
2749 g_signal_new (I_("selection-get"),
2750 G_TYPE_FROM_CLASS (klass),
2751 G_SIGNAL_RUN_LAST,
2752 G_STRUCT_OFFSET (GtkWidgetClass, selection_get),
2753 NULL, NULL,
2754 _gtk_marshal_VOID__BOXED_UINT_UINT,
2755 G_TYPE_NONE, 3,
2756 GTK_TYPE_SELECTION_DATA | G_SIGNAL_TYPE_STATIC_SCOPE,
2757 G_TYPE_UINT,
2758 G_TYPE_UINT);
2759 g_signal_set_va_marshaller (widget_signals[SELECTION_GET],
2760 G_TYPE_FROM_CLASS (klass),
2761 _gtk_marshal_VOID__BOXED_UINT_UINTv);
2762
2763 /**
2764 * GtkWidget::proximity-in-event:
2765 * @widget: the object which received the signal
2766 * @event: (type Gdk.EventProximity): the #GdkEventProximity which triggered
2767 * this signal.
2768 *
2769 * To receive this signal the #GdkWindow associated to the widget needs
2770 * to enable the #GDK_PROXIMITY_IN_MASK mask.
2771 *
2772 * This signal will be sent to the grab widget if there is one.
2773 *
2774 * Returns: %TRUE to stop other handlers from being invoked for the event.
2775 * %FALSE to propagate the event further.
2776 */
2777 widget_signals[PROXIMITY_IN_EVENT] =
2778 g_signal_new (I_("proximity-in-event"),
2779 G_TYPE_FROM_CLASS (klass),
2780 G_SIGNAL_RUN_LAST,
2781 G_STRUCT_OFFSET (GtkWidgetClass, proximity_in_event),
2782 _gtk_boolean_handled_accumulator, NULL,
2783 _gtk_marshal_BOOLEAN__BOXED,
2784 G_TYPE_BOOLEAN, 1,
2785 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2786 g_signal_set_va_marshaller (widget_signals[PROXIMITY_IN_EVENT], G_TYPE_FROM_CLASS (klass),
2787 _gtk_marshal_BOOLEAN__BOXEDv);
2788
2789 /**
2790 * GtkWidget::proximity-out-event:
2791 * @widget: the object which received the signal
2792 * @event: (type Gdk.EventProximity): the #GdkEventProximity which triggered
2793 * this signal.
2794 *
2795 * To receive this signal the #GdkWindow associated to the widget needs
2796 * to enable the #GDK_PROXIMITY_OUT_MASK mask.
2797 *
2798 * This signal will be sent to the grab widget if there is one.
2799 *
2800 * Returns: %TRUE to stop other handlers from being invoked for the event.
2801 * %FALSE to propagate the event further.
2802 */
2803 widget_signals[PROXIMITY_OUT_EVENT] =
2804 g_signal_new (I_("proximity-out-event"),
2805 G_TYPE_FROM_CLASS (klass),
2806 G_SIGNAL_RUN_LAST,
2807 G_STRUCT_OFFSET (GtkWidgetClass, proximity_out_event),
2808 _gtk_boolean_handled_accumulator, NULL,
2809 _gtk_marshal_BOOLEAN__BOXED,
2810 G_TYPE_BOOLEAN, 1,
2811 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
2812 g_signal_set_va_marshaller (widget_signals[PROXIMITY_OUT_EVENT], G_TYPE_FROM_CLASS (klass),
2813 _gtk_marshal_BOOLEAN__BOXEDv);
2814
2815 /**
2816 * GtkWidget::drag-leave:
2817 * @widget: the object which received the signal.
2818 * @context: the drag context
2819 * @time: the timestamp of the motion event
2820 *
2821 * The ::drag-leave signal is emitted on the drop site when the cursor
2822 * leaves the widget. A typical reason to connect to this signal is to
2823 * undo things done in #GtkWidget::drag-motion, e.g. undo highlighting
2824 * with gtk_drag_unhighlight().
2825 *
2826 *
2827 * Likewise, the #GtkWidget::drag-leave signal is also emitted before the
2828 * ::drag-drop signal, for instance to allow cleaning up of a preview item
2829 * created in the #GtkWidget::drag-motion signal handler.
2830 */
2831 widget_signals[DRAG_LEAVE] =
2832 g_signal_new (I_("drag-leave"),
2833 G_TYPE_FROM_CLASS (klass),
2834 G_SIGNAL_RUN_LAST,
2835 G_STRUCT_OFFSET (GtkWidgetClass, drag_leave),
2836 NULL, NULL,
2837 _gtk_marshal_VOID__OBJECT_UINT,
2838 G_TYPE_NONE, 2,
2839 GDK_TYPE_DRAG_CONTEXT,
2840 G_TYPE_UINT);
2841 g_signal_set_va_marshaller (widget_signals[DRAG_LEAVE],
2842 G_TYPE_FROM_CLASS (klass),
2843 _gtk_marshal_VOID__OBJECT_UINTv);
2844
2845 /**
2846 * GtkWidget::drag-begin:
2847 * @widget: the object which received the signal
2848 * @context: the drag context
2849 *
2850 * The ::drag-begin signal is emitted on the drag source when a drag is
2851 * started. A typical reason to connect to this signal is to set up a
2852 * custom drag icon with e.g. gtk_drag_source_set_icon_pixbuf().
2853 *
2854 * Note that some widgets set up a drag icon in the default handler of
2855 * this signal, so you may have to use g_signal_connect_after() to
2856 * override what the default handler did.
2857 */
2858 widget_signals[DRAG_BEGIN] =
2859 g_signal_new (I_("drag-begin"),
2860 G_TYPE_FROM_CLASS (klass),
2861 G_SIGNAL_RUN_LAST,
2862 G_STRUCT_OFFSET (GtkWidgetClass, drag_begin),
2863 NULL, NULL,
2864 NULL,
2865 G_TYPE_NONE, 1,
2866 GDK_TYPE_DRAG_CONTEXT);
2867
2868 /**
2869 * GtkWidget::drag-end:
2870 * @widget: the object which received the signal
2871 * @context: the drag context
2872 *
2873 * The ::drag-end signal is emitted on the drag source when a drag is
2874 * finished. A typical reason to connect to this signal is to undo
2875 * things done in #GtkWidget::drag-begin.
2876 */
2877 widget_signals[DRAG_END] =
2878 g_signal_new (I_("drag-end"),
2879 G_TYPE_FROM_CLASS (klass),
2880 G_SIGNAL_RUN_LAST,
2881 G_STRUCT_OFFSET (GtkWidgetClass, drag_end),
2882 NULL, NULL,
2883 NULL,
2884 G_TYPE_NONE, 1,
2885 GDK_TYPE_DRAG_CONTEXT);
2886
2887 /**
2888 * GtkWidget::drag-data-delete:
2889 * @widget: the object which received the signal
2890 * @context: the drag context
2891 *
2892 * The ::drag-data-delete signal is emitted on the drag source when a drag
2893 * with the action %GDK_ACTION_MOVE is successfully completed. The signal
2894 * handler is responsible for deleting the data that has been dropped. What
2895 * "delete" means depends on the context of the drag operation.
2896 */
2897 widget_signals[DRAG_DATA_DELETE] =
2898 g_signal_new (I_("drag-data-delete"),
2899 G_TYPE_FROM_CLASS (klass),
2900 G_SIGNAL_RUN_LAST,
2901 G_STRUCT_OFFSET (GtkWidgetClass, drag_data_delete),
2902 NULL, NULL,
2903 NULL,
2904 G_TYPE_NONE, 1,
2905 GDK_TYPE_DRAG_CONTEXT);
2906
2907 /**
2908 * GtkWidget::drag-failed:
2909 * @widget: the object which received the signal
2910 * @context: the drag context
2911 * @result: the result of the drag operation
2912 *
2913 * The ::drag-failed signal is emitted on the drag source when a drag has
2914 * failed. The signal handler may hook custom code to handle a failed DnD
2915 * operation based on the type of error, it returns %TRUE is the failure has
2916 * been already handled (not showing the default "drag operation failed"
2917 * animation), otherwise it returns %FALSE.
2918 *
2919 * Returns: %TRUE if the failed drag operation has been already handled.
2920 *
2921 * Since: 2.12
2922 */
2923 widget_signals[DRAG_FAILED] =
2924 g_signal_new (I_("drag-failed"),
2925 G_TYPE_FROM_CLASS (klass),
2926 G_SIGNAL_RUN_LAST,
2927 G_STRUCT_OFFSET (GtkWidgetClass, drag_failed),
2928 _gtk_boolean_handled_accumulator, NULL,
2929 _gtk_marshal_BOOLEAN__OBJECT_ENUM,
2930 G_TYPE_BOOLEAN, 2,
2931 GDK_TYPE_DRAG_CONTEXT,
2932 GTK_TYPE_DRAG_RESULT);
2933 g_signal_set_va_marshaller (widget_signals[DRAG_FAILED],
2934 G_TYPE_FROM_CLASS (klass),
2935 _gtk_marshal_BOOLEAN__OBJECT_ENUMv);
2936
2937 /**
2938 * GtkWidget::drag-motion:
2939 * @widget: the object which received the signal
2940 * @context: the drag context
2941 * @x: the x coordinate of the current cursor position
2942 * @y: the y coordinate of the current cursor position
2943 * @time: the timestamp of the motion event
2944 *
2945 * The ::drag-motion signal is emitted on the drop site when the user
2946 * moves the cursor over the widget during a drag. The signal handler
2947 * must determine whether the cursor position is in a drop zone or not.
2948 * If it is not in a drop zone, it returns %FALSE and no further processing
2949 * is necessary. Otherwise, the handler returns %TRUE. In this case, the
2950 * handler is responsible for providing the necessary information for
2951 * displaying feedback to the user, by calling gdk_drag_status().
2952 *
2953 * If the decision whether the drop will be accepted or rejected can't be
2954 * made based solely on the cursor position and the type of the data, the
2955 * handler may inspect the dragged data by calling gtk_drag_get_data() and
2956 * defer the gdk_drag_status() call to the #GtkWidget::drag-data-received
2957 * handler. Note that you must pass #GTK_DEST_DEFAULT_DROP,
2958 * #GTK_DEST_DEFAULT_MOTION or #GTK_DEST_DEFAULT_ALL to gtk_drag_dest_set()
2959 * when using the drag-motion signal that way.
2960 *
2961 * Also note that there is no drag-enter signal. The drag receiver has to
2962 * keep track of whether he has received any drag-motion signals since the
2963 * last #GtkWidget::drag-leave and if not, treat the drag-motion signal as
2964 * an "enter" signal. Upon an "enter", the handler will typically highlight
2965 * the drop site with gtk_drag_highlight().
2966 * |[<!-- language="C" -->
2967 * static void
2968 * drag_motion (GtkWidget *widget,
2969 * GdkDragContext *context,
2970 * gint x,
2971 * gint y,
2972 * guint time)
2973 * {
2974 * GdkAtom target;
2975 *
2976 * PrivateData *private_data = GET_PRIVATE_DATA (widget);
2977 *
2978 * if (!private_data->drag_highlight)
2979 * {
2980 * private_data->drag_highlight = 1;
2981 * gtk_drag_highlight (widget);
2982 * }
2983 *
2984 * target = gtk_drag_dest_find_target (widget, context, NULL);
2985 * if (target == GDK_NONE)
2986 * gdk_drag_status (context, 0, time);
2987 * else
2988 * {
2989 * private_data->pending_status
2990 * = gdk_drag_context_get_suggested_action (context);
2991 * gtk_drag_get_data (widget, context, target, time);
2992 * }
2993 *
2994 * return TRUE;
2995 * }
2996 *
2997 * static void
2998 * drag_data_received (GtkWidget *widget,
2999 * GdkDragContext *context,
3000 * gint x,
3001 * gint y,
3002 * GtkSelectionData *selection_data,
3003 * guint info,
3004 * guint time)
3005 * {
3006 * PrivateData *private_data = GET_PRIVATE_DATA (widget);
3007 *
3008 * if (private_data->suggested_action)
3009 * {
3010 * private_data->suggested_action = 0;
3011 *
3012 * // We are getting this data due to a request in drag_motion,
3013 * // rather than due to a request in drag_drop, so we are just
3014 * // supposed to call gdk_drag_status(), not actually paste in
3015 * // the data.
3016 *
3017 * str = gtk_selection_data_get_text (selection_data);
3018 * if (!data_is_acceptable (str))
3019 * gdk_drag_status (context, 0, time);
3020 * else
3021 * gdk_drag_status (context,
3022 * private_data->suggested_action,
3023 * time);
3024 * }
3025 * else
3026 * {
3027 * // accept the drop
3028 * }
3029 * }
3030 * ]|
3031 *
3032 * Returns: whether the cursor position is in a drop zone
3033 */
3034 widget_signals[DRAG_MOTION] =
3035 g_signal_new (I_("drag-motion"),
3036 G_TYPE_FROM_CLASS (klass),
3037 G_SIGNAL_RUN_LAST,
3038 G_STRUCT_OFFSET (GtkWidgetClass, drag_motion),
3039 _gtk_boolean_handled_accumulator, NULL,
3040 _gtk_marshal_BOOLEAN__OBJECT_INT_INT_UINT,
3041 G_TYPE_BOOLEAN, 4,
3042 GDK_TYPE_DRAG_CONTEXT,
3043 G_TYPE_INT,
3044 G_TYPE_INT,
3045 G_TYPE_UINT);
3046 g_signal_set_va_marshaller (widget_signals[DRAG_MOTION],
3047 G_TYPE_FROM_CLASS (klass),
3048 _gtk_marshal_BOOLEAN__OBJECT_INT_INT_UINTv);
3049
3050 /**
3051 * GtkWidget::drag-drop:
3052 * @widget: the object which received the signal
3053 * @context: the drag context
3054 * @x: the x coordinate of the current cursor position
3055 * @y: the y coordinate of the current cursor position
3056 * @time: the timestamp of the motion event
3057 *
3058 * The ::drag-drop signal is emitted on the drop site when the user drops
3059 * the data onto the widget. The signal handler must determine whether
3060 * the cursor position is in a drop zone or not. If it is not in a drop
3061 * zone, it returns %FALSE and no further processing is necessary.
3062 * Otherwise, the handler returns %TRUE. In this case, the handler must
3063 * ensure that gtk_drag_finish() is called to let the source know that
3064 * the drop is done. The call to gtk_drag_finish() can be done either
3065 * directly or in a #GtkWidget::drag-data-received handler which gets
3066 * triggered by calling gtk_drag_get_data() to receive the data for one
3067 * or more of the supported targets.
3068 *
3069 * Returns: whether the cursor position is in a drop zone
3070 */
3071 widget_signals[DRAG_DROP] =
3072 g_signal_new (I_("drag-drop"),
3073 G_TYPE_FROM_CLASS (klass),
3074 G_SIGNAL_RUN_LAST,
3075 G_STRUCT_OFFSET (GtkWidgetClass, drag_drop),
3076 _gtk_boolean_handled_accumulator, NULL,
3077 _gtk_marshal_BOOLEAN__OBJECT_INT_INT_UINT,
3078 G_TYPE_BOOLEAN, 4,
3079 GDK_TYPE_DRAG_CONTEXT,
3080 G_TYPE_INT,
3081 G_TYPE_INT,
3082 G_TYPE_UINT);
3083 g_signal_set_va_marshaller (widget_signals[DRAG_DROP],
3084 G_TYPE_FROM_CLASS (klass),
3085 _gtk_marshal_BOOLEAN__OBJECT_INT_INT_UINTv);
3086
3087 /**
3088 * GtkWidget::drag-data-get:
3089 * @widget: the object which received the signal
3090 * @context: the drag context
3091 * @data: the #GtkSelectionData to be filled with the dragged data
3092 * @info: the info that has been registered with the target in the
3093 * #GtkTargetList
3094 * @time: the timestamp at which the data was requested
3095 *
3096 * The ::drag-data-get signal is emitted on the drag source when the drop
3097 * site requests the data which is dragged. It is the responsibility of
3098 * the signal handler to fill @data with the data in the format which
3099 * is indicated by @info. See gtk_selection_data_set() and
3100 * gtk_selection_data_set_text().
3101 */
3102 widget_signals[DRAG_DATA_GET] =
3103 g_signal_new (I_("drag-data-get"),
3104 G_TYPE_FROM_CLASS (klass),
3105 G_SIGNAL_RUN_LAST,
3106 G_STRUCT_OFFSET (GtkWidgetClass, drag_data_get),
3107 NULL, NULL,
3108 _gtk_marshal_VOID__OBJECT_BOXED_UINT_UINT,
3109 G_TYPE_NONE, 4,
3110 GDK_TYPE_DRAG_CONTEXT,
3111 GTK_TYPE_SELECTION_DATA | G_SIGNAL_TYPE_STATIC_SCOPE,
3112 G_TYPE_UINT,
3113 G_TYPE_UINT);
3114 g_signal_set_va_marshaller (widget_signals[DRAG_DATA_GET],
3115 G_TYPE_FROM_CLASS (klass),
3116 _gtk_marshal_VOID__OBJECT_BOXED_UINT_UINTv);
3117
3118 /**
3119 * GtkWidget::drag-data-received:
3120 * @widget: the object which received the signal
3121 * @context: the drag context
3122 * @x: where the drop happened
3123 * @y: where the drop happened
3124 * @data: the received data
3125 * @info: the info that has been registered with the target in the
3126 * #GtkTargetList
3127 * @time: the timestamp at which the data was received
3128 *
3129 * The ::drag-data-received signal is emitted on the drop site when the
3130 * dragged data has been received. If the data was received in order to
3131 * determine whether the drop will be accepted, the handler is expected
3132 * to call gdk_drag_status() and not finish the drag.
3133 * If the data was received in response to a #GtkWidget::drag-drop signal
3134 * (and this is the last target to be received), the handler for this
3135 * signal is expected to process the received data and then call
3136 * gtk_drag_finish(), setting the @success parameter depending on
3137 * whether the data was processed successfully.
3138 *
3139 * Applications must create some means to determine why the signal was emitted
3140 * and therefore whether to call gdk_drag_status() or gtk_drag_finish().
3141 *
3142 * The handler may inspect the selected action with
3143 * gdk_drag_context_get_selected_action() before calling
3144 * gtk_drag_finish(), e.g. to implement %GDK_ACTION_ASK as
3145 * shown in the following example:
3146 * |[<!-- language="C" -->
3147 * void
3148 * drag_data_received (GtkWidget *widget,
3149 * GdkDragContext *context,
3150 * gint x,
3151 * gint y,
3152 * GtkSelectionData *data,
3153 * guint info,
3154 * guint time)
3155 * {
3156 * if ((data->length >= 0) && (data->format == 8))
3157 * {
3158 * GdkDragAction action;
3159 *
3160 * // handle data here
3161 *
3162 * action = gdk_drag_context_get_selected_action (context);
3163 * if (action == GDK_ACTION_ASK)
3164 * {
3165 * GtkWidget *dialog;
3166 * gint response;
3167 *
3168 * dialog = gtk_message_dialog_new (NULL,
3169 * GTK_DIALOG_MODAL |
3170 * GTK_DIALOG_DESTROY_WITH_PARENT,
3171 * GTK_MESSAGE_INFO,
3172 * GTK_BUTTONS_YES_NO,
3173 * "Move the data ?\n");
3174 * response = gtk_dialog_run (GTK_DIALOG (dialog));
3175 * gtk_widget_destroy (dialog);
3176 *
3177 * if (response == GTK_RESPONSE_YES)
3178 * action = GDK_ACTION_MOVE;
3179 * else
3180 * action = GDK_ACTION_COPY;
3181 * }
3182 *
3183 * gtk_drag_finish (context, TRUE, action == GDK_ACTION_MOVE, time);
3184 * }
3185 * else
3186 * gtk_drag_finish (context, FALSE, FALSE, time);
3187 * }
3188 * ]|
3189 */
3190 widget_signals[DRAG_DATA_RECEIVED] =
3191 g_signal_new (I_("drag-data-received"),
3192 G_TYPE_FROM_CLASS (klass),
3193 G_SIGNAL_RUN_LAST,
3194 G_STRUCT_OFFSET (GtkWidgetClass, drag_data_received),
3195 NULL, NULL,
3196 _gtk_marshal_VOID__OBJECT_INT_INT_BOXED_UINT_UINT,
3197 G_TYPE_NONE, 6,
3198 GDK_TYPE_DRAG_CONTEXT,
3199 G_TYPE_INT,
3200 G_TYPE_INT,
3201 GTK_TYPE_SELECTION_DATA | G_SIGNAL_TYPE_STATIC_SCOPE,
3202 G_TYPE_UINT,
3203 G_TYPE_UINT);
3204 g_signal_set_va_marshaller (widget_signals[DRAG_DATA_RECEIVED],
3205 G_TYPE_FROM_CLASS (klass),
3206 _gtk_marshal_VOID__OBJECT_INT_INT_BOXED_UINT_UINTv);
3207
3208 /**
3209 * GtkWidget::visibility-notify-event:
3210 * @widget: the object which received the signal
3211 * @event: (type Gdk.EventVisibility): the #GdkEventVisibility which
3212 * triggered this signal.
3213 *
3214 * The ::visibility-notify-event will be emitted when the @widget's
3215 * window is obscured or unobscured.
3216 *
3217 * To receive this signal the #GdkWindow associated to the widget needs
3218 * to enable the #GDK_VISIBILITY_NOTIFY_MASK mask.
3219 *
3220 * Returns: %TRUE to stop other handlers from being invoked for the event.
3221 * %FALSE to propagate the event further.
3222 *
3223 * Deprecated: 3.12: Modern composited windowing systems with pervasive
3224 * transparency make it impossible to track the visibility of a window
3225 * reliably, so this signal can not be guaranteed to provide useful
3226 * information.
3227 */
3228 widget_signals[VISIBILITY_NOTIFY_EVENT] =
3229 g_signal_new (I_("visibility-notify-event"),
3230 G_TYPE_FROM_CLASS (klass),
3231 G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED,
3232 G_STRUCT_OFFSET (GtkWidgetClass, visibility_notify_event),
3233 _gtk_boolean_handled_accumulator, NULL,
3234 _gtk_marshal_BOOLEAN__BOXED,
3235 G_TYPE_BOOLEAN, 1,
3236 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
3237 g_signal_set_va_marshaller (widget_signals[VISIBILITY_NOTIFY_EVENT],
3238 G_TYPE_FROM_CLASS (klass),
3239 _gtk_marshal_BOOLEAN__BOXEDv);
3240
3241 /**
3242 * GtkWidget::window-state-event:
3243 * @widget: the object which received the signal
3244 * @event: (type Gdk.EventWindowState): the #GdkEventWindowState which
3245 * triggered this signal.
3246 *
3247 * The ::window-state-event will be emitted when the state of the
3248 * toplevel window associated to the @widget changes.
3249 *
3250 * To receive this signal the #GdkWindow associated to the widget
3251 * needs to enable the #GDK_STRUCTURE_MASK mask. GDK will enable
3252 * this mask automatically for all new windows.
3253 *
3254 * Returns: %TRUE to stop other handlers from being invoked for the
3255 * event. %FALSE to propagate the event further.
3256 */
3257 widget_signals[WINDOW_STATE_EVENT] =
3258 g_signal_new (I_("window-state-event"),
3259 G_TYPE_FROM_CLASS (klass),
3260 G_SIGNAL_RUN_LAST,
3261 G_STRUCT_OFFSET (GtkWidgetClass, window_state_event),
3262 _gtk_boolean_handled_accumulator, NULL,
3263 _gtk_marshal_BOOLEAN__BOXED,
3264 G_TYPE_BOOLEAN, 1,
3265 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
3266 g_signal_set_va_marshaller (widget_signals[WINDOW_STATE_EVENT], G_TYPE_FROM_CLASS (klass),
3267 _gtk_marshal_BOOLEAN__BOXEDv);
3268
3269 /**
3270 * GtkWidget::damage-event:
3271 * @widget: the object which received the signal
3272 * @event: (type Gdk.EventExpose): the #GdkEventExpose event
3273 *
3274 * Emitted when a redirected window belonging to @widget gets drawn into.
3275 * The region/area members of the event shows what area of the redirected
3276 * drawable was drawn into.
3277 *
3278 * Returns: %TRUE to stop other handlers from being invoked for the event.
3279 * %FALSE to propagate the event further.
3280 *
3281 * Since: 2.14
3282 */
3283 widget_signals[DAMAGE_EVENT] =
3284 g_signal_new (I_("damage-event"),
3285 G_TYPE_FROM_CLASS (klass),
3286 G_SIGNAL_RUN_LAST,
3287 G_STRUCT_OFFSET (GtkWidgetClass, damage_event),
3288 _gtk_boolean_handled_accumulator, NULL,
3289 _gtk_marshal_BOOLEAN__BOXED,
3290 G_TYPE_BOOLEAN, 1,
3291 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
3292 g_signal_set_va_marshaller (widget_signals[DAMAGE_EVENT], G_TYPE_FROM_CLASS (klass),
3293 _gtk_marshal_BOOLEAN__BOXEDv);
3294
3295 /**
3296 * GtkWidget::grab-broken-event:
3297 * @widget: the object which received the signal
3298 * @event: (type Gdk.EventGrabBroken): the #GdkEventGrabBroken event
3299 *
3300 * Emitted when a pointer or keyboard grab on a window belonging
3301 * to @widget gets broken.
3302 *
3303 * On X11, this happens when the grab window becomes unviewable
3304 * (i.e. it or one of its ancestors is unmapped), or if the same
3305 * application grabs the pointer or keyboard again.
3306 *
3307 * Returns: %TRUE to stop other handlers from being invoked for
3308 * the event. %FALSE to propagate the event further.
3309 *
3310 * Since: 2.8
3311 */
3312 widget_signals[GRAB_BROKEN_EVENT] =
3313 g_signal_new (I_("grab-broken-event"),
3314 G_TYPE_FROM_CLASS (klass),
3315 G_SIGNAL_RUN_LAST,
3316 G_STRUCT_OFFSET (GtkWidgetClass, grab_broken_event),
3317 _gtk_boolean_handled_accumulator, NULL,
3318 _gtk_marshal_BOOLEAN__BOXED,
3319 G_TYPE_BOOLEAN, 1,
3320 GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
3321 g_signal_set_va_marshaller (widget_signals[GRAB_BROKEN_EVENT], G_TYPE_FROM_CLASS (klass),
3322 _gtk_marshal_BOOLEAN__BOXEDv);
3323
3324 /**
3325 * GtkWidget::query-tooltip:
3326 * @widget: the object which received the signal
3327 * @x: the x coordinate of the cursor position where the request has
3328 * been emitted, relative to @widget's left side
3329 * @y: the y coordinate of the cursor position where the request has
3330 * been emitted, relative to @widget's top
3331 * @keyboard_mode: %TRUE if the tooltip was triggered using the keyboard
3332 * @tooltip: a #GtkTooltip
3333 *
3334 * Emitted when #GtkWidget:has-tooltip is %TRUE and the hover timeout
3335 * has expired with the cursor hovering "above" @widget; or emitted when @widget got
3336 * focus in keyboard mode.
3337 *
3338 * Using the given coordinates, the signal handler should determine
3339 * whether a tooltip should be shown for @widget. If this is the case
3340 * %TRUE should be returned, %FALSE otherwise. Note that if
3341 * @keyboard_mode is %TRUE, the values of @x and @y are undefined and
3342 * should not be used.
3343 *
3344 * The signal handler is free to manipulate @tooltip with the therefore
3345 * destined function calls.
3346 *
3347 * Returns: %TRUE if @tooltip should be shown right now, %FALSE otherwise.
3348 *
3349 * Since: 2.12
3350 */
3351 widget_signals[QUERY_TOOLTIP] =
3352 g_signal_new (I_("query-tooltip"),
3353 G_TYPE_FROM_CLASS (klass),
3354 G_SIGNAL_RUN_LAST,
3355 G_STRUCT_OFFSET (GtkWidgetClass, query_tooltip),
3356 _gtk_boolean_handled_accumulator, NULL,
3357 _gtk_marshal_BOOLEAN__INT_INT_BOOLEAN_OBJECT,
3358 G_TYPE_BOOLEAN, 4,
3359 G_TYPE_INT,
3360 G_TYPE_INT,
3361 G_TYPE_BOOLEAN,
3362 GTK_TYPE_TOOLTIP);
3363 g_signal_set_va_marshaller (widget_signals[QUERY_TOOLTIP],
3364 G_TYPE_FROM_CLASS (klass),
3365 _gtk_marshal_BOOLEAN__INT_INT_BOOLEAN_OBJECTv);
3366
3367 /**
3368 * GtkWidget::popup-menu:
3369 * @widget: the object which received the signal
3370 *
3371 * This signal gets emitted whenever a widget should pop up a context
3372 * menu. This usually happens through the standard key binding mechanism;
3373 * by pressing a certain key while a widget is focused, the user can cause
3374 * the widget to pop up a menu. For example, the #GtkEntry widget creates
3375 * a menu with clipboard commands. See the
3376 * [Popup Menu Migration Checklist][checklist-popup-menu]
3377 * for an example of how to use this signal.
3378 *
3379 * Returns: %TRUE if a menu was activated
3380 */
3381 widget_signals[POPUP_MENU] =
3382 g_signal_new (I_("popup-menu"),
3383 G_TYPE_FROM_CLASS (klass),
3384 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
3385 G_STRUCT_OFFSET (GtkWidgetClass, popup_menu),
3386 _gtk_boolean_handled_accumulator, NULL,
3387 _gtk_marshal_BOOLEAN__VOID,
3388 G_TYPE_BOOLEAN, 0);
3389 g_signal_set_va_marshaller (widget_signals[POPUP_MENU],
3390 G_TYPE_FROM_CLASS (klass),
3391 _gtk_marshal_BOOLEAN__VOIDv);
3392
3393 /**
3394 * GtkWidget::show-help:
3395 * @widget: the object which received the signal.
3396 * @help_type:
3397 *
3398 * Returns: %TRUE to stop other handlers from being invoked for the event.
3399 * %FALSE to propagate the event further.
3400 */
3401 widget_signals[SHOW_HELP] =
3402 g_signal_new (I_("show-help"),
3403 G_TYPE_FROM_CLASS (klass),
3404 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
3405 G_STRUCT_OFFSET (GtkWidgetClass, show_help),
3406 _gtk_boolean_handled_accumulator, NULL,
3407 _gtk_marshal_BOOLEAN__ENUM,
3408 G_TYPE_BOOLEAN, 1,
3409 GTK_TYPE_WIDGET_HELP_TYPE);
3410 g_signal_set_va_marshaller (widget_signals[SHOW_HELP],
3411 G_TYPE_FROM_CLASS (klass),
3412 _gtk_marshal_BOOLEAN__ENUMv);
3413
3414 /**
3415 * GtkWidget::accel-closures-changed:
3416 * @widget: the object which received the signal.
3417 */
3418 widget_signals[ACCEL_CLOSURES_CHANGED] =
3419 g_signal_new (I_("accel-closures-changed"),
3420 G_TYPE_FROM_CLASS (klass),
3421 0,
3422 0,
3423 NULL, NULL,
3424 NULL,
3425 G_TYPE_NONE, 0);
3426
3427 /**
3428 * GtkWidget::screen-changed:
3429 * @widget: the object on which the signal is emitted
3430 * @previous_screen: (allow-none): the previous screen, or %NULL if the
3431 * widget was not associated with a screen before
3432 *
3433 * The ::screen-changed signal gets emitted when the
3434 * screen of a widget has changed.
3435 */
3436 widget_signals[SCREEN_CHANGED] =
3437 g_signal_new (I_("screen-changed"),
3438 G_TYPE_FROM_CLASS (klass),
3439 G_SIGNAL_RUN_LAST,
3440 G_STRUCT_OFFSET (GtkWidgetClass, screen_changed),
3441 NULL, NULL,
3442 NULL,
3443 G_TYPE_NONE, 1,
3444 GDK_TYPE_SCREEN);
3445
3446 /**
3447 * GtkWidget::can-activate-accel:
3448 * @widget: the object which received the signal
3449 * @signal_id: the ID of a signal installed on @widget
3450 *
3451 * Determines whether an accelerator that activates the signal
3452 * identified by @signal_id can currently be activated.
3453 * This signal is present to allow applications and derived
3454 * widgets to override the default #GtkWidget handling
3455 * for determining whether an accelerator can be activated.
3456 *
3457 * Returns: %TRUE if the signal can be activated.
3458 */
3459 widget_signals[CAN_ACTIVATE_ACCEL] =
3460 g_signal_new (I_("can-activate-accel"),
3461 G_TYPE_FROM_CLASS (klass),
3462 G_SIGNAL_RUN_LAST,
3463 G_STRUCT_OFFSET (GtkWidgetClass, can_activate_accel),
3464 _gtk_boolean_handled_accumulator, NULL,
3465 _gtk_marshal_BOOLEAN__UINT,
3466 G_TYPE_BOOLEAN, 1, G_TYPE_UINT);
3467
3468 binding_set = gtk_binding_set_by_class (klass);
3469 gtk_binding_entry_add_signal (binding_set, GDK_KEY_F10, GDK_SHIFT_MASK,
3470 "popup-menu", 0);
3471 gtk_binding_entry_add_signal (binding_set, GDK_KEY_Menu, 0,
3472 "popup-menu", 0);
3473
3474 gtk_binding_entry_add_signal (binding_set, GDK_KEY_F1, GDK_CONTROL_MASK,
3475 "show-help", 1,
3476 GTK_TYPE_WIDGET_HELP_TYPE,
3477 GTK_WIDGET_HELP_TOOLTIP);
3478 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_F1, GDK_CONTROL_MASK,
3479 "show-help", 1,
3480 GTK_TYPE_WIDGET_HELP_TYPE,
3481 GTK_WIDGET_HELP_TOOLTIP);
3482 gtk_binding_entry_add_signal (binding_set, GDK_KEY_F1, GDK_SHIFT_MASK,
3483 "show-help", 1,
3484 GTK_TYPE_WIDGET_HELP_TYPE,
3485 GTK_WIDGET_HELP_WHATS_THIS);
3486 gtk_binding_entry_add_signal (binding_set, GDK_KEY_KP_F1, GDK_SHIFT_MASK,
3487 "show-help", 1,
3488 GTK_TYPE_WIDGET_HELP_TYPE,
3489 GTK_WIDGET_HELP_WHATS_THIS);
3490
3491 /**
3492 * GtkWidget:interior-focus:
3493 *
3494 * The "interior-focus" style property defines whether
3495 * to draw the focus indicator inside widgets.
3496 *
3497 * Deprecated: 3.14: use the outline CSS properties instead.
3498 */
3499 gtk_widget_class_install_style_property (klass,
3500 g_param_spec_boolean ("interior-focus",
3501 P_("Interior Focus"),
3502 P_("Whether to draw the focus indicator inside widgets"),
3503 TRUE,
3504 GTK_PARAM_READABLE | G_PARAM_DEPRECATED));
3505 /**
3506 * GtkWidget:focus-line-width:
3507 *
3508 * The "focus-line-width" style property defines the width,
3509 * in pixels, of the focus indicator line
3510 *
3511 * Deprecated: 3.14: use the outline-width and padding CSS properties instead.
3512 */
3513 gtk_widget_class_install_style_property (klass,
3514 g_param_spec_int ("focus-line-width",
3515 P_("Focus linewidth"),
3516 P_("Width, in pixels, of the focus indicator line"),
3517 0, G_MAXINT, 1,
3518 GTK_PARAM_READABLE | G_PARAM_DEPRECATED));
3519 /**
3520 * GtkWidget:focus-line-pattern:
3521 *
3522 * The "focus-line-pattern" style property defines the dash pattern used to
3523 * draw the focus indicator. The character values are interpreted as pixel
3524 * widths of alternating on and off segments of the line.
3525 *
3526 * Deprecated: 3.14: use the outline-style CSS property instead.
3527 */
3528 gtk_widget_class_install_style_property (klass,
3529 g_param_spec_string ("focus-line-pattern",
3530 P_("Focus line dash pattern"),
3531 P_("Dash pattern used to draw the focus indicator. The character values are interpreted as pixel widths of alternating on and off segments of the line."),
3532 "\1\1",
3533 GTK_PARAM_READABLE | G_PARAM_DEPRECATED));
3534 /**
3535 * GtkWidget:focus-padding:
3536 *
3537 * The "focus-padding" style property defines the width, in pixels,
3538 * between focus indicator and the widget 'box'.
3539 *
3540 * Deprecated: 3.14: use the outline-offset CSS properties instead.
3541 */
3542 gtk_widget_class_install_style_property (klass,
3543 g_param_spec_int ("focus-padding",
3544 P_("Focus padding"),
3545 P_("Width, in pixels, between focus indicator and the widget 'box'"),
3546 0, G_MAXINT, 1,
3547 GTK_PARAM_READABLE | G_PARAM_DEPRECATED));
3548 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3549 /**
3550 * GtkWidget:cursor-color:
3551 *
3552 * The color with which to draw the insertion cursor in entries and
3553 * text views.
3554 *
3555 * Deprecated: 3.20: Use the caret-color CSS property
3556 */
3557 gtk_widget_class_install_style_property (klass,
3558 g_param_spec_boxed ("cursor-color",
3559 P_("Cursor color"),
3560 P_("Color with which to draw insertion cursor"),
3561 GDK_TYPE_COLOR,
3562 GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
3563 /**
3564 * GtkWidget:secondary-cursor-color:
3565 *
3566 * The color with which to draw the secondary insertion cursor in entries and
3567 * text views when editing mixed right-to-left and left-to-right text.
3568 *
3569 * Deprecated: 3.20: Use the -gtk-secondary-caret-color CSS property
3570 */
3571 gtk_widget_class_install_style_property (klass,
3572 g_param_spec_boxed ("secondary-cursor-color",
3573 P_("Secondary cursor color"),
3574 P_("Color with which to draw the secondary insertion cursor when editing mixed right-to-left and left-to-right text"),
3575 GDK_TYPE_COLOR,
3576 GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
3577 G_GNUC_END_IGNORE_DEPRECATIONS
3578 gtk_widget_class_install_style_property (klass,
3579 g_param_spec_float ("cursor-aspect-ratio",
3580 P_("Cursor line aspect ratio"),
3581 P_("Aspect ratio with which to draw insertion cursor"),
3582 0.0, 1.0, 0.04,
3583 GTK_PARAM_READABLE));
3584
3585 gtk_widget_class_install_style_property (klass,
3586 g_param_spec_boolean ("window-dragging",
3587 P_("Window dragging"),
3588 P_("Whether windows can be dragged and maximized by clicking on empty areas"),
3589 FALSE,
3590 GTK_PARAM_READABLE));
3591
3592 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3593 /**
3594 * GtkWidget:link-color:
3595 *
3596 * The "link-color" style property defines the color of unvisited links.
3597 *
3598 * Since: 2.10
3599 *
3600 * Deprecated: 3.12: Links now use a separate state flags for selecting
3601 * different theming, this style property is ignored
3602 */
3603 gtk_widget_class_install_style_property (klass,
3604 g_param_spec_boxed ("link-color",
3605 P_("Unvisited Link Color"),
3606 P_("Color of unvisited links"),
3607 GDK_TYPE_COLOR,
3608 GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
3609
3610 /**
3611 * GtkWidget:visited-link-color:
3612 *
3613 * The "visited-link-color" style property defines the color of visited links.
3614 *
3615 * Since: 2.10
3616 *
3617 * Deprecated: 3.12: Links now use a separate state flags for selecting
3618 * different theming, this style property is ignored
3619 */
3620 gtk_widget_class_install_style_property (klass,
3621 g_param_spec_boxed ("visited-link-color",
3622 P_("Visited Link Color"),
3623 P_("Color of visited links"),
3624 GDK_TYPE_COLOR,
3625 GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
3626 G_GNUC_END_IGNORE_DEPRECATIONS
3627
3628 /**
3629 * GtkWidget:wide-separators:
3630 *
3631 * The "wide-separators" style property defines whether separators have
3632 * configurable width and should be drawn using a box instead of a line.
3633 *
3634 * Since: 2.10
3635 *
3636 * Deprecated: 3.20: Use CSS properties on the separator elements to style
3637 * separators; the value of this style property is ignored.
3638 */
3639 gtk_widget_class_install_style_property (klass,
3640 g_param_spec_boolean ("wide-separators",
3641 P_("Wide Separators"),
3642 P_("Whether separators have configurable width and should be drawn using a box instead of a line"),
3643 FALSE,
3644 GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
3645
3646 /**
3647 * GtkWidget:separator-width:
3648 *
3649 * The "separator-width" style property defines the width of separators.
3650 * This property only takes effect if the "wide-separators" style property is %TRUE.
3651 *
3652 * Since: 2.10
3653 *
3654 * Deprecated: 3.20: Use the standard min-width CSS property on the separator
3655 * elements to size separators; the value of this style property is ignored.
3656 */
3657 gtk_widget_class_install_style_property (klass,
3658 g_param_spec_int ("separator-width",
3659 P_("Separator Width"),
3660 P_("The width of separators if wide-separators is TRUE"),
3661 0, G_MAXINT, 0,
3662 GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
3663
3664 /**
3665 * GtkWidget:separator-height:
3666 *
3667 * The "separator-height" style property defines the height of separators.
3668 * This property only takes effect if the "wide-separators" style property is %TRUE.
3669 *
3670 * Since: 2.10
3671 *
3672 * Deprecated: 3.20: Use the standard min-height CSS property on the separator
3673 * elements to size separators; the value of this style property is ignored.
3674 */
3675 gtk_widget_class_install_style_property (klass,
3676 g_param_spec_int ("separator-height",
3677 P_("Separator Height"),
3678 P_("The height of separators if \"wide-separators\" is TRUE"),
3679 0, G_MAXINT, 0,
3680 GTK_PARAM_READABLE|G_PARAM_DEPRECATED));
3681
3682 /**
3683 * GtkWidget:scroll-arrow-hlength:
3684 *
3685 * The "scroll-arrow-hlength" style property defines the length of
3686 * horizontal scroll arrows.
3687 *
3688 * Since: 2.10
3689 */
3690 gtk_widget_class_install_style_property (klass,
3691 g_param_spec_int ("scroll-arrow-hlength",
3692 P_("Horizontal Scroll Arrow Length"),
3693 P_("The length of horizontal scroll arrows"),
3694 1, G_MAXINT, 16,
3695 GTK_PARAM_READABLE));
3696
3697 /**
3698 * GtkWidget:scroll-arrow-vlength:
3699 *
3700 * The "scroll-arrow-vlength" style property defines the length of
3701 * vertical scroll arrows.
3702 *
3703 * Since: 2.10
3704 */
3705 gtk_widget_class_install_style_property (klass,
3706 g_param_spec_int ("scroll-arrow-vlength",
3707 P_("Vertical Scroll Arrow Length"),
3708 P_("The length of vertical scroll arrows"),
3709 1, G_MAXINT, 16,
3710 GTK_PARAM_READABLE));
3711
3712 gtk_widget_class_install_style_property (klass,
3713 g_param_spec_int ("text-handle-width",
3714 P_("Width of text selection handles"),
3715 P_("Width of text selection handles"),
3716 1, G_MAXINT, 16,
3717 GTK_PARAM_READABLE));
3718 gtk_widget_class_install_style_property (klass,
3719 g_param_spec_int ("text-handle-height",
3720 P_("Height of text selection handles"),
3721 P_("Height of text selection handles"),
3722 1, G_MAXINT, 20,
3723 GTK_PARAM_READABLE));
3724
3725 gtk_widget_class_set_accessible_type (klass, GTK_TYPE_WIDGET_ACCESSIBLE);
3726 gtk_widget_class_set_css_name (klass, "widget");
3727 }
3728
3729 static void
gtk_widget_base_class_finalize(GtkWidgetClass * klass)3730 gtk_widget_base_class_finalize (GtkWidgetClass *klass)
3731 {
3732 GList *list, *node;
3733
3734 list = g_param_spec_pool_list_owned (style_property_spec_pool, G_OBJECT_CLASS_TYPE (klass));
3735 for (node = list; node; node = node->next)
3736 {
3737 GParamSpec *pspec = node->data;
3738
3739 g_param_spec_pool_remove (style_property_spec_pool, pspec);
3740 g_param_spec_unref (pspec);
3741 }
3742 g_list_free (list);
3743
3744 template_data_free (klass->priv->template);
3745 }
3746
3747 static void
gtk_widget_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)3748 gtk_widget_set_property (GObject *object,
3749 guint prop_id,
3750 const GValue *value,
3751 GParamSpec *pspec)
3752 {
3753 GtkWidget *widget = GTK_WIDGET (object);
3754
3755 switch (prop_id)
3756 {
3757 gboolean tmp;
3758 gchar *tooltip_markup;
3759 const gchar *tooltip_text;
3760 GtkWindow *tooltip_window;
3761
3762 case PROP_NAME:
3763 gtk_widget_set_name (widget, g_value_get_string (value));
3764 break;
3765 case PROP_PARENT:
3766 gtk_container_add (GTK_CONTAINER (g_value_get_object (value)), widget);
3767 break;
3768 case PROP_WIDTH_REQUEST:
3769 gtk_widget_set_usize_internal (widget, g_value_get_int (value), -2);
3770 break;
3771 case PROP_HEIGHT_REQUEST:
3772 gtk_widget_set_usize_internal (widget, -2, g_value_get_int (value));
3773 break;
3774 case PROP_VISIBLE:
3775 gtk_widget_set_visible (widget, g_value_get_boolean (value));
3776 break;
3777 case PROP_SENSITIVE:
3778 gtk_widget_set_sensitive (widget, g_value_get_boolean (value));
3779 break;
3780 case PROP_APP_PAINTABLE:
3781 gtk_widget_set_app_paintable (widget, g_value_get_boolean (value));
3782 break;
3783 case PROP_CAN_FOCUS:
3784 gtk_widget_set_can_focus (widget, g_value_get_boolean (value));
3785 break;
3786 case PROP_HAS_FOCUS:
3787 if (g_value_get_boolean (value))
3788 gtk_widget_grab_focus (widget);
3789 break;
3790 case PROP_IS_FOCUS:
3791 if (g_value_get_boolean (value))
3792 gtk_widget_grab_focus (widget);
3793 break;
3794 case PROP_FOCUS_ON_CLICK:
3795 gtk_widget_set_focus_on_click (widget, g_value_get_boolean (value));
3796 break;
3797 case PROP_CAN_DEFAULT:
3798 gtk_widget_set_can_default (widget, g_value_get_boolean (value));
3799 break;
3800 case PROP_HAS_DEFAULT:
3801 if (g_value_get_boolean (value))
3802 gtk_widget_grab_default (widget);
3803 break;
3804 case PROP_RECEIVES_DEFAULT:
3805 gtk_widget_set_receives_default (widget, g_value_get_boolean (value));
3806 break;
3807 case PROP_STYLE:
3808 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
3809 gtk_widget_set_style (widget, g_value_get_object (value));
3810 G_GNUC_END_IGNORE_DEPRECATIONS;
3811 break;
3812 case PROP_EVENTS:
3813 if (!_gtk_widget_get_realized (widget) && _gtk_widget_get_has_window (widget))
3814 gtk_widget_set_events (widget, g_value_get_flags (value));
3815 break;
3816 case PROP_NO_SHOW_ALL:
3817 gtk_widget_set_no_show_all (widget, g_value_get_boolean (value));
3818 break;
3819 case PROP_HAS_TOOLTIP:
3820 gtk_widget_real_set_has_tooltip (widget,
3821 g_value_get_boolean (value), FALSE);
3822 break;
3823 case PROP_TOOLTIP_MARKUP:
3824 tooltip_window = g_object_get_qdata (object, quark_tooltip_window);
3825 tooltip_markup = g_value_dup_string (value);
3826
3827 /* Treat an empty string as a NULL string,
3828 * because an empty string would be useless for a tooltip:
3829 */
3830 if (tooltip_markup && (strlen (tooltip_markup) == 0))
3831 {
3832 g_free (tooltip_markup);
3833 tooltip_markup = NULL;
3834 }
3835
3836 g_object_set_qdata_full (object, quark_tooltip_markup,
3837 tooltip_markup, g_free);
3838
3839 tmp = (tooltip_window != NULL || tooltip_markup != NULL);
3840 gtk_widget_real_set_has_tooltip (widget, tmp, FALSE);
3841 if (_gtk_widget_get_visible (widget))
3842 gtk_widget_queue_tooltip_query (widget);
3843 break;
3844 case PROP_TOOLTIP_TEXT:
3845 tooltip_window = g_object_get_qdata (object, quark_tooltip_window);
3846
3847 tooltip_text = g_value_get_string (value);
3848
3849 /* Treat an empty string as a NULL string,
3850 * because an empty string would be useless for a tooltip:
3851 */
3852 if (tooltip_text && (strlen (tooltip_text) == 0))
3853 tooltip_text = NULL;
3854
3855 tooltip_markup = tooltip_text ? g_markup_escape_text (tooltip_text, -1) : NULL;
3856
3857 g_object_set_qdata_full (object, quark_tooltip_markup,
3858 tooltip_markup, g_free);
3859
3860 tmp = (tooltip_window != NULL || tooltip_markup != NULL);
3861 gtk_widget_real_set_has_tooltip (widget, tmp, FALSE);
3862 if (_gtk_widget_get_visible (widget))
3863 gtk_widget_queue_tooltip_query (widget);
3864 break;
3865 case PROP_DOUBLE_BUFFERED:
3866 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
3867 gtk_widget_set_double_buffered (widget, g_value_get_boolean (value));
3868 G_GNUC_END_IGNORE_DEPRECATIONS
3869 break;
3870 case PROP_HALIGN:
3871 gtk_widget_set_halign (widget, g_value_get_enum (value));
3872 break;
3873 case PROP_VALIGN:
3874 gtk_widget_set_valign (widget, g_value_get_enum (value));
3875 break;
3876 case PROP_MARGIN_LEFT:
3877 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
3878 gtk_widget_set_margin_left (widget, g_value_get_int (value));
3879 G_GNUC_END_IGNORE_DEPRECATIONS;
3880 break;
3881 case PROP_MARGIN_RIGHT:
3882 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
3883 gtk_widget_set_margin_right (widget, g_value_get_int (value));
3884 G_GNUC_END_IGNORE_DEPRECATIONS;
3885 break;
3886 case PROP_MARGIN_START:
3887 gtk_widget_set_margin_start (widget, g_value_get_int (value));
3888 break;
3889 case PROP_MARGIN_END:
3890 gtk_widget_set_margin_end (widget, g_value_get_int (value));
3891 break;
3892 case PROP_MARGIN_TOP:
3893 gtk_widget_set_margin_top (widget, g_value_get_int (value));
3894 break;
3895 case PROP_MARGIN_BOTTOM:
3896 gtk_widget_set_margin_bottom (widget, g_value_get_int (value));
3897 break;
3898 case PROP_MARGIN:
3899 g_object_freeze_notify (G_OBJECT (widget));
3900 gtk_widget_set_margin_start (widget, g_value_get_int (value));
3901 gtk_widget_set_margin_end (widget, g_value_get_int (value));
3902 gtk_widget_set_margin_top (widget, g_value_get_int (value));
3903 gtk_widget_set_margin_bottom (widget, g_value_get_int (value));
3904 g_object_thaw_notify (G_OBJECT (widget));
3905 break;
3906 case PROP_HEXPAND:
3907 gtk_widget_set_hexpand (widget, g_value_get_boolean (value));
3908 break;
3909 case PROP_HEXPAND_SET:
3910 gtk_widget_set_hexpand_set (widget, g_value_get_boolean (value));
3911 break;
3912 case PROP_VEXPAND:
3913 gtk_widget_set_vexpand (widget, g_value_get_boolean (value));
3914 break;
3915 case PROP_VEXPAND_SET:
3916 gtk_widget_set_vexpand_set (widget, g_value_get_boolean (value));
3917 break;
3918 case PROP_EXPAND:
3919 g_object_freeze_notify (G_OBJECT (widget));
3920 gtk_widget_set_hexpand (widget, g_value_get_boolean (value));
3921 gtk_widget_set_vexpand (widget, g_value_get_boolean (value));
3922 g_object_thaw_notify (G_OBJECT (widget));
3923 break;
3924 case PROP_OPACITY:
3925 gtk_widget_set_opacity (widget, g_value_get_double (value));
3926 break;
3927 default:
3928 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
3929 break;
3930 }
3931 }
3932
3933 static void
gtk_widget_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)3934 gtk_widget_get_property (GObject *object,
3935 guint prop_id,
3936 GValue *value,
3937 GParamSpec *pspec)
3938 {
3939 GtkWidget *widget = GTK_WIDGET (object);
3940 GtkWidgetPrivate *priv = widget->priv;
3941
3942 switch (prop_id)
3943 {
3944 gpointer *eventp;
3945
3946 case PROP_NAME:
3947 if (priv->name)
3948 g_value_set_string (value, priv->name);
3949 else
3950 g_value_set_static_string (value, "");
3951 break;
3952 case PROP_PARENT:
3953 g_value_set_object (value, priv->parent);
3954 break;
3955 case PROP_WIDTH_REQUEST:
3956 {
3957 int w;
3958 gtk_widget_get_size_request (widget, &w, NULL);
3959 g_value_set_int (value, w);
3960 }
3961 break;
3962 case PROP_HEIGHT_REQUEST:
3963 {
3964 int h;
3965 gtk_widget_get_size_request (widget, NULL, &h);
3966 g_value_set_int (value, h);
3967 }
3968 break;
3969 case PROP_VISIBLE:
3970 g_value_set_boolean (value, _gtk_widget_get_visible (widget));
3971 break;
3972 case PROP_SENSITIVE:
3973 g_value_set_boolean (value, gtk_widget_get_sensitive (widget));
3974 break;
3975 case PROP_APP_PAINTABLE:
3976 g_value_set_boolean (value, gtk_widget_get_app_paintable (widget));
3977 break;
3978 case PROP_CAN_FOCUS:
3979 g_value_set_boolean (value, gtk_widget_get_can_focus (widget));
3980 break;
3981 case PROP_HAS_FOCUS:
3982 g_value_set_boolean (value, gtk_widget_has_focus (widget));
3983 break;
3984 case PROP_IS_FOCUS:
3985 g_value_set_boolean (value, gtk_widget_is_focus (widget));
3986 break;
3987 case PROP_FOCUS_ON_CLICK:
3988 g_value_set_boolean (value, gtk_widget_get_focus_on_click (widget));
3989 break;
3990 case PROP_CAN_DEFAULT:
3991 g_value_set_boolean (value, gtk_widget_get_can_default (widget));
3992 break;
3993 case PROP_HAS_DEFAULT:
3994 g_value_set_boolean (value, gtk_widget_has_default (widget));
3995 break;
3996 case PROP_RECEIVES_DEFAULT:
3997 g_value_set_boolean (value, gtk_widget_get_receives_default (widget));
3998 break;
3999 case PROP_COMPOSITE_CHILD:
4000 g_value_set_boolean (value, widget->priv->composite_child);
4001 break;
4002 case PROP_STYLE:
4003 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
4004 g_value_set_object (value, gtk_widget_get_style (widget));
4005 G_GNUC_END_IGNORE_DEPRECATIONS;
4006 break;
4007 case PROP_EVENTS:
4008 eventp = g_object_get_qdata (G_OBJECT (widget), quark_event_mask);
4009 g_value_set_flags (value, GPOINTER_TO_INT (eventp));
4010 break;
4011 case PROP_NO_SHOW_ALL:
4012 g_value_set_boolean (value, gtk_widget_get_no_show_all (widget));
4013 break;
4014 case PROP_HAS_TOOLTIP:
4015 g_value_set_boolean (value, gtk_widget_get_has_tooltip (widget));
4016 break;
4017 case PROP_TOOLTIP_TEXT:
4018 {
4019 gchar *escaped = g_object_get_qdata (object, quark_tooltip_markup);
4020 gchar *text = NULL;
4021
4022 if (escaped && !pango_parse_markup (escaped, -1, 0, NULL, &text, NULL, NULL))
4023 g_assert (NULL == text); /* text should still be NULL in case of markup errors */
4024
4025 g_value_take_string (value, text);
4026 }
4027 break;
4028 case PROP_TOOLTIP_MARKUP:
4029 g_value_set_string (value, g_object_get_qdata (object, quark_tooltip_markup));
4030 break;
4031 case PROP_WINDOW:
4032 g_value_set_object (value, _gtk_widget_get_window (widget));
4033 break;
4034 case PROP_DOUBLE_BUFFERED:
4035 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
4036 g_value_set_boolean (value, gtk_widget_get_double_buffered (widget));
4037 G_GNUC_END_IGNORE_DEPRECATIONS
4038 break;
4039 case PROP_HALIGN:
4040 g_value_set_enum (value, gtk_widget_get_halign (widget));
4041 break;
4042 case PROP_VALIGN:
4043 g_value_set_enum (value, gtk_widget_get_valign_with_baseline (widget));
4044 break;
4045 case PROP_MARGIN_LEFT:
4046 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
4047 g_value_set_int (value, gtk_widget_get_margin_left (widget));
4048 G_GNUC_END_IGNORE_DEPRECATIONS;
4049 break;
4050 case PROP_MARGIN_RIGHT:
4051 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
4052 g_value_set_int (value, gtk_widget_get_margin_right (widget));
4053 G_GNUC_END_IGNORE_DEPRECATIONS;
4054 break;
4055 case PROP_MARGIN_START:
4056 g_value_set_int (value, gtk_widget_get_margin_start (widget));
4057 break;
4058 case PROP_MARGIN_END:
4059 g_value_set_int (value, gtk_widget_get_margin_end (widget));
4060 break;
4061 case PROP_MARGIN_TOP:
4062 g_value_set_int (value, gtk_widget_get_margin_top (widget));
4063 break;
4064 case PROP_MARGIN_BOTTOM:
4065 g_value_set_int (value, gtk_widget_get_margin_bottom (widget));
4066 break;
4067 case PROP_MARGIN:
4068 g_value_set_int (value, MAX (MAX (priv->margin.left,
4069 priv->margin.right),
4070 MAX (priv->margin.top,
4071 priv->margin.bottom)));
4072 break;
4073 case PROP_HEXPAND:
4074 g_value_set_boolean (value, gtk_widget_get_hexpand (widget));
4075 break;
4076 case PROP_HEXPAND_SET:
4077 g_value_set_boolean (value, gtk_widget_get_hexpand_set (widget));
4078 break;
4079 case PROP_VEXPAND:
4080 g_value_set_boolean (value, gtk_widget_get_vexpand (widget));
4081 break;
4082 case PROP_VEXPAND_SET:
4083 g_value_set_boolean (value, gtk_widget_get_vexpand_set (widget));
4084 break;
4085 case PROP_EXPAND:
4086 g_value_set_boolean (value,
4087 gtk_widget_get_hexpand (widget) &&
4088 gtk_widget_get_vexpand (widget));
4089 break;
4090 case PROP_OPACITY:
4091 g_value_set_double (value, gtk_widget_get_opacity (widget));
4092 break;
4093 case PROP_SCALE_FACTOR:
4094 g_value_set_int (value, gtk_widget_get_scale_factor (widget));
4095 break;
4096 default:
4097 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
4098 break;
4099 }
4100 }
4101
4102 static void
_gtk_widget_emulate_press(GtkWidget * widget,const GdkEvent * event)4103 _gtk_widget_emulate_press (GtkWidget *widget,
4104 const GdkEvent *event)
4105 {
4106 GtkWidget *event_widget, *next_child, *parent;
4107 GdkEvent *press;
4108
4109 event_widget = gtk_get_event_widget ((GdkEvent *) event);
4110
4111 if (event_widget == widget)
4112 return;
4113
4114 if (event->type == GDK_TOUCH_BEGIN ||
4115 event->type == GDK_TOUCH_UPDATE ||
4116 event->type == GDK_TOUCH_END)
4117 {
4118 press = gdk_event_copy (event);
4119 press->type = GDK_TOUCH_BEGIN;
4120 }
4121 else if (event->type == GDK_BUTTON_PRESS ||
4122 event->type == GDK_BUTTON_RELEASE)
4123 {
4124 press = gdk_event_copy (event);
4125 press->type = GDK_BUTTON_PRESS;
4126 }
4127 else if (event->type == GDK_MOTION_NOTIFY)
4128 {
4129 press = gdk_event_new (GDK_BUTTON_PRESS);
4130 press->button.window = g_object_ref (event->motion.window);
4131 press->button.time = event->motion.time;
4132 press->button.x = event->motion.x;
4133 press->button.y = event->motion.y;
4134 press->button.x_root = event->motion.x_root;
4135 press->button.y_root = event->motion.y_root;
4136 press->button.state = event->motion.state;
4137
4138 press->button.axes = g_memdup (event->motion.axes,
4139 sizeof (gdouble) *
4140 gdk_device_get_n_axes (event->motion.device));
4141
4142 if (event->motion.state & GDK_BUTTON3_MASK)
4143 press->button.button = 3;
4144 else if (event->motion.state & GDK_BUTTON2_MASK)
4145 press->button.button = 2;
4146 else
4147 {
4148 if ((event->motion.state & GDK_BUTTON1_MASK) == 0)
4149 g_critical ("Guessing button number 1 on generated button press event");
4150
4151 press->button.button = 1;
4152 }
4153
4154 gdk_event_set_device (press, gdk_event_get_device (event));
4155 gdk_event_set_source_device (press, gdk_event_get_source_device (event));
4156 }
4157 else
4158 return;
4159
4160 press->any.send_event = TRUE;
4161 next_child = event_widget;
4162 parent = _gtk_widget_get_parent (next_child);
4163
4164 while (parent != widget)
4165 {
4166 next_child = parent;
4167 parent = _gtk_widget_get_parent (parent);
4168 }
4169
4170 /* Perform propagation state starting from the next child in the chain */
4171 if (!_gtk_propagate_captured_event (event_widget, press, next_child))
4172 gtk_propagate_event (event_widget, press);
4173
4174 gdk_event_free (press);
4175 }
4176
4177 static const GdkEvent *
_gtk_widget_get_last_event(GtkWidget * widget,GdkEventSequence * sequence)4178 _gtk_widget_get_last_event (GtkWidget *widget,
4179 GdkEventSequence *sequence)
4180 {
4181 GtkWidgetPrivate *priv = widget->priv;
4182 EventControllerData *data;
4183 const GdkEvent *event;
4184 GList *l;
4185
4186 for (l = priv->event_controllers; l; l = l->next)
4187 {
4188 data = l->data;
4189
4190 if (!GTK_IS_GESTURE (data->controller))
4191 continue;
4192
4193 event = gtk_gesture_get_last_event (GTK_GESTURE (data->controller),
4194 sequence);
4195 if (event)
4196 return event;
4197 }
4198
4199 return NULL;
4200 }
4201
4202 static gboolean
_gtk_widget_get_emulating_sequence(GtkWidget * widget,GdkEventSequence * sequence,GdkEventSequence ** sequence_out)4203 _gtk_widget_get_emulating_sequence (GtkWidget *widget,
4204 GdkEventSequence *sequence,
4205 GdkEventSequence **sequence_out)
4206 {
4207 GtkWidgetPrivate *priv = widget->priv;
4208 GList *l;
4209
4210 *sequence_out = sequence;
4211
4212 if (sequence)
4213 {
4214 const GdkEvent *last_event;
4215
4216 last_event = _gtk_widget_get_last_event (widget, sequence);
4217
4218 if (last_event &&
4219 (last_event->type == GDK_TOUCH_BEGIN ||
4220 last_event->type == GDK_TOUCH_UPDATE ||
4221 last_event->type == GDK_TOUCH_END) &&
4222 last_event->touch.emulating_pointer)
4223 return TRUE;
4224 }
4225 else
4226 {
4227 /* For a NULL(pointer) sequence, find the pointer emulating one */
4228 for (l = priv->event_controllers; l; l = l->next)
4229 {
4230 EventControllerData *data = l->data;
4231
4232 if (!GTK_IS_GESTURE (data->controller))
4233 continue;
4234
4235 if (_gtk_gesture_get_pointer_emulating_sequence (GTK_GESTURE (data->controller),
4236 sequence_out))
4237 return TRUE;
4238 }
4239 }
4240
4241 return FALSE;
4242 }
4243
4244 static gboolean
gtk_widget_needs_press_emulation(GtkWidget * widget,GdkEventSequence * sequence)4245 gtk_widget_needs_press_emulation (GtkWidget *widget,
4246 GdkEventSequence *sequence)
4247 {
4248 GtkWidgetPrivate *priv = widget->priv;
4249 gboolean sequence_press_handled = FALSE;
4250 GList *l;
4251
4252 /* Check whether there is any remaining gesture in
4253 * the capture phase that handled the press event
4254 */
4255 for (l = priv->event_controllers; l; l = l->next)
4256 {
4257 EventControllerData *data;
4258 GtkPropagationPhase phase;
4259 GtkGesture *gesture;
4260
4261 data = l->data;
4262 phase = gtk_event_controller_get_propagation_phase (data->controller);
4263
4264 if (phase != GTK_PHASE_CAPTURE)
4265 continue;
4266 if (!GTK_IS_GESTURE (data->controller))
4267 continue;
4268
4269 gesture = GTK_GESTURE (data->controller);
4270 sequence_press_handled |=
4271 (gtk_gesture_handles_sequence (gesture, sequence) &&
4272 _gtk_gesture_handled_sequence_press (gesture, sequence));
4273 }
4274
4275 return !sequence_press_handled;
4276 }
4277
4278 static gint
_gtk_widget_set_sequence_state_internal(GtkWidget * widget,GdkEventSequence * sequence,GtkEventSequenceState state,GtkGesture * emitter)4279 _gtk_widget_set_sequence_state_internal (GtkWidget *widget,
4280 GdkEventSequence *sequence,
4281 GtkEventSequenceState state,
4282 GtkGesture *emitter)
4283 {
4284 gboolean emulates_pointer, sequence_handled = FALSE;
4285 GtkWidgetPrivate *priv = widget->priv;
4286 const GdkEvent *mimic_event;
4287 GList *group = NULL, *l;
4288 GdkEventSequence *seq;
4289 gint n_handled = 0;
4290
4291 if (!priv->event_controllers && state != GTK_EVENT_SEQUENCE_CLAIMED)
4292 return TRUE;
4293
4294 if (emitter)
4295 group = gtk_gesture_get_group (emitter);
4296
4297 emulates_pointer = _gtk_widget_get_emulating_sequence (widget, sequence, &seq);
4298 mimic_event = _gtk_widget_get_last_event (widget, seq);
4299
4300 for (l = priv->event_controllers; l; l = l->next)
4301 {
4302 GtkEventSequenceState gesture_state;
4303 EventControllerData *data;
4304 GtkGesture *gesture;
4305 gboolean retval;
4306
4307 seq = sequence;
4308 data = l->data;
4309 gesture_state = state;
4310
4311 if (!GTK_IS_GESTURE (data->controller))
4312 continue;
4313
4314 gesture = GTK_GESTURE (data->controller);
4315
4316 if (gesture == emitter)
4317 {
4318 sequence_handled |=
4319 _gtk_gesture_handled_sequence_press (gesture, sequence);
4320 n_handled++;
4321 continue;
4322 }
4323
4324 if (seq && emulates_pointer &&
4325 !gtk_gesture_handles_sequence (gesture, seq))
4326 seq = NULL;
4327
4328 if (group && !g_list_find (group, data->controller))
4329 {
4330 /* If a group is provided, ensure only gestures pertaining to the group
4331 * get a "claimed" state, all other claiming gestures must deny the sequence.
4332 */
4333 if (gesture_state == GTK_EVENT_SEQUENCE_CLAIMED &&
4334 gtk_gesture_get_sequence_state (gesture, sequence) == GTK_EVENT_SEQUENCE_CLAIMED)
4335 gesture_state = GTK_EVENT_SEQUENCE_DENIED;
4336 else
4337 continue;
4338 }
4339 else if (!group &&
4340 gtk_gesture_get_sequence_state (gesture, sequence) != GTK_EVENT_SEQUENCE_CLAIMED)
4341 continue;
4342
4343 g_signal_handler_block (data->controller, data->sequence_state_changed_id);
4344 retval = gtk_gesture_set_sequence_state (gesture, seq, gesture_state);
4345 g_signal_handler_unblock (data->controller, data->sequence_state_changed_id);
4346
4347 if (retval || gesture == emitter)
4348 {
4349 sequence_handled |=
4350 _gtk_gesture_handled_sequence_press (gesture, seq);
4351 n_handled++;
4352 }
4353 }
4354
4355 /* If the sequence goes denied, check whether this is a controller attached
4356 * to the capture phase, that additionally handled the button/touch press (i.e.
4357 * it was consumed), the corresponding press will be emulated for widgets
4358 * beneath, so the widgets beneath get a coherent stream of events from now on.
4359 */
4360 if (n_handled > 0 && sequence_handled &&
4361 state == GTK_EVENT_SEQUENCE_DENIED &&
4362 gtk_widget_needs_press_emulation (widget, sequence))
4363 _gtk_widget_emulate_press (widget, mimic_event);
4364
4365 g_list_free (group);
4366
4367 return n_handled;
4368 }
4369
4370 static gboolean
_gtk_widget_cancel_sequence(GtkWidget * widget,GdkEventSequence * sequence)4371 _gtk_widget_cancel_sequence (GtkWidget *widget,
4372 GdkEventSequence *sequence)
4373 {
4374 GtkWidgetPrivate *priv = widget->priv;
4375 gboolean emulates_pointer;
4376 gboolean handled = FALSE;
4377 GdkEventSequence *seq;
4378 GList *l;
4379
4380 emulates_pointer = _gtk_widget_get_emulating_sequence (widget, sequence, &seq);
4381
4382 for (l = priv->event_controllers; l; l = l->next)
4383 {
4384 EventControllerData *data;
4385 GtkGesture *gesture;
4386
4387 seq = sequence;
4388 data = l->data;
4389
4390 if (!GTK_IS_GESTURE (data->controller))
4391 continue;
4392
4393 gesture = GTK_GESTURE (data->controller);
4394
4395 if (seq && emulates_pointer &&
4396 !gtk_gesture_handles_sequence (gesture, seq))
4397 seq = NULL;
4398
4399 if (!gtk_gesture_handles_sequence (gesture, seq))
4400 continue;
4401
4402 handled |= _gtk_gesture_cancel_sequence (gesture, seq);
4403 }
4404
4405 return handled;
4406 }
4407
4408 static void
gtk_widget_init(GTypeInstance * instance,gpointer g_class)4409 gtk_widget_init (GTypeInstance *instance, gpointer g_class)
4410 {
4411 GtkWidget *widget = GTK_WIDGET (instance);
4412 GtkWidgetPrivate *priv;
4413
4414 widget->priv = gtk_widget_get_instance_private (widget);
4415 priv = widget->priv;
4416
4417 priv->child_visible = TRUE;
4418 priv->name = NULL;
4419 priv->allocation.x = -1;
4420 priv->allocation.y = -1;
4421 priv->allocation.width = 1;
4422 priv->allocation.height = 1;
4423 priv->user_alpha = 255;
4424 priv->alpha = 255;
4425 priv->window = NULL;
4426 priv->parent = NULL;
4427
4428 priv->sensitive = TRUE;
4429 priv->composite_child = composite_child_stack != 0;
4430 priv->double_buffered = TRUE;
4431 priv->redraw_on_alloc = TRUE;
4432 priv->alloc_needed = TRUE;
4433 priv->alloc_needed_on_child = TRUE;
4434 priv->focus_on_click = TRUE;
4435 #ifdef G_ENABLE_DEBUG
4436 priv->highlight_resize = FALSE;
4437 #endif
4438
4439 switch (_gtk_widget_get_direction (widget))
4440 {
4441 case GTK_TEXT_DIR_LTR:
4442 priv->state_flags = GTK_STATE_FLAG_DIR_LTR;
4443 break;
4444
4445 case GTK_TEXT_DIR_RTL:
4446 priv->state_flags = GTK_STATE_FLAG_DIR_RTL;
4447 break;
4448
4449 case GTK_TEXT_DIR_NONE:
4450 default:
4451 g_assert_not_reached ();
4452 break;
4453 }
4454
4455 /* this will be set to TRUE if the widget gets a child or if the
4456 * expand flag is set on the widget, but until one of those happen
4457 * we know the expand is already properly FALSE.
4458 *
4459 * We really want to default FALSE here to avoid computing expand
4460 * all over the place while initially building a widget tree.
4461 */
4462 priv->need_compute_expand = FALSE;
4463
4464 priv->halign = GTK_ALIGN_FILL;
4465 priv->valign = GTK_ALIGN_FILL;
4466
4467 priv->width = -1;
4468 priv->height = -1;
4469
4470 _gtk_size_request_cache_init (&priv->requests);
4471
4472 priv->cssnode = gtk_css_widget_node_new (widget);
4473 gtk_css_node_set_state (priv->cssnode, priv->state_flags);
4474 /* need to set correct type here, and only class has the correct type here */
4475 gtk_css_node_set_widget_type (priv->cssnode, G_TYPE_FROM_CLASS (g_class));
4476 gtk_css_node_set_name (priv->cssnode, GTK_WIDGET_CLASS (g_class)->priv->css_name);
4477
4478 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
4479 priv->style = gtk_widget_get_default_style ();
4480 G_GNUC_END_IGNORE_DEPRECATIONS;
4481 g_object_ref (priv->style);
4482 }
4483
4484
4485 static void
gtk_widget_dispatch_child_properties_changed(GtkWidget * widget,guint n_pspecs,GParamSpec ** pspecs)4486 gtk_widget_dispatch_child_properties_changed (GtkWidget *widget,
4487 guint n_pspecs,
4488 GParamSpec **pspecs)
4489 {
4490 GtkWidgetPrivate *priv = widget->priv;
4491 GtkWidget *container = priv->parent;
4492 guint i;
4493
4494 for (i = 0; widget->priv->parent == container && i < n_pspecs; i++)
4495 g_signal_emit (widget, widget_signals[CHILD_NOTIFY], g_param_spec_get_name_quark (pspecs[i]), pspecs[i]);
4496 }
4497
4498 /**
4499 * gtk_widget_freeze_child_notify:
4500 * @widget: a #GtkWidget
4501 *
4502 * Stops emission of #GtkWidget::child-notify signals on @widget. The
4503 * signals are queued until gtk_widget_thaw_child_notify() is called
4504 * on @widget.
4505 *
4506 * This is the analogue of g_object_freeze_notify() for child properties.
4507 **/
4508 void
gtk_widget_freeze_child_notify(GtkWidget * widget)4509 gtk_widget_freeze_child_notify (GtkWidget *widget)
4510 {
4511 g_return_if_fail (GTK_IS_WIDGET (widget));
4512
4513 if (!G_OBJECT (widget)->ref_count)
4514 return;
4515
4516 g_object_ref (widget);
4517 g_object_notify_queue_freeze (G_OBJECT (widget), _gtk_widget_child_property_notify_context);
4518 g_object_unref (widget);
4519 }
4520
4521 /**
4522 * gtk_widget_child_notify:
4523 * @widget: a #GtkWidget
4524 * @child_property: the name of a child property installed on the
4525 * class of @widget’s parent
4526 *
4527 * Emits a #GtkWidget::child-notify signal for the
4528 * [child property][child-properties] @child_property
4529 * on @widget.
4530 *
4531 * This is the analogue of g_object_notify() for child properties.
4532 *
4533 * Also see gtk_container_child_notify().
4534 */
4535 void
gtk_widget_child_notify(GtkWidget * widget,const gchar * child_property)4536 gtk_widget_child_notify (GtkWidget *widget,
4537 const gchar *child_property)
4538 {
4539 if (widget->priv->parent == NULL)
4540 return;
4541
4542 gtk_container_child_notify (GTK_CONTAINER (widget->priv->parent), widget, child_property);
4543 }
4544
4545 /**
4546 * gtk_widget_thaw_child_notify:
4547 * @widget: a #GtkWidget
4548 *
4549 * Reverts the effect of a previous call to gtk_widget_freeze_child_notify().
4550 * This causes all queued #GtkWidget::child-notify signals on @widget to be
4551 * emitted.
4552 */
4553 void
gtk_widget_thaw_child_notify(GtkWidget * widget)4554 gtk_widget_thaw_child_notify (GtkWidget *widget)
4555 {
4556 GObjectNotifyQueue *nqueue;
4557
4558 g_return_if_fail (GTK_IS_WIDGET (widget));
4559
4560 if (!G_OBJECT (widget)->ref_count)
4561 return;
4562
4563 g_object_ref (widget);
4564 nqueue = g_object_notify_queue_from_object (G_OBJECT (widget), _gtk_widget_child_property_notify_context);
4565 if (!nqueue || !nqueue->freeze_count)
4566 g_warning (G_STRLOC ": child-property-changed notification for %s(%p) is not frozen",
4567 G_OBJECT_TYPE_NAME (widget), widget);
4568 else
4569 g_object_notify_queue_thaw (G_OBJECT (widget), nqueue);
4570 g_object_unref (widget);
4571 }
4572
4573
4574 /**
4575 * gtk_widget_new:
4576 * @type: type ID of the widget to create
4577 * @first_property_name: name of first property to set
4578 * @...: value of first property, followed by more properties,
4579 * %NULL-terminated
4580 *
4581 * This is a convenience function for creating a widget and setting
4582 * its properties in one go. For example you might write:
4583 * `gtk_widget_new (GTK_TYPE_LABEL, "label", "Hello World", "xalign",
4584 * 0.0, NULL)` to create a left-aligned label. Equivalent to
4585 * g_object_new(), but returns a widget so you don’t have to
4586 * cast the object yourself.
4587 *
4588 * Returns: a new #GtkWidget of type @widget_type
4589 **/
4590 GtkWidget*
gtk_widget_new(GType type,const gchar * first_property_name,...)4591 gtk_widget_new (GType type,
4592 const gchar *first_property_name,
4593 ...)
4594 {
4595 GtkWidget *widget;
4596 va_list var_args;
4597
4598 g_return_val_if_fail (g_type_is_a (type, GTK_TYPE_WIDGET), NULL);
4599
4600 va_start (var_args, first_property_name);
4601 widget = (GtkWidget *)g_object_new_valist (type, first_property_name, var_args);
4602 va_end (var_args);
4603
4604 return widget;
4605 }
4606
4607 static inline void
gtk_widget_queue_draw_child(GtkWidget * widget)4608 gtk_widget_queue_draw_child (GtkWidget *widget)
4609 {
4610 GtkWidgetPrivate *priv = widget->priv;
4611 GtkWidget *parent;
4612
4613 parent = priv->parent;
4614 if (parent && _gtk_widget_is_drawable (parent))
4615 gtk_widget_queue_draw_area (parent,
4616 priv->clip.x,
4617 priv->clip.y,
4618 priv->clip.width,
4619 priv->clip.height);
4620 }
4621
4622 /**
4623 * gtk_widget_unparent:
4624 * @widget: a #GtkWidget
4625 *
4626 * This function is only for use in widget implementations.
4627 * Should be called by implementations of the remove method
4628 * on #GtkContainer, to dissociate a child from the container.
4629 **/
4630 void
gtk_widget_unparent(GtkWidget * widget)4631 gtk_widget_unparent (GtkWidget *widget)
4632 {
4633 GtkWidgetPrivate *priv;
4634 GObjectNotifyQueue *nqueue;
4635 GtkWidget *toplevel;
4636 GtkWidget *old_parent;
4637
4638 g_return_if_fail (GTK_IS_WIDGET (widget));
4639
4640 priv = widget->priv;
4641
4642 if (priv->parent == NULL)
4643 return;
4644
4645 /* keep this function in sync with gtk_menu_detach() */
4646
4647 gtk_widget_push_verify_invariants (widget);
4648
4649 g_object_freeze_notify (G_OBJECT (widget));
4650 nqueue = g_object_notify_queue_freeze (G_OBJECT (widget), _gtk_widget_child_property_notify_context);
4651
4652 toplevel = _gtk_widget_get_toplevel (widget);
4653 if (_gtk_widget_is_toplevel (toplevel))
4654 _gtk_window_unset_focus_and_default (GTK_WINDOW (toplevel), widget);
4655
4656 if (gtk_container_get_focus_child (GTK_CONTAINER (priv->parent)) == widget)
4657 gtk_container_set_focus_child (GTK_CONTAINER (priv->parent), NULL);
4658
4659 gtk_widget_queue_draw_child (widget);
4660
4661 /* Reset the width and height here, to force reallocation if we
4662 * get added back to a new parent. This won't work if our new
4663 * allocation is smaller than 1x1 and we actually want a size of 1x1...
4664 * (would 0x0 be OK here?)
4665 */
4666 priv->allocation.width = 1;
4667 priv->allocation.height = 1;
4668
4669 if (_gtk_widget_get_realized (widget))
4670 {
4671 if (priv->in_reparent)
4672 gtk_widget_unmap (widget);
4673 else
4674 gtk_widget_unrealize (widget);
4675 }
4676
4677 /* If we are unanchoring the child, we save around the toplevel
4678 * to emit hierarchy changed
4679 */
4680 if (priv->parent->priv->anchored)
4681 g_object_ref (toplevel);
4682 else
4683 toplevel = NULL;
4684
4685 /* Removing a widget from a container restores the child visible
4686 * flag to the default state, so it doesn't affect the child
4687 * in the next parent.
4688 */
4689 priv->child_visible = TRUE;
4690
4691 old_parent = priv->parent;
4692 priv->parent = NULL;
4693
4694 /* parent may no longer expand if the removed
4695 * child was expand=TRUE and could therefore
4696 * be forcing it to.
4697 */
4698 if (_gtk_widget_get_visible (widget) &&
4699 (priv->need_compute_expand ||
4700 priv->computed_hexpand ||
4701 priv->computed_vexpand))
4702 {
4703 gtk_widget_queue_compute_expand (old_parent);
4704 }
4705
4706 /* Unset BACKDROP since we are no longer inside a toplevel window */
4707 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP);
4708 if (priv->context)
4709 gtk_style_context_set_parent (priv->context, NULL);
4710 gtk_css_node_set_parent (widget->priv->cssnode, NULL);
4711
4712 _gtk_widget_update_parent_muxer (widget);
4713
4714 g_signal_emit (widget, widget_signals[PARENT_SET], 0, old_parent);
4715 if (toplevel)
4716 {
4717 _gtk_widget_propagate_hierarchy_changed (widget, toplevel);
4718 g_object_unref (toplevel);
4719 }
4720
4721 /* Now that the parent pointer is nullified and the hierarchy-changed
4722 * already passed, go ahead and unset the parent window, if we are unparenting
4723 * an embedded GtkWindow the window will become toplevel again and hierarchy-changed
4724 * will fire again for the new subhierarchy.
4725 */
4726 gtk_widget_set_parent_window (widget, NULL);
4727
4728 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_PARENT]);
4729 g_object_thaw_notify (G_OBJECT (widget));
4730 if (!priv->parent)
4731 g_object_notify_queue_clear (G_OBJECT (widget), nqueue);
4732 g_object_notify_queue_thaw (G_OBJECT (widget), nqueue);
4733
4734 gtk_widget_pop_verify_invariants (widget);
4735 g_object_unref (widget);
4736 }
4737
4738 /**
4739 * gtk_widget_destroy:
4740 * @widget: a #GtkWidget
4741 *
4742 * Destroys a widget.
4743 *
4744 * When a widget is destroyed all references it holds on other objects
4745 * will be released:
4746 *
4747 * - if the widget is inside a container, it will be removed from its
4748 * parent
4749 * - if the widget is a container, all its children will be destroyed,
4750 * recursively
4751 * - if the widget is a top level, it will be removed from the list
4752 * of top level widgets that GTK+ maintains internally
4753 *
4754 * It's expected that all references held on the widget will also
4755 * be released; you should connect to the #GtkWidget::destroy signal
4756 * if you hold a reference to @widget and you wish to remove it when
4757 * this function is called. It is not necessary to do so if you are
4758 * implementing a #GtkContainer, as you'll be able to use the
4759 * #GtkContainerClass.remove() virtual function for that.
4760 *
4761 * It's important to notice that gtk_widget_destroy() will only cause
4762 * the @widget to be finalized if no additional references, acquired
4763 * using g_object_ref(), are held on it. In case additional references
4764 * are in place, the @widget will be in an "inert" state after calling
4765 * this function; @widget will still point to valid memory, allowing you
4766 * to release the references you hold, but you may not query the widget's
4767 * own state.
4768 *
4769 * You should typically call this function on top level widgets, and
4770 * rarely on child widgets.
4771 *
4772 * See also: gtk_container_remove()
4773 */
4774 void
gtk_widget_destroy(GtkWidget * widget)4775 gtk_widget_destroy (GtkWidget *widget)
4776 {
4777 g_return_if_fail (GTK_IS_WIDGET (widget));
4778
4779 if (!widget->priv->in_destruction)
4780 g_object_run_dispose (G_OBJECT (widget));
4781 }
4782
4783 /**
4784 * gtk_widget_destroyed:
4785 * @widget: a #GtkWidget
4786 * @widget_pointer: (inout) (transfer none): address of a variable that contains @widget
4787 *
4788 * This function sets *@widget_pointer to %NULL if @widget_pointer !=
4789 * %NULL. It’s intended to be used as a callback connected to the
4790 * “destroy” signal of a widget. You connect gtk_widget_destroyed()
4791 * as a signal handler, and pass the address of your widget variable
4792 * as user data. Then when the widget is destroyed, the variable will
4793 * be set to %NULL. Useful for example to avoid multiple copies
4794 * of the same dialog.
4795 **/
4796 void
gtk_widget_destroyed(GtkWidget * widget,GtkWidget ** widget_pointer)4797 gtk_widget_destroyed (GtkWidget *widget,
4798 GtkWidget **widget_pointer)
4799 {
4800 /* Don't make any assumptions about the
4801 * value of widget!
4802 * Even check widget_pointer.
4803 */
4804 if (widget_pointer)
4805 *widget_pointer = NULL;
4806 }
4807
4808 /**
4809 * gtk_widget_show:
4810 * @widget: a #GtkWidget
4811 *
4812 * Flags a widget to be displayed. Any widget that isn’t shown will
4813 * not appear on the screen. If you want to show all the widgets in a
4814 * container, it’s easier to call gtk_widget_show_all() on the
4815 * container, instead of individually showing the widgets.
4816 *
4817 * Remember that you have to show the containers containing a widget,
4818 * in addition to the widget itself, before it will appear onscreen.
4819 *
4820 * When a toplevel container is shown, it is immediately realized and
4821 * mapped; other shown widgets are realized and mapped when their
4822 * toplevel container is realized and mapped.
4823 **/
4824 void
gtk_widget_show(GtkWidget * widget)4825 gtk_widget_show (GtkWidget *widget)
4826 {
4827 g_return_if_fail (GTK_IS_WIDGET (widget));
4828
4829 if (!_gtk_widget_get_visible (widget))
4830 {
4831 GtkWidget *parent;
4832
4833 g_object_ref (widget);
4834 gtk_widget_push_verify_invariants (widget);
4835
4836 parent = _gtk_widget_get_parent (widget);
4837 if (parent)
4838 {
4839 gtk_widget_queue_resize (parent);
4840
4841 /* see comment in set_parent() for why this should and can be
4842 * conditional
4843 */
4844 if (widget->priv->need_compute_expand ||
4845 widget->priv->computed_hexpand ||
4846 widget->priv->computed_vexpand)
4847 gtk_widget_queue_compute_expand (parent);
4848 }
4849
4850 gtk_css_node_set_visible (widget->priv->cssnode, TRUE);
4851
4852 g_signal_emit (widget, widget_signals[SHOW], 0);
4853 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_VISIBLE]);
4854
4855 gtk_widget_pop_verify_invariants (widget);
4856 g_object_unref (widget);
4857 }
4858 }
4859
4860 static void
gtk_widget_real_show(GtkWidget * widget)4861 gtk_widget_real_show (GtkWidget *widget)
4862 {
4863 GtkWidgetPrivate *priv = widget->priv;
4864
4865 if (!_gtk_widget_get_visible (widget))
4866 {
4867 priv->visible = TRUE;
4868
4869 if (priv->parent &&
4870 _gtk_widget_get_mapped (priv->parent) &&
4871 _gtk_widget_get_child_visible (widget) &&
4872 !_gtk_widget_get_mapped (widget))
4873 gtk_widget_map (widget);
4874 }
4875 }
4876
4877 static void
gtk_widget_show_map_callback(GtkWidget * widget,GdkEvent * event,gint * flag)4878 gtk_widget_show_map_callback (GtkWidget *widget, GdkEvent *event, gint *flag)
4879 {
4880 *flag = TRUE;
4881 g_signal_handlers_disconnect_by_func (widget,
4882 gtk_widget_show_map_callback,
4883 flag);
4884 }
4885
4886 /**
4887 * gtk_widget_show_now:
4888 * @widget: a #GtkWidget
4889 *
4890 * Shows a widget. If the widget is an unmapped toplevel widget
4891 * (i.e. a #GtkWindow that has not yet been shown), enter the main
4892 * loop and wait for the window to actually be mapped. Be careful;
4893 * because the main loop is running, anything can happen during
4894 * this function.
4895 **/
4896 void
gtk_widget_show_now(GtkWidget * widget)4897 gtk_widget_show_now (GtkWidget *widget)
4898 {
4899 gint flag = FALSE;
4900
4901 g_return_if_fail (GTK_IS_WIDGET (widget));
4902
4903 /* make sure we will get event */
4904 if (!_gtk_widget_get_mapped (widget) &&
4905 _gtk_widget_is_toplevel (widget))
4906 {
4907 gtk_widget_show (widget);
4908
4909 g_signal_connect (widget, "map-event",
4910 G_CALLBACK (gtk_widget_show_map_callback),
4911 &flag);
4912
4913 while (!flag)
4914 gtk_main_iteration ();
4915 }
4916 else
4917 gtk_widget_show (widget);
4918 }
4919
4920 /**
4921 * gtk_widget_hide:
4922 * @widget: a #GtkWidget
4923 *
4924 * Reverses the effects of gtk_widget_show(), causing the widget to be
4925 * hidden (invisible to the user).
4926 **/
4927 void
gtk_widget_hide(GtkWidget * widget)4928 gtk_widget_hide (GtkWidget *widget)
4929 {
4930 g_return_if_fail (GTK_IS_WIDGET (widget));
4931
4932 if (_gtk_widget_get_visible (widget))
4933 {
4934 GtkWidget *toplevel = _gtk_widget_get_toplevel (widget);
4935 GtkWidget *parent;
4936
4937 g_object_ref (widget);
4938 gtk_widget_push_verify_invariants (widget);
4939
4940 if (toplevel != widget && _gtk_widget_is_toplevel (toplevel))
4941 _gtk_window_unset_focus_and_default (GTK_WINDOW (toplevel), widget);
4942
4943 /* a parent may now be expand=FALSE since we're hidden. */
4944 if (widget->priv->need_compute_expand ||
4945 widget->priv->computed_hexpand ||
4946 widget->priv->computed_vexpand)
4947 {
4948 gtk_widget_queue_compute_expand (widget);
4949 }
4950
4951 gtk_css_node_set_visible (widget->priv->cssnode, FALSE);
4952
4953 g_signal_emit (widget, widget_signals[HIDE], 0);
4954 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_VISIBLE]);
4955
4956 parent = gtk_widget_get_parent (widget);
4957 if (parent)
4958 gtk_widget_queue_resize (parent);
4959
4960 gtk_widget_queue_allocate (widget);
4961
4962 gtk_widget_pop_verify_invariants (widget);
4963 g_object_unref (widget);
4964 }
4965 }
4966
4967 static void
gtk_widget_real_hide(GtkWidget * widget)4968 gtk_widget_real_hide (GtkWidget *widget)
4969 {
4970 if (_gtk_widget_get_visible (widget))
4971 {
4972 widget->priv->visible = FALSE;
4973
4974 if (_gtk_widget_get_mapped (widget))
4975 gtk_widget_unmap (widget);
4976 }
4977 }
4978
4979 /**
4980 * gtk_widget_hide_on_delete:
4981 * @widget: a #GtkWidget
4982 *
4983 * Utility function; intended to be connected to the #GtkWidget::delete-event
4984 * signal on a #GtkWindow. The function calls gtk_widget_hide() on its
4985 * argument, then returns %TRUE. If connected to ::delete-event, the
4986 * result is that clicking the close button for a window (on the
4987 * window frame, top right corner usually) will hide but not destroy
4988 * the window. By default, GTK+ destroys windows when ::delete-event
4989 * is received.
4990 *
4991 * Returns: %TRUE
4992 **/
4993 gboolean
gtk_widget_hide_on_delete(GtkWidget * widget)4994 gtk_widget_hide_on_delete (GtkWidget *widget)
4995 {
4996 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
4997
4998 gtk_widget_hide (widget);
4999
5000 return TRUE;
5001 }
5002
5003 /**
5004 * gtk_widget_show_all:
5005 * @widget: a #GtkWidget
5006 *
5007 * Recursively shows a widget, and any child widgets (if the widget is
5008 * a container).
5009 **/
5010 void
gtk_widget_show_all(GtkWidget * widget)5011 gtk_widget_show_all (GtkWidget *widget)
5012 {
5013 GtkWidgetClass *class;
5014
5015 g_return_if_fail (GTK_IS_WIDGET (widget));
5016
5017 if (gtk_widget_get_no_show_all (widget))
5018 return;
5019
5020 class = GTK_WIDGET_GET_CLASS (widget);
5021
5022 if (class->show_all)
5023 class->show_all (widget);
5024 }
5025
5026 /**
5027 * gtk_widget_map:
5028 * @widget: a #GtkWidget
5029 *
5030 * This function is only for use in widget implementations. Causes
5031 * a widget to be mapped if it isn’t already.
5032 **/
5033 void
gtk_widget_map(GtkWidget * widget)5034 gtk_widget_map (GtkWidget *widget)
5035 {
5036 GtkWidgetPrivate *priv;
5037
5038 g_return_if_fail (GTK_IS_WIDGET (widget));
5039 g_return_if_fail (_gtk_widget_get_visible (widget));
5040 g_return_if_fail (_gtk_widget_get_child_visible (widget));
5041
5042 priv = widget->priv;
5043
5044 if (!_gtk_widget_get_mapped (widget))
5045 {
5046 gtk_widget_push_verify_invariants (widget);
5047
5048 if (!_gtk_widget_get_realized (widget))
5049 gtk_widget_realize (widget);
5050
5051 g_signal_emit (widget, widget_signals[MAP], 0);
5052
5053 if (!_gtk_widget_get_has_window (widget))
5054 gdk_window_invalidate_rect (priv->window, &priv->clip, FALSE);
5055
5056 gtk_widget_pop_verify_invariants (widget);
5057 }
5058 }
5059
5060 /**
5061 * gtk_widget_unmap:
5062 * @widget: a #GtkWidget
5063 *
5064 * This function is only for use in widget implementations. Causes
5065 * a widget to be unmapped if it’s currently mapped.
5066 **/
5067 void
gtk_widget_unmap(GtkWidget * widget)5068 gtk_widget_unmap (GtkWidget *widget)
5069 {
5070 GtkWidgetPrivate *priv;
5071
5072 g_return_if_fail (GTK_IS_WIDGET (widget));
5073
5074 priv = widget->priv;
5075
5076 if (_gtk_widget_get_mapped (widget))
5077 {
5078 g_object_ref (widget);
5079 gtk_widget_push_verify_invariants (widget);
5080
5081 if (!_gtk_widget_get_has_window (widget))
5082 gdk_window_invalidate_rect (priv->window, &priv->clip, FALSE);
5083 _gtk_tooltip_hide (widget);
5084
5085 g_signal_emit (widget, widget_signals[UNMAP], 0);
5086
5087 gtk_widget_pop_verify_invariants (widget);
5088 g_object_unref (widget);
5089 }
5090 }
5091
5092 static void
_gtk_widget_enable_device_events(GtkWidget * widget)5093 _gtk_widget_enable_device_events (GtkWidget *widget)
5094 {
5095 GHashTable *device_events;
5096 GHashTableIter iter;
5097 gpointer key, value;
5098
5099 device_events = g_object_get_qdata (G_OBJECT (widget), quark_device_event_mask);
5100
5101 if (!device_events)
5102 return;
5103
5104 g_hash_table_iter_init (&iter, device_events);
5105
5106 while (g_hash_table_iter_next (&iter, &key, &value))
5107 {
5108 GdkDevice *device;
5109 GdkEventMask event_mask;
5110
5111 device = key;
5112 event_mask = GPOINTER_TO_UINT (value);
5113 gtk_widget_add_events_internal (widget, device, event_mask);
5114 }
5115 }
5116
5117 typedef struct {
5118 GtkWidget *widget;
5119 GdkDevice *device;
5120 gboolean enabled;
5121 } DeviceEnableData;
5122
5123 static void
device_enable_foreach(GtkWidget * widget,gpointer user_data)5124 device_enable_foreach (GtkWidget *widget,
5125 gpointer user_data)
5126 {
5127 DeviceEnableData *data = user_data;
5128 gtk_widget_set_device_enabled_internal (widget, data->device, TRUE, data->enabled);
5129 }
5130
5131 static void
device_enable_foreach_window(gpointer win,gpointer user_data)5132 device_enable_foreach_window (gpointer win,
5133 gpointer user_data)
5134 {
5135 GdkWindow *window = win;
5136 DeviceEnableData *data = user_data;
5137 GdkEventMask events;
5138 GtkWidget *window_widget;
5139 GList *window_list;
5140
5141 gdk_window_get_user_data (window, (gpointer *) &window_widget);
5142 if (data->widget != window_widget)
5143 return;
5144
5145 if (data->enabled)
5146 events = gdk_window_get_events (window);
5147 else
5148 events = 0;
5149
5150 gdk_window_set_device_events (window, data->device, events);
5151
5152 window_list = gdk_window_peek_children (window);
5153 g_list_foreach (window_list, device_enable_foreach_window, data);
5154 }
5155
5156 void
gtk_widget_set_device_enabled_internal(GtkWidget * widget,GdkDevice * device,gboolean recurse,gboolean enabled)5157 gtk_widget_set_device_enabled_internal (GtkWidget *widget,
5158 GdkDevice *device,
5159 gboolean recurse,
5160 gboolean enabled)
5161 {
5162 DeviceEnableData data;
5163
5164 data.widget = widget;
5165 data.device = device;
5166 data.enabled = enabled;
5167
5168 if (_gtk_widget_get_has_window (widget))
5169 {
5170 GdkWindow *window;
5171
5172 window = _gtk_widget_get_window (widget);
5173 device_enable_foreach_window (window, &data);
5174 }
5175 else
5176 {
5177 GList *window_list;
5178
5179 window_list = gdk_window_peek_children (_gtk_widget_get_window (widget));
5180 g_list_foreach (window_list, device_enable_foreach_window, &data);
5181 }
5182
5183 if (recurse && GTK_IS_CONTAINER (widget))
5184 gtk_container_forall (GTK_CONTAINER (widget), device_enable_foreach, &data);
5185 }
5186
5187 static void
gtk_widget_update_devices_mask(GtkWidget * widget,gboolean recurse)5188 gtk_widget_update_devices_mask (GtkWidget *widget,
5189 gboolean recurse)
5190 {
5191 GList *enabled_devices, *l;
5192
5193 enabled_devices = g_object_get_qdata (G_OBJECT (widget), quark_enabled_devices);
5194
5195 for (l = enabled_devices; l; l = l->next)
5196 gtk_widget_set_device_enabled_internal (widget, GDK_DEVICE (l->data), recurse, TRUE);
5197 }
5198
5199 typedef struct _GtkTickCallbackInfo GtkTickCallbackInfo;
5200
5201 struct _GtkTickCallbackInfo
5202 {
5203 guint refcount;
5204
5205 guint id;
5206 GtkTickCallback callback;
5207 gpointer user_data;
5208 GDestroyNotify notify;
5209
5210 guint destroyed : 1;
5211 };
5212
5213 static void
ref_tick_callback_info(GtkTickCallbackInfo * info)5214 ref_tick_callback_info (GtkTickCallbackInfo *info)
5215 {
5216 info->refcount++;
5217 }
5218
5219 static void
unref_tick_callback_info(GtkWidget * widget,GtkTickCallbackInfo * info,GList * link)5220 unref_tick_callback_info (GtkWidget *widget,
5221 GtkTickCallbackInfo *info,
5222 GList *link)
5223 {
5224 GtkWidgetPrivate *priv = widget->priv;
5225
5226 info->refcount--;
5227 if (info->refcount == 0)
5228 {
5229 priv->tick_callbacks = g_list_delete_link (priv->tick_callbacks, link);
5230 if (info->notify)
5231 info->notify (info->user_data);
5232 g_slice_free (GtkTickCallbackInfo, info);
5233 }
5234
5235 if (priv->tick_callbacks == NULL && priv->clock_tick_id)
5236 {
5237 GdkFrameClock *frame_clock = gtk_widget_get_frame_clock (widget);
5238 g_signal_handler_disconnect (frame_clock, priv->clock_tick_id);
5239 priv->clock_tick_id = 0;
5240 gdk_frame_clock_end_updating (frame_clock);
5241 }
5242 }
5243
5244 static void
destroy_tick_callback_info(GtkWidget * widget,GtkTickCallbackInfo * info,GList * link)5245 destroy_tick_callback_info (GtkWidget *widget,
5246 GtkTickCallbackInfo *info,
5247 GList *link)
5248 {
5249 if (!info->destroyed)
5250 {
5251 info->destroyed = TRUE;
5252 unref_tick_callback_info (widget, info, link);
5253 }
5254 }
5255
5256 static void
destroy_tick_callbacks(GtkWidget * widget)5257 destroy_tick_callbacks (GtkWidget *widget)
5258 {
5259 GtkWidgetPrivate *priv = widget->priv;
5260 GList *l;
5261
5262 for (l = priv->tick_callbacks; l;)
5263 {
5264 GList *next = l->next;
5265 destroy_tick_callback_info (widget, l->data, l);
5266 l = next;
5267 }
5268 }
5269
5270 static void
gtk_widget_on_frame_clock_update(GdkFrameClock * frame_clock,GtkWidget * widget)5271 gtk_widget_on_frame_clock_update (GdkFrameClock *frame_clock,
5272 GtkWidget *widget)
5273 {
5274 GtkWidgetPrivate *priv = widget->priv;
5275 GList *l;
5276
5277 g_object_ref (widget);
5278
5279 for (l = priv->tick_callbacks; l;)
5280 {
5281 GtkTickCallbackInfo *info = l->data;
5282 GList *next;
5283
5284 ref_tick_callback_info (info);
5285 if (!info->destroyed)
5286 {
5287 if (info->callback (widget,
5288 frame_clock,
5289 info->user_data) == G_SOURCE_REMOVE)
5290 {
5291 destroy_tick_callback_info (widget, info, l);
5292 }
5293 }
5294
5295 next = l->next;
5296 unref_tick_callback_info (widget, info, l);
5297 l = next;
5298 }
5299
5300 g_object_unref (widget);
5301 }
5302
5303 static guint tick_callback_id;
5304
5305 /**
5306 * gtk_widget_add_tick_callback:
5307 * @widget: a #GtkWidget
5308 * @callback: function to call for updating animations
5309 * @user_data: data to pass to @callback
5310 * @notify: function to call to free @user_data when the callback is removed.
5311 *
5312 * Queues an animation frame update and adds a callback to be called
5313 * before each frame. Until the tick callback is removed, it will be
5314 * called frequently (usually at the frame rate of the output device
5315 * or as quickly as the application can be repainted, whichever is
5316 * slower). For this reason, is most suitable for handling graphics
5317 * that change every frame or every few frames. The tick callback does
5318 * not automatically imply a relayout or repaint. If you want a
5319 * repaint or relayout, and aren’t changing widget properties that
5320 * would trigger that (for example, changing the text of a #GtkLabel),
5321 * then you will have to call gtk_widget_queue_resize() or
5322 * gtk_widget_queue_draw_area() yourself.
5323 *
5324 * gdk_frame_clock_get_frame_time() should generally be used for timing
5325 * continuous animations and
5326 * gdk_frame_timings_get_predicted_presentation_time() if you are
5327 * trying to display isolated frames at particular times.
5328 *
5329 * This is a more convenient alternative to connecting directly to the
5330 * #GdkFrameClock::update signal of #GdkFrameClock, since you don't
5331 * have to worry about when a #GdkFrameClock is assigned to a widget.
5332 *
5333 * Returns: an id for the connection of this callback. Remove the callback
5334 * by passing it to gtk_widget_remove_tick_callback()
5335 *
5336 * Since: 3.8
5337 */
5338 guint
gtk_widget_add_tick_callback(GtkWidget * widget,GtkTickCallback callback,gpointer user_data,GDestroyNotify notify)5339 gtk_widget_add_tick_callback (GtkWidget *widget,
5340 GtkTickCallback callback,
5341 gpointer user_data,
5342 GDestroyNotify notify)
5343 {
5344 GtkWidgetPrivate *priv;
5345 GtkTickCallbackInfo *info;
5346 GdkFrameClock *frame_clock;
5347
5348 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
5349
5350 priv = widget->priv;
5351
5352 if (priv->frameclock_connected && !priv->clock_tick_id)
5353 {
5354 frame_clock = gtk_widget_get_frame_clock (widget);
5355
5356 if (frame_clock)
5357 {
5358 priv->clock_tick_id = g_signal_connect (frame_clock, "update",
5359 G_CALLBACK (gtk_widget_on_frame_clock_update),
5360 widget);
5361 gdk_frame_clock_begin_updating (frame_clock);
5362 }
5363 }
5364
5365 info = g_slice_new0 (GtkTickCallbackInfo);
5366
5367 info->refcount = 1;
5368 info->id = ++tick_callback_id;
5369 info->callback = callback;
5370 info->user_data = user_data;
5371 info->notify = notify;
5372
5373 priv->tick_callbacks = g_list_prepend (priv->tick_callbacks,
5374 info);
5375
5376 return info->id;
5377 }
5378
5379 /**
5380 * gtk_widget_remove_tick_callback:
5381 * @widget: a #GtkWidget
5382 * @id: an id returned by gtk_widget_add_tick_callback()
5383 *
5384 * Removes a tick callback previously registered with
5385 * gtk_widget_add_tick_callback().
5386 *
5387 * Since: 3.8
5388 */
5389 void
gtk_widget_remove_tick_callback(GtkWidget * widget,guint id)5390 gtk_widget_remove_tick_callback (GtkWidget *widget,
5391 guint id)
5392 {
5393 GtkWidgetPrivate *priv;
5394 GList *l;
5395
5396 g_return_if_fail (GTK_IS_WIDGET (widget));
5397
5398 priv = widget->priv;
5399
5400 for (l = priv->tick_callbacks; l; l = l->next)
5401 {
5402 GtkTickCallbackInfo *info = l->data;
5403 if (info->id == id)
5404 {
5405 destroy_tick_callback_info (widget, info, l);
5406 return;
5407 }
5408 }
5409 }
5410
5411 gboolean
gtk_widget_has_tick_callback(GtkWidget * widget)5412 gtk_widget_has_tick_callback (GtkWidget *widget)
5413 {
5414 return widget->priv->tick_callbacks != NULL;
5415 }
5416
5417 static void
gtk_widget_connect_frame_clock(GtkWidget * widget,GdkFrameClock * frame_clock)5418 gtk_widget_connect_frame_clock (GtkWidget *widget,
5419 GdkFrameClock *frame_clock)
5420 {
5421 GtkWidgetPrivate *priv = widget->priv;
5422
5423 priv->frameclock_connected = TRUE;
5424
5425 if (GTK_IS_CONTAINER (widget))
5426 _gtk_container_maybe_start_idle_sizer (GTK_CONTAINER (widget));
5427
5428 if (priv->tick_callbacks != NULL && !priv->clock_tick_id)
5429 {
5430 priv->clock_tick_id = g_signal_connect (frame_clock, "update",
5431 G_CALLBACK (gtk_widget_on_frame_clock_update),
5432 widget);
5433 gdk_frame_clock_begin_updating (frame_clock);
5434 }
5435
5436 gtk_css_node_invalidate_frame_clock (priv->cssnode, FALSE);
5437
5438 if (priv->context)
5439 gtk_style_context_set_frame_clock (priv->context, frame_clock);
5440 }
5441
5442 static void
gtk_widget_disconnect_frame_clock(GtkWidget * widget,GdkFrameClock * frame_clock)5443 gtk_widget_disconnect_frame_clock (GtkWidget *widget,
5444 GdkFrameClock *frame_clock)
5445 {
5446 GtkWidgetPrivate *priv = widget->priv;
5447
5448 if (GTK_IS_CONTAINER (widget))
5449 _gtk_container_stop_idle_sizer (GTK_CONTAINER (widget));
5450
5451 gtk_css_node_invalidate_frame_clock (priv->cssnode, FALSE);
5452
5453 if (priv->clock_tick_id)
5454 {
5455 g_signal_handler_disconnect (frame_clock, priv->clock_tick_id);
5456 priv->clock_tick_id = 0;
5457 gdk_frame_clock_end_updating (frame_clock);
5458 }
5459
5460 priv->frameclock_connected = FALSE;
5461
5462 if (priv->context)
5463 gtk_style_context_set_frame_clock (priv->context, NULL);
5464 }
5465
5466 /**
5467 * gtk_widget_realize:
5468 * @widget: a #GtkWidget
5469 *
5470 * Creates the GDK (windowing system) resources associated with a
5471 * widget. For example, @widget->window will be created when a widget
5472 * is realized. Normally realization happens implicitly; if you show
5473 * a widget and all its parent containers, then the widget will be
5474 * realized and mapped automatically.
5475 *
5476 * Realizing a widget requires all
5477 * the widget’s parent widgets to be realized; calling
5478 * gtk_widget_realize() realizes the widget’s parents in addition to
5479 * @widget itself. If a widget is not yet inside a toplevel window
5480 * when you realize it, bad things will happen.
5481 *
5482 * This function is primarily used in widget implementations, and
5483 * isn’t very useful otherwise. Many times when you think you might
5484 * need it, a better approach is to connect to a signal that will be
5485 * called after the widget is realized automatically, such as
5486 * #GtkWidget::draw. Or simply g_signal_connect () to the
5487 * #GtkWidget::realize signal.
5488 **/
5489 void
gtk_widget_realize(GtkWidget * widget)5490 gtk_widget_realize (GtkWidget *widget)
5491 {
5492 GtkWidgetPrivate *priv;
5493 cairo_region_t *region;
5494
5495 g_return_if_fail (GTK_IS_WIDGET (widget));
5496 g_return_if_fail (widget->priv->anchored ||
5497 GTK_IS_INVISIBLE (widget));
5498
5499 priv = widget->priv;
5500
5501 if (!_gtk_widget_get_realized (widget))
5502 {
5503 gtk_widget_push_verify_invariants (widget);
5504
5505 /*
5506 if (GTK_IS_CONTAINER (widget) && _gtk_widget_get_has_window (widget))
5507 g_message ("gtk_widget_realize(%s)", G_OBJECT_TYPE_NAME (widget));
5508 */
5509
5510 if (priv->parent == NULL &&
5511 !_gtk_widget_is_toplevel (widget))
5512 g_warning ("Calling gtk_widget_realize() on a widget that isn't "
5513 "inside a toplevel window is not going to work very well. "
5514 "Widgets must be inside a toplevel container before realizing them.");
5515
5516 if (priv->parent && !_gtk_widget_get_realized (priv->parent))
5517 gtk_widget_realize (priv->parent);
5518
5519 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
5520 gtk_widget_ensure_style (widget);
5521 G_GNUC_END_IGNORE_DEPRECATIONS
5522
5523 g_signal_emit (widget, widget_signals[REALIZE], 0);
5524
5525 gtk_widget_real_set_has_tooltip (widget, gtk_widget_get_has_tooltip (widget), TRUE);
5526
5527 if (priv->has_shape_mask)
5528 {
5529 region = g_object_get_qdata (G_OBJECT (widget), quark_shape_info);
5530 gdk_window_shape_combine_region (priv->window, region, 0, 0);
5531 }
5532
5533 gtk_widget_update_input_shape (widget);
5534
5535 if (priv->multidevice)
5536 gdk_window_set_support_multidevice (priv->window, TRUE);
5537
5538 _gtk_widget_enable_device_events (widget);
5539 gtk_widget_update_devices_mask (widget, TRUE);
5540
5541 gtk_widget_update_alpha (widget);
5542
5543 if (priv->context)
5544 gtk_style_context_set_scale (priv->context, gtk_widget_get_scale_factor (widget));
5545 gtk_widget_connect_frame_clock (widget,
5546 gtk_widget_get_frame_clock (widget));
5547
5548 gtk_widget_pop_verify_invariants (widget);
5549 }
5550 }
5551
5552 /**
5553 * gtk_widget_unrealize:
5554 * @widget: a #GtkWidget
5555 *
5556 * This function is only useful in widget implementations.
5557 * Causes a widget to be unrealized (frees all GDK resources
5558 * associated with the widget, such as @widget->window).
5559 **/
5560 void
gtk_widget_unrealize(GtkWidget * widget)5561 gtk_widget_unrealize (GtkWidget *widget)
5562 {
5563 g_return_if_fail (GTK_IS_WIDGET (widget));
5564
5565 g_object_ref (widget);
5566 gtk_widget_push_verify_invariants (widget);
5567
5568 if (widget->priv->has_shape_mask)
5569 gtk_widget_shape_combine_region (widget, NULL);
5570
5571 if (g_object_get_qdata (G_OBJECT (widget), quark_input_shape_info))
5572 gtk_widget_input_shape_combine_region (widget, NULL);
5573
5574 if (_gtk_widget_get_realized (widget))
5575 {
5576 if (widget->priv->mapped)
5577 gtk_widget_unmap (widget);
5578
5579 gtk_widget_disconnect_frame_clock (widget,
5580 gtk_widget_get_frame_clock (widget));
5581
5582 g_signal_emit (widget, widget_signals[UNREALIZE], 0);
5583 g_assert (!widget->priv->mapped);
5584 gtk_widget_set_realized (widget, FALSE);
5585 }
5586
5587 gtk_widget_pop_verify_invariants (widget);
5588 g_object_unref (widget);
5589 }
5590
5591 /*****************************************
5592 * Draw queueing.
5593 *****************************************/
5594
5595 static void
gtk_widget_real_queue_draw_region(GtkWidget * widget,const cairo_region_t * region)5596 gtk_widget_real_queue_draw_region (GtkWidget *widget,
5597 const cairo_region_t *region)
5598 {
5599 GtkWidgetPrivate *priv = widget->priv;
5600
5601 gdk_window_invalidate_region (priv->window, region, TRUE);
5602 }
5603
5604 /**
5605 * gtk_widget_queue_draw_region:
5606 * @widget: a #GtkWidget
5607 * @region: region to draw
5608 *
5609 * Invalidates the area of @widget defined by @region by calling
5610 * gdk_window_invalidate_region() on the widget’s window and all its
5611 * child windows. Once the main loop becomes idle (after the current
5612 * batch of events has been processed, roughly), the window will
5613 * receive expose events for the union of all regions that have been
5614 * invalidated.
5615 *
5616 * Normally you would only use this function in widget
5617 * implementations. You might also use it to schedule a redraw of a
5618 * #GtkDrawingArea or some portion thereof.
5619 *
5620 * Since: 3.0
5621 **/
5622 void
gtk_widget_queue_draw_region(GtkWidget * widget,const cairo_region_t * region)5623 gtk_widget_queue_draw_region (GtkWidget *widget,
5624 const cairo_region_t *region)
5625 {
5626 GtkWidget *w;
5627
5628 g_return_if_fail (GTK_IS_WIDGET (widget));
5629
5630 if (!_gtk_widget_get_realized (widget))
5631 return;
5632
5633 /* Just return if the widget or one of its ancestors isn't mapped */
5634 for (w = widget; w != NULL; w = w->priv->parent)
5635 if (!_gtk_widget_get_mapped (w))
5636 return;
5637
5638 WIDGET_CLASS (widget)->queue_draw_region (widget, region);
5639 }
5640
5641 /**
5642 * gtk_widget_queue_draw_area:
5643 * @widget: a #GtkWidget
5644 * @x: x coordinate of upper-left corner of rectangle to redraw
5645 * @y: y coordinate of upper-left corner of rectangle to redraw
5646 * @width: width of region to draw
5647 * @height: height of region to draw
5648 *
5649 * Convenience function that calls gtk_widget_queue_draw_region() on
5650 * the region created from the given coordinates.
5651 *
5652 * The region here is specified in widget coordinates.
5653 * Widget coordinates are a bit odd; for historical reasons, they are
5654 * defined as @widget->window coordinates for widgets that return %TRUE for
5655 * gtk_widget_get_has_window(), and are relative to @widget->allocation.x,
5656 * @widget->allocation.y otherwise.
5657 *
5658 * @width or @height may be 0, in this case this function does
5659 * nothing. Negative values for @width and @height are not allowed.
5660 */
5661 void
gtk_widget_queue_draw_area(GtkWidget * widget,gint x,gint y,gint width,gint height)5662 gtk_widget_queue_draw_area (GtkWidget *widget,
5663 gint x,
5664 gint y,
5665 gint width,
5666 gint height)
5667 {
5668 GdkRectangle rect;
5669 cairo_region_t *region;
5670
5671 g_return_if_fail (GTK_IS_WIDGET (widget));
5672 g_return_if_fail (width >= 0);
5673 g_return_if_fail (height >= 0);
5674
5675 if (width == 0 || height == 0)
5676 return;
5677
5678 rect.x = x;
5679 rect.y = y;
5680 rect.width = width;
5681 rect.height = height;
5682
5683 region = cairo_region_create_rectangle (&rect);
5684 gtk_widget_queue_draw_region (widget, region);
5685 cairo_region_destroy (region);
5686 }
5687
5688 /**
5689 * gtk_widget_queue_draw:
5690 * @widget: a #GtkWidget
5691 *
5692 * Equivalent to calling gtk_widget_queue_draw_area() for the
5693 * entire area of a widget.
5694 **/
5695 void
gtk_widget_queue_draw(GtkWidget * widget)5696 gtk_widget_queue_draw (GtkWidget *widget)
5697 {
5698 GdkRectangle rect;
5699
5700 g_return_if_fail (GTK_IS_WIDGET (widget));
5701
5702 gtk_widget_get_clip (widget, &rect);
5703
5704 if (!_gtk_widget_get_has_window (widget))
5705 gtk_widget_queue_draw_area (widget,
5706 rect.x, rect.y, rect.width, rect.height);
5707 else
5708 gtk_widget_queue_draw_area (widget,
5709 0, 0, rect.width, rect.height);
5710 }
5711
5712 static void
5713 gtk_widget_set_alloc_needed (GtkWidget *widget);
5714 /**
5715 * gtk_widget_queue_allocate:
5716 * @widget: a #GtkWidget
5717 *
5718 * This function is only for use in widget implementations.
5719 *
5720 * Flags the widget for a rerun of the GtkWidgetClass::size_allocate
5721 * function. Use this function instead of gtk_widget_queue_resize()
5722 * when the @widget's size request didn't change but it wants to
5723 * reposition its contents.
5724 *
5725 * An example user of this function is gtk_widget_set_halign().
5726 *
5727 * Since: 3.20
5728 */
5729 void
gtk_widget_queue_allocate(GtkWidget * widget)5730 gtk_widget_queue_allocate (GtkWidget *widget)
5731 {
5732 g_return_if_fail (GTK_IS_WIDGET (widget));
5733
5734 if (_gtk_widget_get_realized (widget))
5735 gtk_widget_queue_draw (widget);
5736
5737 gtk_widget_set_alloc_needed (widget);
5738 }
5739
5740 /**
5741 * gtk_widget_queue_resize_internal:
5742 * @widget: a #GtkWidget
5743 *
5744 * Queue a resize on a widget, and on all other widgets grouped with this widget.
5745 **/
5746 void
gtk_widget_queue_resize_internal(GtkWidget * widget)5747 gtk_widget_queue_resize_internal (GtkWidget *widget)
5748 {
5749 GSList *groups, *l, *widgets;
5750
5751 if (gtk_widget_get_resize_needed (widget))
5752 return;
5753
5754 gtk_widget_queue_resize_on_widget (widget);
5755
5756 groups = _gtk_widget_get_sizegroups (widget);
5757
5758 for (l = groups; l; l = l->next)
5759 {
5760
5761 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
5762 if (gtk_size_group_get_ignore_hidden (l->data) && !gtk_widget_is_visible (widget))
5763 continue;
5764 G_GNUC_END_IGNORE_DEPRECATIONS
5765
5766 for (widgets = gtk_size_group_get_widgets (l->data); widgets; widgets = widgets->next)
5767 {
5768 gtk_widget_queue_resize_internal (widgets->data);
5769 }
5770 }
5771
5772 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
5773 if (GTK_IS_RESIZE_CONTAINER (widget))
5774 {
5775 gtk_container_queue_resize_handler (GTK_CONTAINER (widget));
5776 G_GNUC_END_IGNORE_DEPRECATIONS;
5777 }
5778 else if (_gtk_widget_get_visible (widget))
5779 {
5780 GtkWidget *parent = _gtk_widget_get_parent (widget);
5781 if (parent)
5782 gtk_widget_queue_resize_internal (parent);
5783 }
5784 }
5785
5786 /**
5787 * gtk_widget_queue_resize:
5788 * @widget: a #GtkWidget
5789 *
5790 * This function is only for use in widget implementations.
5791 * Flags a widget to have its size renegotiated; should
5792 * be called when a widget for some reason has a new size request.
5793 * For example, when you change the text in a #GtkLabel, #GtkLabel
5794 * queues a resize to ensure there’s enough space for the new text.
5795 *
5796 * Note that you cannot call gtk_widget_queue_resize() on a widget
5797 * from inside its implementation of the GtkWidgetClass::size_allocate
5798 * virtual method. Calls to gtk_widget_queue_resize() from inside
5799 * GtkWidgetClass::size_allocate will be silently ignored.
5800 **/
5801 void
gtk_widget_queue_resize(GtkWidget * widget)5802 gtk_widget_queue_resize (GtkWidget *widget)
5803 {
5804 g_return_if_fail (GTK_IS_WIDGET (widget));
5805
5806 if (_gtk_widget_get_realized (widget))
5807 gtk_widget_queue_draw (widget);
5808
5809 gtk_widget_queue_resize_internal (widget);
5810 }
5811
5812 /**
5813 * gtk_widget_queue_resize_no_redraw:
5814 * @widget: a #GtkWidget
5815 *
5816 * This function works like gtk_widget_queue_resize(),
5817 * except that the widget is not invalidated.
5818 *
5819 * Since: 2.4
5820 **/
5821 void
gtk_widget_queue_resize_no_redraw(GtkWidget * widget)5822 gtk_widget_queue_resize_no_redraw (GtkWidget *widget)
5823 {
5824 g_return_if_fail (GTK_IS_WIDGET (widget));
5825
5826 gtk_widget_queue_resize_internal (widget);
5827 }
5828
5829 /**
5830 * gtk_widget_get_frame_clock:
5831 * @widget: a #GtkWidget
5832 *
5833 * Obtains the frame clock for a widget. The frame clock is a global
5834 * “ticker” that can be used to drive animations and repaints. The
5835 * most common reason to get the frame clock is to call
5836 * gdk_frame_clock_get_frame_time(), in order to get a time to use for
5837 * animating. For example you might record the start of the animation
5838 * with an initial value from gdk_frame_clock_get_frame_time(), and
5839 * then update the animation by calling
5840 * gdk_frame_clock_get_frame_time() again during each repaint.
5841 *
5842 * gdk_frame_clock_request_phase() will result in a new frame on the
5843 * clock, but won’t necessarily repaint any widgets. To repaint a
5844 * widget, you have to use gtk_widget_queue_draw() which invalidates
5845 * the widget (thus scheduling it to receive a draw on the next
5846 * frame). gtk_widget_queue_draw() will also end up requesting a frame
5847 * on the appropriate frame clock.
5848 *
5849 * A widget’s frame clock will not change while the widget is
5850 * mapped. Reparenting a widget (which implies a temporary unmap) can
5851 * change the widget’s frame clock.
5852 *
5853 * Unrealized widgets do not have a frame clock.
5854 *
5855 * Returns: (nullable) (transfer none): a #GdkFrameClock,
5856 * or %NULL if widget is unrealized
5857 *
5858 * Since: 3.8
5859 */
5860 GdkFrameClock*
gtk_widget_get_frame_clock(GtkWidget * widget)5861 gtk_widget_get_frame_clock (GtkWidget *widget)
5862 {
5863 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
5864
5865 if (widget->priv->realized)
5866 {
5867 /* We use gtk_widget_get_toplevel() here to make it explicit that
5868 * the frame clock is a property of the toplevel that a widget
5869 * is anchored to; gdk_window_get_toplevel() will go up the
5870 * hierarchy anyways, but should squash any funny business with
5871 * reparenting windows and widgets.
5872 */
5873 GtkWidget *toplevel = _gtk_widget_get_toplevel (widget);
5874 GdkWindow *window = _gtk_widget_get_window (toplevel);
5875 g_assert (window != NULL);
5876
5877 return gdk_window_get_frame_clock (window);
5878 }
5879 else
5880 {
5881 return NULL;
5882 }
5883 }
5884
5885 /**
5886 * gtk_widget_size_request:
5887 * @widget: a #GtkWidget
5888 * @requisition: (out): a #GtkRequisition to be filled in
5889 *
5890 * This function is typically used when implementing a #GtkContainer
5891 * subclass. Obtains the preferred size of a widget. The container
5892 * uses this information to arrange its child widgets and decide what
5893 * size allocations to give them with gtk_widget_size_allocate().
5894 *
5895 * You can also call this function from an application, with some
5896 * caveats. Most notably, getting a size request requires the widget
5897 * to be associated with a screen, because font information may be
5898 * needed. Multihead-aware applications should keep this in mind.
5899 *
5900 * Also remember that the size request is not necessarily the size
5901 * a widget will actually be allocated.
5902 *
5903 * Deprecated: 3.0: Use gtk_widget_get_preferred_size() instead.
5904 **/
5905 void
gtk_widget_size_request(GtkWidget * widget,GtkRequisition * requisition)5906 gtk_widget_size_request (GtkWidget *widget,
5907 GtkRequisition *requisition)
5908 {
5909 g_return_if_fail (GTK_IS_WIDGET (widget));
5910
5911 gtk_widget_get_preferred_size (widget, requisition, NULL);
5912 }
5913
5914 /**
5915 * gtk_widget_get_child_requisition:
5916 * @widget: a #GtkWidget
5917 * @requisition: (out): a #GtkRequisition to be filled in
5918 *
5919 * This function is only for use in widget implementations. Obtains
5920 * @widget->requisition, unless someone has forced a particular
5921 * geometry on the widget (e.g. with gtk_widget_set_size_request()),
5922 * in which case it returns that geometry instead of the widget's
5923 * requisition.
5924 *
5925 * This function differs from gtk_widget_size_request() in that
5926 * it retrieves the last size request value from @widget->requisition,
5927 * while gtk_widget_size_request() actually calls the "size_request" method
5928 * on @widget to compute the size request and fill in @widget->requisition,
5929 * and only then returns @widget->requisition.
5930 *
5931 * Because this function does not call the “size_request” method, it
5932 * can only be used when you know that @widget->requisition is
5933 * up-to-date, that is, gtk_widget_size_request() has been called
5934 * since the last time a resize was queued. In general, only container
5935 * implementations have this information; applications should use
5936 * gtk_widget_size_request().
5937 *
5938 *
5939 * Deprecated: 3.0: Use gtk_widget_get_preferred_size() instead.
5940 **/
5941 void
gtk_widget_get_child_requisition(GtkWidget * widget,GtkRequisition * requisition)5942 gtk_widget_get_child_requisition (GtkWidget *widget,
5943 GtkRequisition *requisition)
5944 {
5945 gtk_widget_get_preferred_size (widget, requisition, NULL);
5946 }
5947
5948 static gboolean
invalidate_predicate(GdkWindow * window,gpointer data)5949 invalidate_predicate (GdkWindow *window,
5950 gpointer data)
5951 {
5952 gpointer user_data;
5953
5954 gdk_window_get_user_data (window, &user_data);
5955
5956 return (user_data == data);
5957 }
5958
5959 /* Invalidate @region in widget->window and all children
5960 * of widget->window owned by widget. @region is in the
5961 * same coordinates as widget->allocation and will be
5962 * modified by this call.
5963 */
5964 static void
gtk_widget_invalidate_widget_windows(GtkWidget * widget,cairo_region_t * region)5965 gtk_widget_invalidate_widget_windows (GtkWidget *widget,
5966 cairo_region_t *region)
5967 {
5968 GtkWidgetPrivate *priv = widget->priv;
5969
5970 if (!_gtk_widget_get_realized (widget))
5971 return;
5972
5973 if (_gtk_widget_get_has_window (widget) && priv->parent)
5974 {
5975 int x, y;
5976
5977 gdk_window_get_position (priv->window, &x, &y);
5978 cairo_region_translate (region, -x, -y);
5979 }
5980
5981 gdk_window_invalidate_maybe_recurse (priv->window, region,
5982 invalidate_predicate, widget);
5983 }
5984
5985 /**
5986 * gtk_widget_size_allocate_with_baseline:
5987 * @widget: a #GtkWidget
5988 * @allocation: position and size to be allocated to @widget
5989 * @baseline: The baseline of the child, or -1
5990 *
5991 * This function is only used by #GtkContainer subclasses, to assign a size,
5992 * position and (optionally) baseline to their child widgets.
5993 *
5994 * In this function, the allocation and baseline may be adjusted. It
5995 * will be forced to a 1x1 minimum size, and the
5996 * adjust_size_allocation virtual and adjust_baseline_allocation
5997 * methods on the child will be used to adjust the allocation and
5998 * baseline. Standard adjustments include removing the widget's
5999 * margins, and applying the widget’s #GtkWidget:halign and
6000 * #GtkWidget:valign properties.
6001 *
6002 * If the child widget does not have a valign of %GTK_ALIGN_BASELINE the
6003 * baseline argument is ignored and -1 is used instead.
6004 *
6005 * Since: 3.10
6006 **/
6007 void
gtk_widget_size_allocate_with_baseline(GtkWidget * widget,GtkAllocation * allocation,gint baseline)6008 gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
6009 GtkAllocation *allocation,
6010 gint baseline)
6011 {
6012 GtkWidgetPrivate *priv;
6013 GdkRectangle real_allocation;
6014 GdkRectangle old_allocation, old_clip;
6015 GdkRectangle adjusted_allocation;
6016 gboolean alloc_needed;
6017 gboolean size_changed;
6018 gboolean baseline_changed;
6019 gboolean position_changed;
6020 gint natural_width, natural_height, dummy;
6021 gint min_width, min_height;
6022 gint old_baseline;
6023
6024 g_return_if_fail (GTK_IS_WIDGET (widget));
6025
6026 priv = widget->priv;
6027
6028 if (!priv->visible && !_gtk_widget_is_toplevel (widget))
6029 return;
6030
6031 gtk_widget_push_verify_invariants (widget);
6032
6033 #ifdef G_ENABLE_DEBUG
6034 if (GTK_DISPLAY_DEBUG_CHECK (gtk_widget_get_display (widget), RESIZE))
6035 {
6036 priv->highlight_resize = TRUE;
6037 gtk_widget_queue_draw (widget);
6038 }
6039
6040 #ifdef G_ENABLE_CONSISTENCY_CHECKS
6041 if (gtk_widget_get_resize_needed (widget))
6042 {
6043 g_warning ("Allocating size to %s %p without calling gtk_widget_get_preferred_width/height(). "
6044 "How does the code know the size to allocate?",
6045 gtk_widget_get_name (widget), widget);
6046 }
6047 #endif
6048
6049 if (GTK_DEBUG_CHECK (GEOMETRY))
6050 {
6051 gint depth;
6052 GtkWidget *parent;
6053 const gchar *name;
6054
6055 depth = 0;
6056 parent = widget;
6057 while (parent)
6058 {
6059 depth++;
6060 parent = _gtk_widget_get_parent (parent);
6061 }
6062
6063 name = g_type_name (G_OBJECT_TYPE (G_OBJECT (widget)));
6064 g_message ("gtk_widget_size_allocate: %*s%s %d %d %d %d, baseline %d",
6065 2 * depth, " ", name,
6066 allocation->x, allocation->y,
6067 allocation->width, allocation->height,
6068 baseline);
6069 }
6070 #endif /* G_ENABLE_DEBUG */
6071
6072 /* Never pass a baseline to a child unless it requested it.
6073 This means containers don't have to manually check for this. */
6074 if (baseline != -1 &&
6075 (gtk_widget_get_valign_with_baseline (widget) != GTK_ALIGN_BASELINE ||
6076 !_gtk_widget_has_baseline_support (widget)))
6077 baseline = -1;
6078
6079 alloc_needed = priv->alloc_needed;
6080 /* Preserve request/allocate ordering */
6081 priv->alloc_needed = FALSE;
6082
6083 old_allocation = priv->allocation;
6084 old_clip = priv->clip;
6085 old_baseline = priv->allocated_baseline;
6086 real_allocation = *allocation;
6087
6088 priv->allocated_size = *allocation;
6089 priv->allocated_size_baseline = baseline;
6090
6091 adjusted_allocation = real_allocation;
6092 if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
6093 {
6094 /* Go ahead and request the height for allocated width, note that the internals
6095 * of get_height_for_width will internally limit the for_size to natural size
6096 * when aligning implicitly.
6097 */
6098 gtk_widget_get_preferred_width (widget, &min_width, &natural_width);
6099 gtk_widget_get_preferred_height_for_width (widget, real_allocation.width, &min_height, &natural_height);
6100 }
6101 else
6102 {
6103 /* Go ahead and request the width for allocated height, note that the internals
6104 * of get_width_for_height will internally limit the for_size to natural size
6105 * when aligning implicitly.
6106 */
6107 gtk_widget_get_preferred_height (widget, &min_height, &natural_height);
6108 gtk_widget_get_preferred_width_for_height (widget, real_allocation.height, &min_width, &natural_width);
6109 }
6110
6111 #ifdef G_ENABLE_CONSISTENCY_CHECKS
6112 if ((min_width > real_allocation.width || min_height > real_allocation.height) &&
6113 !GTK_IS_SCROLLABLE (widget))
6114 g_warning ("gtk_widget_size_allocate(): attempt to underallocate %s%s %s %p. "
6115 "Allocation is %dx%d, but minimum required size is %dx%d.",
6116 priv->parent ? G_OBJECT_TYPE_NAME (priv->parent) : "", priv->parent ? "'s child" : "toplevel",
6117 G_OBJECT_TYPE_NAME (widget), widget,
6118 real_allocation.width, real_allocation.height,
6119 min_width, min_height);
6120 #endif
6121 /* Now that we have the right natural height and width, go ahead and remove any margins from the
6122 * allocated sizes and possibly limit them to the natural sizes */
6123 GTK_WIDGET_GET_CLASS (widget)->adjust_size_allocation (widget,
6124 GTK_ORIENTATION_HORIZONTAL,
6125 &dummy,
6126 &natural_width,
6127 &adjusted_allocation.x,
6128 &adjusted_allocation.width);
6129 GTK_WIDGET_GET_CLASS (widget)->adjust_size_allocation (widget,
6130 GTK_ORIENTATION_VERTICAL,
6131 &dummy,
6132 &natural_height,
6133 &adjusted_allocation.y,
6134 &adjusted_allocation.height);
6135 if (baseline >= 0)
6136 GTK_WIDGET_GET_CLASS (widget)->adjust_baseline_allocation (widget,
6137 &baseline);
6138
6139 if (adjusted_allocation.x < real_allocation.x ||
6140 adjusted_allocation.y < real_allocation.y ||
6141 (adjusted_allocation.x + adjusted_allocation.width) >
6142 (real_allocation.x + real_allocation.width) ||
6143 (adjusted_allocation.y + adjusted_allocation.height >
6144 real_allocation.y + real_allocation.height))
6145 {
6146 g_warning ("%s %p attempted to adjust its size allocation from %d,%d %dx%d to %d,%d %dx%d. adjust_size_allocation must keep allocation inside original bounds",
6147 G_OBJECT_TYPE_NAME (widget), widget,
6148 real_allocation.x, real_allocation.y, real_allocation.width, real_allocation.height,
6149 adjusted_allocation.x, adjusted_allocation.y, adjusted_allocation.width, adjusted_allocation.height);
6150 }
6151 else
6152 {
6153 real_allocation = adjusted_allocation;
6154 }
6155
6156 if (real_allocation.width < 0 || real_allocation.height < 0)
6157 {
6158 g_warning ("gtk_widget_size_allocate(): attempt to allocate widget with width %d and height %d",
6159 real_allocation.width,
6160 real_allocation.height);
6161 }
6162
6163 real_allocation.width = MAX (real_allocation.width, 1);
6164 real_allocation.height = MAX (real_allocation.height, 1);
6165
6166 baseline_changed = old_baseline != baseline;
6167 size_changed = (old_allocation.width != real_allocation.width ||
6168 old_allocation.height != real_allocation.height);
6169 position_changed = (old_allocation.x != real_allocation.x ||
6170 old_allocation.y != real_allocation.y);
6171
6172 if (!alloc_needed && !size_changed && !position_changed && !baseline_changed)
6173 goto out;
6174
6175 priv->allocated_baseline = baseline;
6176 if (g_signal_has_handler_pending (widget, widget_signals[SIZE_ALLOCATE], 0, FALSE))
6177 g_signal_emit (widget, widget_signals[SIZE_ALLOCATE], 0, &real_allocation);
6178 else
6179 GTK_WIDGET_GET_CLASS (widget)->size_allocate (widget, &real_allocation);
6180
6181 /* Size allocation is god... after consulting god, no further requests or allocations are needed */
6182 #ifdef G_ENABLE_DEBUG
6183 if (GTK_DEBUG_CHECK (GEOMETRY) && gtk_widget_get_resize_needed (widget))
6184 {
6185 g_warning ("%s %p or a child called gtk_widget_queue_resize() during size_allocate().",
6186 gtk_widget_get_name (widget), widget);
6187 }
6188 #endif
6189 gtk_widget_ensure_resize (widget);
6190 priv->alloc_needed = FALSE;
6191 priv->alloc_needed_on_child = FALSE;
6192
6193 size_changed |= (old_clip.width != priv->clip.width ||
6194 old_clip.height != priv->clip.height);
6195 position_changed |= (old_clip.x != priv->clip.x ||
6196 old_clip.y != priv->clip.y);
6197
6198 if (_gtk_widget_get_mapped (widget) && priv->redraw_on_alloc)
6199 {
6200 if (!_gtk_widget_get_has_window (widget) && position_changed)
6201 {
6202 /* Invalidate union(old_clip,priv->clip) in priv->window
6203 */
6204 cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->clip);
6205 cairo_region_union_rectangle (invalidate, &old_clip);
6206
6207 gdk_window_invalidate_region (priv->window, invalidate, FALSE);
6208 cairo_region_destroy (invalidate);
6209 }
6210
6211 if (size_changed || baseline_changed)
6212 {
6213 /* Invalidate union(old_clip,priv->clip) in priv->window and descendants owned by widget
6214 */
6215 cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->clip);
6216 cairo_region_union_rectangle (invalidate, &old_clip);
6217
6218 gtk_widget_invalidate_widget_windows (widget, invalidate);
6219 cairo_region_destroy (invalidate);
6220 }
6221 }
6222
6223 if ((size_changed || position_changed || baseline_changed) && priv->parent &&
6224 _gtk_widget_get_realized (priv->parent) && _gtk_container_get_reallocate_redraws (GTK_CONTAINER (priv->parent)))
6225 {
6226 cairo_region_t *invalidate = cairo_region_create_rectangle (&priv->parent->priv->clip);
6227 gtk_widget_invalidate_widget_windows (priv->parent, invalidate);
6228 cairo_region_destroy (invalidate);
6229 }
6230
6231 out:
6232 if (priv->alloc_needed_on_child)
6233 gtk_widget_ensure_allocate (widget);
6234
6235 gtk_widget_pop_verify_invariants (widget);
6236 }
6237
6238
6239 /**
6240 * gtk_widget_size_allocate:
6241 * @widget: a #GtkWidget
6242 * @allocation: position and size to be allocated to @widget
6243 *
6244 * This function is only used by #GtkContainer subclasses, to assign a size
6245 * and position to their child widgets.
6246 *
6247 * In this function, the allocation may be adjusted. It will be forced
6248 * to a 1x1 minimum size, and the adjust_size_allocation virtual
6249 * method on the child will be used to adjust the allocation. Standard
6250 * adjustments include removing the widget’s margins, and applying the
6251 * widget’s #GtkWidget:halign and #GtkWidget:valign properties.
6252 *
6253 * For baseline support in containers you need to use gtk_widget_size_allocate_with_baseline()
6254 * instead.
6255 **/
6256 void
gtk_widget_size_allocate(GtkWidget * widget,GtkAllocation * allocation)6257 gtk_widget_size_allocate (GtkWidget *widget,
6258 GtkAllocation *allocation)
6259 {
6260 gtk_widget_size_allocate_with_baseline (widget, allocation, -1);
6261 }
6262
6263 /**
6264 * gtk_widget_common_ancestor:
6265 * @widget_a: a #GtkWidget
6266 * @widget_b: a #GtkWidget
6267 *
6268 * Find the common ancestor of @widget_a and @widget_b that
6269 * is closest to the two widgets.
6270 *
6271 * Returns: (nullable): the closest common ancestor of @widget_a and
6272 * @widget_b or %NULL if @widget_a and @widget_b do not
6273 * share a common ancestor.
6274 **/
6275 static GtkWidget *
gtk_widget_common_ancestor(GtkWidget * widget_a,GtkWidget * widget_b)6276 gtk_widget_common_ancestor (GtkWidget *widget_a,
6277 GtkWidget *widget_b)
6278 {
6279 GtkWidget *parent_a;
6280 GtkWidget *parent_b;
6281 gint depth_a = 0;
6282 gint depth_b = 0;
6283
6284 parent_a = widget_a;
6285 while (parent_a->priv->parent)
6286 {
6287 parent_a = parent_a->priv->parent;
6288 depth_a++;
6289 }
6290
6291 parent_b = widget_b;
6292 while (parent_b->priv->parent)
6293 {
6294 parent_b = parent_b->priv->parent;
6295 depth_b++;
6296 }
6297
6298 if (parent_a != parent_b)
6299 return NULL;
6300
6301 while (depth_a > depth_b)
6302 {
6303 widget_a = widget_a->priv->parent;
6304 depth_a--;
6305 }
6306
6307 while (depth_b > depth_a)
6308 {
6309 widget_b = widget_b->priv->parent;
6310 depth_b--;
6311 }
6312
6313 while (widget_a != widget_b)
6314 {
6315 widget_a = widget_a->priv->parent;
6316 widget_b = widget_b->priv->parent;
6317 }
6318
6319 return widget_a;
6320 }
6321
6322 /**
6323 * gtk_widget_translate_coordinates:
6324 * @src_widget: a #GtkWidget
6325 * @dest_widget: a #GtkWidget
6326 * @src_x: X position relative to @src_widget
6327 * @src_y: Y position relative to @src_widget
6328 * @dest_x: (out) (optional): location to store X position relative to @dest_widget
6329 * @dest_y: (out) (optional): location to store Y position relative to @dest_widget
6330 *
6331 * Translate coordinates relative to @src_widget’s allocation to coordinates
6332 * relative to @dest_widget’s allocations. In order to perform this
6333 * operation, both widgets must be realized, and must share a common
6334 * toplevel.
6335 *
6336 * Returns: %FALSE if either widget was not realized, or there
6337 * was no common ancestor. In this case, nothing is stored in
6338 * *@dest_x and *@dest_y. Otherwise %TRUE.
6339 **/
6340 gboolean
gtk_widget_translate_coordinates(GtkWidget * src_widget,GtkWidget * dest_widget,gint src_x,gint src_y,gint * dest_x,gint * dest_y)6341 gtk_widget_translate_coordinates (GtkWidget *src_widget,
6342 GtkWidget *dest_widget,
6343 gint src_x,
6344 gint src_y,
6345 gint *dest_x,
6346 gint *dest_y)
6347 {
6348 GtkWidgetPrivate *src_priv;
6349 GtkWidgetPrivate *dest_priv;
6350 GtkWidget *ancestor;
6351 GdkWindow *window;
6352 GList *dest_list = NULL;
6353
6354 g_return_val_if_fail (GTK_IS_WIDGET (src_widget), FALSE);
6355 g_return_val_if_fail (GTK_IS_WIDGET (dest_widget), FALSE);
6356
6357 ancestor = gtk_widget_common_ancestor (src_widget, dest_widget);
6358 if (!ancestor || !_gtk_widget_get_realized (src_widget) || !_gtk_widget_get_realized (dest_widget))
6359 return FALSE;
6360
6361 src_priv = src_widget->priv;
6362 dest_priv = dest_widget->priv;
6363
6364 /* Translate from allocation relative to window relative */
6365 if (_gtk_widget_get_has_window (src_widget) && src_priv->parent)
6366 {
6367 gint wx, wy;
6368 gdk_window_get_position (src_priv->window, &wx, &wy);
6369
6370 src_x -= wx - src_priv->allocation.x;
6371 src_y -= wy - src_priv->allocation.y;
6372 }
6373 else
6374 {
6375 src_x += src_priv->allocation.x;
6376 src_y += src_priv->allocation.y;
6377 }
6378
6379 /* Translate to the common ancestor */
6380 window = src_priv->window;
6381 while (window != ancestor->priv->window)
6382 {
6383 gdouble dx, dy;
6384
6385 gdk_window_coords_to_parent (window, src_x, src_y, &dx, &dy);
6386
6387 src_x = dx;
6388 src_y = dy;
6389
6390 window = gdk_window_get_effective_parent (window);
6391
6392 if (!window) /* Handle GtkHandleBox */
6393 return FALSE;
6394 }
6395
6396 /* And back */
6397 window = dest_priv->window;
6398 while (window != ancestor->priv->window)
6399 {
6400 dest_list = g_list_prepend (dest_list, window);
6401
6402 window = gdk_window_get_effective_parent (window);
6403
6404 if (!window) /* Handle GtkHandleBox */
6405 {
6406 g_list_free (dest_list);
6407 return FALSE;
6408 }
6409 }
6410
6411 while (dest_list)
6412 {
6413 gdouble dx, dy;
6414
6415 gdk_window_coords_from_parent (dest_list->data, src_x, src_y, &dx, &dy);
6416
6417 src_x = dx;
6418 src_y = dy;
6419
6420 dest_list = g_list_remove (dest_list, dest_list->data);
6421 }
6422
6423 /* Translate from window relative to allocation relative */
6424 if (_gtk_widget_get_has_window (dest_widget) && dest_priv->parent)
6425 {
6426 gint wx, wy;
6427 gdk_window_get_position (dest_priv->window, &wx, &wy);
6428
6429 src_x += wx - dest_priv->allocation.x;
6430 src_y += wy - dest_priv->allocation.y;
6431 }
6432 else
6433 {
6434 src_x -= dest_priv->allocation.x;
6435 src_y -= dest_priv->allocation.y;
6436 }
6437
6438 if (dest_x)
6439 *dest_x = src_x;
6440 if (dest_y)
6441 *dest_y = src_y;
6442
6443 return TRUE;
6444 }
6445
6446 static void
gtk_widget_real_size_allocate(GtkWidget * widget,GtkAllocation * allocation)6447 gtk_widget_real_size_allocate (GtkWidget *widget,
6448 GtkAllocation *allocation)
6449 {
6450 GtkWidgetPrivate *priv = widget->priv;
6451
6452 gtk_widget_set_allocation (widget, allocation);
6453
6454 if (_gtk_widget_get_realized (widget) &&
6455 _gtk_widget_get_has_window (widget))
6456 {
6457 gdk_window_move_resize (priv->window,
6458 allocation->x, allocation->y,
6459 allocation->width, allocation->height);
6460 }
6461 }
6462
6463 /* translate initial/final into start/end */
6464 static GtkAlign
effective_align(GtkAlign align,GtkTextDirection direction)6465 effective_align (GtkAlign align,
6466 GtkTextDirection direction)
6467 {
6468 switch (align)
6469 {
6470 case GTK_ALIGN_START:
6471 return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_END : GTK_ALIGN_START;
6472 case GTK_ALIGN_END:
6473 return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END;
6474 default:
6475 return align;
6476 }
6477 }
6478
6479 static void
adjust_for_align(GtkAlign align,gint * natural_size,gint * allocated_pos,gint * allocated_size)6480 adjust_for_align (GtkAlign align,
6481 gint *natural_size,
6482 gint *allocated_pos,
6483 gint *allocated_size)
6484 {
6485 switch (align)
6486 {
6487 case GTK_ALIGN_BASELINE:
6488 case GTK_ALIGN_FILL:
6489 /* change nothing */
6490 break;
6491 case GTK_ALIGN_START:
6492 /* keep *allocated_pos where it is */
6493 *allocated_size = MIN (*allocated_size, *natural_size);
6494 break;
6495 case GTK_ALIGN_END:
6496 if (*allocated_size > *natural_size)
6497 {
6498 *allocated_pos += (*allocated_size - *natural_size);
6499 *allocated_size = *natural_size;
6500 }
6501 break;
6502 case GTK_ALIGN_CENTER:
6503 if (*allocated_size > *natural_size)
6504 {
6505 *allocated_pos += (*allocated_size - *natural_size) / 2;
6506 *allocated_size = MIN (*allocated_size, *natural_size);
6507 }
6508 break;
6509 }
6510 }
6511
6512 static void
adjust_for_margin(gint start_margin,gint end_margin,gint * minimum_size,gint * natural_size,gint * allocated_pos,gint * allocated_size)6513 adjust_for_margin(gint start_margin,
6514 gint end_margin,
6515 gint *minimum_size,
6516 gint *natural_size,
6517 gint *allocated_pos,
6518 gint *allocated_size)
6519 {
6520 *minimum_size -= (start_margin + end_margin);
6521 *natural_size -= (start_margin + end_margin);
6522 *allocated_pos += start_margin;
6523 *allocated_size -= (start_margin + end_margin);
6524 }
6525
6526 static void
gtk_widget_real_adjust_size_allocation(GtkWidget * widget,GtkOrientation orientation,gint * minimum_size,gint * natural_size,gint * allocated_pos,gint * allocated_size)6527 gtk_widget_real_adjust_size_allocation (GtkWidget *widget,
6528 GtkOrientation orientation,
6529 gint *minimum_size,
6530 gint *natural_size,
6531 gint *allocated_pos,
6532 gint *allocated_size)
6533 {
6534 GtkWidgetPrivate *priv = widget->priv;
6535
6536 if (orientation == GTK_ORIENTATION_HORIZONTAL)
6537 {
6538 adjust_for_margin (priv->margin.left,
6539 priv->margin.right,
6540 minimum_size, natural_size,
6541 allocated_pos, allocated_size);
6542 adjust_for_align (effective_align (priv->halign, _gtk_widget_get_direction (widget)),
6543 natural_size, allocated_pos, allocated_size);
6544 }
6545 else
6546 {
6547 adjust_for_margin (priv->margin.top,
6548 priv->margin.bottom,
6549 minimum_size, natural_size,
6550 allocated_pos, allocated_size);
6551 adjust_for_align (effective_align (priv->valign, GTK_TEXT_DIR_NONE),
6552 natural_size, allocated_pos, allocated_size);
6553 }
6554 }
6555
6556 static void
gtk_widget_real_adjust_baseline_allocation(GtkWidget * widget,gint * baseline)6557 gtk_widget_real_adjust_baseline_allocation (GtkWidget *widget,
6558 gint *baseline)
6559 {
6560 if (*baseline >= 0)
6561 *baseline -= widget->priv->margin.top;
6562 }
6563
6564 static gboolean
gtk_widget_real_can_activate_accel(GtkWidget * widget,guint signal_id)6565 gtk_widget_real_can_activate_accel (GtkWidget *widget,
6566 guint signal_id)
6567 {
6568 GtkWidgetPrivate *priv = widget->priv;
6569
6570 /* widgets must be onscreen for accels to take effect */
6571 return gtk_widget_is_sensitive (widget) &&
6572 _gtk_widget_is_drawable (widget) &&
6573 gdk_window_is_viewable (priv->window);
6574 }
6575
6576 /**
6577 * gtk_widget_can_activate_accel:
6578 * @widget: a #GtkWidget
6579 * @signal_id: the ID of a signal installed on @widget
6580 *
6581 * Determines whether an accelerator that activates the signal
6582 * identified by @signal_id can currently be activated.
6583 * This is done by emitting the #GtkWidget::can-activate-accel
6584 * signal on @widget; if the signal isn’t overridden by a
6585 * handler or in a derived widget, then the default check is
6586 * that the widget must be sensitive, and the widget and all
6587 * its ancestors mapped.
6588 *
6589 * Returns: %TRUE if the accelerator can be activated.
6590 *
6591 * Since: 2.4
6592 **/
6593 gboolean
gtk_widget_can_activate_accel(GtkWidget * widget,guint signal_id)6594 gtk_widget_can_activate_accel (GtkWidget *widget,
6595 guint signal_id)
6596 {
6597 gboolean can_activate = FALSE;
6598 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
6599 g_signal_emit (widget, widget_signals[CAN_ACTIVATE_ACCEL], 0, signal_id, &can_activate);
6600 return can_activate;
6601 }
6602
6603 typedef struct {
6604 GClosure closure;
6605 guint signal_id;
6606 } AccelClosure;
6607
6608 static void
closure_accel_activate(GClosure * closure,GValue * return_value,guint n_param_values,const GValue * param_values,gpointer invocation_hint,gpointer marshal_data)6609 closure_accel_activate (GClosure *closure,
6610 GValue *return_value,
6611 guint n_param_values,
6612 const GValue *param_values,
6613 gpointer invocation_hint,
6614 gpointer marshal_data)
6615 {
6616 AccelClosure *aclosure = (AccelClosure*) closure;
6617 gboolean can_activate = gtk_widget_can_activate_accel (closure->data, aclosure->signal_id);
6618
6619 if (can_activate)
6620 g_signal_emit (closure->data, aclosure->signal_id, 0);
6621
6622 /* whether accelerator was handled */
6623 g_value_set_boolean (return_value, can_activate);
6624 }
6625
6626 static void
closures_destroy(gpointer data)6627 closures_destroy (gpointer data)
6628 {
6629 GSList *slist, *closures = data;
6630
6631 for (slist = closures; slist; slist = slist->next)
6632 {
6633 g_closure_invalidate (slist->data);
6634 g_closure_unref (slist->data);
6635 }
6636 g_slist_free (closures);
6637 }
6638
6639 static GClosure*
widget_new_accel_closure(GtkWidget * widget,guint signal_id)6640 widget_new_accel_closure (GtkWidget *widget,
6641 guint signal_id)
6642 {
6643 AccelClosure *aclosure;
6644 GClosure *closure = NULL;
6645 GSList *slist, *closures;
6646
6647 closures = g_object_steal_qdata (G_OBJECT (widget), quark_accel_closures);
6648 for (slist = closures; slist; slist = slist->next)
6649 if (!gtk_accel_group_from_accel_closure (slist->data))
6650 {
6651 /* reuse this closure */
6652 closure = slist->data;
6653 break;
6654 }
6655 if (!closure)
6656 {
6657 closure = g_closure_new_object (sizeof (AccelClosure), G_OBJECT (widget));
6658 closures = g_slist_prepend (closures, g_closure_ref (closure));
6659 g_closure_sink (closure);
6660 g_closure_set_marshal (closure, closure_accel_activate);
6661 }
6662 g_object_set_qdata_full (G_OBJECT (widget), quark_accel_closures, closures, closures_destroy);
6663
6664 aclosure = (AccelClosure*) closure;
6665 g_assert (closure->data == widget);
6666 g_assert (closure->marshal == closure_accel_activate);
6667 aclosure->signal_id = signal_id;
6668
6669 return closure;
6670 }
6671
6672 /**
6673 * gtk_widget_add_accelerator:
6674 * @widget: widget to install an accelerator on
6675 * @accel_signal: widget signal to emit on accelerator activation
6676 * @accel_group: accel group for this widget, added to its toplevel
6677 * @accel_key: GDK keyval of the accelerator
6678 * @accel_mods: modifier key combination of the accelerator
6679 * @accel_flags: flag accelerators, e.g. %GTK_ACCEL_VISIBLE
6680 *
6681 * Installs an accelerator for this @widget in @accel_group that causes
6682 * @accel_signal to be emitted if the accelerator is activated.
6683 * The @accel_group needs to be added to the widget’s toplevel via
6684 * gtk_window_add_accel_group(), and the signal must be of type %G_SIGNAL_ACTION.
6685 * Accelerators added through this function are not user changeable during
6686 * runtime. If you want to support accelerators that can be changed by the
6687 * user, use gtk_accel_map_add_entry() and gtk_widget_set_accel_path() or
6688 * gtk_menu_item_set_accel_path() instead.
6689 */
6690 void
gtk_widget_add_accelerator(GtkWidget * widget,const gchar * accel_signal,GtkAccelGroup * accel_group,guint accel_key,GdkModifierType accel_mods,GtkAccelFlags accel_flags)6691 gtk_widget_add_accelerator (GtkWidget *widget,
6692 const gchar *accel_signal,
6693 GtkAccelGroup *accel_group,
6694 guint accel_key,
6695 GdkModifierType accel_mods,
6696 GtkAccelFlags accel_flags)
6697 {
6698 GClosure *closure;
6699 GSignalQuery query;
6700
6701 g_return_if_fail (GTK_IS_WIDGET (widget));
6702 g_return_if_fail (accel_signal != NULL);
6703 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
6704
6705 g_signal_query (g_signal_lookup (accel_signal, G_OBJECT_TYPE (widget)), &query);
6706 if (!query.signal_id ||
6707 !(query.signal_flags & G_SIGNAL_ACTION) ||
6708 query.return_type != G_TYPE_NONE ||
6709 query.n_params)
6710 {
6711 /* hmm, should be elaborate enough */
6712 g_warning (G_STRLOC ": widget '%s' has no activatable signal \"%s\" without arguments",
6713 G_OBJECT_TYPE_NAME (widget), accel_signal);
6714 return;
6715 }
6716
6717 closure = widget_new_accel_closure (widget, query.signal_id);
6718
6719 g_object_ref (widget);
6720
6721 /* install the accelerator. since we don't map this onto an accel_path,
6722 * the accelerator will automatically be locked.
6723 */
6724 gtk_accel_group_connect (accel_group,
6725 accel_key,
6726 accel_mods,
6727 accel_flags | GTK_ACCEL_LOCKED,
6728 closure);
6729
6730 g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
6731
6732 g_object_unref (widget);
6733 }
6734
6735 /**
6736 * gtk_widget_remove_accelerator:
6737 * @widget: widget to install an accelerator on
6738 * @accel_group: accel group for this widget
6739 * @accel_key: GDK keyval of the accelerator
6740 * @accel_mods: modifier key combination of the accelerator
6741 *
6742 * Removes an accelerator from @widget, previously installed with
6743 * gtk_widget_add_accelerator().
6744 *
6745 * Returns: whether an accelerator was installed and could be removed
6746 */
6747 gboolean
gtk_widget_remove_accelerator(GtkWidget * widget,GtkAccelGroup * accel_group,guint accel_key,GdkModifierType accel_mods)6748 gtk_widget_remove_accelerator (GtkWidget *widget,
6749 GtkAccelGroup *accel_group,
6750 guint accel_key,
6751 GdkModifierType accel_mods)
6752 {
6753 GtkAccelGroupEntry *ag_entry;
6754 GList *slist, *clist;
6755 guint n;
6756
6757 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
6758 g_return_val_if_fail (GTK_IS_ACCEL_GROUP (accel_group), FALSE);
6759
6760 ag_entry = gtk_accel_group_query (accel_group, accel_key, accel_mods, &n);
6761 clist = gtk_widget_list_accel_closures (widget);
6762 for (slist = clist; slist; slist = slist->next)
6763 {
6764 guint i;
6765
6766 for (i = 0; i < n; i++)
6767 if (slist->data == (gpointer) ag_entry[i].closure)
6768 {
6769 gboolean is_removed = gtk_accel_group_disconnect (accel_group, slist->data);
6770
6771 g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
6772
6773 g_list_free (clist);
6774
6775 return is_removed;
6776 }
6777 }
6778 g_list_free (clist);
6779
6780 g_warning (G_STRLOC ": no accelerator (%u,%u) installed in accel group (%p) for %s (%p)",
6781 accel_key, accel_mods, accel_group,
6782 G_OBJECT_TYPE_NAME (widget), widget);
6783
6784 return FALSE;
6785 }
6786
6787 /**
6788 * gtk_widget_list_accel_closures:
6789 * @widget: widget to list accelerator closures for
6790 *
6791 * Lists the closures used by @widget for accelerator group connections
6792 * with gtk_accel_group_connect_by_path() or gtk_accel_group_connect().
6793 * The closures can be used to monitor accelerator changes on @widget,
6794 * by connecting to the @GtkAccelGroup::accel-changed signal of the
6795 * #GtkAccelGroup of a closure which can be found out with
6796 * gtk_accel_group_from_accel_closure().
6797 *
6798 * Returns: (transfer container) (element-type GClosure):
6799 * a newly allocated #GList of closures
6800 */
6801 GList*
gtk_widget_list_accel_closures(GtkWidget * widget)6802 gtk_widget_list_accel_closures (GtkWidget *widget)
6803 {
6804 GSList *slist;
6805 GList *clist = NULL;
6806
6807 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
6808
6809 for (slist = g_object_get_qdata (G_OBJECT (widget), quark_accel_closures); slist; slist = slist->next)
6810 if (gtk_accel_group_from_accel_closure (slist->data))
6811 clist = g_list_prepend (clist, slist->data);
6812 return clist;
6813 }
6814
6815 typedef struct {
6816 GQuark path_quark;
6817 GtkAccelGroup *accel_group;
6818 GClosure *closure;
6819 } AccelPath;
6820
6821 static void
destroy_accel_path(gpointer data)6822 destroy_accel_path (gpointer data)
6823 {
6824 AccelPath *apath = data;
6825
6826 gtk_accel_group_disconnect (apath->accel_group, apath->closure);
6827
6828 /* closures_destroy takes care of unrefing the closure */
6829 g_object_unref (apath->accel_group);
6830
6831 g_slice_free (AccelPath, apath);
6832 }
6833
6834
6835 /**
6836 * gtk_widget_set_accel_path:
6837 * @widget: a #GtkWidget
6838 * @accel_path: (allow-none): path used to look up the accelerator
6839 * @accel_group: (allow-none): a #GtkAccelGroup.
6840 *
6841 * Given an accelerator group, @accel_group, and an accelerator path,
6842 * @accel_path, sets up an accelerator in @accel_group so whenever the
6843 * key binding that is defined for @accel_path is pressed, @widget
6844 * will be activated. This removes any accelerators (for any
6845 * accelerator group) installed by previous calls to
6846 * gtk_widget_set_accel_path(). Associating accelerators with
6847 * paths allows them to be modified by the user and the modifications
6848 * to be saved for future use. (See gtk_accel_map_save().)
6849 *
6850 * This function is a low level function that would most likely
6851 * be used by a menu creation system like #GtkUIManager. If you
6852 * use #GtkUIManager, setting up accelerator paths will be done
6853 * automatically.
6854 *
6855 * Even when you you aren’t using #GtkUIManager, if you only want to
6856 * set up accelerators on menu items gtk_menu_item_set_accel_path()
6857 * provides a somewhat more convenient interface.
6858 *
6859 * Note that @accel_path string will be stored in a #GQuark. Therefore, if you
6860 * pass a static string, you can save some memory by interning it first with
6861 * g_intern_static_string().
6862 **/
6863 void
gtk_widget_set_accel_path(GtkWidget * widget,const gchar * accel_path,GtkAccelGroup * accel_group)6864 gtk_widget_set_accel_path (GtkWidget *widget,
6865 const gchar *accel_path,
6866 GtkAccelGroup *accel_group)
6867 {
6868 AccelPath *apath;
6869
6870 g_return_if_fail (GTK_IS_WIDGET (widget));
6871 g_return_if_fail (GTK_WIDGET_GET_CLASS (widget)->activate_signal != 0);
6872
6873 if (accel_path)
6874 {
6875 g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group));
6876 g_return_if_fail (_gtk_accel_path_is_valid (accel_path));
6877
6878 gtk_accel_map_add_entry (accel_path, 0, 0);
6879 apath = g_slice_new (AccelPath);
6880 apath->accel_group = g_object_ref (accel_group);
6881 apath->path_quark = g_quark_from_string (accel_path);
6882 apath->closure = widget_new_accel_closure (widget, GTK_WIDGET_GET_CLASS (widget)->activate_signal);
6883 }
6884 else
6885 apath = NULL;
6886
6887 /* also removes possible old settings */
6888 g_object_set_qdata_full (G_OBJECT (widget), quark_accel_path, apath, destroy_accel_path);
6889
6890 if (apath)
6891 gtk_accel_group_connect_by_path (apath->accel_group, g_quark_to_string (apath->path_quark), apath->closure);
6892
6893 g_signal_emit (widget, widget_signals[ACCEL_CLOSURES_CHANGED], 0);
6894 }
6895
6896 const gchar*
_gtk_widget_get_accel_path(GtkWidget * widget,gboolean * locked)6897 _gtk_widget_get_accel_path (GtkWidget *widget,
6898 gboolean *locked)
6899 {
6900 AccelPath *apath;
6901
6902 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
6903
6904 apath = g_object_get_qdata (G_OBJECT (widget), quark_accel_path);
6905 if (locked)
6906 *locked = apath ? gtk_accel_group_get_is_locked (apath->accel_group) : TRUE;
6907 return apath ? g_quark_to_string (apath->path_quark) : NULL;
6908 }
6909
6910 /**
6911 * gtk_widget_mnemonic_activate:
6912 * @widget: a #GtkWidget
6913 * @group_cycling: %TRUE if there are other widgets with the same mnemonic
6914 *
6915 * Emits the #GtkWidget::mnemonic-activate signal.
6916 *
6917 * Returns: %TRUE if the signal has been handled
6918 */
6919 gboolean
gtk_widget_mnemonic_activate(GtkWidget * widget,gboolean group_cycling)6920 gtk_widget_mnemonic_activate (GtkWidget *widget,
6921 gboolean group_cycling)
6922 {
6923 gboolean handled;
6924
6925 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
6926
6927 group_cycling = group_cycling != FALSE;
6928 if (!gtk_widget_is_sensitive (widget))
6929 handled = TRUE;
6930 else
6931 g_signal_emit (widget,
6932 widget_signals[MNEMONIC_ACTIVATE],
6933 0,
6934 group_cycling,
6935 &handled);
6936 return handled;
6937 }
6938
6939 static gboolean
gtk_widget_real_mnemonic_activate(GtkWidget * widget,gboolean group_cycling)6940 gtk_widget_real_mnemonic_activate (GtkWidget *widget,
6941 gboolean group_cycling)
6942 {
6943 if (!group_cycling && GTK_WIDGET_GET_CLASS (widget)->activate_signal)
6944 gtk_widget_activate (widget);
6945 else if (gtk_widget_get_can_focus (widget))
6946 gtk_widget_grab_focus (widget);
6947 else
6948 {
6949 g_warning ("widget '%s' isn't suitable for mnemonic activation",
6950 G_OBJECT_TYPE_NAME (widget));
6951 gtk_widget_error_bell (widget);
6952 }
6953 return TRUE;
6954 }
6955
6956 static const cairo_user_data_key_t mark_for_draw_key;
6957
6958 static gboolean
gtk_cairo_is_marked_for_draw(cairo_t * cr)6959 gtk_cairo_is_marked_for_draw (cairo_t *cr)
6960 {
6961 return cairo_get_user_data (cr, &mark_for_draw_key) != NULL;
6962 }
6963
6964 static void
gtk_cairo_set_marked_for_draw(cairo_t * cr,gboolean marked)6965 gtk_cairo_set_marked_for_draw (cairo_t *cr,
6966 gboolean marked)
6967 {
6968 if (marked)
6969 cairo_set_user_data (cr, &mark_for_draw_key, GINT_TO_POINTER (1), NULL);
6970 else
6971 cairo_set_user_data (cr, &mark_for_draw_key, NULL, NULL);
6972 }
6973
6974 /**
6975 * gtk_cairo_should_draw_window:
6976 * @cr: a cairo context
6977 * @window: the window to check. @window may not be an input-only
6978 * window.
6979 *
6980 * This function is supposed to be called in #GtkWidget::draw
6981 * implementations for widgets that support multiple windows.
6982 * @cr must be untransformed from invoking of the draw function.
6983 * This function will return %TRUE if the contents of the given
6984 * @window are supposed to be drawn and %FALSE otherwise. Note
6985 * that when the drawing was not initiated by the windowing
6986 * system this function will return %TRUE for all windows, so
6987 * you need to draw the bottommost window first. Also, do not
6988 * use “else if” statements to check which window should be drawn.
6989 *
6990 * Returns: %TRUE if @window should be drawn
6991 *
6992 * Since: 3.0
6993 */
6994 gboolean
gtk_cairo_should_draw_window(cairo_t * cr,GdkWindow * window)6995 gtk_cairo_should_draw_window (cairo_t *cr,
6996 GdkWindow *window)
6997 {
6998 GdkDrawingContext *context;
6999 GdkWindow *tmp;
7000
7001 g_return_val_if_fail (cr != NULL, FALSE);
7002 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7003
7004 if (gtk_cairo_is_marked_for_draw (cr))
7005 return TRUE;
7006
7007 context = gdk_cairo_get_drawing_context (cr);
7008 if (context == NULL)
7009 return TRUE;
7010
7011 tmp = gdk_drawing_context_get_window (context);
7012 if (tmp == NULL)
7013 return TRUE;
7014
7015 while (!gdk_window_has_native (window))
7016 window = gdk_window_get_parent (window);
7017
7018 return tmp == window;
7019 }
7020
7021 void
gtk_widget_draw_internal(GtkWidget * widget,cairo_t * cr,gboolean clip_to_size)7022 gtk_widget_draw_internal (GtkWidget *widget,
7023 cairo_t *cr,
7024 gboolean clip_to_size)
7025 {
7026 if (!_gtk_widget_is_drawable (widget))
7027 return;
7028
7029 if (clip_to_size)
7030 {
7031 cairo_rectangle (cr,
7032 widget->priv->clip.x - widget->priv->allocation.x,
7033 widget->priv->clip.y - widget->priv->allocation.y,
7034 widget->priv->clip.width,
7035 widget->priv->clip.height);
7036 cairo_clip (cr);
7037 }
7038
7039 if (gdk_cairo_get_clip_rectangle (cr, NULL))
7040 {
7041 GdkWindow *event_window = NULL;
7042 gboolean result;
7043 gboolean push_group;
7044
7045 /* If this was a cairo_t passed via gtk_widget_draw() then we don't
7046 * require a window; otherwise we check for the window associated
7047 * to the drawing context and mark it using the clip region of the
7048 * Cairo context.
7049 */
7050 if (!gtk_cairo_is_marked_for_draw (cr))
7051 {
7052 GdkDrawingContext *context = gdk_cairo_get_drawing_context (cr);
7053
7054 if (context != NULL)
7055 {
7056 event_window = gdk_drawing_context_get_window (context);
7057 if (event_window != NULL)
7058 gdk_window_mark_paint_from_clip (event_window, cr);
7059 }
7060 }
7061
7062 push_group =
7063 widget->priv->alpha != 255 &&
7064 (!_gtk_widget_is_toplevel (widget) ||
7065 gtk_widget_get_visual (widget) == gdk_screen_get_rgba_visual (gtk_widget_get_screen (widget)));
7066
7067 if (push_group)
7068 cairo_push_group (cr);
7069
7070 #ifdef G_ENABLE_CONSISTENCY_CHECKS
7071 if (_gtk_widget_get_alloc_needed (widget))
7072 g_warning ("%s %p is drawn without a current allocation. This should not happen.", G_OBJECT_TYPE_NAME (widget), widget);
7073 #endif
7074
7075 if (g_signal_has_handler_pending (widget, widget_signals[DRAW], 0, FALSE))
7076 {
7077 g_signal_emit (widget, widget_signals[DRAW],
7078 0, cr,
7079 &result);
7080 }
7081 else if (GTK_WIDGET_GET_CLASS (widget)->draw)
7082 {
7083 cairo_save (cr);
7084 GTK_WIDGET_GET_CLASS (widget)->draw (widget, cr);
7085 cairo_restore (cr);
7086 }
7087
7088 #ifdef G_ENABLE_DEBUG
7089 if (GTK_DISPLAY_DEBUG_CHECK (gtk_widget_get_display (widget), BASELINES))
7090 {
7091 gint baseline = gtk_widget_get_allocated_baseline (widget);
7092 gint width = gtk_widget_get_allocated_width (widget);
7093
7094 if (baseline != -1)
7095 {
7096 cairo_save (cr);
7097 cairo_new_path (cr);
7098 cairo_move_to (cr, 0, baseline+0.5);
7099 cairo_line_to (cr, width, baseline+0.5);
7100 cairo_set_line_width (cr, 1.0);
7101 cairo_set_source_rgba (cr, 1.0, 0, 0, 0.25);
7102 cairo_stroke (cr);
7103 cairo_restore (cr);
7104 }
7105 }
7106 if (widget->priv->highlight_resize)
7107 {
7108 GtkAllocation alloc;
7109 gtk_widget_get_allocation (widget, &alloc);
7110
7111 cairo_rectangle (cr, 0, 0, alloc.width, alloc.height);
7112 cairo_set_source_rgba (cr, 1, 0, 0, 0.2);
7113 cairo_fill (cr);
7114
7115 gtk_widget_queue_draw (widget);
7116
7117 widget->priv->highlight_resize = FALSE;
7118 }
7119 #endif
7120
7121 if (push_group)
7122 {
7123 cairo_pop_group_to_source (cr);
7124 cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
7125 cairo_paint_with_alpha (cr, widget->priv->alpha / 255.0);
7126 }
7127
7128 if (cairo_status (cr) &&
7129 event_window != NULL)
7130 {
7131 /* We check the event so we only warn about internal GTK+ calls.
7132 * Errors might come from PDF streams having write failures and
7133 * we don't want to spam stderr in that case.
7134 * We do want to catch errors from
7135 */
7136 g_warning ("drawing failure for widget '%s': %s",
7137 G_OBJECT_TYPE_NAME (widget),
7138 cairo_status_to_string (cairo_status (cr)));
7139 }
7140 }
7141 }
7142
7143 /**
7144 * gtk_widget_draw:
7145 * @widget: the widget to draw. It must be drawable (see
7146 * gtk_widget_is_drawable()) and a size must have been allocated.
7147 * @cr: a cairo context to draw to
7148 *
7149 * Draws @widget to @cr. The top left corner of the widget will be
7150 * drawn to the currently set origin point of @cr.
7151 *
7152 * You should pass a cairo context as @cr argument that is in an
7153 * original state. Otherwise the resulting drawing is undefined. For
7154 * example changing the operator using cairo_set_operator() or the
7155 * line width using cairo_set_line_width() might have unwanted side
7156 * effects.
7157 * You may however change the context’s transform matrix - like with
7158 * cairo_scale(), cairo_translate() or cairo_set_matrix() and clip
7159 * region with cairo_clip() prior to calling this function. Also, it
7160 * is fine to modify the context with cairo_save() and
7161 * cairo_push_group() prior to calling this function.
7162 *
7163 * Note that special-purpose widgets may contain special code for
7164 * rendering to the screen and might appear differently on screen
7165 * and when rendered using gtk_widget_draw().
7166 *
7167 * Since: 3.0
7168 **/
7169 void
gtk_widget_draw(GtkWidget * widget,cairo_t * cr)7170 gtk_widget_draw (GtkWidget *widget,
7171 cairo_t *cr)
7172 {
7173 gboolean was_marked;
7174
7175 g_return_if_fail (GTK_IS_WIDGET (widget));
7176 g_return_if_fail (!widget->priv->alloc_needed);
7177 g_return_if_fail (!widget->priv->alloc_needed_on_child);
7178 g_return_if_fail (cr != NULL);
7179
7180 cairo_save (cr);
7181
7182 was_marked = gtk_cairo_is_marked_for_draw (cr);
7183
7184 /* We mark the window so that gtk_cairo_should_draw_window()
7185 * will always return TRUE, and all GdkWindows get drawn
7186 */
7187 gtk_cairo_set_marked_for_draw (cr, TRUE);
7188
7189 gtk_widget_draw_internal (widget, cr, TRUE);
7190
7191 gtk_cairo_set_marked_for_draw (cr, was_marked);
7192
7193 cairo_restore (cr);
7194 }
7195
7196 static gboolean
gtk_widget_real_scroll_event(GtkWidget * widget,GdkEventScroll * event)7197 gtk_widget_real_scroll_event (GtkWidget *widget,
7198 GdkEventScroll *event)
7199 {
7200 return _gtk_widget_run_controllers (widget, (GdkEvent *) event,
7201 GTK_PHASE_BUBBLE);
7202 }
7203
7204 static gboolean
gtk_widget_real_button_event(GtkWidget * widget,GdkEventButton * event)7205 gtk_widget_real_button_event (GtkWidget *widget,
7206 GdkEventButton *event)
7207 {
7208 return _gtk_widget_run_controllers (widget, (GdkEvent *) event,
7209 GTK_PHASE_BUBBLE);
7210 }
7211
7212 static gboolean
gtk_widget_real_motion_event(GtkWidget * widget,GdkEventMotion * event)7213 gtk_widget_real_motion_event (GtkWidget *widget,
7214 GdkEventMotion *event)
7215 {
7216 return _gtk_widget_run_controllers (widget, (GdkEvent *) event,
7217 GTK_PHASE_BUBBLE);
7218 }
7219
7220 static gboolean
gtk_widget_real_key_press_event(GtkWidget * widget,GdkEventKey * event)7221 gtk_widget_real_key_press_event (GtkWidget *widget,
7222 GdkEventKey *event)
7223 {
7224 if (_gtk_widget_run_controllers (widget, (GdkEvent *) event,
7225 GTK_PHASE_BUBBLE))
7226 return GDK_EVENT_STOP;
7227
7228 return gtk_bindings_activate_event (G_OBJECT (widget), event);
7229 }
7230
7231 static gboolean
gtk_widget_real_key_release_event(GtkWidget * widget,GdkEventKey * event)7232 gtk_widget_real_key_release_event (GtkWidget *widget,
7233 GdkEventKey *event)
7234 {
7235 if (_gtk_widget_run_controllers (widget, (GdkEvent *) event,
7236 GTK_PHASE_BUBBLE))
7237 return GDK_EVENT_STOP;
7238
7239 return gtk_bindings_activate_event (G_OBJECT (widget), event);
7240 }
7241
7242 static gboolean
gtk_widget_real_focus_in_event(GtkWidget * widget,GdkEventFocus * event)7243 gtk_widget_real_focus_in_event (GtkWidget *widget,
7244 GdkEventFocus *event)
7245 {
7246 gtk_widget_queue_draw (widget);
7247
7248 return FALSE;
7249 }
7250
7251 static gboolean
gtk_widget_real_focus_out_event(GtkWidget * widget,GdkEventFocus * event)7252 gtk_widget_real_focus_out_event (GtkWidget *widget,
7253 GdkEventFocus *event)
7254 {
7255 gtk_widget_queue_draw (widget);
7256
7257 return FALSE;
7258 }
7259
7260 static gboolean
gtk_widget_real_touch_event(GtkWidget * widget,GdkEventTouch * event)7261 gtk_widget_real_touch_event (GtkWidget *widget,
7262 GdkEventTouch *event)
7263 {
7264 GdkEvent *bevent;
7265 gboolean return_val = FALSE;
7266
7267 if (!event->emulating_pointer)
7268 return _gtk_widget_run_controllers (widget, (GdkEvent*) event,
7269 GTK_PHASE_BUBBLE);
7270
7271 if (event->type == GDK_TOUCH_UPDATE ||
7272 event->type == GDK_TOUCH_BEGIN)
7273 {
7274 bevent = gdk_event_new (GDK_MOTION_NOTIFY);
7275 bevent->any.window = g_object_ref (event->window);
7276 bevent->any.send_event = FALSE;
7277 bevent->motion.time = event->time;
7278 bevent->button.state = event->state;
7279 bevent->motion.x_root = event->x_root;
7280 bevent->motion.y_root = event->y_root;
7281 bevent->motion.x = event->x;
7282 bevent->motion.y = event->y;
7283 bevent->motion.device = event->device;
7284 bevent->motion.is_hint = FALSE;
7285 bevent->motion.axes = g_memdup (event->axes,
7286 sizeof (gdouble) * gdk_device_get_n_axes (event->device));
7287 gdk_event_set_source_device (bevent, gdk_event_get_source_device ((GdkEvent*)event));
7288
7289 if (event->type == GDK_TOUCH_UPDATE)
7290 bevent->motion.state |= GDK_BUTTON1_MASK;
7291
7292 g_signal_emit (widget, widget_signals[MOTION_NOTIFY_EVENT], 0, bevent, &return_val);
7293
7294 gdk_event_free (bevent);
7295 }
7296
7297 if (event->type == GDK_TOUCH_BEGIN ||
7298 event->type == GDK_TOUCH_END)
7299 {
7300 GdkEventType type;
7301 gint signum;
7302
7303 if (event->type == GDK_TOUCH_BEGIN)
7304 {
7305 type = GDK_BUTTON_PRESS;
7306 signum = BUTTON_PRESS_EVENT;
7307 }
7308 else
7309 {
7310 type = GDK_BUTTON_RELEASE;
7311 signum = BUTTON_RELEASE_EVENT;
7312 }
7313 bevent = gdk_event_new (type);
7314 bevent->any.window = g_object_ref (event->window);
7315 bevent->any.send_event = FALSE;
7316 bevent->button.time = event->time;
7317 bevent->button.state = event->state;
7318 bevent->button.button = 1;
7319 bevent->button.x_root = event->x_root;
7320 bevent->button.y_root = event->y_root;
7321 bevent->button.x = event->x;
7322 bevent->button.y = event->y;
7323 bevent->button.device = event->device;
7324 bevent->button.axes = g_memdup (event->axes,
7325 sizeof (gdouble) * gdk_device_get_n_axes (event->device));
7326 gdk_event_set_source_device (bevent, gdk_event_get_source_device ((GdkEvent*)event));
7327
7328 if (event->type == GDK_TOUCH_END)
7329 bevent->button.state |= GDK_BUTTON1_MASK;
7330
7331 g_signal_emit (widget, widget_signals[signum], 0, bevent, &return_val);
7332
7333 gdk_event_free (bevent);
7334 }
7335
7336 return return_val;
7337 }
7338
7339 static gboolean
gtk_widget_real_grab_broken_event(GtkWidget * widget,GdkEventGrabBroken * event)7340 gtk_widget_real_grab_broken_event (GtkWidget *widget,
7341 GdkEventGrabBroken *event)
7342 {
7343 return _gtk_widget_run_controllers (widget, (GdkEvent*) event,
7344 GTK_PHASE_BUBBLE);
7345 }
7346
7347 #define WIDGET_REALIZED_FOR_EVENT(widget, event) \
7348 (event->type == GDK_FOCUS_CHANGE || _gtk_widget_get_realized(widget))
7349
7350 /**
7351 * gtk_widget_event:
7352 * @widget: a #GtkWidget
7353 * @event: a #GdkEvent
7354 *
7355 * Rarely-used function. This function is used to emit
7356 * the event signals on a widget (those signals should never
7357 * be emitted without using this function to do so).
7358 * If you want to synthesize an event though, don’t use this function;
7359 * instead, use gtk_main_do_event() so the event will behave as if
7360 * it were in the event queue. Don’t synthesize expose events; instead,
7361 * use gdk_window_invalidate_rect() to invalidate a region of the
7362 * window.
7363 *
7364 * Returns: return from the event signal emission (%TRUE if
7365 * the event was handled)
7366 **/
7367 gboolean
gtk_widget_event(GtkWidget * widget,GdkEvent * event)7368 gtk_widget_event (GtkWidget *widget,
7369 GdkEvent *event)
7370 {
7371 g_return_val_if_fail (GTK_IS_WIDGET (widget), TRUE);
7372 g_return_val_if_fail (WIDGET_REALIZED_FOR_EVENT (widget, event), TRUE);
7373
7374 if (event->type == GDK_EXPOSE)
7375 {
7376 g_warning ("Events of type GDK_EXPOSE cannot be synthesized. To get "
7377 "the same effect, call gdk_window_invalidate_rect/region(), "
7378 "followed by gdk_window_process_updates().");
7379 return TRUE;
7380 }
7381
7382 return gtk_widget_event_internal (widget, event);
7383 }
7384
7385 void
_gtk_widget_set_captured_event_handler(GtkWidget * widget,GtkCapturedEventHandler callback)7386 _gtk_widget_set_captured_event_handler (GtkWidget *widget,
7387 GtkCapturedEventHandler callback)
7388 {
7389 g_object_set_data (G_OBJECT (widget), "captured-event-handler", callback);
7390 }
7391
7392 static GdkEventMask
_gtk_widget_get_controllers_evmask(GtkWidget * widget)7393 _gtk_widget_get_controllers_evmask (GtkWidget *widget)
7394 {
7395 EventControllerData *data;
7396 GdkEventMask evmask = 0;
7397 GtkWidgetPrivate *priv;
7398 GList *l;
7399
7400 priv = widget->priv;
7401
7402 for (l = priv->event_controllers; l; l = l->next)
7403 {
7404 data = l->data;
7405 if (data->controller)
7406 evmask |= gtk_event_controller_get_event_mask (GTK_EVENT_CONTROLLER (data->controller));
7407 }
7408
7409 return evmask;
7410 }
7411
7412 static gboolean
_gtk_widget_run_controllers(GtkWidget * widget,const GdkEvent * event,GtkPropagationPhase phase)7413 _gtk_widget_run_controllers (GtkWidget *widget,
7414 const GdkEvent *event,
7415 GtkPropagationPhase phase)
7416 {
7417 EventControllerData *data;
7418 gboolean handled = FALSE;
7419 GtkWidgetPrivate *priv;
7420 GList *l;
7421
7422 priv = widget->priv;
7423 g_object_ref (widget);
7424
7425 l = priv->event_controllers;
7426 while (l != NULL)
7427 {
7428 GList *next = l->next;
7429
7430 if (!WIDGET_REALIZED_FOR_EVENT (widget, event))
7431 break;
7432
7433 data = l->data;
7434
7435 if (data->controller == NULL)
7436 {
7437 priv->event_controllers = g_list_delete_link (priv->event_controllers, l);
7438 g_free (data);
7439 }
7440 else
7441 {
7442 GtkPropagationPhase controller_phase;
7443
7444 controller_phase = gtk_event_controller_get_propagation_phase (data->controller);
7445
7446 if (controller_phase == phase)
7447 handled |= gtk_event_controller_handle_event (data->controller, event);
7448 }
7449
7450 l = next;
7451 }
7452
7453 g_object_unref (widget);
7454
7455 return handled;
7456 }
7457
7458 static void
cancel_event_sequence_on_hierarchy(GtkWidget * widget,GtkWidget * event_widget,GdkEventSequence * sequence)7459 cancel_event_sequence_on_hierarchy (GtkWidget *widget,
7460 GtkWidget *event_widget,
7461 GdkEventSequence *sequence)
7462 {
7463 gboolean cancel = TRUE;
7464
7465 while (event_widget)
7466 {
7467 if (event_widget == widget)
7468 cancel = FALSE;
7469 else if (cancel)
7470 _gtk_widget_cancel_sequence (event_widget, sequence);
7471 else
7472 _gtk_widget_set_sequence_state_internal (event_widget, sequence,
7473 GTK_EVENT_SEQUENCE_DENIED,
7474 NULL);
7475
7476 event_widget = _gtk_widget_get_parent (event_widget);
7477 }
7478 }
7479
7480 gboolean
_gtk_widget_captured_event(GtkWidget * widget,GdkEvent * event)7481 _gtk_widget_captured_event (GtkWidget *widget,
7482 GdkEvent *event)
7483 {
7484 gboolean return_val = FALSE;
7485 GtkCapturedEventHandler handler;
7486
7487 g_return_val_if_fail (GTK_IS_WIDGET (widget), TRUE);
7488 g_return_val_if_fail (WIDGET_REALIZED_FOR_EVENT (widget, event), TRUE);
7489
7490 if (event->type == GDK_EXPOSE)
7491 {
7492 g_warning ("Events of type GDK_EXPOSE cannot be synthesized. To get "
7493 "the same effect, call gdk_window_invalidate_rect/region(), "
7494 "followed by gdk_window_process_updates().");
7495 return TRUE;
7496 }
7497
7498 if (!event_window_is_still_viewable (event))
7499 return TRUE;
7500
7501 return_val = _gtk_widget_run_controllers (widget, event, GTK_PHASE_CAPTURE);
7502
7503 handler = g_object_get_data (G_OBJECT (widget), "captured-event-handler");
7504 if (!handler)
7505 return return_val;
7506
7507 g_object_ref (widget);
7508
7509 return_val |= handler (widget, event);
7510 return_val |= !WIDGET_REALIZED_FOR_EVENT (widget, event);
7511
7512 /* The widget that was originally to receive the event
7513 * handles motion hints, but the capturing widget might
7514 * not, so ensure we get further motion events.
7515 */
7516 if (return_val &&
7517 event->type == GDK_MOTION_NOTIFY &&
7518 event->motion.is_hint &&
7519 (gdk_window_get_events (event->any.window) &
7520 GDK_POINTER_MOTION_HINT_MASK) != 0)
7521 gdk_event_request_motions (&event->motion);
7522
7523 g_object_unref (widget);
7524
7525 return return_val;
7526 }
7527
7528 /* Returns TRUE if a translation should be done */
7529 static gboolean
_gtk_widget_get_translation_to_window(GtkWidget * widget,GdkWindow * window,int * x,int * y)7530 _gtk_widget_get_translation_to_window (GtkWidget *widget,
7531 GdkWindow *window,
7532 int *x,
7533 int *y)
7534 {
7535 GdkWindow *w, *widget_window;
7536
7537 if (!_gtk_widget_get_has_window (widget))
7538 {
7539 *x = -widget->priv->allocation.x;
7540 *y = -widget->priv->allocation.y;
7541 }
7542 else
7543 {
7544 *x = 0;
7545 *y = 0;
7546 }
7547
7548 widget_window = _gtk_widget_get_window (widget);
7549
7550 for (w = window; w && w != widget_window; w = gdk_window_get_parent (w))
7551 {
7552 int wx, wy;
7553 gdk_window_get_position (w, &wx, &wy);
7554 *x += wx;
7555 *y += wy;
7556 }
7557
7558 if (w == NULL)
7559 {
7560 *x = 0;
7561 *y = 0;
7562 return FALSE;
7563 }
7564
7565 return TRUE;
7566 }
7567
7568
7569 /**
7570 * gtk_cairo_transform_to_window:
7571 * @cr: the cairo context to transform
7572 * @widget: the widget the context is currently centered for
7573 * @window: the window to transform the context to
7574 *
7575 * Transforms the given cairo context @cr that from @widget-relative
7576 * coordinates to @window-relative coordinates.
7577 * If the @widget’s window is not an ancestor of @window, no
7578 * modification will be applied.
7579 *
7580 * This is the inverse to the transformation GTK applies when
7581 * preparing an expose event to be emitted with the #GtkWidget::draw
7582 * signal. It is intended to help porting multiwindow widgets from
7583 * GTK+ 2 to the rendering architecture of GTK+ 3.
7584 *
7585 * Since: 3.0
7586 **/
7587 void
gtk_cairo_transform_to_window(cairo_t * cr,GtkWidget * widget,GdkWindow * window)7588 gtk_cairo_transform_to_window (cairo_t *cr,
7589 GtkWidget *widget,
7590 GdkWindow *window)
7591 {
7592 int x, y;
7593
7594 g_return_if_fail (cr != NULL);
7595 g_return_if_fail (GTK_IS_WIDGET (widget));
7596 g_return_if_fail (GDK_IS_WINDOW (window));
7597
7598 if (_gtk_widget_get_translation_to_window (widget, window, &x, &y))
7599 cairo_translate (cr, x, y);
7600 }
7601
7602 /**
7603 * gtk_widget_send_expose:
7604 * @widget: a #GtkWidget
7605 * @event: a expose #GdkEvent
7606 *
7607 * Very rarely-used function. This function is used to emit
7608 * an expose event on a widget. This function is not normally used
7609 * directly. The only time it is used is when propagating an expose
7610 * event to a windowless child widget (gtk_widget_get_has_window() is %FALSE),
7611 * and that is normally done using gtk_container_propagate_draw().
7612 *
7613 * If you want to force an area of a window to be redrawn,
7614 * use gdk_window_invalidate_rect() or gdk_window_invalidate_region().
7615 * To cause the redraw to be done immediately, follow that call
7616 * with a call to gdk_window_process_updates().
7617 *
7618 * Returns: return from the event signal emission (%TRUE if
7619 * the event was handled)
7620 *
7621 * Deprecated: 3.22: Application and widget code should not handle
7622 * expose events directly; invalidation should use the #GtkWidget
7623 * API, and drawing should only happen inside #GtkWidget::draw
7624 * implementations
7625 */
7626 gint
gtk_widget_send_expose(GtkWidget * widget,GdkEvent * event)7627 gtk_widget_send_expose (GtkWidget *widget,
7628 GdkEvent *event)
7629 {
7630 g_return_val_if_fail (GTK_IS_WIDGET (widget), TRUE);
7631 g_return_val_if_fail (gtk_widget_get_realized (widget), TRUE);
7632 g_return_val_if_fail (event != NULL, TRUE);
7633 g_return_val_if_fail (event->type == GDK_EXPOSE, TRUE);
7634
7635 gtk_widget_render (widget, event->any.window, event->expose.region);
7636
7637 return FALSE;
7638 }
7639
7640 static gboolean
event_window_is_still_viewable(GdkEvent * event)7641 event_window_is_still_viewable (GdkEvent *event)
7642 {
7643 /* Check that we think the event's window is viewable before
7644 * delivering the event, to prevent surprises. We do this here
7645 * at the last moment, since the event may have been queued
7646 * up behind other events, held over a recursive main loop, etc.
7647 */
7648 switch (event->type)
7649 {
7650 case GDK_EXPOSE:
7651 case GDK_MOTION_NOTIFY:
7652 case GDK_BUTTON_PRESS:
7653 case GDK_2BUTTON_PRESS:
7654 case GDK_3BUTTON_PRESS:
7655 case GDK_KEY_PRESS:
7656 case GDK_ENTER_NOTIFY:
7657 case GDK_PROXIMITY_IN:
7658 case GDK_SCROLL:
7659 return event->any.window && gdk_window_is_viewable (event->any.window);
7660
7661 #if 0
7662 /* The following events are the second half of paired events;
7663 * we always deliver them to deal with widgets that clean up
7664 * on the second half.
7665 */
7666 case GDK_BUTTON_RELEASE:
7667 case GDK_KEY_RELEASE:
7668 case GDK_LEAVE_NOTIFY:
7669 case GDK_PROXIMITY_OUT:
7670 #endif
7671
7672 default:
7673 /* Remaining events would make sense on an not-viewable window,
7674 * or don't have an associated window.
7675 */
7676 return TRUE;
7677 }
7678 }
7679
7680 static gint
gtk_widget_event_internal(GtkWidget * widget,GdkEvent * event)7681 gtk_widget_event_internal (GtkWidget *widget,
7682 GdkEvent *event)
7683 {
7684 gboolean return_val = FALSE, handled;
7685
7686 /* We check only once for is-still-visible; if someone
7687 * hides the window in on of the signals on the widget,
7688 * they are responsible for returning TRUE to terminate
7689 * handling.
7690 */
7691 if (!event_window_is_still_viewable (event))
7692 return TRUE;
7693
7694 g_object_ref (widget);
7695
7696 if (widget == gtk_get_event_widget (event))
7697 return_val |= _gtk_widget_run_controllers (widget, event, GTK_PHASE_TARGET);
7698
7699 g_signal_emit (widget, widget_signals[EVENT], 0, event, &handled);
7700 return_val |= handled | !WIDGET_REALIZED_FOR_EVENT (widget, event);
7701 if (!return_val)
7702 {
7703 gint signal_num;
7704
7705 switch (event->type)
7706 {
7707 case GDK_TOUCHPAD_SWIPE:
7708 case GDK_TOUCHPAD_PINCH:
7709 return_val |= _gtk_widget_run_controllers (widget, event, GTK_PHASE_BUBBLE);
7710 /* Fall through */
7711 case GDK_PAD_BUTTON_PRESS:
7712 case GDK_PAD_BUTTON_RELEASE:
7713 case GDK_PAD_RING:
7714 case GDK_PAD_STRIP:
7715 case GDK_PAD_GROUP_MODE:
7716 case GDK_EXPOSE:
7717 case GDK_NOTHING:
7718 signal_num = -1;
7719 break;
7720 case GDK_BUTTON_PRESS:
7721 case GDK_2BUTTON_PRESS:
7722 case GDK_3BUTTON_PRESS:
7723 signal_num = BUTTON_PRESS_EVENT;
7724 break;
7725 case GDK_TOUCH_BEGIN:
7726 case GDK_TOUCH_UPDATE:
7727 case GDK_TOUCH_END:
7728 case GDK_TOUCH_CANCEL:
7729 signal_num = TOUCH_EVENT;
7730 break;
7731 case GDK_SCROLL:
7732 signal_num = SCROLL_EVENT;
7733 break;
7734 case GDK_BUTTON_RELEASE:
7735 signal_num = BUTTON_RELEASE_EVENT;
7736 break;
7737 case GDK_MOTION_NOTIFY:
7738 signal_num = MOTION_NOTIFY_EVENT;
7739 break;
7740 case GDK_DELETE:
7741 signal_num = DELETE_EVENT;
7742 break;
7743 case GDK_DESTROY:
7744 signal_num = DESTROY_EVENT;
7745 _gtk_tooltip_hide (widget);
7746 break;
7747 case GDK_KEY_PRESS:
7748 signal_num = KEY_PRESS_EVENT;
7749 break;
7750 case GDK_KEY_RELEASE:
7751 signal_num = KEY_RELEASE_EVENT;
7752 break;
7753 case GDK_ENTER_NOTIFY:
7754 signal_num = ENTER_NOTIFY_EVENT;
7755 break;
7756 case GDK_LEAVE_NOTIFY:
7757 signal_num = LEAVE_NOTIFY_EVENT;
7758 break;
7759 case GDK_FOCUS_CHANGE:
7760 signal_num = event->focus_change.in ? FOCUS_IN_EVENT : FOCUS_OUT_EVENT;
7761 if (event->focus_change.in)
7762 _gtk_tooltip_focus_in (widget);
7763 else
7764 _gtk_tooltip_focus_out (widget);
7765 break;
7766 case GDK_CONFIGURE:
7767 signal_num = CONFIGURE_EVENT;
7768 break;
7769 case GDK_MAP:
7770 signal_num = MAP_EVENT;
7771 break;
7772 case GDK_UNMAP:
7773 signal_num = UNMAP_EVENT;
7774 break;
7775 case GDK_WINDOW_STATE:
7776 signal_num = WINDOW_STATE_EVENT;
7777 break;
7778 case GDK_PROPERTY_NOTIFY:
7779 signal_num = PROPERTY_NOTIFY_EVENT;
7780 break;
7781 case GDK_SELECTION_CLEAR:
7782 signal_num = SELECTION_CLEAR_EVENT;
7783 break;
7784 case GDK_SELECTION_REQUEST:
7785 signal_num = SELECTION_REQUEST_EVENT;
7786 break;
7787 case GDK_SELECTION_NOTIFY:
7788 signal_num = SELECTION_NOTIFY_EVENT;
7789 break;
7790 case GDK_PROXIMITY_IN:
7791 signal_num = PROXIMITY_IN_EVENT;
7792 break;
7793 case GDK_PROXIMITY_OUT:
7794 signal_num = PROXIMITY_OUT_EVENT;
7795 break;
7796 case GDK_VISIBILITY_NOTIFY:
7797 signal_num = VISIBILITY_NOTIFY_EVENT;
7798 break;
7799 case GDK_GRAB_BROKEN:
7800 signal_num = GRAB_BROKEN_EVENT;
7801 break;
7802 case GDK_DAMAGE:
7803 signal_num = DAMAGE_EVENT;
7804 break;
7805 default:
7806 g_warning ("gtk_widget_event(): unhandled event type: %d", event->type);
7807 signal_num = -1;
7808 break;
7809 }
7810 if (signal_num != -1)
7811 {
7812 g_signal_emit (widget, widget_signals[signal_num], 0, event, &handled);
7813 return_val |= handled;
7814 }
7815 }
7816 if (WIDGET_REALIZED_FOR_EVENT (widget, event))
7817 g_signal_emit (widget, widget_signals[EVENT_AFTER], 0, event);
7818 else
7819 return_val = TRUE;
7820
7821 g_object_unref (widget);
7822
7823 return return_val;
7824 }
7825
7826 /**
7827 * gtk_widget_activate:
7828 * @widget: a #GtkWidget that’s activatable
7829 *
7830 * For widgets that can be “activated” (buttons, menu items, etc.)
7831 * this function activates them. Activation is what happens when you
7832 * press Enter on a widget during key navigation. If @widget isn't
7833 * activatable, the function returns %FALSE.
7834 *
7835 * Returns: %TRUE if the widget was activatable
7836 **/
7837 gboolean
gtk_widget_activate(GtkWidget * widget)7838 gtk_widget_activate (GtkWidget *widget)
7839 {
7840 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
7841
7842 if (WIDGET_CLASS (widget)->activate_signal)
7843 {
7844 /* FIXME: we should eventually check the signals signature here */
7845 g_signal_emit (widget, WIDGET_CLASS (widget)->activate_signal, 0);
7846
7847 return TRUE;
7848 }
7849 else
7850 return FALSE;
7851 }
7852
7853 static void
gtk_widget_reparent_subwindows(GtkWidget * widget,GdkWindow * new_window)7854 gtk_widget_reparent_subwindows (GtkWidget *widget,
7855 GdkWindow *new_window)
7856 {
7857 GtkWidgetPrivate *priv = widget->priv;
7858
7859 if (!_gtk_widget_get_has_window (widget))
7860 {
7861 GList *children = gdk_window_get_children (priv->window);
7862 GList *tmp_list;
7863
7864 for (tmp_list = children; tmp_list; tmp_list = tmp_list->next)
7865 {
7866 GdkWindow *window = tmp_list->data;
7867 gpointer child;
7868
7869 gdk_window_get_user_data (window, &child);
7870 while (child && child != widget)
7871 child = ((GtkWidget*) child)->priv->parent;
7872
7873 if (child)
7874 gdk_window_reparent (window, new_window, 0, 0);
7875 }
7876
7877 g_list_free (children);
7878 }
7879 else
7880 {
7881 GdkWindow *parent;
7882 GList *tmp_list, *children;
7883
7884 parent = gdk_window_get_parent (priv->window);
7885
7886 if (parent == NULL)
7887 gdk_window_reparent (priv->window, new_window, 0, 0);
7888 else
7889 {
7890 children = gdk_window_get_children (parent);
7891
7892 for (tmp_list = children; tmp_list; tmp_list = tmp_list->next)
7893 {
7894 GdkWindow *window = tmp_list->data;
7895 gpointer child;
7896
7897 gdk_window_get_user_data (window, &child);
7898
7899 if (child == widget)
7900 gdk_window_reparent (window, new_window, 0, 0);
7901 }
7902
7903 g_list_free (children);
7904 }
7905 }
7906 }
7907
7908 static void
gtk_widget_reparent_fixup_child(GtkWidget * widget,gpointer client_data)7909 gtk_widget_reparent_fixup_child (GtkWidget *widget,
7910 gpointer client_data)
7911 {
7912 GtkWidgetPrivate *priv = widget->priv;
7913
7914 g_assert (client_data != NULL);
7915
7916 if (!_gtk_widget_get_has_window (widget))
7917 {
7918 if (priv->window)
7919 g_object_unref (priv->window);
7920 priv->window = (GdkWindow*) client_data;
7921 if (priv->window)
7922 g_object_ref (priv->window);
7923
7924 if (GTK_IS_CONTAINER (widget))
7925 gtk_container_forall (GTK_CONTAINER (widget),
7926 gtk_widget_reparent_fixup_child,
7927 client_data);
7928 }
7929 }
7930
7931 /**
7932 * gtk_widget_reparent:
7933 * @widget: a #GtkWidget
7934 * @new_parent: a #GtkContainer to move the widget into
7935 *
7936 * Moves a widget from one #GtkContainer to another, handling reference
7937 * count issues to avoid destroying the widget.
7938 *
7939 * Deprecated: 3.14: Use gtk_container_remove() and gtk_container_add().
7940 **/
7941 void
gtk_widget_reparent(GtkWidget * widget,GtkWidget * new_parent)7942 gtk_widget_reparent (GtkWidget *widget,
7943 GtkWidget *new_parent)
7944 {
7945 GtkWidgetPrivate *priv;
7946
7947 g_return_if_fail (GTK_IS_WIDGET (widget));
7948 g_return_if_fail (GTK_IS_CONTAINER (new_parent));
7949 priv = widget->priv;
7950 g_return_if_fail (priv->parent != NULL);
7951
7952 if (priv->parent != new_parent)
7953 {
7954 /* First try to see if we can get away without unrealizing
7955 * the widget as we reparent it. if so we set a flag so
7956 * that gtk_widget_unparent doesn't unrealize widget
7957 */
7958 if (_gtk_widget_get_realized (widget) && _gtk_widget_get_realized (new_parent))
7959 priv->in_reparent = TRUE;
7960
7961 g_object_ref (widget);
7962 gtk_container_remove (GTK_CONTAINER (priv->parent), widget);
7963 gtk_container_add (GTK_CONTAINER (new_parent), widget);
7964 g_object_unref (widget);
7965
7966 if (priv->in_reparent)
7967 {
7968 priv->in_reparent = FALSE;
7969
7970 gtk_widget_reparent_subwindows (widget, gtk_widget_get_parent_window (widget));
7971 gtk_widget_reparent_fixup_child (widget,
7972 gtk_widget_get_parent_window (widget));
7973 }
7974
7975 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_PARENT]);
7976 }
7977 }
7978
7979 /**
7980 * gtk_widget_intersect:
7981 * @widget: a #GtkWidget
7982 * @area: a rectangle
7983 * @intersection: (out caller-allocates) (optional): rectangle to store
7984 * intersection of @widget and @area
7985 *
7986 * Computes the intersection of a @widget’s area and @area, storing
7987 * the intersection in @intersection, and returns %TRUE if there was
7988 * an intersection. @intersection may be %NULL if you’re only
7989 * interested in whether there was an intersection.
7990 *
7991 * Returns: %TRUE if there was an intersection
7992 **/
7993 gboolean
gtk_widget_intersect(GtkWidget * widget,const GdkRectangle * area,GdkRectangle * intersection)7994 gtk_widget_intersect (GtkWidget *widget,
7995 const GdkRectangle *area,
7996 GdkRectangle *intersection)
7997 {
7998 GtkWidgetPrivate *priv;
7999 GdkRectangle *dest;
8000 GdkRectangle tmp;
8001 gint return_val;
8002
8003 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8004 g_return_val_if_fail (area != NULL, FALSE);
8005
8006 priv = widget->priv;
8007
8008 if (intersection)
8009 dest = intersection;
8010 else
8011 dest = &tmp;
8012
8013 return_val = gdk_rectangle_intersect (&priv->allocation, area, dest);
8014
8015 if (return_val && intersection && _gtk_widget_get_has_window (widget))
8016 {
8017 intersection->x -= priv->allocation.x;
8018 intersection->y -= priv->allocation.y;
8019 }
8020
8021 return return_val;
8022 }
8023
8024 /**
8025 * gtk_widget_region_intersect:
8026 * @widget: a #GtkWidget
8027 * @region: a #cairo_region_t, in the same coordinate system as
8028 * @widget->allocation. That is, relative to @widget->window
8029 * for widgets which return %FALSE from gtk_widget_get_has_window();
8030 * relative to the parent window of @widget->window otherwise.
8031 *
8032 * Computes the intersection of a @widget’s area and @region, returning
8033 * the intersection. The result may be empty, use cairo_region_is_empty() to
8034 * check.
8035 *
8036 * Returns: A newly allocated region holding the intersection of @widget
8037 * and @region.
8038 *
8039 * Deprecated: 3.14: Use gtk_widget_get_allocation() and
8040 * cairo_region_intersect_rectangle() to get the same behavior.
8041 */
8042 cairo_region_t *
gtk_widget_region_intersect(GtkWidget * widget,const cairo_region_t * region)8043 gtk_widget_region_intersect (GtkWidget *widget,
8044 const cairo_region_t *region)
8045 {
8046 GdkRectangle rect;
8047 cairo_region_t *dest;
8048
8049 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
8050 g_return_val_if_fail (region != NULL, NULL);
8051
8052 _gtk_widget_get_allocation (widget, &rect);
8053
8054 dest = cairo_region_create_rectangle (&rect);
8055
8056 cairo_region_intersect (dest, region);
8057
8058 return dest;
8059 }
8060
8061 /**
8062 * _gtk_widget_grab_notify:
8063 * @widget: a #GtkWidget
8064 * @was_grabbed: whether a grab is now in effect
8065 *
8066 * Emits the #GtkWidget::grab-notify signal on @widget.
8067 *
8068 * Since: 2.6
8069 **/
8070 void
_gtk_widget_grab_notify(GtkWidget * widget,gboolean was_grabbed)8071 _gtk_widget_grab_notify (GtkWidget *widget,
8072 gboolean was_grabbed)
8073 {
8074 g_signal_emit (widget, widget_signals[GRAB_NOTIFY], 0, was_grabbed);
8075 }
8076
8077 /**
8078 * gtk_widget_grab_focus:
8079 * @widget: a #GtkWidget
8080 *
8081 * Causes @widget to have the keyboard focus for the #GtkWindow it's
8082 * inside. @widget must be a focusable widget, such as a #GtkEntry;
8083 * something like #GtkFrame won’t work.
8084 *
8085 * More precisely, it must have the %GTK_CAN_FOCUS flag set. Use
8086 * gtk_widget_set_can_focus() to modify that flag.
8087 *
8088 * The widget also needs to be realized and mapped. This is indicated by the
8089 * related signals. Grabbing the focus immediately after creating the widget
8090 * will likely fail and cause critical warnings.
8091 **/
8092 void
gtk_widget_grab_focus(GtkWidget * widget)8093 gtk_widget_grab_focus (GtkWidget *widget)
8094 {
8095 g_return_if_fail (GTK_IS_WIDGET (widget));
8096
8097 if (!gtk_widget_is_sensitive (widget))
8098 return;
8099
8100 g_object_ref (widget);
8101 g_signal_emit (widget, widget_signals[GRAB_FOCUS], 0);
8102 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]);
8103 g_object_unref (widget);
8104 }
8105
8106 static void
reset_focus_recurse(GtkWidget * widget,gpointer data)8107 reset_focus_recurse (GtkWidget *widget,
8108 gpointer data)
8109 {
8110 if (GTK_IS_CONTAINER (widget))
8111 {
8112 GtkContainer *container;
8113
8114 container = GTK_CONTAINER (widget);
8115 gtk_container_set_focus_child (container, NULL);
8116
8117 gtk_container_foreach (container,
8118 reset_focus_recurse,
8119 NULL);
8120 }
8121 }
8122
8123 static void
gtk_widget_real_grab_focus(GtkWidget * focus_widget)8124 gtk_widget_real_grab_focus (GtkWidget *focus_widget)
8125 {
8126 if (gtk_widget_get_can_focus (focus_widget))
8127 {
8128 GtkWidget *toplevel;
8129 GtkWidget *widget;
8130
8131 /* clear the current focus setting, break if the current widget
8132 * is the focus widget's parent, since containers above that will
8133 * be set by the next loop.
8134 */
8135 toplevel = _gtk_widget_get_toplevel (focus_widget);
8136 if (_gtk_widget_is_toplevel (toplevel) && GTK_IS_WINDOW (toplevel))
8137 {
8138 widget = gtk_window_get_focus (GTK_WINDOW (toplevel));
8139
8140 if (widget == focus_widget)
8141 {
8142 /* We call _gtk_window_internal_set_focus() here so that the
8143 * toplevel window can request the focus if necessary.
8144 * This is needed when the toplevel is a GtkPlug
8145 */
8146 if (!gtk_widget_has_focus (widget))
8147 _gtk_window_internal_set_focus (GTK_WINDOW (toplevel), focus_widget);
8148
8149 return;
8150 }
8151
8152 if (widget)
8153 {
8154 GtkWidget *common_ancestor = gtk_widget_common_ancestor (widget, focus_widget);
8155
8156 if (widget != common_ancestor)
8157 {
8158 while (widget->priv->parent)
8159 {
8160 widget = widget->priv->parent;
8161 gtk_container_set_focus_child (GTK_CONTAINER (widget), NULL);
8162 if (widget == common_ancestor)
8163 break;
8164 }
8165 }
8166 }
8167 }
8168 else if (toplevel != focus_widget)
8169 {
8170 /* gtk_widget_grab_focus() operates on a tree without window...
8171 * actually, this is very questionable behavior.
8172 */
8173
8174 gtk_container_foreach (GTK_CONTAINER (toplevel),
8175 reset_focus_recurse,
8176 NULL);
8177 }
8178
8179 /* now propagate the new focus up the widget tree and finally
8180 * set it on the window
8181 */
8182 widget = focus_widget;
8183 while (widget->priv->parent)
8184 {
8185 gtk_container_set_focus_child (GTK_CONTAINER (widget->priv->parent), widget);
8186 widget = widget->priv->parent;
8187 }
8188 if (GTK_IS_WINDOW (widget))
8189 _gtk_window_internal_set_focus (GTK_WINDOW (widget), focus_widget);
8190 }
8191 }
8192
8193 static gboolean
gtk_widget_real_query_tooltip(GtkWidget * widget,gint x,gint y,gboolean keyboard_tip,GtkTooltip * tooltip)8194 gtk_widget_real_query_tooltip (GtkWidget *widget,
8195 gint x,
8196 gint y,
8197 gboolean keyboard_tip,
8198 GtkTooltip *tooltip)
8199 {
8200 gchar *tooltip_markup;
8201 gboolean has_tooltip;
8202
8203 tooltip_markup = g_object_get_qdata (G_OBJECT (widget), quark_tooltip_markup);
8204 has_tooltip = gtk_widget_get_has_tooltip (widget);
8205
8206 if (has_tooltip && tooltip_markup)
8207 {
8208 gtk_tooltip_set_markup (tooltip, tooltip_markup);
8209 return TRUE;
8210 }
8211
8212 return FALSE;
8213 }
8214
8215 gboolean
gtk_widget_query_tooltip(GtkWidget * widget,gint x,gint y,gboolean keyboard_mode,GtkTooltip * tooltip)8216 gtk_widget_query_tooltip (GtkWidget *widget,
8217 gint x,
8218 gint y,
8219 gboolean keyboard_mode,
8220 GtkTooltip *tooltip)
8221 {
8222 gboolean retval = FALSE;
8223
8224 g_signal_emit (widget,
8225 widget_signals[QUERY_TOOLTIP],
8226 0,
8227 x, y,
8228 keyboard_mode,
8229 tooltip,
8230 &retval);
8231
8232 return retval;
8233 }
8234
8235 static void
gtk_widget_real_state_flags_changed(GtkWidget * widget,GtkStateFlags old_state)8236 gtk_widget_real_state_flags_changed (GtkWidget *widget,
8237 GtkStateFlags old_state)
8238 {
8239 }
8240
8241 static void
gtk_widget_real_style_updated(GtkWidget * widget)8242 gtk_widget_real_style_updated (GtkWidget *widget)
8243 {
8244 GtkWidgetPrivate *priv = widget->priv;
8245
8246 gtk_widget_update_alpha (widget);
8247
8248 if (widget->priv->context)
8249 {
8250 GtkCssStyleChange *change = gtk_style_context_get_change (widget->priv->context);
8251 gboolean has_text = gtk_widget_peek_pango_context (widget) != NULL;
8252
8253 if (change == NULL ||
8254 (has_text && gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_FONT)))
8255 gtk_widget_update_pango_context (widget);
8256
8257 if (widget->priv->anchored)
8258 {
8259 if (change == NULL ||
8260 gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_SIZE) ||
8261 (has_text && gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_TEXT)))
8262 gtk_widget_queue_resize (widget);
8263 else if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_CLIP))
8264 gtk_widget_queue_allocate (widget);
8265 else if (gtk_css_style_change_affects (change, GTK_CSS_AFFECTS_REDRAW))
8266 gtk_widget_queue_draw (widget);
8267 }
8268 }
8269 else
8270 {
8271 gtk_widget_update_pango_context (widget);
8272
8273 if (widget->priv->anchored)
8274 gtk_widget_queue_resize (widget);
8275 }
8276
8277 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
8278 if (priv->style != NULL &&
8279 priv->style != gtk_widget_get_default_style ())
8280 {
8281 /* Trigger ::style-set for old
8282 * widgets not listening to this
8283 */
8284 g_signal_emit (widget,
8285 widget_signals[STYLE_SET],
8286 0,
8287 widget->priv->style);
8288 }
8289 G_GNUC_END_IGNORE_DEPRECATIONS;
8290
8291 }
8292
8293 static gboolean
gtk_widget_real_show_help(GtkWidget * widget,GtkWidgetHelpType help_type)8294 gtk_widget_real_show_help (GtkWidget *widget,
8295 GtkWidgetHelpType help_type)
8296 {
8297 if (help_type == GTK_WIDGET_HELP_TOOLTIP)
8298 {
8299 _gtk_tooltip_toggle_keyboard_mode (widget);
8300
8301 return TRUE;
8302 }
8303 else
8304 return FALSE;
8305 }
8306
8307 static gboolean
gtk_widget_real_focus(GtkWidget * widget,GtkDirectionType direction)8308 gtk_widget_real_focus (GtkWidget *widget,
8309 GtkDirectionType direction)
8310 {
8311 if (!gtk_widget_get_can_focus (widget))
8312 return FALSE;
8313
8314 if (!gtk_widget_is_focus (widget))
8315 {
8316 gtk_widget_grab_focus (widget);
8317 return TRUE;
8318 }
8319 else
8320 return FALSE;
8321 }
8322
8323 static void
gtk_widget_real_move_focus(GtkWidget * widget,GtkDirectionType direction)8324 gtk_widget_real_move_focus (GtkWidget *widget,
8325 GtkDirectionType direction)
8326 {
8327 GtkWidget *toplevel = _gtk_widget_get_toplevel (widget);
8328
8329 if (widget != toplevel && GTK_IS_WINDOW (toplevel))
8330 {
8331 g_signal_emit (toplevel, widget_signals[MOVE_FOCUS], 0,
8332 direction);
8333 }
8334 }
8335
8336 static gboolean
gtk_widget_real_keynav_failed(GtkWidget * widget,GtkDirectionType direction)8337 gtk_widget_real_keynav_failed (GtkWidget *widget,
8338 GtkDirectionType direction)
8339 {
8340 switch (direction)
8341 {
8342 case GTK_DIR_TAB_FORWARD:
8343 case GTK_DIR_TAB_BACKWARD:
8344 return FALSE;
8345
8346 case GTK_DIR_UP:
8347 case GTK_DIR_DOWN:
8348 case GTK_DIR_LEFT:
8349 case GTK_DIR_RIGHT:
8350 break;
8351 }
8352
8353 gtk_widget_error_bell (widget);
8354
8355 return TRUE;
8356 }
8357
8358 /**
8359 * gtk_widget_set_can_focus:
8360 * @widget: a #GtkWidget
8361 * @can_focus: whether or not @widget can own the input focus.
8362 *
8363 * Specifies whether @widget can own the input focus. See
8364 * gtk_widget_grab_focus() for actually setting the input focus on a
8365 * widget.
8366 *
8367 * Since: 2.18
8368 **/
8369 void
gtk_widget_set_can_focus(GtkWidget * widget,gboolean can_focus)8370 gtk_widget_set_can_focus (GtkWidget *widget,
8371 gboolean can_focus)
8372 {
8373 g_return_if_fail (GTK_IS_WIDGET (widget));
8374
8375 if (widget->priv->can_focus != can_focus)
8376 {
8377 widget->priv->can_focus = can_focus;
8378
8379 gtk_widget_queue_resize (widget);
8380 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_CAN_FOCUS]);
8381 }
8382 }
8383
8384 /**
8385 * gtk_widget_get_can_focus:
8386 * @widget: a #GtkWidget
8387 *
8388 * Determines whether @widget can own the input focus. See
8389 * gtk_widget_set_can_focus().
8390 *
8391 * Returns: %TRUE if @widget can own the input focus, %FALSE otherwise
8392 *
8393 * Since: 2.18
8394 **/
8395 gboolean
gtk_widget_get_can_focus(GtkWidget * widget)8396 gtk_widget_get_can_focus (GtkWidget *widget)
8397 {
8398 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8399
8400 return widget->priv->can_focus;
8401 }
8402
8403 /**
8404 * gtk_widget_has_focus:
8405 * @widget: a #GtkWidget
8406 *
8407 * Determines if the widget has the global input focus. See
8408 * gtk_widget_is_focus() for the difference between having the global
8409 * input focus, and only having the focus within a toplevel.
8410 *
8411 * Returns: %TRUE if the widget has the global input focus.
8412 *
8413 * Since: 2.18
8414 **/
8415 gboolean
gtk_widget_has_focus(GtkWidget * widget)8416 gtk_widget_has_focus (GtkWidget *widget)
8417 {
8418 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8419
8420 return widget->priv->has_focus;
8421 }
8422
8423 /**
8424 * gtk_widget_has_visible_focus:
8425 * @widget: a #GtkWidget
8426 *
8427 * Determines if the widget should show a visible indication that
8428 * it has the global input focus. This is a convenience function for
8429 * use in ::draw handlers that takes into account whether focus
8430 * indication should currently be shown in the toplevel window of
8431 * @widget. See gtk_window_get_focus_visible() for more information
8432 * about focus indication.
8433 *
8434 * To find out if the widget has the global input focus, use
8435 * gtk_widget_has_focus().
8436 *
8437 * Returns: %TRUE if the widget should display a “focus rectangle”
8438 *
8439 * Since: 3.2
8440 */
8441 gboolean
gtk_widget_has_visible_focus(GtkWidget * widget)8442 gtk_widget_has_visible_focus (GtkWidget *widget)
8443 {
8444 gboolean draw_focus;
8445
8446 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8447
8448 if (widget->priv->has_focus)
8449 {
8450 GtkWidget *toplevel;
8451
8452 toplevel = _gtk_widget_get_toplevel (widget);
8453
8454 if (GTK_IS_WINDOW (toplevel))
8455 draw_focus = gtk_window_get_focus_visible (GTK_WINDOW (toplevel));
8456 else
8457 draw_focus = TRUE;
8458 }
8459 else
8460 draw_focus = FALSE;
8461
8462 return draw_focus;
8463 }
8464
8465 /**
8466 * gtk_widget_is_focus:
8467 * @widget: a #GtkWidget
8468 *
8469 * Determines if the widget is the focus widget within its
8470 * toplevel. (This does not mean that the #GtkWidget:has-focus property is
8471 * necessarily set; #GtkWidget:has-focus will only be set if the
8472 * toplevel widget additionally has the global input focus.)
8473 *
8474 * Returns: %TRUE if the widget is the focus widget.
8475 **/
8476 gboolean
gtk_widget_is_focus(GtkWidget * widget)8477 gtk_widget_is_focus (GtkWidget *widget)
8478 {
8479 GtkWidget *toplevel;
8480
8481 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8482
8483 toplevel = _gtk_widget_get_toplevel (widget);
8484
8485 if (GTK_IS_WINDOW (toplevel))
8486 return widget == gtk_window_get_focus (GTK_WINDOW (toplevel));
8487 else
8488 return FALSE;
8489 }
8490
8491 /**
8492 * gtk_widget_set_focus_on_click:
8493 * @widget: a #GtkWidget
8494 * @focus_on_click: whether the widget should grab focus when clicked with the mouse
8495 *
8496 * Sets whether the widget should grab focus when it is clicked with the mouse.
8497 * Making mouse clicks not grab focus is useful in places like toolbars where
8498 * you don’t want the keyboard focus removed from the main area of the
8499 * application.
8500 *
8501 * Since: 3.20
8502 **/
8503 void
gtk_widget_set_focus_on_click(GtkWidget * widget,gboolean focus_on_click)8504 gtk_widget_set_focus_on_click (GtkWidget *widget,
8505 gboolean focus_on_click)
8506 {
8507 GtkWidgetPrivate *priv;
8508
8509 g_return_if_fail (GTK_IS_WIDGET (widget));
8510
8511 priv = widget->priv;
8512
8513 focus_on_click = focus_on_click != FALSE;
8514
8515 if (priv->focus_on_click != focus_on_click)
8516 {
8517 priv->focus_on_click = focus_on_click;
8518
8519 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_FOCUS_ON_CLICK]);
8520 }
8521 }
8522
8523 /**
8524 * gtk_widget_get_focus_on_click:
8525 * @widget: a #GtkWidget
8526 *
8527 * Returns whether the widget should grab focus when it is clicked with the mouse.
8528 * See gtk_widget_set_focus_on_click().
8529 *
8530 * Returns: %TRUE if the widget should grab focus when it is clicked with
8531 * the mouse.
8532 *
8533 * Since: 3.20
8534 **/
8535 gboolean
gtk_widget_get_focus_on_click(GtkWidget * widget)8536 gtk_widget_get_focus_on_click (GtkWidget *widget)
8537 {
8538 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8539
8540 return widget->priv->focus_on_click;
8541 }
8542
8543
8544 /**
8545 * gtk_widget_set_can_default:
8546 * @widget: a #GtkWidget
8547 * @can_default: whether or not @widget can be a default widget.
8548 *
8549 * Specifies whether @widget can be a default widget. See
8550 * gtk_widget_grab_default() for details about the meaning of
8551 * “default”.
8552 *
8553 * Since: 2.18
8554 **/
8555 void
gtk_widget_set_can_default(GtkWidget * widget,gboolean can_default)8556 gtk_widget_set_can_default (GtkWidget *widget,
8557 gboolean can_default)
8558 {
8559 g_return_if_fail (GTK_IS_WIDGET (widget));
8560
8561 if (widget->priv->can_default != can_default)
8562 {
8563 widget->priv->can_default = can_default;
8564
8565 gtk_widget_queue_resize (widget);
8566 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_CAN_DEFAULT]);
8567 }
8568 }
8569
8570 /**
8571 * gtk_widget_get_can_default:
8572 * @widget: a #GtkWidget
8573 *
8574 * Determines whether @widget can be a default widget. See
8575 * gtk_widget_set_can_default().
8576 *
8577 * Returns: %TRUE if @widget can be a default widget, %FALSE otherwise
8578 *
8579 * Since: 2.18
8580 **/
8581 gboolean
gtk_widget_get_can_default(GtkWidget * widget)8582 gtk_widget_get_can_default (GtkWidget *widget)
8583 {
8584 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8585
8586 return widget->priv->can_default;
8587 }
8588
8589 /**
8590 * gtk_widget_has_default:
8591 * @widget: a #GtkWidget
8592 *
8593 * Determines whether @widget is the current default widget within its
8594 * toplevel. See gtk_widget_set_can_default().
8595 *
8596 * Returns: %TRUE if @widget is the current default widget within
8597 * its toplevel, %FALSE otherwise
8598 *
8599 * Since: 2.18
8600 */
8601 gboolean
gtk_widget_has_default(GtkWidget * widget)8602 gtk_widget_has_default (GtkWidget *widget)
8603 {
8604 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8605
8606 return widget->priv->has_default;
8607 }
8608
8609 void
_gtk_widget_set_has_default(GtkWidget * widget,gboolean has_default)8610 _gtk_widget_set_has_default (GtkWidget *widget,
8611 gboolean has_default)
8612 {
8613 GtkStyleContext *context;
8614
8615 widget->priv->has_default = has_default;
8616
8617 context = _gtk_widget_get_style_context (widget);
8618
8619 if (has_default)
8620 gtk_style_context_add_class (context, GTK_STYLE_CLASS_DEFAULT);
8621 else
8622 gtk_style_context_remove_class (context, GTK_STYLE_CLASS_DEFAULT);
8623 }
8624
8625 /**
8626 * gtk_widget_grab_default:
8627 * @widget: a #GtkWidget
8628 *
8629 * Causes @widget to become the default widget. @widget must be able to be
8630 * a default widget; typically you would ensure this yourself
8631 * by calling gtk_widget_set_can_default() with a %TRUE value.
8632 * The default widget is activated when
8633 * the user presses Enter in a window. Default widgets must be
8634 * activatable, that is, gtk_widget_activate() should affect them. Note
8635 * that #GtkEntry widgets require the “activates-default” property
8636 * set to %TRUE before they activate the default widget when Enter
8637 * is pressed and the #GtkEntry is focused.
8638 **/
8639 void
gtk_widget_grab_default(GtkWidget * widget)8640 gtk_widget_grab_default (GtkWidget *widget)
8641 {
8642 GtkWidget *window;
8643
8644 g_return_if_fail (GTK_IS_WIDGET (widget));
8645 g_return_if_fail (gtk_widget_get_can_default (widget));
8646
8647 window = _gtk_widget_get_toplevel (widget);
8648
8649 if (window && _gtk_widget_is_toplevel (window))
8650 gtk_window_set_default (GTK_WINDOW (window), widget);
8651 else
8652 g_warning (G_STRLOC ": widget not within a GtkWindow");
8653 }
8654
8655 /**
8656 * gtk_widget_set_receives_default:
8657 * @widget: a #GtkWidget
8658 * @receives_default: whether or not @widget can be a default widget.
8659 *
8660 * Specifies whether @widget will be treated as the default widget
8661 * within its toplevel when it has the focus, even if another widget
8662 * is the default.
8663 *
8664 * See gtk_widget_grab_default() for details about the meaning of
8665 * “default”.
8666 *
8667 * Since: 2.18
8668 **/
8669 void
gtk_widget_set_receives_default(GtkWidget * widget,gboolean receives_default)8670 gtk_widget_set_receives_default (GtkWidget *widget,
8671 gboolean receives_default)
8672 {
8673 g_return_if_fail (GTK_IS_WIDGET (widget));
8674
8675 if (widget->priv->receives_default != receives_default)
8676 {
8677 widget->priv->receives_default = receives_default;
8678
8679 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_RECEIVES_DEFAULT]);
8680 }
8681 }
8682
8683 /**
8684 * gtk_widget_get_receives_default:
8685 * @widget: a #GtkWidget
8686 *
8687 * Determines whether @widget is always treated as the default widget
8688 * within its toplevel when it has the focus, even if another widget
8689 * is the default.
8690 *
8691 * See gtk_widget_set_receives_default().
8692 *
8693 * Returns: %TRUE if @widget acts as the default widget when focused,
8694 * %FALSE otherwise
8695 *
8696 * Since: 2.18
8697 **/
8698 gboolean
gtk_widget_get_receives_default(GtkWidget * widget)8699 gtk_widget_get_receives_default (GtkWidget *widget)
8700 {
8701 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8702
8703 return widget->priv->receives_default;
8704 }
8705
8706 /**
8707 * gtk_widget_has_grab:
8708 * @widget: a #GtkWidget
8709 *
8710 * Determines whether the widget is currently grabbing events, so it
8711 * is the only widget receiving input events (keyboard and mouse).
8712 *
8713 * See also gtk_grab_add().
8714 *
8715 * Returns: %TRUE if the widget is in the grab_widgets stack
8716 *
8717 * Since: 2.18
8718 **/
8719 gboolean
gtk_widget_has_grab(GtkWidget * widget)8720 gtk_widget_has_grab (GtkWidget *widget)
8721 {
8722 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8723
8724 return widget->priv->has_grab;
8725 }
8726
8727 void
_gtk_widget_set_has_grab(GtkWidget * widget,gboolean has_grab)8728 _gtk_widget_set_has_grab (GtkWidget *widget,
8729 gboolean has_grab)
8730 {
8731 widget->priv->has_grab = has_grab;
8732 }
8733
8734 /**
8735 * gtk_widget_device_is_shadowed:
8736 * @widget: a #GtkWidget
8737 * @device: a #GdkDevice
8738 *
8739 * Returns %TRUE if @device has been shadowed by a GTK+
8740 * device grab on another widget, so it would stop sending
8741 * events to @widget. This may be used in the
8742 * #GtkWidget::grab-notify signal to check for specific
8743 * devices. See gtk_device_grab_add().
8744 *
8745 * Returns: %TRUE if there is an ongoing grab on @device
8746 * by another #GtkWidget than @widget.
8747 *
8748 * Since: 3.0
8749 **/
8750 gboolean
gtk_widget_device_is_shadowed(GtkWidget * widget,GdkDevice * device)8751 gtk_widget_device_is_shadowed (GtkWidget *widget,
8752 GdkDevice *device)
8753 {
8754 GtkWindowGroup *group;
8755 GtkWidget *grab_widget, *toplevel;
8756
8757 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
8758 g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
8759
8760 if (!_gtk_widget_get_realized (widget))
8761 return TRUE;
8762
8763 toplevel = _gtk_widget_get_toplevel (widget);
8764
8765 if (GTK_IS_WINDOW (toplevel))
8766 group = gtk_window_get_group (GTK_WINDOW (toplevel));
8767 else
8768 group = gtk_window_get_group (NULL);
8769
8770 grab_widget = gtk_window_group_get_current_device_grab (group, device);
8771
8772 /* Widget not inside the hierarchy of grab_widget */
8773 if (grab_widget &&
8774 widget != grab_widget &&
8775 !gtk_widget_is_ancestor (widget, grab_widget))
8776 return TRUE;
8777
8778 grab_widget = gtk_window_group_get_current_grab (group);
8779 if (grab_widget && widget != grab_widget &&
8780 !gtk_widget_is_ancestor (widget, grab_widget))
8781 return TRUE;
8782
8783 return FALSE;
8784 }
8785
8786 /**
8787 * gtk_widget_set_name:
8788 * @widget: a #GtkWidget
8789 * @name: name for the widget
8790 *
8791 * Widgets can be named, which allows you to refer to them from a
8792 * CSS file. You can apply a style to widgets with a particular name
8793 * in the CSS file. See the documentation for the CSS syntax (on the
8794 * same page as the docs for #GtkStyleContext).
8795 *
8796 * Note that the CSS syntax has certain special characters to delimit
8797 * and represent elements in a selector (period, #, >, *...), so using
8798 * these will make your widget impossible to match by name. Any combination
8799 * of alphanumeric symbols, dashes and underscores will suffice.
8800 */
8801 void
gtk_widget_set_name(GtkWidget * widget,const gchar * name)8802 gtk_widget_set_name (GtkWidget *widget,
8803 const gchar *name)
8804 {
8805 GtkWidgetPrivate *priv;
8806 gchar *new_name;
8807
8808 g_return_if_fail (GTK_IS_WIDGET (widget));
8809
8810 priv = widget->priv;
8811
8812 new_name = g_strdup (name);
8813 g_free (priv->name);
8814 priv->name = new_name;
8815
8816 if (priv->context)
8817 gtk_style_context_set_id (priv->context, priv->name);
8818
8819 gtk_css_node_set_id (priv->cssnode, priv->name);
8820
8821 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_NAME]);
8822 }
8823
8824 /**
8825 * gtk_widget_get_name:
8826 * @widget: a #GtkWidget
8827 *
8828 * Retrieves the name of a widget. See gtk_widget_set_name() for the
8829 * significance of widget names.
8830 *
8831 * Returns: name of the widget. This string is owned by GTK+ and
8832 * should not be modified or freed
8833 **/
8834 const gchar*
gtk_widget_get_name(GtkWidget * widget)8835 gtk_widget_get_name (GtkWidget *widget)
8836 {
8837 GtkWidgetPrivate *priv;
8838
8839 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
8840
8841 priv = widget->priv;
8842
8843 if (priv->name)
8844 return priv->name;
8845 return G_OBJECT_TYPE_NAME (widget);
8846 }
8847
8848 static void
gtk_widget_update_state_flags(GtkWidget * widget,GtkStateFlags flags_to_set,GtkStateFlags flags_to_unset)8849 gtk_widget_update_state_flags (GtkWidget *widget,
8850 GtkStateFlags flags_to_set,
8851 GtkStateFlags flags_to_unset)
8852 {
8853 GtkWidgetPrivate *priv;
8854
8855 priv = widget->priv;
8856
8857 /* Handle insensitive first, since it is propagated
8858 * differently throughout the widget hierarchy.
8859 */
8860 if ((priv->state_flags & GTK_STATE_FLAG_INSENSITIVE) && (flags_to_unset & GTK_STATE_FLAG_INSENSITIVE))
8861 gtk_widget_set_sensitive (widget, TRUE);
8862 else if (!(priv->state_flags & GTK_STATE_FLAG_INSENSITIVE) && (flags_to_set & GTK_STATE_FLAG_INSENSITIVE))
8863 gtk_widget_set_sensitive (widget, FALSE);
8864
8865 flags_to_set &= ~(GTK_STATE_FLAG_INSENSITIVE);
8866 flags_to_unset &= ~(GTK_STATE_FLAG_INSENSITIVE);
8867
8868 if (flags_to_set != 0 || flags_to_unset != 0)
8869 {
8870 GtkStateData data;
8871
8872 data.old_scale_factor = gtk_widget_get_scale_factor (widget);
8873 data.flags_to_set = flags_to_set;
8874 data.flags_to_unset = flags_to_unset;
8875
8876 gtk_widget_propagate_state (widget, &data);
8877 }
8878 }
8879
8880 /**
8881 * gtk_widget_set_state_flags:
8882 * @widget: a #GtkWidget
8883 * @flags: State flags to turn on
8884 * @clear: Whether to clear state before turning on @flags
8885 *
8886 * This function is for use in widget implementations. Turns on flag
8887 * values in the current widget state (insensitive, prelighted, etc.).
8888 *
8889 * This function accepts the values %GTK_STATE_FLAG_DIR_LTR and
8890 * %GTK_STATE_FLAG_DIR_RTL but ignores them. If you want to set the widget's
8891 * direction, use gtk_widget_set_direction().
8892 *
8893 * It is worth mentioning that any other state than %GTK_STATE_FLAG_INSENSITIVE,
8894 * will be propagated down to all non-internal children if @widget is a
8895 * #GtkContainer, while %GTK_STATE_FLAG_INSENSITIVE itself will be propagated
8896 * down to all #GtkContainer children by different means than turning on the
8897 * state flag down the hierarchy, both gtk_widget_get_state_flags() and
8898 * gtk_widget_is_sensitive() will make use of these.
8899 *
8900 * Since: 3.0
8901 **/
8902 void
gtk_widget_set_state_flags(GtkWidget * widget,GtkStateFlags flags,gboolean clear)8903 gtk_widget_set_state_flags (GtkWidget *widget,
8904 GtkStateFlags flags,
8905 gboolean clear)
8906 {
8907 #define ALLOWED_FLAGS (~(GTK_STATE_FLAG_DIR_LTR | GTK_STATE_FLAG_DIR_RTL))
8908
8909 g_return_if_fail (GTK_IS_WIDGET (widget));
8910 g_return_if_fail (flags < (1 << GTK_STATE_FLAGS_BITS));
8911
8912 if ((!clear && (widget->priv->state_flags & flags) == flags) ||
8913 (clear && widget->priv->state_flags == flags))
8914 return;
8915
8916 if (clear)
8917 gtk_widget_update_state_flags (widget, flags & ALLOWED_FLAGS, ~flags & ALLOWED_FLAGS);
8918 else
8919 gtk_widget_update_state_flags (widget, flags & ALLOWED_FLAGS, 0);
8920
8921 #undef ALLOWED_FLAGS
8922 }
8923
8924 /**
8925 * gtk_widget_unset_state_flags:
8926 * @widget: a #GtkWidget
8927 * @flags: State flags to turn off
8928 *
8929 * This function is for use in widget implementations. Turns off flag
8930 * values for the current widget state (insensitive, prelighted, etc.).
8931 * See gtk_widget_set_state_flags().
8932 *
8933 * Since: 3.0
8934 **/
8935 void
gtk_widget_unset_state_flags(GtkWidget * widget,GtkStateFlags flags)8936 gtk_widget_unset_state_flags (GtkWidget *widget,
8937 GtkStateFlags flags)
8938 {
8939 g_return_if_fail (GTK_IS_WIDGET (widget));
8940 g_return_if_fail (flags < (1 << GTK_STATE_FLAGS_BITS));
8941
8942 if ((widget->priv->state_flags & flags) == 0)
8943 return;
8944
8945 gtk_widget_update_state_flags (widget, 0, flags);
8946 }
8947
8948 /**
8949 * gtk_widget_get_state_flags:
8950 * @widget: a #GtkWidget
8951 *
8952 * Returns the widget state as a flag set. It is worth mentioning
8953 * that the effective %GTK_STATE_FLAG_INSENSITIVE state will be
8954 * returned, that is, also based on parent insensitivity, even if
8955 * @widget itself is sensitive.
8956 *
8957 * Also note that if you are looking for a way to obtain the
8958 * #GtkStateFlags to pass to a #GtkStyleContext method, you
8959 * should look at gtk_style_context_get_state().
8960 *
8961 * Returns: The state flags for widget
8962 *
8963 * Since: 3.0
8964 **/
8965 GtkStateFlags
gtk_widget_get_state_flags(GtkWidget * widget)8966 gtk_widget_get_state_flags (GtkWidget *widget)
8967 {
8968 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
8969
8970 return widget->priv->state_flags;
8971 }
8972
8973 /**
8974 * gtk_widget_set_state:
8975 * @widget: a #GtkWidget
8976 * @state: new state for @widget
8977 *
8978 * This function is for use in widget implementations. Sets the state
8979 * of a widget (insensitive, prelighted, etc.) Usually you should set
8980 * the state using wrapper functions such as gtk_widget_set_sensitive().
8981 *
8982 * Deprecated: 3.0: Use gtk_widget_set_state_flags() instead.
8983 **/
8984 void
gtk_widget_set_state(GtkWidget * widget,GtkStateType state)8985 gtk_widget_set_state (GtkWidget *widget,
8986 GtkStateType state)
8987 {
8988 GtkStateFlags flags;
8989
8990 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
8991 if (state == gtk_widget_get_state (widget))
8992 return;
8993 G_GNUC_END_IGNORE_DEPRECATIONS;
8994
8995 switch (state)
8996 {
8997 case GTK_STATE_ACTIVE:
8998 flags = GTK_STATE_FLAG_ACTIVE;
8999 break;
9000 case GTK_STATE_PRELIGHT:
9001 flags = GTK_STATE_FLAG_PRELIGHT;
9002 break;
9003 case GTK_STATE_SELECTED:
9004 flags = GTK_STATE_FLAG_SELECTED;
9005 break;
9006 case GTK_STATE_INSENSITIVE:
9007 flags = GTK_STATE_FLAG_INSENSITIVE;
9008 break;
9009 case GTK_STATE_INCONSISTENT:
9010 flags = GTK_STATE_FLAG_INCONSISTENT;
9011 break;
9012 case GTK_STATE_FOCUSED:
9013 flags = GTK_STATE_FLAG_FOCUSED;
9014 break;
9015 case GTK_STATE_NORMAL:
9016 default:
9017 flags = 0;
9018 break;
9019 }
9020
9021 gtk_widget_update_state_flags (widget,
9022 flags,
9023 (GTK_STATE_FLAG_ACTIVE | GTK_STATE_FLAG_PRELIGHT | GTK_STATE_FLAG_SELECTED
9024 | GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_INCONSISTENT | GTK_STATE_FLAG_FOCUSED) ^ flags);
9025 }
9026
9027 /**
9028 * gtk_widget_get_state:
9029 * @widget: a #GtkWidget
9030 *
9031 * Returns the widget’s state. See gtk_widget_set_state().
9032 *
9033 * Returns: the state of @widget.
9034 *
9035 * Since: 2.18
9036 *
9037 * Deprecated: 3.0: Use gtk_widget_get_state_flags() instead.
9038 */
9039 GtkStateType
gtk_widget_get_state(GtkWidget * widget)9040 gtk_widget_get_state (GtkWidget *widget)
9041 {
9042 GtkStateFlags flags;
9043
9044 g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_STATE_NORMAL);
9045
9046 flags = _gtk_widget_get_state_flags (widget);
9047
9048 if (flags & GTK_STATE_FLAG_INSENSITIVE)
9049 return GTK_STATE_INSENSITIVE;
9050 else if (flags & GTK_STATE_FLAG_ACTIVE)
9051 return GTK_STATE_ACTIVE;
9052 else if (flags & GTK_STATE_FLAG_SELECTED)
9053 return GTK_STATE_SELECTED;
9054 else if (flags & GTK_STATE_FLAG_PRELIGHT)
9055 return GTK_STATE_PRELIGHT;
9056 else
9057 return GTK_STATE_NORMAL;
9058 }
9059
9060 /**
9061 * gtk_widget_set_visible:
9062 * @widget: a #GtkWidget
9063 * @visible: whether the widget should be shown or not
9064 *
9065 * Sets the visibility state of @widget. Note that setting this to
9066 * %TRUE doesn’t mean the widget is actually viewable, see
9067 * gtk_widget_get_visible().
9068 *
9069 * This function simply calls gtk_widget_show() or gtk_widget_hide()
9070 * but is nicer to use when the visibility of the widget depends on
9071 * some condition.
9072 *
9073 * Since: 2.18
9074 **/
9075 void
gtk_widget_set_visible(GtkWidget * widget,gboolean visible)9076 gtk_widget_set_visible (GtkWidget *widget,
9077 gboolean visible)
9078 {
9079 g_return_if_fail (GTK_IS_WIDGET (widget));
9080
9081 if (visible)
9082 gtk_widget_show (widget);
9083 else
9084 gtk_widget_hide (widget);
9085 }
9086
9087 void
_gtk_widget_set_visible_flag(GtkWidget * widget,gboolean visible)9088 _gtk_widget_set_visible_flag (GtkWidget *widget,
9089 gboolean visible)
9090 {
9091 GtkWidgetPrivate *priv = widget->priv;
9092
9093 priv->visible = visible;
9094
9095 if (!visible)
9096 {
9097 priv->allocation.x = -1;
9098 priv->allocation.y = -1;
9099 priv->allocation.width = 1;
9100 priv->allocation.height = 1;
9101 memset (&priv->clip, 0, sizeof (priv->clip));
9102 memset (&priv->allocated_size, 0, sizeof (priv->allocated_size));
9103 priv->allocated_size_baseline = 0;
9104 }
9105 }
9106
9107 /**
9108 * gtk_widget_get_visible:
9109 * @widget: a #GtkWidget
9110 *
9111 * Determines whether the widget is visible. If you want to
9112 * take into account whether the widget’s parent is also marked as
9113 * visible, use gtk_widget_is_visible() instead.
9114 *
9115 * This function does not check if the widget is obscured in any way.
9116 *
9117 * See gtk_widget_set_visible().
9118 *
9119 * Returns: %TRUE if the widget is visible
9120 *
9121 * Since: 2.18
9122 **/
9123 gboolean
gtk_widget_get_visible(GtkWidget * widget)9124 gtk_widget_get_visible (GtkWidget *widget)
9125 {
9126 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9127
9128 return widget->priv->visible;
9129 }
9130
9131 /**
9132 * gtk_widget_is_visible:
9133 * @widget: a #GtkWidget
9134 *
9135 * Determines whether the widget and all its parents are marked as
9136 * visible.
9137 *
9138 * This function does not check if the widget is obscured in any way.
9139 *
9140 * See also gtk_widget_get_visible() and gtk_widget_set_visible()
9141 *
9142 * Returns: %TRUE if the widget and all its parents are visible
9143 *
9144 * Since: 3.8
9145 **/
9146 gboolean
gtk_widget_is_visible(GtkWidget * widget)9147 gtk_widget_is_visible (GtkWidget *widget)
9148 {
9149 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9150
9151 while (widget)
9152 {
9153 GtkWidgetPrivate *priv = widget->priv;
9154
9155 if (!priv->visible)
9156 return FALSE;
9157
9158 widget = priv->parent;
9159 }
9160
9161 return TRUE;
9162 }
9163
9164 /**
9165 * gtk_widget_set_has_window:
9166 * @widget: a #GtkWidget
9167 * @has_window: whether or not @widget has a window.
9168 *
9169 * Specifies whether @widget has a #GdkWindow of its own. Note that
9170 * all realized widgets have a non-%NULL “window” pointer
9171 * (gtk_widget_get_window() never returns a %NULL window when a widget
9172 * is realized), but for many of them it’s actually the #GdkWindow of
9173 * one of its parent widgets. Widgets that do not create a %window for
9174 * themselves in #GtkWidget::realize must announce this by
9175 * calling this function with @has_window = %FALSE.
9176 *
9177 * This function should only be called by widget implementations,
9178 * and they should call it in their init() function.
9179 *
9180 * Since: 2.18
9181 **/
9182 void
gtk_widget_set_has_window(GtkWidget * widget,gboolean has_window)9183 gtk_widget_set_has_window (GtkWidget *widget,
9184 gboolean has_window)
9185 {
9186 g_return_if_fail (GTK_IS_WIDGET (widget));
9187
9188 widget->priv->no_window = !has_window;
9189 }
9190
9191 /**
9192 * gtk_widget_get_has_window:
9193 * @widget: a #GtkWidget
9194 *
9195 * Determines whether @widget has a #GdkWindow of its own. See
9196 * gtk_widget_set_has_window().
9197 *
9198 * Returns: %TRUE if @widget has a window, %FALSE otherwise
9199 *
9200 * Since: 2.18
9201 **/
9202 gboolean
gtk_widget_get_has_window(GtkWidget * widget)9203 gtk_widget_get_has_window (GtkWidget *widget)
9204 {
9205 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9206
9207 return ! widget->priv->no_window;
9208 }
9209
9210 /**
9211 * gtk_widget_is_toplevel:
9212 * @widget: a #GtkWidget
9213 *
9214 * Determines whether @widget is a toplevel widget.
9215 *
9216 * Currently only #GtkWindow and #GtkInvisible (and out-of-process
9217 * #GtkPlugs) are toplevel widgets. Toplevel widgets have no parent
9218 * widget.
9219 *
9220 * Returns: %TRUE if @widget is a toplevel, %FALSE otherwise
9221 *
9222 * Since: 2.18
9223 **/
9224 gboolean
gtk_widget_is_toplevel(GtkWidget * widget)9225 gtk_widget_is_toplevel (GtkWidget *widget)
9226 {
9227 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9228
9229 return widget->priv->toplevel;
9230 }
9231
9232 void
_gtk_widget_set_is_toplevel(GtkWidget * widget,gboolean is_toplevel)9233 _gtk_widget_set_is_toplevel (GtkWidget *widget,
9234 gboolean is_toplevel)
9235 {
9236 widget->priv->toplevel = is_toplevel;
9237 }
9238
9239 /**
9240 * gtk_widget_is_drawable:
9241 * @widget: a #GtkWidget
9242 *
9243 * Determines whether @widget can be drawn to. A widget can be drawn
9244 * to if it is mapped and visible.
9245 *
9246 * Returns: %TRUE if @widget is drawable, %FALSE otherwise
9247 *
9248 * Since: 2.18
9249 **/
9250 gboolean
gtk_widget_is_drawable(GtkWidget * widget)9251 gtk_widget_is_drawable (GtkWidget *widget)
9252 {
9253 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9254
9255 return (_gtk_widget_get_visible (widget) &&
9256 _gtk_widget_get_mapped (widget));
9257 }
9258
9259 /**
9260 * gtk_widget_get_realized:
9261 * @widget: a #GtkWidget
9262 *
9263 * Determines whether @widget is realized.
9264 *
9265 * Returns: %TRUE if @widget is realized, %FALSE otherwise
9266 *
9267 * Since: 2.20
9268 **/
9269 gboolean
gtk_widget_get_realized(GtkWidget * widget)9270 gtk_widget_get_realized (GtkWidget *widget)
9271 {
9272 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9273
9274 return widget->priv->realized;
9275 }
9276
9277 /**
9278 * gtk_widget_set_realized:
9279 * @widget: a #GtkWidget
9280 * @realized: %TRUE to mark the widget as realized
9281 *
9282 * Marks the widget as being realized. This function must only be
9283 * called after all #GdkWindows for the @widget have been created
9284 * and registered.
9285 *
9286 * This function should only ever be called in a derived widget's
9287 * “realize” or “unrealize” implementation.
9288 *
9289 * Since: 2.20
9290 */
9291 void
gtk_widget_set_realized(GtkWidget * widget,gboolean realized)9292 gtk_widget_set_realized (GtkWidget *widget,
9293 gboolean realized)
9294 {
9295 g_return_if_fail (GTK_IS_WIDGET (widget));
9296
9297 widget->priv->realized = realized;
9298 }
9299
9300 /**
9301 * gtk_widget_get_mapped:
9302 * @widget: a #GtkWidget
9303 *
9304 * Whether the widget is mapped.
9305 *
9306 * Returns: %TRUE if the widget is mapped, %FALSE otherwise.
9307 *
9308 * Since: 2.20
9309 */
9310 gboolean
gtk_widget_get_mapped(GtkWidget * widget)9311 gtk_widget_get_mapped (GtkWidget *widget)
9312 {
9313 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9314
9315 return widget->priv->mapped;
9316 }
9317
9318 /**
9319 * gtk_widget_set_mapped:
9320 * @widget: a #GtkWidget
9321 * @mapped: %TRUE to mark the widget as mapped
9322 *
9323 * Marks the widget as being mapped.
9324 *
9325 * This function should only ever be called in a derived widget's
9326 * “map” or “unmap” implementation.
9327 *
9328 * Since: 2.20
9329 */
9330 void
gtk_widget_set_mapped(GtkWidget * widget,gboolean mapped)9331 gtk_widget_set_mapped (GtkWidget *widget,
9332 gboolean mapped)
9333 {
9334 g_return_if_fail (GTK_IS_WIDGET (widget));
9335
9336 widget->priv->mapped = mapped;
9337 }
9338
9339 /**
9340 * gtk_widget_set_app_paintable:
9341 * @widget: a #GtkWidget
9342 * @app_paintable: %TRUE if the application will paint on the widget
9343 *
9344 * Sets whether the application intends to draw on the widget in
9345 * an #GtkWidget::draw handler.
9346 *
9347 * This is a hint to the widget and does not affect the behavior of
9348 * the GTK+ core; many widgets ignore this flag entirely. For widgets
9349 * that do pay attention to the flag, such as #GtkEventBox and #GtkWindow,
9350 * the effect is to suppress default themed drawing of the widget's
9351 * background. (Children of the widget will still be drawn.) The application
9352 * is then entirely responsible for drawing the widget background.
9353 *
9354 * Note that the background is still drawn when the widget is mapped.
9355 **/
9356 void
gtk_widget_set_app_paintable(GtkWidget * widget,gboolean app_paintable)9357 gtk_widget_set_app_paintable (GtkWidget *widget,
9358 gboolean app_paintable)
9359 {
9360 g_return_if_fail (GTK_IS_WIDGET (widget));
9361
9362 app_paintable = (app_paintable != FALSE);
9363
9364 if (widget->priv->app_paintable != app_paintable)
9365 {
9366 widget->priv->app_paintable = app_paintable;
9367
9368 if (_gtk_widget_is_drawable (widget))
9369 gtk_widget_queue_draw (widget);
9370
9371 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_APP_PAINTABLE]);
9372 }
9373 }
9374
9375 /**
9376 * gtk_widget_get_app_paintable:
9377 * @widget: a #GtkWidget
9378 *
9379 * Determines whether the application intends to draw on the widget in
9380 * an #GtkWidget::draw handler.
9381 *
9382 * See gtk_widget_set_app_paintable()
9383 *
9384 * Returns: %TRUE if the widget is app paintable
9385 *
9386 * Since: 2.18
9387 **/
9388 gboolean
gtk_widget_get_app_paintable(GtkWidget * widget)9389 gtk_widget_get_app_paintable (GtkWidget *widget)
9390 {
9391 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9392
9393 return widget->priv->app_paintable;
9394 }
9395
9396 /**
9397 * gtk_widget_set_double_buffered:
9398 * @widget: a #GtkWidget
9399 * @double_buffered: %TRUE to double-buffer a widget
9400 *
9401 * Widgets are double buffered by default; you can use this function
9402 * to turn off the buffering. “Double buffered” simply means that
9403 * gdk_window_begin_draw_frame() and gdk_window_end_draw_frame() are called
9404 * automatically around expose events sent to the
9405 * widget. gdk_window_begin_draw_frame() diverts all drawing to a widget's
9406 * window to an offscreen buffer, and gdk_window_end_draw_frame() draws the
9407 * buffer to the screen. The result is that users see the window
9408 * update in one smooth step, and don’t see individual graphics
9409 * primitives being rendered.
9410 *
9411 * In very simple terms, double buffered widgets don’t flicker,
9412 * so you would only use this function to turn off double buffering
9413 * if you had special needs and really knew what you were doing.
9414 *
9415 * Note: if you turn off double-buffering, you have to handle
9416 * expose events, since even the clearing to the background color or
9417 * pixmap will not happen automatically (as it is done in
9418 * gdk_window_begin_draw_frame()).
9419 *
9420 * In 3.10 GTK and GDK have been restructured for translucent drawing. Since
9421 * then expose events for double-buffered widgets are culled into a single
9422 * event to the toplevel GDK window. If you now unset double buffering, you
9423 * will cause a separate rendering pass for every widget. This will likely
9424 * cause rendering problems - in particular related to stacking - and usually
9425 * increases rendering times significantly.
9426 *
9427 * Deprecated: 3.14: This function does not work under non-X11 backends or with
9428 * non-native windows.
9429 * It should not be used in newly written code.
9430 **/
9431 void
gtk_widget_set_double_buffered(GtkWidget * widget,gboolean double_buffered)9432 gtk_widget_set_double_buffered (GtkWidget *widget,
9433 gboolean double_buffered)
9434 {
9435 g_return_if_fail (GTK_IS_WIDGET (widget));
9436
9437 double_buffered = (double_buffered != FALSE);
9438
9439 if (widget->priv->double_buffered != double_buffered)
9440 {
9441 widget->priv->double_buffered = double_buffered;
9442
9443 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_DOUBLE_BUFFERED]);
9444 }
9445 }
9446
9447 /**
9448 * gtk_widget_get_double_buffered:
9449 * @widget: a #GtkWidget
9450 *
9451 * Determines whether the widget is double buffered.
9452 *
9453 * See gtk_widget_set_double_buffered()
9454 *
9455 * Returns: %TRUE if the widget is double buffered
9456 *
9457 * Since: 2.18
9458 **/
9459 gboolean
gtk_widget_get_double_buffered(GtkWidget * widget)9460 gtk_widget_get_double_buffered (GtkWidget *widget)
9461 {
9462 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9463
9464 return widget->priv->double_buffered;
9465 }
9466
9467 /**
9468 * gtk_widget_set_redraw_on_allocate:
9469 * @widget: a #GtkWidget
9470 * @redraw_on_allocate: if %TRUE, the entire widget will be redrawn
9471 * when it is allocated to a new size. Otherwise, only the
9472 * new portion of the widget will be redrawn.
9473 *
9474 * Sets whether the entire widget is queued for drawing when its size
9475 * allocation changes. By default, this setting is %TRUE and
9476 * the entire widget is redrawn on every size change. If your widget
9477 * leaves the upper left unchanged when made bigger, turning this
9478 * setting off will improve performance.
9479
9480 * Note that for widgets where gtk_widget_get_has_window() is %FALSE
9481 * setting this flag to %FALSE turns off all allocation on resizing:
9482 * the widget will not even redraw if its position changes; this is to
9483 * allow containers that don’t draw anything to avoid excess
9484 * invalidations. If you set this flag on a widget with no window that
9485 * does draw on @widget->window, you are
9486 * responsible for invalidating both the old and new allocation of the
9487 * widget when the widget is moved and responsible for invalidating
9488 * regions newly when the widget increases size.
9489 **/
9490 void
gtk_widget_set_redraw_on_allocate(GtkWidget * widget,gboolean redraw_on_allocate)9491 gtk_widget_set_redraw_on_allocate (GtkWidget *widget,
9492 gboolean redraw_on_allocate)
9493 {
9494 g_return_if_fail (GTK_IS_WIDGET (widget));
9495
9496 widget->priv->redraw_on_alloc = redraw_on_allocate;
9497 }
9498
9499 /**
9500 * gtk_widget_set_sensitive:
9501 * @widget: a #GtkWidget
9502 * @sensitive: %TRUE to make the widget sensitive
9503 *
9504 * Sets the sensitivity of a widget. A widget is sensitive if the user
9505 * can interact with it. Insensitive widgets are “grayed out” and the
9506 * user can’t interact with them. Insensitive widgets are known as
9507 * “inactive”, “disabled”, or “ghosted” in some other toolkits.
9508 **/
9509 void
gtk_widget_set_sensitive(GtkWidget * widget,gboolean sensitive)9510 gtk_widget_set_sensitive (GtkWidget *widget,
9511 gboolean sensitive)
9512 {
9513 GtkWidgetPrivate *priv;
9514
9515 g_return_if_fail (GTK_IS_WIDGET (widget));
9516
9517 priv = widget->priv;
9518
9519 sensitive = (sensitive != FALSE);
9520
9521 if (priv->sensitive == sensitive)
9522 return;
9523
9524 priv->sensitive = sensitive;
9525
9526 if (priv->parent == NULL
9527 || gtk_widget_is_sensitive (priv->parent))
9528 {
9529 GtkStateData data;
9530
9531 data.old_scale_factor = gtk_widget_get_scale_factor (widget);
9532
9533 if (sensitive)
9534 {
9535 data.flags_to_set = 0;
9536 data.flags_to_unset = GTK_STATE_FLAG_INSENSITIVE;
9537 }
9538 else
9539 {
9540 data.flags_to_set = GTK_STATE_FLAG_INSENSITIVE;
9541 data.flags_to_unset = 0;
9542 }
9543
9544 gtk_widget_propagate_state (widget, &data);
9545 }
9546
9547 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_SENSITIVE]);
9548 }
9549
9550 /**
9551 * gtk_widget_get_sensitive:
9552 * @widget: a #GtkWidget
9553 *
9554 * Returns the widget’s sensitivity (in the sense of returning
9555 * the value that has been set using gtk_widget_set_sensitive()).
9556 *
9557 * The effective sensitivity of a widget is however determined by both its
9558 * own and its parent widget’s sensitivity. See gtk_widget_is_sensitive().
9559 *
9560 * Returns: %TRUE if the widget is sensitive
9561 *
9562 * Since: 2.18
9563 */
9564 gboolean
gtk_widget_get_sensitive(GtkWidget * widget)9565 gtk_widget_get_sensitive (GtkWidget *widget)
9566 {
9567 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9568
9569 return widget->priv->sensitive;
9570 }
9571
9572 /**
9573 * gtk_widget_is_sensitive:
9574 * @widget: a #GtkWidget
9575 *
9576 * Returns the widget’s effective sensitivity, which means
9577 * it is sensitive itself and also its parent widget is sensitive
9578 *
9579 * Returns: %TRUE if the widget is effectively sensitive
9580 *
9581 * Since: 2.18
9582 */
9583 gboolean
gtk_widget_is_sensitive(GtkWidget * widget)9584 gtk_widget_is_sensitive (GtkWidget *widget)
9585 {
9586 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
9587
9588 return !(widget->priv->state_flags & GTK_STATE_FLAG_INSENSITIVE);
9589 }
9590
9591 /**
9592 * gtk_widget_set_parent:
9593 * @widget: a #GtkWidget
9594 * @parent: parent container
9595 *
9596 * This function is useful only when implementing subclasses of
9597 * #GtkContainer.
9598 * Sets the container as the parent of @widget, and takes care of
9599 * some details such as updating the state and style of the child
9600 * to reflect its new location. The opposite function is
9601 * gtk_widget_unparent().
9602 **/
9603 void
gtk_widget_set_parent(GtkWidget * widget,GtkWidget * parent)9604 gtk_widget_set_parent (GtkWidget *widget,
9605 GtkWidget *parent)
9606 {
9607 GtkStateFlags parent_flags;
9608 GtkWidgetPrivate *priv;
9609 GtkStateData data;
9610
9611 g_return_if_fail (GTK_IS_WIDGET (widget));
9612 g_return_if_fail (GTK_IS_WIDGET (parent));
9613 g_return_if_fail (widget != parent);
9614
9615 priv = widget->priv;
9616
9617 if (priv->parent != NULL)
9618 {
9619 g_warning ("Can't set a parent on widget which has a parent");
9620 return;
9621 }
9622 if (_gtk_widget_is_toplevel (widget))
9623 {
9624 g_warning ("Can't set a parent on a toplevel widget");
9625 return;
9626 }
9627
9628 data.old_scale_factor = gtk_widget_get_scale_factor (widget);
9629
9630 /* keep this function in sync with gtk_menu_attach_to_widget()
9631 */
9632
9633 g_object_ref_sink (widget);
9634
9635 gtk_widget_push_verify_invariants (widget);
9636
9637 priv->parent = parent;
9638
9639 parent_flags = _gtk_widget_get_state_flags (parent);
9640
9641 /* Merge both old state and current parent state,
9642 * making sure to only propagate the right states */
9643 data.flags_to_set = parent_flags & GTK_STATE_FLAGS_DO_PROPAGATE;
9644 data.flags_to_unset = 0;
9645 gtk_widget_propagate_state (widget, &data);
9646
9647 if (gtk_css_node_get_parent (widget->priv->cssnode) == NULL)
9648 gtk_css_node_set_parent (widget->priv->cssnode, parent->priv->cssnode);
9649 if (priv->context)
9650 gtk_style_context_set_parent (priv->context,
9651 _gtk_widget_get_style_context (parent));
9652
9653 _gtk_widget_update_parent_muxer (widget);
9654
9655 g_signal_emit (widget, widget_signals[PARENT_SET], 0, NULL);
9656 if (priv->parent->priv->anchored)
9657 _gtk_widget_propagate_hierarchy_changed (widget, NULL);
9658 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_PARENT]);
9659
9660 /* Enforce realized/mapped invariants
9661 */
9662 if (_gtk_widget_get_realized (priv->parent))
9663 gtk_widget_realize (widget);
9664
9665 if (_gtk_widget_get_visible (priv->parent) &&
9666 _gtk_widget_get_visible (widget))
9667 {
9668 if (_gtk_widget_get_child_visible (widget) &&
9669 _gtk_widget_get_mapped (priv->parent))
9670 gtk_widget_map (widget);
9671
9672 gtk_widget_queue_resize (priv->parent);
9673 }
9674
9675 /* child may cause parent's expand to change, if the child is
9676 * expanded. If child is not expanded, then it can't modify the
9677 * parent's expand. If the child becomes expanded later then it will
9678 * queue compute_expand then. This optimization plus defaulting
9679 * newly-constructed widgets to need_compute_expand=FALSE should
9680 * mean that initially building a widget tree doesn't have to keep
9681 * walking up setting need_compute_expand on parents over and over.
9682 *
9683 * We can't change a parent to need to expand unless we're visible.
9684 */
9685 if (_gtk_widget_get_visible (widget) &&
9686 (priv->need_compute_expand ||
9687 priv->computed_hexpand ||
9688 priv->computed_vexpand))
9689 {
9690 gtk_widget_queue_compute_expand (parent);
9691 }
9692
9693 gtk_widget_pop_verify_invariants (widget);
9694 }
9695
9696 /**
9697 * gtk_widget_get_parent:
9698 * @widget: a #GtkWidget
9699 *
9700 * Returns the parent container of @widget.
9701 *
9702 * Returns: (transfer none) (nullable): the parent container of @widget, or %NULL
9703 **/
9704 GtkWidget *
gtk_widget_get_parent(GtkWidget * widget)9705 gtk_widget_get_parent (GtkWidget *widget)
9706 {
9707 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
9708
9709 return widget->priv->parent;
9710 }
9711
9712 static GtkModifierStyle *
_gtk_widget_get_modifier_properties(GtkWidget * widget)9713 _gtk_widget_get_modifier_properties (GtkWidget *widget)
9714 {
9715 GtkModifierStyle *style;
9716
9717 style = g_object_get_qdata (G_OBJECT (widget), quark_modifier_style);
9718
9719 if (G_UNLIKELY (!style))
9720 {
9721 GtkStyleContext *context;
9722
9723 style = _gtk_modifier_style_new ();
9724 g_object_set_qdata_full (G_OBJECT (widget),
9725 quark_modifier_style,
9726 style,
9727 (GDestroyNotify) g_object_unref);
9728
9729 context = _gtk_widget_get_style_context (widget);
9730
9731 gtk_style_context_add_provider (context,
9732 GTK_STYLE_PROVIDER (style),
9733 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
9734 }
9735
9736 return style;
9737 }
9738
9739 /**
9740 * gtk_widget_override_color:
9741 * @widget: a #GtkWidget
9742 * @state: the state for which to set the color
9743 * @color: (allow-none): the color to assign, or %NULL to undo the effect
9744 * of previous calls to gtk_widget_override_color()
9745 *
9746 * Sets the color to use for a widget.
9747 *
9748 * All other style values are left untouched.
9749 *
9750 * This function does not act recursively. Setting the color of a
9751 * container does not affect its children. Note that some widgets that
9752 * you may not think of as containers, for instance #GtkButtons,
9753 * are actually containers.
9754 *
9755 * This API is mostly meant as a quick way for applications to
9756 * change a widget appearance. If you are developing a widgets
9757 * library and intend this change to be themeable, it is better
9758 * done by setting meaningful CSS classes in your
9759 * widget/container implementation through gtk_style_context_add_class().
9760 *
9761 * This way, your widget library can install a #GtkCssProvider
9762 * with the %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK priority in order
9763 * to provide a default styling for those widgets that need so, and
9764 * this theming may fully overridden by the user’s theme.
9765 *
9766 * Note that for complex widgets this may bring in undesired
9767 * results (such as uniform background color everywhere), in
9768 * these cases it is better to fully style such widgets through a
9769 * #GtkCssProvider with the %GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
9770 * priority.
9771 *
9772 * Since: 3.0
9773 *
9774 * Deprecated:3.16: Use a custom style provider and style classes instead
9775 */
9776 void
gtk_widget_override_color(GtkWidget * widget,GtkStateFlags state,const GdkRGBA * color)9777 gtk_widget_override_color (GtkWidget *widget,
9778 GtkStateFlags state,
9779 const GdkRGBA *color)
9780 {
9781 GtkModifierStyle *style;
9782
9783 g_return_if_fail (GTK_IS_WIDGET (widget));
9784
9785 style = _gtk_widget_get_modifier_properties (widget);
9786 _gtk_modifier_style_set_color (style, state, color);
9787 }
9788
9789 /**
9790 * gtk_widget_override_background_color:
9791 * @widget: a #GtkWidget
9792 * @state: the state for which to set the background color
9793 * @color: (allow-none): the color to assign, or %NULL to undo the effect
9794 * of previous calls to gtk_widget_override_background_color()
9795 *
9796 * Sets the background color to use for a widget.
9797 *
9798 * All other style values are left untouched.
9799 * See gtk_widget_override_color().
9800 *
9801 * Since: 3.0
9802 *
9803 * Deprecated: 3.16: This function is not useful in the context of CSS-based
9804 * rendering. If you wish to change the way a widget renders its background
9805 * you should use a custom CSS style, through an application-specific
9806 * #GtkStyleProvider and a CSS style class. You can also override the default
9807 * drawing of a widget through the #GtkWidget::draw signal, and use Cairo to
9808 * draw a specific color, regardless of the CSS style.
9809 */
9810 void
gtk_widget_override_background_color(GtkWidget * widget,GtkStateFlags state,const GdkRGBA * color)9811 gtk_widget_override_background_color (GtkWidget *widget,
9812 GtkStateFlags state,
9813 const GdkRGBA *color)
9814 {
9815 GtkModifierStyle *style;
9816
9817 g_return_if_fail (GTK_IS_WIDGET (widget));
9818
9819 style = _gtk_widget_get_modifier_properties (widget);
9820 _gtk_modifier_style_set_background_color (style, state, color);
9821 }
9822
9823 /**
9824 * gtk_widget_override_font:
9825 * @widget: a #GtkWidget
9826 * @font_desc: (allow-none): the font description to use, or %NULL to undo
9827 * the effect of previous calls to gtk_widget_override_font()
9828 *
9829 * Sets the font to use for a widget. All other style values are
9830 * left untouched. See gtk_widget_override_color().
9831 *
9832 * Since: 3.0
9833 *
9834 * Deprecated: 3.16: This function is not useful in the context of CSS-based
9835 * rendering. If you wish to change the font a widget uses to render its text
9836 * you should use a custom CSS style, through an application-specific
9837 * #GtkStyleProvider and a CSS style class.
9838 */
9839 void
gtk_widget_override_font(GtkWidget * widget,const PangoFontDescription * font_desc)9840 gtk_widget_override_font (GtkWidget *widget,
9841 const PangoFontDescription *font_desc)
9842 {
9843 GtkModifierStyle *style;
9844
9845 g_return_if_fail (GTK_IS_WIDGET (widget));
9846
9847 style = _gtk_widget_get_modifier_properties (widget);
9848 _gtk_modifier_style_set_font (style, font_desc);
9849 }
9850
9851 /**
9852 * gtk_widget_override_symbolic_color:
9853 * @widget: a #GtkWidget
9854 * @name: the name of the symbolic color to modify
9855 * @color: (allow-none): the color to assign (does not need
9856 * to be allocated), or %NULL to undo the effect of previous
9857 * calls to gtk_widget_override_symbolic_color()
9858 *
9859 * Sets a symbolic color for a widget.
9860 *
9861 * All other style values are left untouched.
9862 * See gtk_widget_override_color() for overriding the foreground
9863 * or background color.
9864 *
9865 * Since: 3.0
9866 *
9867 * Deprecated: 3.16: This function is not useful in the context of CSS-based
9868 * rendering. If you wish to change the color used to render symbolic icons
9869 * you should use a custom CSS style, through an application-specific
9870 * #GtkStyleProvider and a CSS style class.
9871 */
9872 void
gtk_widget_override_symbolic_color(GtkWidget * widget,const gchar * name,const GdkRGBA * color)9873 gtk_widget_override_symbolic_color (GtkWidget *widget,
9874 const gchar *name,
9875 const GdkRGBA *color)
9876 {
9877 GtkModifierStyle *style;
9878
9879 g_return_if_fail (GTK_IS_WIDGET (widget));
9880
9881 style = _gtk_widget_get_modifier_properties (widget);
9882 _gtk_modifier_style_map_color (style, name, color);
9883 }
9884
9885 /**
9886 * gtk_widget_override_cursor:
9887 * @widget: a #GtkWidget
9888 * @cursor: (allow-none): the color to use for primary cursor (does not need to be
9889 * allocated), or %NULL to undo the effect of previous calls to
9890 * of gtk_widget_override_cursor().
9891 * @secondary_cursor: (allow-none): the color to use for secondary cursor (does not
9892 * need to be allocated), or %NULL to undo the effect of previous
9893 * calls to of gtk_widget_override_cursor().
9894 *
9895 * Sets the cursor color to use in a widget, overriding the
9896 * cursor-color and secondary-cursor-color
9897 * style properties. All other style values are left untouched.
9898 * See also gtk_widget_modify_style().
9899 *
9900 * Note that the underlying properties have the #GdkColor type,
9901 * so the alpha value in @primary and @secondary will be ignored.
9902 *
9903 * Since: 3.0
9904 *
9905 * Deprecated: 3.16: This function is not useful in the context of CSS-based
9906 * rendering. If you wish to change the color used to render the primary
9907 * and secondary cursors you should use a custom CSS style, through an
9908 * application-specific #GtkStyleProvider and a CSS style class.
9909 */
9910 void
gtk_widget_override_cursor(GtkWidget * widget,const GdkRGBA * cursor,const GdkRGBA * secondary_cursor)9911 gtk_widget_override_cursor (GtkWidget *widget,
9912 const GdkRGBA *cursor,
9913 const GdkRGBA *secondary_cursor)
9914 {
9915 GtkModifierStyle *style;
9916
9917 g_return_if_fail (GTK_IS_WIDGET (widget));
9918
9919 style = _gtk_widget_get_modifier_properties (widget);
9920 _gtk_modifier_style_set_color_property (style,
9921 GTK_TYPE_WIDGET,
9922 "cursor-color", cursor);
9923 _gtk_modifier_style_set_color_property (style,
9924 GTK_TYPE_WIDGET,
9925 "secondary-cursor-color",
9926 secondary_cursor);
9927 }
9928
9929 static void
gtk_widget_real_direction_changed(GtkWidget * widget,GtkTextDirection previous_direction)9930 gtk_widget_real_direction_changed (GtkWidget *widget,
9931 GtkTextDirection previous_direction)
9932 {
9933 gtk_widget_queue_resize (widget);
9934 }
9935
9936 static void
gtk_widget_real_style_set(GtkWidget * widget,GtkStyle * previous_style)9937 gtk_widget_real_style_set (GtkWidget *widget,
9938 GtkStyle *previous_style)
9939 {
9940 }
9941
9942 typedef struct {
9943 GtkWidget *previous_toplevel;
9944 GdkScreen *previous_screen;
9945 GdkScreen *new_screen;
9946 } HierarchyChangedInfo;
9947
9948 static void
do_screen_change(GtkWidget * widget,GdkScreen * old_screen,GdkScreen * new_screen)9949 do_screen_change (GtkWidget *widget,
9950 GdkScreen *old_screen,
9951 GdkScreen *new_screen)
9952 {
9953 if (old_screen != new_screen)
9954 {
9955 GtkWidgetPrivate *priv = widget->priv;
9956
9957 if (old_screen)
9958 {
9959 PangoContext *context = g_object_get_qdata (G_OBJECT (widget), quark_pango_context);
9960 if (context)
9961 g_object_set_qdata (G_OBJECT (widget), quark_pango_context, NULL);
9962 }
9963
9964 _gtk_tooltip_hide (widget);
9965
9966 if (new_screen && priv->context)
9967 gtk_style_context_set_screen (priv->context, new_screen);
9968
9969 g_signal_emit (widget, widget_signals[SCREEN_CHANGED], 0, old_screen);
9970 }
9971 }
9972
9973 static void
gtk_widget_propagate_hierarchy_changed_recurse(GtkWidget * widget,gpointer client_data)9974 gtk_widget_propagate_hierarchy_changed_recurse (GtkWidget *widget,
9975 gpointer client_data)
9976 {
9977 GtkWidgetPrivate *priv = widget->priv;
9978 HierarchyChangedInfo *info = client_data;
9979 gboolean new_anchored = _gtk_widget_is_toplevel (widget) ||
9980 (priv->parent && priv->parent->priv->anchored);
9981
9982 if (priv->anchored != new_anchored)
9983 {
9984 g_object_ref (widget);
9985
9986 priv->anchored = new_anchored;
9987
9988 /* This can only happen with gtk_widget_reparent() */
9989 if (priv->realized)
9990 {
9991 if (new_anchored)
9992 gtk_widget_connect_frame_clock (widget,
9993 gtk_widget_get_frame_clock (widget));
9994 else
9995 gtk_widget_disconnect_frame_clock (widget,
9996 gtk_widget_get_frame_clock (info->previous_toplevel));
9997 }
9998
9999 g_signal_emit (widget, widget_signals[HIERARCHY_CHANGED], 0, info->previous_toplevel);
10000 do_screen_change (widget, info->previous_screen, info->new_screen);
10001
10002 if (GTK_IS_CONTAINER (widget))
10003 gtk_container_forall (GTK_CONTAINER (widget),
10004 gtk_widget_propagate_hierarchy_changed_recurse,
10005 client_data);
10006
10007 g_object_unref (widget);
10008 }
10009 }
10010
10011 /**
10012 * _gtk_widget_propagate_hierarchy_changed:
10013 * @widget: a #GtkWidget
10014 * @previous_toplevel: Previous toplevel
10015 *
10016 * Propagates changes in the anchored state to a widget and all
10017 * children, unsetting or setting the %ANCHORED flag, and
10018 * emitting #GtkWidget::hierarchy-changed.
10019 **/
10020 void
_gtk_widget_propagate_hierarchy_changed(GtkWidget * widget,GtkWidget * previous_toplevel)10021 _gtk_widget_propagate_hierarchy_changed (GtkWidget *widget,
10022 GtkWidget *previous_toplevel)
10023 {
10024 GtkWidgetPrivate *priv = widget->priv;
10025 HierarchyChangedInfo info;
10026
10027 info.previous_toplevel = previous_toplevel;
10028 info.previous_screen = previous_toplevel ? gtk_widget_get_screen (previous_toplevel) : NULL;
10029
10030 if (_gtk_widget_is_toplevel (widget) ||
10031 (priv->parent && priv->parent->priv->anchored))
10032 info.new_screen = gtk_widget_get_screen (widget);
10033 else
10034 info.new_screen = NULL;
10035
10036 if (info.previous_screen)
10037 g_object_ref (info.previous_screen);
10038 if (previous_toplevel)
10039 g_object_ref (previous_toplevel);
10040
10041 gtk_widget_propagate_hierarchy_changed_recurse (widget, &info);
10042
10043 if (previous_toplevel)
10044 g_object_unref (previous_toplevel);
10045 if (info.previous_screen)
10046 g_object_unref (info.previous_screen);
10047 }
10048
10049 static void
gtk_widget_propagate_screen_changed_recurse(GtkWidget * widget,gpointer client_data)10050 gtk_widget_propagate_screen_changed_recurse (GtkWidget *widget,
10051 gpointer client_data)
10052 {
10053 HierarchyChangedInfo *info = client_data;
10054
10055 g_object_ref (widget);
10056
10057 do_screen_change (widget, info->previous_screen, info->new_screen);
10058
10059 if (GTK_IS_CONTAINER (widget))
10060 gtk_container_forall (GTK_CONTAINER (widget),
10061 gtk_widget_propagate_screen_changed_recurse,
10062 client_data);
10063
10064 g_object_unref (widget);
10065 }
10066
10067 /**
10068 * gtk_widget_is_composited:
10069 * @widget: a #GtkWidget
10070 *
10071 * Whether @widget can rely on having its alpha channel
10072 * drawn correctly. On X11 this function returns whether a
10073 * compositing manager is running for @widget’s screen.
10074 *
10075 * Please note that the semantics of this call will change
10076 * in the future if used on a widget that has a composited
10077 * window in its hierarchy (as set by gdk_window_set_composited()).
10078 *
10079 * Returns: %TRUE if the widget can rely on its alpha
10080 * channel being drawn correctly.
10081 *
10082 * Since: 2.10
10083 *
10084 * Deprecated: 3.22: Use gdk_screen_is_composited() instead.
10085 */
10086 gboolean
gtk_widget_is_composited(GtkWidget * widget)10087 gtk_widget_is_composited (GtkWidget *widget)
10088 {
10089 GdkScreen *screen;
10090
10091 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
10092
10093 screen = gtk_widget_get_screen (widget);
10094
10095 return gdk_screen_is_composited (screen);
10096 }
10097
10098 static void
propagate_composited_changed(GtkWidget * widget,gpointer dummy)10099 propagate_composited_changed (GtkWidget *widget,
10100 gpointer dummy)
10101 {
10102 if (GTK_IS_CONTAINER (widget))
10103 {
10104 gtk_container_forall (GTK_CONTAINER (widget),
10105 propagate_composited_changed,
10106 NULL);
10107 }
10108
10109 g_signal_emit (widget, widget_signals[COMPOSITED_CHANGED], 0);
10110 }
10111
10112 void
_gtk_widget_propagate_composited_changed(GtkWidget * widget)10113 _gtk_widget_propagate_composited_changed (GtkWidget *widget)
10114 {
10115 propagate_composited_changed (widget, NULL);
10116 }
10117
10118 /**
10119 * _gtk_widget_propagate_screen_changed:
10120 * @widget: a #GtkWidget
10121 * @previous_screen: Previous screen
10122 *
10123 * Propagates changes in the screen for a widget to all
10124 * children, emitting #GtkWidget::screen-changed.
10125 **/
10126 void
_gtk_widget_propagate_screen_changed(GtkWidget * widget,GdkScreen * previous_screen)10127 _gtk_widget_propagate_screen_changed (GtkWidget *widget,
10128 GdkScreen *previous_screen)
10129 {
10130 HierarchyChangedInfo info;
10131
10132 info.previous_screen = previous_screen;
10133 info.new_screen = gtk_widget_get_screen (widget);
10134
10135 if (previous_screen)
10136 g_object_ref (previous_screen);
10137
10138 gtk_widget_propagate_screen_changed_recurse (widget, &info);
10139
10140 if (previous_screen)
10141 g_object_unref (previous_screen);
10142 }
10143
10144 static void
reset_style_recurse(GtkWidget * widget,gpointer data)10145 reset_style_recurse (GtkWidget *widget, gpointer data)
10146 {
10147 _gtk_widget_invalidate_style_context (widget, GTK_CSS_CHANGE_ANY);
10148
10149 if (GTK_IS_CONTAINER (widget))
10150 gtk_container_forall (GTK_CONTAINER (widget),
10151 reset_style_recurse,
10152 NULL);
10153 }
10154
10155 /**
10156 * gtk_widget_reset_style:
10157 * @widget: a #GtkWidget
10158 *
10159 * Updates the style context of @widget and all descendants
10160 * by updating its widget path. #GtkContainers may want
10161 * to use this on a child when reordering it in a way that a different
10162 * style might apply to it. See also gtk_container_get_path_for_child().
10163 *
10164 * Since: 3.0
10165 */
10166 void
gtk_widget_reset_style(GtkWidget * widget)10167 gtk_widget_reset_style (GtkWidget *widget)
10168 {
10169 g_return_if_fail (GTK_IS_WIDGET (widget));
10170
10171 reset_style_recurse (widget, NULL);
10172
10173 g_list_foreach (widget->priv->attached_windows,
10174 (GFunc) reset_style_recurse, NULL);
10175 }
10176
10177 #ifdef G_ENABLE_CONSISTENCY_CHECKS
10178
10179 /* Verify invariants, see docs/widget_system.txt for notes on much of
10180 * this. Invariants may be temporarily broken while we’re in the
10181 * process of updating state, of course, so you can only
10182 * verify_invariants() after a given operation is complete.
10183 * Use push/pop_verify_invariants to help with that.
10184 */
10185 static void
gtk_widget_verify_invariants(GtkWidget * widget)10186 gtk_widget_verify_invariants (GtkWidget *widget)
10187 {
10188 GtkWidget *parent;
10189
10190 if (widget->priv->verifying_invariants_count > 0)
10191 return;
10192
10193 parent = widget->priv->parent;
10194
10195 if (widget->priv->mapped)
10196 {
10197 /* Mapped implies ... */
10198
10199 if (!widget->priv->realized)
10200 g_warning ("%s %p is mapped but not realized",
10201 G_OBJECT_TYPE_NAME (widget), widget);
10202
10203 if (!widget->priv->visible)
10204 g_warning ("%s %p is mapped but not visible",
10205 G_OBJECT_TYPE_NAME (widget), widget);
10206
10207 if (!widget->priv->toplevel)
10208 {
10209 if (!widget->priv->child_visible)
10210 g_warning ("%s %p is mapped but not child_visible",
10211 G_OBJECT_TYPE_NAME (widget), widget);
10212 }
10213 }
10214 else
10215 {
10216 /* Not mapped implies... */
10217
10218 #if 0
10219 /* This check makes sense for normal toplevels, but for
10220 * something like a toplevel that is embedded within a clutter
10221 * state, mapping may depend on external factors.
10222 */
10223 if (widget->priv->toplevel)
10224 {
10225 if (widget->priv->visible)
10226 g_warning ("%s %p toplevel is visible but not mapped",
10227 G_OBJECT_TYPE_NAME (widget), widget);
10228 }
10229 #endif
10230 }
10231
10232 /* Parent related checks aren't possible if parent has
10233 * verifying_invariants_count > 0 because parent needs to recurse
10234 * children first before the invariants will hold.
10235 */
10236 if (parent == NULL || parent->priv->verifying_invariants_count == 0)
10237 {
10238 if (parent &&
10239 parent->priv->realized)
10240 {
10241 /* Parent realized implies... */
10242
10243 #if 0
10244 /* This is in widget_system.txt but appears to fail
10245 * because there's no gtk_container_realize() that
10246 * realizes all children... instead we just lazily
10247 * wait for map to fix things up.
10248 */
10249 if (!widget->priv->realized)
10250 g_warning ("%s %p is realized but child %s %p is not realized",
10251 G_OBJECT_TYPE_NAME (parent), parent,
10252 G_OBJECT_TYPE_NAME (widget), widget);
10253 #endif
10254 }
10255 else if (!widget->priv->toplevel)
10256 {
10257 /* No parent or parent not realized on non-toplevel implies... */
10258
10259 if (widget->priv->realized && !widget->priv->in_reparent)
10260 g_warning ("%s %p is not realized but child %s %p is realized",
10261 parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
10262 G_OBJECT_TYPE_NAME (widget), widget);
10263 }
10264
10265 if (parent &&
10266 parent->priv->mapped &&
10267 widget->priv->visible &&
10268 widget->priv->child_visible)
10269 {
10270 /* Parent mapped and we are visible implies... */
10271
10272 if (!widget->priv->mapped)
10273 g_warning ("%s %p is mapped but visible child %s %p is not mapped",
10274 G_OBJECT_TYPE_NAME (parent), parent,
10275 G_OBJECT_TYPE_NAME (widget), widget);
10276 }
10277 else if (!widget->priv->toplevel)
10278 {
10279 /* No parent or parent not mapped on non-toplevel implies... */
10280
10281 if (widget->priv->mapped && !widget->priv->in_reparent)
10282 g_warning ("%s %p is mapped but visible=%d child_visible=%d parent %s %p mapped=%d",
10283 G_OBJECT_TYPE_NAME (widget), widget,
10284 widget->priv->visible,
10285 widget->priv->child_visible,
10286 parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
10287 parent ? parent->priv->mapped : FALSE);
10288 }
10289 }
10290
10291 if (!widget->priv->realized)
10292 {
10293 /* Not realized implies... */
10294
10295 #if 0
10296 /* widget_system.txt says these hold, but they don't. */
10297 if (widget->priv->alloc_needed)
10298 g_warning ("%s %p alloc needed but not realized",
10299 G_OBJECT_TYPE_NAME (widget), widget);
10300
10301 if (widget->priv->width_request_needed)
10302 g_warning ("%s %p width request needed but not realized",
10303 G_OBJECT_TYPE_NAME (widget), widget);
10304
10305 if (widget->priv->height_request_needed)
10306 g_warning ("%s %p height request needed but not realized",
10307 G_OBJECT_TYPE_NAME (widget), widget);
10308 #endif
10309 }
10310 }
10311
10312 /* The point of this push/pop is that invariants may not hold while
10313 * we’re busy making changes. So we only check at the outermost call
10314 * on the call stack, after we finish updating everything.
10315 */
10316 static void
gtk_widget_push_verify_invariants(GtkWidget * widget)10317 gtk_widget_push_verify_invariants (GtkWidget *widget)
10318 {
10319 widget->priv->verifying_invariants_count += 1;
10320 }
10321
10322 static void
gtk_widget_verify_child_invariants(GtkWidget * widget,gpointer client_data)10323 gtk_widget_verify_child_invariants (GtkWidget *widget,
10324 gpointer client_data)
10325 {
10326 /* We don't recurse further; this is a one-level check. */
10327 gtk_widget_verify_invariants (widget);
10328 }
10329
10330 static void
gtk_widget_pop_verify_invariants(GtkWidget * widget)10331 gtk_widget_pop_verify_invariants (GtkWidget *widget)
10332 {
10333 g_assert (widget->priv->verifying_invariants_count > 0);
10334
10335 widget->priv->verifying_invariants_count -= 1;
10336
10337 if (widget->priv->verifying_invariants_count == 0)
10338 {
10339 gtk_widget_verify_invariants (widget);
10340
10341 if (GTK_IS_CONTAINER (widget))
10342 {
10343 /* Check one level of children, because our
10344 * push_verify_invariants() will have prevented some of the
10345 * checks. This does not recurse because if recursion is
10346 * needed, it will happen naturally as each child has a
10347 * push/pop on that child. For example if we're recursively
10348 * mapping children, we'll push/pop on each child as we map
10349 * it.
10350 */
10351 gtk_container_forall (GTK_CONTAINER (widget),
10352 gtk_widget_verify_child_invariants,
10353 NULL);
10354 }
10355 }
10356 }
10357 #endif /* G_ENABLE_CONSISTENCY_CHECKS */
10358
10359 static PangoContext *
gtk_widget_peek_pango_context(GtkWidget * widget)10360 gtk_widget_peek_pango_context (GtkWidget *widget)
10361 {
10362 return g_object_get_qdata (G_OBJECT (widget), quark_pango_context);
10363 }
10364
10365 /**
10366 * gtk_widget_get_pango_context:
10367 * @widget: a #GtkWidget
10368 *
10369 * Gets a #PangoContext with the appropriate font map, font description,
10370 * and base direction for this widget. Unlike the context returned
10371 * by gtk_widget_create_pango_context(), this context is owned by
10372 * the widget (it can be used until the screen for the widget changes
10373 * or the widget is removed from its toplevel), and will be updated to
10374 * match any changes to the widget’s attributes. This can be tracked
10375 * by using the #GtkWidget::screen-changed signal on the widget.
10376 *
10377 * Returns: (transfer none): the #PangoContext for the widget.
10378 **/
10379 PangoContext *
gtk_widget_get_pango_context(GtkWidget * widget)10380 gtk_widget_get_pango_context (GtkWidget *widget)
10381 {
10382 PangoContext *context;
10383
10384 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
10385
10386 context = g_object_get_qdata (G_OBJECT (widget), quark_pango_context);
10387 if (!context)
10388 {
10389 context = gtk_widget_create_pango_context (GTK_WIDGET (widget));
10390 g_object_set_qdata_full (G_OBJECT (widget),
10391 quark_pango_context,
10392 context,
10393 g_object_unref);
10394 }
10395
10396 return context;
10397 }
10398
10399 static PangoFontMap *
gtk_widget_get_effective_font_map(GtkWidget * widget)10400 gtk_widget_get_effective_font_map (GtkWidget *widget)
10401 {
10402 PangoFontMap *font_map;
10403
10404 font_map = PANGO_FONT_MAP (g_object_get_qdata (G_OBJECT (widget), quark_font_map));
10405 if (font_map)
10406 return font_map;
10407 else if (widget->priv->parent)
10408 return gtk_widget_get_effective_font_map (widget->priv->parent);
10409 else
10410 return pango_cairo_font_map_get_default ();
10411 }
10412
10413 static void
update_pango_context(GtkWidget * widget,PangoContext * context)10414 update_pango_context (GtkWidget *widget,
10415 PangoContext *context)
10416 {
10417 PangoFontDescription *font_desc;
10418 GtkStyleContext *style_context;
10419 GdkScreen *screen;
10420 cairo_font_options_t *font_options;
10421
10422 style_context = _gtk_widget_get_style_context (widget);
10423 gtk_style_context_get (style_context,
10424 gtk_style_context_get_state (style_context),
10425 "font", &font_desc,
10426 NULL);
10427
10428 pango_context_set_font_description (context, font_desc);
10429
10430 pango_font_description_free (font_desc);
10431
10432 pango_context_set_base_dir (context,
10433 _gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
10434 PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL);
10435
10436 pango_cairo_context_set_resolution (context,
10437 _gtk_css_number_value_get (
10438 _gtk_style_context_peek_property (style_context,
10439 GTK_CSS_PROPERTY_DPI),
10440 100));
10441
10442 screen = gtk_widget_get_screen_unchecked (widget);
10443 font_options = (cairo_font_options_t*)g_object_get_qdata (G_OBJECT (widget), quark_font_options);
10444 if (screen && font_options)
10445 {
10446 cairo_font_options_t *options;
10447
10448 options = cairo_font_options_copy (gdk_screen_get_font_options (screen));
10449 cairo_font_options_merge (options, font_options);
10450 pango_cairo_context_set_font_options (context, options);
10451 cairo_font_options_destroy (options);
10452 }
10453 else if (screen)
10454 {
10455 pango_cairo_context_set_font_options (context,
10456 gdk_screen_get_font_options (screen));
10457 }
10458
10459 pango_context_set_font_map (context, gtk_widget_get_effective_font_map (widget));
10460 }
10461
10462 static void
gtk_widget_update_pango_context(GtkWidget * widget)10463 gtk_widget_update_pango_context (GtkWidget *widget)
10464 {
10465 PangoContext *context = gtk_widget_peek_pango_context (widget);
10466
10467 if (context)
10468 update_pango_context (widget, context);
10469 }
10470
10471 /**
10472 * gtk_widget_set_font_options:
10473 * @widget: a #GtkWidget
10474 * @options: (allow-none): a #cairo_font_options_t, or %NULL to unset any
10475 * previously set default font options.
10476 *
10477 * Sets the #cairo_font_options_t used for Pango rendering in this widget.
10478 * When not set, the default font options for the #GdkScreen will be used.
10479 *
10480 * Since: 3.18
10481 **/
10482 void
gtk_widget_set_font_options(GtkWidget * widget,const cairo_font_options_t * options)10483 gtk_widget_set_font_options (GtkWidget *widget,
10484 const cairo_font_options_t *options)
10485 {
10486 cairo_font_options_t *font_options;
10487
10488 g_return_if_fail (GTK_IS_WIDGET (widget));
10489
10490 font_options = (cairo_font_options_t *)g_object_get_qdata (G_OBJECT (widget), quark_font_options);
10491 if (font_options != options)
10492 {
10493 g_object_set_qdata_full (G_OBJECT (widget),
10494 quark_font_options,
10495 options ? cairo_font_options_copy (options) : NULL,
10496 (GDestroyNotify)cairo_font_options_destroy);
10497
10498 gtk_widget_update_pango_context (widget);
10499 }
10500 }
10501
10502 /**
10503 * gtk_widget_get_font_options:
10504 * @widget: a #GtkWidget
10505 *
10506 * Returns the #cairo_font_options_t used for Pango rendering. When not set,
10507 * the defaults font options for the #GdkScreen will be used.
10508 *
10509 * Returns: (transfer none) (nullable): the #cairo_font_options_t or %NULL if not set
10510 *
10511 * Since: 3.18
10512 **/
10513 const cairo_font_options_t *
gtk_widget_get_font_options(GtkWidget * widget)10514 gtk_widget_get_font_options (GtkWidget *widget)
10515 {
10516 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
10517
10518 return (cairo_font_options_t *)g_object_get_qdata (G_OBJECT (widget), quark_font_options);
10519 }
10520
10521 static void
gtk_widget_set_font_map_recurse(GtkWidget * widget,gpointer data)10522 gtk_widget_set_font_map_recurse (GtkWidget *widget, gpointer data)
10523 {
10524 if (g_object_get_qdata (G_OBJECT (widget), quark_font_map))
10525 return;
10526
10527 gtk_widget_update_pango_context (widget);
10528
10529 if (GTK_IS_CONTAINER (widget))
10530 gtk_container_forall (GTK_CONTAINER (widget),
10531 gtk_widget_set_font_map_recurse,
10532 data);
10533 }
10534
10535 /**
10536 * gtk_widget_set_font_map:
10537 * @widget: a #GtkWidget
10538 * @font_map: (allow-none): a #PangoFontMap, or %NULL to unset any previously
10539 * set font map
10540 *
10541 * Sets the font map to use for Pango rendering. When not set, the widget
10542 * will inherit the font map from its parent.
10543 *
10544 * Since: 3.18
10545 */
10546 void
gtk_widget_set_font_map(GtkWidget * widget,PangoFontMap * font_map)10547 gtk_widget_set_font_map (GtkWidget *widget,
10548 PangoFontMap *font_map)
10549 {
10550 PangoFontMap *map;
10551
10552 g_return_if_fail (GTK_IS_WIDGET (widget));
10553
10554 map = PANGO_FONT_MAP (g_object_get_qdata (G_OBJECT (widget), quark_font_map));
10555 if (map == font_map)
10556 return;
10557
10558 g_object_set_qdata_full (G_OBJECT (widget),
10559 quark_font_map,
10560 g_object_ref (font_map),
10561 g_object_unref);
10562
10563 gtk_widget_update_pango_context (widget);
10564 if (GTK_IS_CONTAINER (widget))
10565 gtk_container_forall (GTK_CONTAINER (widget),
10566 gtk_widget_set_font_map_recurse,
10567 NULL);
10568 }
10569
10570 /**
10571 * gtk_widget_get_font_map:
10572 * @widget: a #GtkWidget
10573 *
10574 * Gets the font map that has been set with gtk_widget_set_font_map().
10575 *
10576 * Returns: (transfer none) (nullable): A #PangoFontMap, or %NULL
10577 *
10578 * Since: 3.18
10579 */
10580 PangoFontMap *
gtk_widget_get_font_map(GtkWidget * widget)10581 gtk_widget_get_font_map (GtkWidget *widget)
10582 {
10583 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
10584
10585 return PANGO_FONT_MAP (g_object_get_qdata (G_OBJECT (widget), quark_font_map));
10586 }
10587
10588 /**
10589 * gtk_widget_create_pango_context:
10590 * @widget: a #GtkWidget
10591 *
10592 * Creates a new #PangoContext with the appropriate font map,
10593 * font options, font description, and base direction for drawing
10594 * text for this widget. See also gtk_widget_get_pango_context().
10595 *
10596 * Returns: (transfer full): the new #PangoContext
10597 **/
10598 PangoContext *
gtk_widget_create_pango_context(GtkWidget * widget)10599 gtk_widget_create_pango_context (GtkWidget *widget)
10600 {
10601 GdkDisplay *display;
10602 PangoContext *context;
10603
10604 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
10605
10606 display = gtk_widget_get_display (widget);
10607 context = gdk_pango_context_get_for_display (display);
10608 update_pango_context (widget, context);
10609 pango_context_set_language (context, gtk_get_default_language ());
10610
10611 return context;
10612 }
10613
10614 /**
10615 * gtk_widget_create_pango_layout:
10616 * @widget: a #GtkWidget
10617 * @text: (nullable): text to set on the layout (can be %NULL)
10618 *
10619 * Creates a new #PangoLayout with the appropriate font map,
10620 * font description, and base direction for drawing text for
10621 * this widget.
10622 *
10623 * If you keep a #PangoLayout created in this way around, you need
10624 * to re-create it when the widget #PangoContext is replaced.
10625 * This can be tracked by using the #GtkWidget::screen-changed signal
10626 * on the widget.
10627 *
10628 * Returns: (transfer full): the new #PangoLayout
10629 **/
10630 PangoLayout *
gtk_widget_create_pango_layout(GtkWidget * widget,const gchar * text)10631 gtk_widget_create_pango_layout (GtkWidget *widget,
10632 const gchar *text)
10633 {
10634 PangoLayout *layout;
10635 PangoContext *context;
10636
10637 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
10638
10639 context = gtk_widget_get_pango_context (widget);
10640 layout = pango_layout_new (context);
10641
10642 if (text)
10643 pango_layout_set_text (layout, text, -1);
10644
10645 return layout;
10646 }
10647
10648 /**
10649 * gtk_widget_render_icon_pixbuf:
10650 * @widget: a #GtkWidget
10651 * @stock_id: a stock ID
10652 * @size: (type int): a stock size (#GtkIconSize). A size of `(GtkIconSize)-1`
10653 * means render at the size of the source and don’t scale (if there are
10654 * multiple source sizes, GTK+ picks one of the available sizes).
10655 *
10656 * A convenience function that uses the theme engine and style
10657 * settings for @widget to look up @stock_id and render it to
10658 * a pixbuf. @stock_id should be a stock icon ID such as
10659 * #GTK_STOCK_OPEN or #GTK_STOCK_OK. @size should be a size
10660 * such as #GTK_ICON_SIZE_MENU.
10661 *
10662 * The pixels in the returned #GdkPixbuf are shared with the rest of
10663 * the application and should not be modified. The pixbuf should be freed
10664 * after use with g_object_unref().
10665 *
10666 * Returns: (transfer full) (nullable): a new pixbuf, or %NULL if the
10667 * stock ID wasn’t known
10668 *
10669 * Since: 3.0
10670 *
10671 * Deprecated: 3.10: Use gtk_icon_theme_load_icon() instead.
10672 **/
10673 GdkPixbuf*
gtk_widget_render_icon_pixbuf(GtkWidget * widget,const gchar * stock_id,GtkIconSize size)10674 gtk_widget_render_icon_pixbuf (GtkWidget *widget,
10675 const gchar *stock_id,
10676 GtkIconSize size)
10677 {
10678 GtkStyleContext *context;
10679 GtkIconSet *icon_set;
10680
10681 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
10682 g_return_val_if_fail (stock_id != NULL, NULL);
10683 g_return_val_if_fail (size > GTK_ICON_SIZE_INVALID || size == -1, NULL);
10684
10685 context = _gtk_widget_get_style_context (widget);
10686 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
10687 icon_set = gtk_style_context_lookup_icon_set (context, stock_id);
10688
10689 if (icon_set == NULL)
10690 return NULL;
10691
10692 return gtk_icon_set_render_icon_pixbuf (icon_set, context, size);
10693 G_GNUC_END_IGNORE_DEPRECATIONS;
10694 }
10695
10696 /**
10697 * gtk_widget_set_parent_window:
10698 * @widget: a #GtkWidget.
10699 * @parent_window: the new parent window.
10700 *
10701 * Sets a non default parent window for @widget.
10702 *
10703 * For #GtkWindow classes, setting a @parent_window effects whether
10704 * the window is a toplevel window or can be embedded into other
10705 * widgets.
10706 *
10707 * For #GtkWindow classes, this needs to be called before the
10708 * window is realized.
10709 */
10710 void
gtk_widget_set_parent_window(GtkWidget * widget,GdkWindow * parent_window)10711 gtk_widget_set_parent_window (GtkWidget *widget,
10712 GdkWindow *parent_window)
10713 {
10714 GdkWindow *old_parent_window;
10715
10716 g_return_if_fail (GTK_IS_WIDGET (widget));
10717
10718 old_parent_window = g_object_get_qdata (G_OBJECT (widget),
10719 quark_parent_window);
10720
10721 if (parent_window != old_parent_window)
10722 {
10723 gboolean is_plug;
10724
10725 g_object_set_qdata (G_OBJECT (widget), quark_parent_window,
10726 parent_window);
10727 if (old_parent_window)
10728 g_object_unref (old_parent_window);
10729 if (parent_window)
10730 g_object_ref (parent_window);
10731
10732 /* Unset toplevel flag when adding a parent window to a widget,
10733 * this is the primary entry point to allow toplevels to be
10734 * embeddable.
10735 */
10736 #ifdef GDK_WINDOWING_X11
10737 is_plug = GTK_IS_PLUG (widget);
10738 #else
10739 is_plug = FALSE;
10740 #endif
10741 if (GTK_IS_WINDOW (widget) && !is_plug)
10742 _gtk_window_set_is_toplevel (GTK_WINDOW (widget), parent_window == NULL);
10743 }
10744 }
10745
10746 /**
10747 * gtk_widget_get_parent_window:
10748 * @widget: a #GtkWidget.
10749 *
10750 * Gets @widget’s parent window, or %NULL if it does not have one.
10751 *
10752 * Returns: (transfer none) (nullable): the parent window of @widget, or %NULL
10753 * if it does not have a parent window.
10754 **/
10755 GdkWindow *
gtk_widget_get_parent_window(GtkWidget * widget)10756 gtk_widget_get_parent_window (GtkWidget *widget)
10757 {
10758 GtkWidgetPrivate *priv;
10759 GdkWindow *parent_window;
10760
10761 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
10762
10763 priv = widget->priv;
10764
10765 parent_window = g_object_get_qdata (G_OBJECT (widget), quark_parent_window);
10766
10767 return (parent_window != NULL) ? parent_window :
10768 (priv->parent != NULL) ? priv->parent->priv->window : NULL;
10769 }
10770
10771
10772 /**
10773 * gtk_widget_set_child_visible:
10774 * @widget: a #GtkWidget
10775 * @is_visible: if %TRUE, @widget should be mapped along with its parent.
10776 *
10777 * Sets whether @widget should be mapped along with its when its parent
10778 * is mapped and @widget has been shown with gtk_widget_show().
10779 *
10780 * The child visibility can be set for widget before it is added to
10781 * a container with gtk_widget_set_parent(), to avoid mapping
10782 * children unnecessary before immediately unmapping them. However
10783 * it will be reset to its default state of %TRUE when the widget
10784 * is removed from a container.
10785 *
10786 * Note that changing the child visibility of a widget does not
10787 * queue a resize on the widget. Most of the time, the size of
10788 * a widget is computed from all visible children, whether or
10789 * not they are mapped. If this is not the case, the container
10790 * can queue a resize itself.
10791 *
10792 * This function is only useful for container implementations and
10793 * never should be called by an application.
10794 **/
10795 void
gtk_widget_set_child_visible(GtkWidget * widget,gboolean is_visible)10796 gtk_widget_set_child_visible (GtkWidget *widget,
10797 gboolean is_visible)
10798 {
10799 GtkWidgetPrivate *priv;
10800
10801 g_return_if_fail (GTK_IS_WIDGET (widget));
10802 g_return_if_fail (!_gtk_widget_is_toplevel (widget));
10803
10804 priv = widget->priv;
10805
10806 g_object_ref (widget);
10807 gtk_widget_verify_invariants (widget);
10808
10809 if (is_visible)
10810 priv->child_visible = TRUE;
10811 else
10812 {
10813 GtkWidget *toplevel;
10814
10815 priv->child_visible = FALSE;
10816
10817 toplevel = _gtk_widget_get_toplevel (widget);
10818 if (toplevel != widget && _gtk_widget_is_toplevel (toplevel))
10819 _gtk_window_unset_focus_and_default (GTK_WINDOW (toplevel), widget);
10820 }
10821
10822 if (priv->parent && _gtk_widget_get_realized (priv->parent))
10823 {
10824 if (_gtk_widget_get_mapped (priv->parent) &&
10825 priv->child_visible &&
10826 _gtk_widget_get_visible (widget))
10827 gtk_widget_map (widget);
10828 else
10829 gtk_widget_unmap (widget);
10830 }
10831
10832 gtk_widget_verify_invariants (widget);
10833 g_object_unref (widget);
10834 }
10835
10836 /**
10837 * gtk_widget_get_child_visible:
10838 * @widget: a #GtkWidget
10839 *
10840 * Gets the value set with gtk_widget_set_child_visible().
10841 * If you feel a need to use this function, your code probably
10842 * needs reorganization.
10843 *
10844 * This function is only useful for container implementations and
10845 * never should be called by an application.
10846 *
10847 * Returns: %TRUE if the widget is mapped with the parent.
10848 **/
10849 gboolean
gtk_widget_get_child_visible(GtkWidget * widget)10850 gtk_widget_get_child_visible (GtkWidget *widget)
10851 {
10852 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
10853
10854 return widget->priv->child_visible;
10855 }
10856
10857 static GdkScreen *
gtk_widget_get_screen_unchecked(GtkWidget * widget)10858 gtk_widget_get_screen_unchecked (GtkWidget *widget)
10859 {
10860 GtkWidget *toplevel;
10861
10862 toplevel = _gtk_widget_get_toplevel (widget);
10863
10864 if (_gtk_widget_is_toplevel (toplevel))
10865 {
10866 if (GTK_IS_WINDOW (toplevel))
10867 return _gtk_window_get_screen (GTK_WINDOW (toplevel));
10868 else if (GTK_IS_INVISIBLE (toplevel))
10869 return gtk_invisible_get_screen (GTK_INVISIBLE (widget));
10870 }
10871
10872 return NULL;
10873 }
10874
10875 /**
10876 * gtk_widget_get_screen:
10877 * @widget: a #GtkWidget
10878 *
10879 * Get the #GdkScreen from the toplevel window associated with
10880 * this widget. This function can only be called after the widget
10881 * has been added to a widget hierarchy with a #GtkWindow
10882 * at the top.
10883 *
10884 * In general, you should only create screen specific
10885 * resources when a widget has been realized, and you should
10886 * free those resources when the widget is unrealized.
10887 *
10888 * Returns: (transfer none): the #GdkScreen for the toplevel for this widget.
10889 *
10890 * Since: 2.2
10891 **/
10892 GdkScreen*
gtk_widget_get_screen(GtkWidget * widget)10893 gtk_widget_get_screen (GtkWidget *widget)
10894 {
10895 GdkScreen *screen;
10896
10897 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
10898
10899 screen = gtk_widget_get_screen_unchecked (widget);
10900
10901 if (screen)
10902 return screen;
10903 else
10904 return gdk_screen_get_default ();
10905 }
10906
10907 /**
10908 * gtk_widget_has_screen:
10909 * @widget: a #GtkWidget
10910 *
10911 * Checks whether there is a #GdkScreen is associated with
10912 * this widget. All toplevel widgets have an associated
10913 * screen, and all widgets added into a hierarchy with a toplevel
10914 * window at the top.
10915 *
10916 * Returns: %TRUE if there is a #GdkScreen associated
10917 * with the widget.
10918 *
10919 * Since: 2.2
10920 **/
10921 gboolean
gtk_widget_has_screen(GtkWidget * widget)10922 gtk_widget_has_screen (GtkWidget *widget)
10923 {
10924 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
10925
10926 return (gtk_widget_get_screen_unchecked (widget) != NULL);
10927 }
10928
10929 void
_gtk_widget_scale_changed(GtkWidget * widget)10930 _gtk_widget_scale_changed (GtkWidget *widget)
10931 {
10932 GtkWidgetPrivate *priv;
10933
10934 g_return_if_fail (GTK_IS_WIDGET (widget));
10935
10936 priv = widget->priv;
10937
10938 if (priv->context)
10939 gtk_style_context_set_scale (priv->context, gtk_widget_get_scale_factor (widget));
10940
10941 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_SCALE_FACTOR]);
10942
10943 gtk_widget_queue_draw (widget);
10944
10945 if (GTK_IS_CONTAINER (widget))
10946 gtk_container_forall (GTK_CONTAINER (widget),
10947 (GtkCallback) _gtk_widget_scale_changed,
10948 NULL);
10949 }
10950
10951 /**
10952 * gtk_widget_get_scale_factor:
10953 * @widget: a #GtkWidget
10954 *
10955 * Retrieves the internal scale factor that maps from window coordinates
10956 * to the actual device pixels. On traditional systems this is 1, on
10957 * high density outputs, it can be a higher value (typically 2).
10958 *
10959 * See gdk_window_get_scale_factor().
10960 *
10961 * Returns: the scale factor for @widget
10962 *
10963 * Since: 3.10
10964 */
10965 gint
gtk_widget_get_scale_factor(GtkWidget * widget)10966 gtk_widget_get_scale_factor (GtkWidget *widget)
10967 {
10968 GtkWidget *toplevel;
10969 GdkDisplay *display;
10970 GdkMonitor *monitor;
10971
10972 g_return_val_if_fail (GTK_IS_WIDGET (widget), 1);
10973
10974 if (_gtk_widget_get_realized (widget))
10975 return gdk_window_get_scale_factor (_gtk_widget_get_window (widget));
10976
10977 toplevel = _gtk_widget_get_toplevel (widget);
10978 if (toplevel && toplevel != widget)
10979 return gtk_widget_get_scale_factor (toplevel);
10980
10981 /* else fall back to something that is more likely to be right than
10982 * just returning 1:
10983 */
10984 display = gtk_widget_get_display (widget);
10985 monitor = gdk_display_get_monitor (display, 0);
10986
10987 return gdk_monitor_get_scale_factor (monitor);
10988 }
10989
10990 /**
10991 * gtk_widget_get_display:
10992 * @widget: a #GtkWidget
10993 *
10994 * Get the #GdkDisplay for the toplevel window associated with
10995 * this widget. This function can only be called after the widget
10996 * has been added to a widget hierarchy with a #GtkWindow at the top.
10997 *
10998 * In general, you should only create display specific
10999 * resources when a widget has been realized, and you should
11000 * free those resources when the widget is unrealized.
11001 *
11002 * Returns: (transfer none): the #GdkDisplay for the toplevel for this widget.
11003 *
11004 * Since: 2.2
11005 **/
11006 GdkDisplay*
gtk_widget_get_display(GtkWidget * widget)11007 gtk_widget_get_display (GtkWidget *widget)
11008 {
11009 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
11010
11011 return gdk_screen_get_display (gtk_widget_get_screen (widget));
11012 }
11013
11014 /**
11015 * gtk_widget_get_root_window:
11016 * @widget: a #GtkWidget
11017 *
11018 * Get the root window where this widget is located. This function can
11019 * only be called after the widget has been added to a widget
11020 * hierarchy with #GtkWindow at the top.
11021 *
11022 * The root window is useful for such purposes as creating a popup
11023 * #GdkWindow associated with the window. In general, you should only
11024 * create display specific resources when a widget has been realized,
11025 * and you should free those resources when the widget is unrealized.
11026 *
11027 * Returns: (transfer none): the #GdkWindow root window for the toplevel for this widget.
11028 *
11029 * Since: 2.2
11030 *
11031 * Deprecated: 3.12: Use gdk_screen_get_root_window() instead
11032 */
11033 GdkWindow*
gtk_widget_get_root_window(GtkWidget * widget)11034 gtk_widget_get_root_window (GtkWidget *widget)
11035 {
11036 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
11037
11038 return gdk_screen_get_root_window (gtk_widget_get_screen (widget));
11039 }
11040
11041 /**
11042 * gtk_widget_child_focus:
11043 * @widget: a #GtkWidget
11044 * @direction: direction of focus movement
11045 *
11046 * This function is used by custom widget implementations; if you're
11047 * writing an app, you’d use gtk_widget_grab_focus() to move the focus
11048 * to a particular widget, and gtk_container_set_focus_chain() to
11049 * change the focus tab order. So you may want to investigate those
11050 * functions instead.
11051 *
11052 * gtk_widget_child_focus() is called by containers as the user moves
11053 * around the window using keyboard shortcuts. @direction indicates
11054 * what kind of motion is taking place (up, down, left, right, tab
11055 * forward, tab backward). gtk_widget_child_focus() emits the
11056 * #GtkWidget::focus signal; widgets override the default handler
11057 * for this signal in order to implement appropriate focus behavior.
11058 *
11059 * The default ::focus handler for a widget should return %TRUE if
11060 * moving in @direction left the focus on a focusable location inside
11061 * that widget, and %FALSE if moving in @direction moved the focus
11062 * outside the widget. If returning %TRUE, widgets normally
11063 * call gtk_widget_grab_focus() to place the focus accordingly;
11064 * if returning %FALSE, they don’t modify the current focus location.
11065 *
11066 * Returns: %TRUE if focus ended up inside @widget
11067 **/
11068 gboolean
gtk_widget_child_focus(GtkWidget * widget,GtkDirectionType direction)11069 gtk_widget_child_focus (GtkWidget *widget,
11070 GtkDirectionType direction)
11071 {
11072 gboolean return_val;
11073
11074 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11075
11076 if (!_gtk_widget_get_visible (widget) ||
11077 !gtk_widget_is_sensitive (widget))
11078 return FALSE;
11079
11080 /* child widgets must set CAN_FOCUS, containers
11081 * don't have to though.
11082 */
11083 if (!GTK_IS_CONTAINER (widget) &&
11084 !gtk_widget_get_can_focus (widget))
11085 return FALSE;
11086
11087 g_signal_emit (widget,
11088 widget_signals[FOCUS],
11089 0,
11090 direction, &return_val);
11091
11092 return return_val;
11093 }
11094
11095 /**
11096 * gtk_widget_keynav_failed:
11097 * @widget: a #GtkWidget
11098 * @direction: direction of focus movement
11099 *
11100 * This function should be called whenever keyboard navigation within
11101 * a single widget hits a boundary. The function emits the
11102 * #GtkWidget::keynav-failed signal on the widget and its return
11103 * value should be interpreted in a way similar to the return value of
11104 * gtk_widget_child_focus():
11105 *
11106 * When %TRUE is returned, stay in the widget, the failed keyboard
11107 * navigation is OK and/or there is nowhere we can/should move the
11108 * focus to.
11109 *
11110 * When %FALSE is returned, the caller should continue with keyboard
11111 * navigation outside the widget, e.g. by calling
11112 * gtk_widget_child_focus() on the widget’s toplevel.
11113 *
11114 * The default ::keynav-failed handler returns %FALSE for
11115 * %GTK_DIR_TAB_FORWARD and %GTK_DIR_TAB_BACKWARD. For the other
11116 * values of #GtkDirectionType it returns %TRUE.
11117 *
11118 * Whenever the default handler returns %TRUE, it also calls
11119 * gtk_widget_error_bell() to notify the user of the failed keyboard
11120 * navigation.
11121 *
11122 * A use case for providing an own implementation of ::keynav-failed
11123 * (either by connecting to it or by overriding it) would be a row of
11124 * #GtkEntry widgets where the user should be able to navigate the
11125 * entire row with the cursor keys, as e.g. known from user interfaces
11126 * that require entering license keys.
11127 *
11128 * Returns: %TRUE if stopping keyboard navigation is fine, %FALSE
11129 * if the emitting widget should try to handle the keyboard
11130 * navigation attempt in its parent container(s).
11131 *
11132 * Since: 2.12
11133 **/
11134 gboolean
gtk_widget_keynav_failed(GtkWidget * widget,GtkDirectionType direction)11135 gtk_widget_keynav_failed (GtkWidget *widget,
11136 GtkDirectionType direction)
11137 {
11138 gboolean return_val;
11139
11140 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11141
11142 g_signal_emit (widget, widget_signals[KEYNAV_FAILED], 0,
11143 direction, &return_val);
11144
11145 return return_val;
11146 }
11147
11148 /**
11149 * gtk_widget_error_bell:
11150 * @widget: a #GtkWidget
11151 *
11152 * Notifies the user about an input-related error on this widget.
11153 * If the #GtkSettings:gtk-error-bell setting is %TRUE, it calls
11154 * gdk_window_beep(), otherwise it does nothing.
11155 *
11156 * Note that the effect of gdk_window_beep() can be configured in many
11157 * ways, depending on the windowing backend and the desktop environment
11158 * or window manager that is used.
11159 *
11160 * Since: 2.12
11161 **/
11162 void
gtk_widget_error_bell(GtkWidget * widget)11163 gtk_widget_error_bell (GtkWidget *widget)
11164 {
11165 GtkWidgetPrivate *priv;
11166 GtkSettings* settings;
11167 gboolean beep;
11168
11169 g_return_if_fail (GTK_IS_WIDGET (widget));
11170
11171 priv = widget->priv;
11172
11173 settings = gtk_widget_get_settings (widget);
11174 if (!settings)
11175 return;
11176
11177 g_object_get (settings,
11178 "gtk-error-bell", &beep,
11179 NULL);
11180
11181 if (beep && priv->window)
11182 gdk_window_beep (priv->window);
11183 }
11184
11185 static void
gtk_widget_set_usize_internal(GtkWidget * widget,gint width,gint height)11186 gtk_widget_set_usize_internal (GtkWidget *widget,
11187 gint width,
11188 gint height)
11189 {
11190 GtkWidgetPrivate *priv = widget->priv;
11191 gboolean changed = FALSE;
11192
11193 g_object_freeze_notify (G_OBJECT (widget));
11194
11195 if (width > -2 && priv->width != width)
11196 {
11197 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_WIDTH_REQUEST]);
11198 priv->width = width;
11199 changed = TRUE;
11200 }
11201 if (height > -2 && priv->height != height)
11202 {
11203 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HEIGHT_REQUEST]);
11204 priv->height = height;
11205 changed = TRUE;
11206 }
11207
11208 if (_gtk_widget_get_visible (widget) && changed)
11209 {
11210 gtk_widget_queue_resize (widget);
11211 }
11212
11213 g_object_thaw_notify (G_OBJECT (widget));
11214 }
11215
11216 /**
11217 * gtk_widget_set_size_request:
11218 * @widget: a #GtkWidget
11219 * @width: width @widget should request, or -1 to unset
11220 * @height: height @widget should request, or -1 to unset
11221 *
11222 * Sets the minimum size of a widget; that is, the widget’s size
11223 * request will be at least @width by @height. You can use this
11224 * function to force a widget to be larger than it normally would be.
11225 *
11226 * In most cases, gtk_window_set_default_size() is a better choice for
11227 * toplevel windows than this function; setting the default size will
11228 * still allow users to shrink the window. Setting the size request
11229 * will force them to leave the window at least as large as the size
11230 * request. When dealing with window sizes,
11231 * gtk_window_set_geometry_hints() can be a useful function as well.
11232 *
11233 * Note the inherent danger of setting any fixed size - themes,
11234 * translations into other languages, different fonts, and user action
11235 * can all change the appropriate size for a given widget. So, it's
11236 * basically impossible to hardcode a size that will always be
11237 * correct.
11238 *
11239 * The size request of a widget is the smallest size a widget can
11240 * accept while still functioning well and drawing itself correctly.
11241 * However in some strange cases a widget may be allocated less than
11242 * its requested size, and in many cases a widget may be allocated more
11243 * space than it requested.
11244 *
11245 * If the size request in a given direction is -1 (unset), then
11246 * the “natural” size request of the widget will be used instead.
11247 *
11248 * The size request set here does not include any margin from the
11249 * #GtkWidget properties margin-left, margin-right, margin-top, and
11250 * margin-bottom, but it does include pretty much all other padding
11251 * or border properties set by any subclass of #GtkWidget.
11252 **/
11253 void
gtk_widget_set_size_request(GtkWidget * widget,gint width,gint height)11254 gtk_widget_set_size_request (GtkWidget *widget,
11255 gint width,
11256 gint height)
11257 {
11258 g_return_if_fail (GTK_IS_WIDGET (widget));
11259 g_return_if_fail (width >= -1);
11260 g_return_if_fail (height >= -1);
11261
11262 if (width == 0)
11263 width = 1;
11264 if (height == 0)
11265 height = 1;
11266
11267 gtk_widget_set_usize_internal (widget, width, height);
11268 }
11269
11270
11271 /**
11272 * gtk_widget_get_size_request:
11273 * @widget: a #GtkWidget
11274 * @width: (out) (allow-none): return location for width, or %NULL
11275 * @height: (out) (allow-none): return location for height, or %NULL
11276 *
11277 * Gets the size request that was explicitly set for the widget using
11278 * gtk_widget_set_size_request(). A value of -1 stored in @width or
11279 * @height indicates that that dimension has not been set explicitly
11280 * and the natural requisition of the widget will be used instead. See
11281 * gtk_widget_set_size_request(). To get the size a widget will
11282 * actually request, call gtk_widget_get_preferred_size() instead of
11283 * this function.
11284 **/
11285 void
gtk_widget_get_size_request(GtkWidget * widget,gint * width,gint * height)11286 gtk_widget_get_size_request (GtkWidget *widget,
11287 gint *width,
11288 gint *height)
11289 {
11290 g_return_if_fail (GTK_IS_WIDGET (widget));
11291
11292 if (width)
11293 *width = widget->priv->width;
11294
11295 if (height)
11296 *height = widget->priv->height;
11297 }
11298
11299 /*< private >
11300 * gtk_widget_has_size_request:
11301 * @widget: a #GtkWidget
11302 *
11303 * Returns if the widget has a size request set (anything besides -1 for height
11304 * or width)
11305 */
11306 gboolean
gtk_widget_has_size_request(GtkWidget * widget)11307 gtk_widget_has_size_request (GtkWidget *widget)
11308 {
11309 return !(widget->priv->width == -1 && widget->priv->height == -1);
11310 }
11311
11312 /**
11313 * gtk_widget_set_events:
11314 * @widget: a #GtkWidget
11315 * @events: event mask
11316 *
11317 * Sets the event mask (see #GdkEventMask) for a widget. The event
11318 * mask determines which events a widget will receive. Keep in mind
11319 * that different widgets have different default event masks, and by
11320 * changing the event mask you may disrupt a widget’s functionality,
11321 * so be careful. This function must be called while a widget is
11322 * unrealized. Consider gtk_widget_add_events() for widgets that are
11323 * already realized, or if you want to preserve the existing event
11324 * mask. This function can’t be used with widgets that have no window.
11325 * (See gtk_widget_get_has_window()). To get events on those widgets,
11326 * place them inside a #GtkEventBox and receive events on the event
11327 * box.
11328 **/
11329 void
gtk_widget_set_events(GtkWidget * widget,gint events)11330 gtk_widget_set_events (GtkWidget *widget,
11331 gint events)
11332 {
11333 gint e;
11334
11335 g_return_if_fail (GTK_IS_WIDGET (widget));
11336 g_return_if_fail (!_gtk_widget_get_realized (widget));
11337
11338 e = GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (widget), quark_event_mask));
11339 if (e != events)
11340 {
11341 g_object_set_qdata (G_OBJECT (widget), quark_event_mask,
11342 GINT_TO_POINTER (events));
11343 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_EVENTS]);
11344 }
11345 }
11346
11347 /**
11348 * gtk_widget_set_device_events:
11349 * @widget: a #GtkWidget
11350 * @device: a #GdkDevice
11351 * @events: event mask
11352 *
11353 * Sets the device event mask (see #GdkEventMask) for a widget. The event
11354 * mask determines which events a widget will receive from @device. Keep
11355 * in mind that different widgets have different default event masks, and by
11356 * changing the event mask you may disrupt a widget’s functionality,
11357 * so be careful. This function must be called while a widget is
11358 * unrealized. Consider gtk_widget_add_device_events() for widgets that are
11359 * already realized, or if you want to preserve the existing event
11360 * mask. This function can’t be used with windowless widgets (which return
11361 * %FALSE from gtk_widget_get_has_window());
11362 * to get events on those widgets, place them inside a #GtkEventBox
11363 * and receive events on the event box.
11364 *
11365 * Since: 3.0
11366 **/
11367 void
gtk_widget_set_device_events(GtkWidget * widget,GdkDevice * device,GdkEventMask events)11368 gtk_widget_set_device_events (GtkWidget *widget,
11369 GdkDevice *device,
11370 GdkEventMask events)
11371 {
11372 GHashTable *device_events;
11373
11374 g_return_if_fail (GTK_IS_WIDGET (widget));
11375 g_return_if_fail (GDK_IS_DEVICE (device));
11376 g_return_if_fail (!_gtk_widget_get_realized (widget));
11377
11378 device_events = g_object_get_qdata (G_OBJECT (widget), quark_device_event_mask);
11379
11380 if (G_UNLIKELY (!device_events))
11381 {
11382 device_events = g_hash_table_new (NULL, NULL);
11383 g_object_set_qdata_full (G_OBJECT (widget), quark_device_event_mask, device_events,
11384 (GDestroyNotify) g_hash_table_unref);
11385 }
11386
11387 g_hash_table_insert (device_events, device, GUINT_TO_POINTER (events));
11388 }
11389
11390 /**
11391 * gtk_widget_set_device_enabled:
11392 * @widget: a #GtkWidget
11393 * @device: a #GdkDevice
11394 * @enabled: whether to enable the device
11395 *
11396 * Enables or disables a #GdkDevice to interact with @widget
11397 * and all its children.
11398 *
11399 * It does so by descending through the #GdkWindow hierarchy
11400 * and enabling the same mask that is has for core events
11401 * (i.e. the one that gdk_window_get_events() returns).
11402 *
11403 * Since: 3.0
11404 */
11405 void
gtk_widget_set_device_enabled(GtkWidget * widget,GdkDevice * device,gboolean enabled)11406 gtk_widget_set_device_enabled (GtkWidget *widget,
11407 GdkDevice *device,
11408 gboolean enabled)
11409 {
11410 GList *enabled_devices;
11411
11412 g_return_if_fail (GTK_IS_WIDGET (widget));
11413 g_return_if_fail (GDK_IS_DEVICE (device));
11414
11415 enabled_devices = g_object_get_qdata (G_OBJECT (widget), quark_enabled_devices);
11416 enabled_devices = g_list_append (enabled_devices, device);
11417
11418 g_object_set_qdata_full (G_OBJECT (widget), quark_enabled_devices,
11419 enabled_devices, (GDestroyNotify) g_list_free);;
11420
11421 if (_gtk_widget_get_realized (widget))
11422 gtk_widget_set_device_enabled_internal (widget, device, TRUE, enabled);
11423 }
11424
11425 /**
11426 * gtk_widget_get_device_enabled:
11427 * @widget: a #GtkWidget
11428 * @device: a #GdkDevice
11429 *
11430 * Returns whether @device can interact with @widget and its
11431 * children. See gtk_widget_set_device_enabled().
11432 *
11433 * Returns: %TRUE is @device is enabled for @widget
11434 *
11435 * Since: 3.0
11436 */
11437 gboolean
gtk_widget_get_device_enabled(GtkWidget * widget,GdkDevice * device)11438 gtk_widget_get_device_enabled (GtkWidget *widget,
11439 GdkDevice *device)
11440 {
11441 GList *enabled_devices;
11442
11443 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11444 g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
11445
11446 enabled_devices = g_object_get_qdata (G_OBJECT (widget), quark_enabled_devices);
11447
11448 return g_list_find (enabled_devices, device) != NULL;
11449 }
11450
11451 static void
gtk_widget_add_events_internal_list(GtkWidget * widget,GdkDevice * device,GdkEventMask events,GList * window_list)11452 gtk_widget_add_events_internal_list (GtkWidget *widget,
11453 GdkDevice *device,
11454 GdkEventMask events,
11455 GList *window_list)
11456 {
11457 GdkEventMask controllers_mask;
11458 GList *l;
11459
11460 controllers_mask = _gtk_widget_get_controllers_evmask (widget);
11461
11462 for (l = window_list; l != NULL; l = l->next)
11463 {
11464 GdkWindow *window = l->data;
11465 GtkWidget *window_widget;
11466
11467 gdk_window_get_user_data (window, (gpointer *)&window_widget);
11468 if (window_widget == widget)
11469 {
11470 GList *children;
11471
11472 if (device)
11473 gdk_window_set_device_events (window, device,
11474 gdk_window_get_events (window)
11475 | events
11476 | controllers_mask);
11477 else
11478 gdk_window_set_events (window,
11479 gdk_window_get_events (window)
11480 | events
11481 | controllers_mask);
11482
11483 children = gdk_window_peek_children (window);
11484 gtk_widget_add_events_internal_list (widget, device, events, children);
11485 }
11486 }
11487 }
11488
11489 static void
gtk_widget_add_events_internal(GtkWidget * widget,GdkDevice * device,gint events)11490 gtk_widget_add_events_internal (GtkWidget *widget,
11491 GdkDevice *device,
11492 gint events)
11493 {
11494 GtkWidgetPrivate *priv = widget->priv;
11495 GList *window_list;
11496 GList win;
11497
11498 if (!_gtk_widget_get_has_window (widget))
11499 window_list = gdk_window_peek_children (priv->window);
11500 else
11501 {
11502 win.data = priv->window;
11503 win.prev = win.next = NULL;
11504 window_list = &win;
11505 }
11506
11507 gtk_widget_add_events_internal_list (widget, device, events, window_list);
11508 }
11509
11510 /**
11511 * gtk_widget_add_events:
11512 * @widget: a #GtkWidget
11513 * @events: an event mask, see #GdkEventMask
11514 *
11515 * Adds the events in the bitfield @events to the event mask for
11516 * @widget. See gtk_widget_set_events() and the
11517 * [input handling overview][event-masks] for details.
11518 **/
11519 void
gtk_widget_add_events(GtkWidget * widget,gint events)11520 gtk_widget_add_events (GtkWidget *widget,
11521 gint events)
11522 {
11523 gint old_events;
11524
11525 g_return_if_fail (GTK_IS_WIDGET (widget));
11526
11527 old_events = GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (widget), quark_event_mask));
11528 g_object_set_qdata (G_OBJECT (widget), quark_event_mask,
11529 GINT_TO_POINTER (old_events | events));
11530
11531 if (_gtk_widget_get_realized (widget))
11532 {
11533 gtk_widget_add_events_internal (widget, NULL, events);
11534 gtk_widget_update_devices_mask (widget, FALSE);
11535 }
11536
11537 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_EVENTS]);
11538 }
11539
11540 /**
11541 * gtk_widget_add_device_events:
11542 * @widget: a #GtkWidget
11543 * @device: a #GdkDevice
11544 * @events: an event mask, see #GdkEventMask
11545 *
11546 * Adds the device events in the bitfield @events to the event mask for
11547 * @widget. See gtk_widget_set_device_events() for details.
11548 *
11549 * Since: 3.0
11550 **/
11551 void
gtk_widget_add_device_events(GtkWidget * widget,GdkDevice * device,GdkEventMask events)11552 gtk_widget_add_device_events (GtkWidget *widget,
11553 GdkDevice *device,
11554 GdkEventMask events)
11555 {
11556 GdkEventMask old_events;
11557 GHashTable *device_events;
11558
11559 g_return_if_fail (GTK_IS_WIDGET (widget));
11560 g_return_if_fail (GDK_IS_DEVICE (device));
11561
11562 old_events = gtk_widget_get_device_events (widget, device);
11563
11564 device_events = g_object_get_qdata (G_OBJECT (widget), quark_device_event_mask);
11565
11566 if (G_UNLIKELY (!device_events))
11567 {
11568 device_events = g_hash_table_new (NULL, NULL);
11569 g_object_set_qdata_full (G_OBJECT (widget), quark_device_event_mask, device_events,
11570 (GDestroyNotify) g_hash_table_unref);
11571 }
11572
11573 g_hash_table_insert (device_events, device,
11574 GUINT_TO_POINTER (old_events | events));
11575
11576 if (_gtk_widget_get_realized (widget))
11577 gtk_widget_add_events_internal (widget, device, events);
11578
11579 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_EVENTS]);
11580 }
11581
11582 /**
11583 * gtk_widget_get_toplevel:
11584 * @widget: a #GtkWidget
11585 *
11586 * This function returns the topmost widget in the container hierarchy
11587 * @widget is a part of. If @widget has no parent widgets, it will be
11588 * returned as the topmost widget. No reference will be added to the
11589 * returned widget; it should not be unreferenced.
11590 *
11591 * Note the difference in behavior vs. gtk_widget_get_ancestor();
11592 * `gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW)`
11593 * would return
11594 * %NULL if @widget wasn’t inside a toplevel window, and if the
11595 * window was inside a #GtkWindow-derived widget which was in turn
11596 * inside the toplevel #GtkWindow. While the second case may
11597 * seem unlikely, it actually happens when a #GtkPlug is embedded
11598 * inside a #GtkSocket within the same application.
11599 *
11600 * To reliably find the toplevel #GtkWindow, use
11601 * gtk_widget_get_toplevel() and call GTK_IS_WINDOW()
11602 * on the result. For instance, to get the title of a widget's toplevel
11603 * window, one might use:
11604 * |[<!-- language="C" -->
11605 * static const char *
11606 * get_widget_toplevel_title (GtkWidget *widget)
11607 * {
11608 * GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
11609 * if (GTK_IS_WINDOW (toplevel))
11610 * {
11611 * return gtk_window_get_title (GTK_WINDOW (toplevel));
11612 * }
11613 *
11614 * return NULL;
11615 * }
11616 * ]|
11617 *
11618 * Returns: (transfer none): the topmost ancestor of @widget, or @widget itself
11619 * if there’s no ancestor.
11620 **/
11621 GtkWidget*
gtk_widget_get_toplevel(GtkWidget * widget)11622 gtk_widget_get_toplevel (GtkWidget *widget)
11623 {
11624 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
11625
11626 while (widget->priv->parent)
11627 widget = widget->priv->parent;
11628
11629 return widget;
11630 }
11631
11632 /**
11633 * gtk_widget_get_ancestor:
11634 * @widget: a #GtkWidget
11635 * @widget_type: ancestor type
11636 *
11637 * Gets the first ancestor of @widget with type @widget_type. For example,
11638 * `gtk_widget_get_ancestor (widget, GTK_TYPE_BOX)` gets
11639 * the first #GtkBox that’s an ancestor of @widget. No reference will be
11640 * added to the returned widget; it should not be unreferenced. See note
11641 * about checking for a toplevel #GtkWindow in the docs for
11642 * gtk_widget_get_toplevel().
11643 *
11644 * Note that unlike gtk_widget_is_ancestor(), gtk_widget_get_ancestor()
11645 * considers @widget to be an ancestor of itself.
11646 *
11647 * Returns: (transfer none) (nullable): the ancestor widget, or %NULL if not found
11648 **/
11649 GtkWidget*
gtk_widget_get_ancestor(GtkWidget * widget,GType widget_type)11650 gtk_widget_get_ancestor (GtkWidget *widget,
11651 GType widget_type)
11652 {
11653 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
11654
11655 while (widget && !g_type_is_a (G_OBJECT_TYPE (widget), widget_type))
11656 widget = widget->priv->parent;
11657
11658 if (!(widget && g_type_is_a (G_OBJECT_TYPE (widget), widget_type)))
11659 return NULL;
11660
11661 return widget;
11662 }
11663
11664 /**
11665 * gtk_widget_set_visual:
11666 * @widget: a #GtkWidget
11667 * @visual: (allow-none): visual to be used or %NULL to unset a previous one
11668 *
11669 * Sets the visual that should be used for by widget and its children for
11670 * creating #GdkWindows. The visual must be on the same #GdkScreen as
11671 * returned by gtk_widget_get_screen(), so handling the
11672 * #GtkWidget::screen-changed signal is necessary.
11673 *
11674 * Setting a new @visual will not cause @widget to recreate its windows,
11675 * so you should call this function before @widget is realized.
11676 **/
11677 void
gtk_widget_set_visual(GtkWidget * widget,GdkVisual * visual)11678 gtk_widget_set_visual (GtkWidget *widget,
11679 GdkVisual *visual)
11680 {
11681 g_return_if_fail (GTK_IS_WIDGET (widget));
11682 g_return_if_fail (visual == NULL || GDK_IS_VISUAL (visual));
11683
11684 if (visual)
11685 g_return_if_fail (gtk_widget_get_screen (widget) == gdk_visual_get_screen (visual));
11686
11687 g_object_set_qdata_full (G_OBJECT (widget),
11688 quark_visual,
11689 visual ? g_object_ref (visual) : NULL,
11690 g_object_unref);
11691 }
11692
11693 /**
11694 * gtk_widget_get_visual:
11695 * @widget: a #GtkWidget
11696 *
11697 * Gets the visual that will be used to render @widget.
11698 *
11699 * Returns: (transfer none): the visual for @widget
11700 **/
11701 GdkVisual*
gtk_widget_get_visual(GtkWidget * widget)11702 gtk_widget_get_visual (GtkWidget *widget)
11703 {
11704 GtkWidget *w;
11705 GdkVisual *visual;
11706 GdkScreen *screen;
11707
11708 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
11709
11710 if (!_gtk_widget_get_has_window (widget) &&
11711 widget->priv->window)
11712 return gdk_window_get_visual (widget->priv->window);
11713
11714 screen = gtk_widget_get_screen (widget);
11715
11716 for (w = widget; w != NULL; w = w->priv->parent)
11717 {
11718 visual = g_object_get_qdata (G_OBJECT (w), quark_visual);
11719 if (visual)
11720 {
11721 if (gdk_visual_get_screen (visual) == screen)
11722 return visual;
11723
11724 g_warning ("Ignoring visual set on widget '%s' that is not on the correct screen.",
11725 gtk_widget_get_name (widget));
11726 }
11727 }
11728
11729 return gdk_screen_get_system_visual (screen);
11730 }
11731
11732 /**
11733 * gtk_widget_get_settings:
11734 * @widget: a #GtkWidget
11735 *
11736 * Gets the settings object holding the settings used for this widget.
11737 *
11738 * Note that this function can only be called when the #GtkWidget
11739 * is attached to a toplevel, since the settings object is specific
11740 * to a particular #GdkScreen.
11741 *
11742 * Returns: (transfer none): the relevant #GtkSettings object
11743 */
11744 GtkSettings*
gtk_widget_get_settings(GtkWidget * widget)11745 gtk_widget_get_settings (GtkWidget *widget)
11746 {
11747 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
11748
11749 return gtk_settings_get_for_screen (gtk_widget_get_screen (widget));
11750 }
11751
11752 /**
11753 * gtk_widget_get_events:
11754 * @widget: a #GtkWidget
11755 *
11756 * Returns the event mask (see #GdkEventMask) for the widget. These are the
11757 * events that the widget will receive.
11758 *
11759 * Note: Internally, the widget event mask will be the logical OR of the event
11760 * mask set through gtk_widget_set_events() or gtk_widget_add_events(), and the
11761 * event mask necessary to cater for every #GtkEventController created for the
11762 * widget.
11763 *
11764 * Returns: event mask for @widget
11765 **/
11766 gint
gtk_widget_get_events(GtkWidget * widget)11767 gtk_widget_get_events (GtkWidget *widget)
11768 {
11769 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
11770
11771 return GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (widget), quark_event_mask)) |
11772 _gtk_widget_get_controllers_evmask (widget);
11773 }
11774
11775 /**
11776 * gtk_widget_get_device_events:
11777 * @widget: a #GtkWidget
11778 * @device: a #GdkDevice
11779 *
11780 * Returns the events mask for the widget corresponding to an specific device. These
11781 * are the events that the widget will receive when @device operates on it.
11782 *
11783 * Returns: device event mask for @widget
11784 *
11785 * Since: 3.0
11786 **/
11787 GdkEventMask
gtk_widget_get_device_events(GtkWidget * widget,GdkDevice * device)11788 gtk_widget_get_device_events (GtkWidget *widget,
11789 GdkDevice *device)
11790 {
11791 GHashTable *device_events;
11792
11793 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
11794 g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
11795
11796 device_events = g_object_get_qdata (G_OBJECT (widget), quark_device_event_mask);
11797
11798 if (!device_events)
11799 return 0;
11800
11801 return GPOINTER_TO_UINT (g_hash_table_lookup (device_events, device));
11802 }
11803
11804 /**
11805 * gtk_widget_get_pointer:
11806 * @widget: a #GtkWidget
11807 * @x: (out) (allow-none): return location for the X coordinate, or %NULL
11808 * @y: (out) (allow-none): return location for the Y coordinate, or %NULL
11809 *
11810 * Obtains the location of the mouse pointer in widget coordinates.
11811 * Widget coordinates are a bit odd; for historical reasons, they are
11812 * defined as @widget->window coordinates for widgets that return %TRUE for
11813 * gtk_widget_get_has_window(); and are relative to @widget->allocation.x,
11814 * @widget->allocation.y otherwise.
11815 *
11816 * Deprecated: 3.4: Use gdk_window_get_device_position() instead.
11817 **/
11818 void
gtk_widget_get_pointer(GtkWidget * widget,gint * x,gint * y)11819 gtk_widget_get_pointer (GtkWidget *widget,
11820 gint *x,
11821 gint *y)
11822 {
11823 GtkWidgetPrivate *priv;
11824
11825 g_return_if_fail (GTK_IS_WIDGET (widget));
11826
11827 priv = widget->priv;
11828
11829 if (x)
11830 *x = -1;
11831 if (y)
11832 *y = -1;
11833
11834 if (_gtk_widget_get_realized (widget))
11835 {
11836 GdkSeat *seat;
11837
11838 seat = gdk_display_get_default_seat (gtk_widget_get_display (widget));
11839 gdk_window_get_device_position (priv->window,
11840 gdk_seat_get_pointer (seat),
11841 x, y, NULL);
11842
11843 if (!_gtk_widget_get_has_window (widget))
11844 {
11845 if (x)
11846 *x -= priv->allocation.x;
11847 if (y)
11848 *y -= priv->allocation.y;
11849 }
11850 }
11851 }
11852
11853 /**
11854 * gtk_widget_is_ancestor:
11855 * @widget: a #GtkWidget
11856 * @ancestor: another #GtkWidget
11857 *
11858 * Determines whether @widget is somewhere inside @ancestor, possibly with
11859 * intermediate containers.
11860 *
11861 * Returns: %TRUE if @ancestor contains @widget as a child,
11862 * grandchild, great grandchild, etc.
11863 **/
11864 gboolean
gtk_widget_is_ancestor(GtkWidget * widget,GtkWidget * ancestor)11865 gtk_widget_is_ancestor (GtkWidget *widget,
11866 GtkWidget *ancestor)
11867 {
11868 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
11869 g_return_val_if_fail (ancestor != NULL, FALSE);
11870
11871 while (widget)
11872 {
11873 if (widget->priv->parent == ancestor)
11874 return TRUE;
11875 widget = widget->priv->parent;
11876 }
11877
11878 return FALSE;
11879 }
11880
11881 static GQuark quark_composite_name = 0;
11882
11883 /**
11884 * gtk_widget_set_composite_name:
11885 * @widget: a #GtkWidget.
11886 * @name: the name to set
11887 *
11888 * Sets a widgets composite name. The widget must be
11889 * a composite child of its parent; see gtk_widget_push_composite_child().
11890 *
11891 * Deprecated: 3.10: Use gtk_widget_class_set_template(), or don’t use this API at all.
11892 **/
11893 void
gtk_widget_set_composite_name(GtkWidget * widget,const gchar * name)11894 gtk_widget_set_composite_name (GtkWidget *widget,
11895 const gchar *name)
11896 {
11897 g_return_if_fail (GTK_IS_WIDGET (widget));
11898 g_return_if_fail (widget->priv->composite_child);
11899 g_return_if_fail (name != NULL);
11900
11901 if (!quark_composite_name)
11902 quark_composite_name = g_quark_from_static_string ("gtk-composite-name");
11903
11904 g_object_set_qdata_full (G_OBJECT (widget),
11905 quark_composite_name,
11906 g_strdup (name),
11907 g_free);
11908 }
11909
11910 /**
11911 * gtk_widget_get_composite_name:
11912 * @widget: a #GtkWidget
11913 *
11914 * Obtains the composite name of a widget.
11915 *
11916 * Returns: the composite name of @widget, or %NULL if @widget is not
11917 * a composite child. The string should be freed when it is no
11918 * longer needed.
11919 *
11920 * Deprecated: 3.10: Use gtk_widget_class_set_template(), or don’t use this API at all.
11921 **/
11922 gchar*
gtk_widget_get_composite_name(GtkWidget * widget)11923 gtk_widget_get_composite_name (GtkWidget *widget)
11924 {
11925 GtkWidgetPrivate *priv;
11926
11927 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
11928
11929 priv = widget->priv;
11930
11931 if (widget->priv->composite_child && priv->parent)
11932 return _gtk_container_child_composite_name (GTK_CONTAINER (priv->parent),
11933 widget);
11934 else
11935 return NULL;
11936 }
11937
11938 /**
11939 * gtk_widget_push_composite_child:
11940 *
11941 * Makes all newly-created widgets as composite children until
11942 * the corresponding gtk_widget_pop_composite_child() call.
11943 *
11944 * A composite child is a child that’s an implementation detail of the
11945 * container it’s inside and should not be visible to people using the
11946 * container. Composite children aren’t treated differently by GTK+ (but
11947 * see gtk_container_foreach() vs. gtk_container_forall()), but e.g. GUI
11948 * builders might want to treat them in a different way.
11949 *
11950 * Deprecated: 3.10: This API never really worked well and was mostly unused, now
11951 * we have a more complete mechanism for composite children, see gtk_widget_class_set_template().
11952 **/
11953 void
gtk_widget_push_composite_child(void)11954 gtk_widget_push_composite_child (void)
11955 {
11956 composite_child_stack++;
11957 }
11958
11959 /**
11960 * gtk_widget_pop_composite_child:
11961 *
11962 * Cancels the effect of a previous call to gtk_widget_push_composite_child().
11963 *
11964 * Deprecated: 3.10: Use gtk_widget_class_set_template(), or don’t use this API at all.
11965 **/
11966 void
gtk_widget_pop_composite_child(void)11967 gtk_widget_pop_composite_child (void)
11968 {
11969 if (composite_child_stack)
11970 composite_child_stack--;
11971 }
11972
11973 static void
gtk_widget_emit_direction_changed(GtkWidget * widget,GtkTextDirection old_dir)11974 gtk_widget_emit_direction_changed (GtkWidget *widget,
11975 GtkTextDirection old_dir)
11976 {
11977 GtkTextDirection direction;
11978 GtkStateFlags state;
11979
11980 gtk_widget_update_pango_context (widget);
11981
11982 direction = _gtk_widget_get_direction (widget);
11983
11984 switch (direction)
11985 {
11986 case GTK_TEXT_DIR_LTR:
11987 state = GTK_STATE_FLAG_DIR_LTR;
11988 break;
11989
11990 case GTK_TEXT_DIR_RTL:
11991 state = GTK_STATE_FLAG_DIR_RTL;
11992 break;
11993
11994 case GTK_TEXT_DIR_NONE:
11995 default:
11996 g_assert_not_reached ();
11997 break;
11998 }
11999
12000 gtk_widget_update_state_flags (widget,
12001 state,
12002 state ^ (GTK_STATE_FLAG_DIR_LTR | GTK_STATE_FLAG_DIR_RTL));
12003
12004 g_signal_emit (widget, widget_signals[DIRECTION_CHANGED], 0, old_dir);
12005 }
12006
12007 /**
12008 * gtk_widget_set_direction:
12009 * @widget: a #GtkWidget
12010 * @dir: the new direction
12011 *
12012 * Sets the reading direction on a particular widget. This direction
12013 * controls the primary direction for widgets containing text,
12014 * and also the direction in which the children of a container are
12015 * packed. The ability to set the direction is present in order
12016 * so that correct localization into languages with right-to-left
12017 * reading directions can be done. Generally, applications will
12018 * let the default reading direction present, except for containers
12019 * where the containers are arranged in an order that is explicitly
12020 * visual rather than logical (such as buttons for text justification).
12021 *
12022 * If the direction is set to %GTK_TEXT_DIR_NONE, then the value
12023 * set by gtk_widget_set_default_direction() will be used.
12024 **/
12025 void
gtk_widget_set_direction(GtkWidget * widget,GtkTextDirection dir)12026 gtk_widget_set_direction (GtkWidget *widget,
12027 GtkTextDirection dir)
12028 {
12029 GtkTextDirection old_dir;
12030
12031 g_return_if_fail (GTK_IS_WIDGET (widget));
12032 g_return_if_fail (dir >= GTK_TEXT_DIR_NONE && dir <= GTK_TEXT_DIR_RTL);
12033
12034 old_dir = _gtk_widget_get_direction (widget);
12035
12036 widget->priv->direction = dir;
12037
12038 if (old_dir != _gtk_widget_get_direction (widget))
12039 gtk_widget_emit_direction_changed (widget, old_dir);
12040 }
12041
12042 /**
12043 * gtk_widget_get_direction:
12044 * @widget: a #GtkWidget
12045 *
12046 * Gets the reading direction for a particular widget. See
12047 * gtk_widget_set_direction().
12048 *
12049 * Returns: the reading direction for the widget.
12050 **/
12051 GtkTextDirection
gtk_widget_get_direction(GtkWidget * widget)12052 gtk_widget_get_direction (GtkWidget *widget)
12053 {
12054 g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_TEXT_DIR_LTR);
12055
12056 if (widget->priv->direction == GTK_TEXT_DIR_NONE)
12057 return gtk_default_direction;
12058 else
12059 return widget->priv->direction;
12060 }
12061
12062 static void
gtk_widget_set_default_direction_recurse(GtkWidget * widget,gpointer data)12063 gtk_widget_set_default_direction_recurse (GtkWidget *widget, gpointer data)
12064 {
12065 GtkTextDirection old_dir = GPOINTER_TO_UINT (data);
12066
12067 g_object_ref (widget);
12068
12069 if (widget->priv->direction == GTK_TEXT_DIR_NONE)
12070 gtk_widget_emit_direction_changed (widget, old_dir);
12071
12072 if (GTK_IS_CONTAINER (widget))
12073 gtk_container_forall (GTK_CONTAINER (widget),
12074 gtk_widget_set_default_direction_recurse,
12075 data);
12076
12077 g_object_unref (widget);
12078 }
12079
12080 /**
12081 * gtk_widget_set_default_direction:
12082 * @dir: the new default direction. This cannot be
12083 * %GTK_TEXT_DIR_NONE.
12084 *
12085 * Sets the default reading direction for widgets where the
12086 * direction has not been explicitly set by gtk_widget_set_direction().
12087 **/
12088 void
gtk_widget_set_default_direction(GtkTextDirection dir)12089 gtk_widget_set_default_direction (GtkTextDirection dir)
12090 {
12091 g_return_if_fail (dir == GTK_TEXT_DIR_RTL || dir == GTK_TEXT_DIR_LTR);
12092
12093 if (dir != gtk_default_direction)
12094 {
12095 GList *toplevels, *tmp_list;
12096 GtkTextDirection old_dir = gtk_default_direction;
12097
12098 gtk_default_direction = dir;
12099
12100 tmp_list = toplevels = gtk_window_list_toplevels ();
12101 g_list_foreach (toplevels, (GFunc)g_object_ref, NULL);
12102
12103 while (tmp_list)
12104 {
12105 gtk_widget_set_default_direction_recurse (tmp_list->data,
12106 GUINT_TO_POINTER (old_dir));
12107 g_object_unref (tmp_list->data);
12108 tmp_list = tmp_list->next;
12109 }
12110
12111 g_list_free (toplevels);
12112 }
12113 }
12114
12115 /**
12116 * gtk_widget_get_default_direction:
12117 *
12118 * Obtains the current default reading direction. See
12119 * gtk_widget_set_default_direction().
12120 *
12121 * Returns: the current default direction.
12122 **/
12123 GtkTextDirection
gtk_widget_get_default_direction(void)12124 gtk_widget_get_default_direction (void)
12125 {
12126 return gtk_default_direction;
12127 }
12128
12129 static void
gtk_widget_constructed(GObject * object)12130 gtk_widget_constructed (GObject *object)
12131 {
12132 GtkWidget *widget = GTK_WIDGET (object);
12133 GtkWidgetPath *path;
12134
12135 /* As strange as it may seem, this may happen on object construction.
12136 * init() implementations of parent types may eventually call this function,
12137 * each with its corresponding GType, which could leave a child
12138 * implementation with a wrong widget type in the widget path
12139 */
12140 path = (GtkWidgetPath*)g_object_get_qdata (object, quark_widget_path);
12141 if (path && G_OBJECT_TYPE (widget) != gtk_widget_path_get_object_type (path))
12142 g_object_set_qdata (object, quark_widget_path, NULL);
12143
12144 G_OBJECT_CLASS (gtk_widget_parent_class)->constructed (object);
12145 }
12146
12147 static void
gtk_widget_dispose(GObject * object)12148 gtk_widget_dispose (GObject *object)
12149 {
12150 GtkWidget *widget = GTK_WIDGET (object);
12151 GtkWidgetPrivate *priv = widget->priv;
12152 GSList *sizegroups;
12153
12154 if (priv->parent)
12155 gtk_container_remove (GTK_CONTAINER (priv->parent), widget);
12156 else if (_gtk_widget_get_visible (widget))
12157 gtk_widget_hide (widget);
12158
12159 priv->visible = FALSE;
12160 if (_gtk_widget_get_realized (widget))
12161 gtk_widget_unrealize (widget);
12162
12163 if (!priv->in_destruction)
12164 {
12165 priv->in_destruction = TRUE;
12166 g_signal_emit (object, widget_signals[DESTROY], 0);
12167 priv->in_destruction = FALSE;
12168 }
12169
12170 sizegroups = _gtk_widget_get_sizegroups (widget);
12171 while (sizegroups)
12172 {
12173 GtkSizeGroup *size_group;
12174
12175 size_group = sizegroups->data;
12176 sizegroups = sizegroups->next;
12177 gtk_size_group_remove_widget (size_group, widget);
12178 }
12179
12180 g_object_set_qdata (object, quark_action_muxer, NULL);
12181
12182 while (priv->attached_windows)
12183 gtk_window_set_attached_to (priv->attached_windows->data, NULL);
12184
12185 G_OBJECT_CLASS (gtk_widget_parent_class)->dispose (object);
12186 }
12187
12188 #ifdef G_ENABLE_CONSISTENCY_CHECKS
12189 typedef struct {
12190 AutomaticChildClass *child_class;
12191 GType widget_type;
12192 GObject *object;
12193 gboolean did_finalize;
12194 } FinalizeAssertion;
12195
12196 static void
finalize_assertion_weak_ref(gpointer data,GObject * where_the_object_was)12197 finalize_assertion_weak_ref (gpointer data,
12198 GObject *where_the_object_was)
12199 {
12200 FinalizeAssertion *assertion = (FinalizeAssertion *)data;
12201 assertion->did_finalize = TRUE;
12202 }
12203
12204 static FinalizeAssertion *
finalize_assertion_new(GtkWidget * widget,GType widget_type,AutomaticChildClass * child_class)12205 finalize_assertion_new (GtkWidget *widget,
12206 GType widget_type,
12207 AutomaticChildClass *child_class)
12208 {
12209 FinalizeAssertion *assertion = NULL;
12210 GObject *object;
12211
12212 object = gtk_widget_get_template_child (widget, widget_type, child_class->name);
12213
12214 /* We control the hash table entry, the object should never be NULL
12215 */
12216 g_assert (object);
12217 if (!G_IS_OBJECT (object))
12218 g_critical ("Automated component '%s' of class '%s' seems to have been prematurely finalized",
12219 child_class->name, g_type_name (widget_type));
12220 else
12221 {
12222 assertion = g_slice_new0 (FinalizeAssertion);
12223 assertion->child_class = child_class;
12224 assertion->widget_type = widget_type;
12225 assertion->object = object;
12226
12227 g_object_weak_ref (object, finalize_assertion_weak_ref, assertion);
12228 }
12229
12230 return assertion;
12231 }
12232
12233 static GSList *
build_finalize_assertion_list(GtkWidget * widget)12234 build_finalize_assertion_list (GtkWidget *widget)
12235 {
12236 GType class_type;
12237 GtkWidgetClass *class;
12238 GSList *l, *list = NULL;
12239
12240 for (class = GTK_WIDGET_GET_CLASS (widget);
12241 GTK_IS_WIDGET_CLASS (class);
12242 class = g_type_class_peek_parent (class))
12243 {
12244 if (!class->priv->template)
12245 continue;
12246
12247 class_type = G_OBJECT_CLASS_TYPE (class);
12248
12249 for (l = class->priv->template->children; l; l = l->next)
12250 {
12251 AutomaticChildClass *child_class = l->data;
12252 FinalizeAssertion *assertion;
12253
12254 assertion = finalize_assertion_new (widget, class_type, child_class);
12255 list = g_slist_prepend (list, assertion);
12256 }
12257 }
12258
12259 return list;
12260 }
12261 #endif /* G_ENABLE_CONSISTENCY_CHECKS */
12262
12263 static void
gtk_widget_real_destroy(GtkWidget * object)12264 gtk_widget_real_destroy (GtkWidget *object)
12265 {
12266 /* gtk_object_destroy() will already hold a refcount on object */
12267 GtkWidget *widget = GTK_WIDGET (object);
12268 GtkWidgetPrivate *priv = widget->priv;
12269
12270 if (g_object_get_qdata (G_OBJECT (widget), quark_auto_children))
12271 {
12272 GtkWidgetClass *class;
12273 GSList *l;
12274
12275 #ifdef G_ENABLE_CONSISTENCY_CHECKS
12276 GSList *assertions = NULL;
12277
12278 /* Note, GTK_WIDGET_ASSERT_COMPONENTS is very useful
12279 * to catch ref counting bugs, but can only be used in
12280 * test cases which simply create and destroy a composite
12281 * widget.
12282 *
12283 * This is because some API can expose components explicitly,
12284 * and so we cannot assert that a component is expected to finalize
12285 * in a full application ecosystem.
12286 */
12287 if (g_getenv ("GTK_WIDGET_ASSERT_COMPONENTS") != NULL)
12288 assertions = build_finalize_assertion_list (widget);
12289 #endif /* G_ENABLE_CONSISTENCY_CHECKS */
12290
12291 /* Release references to all automated children */
12292 g_object_set_qdata (G_OBJECT (widget), quark_auto_children, NULL);
12293
12294 #ifdef G_ENABLE_CONSISTENCY_CHECKS
12295 for (l = assertions; l; l = l->next)
12296 {
12297 FinalizeAssertion *assertion = l->data;
12298
12299 if (!assertion->did_finalize)
12300 g_critical ("Automated component '%s' of class '%s' did not finalize in gtk_widget_destroy(). "
12301 "Current reference count is %d",
12302 assertion->child_class->name,
12303 g_type_name (assertion->widget_type),
12304 assertion->object->ref_count);
12305
12306 g_slice_free (FinalizeAssertion, assertion);
12307 }
12308 g_slist_free (assertions);
12309 #endif /* G_ENABLE_CONSISTENCY_CHECKS */
12310
12311 /* Set any automatic private data pointers to NULL */
12312 for (class = GTK_WIDGET_GET_CLASS (widget);
12313 GTK_IS_WIDGET_CLASS (class);
12314 class = g_type_class_peek_parent (class))
12315 {
12316 if (!class->priv->template)
12317 continue;
12318
12319 for (l = class->priv->template->children; l; l = l->next)
12320 {
12321 AutomaticChildClass *child_class = l->data;
12322
12323 if (child_class->offset != 0)
12324 {
12325 gpointer field_p;
12326
12327 /* Nullify instance private data for internal children */
12328 field_p = G_STRUCT_MEMBER_P (widget, child_class->offset);
12329 (* (gpointer *) field_p) = NULL;
12330 }
12331 }
12332 }
12333 }
12334
12335 if (priv->accessible)
12336 {
12337 gtk_accessible_set_widget (GTK_ACCESSIBLE (priv->accessible), NULL);
12338 g_object_unref (priv->accessible);
12339 priv->accessible = NULL;
12340 }
12341
12342 /* wipe accelerator closures (keep order) */
12343 g_object_set_qdata (G_OBJECT (widget), quark_accel_path, NULL);
12344 g_object_set_qdata (G_OBJECT (widget), quark_accel_closures, NULL);
12345
12346 /* Callers of add_mnemonic_label() should disconnect on ::destroy */
12347 g_object_set_qdata (G_OBJECT (widget), quark_mnemonic_labels, NULL);
12348
12349 gtk_grab_remove (widget);
12350
12351 destroy_tick_callbacks (widget);
12352
12353 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
12354 if (priv->style)
12355 g_object_unref (priv->style);
12356 priv->style = gtk_widget_get_default_style ();
12357 g_object_ref (priv->style);
12358 G_GNUC_END_IGNORE_DEPRECATIONS;
12359 }
12360
12361 static void
gtk_widget_finalize(GObject * object)12362 gtk_widget_finalize (GObject *object)
12363 {
12364 GtkWidget *widget = GTK_WIDGET (object);
12365 GtkWidgetPrivate *priv = widget->priv;
12366 GList *l;
12367
12368 gtk_grab_remove (widget);
12369
12370 g_clear_object (&priv->style);
12371
12372 g_free (priv->name);
12373
12374 g_clear_object (&priv->accessible);
12375
12376 gtk_widget_clear_path (widget);
12377
12378 gtk_css_widget_node_widget_destroyed (GTK_CSS_WIDGET_NODE (priv->cssnode));
12379 g_object_unref (priv->cssnode);
12380
12381 g_clear_object (&priv->context);
12382
12383 _gtk_size_request_cache_free (&priv->requests);
12384
12385 for (l = priv->event_controllers; l; l = l->next)
12386 {
12387 EventControllerData *data = l->data;
12388 if (data->controller)
12389 _gtk_widget_remove_controller (widget, data->controller);
12390 }
12391 g_list_free_full (priv->event_controllers, g_free);
12392 priv->event_controllers = NULL;
12393
12394 if (g_object_is_floating (object))
12395 g_warning ("A floating object was finalized. This means that someone\n"
12396 "called g_object_unref() on an object that had only a floating\n"
12397 "reference; the initial floating reference is not owned by anyone\n"
12398 "and must be removed with g_object_ref_sink().");
12399
12400 G_OBJECT_CLASS (gtk_widget_parent_class)->finalize (object);
12401 }
12402
12403 /*****************************************
12404 * gtk_widget_real_map:
12405 *
12406 * arguments:
12407 *
12408 * results:
12409 *****************************************/
12410
12411 static void
gtk_widget_real_map(GtkWidget * widget)12412 gtk_widget_real_map (GtkWidget *widget)
12413 {
12414 GtkWidgetPrivate *priv = widget->priv;
12415
12416 g_assert (_gtk_widget_get_realized (widget));
12417
12418 if (!_gtk_widget_get_mapped (widget))
12419 {
12420 gtk_widget_set_mapped (widget, TRUE);
12421
12422 if (_gtk_widget_get_has_window (widget))
12423 gdk_window_show (priv->window);
12424 }
12425 }
12426
12427 /*****************************************
12428 * gtk_widget_real_unmap:
12429 *
12430 * arguments:
12431 *
12432 * results:
12433 *****************************************/
12434
12435 static void
gtk_widget_real_unmap(GtkWidget * widget)12436 gtk_widget_real_unmap (GtkWidget *widget)
12437 {
12438 GtkWidgetPrivate *priv = widget->priv;
12439
12440 if (_gtk_widget_get_mapped (widget))
12441 {
12442 gtk_widget_set_mapped (widget, FALSE);
12443
12444 if (_gtk_widget_get_has_window (widget))
12445 gdk_window_hide (priv->window);
12446 }
12447 }
12448
12449 /*****************************************
12450 * gtk_widget_real_realize:
12451 *
12452 * arguments:
12453 *
12454 * results:
12455 *****************************************/
12456
12457 static void
gtk_widget_real_realize(GtkWidget * widget)12458 gtk_widget_real_realize (GtkWidget *widget)
12459 {
12460 GtkWidgetPrivate *priv = widget->priv;
12461
12462 g_assert (!_gtk_widget_get_has_window (widget));
12463
12464 gtk_widget_set_realized (widget, TRUE);
12465 if (priv->parent)
12466 {
12467 priv->window = gtk_widget_get_parent_window (widget);
12468 g_object_ref (priv->window);
12469 }
12470 }
12471
12472 /*****************************************
12473 * gtk_widget_real_unrealize:
12474 *
12475 * arguments:
12476 *
12477 * results:
12478 *****************************************/
12479
12480 static void
gtk_widget_real_unrealize(GtkWidget * widget)12481 gtk_widget_real_unrealize (GtkWidget *widget)
12482 {
12483 GtkWidgetPrivate *priv = widget->priv;
12484
12485 g_assert (!widget->priv->mapped);
12486
12487 /* We must do unrealize child widget BEFORE container widget.
12488 * gdk_window_destroy() destroys specified xwindow and its sub-xwindows.
12489 * So, unrealizing container widget before its children causes the problem
12490 * (for example, gdk_ic_destroy () with destroyed window causes crash.)
12491 */
12492
12493 if (GTK_IS_CONTAINER (widget))
12494 gtk_container_forall (GTK_CONTAINER (widget),
12495 (GtkCallback) gtk_widget_unrealize,
12496 NULL);
12497
12498 if (_gtk_widget_get_has_window (widget))
12499 {
12500 gtk_widget_unregister_window (widget, priv->window);
12501 gdk_window_destroy (priv->window);
12502 priv->window = NULL;
12503 }
12504 else
12505 {
12506 g_object_unref (priv->window);
12507 priv->window = NULL;
12508 }
12509
12510 gtk_selection_remove_all (widget);
12511
12512 gtk_widget_set_realized (widget, FALSE);
12513 }
12514
12515 static void
gtk_widget_real_adjust_size_request(GtkWidget * widget,GtkOrientation orientation,gint * minimum_size,gint * natural_size)12516 gtk_widget_real_adjust_size_request (GtkWidget *widget,
12517 GtkOrientation orientation,
12518 gint *minimum_size,
12519 gint *natural_size)
12520 {
12521 GtkWidgetPrivate *priv = widget->priv;
12522
12523 if (orientation == GTK_ORIENTATION_HORIZONTAL && priv->width > 0)
12524 *minimum_size = MAX (*minimum_size, priv->width);
12525 else if (orientation == GTK_ORIENTATION_VERTICAL && priv->height > 0)
12526 *minimum_size = MAX (*minimum_size, priv->height);
12527
12528 /* Fix it if set_size_request made natural size smaller than min size.
12529 * This would also silently fix broken widgets, but we warn about them
12530 * in gtksizerequest.c when calling their size request vfuncs.
12531 */
12532 *natural_size = MAX (*natural_size, *minimum_size);
12533
12534 if (orientation == GTK_ORIENTATION_HORIZONTAL)
12535 {
12536 *minimum_size += priv->margin.left + priv->margin.right;
12537 *natural_size += priv->margin.left + priv->margin.right;
12538 }
12539 else
12540 {
12541 *minimum_size += priv->margin.top + priv->margin.bottom;
12542 *natural_size += priv->margin.top + priv->margin.bottom;
12543 }
12544 }
12545
12546 static void
gtk_widget_real_adjust_baseline_request(GtkWidget * widget,gint * minimum_baseline,gint * natural_baseline)12547 gtk_widget_real_adjust_baseline_request (GtkWidget *widget,
12548 gint *minimum_baseline,
12549 gint *natural_baseline)
12550 {
12551 GtkWidgetPrivate *priv = widget->priv;
12552
12553 if (priv->height >= 0)
12554 {
12555 /* No baseline support for explicitly set height */
12556 *minimum_baseline = -1;
12557 *natural_baseline = -1;
12558 }
12559 else
12560 {
12561 *minimum_baseline += priv->margin.top;
12562 *natural_baseline += priv->margin.top;
12563 }
12564 }
12565
12566 static gboolean
is_my_window(GtkWidget * widget,GdkWindow * window)12567 is_my_window (GtkWidget *widget,
12568 GdkWindow *window)
12569 {
12570 gpointer user_data;
12571
12572 gdk_window_get_user_data (window, &user_data);
12573 return (user_data == widget);
12574 }
12575
12576 /*
12577 * _gtk_widget_get_device_window:
12578 * @widget: a #GtkWidget
12579 * @device: a #GdkDevice
12580 *
12581 * Returns: (nullable): the window of @widget that @device is in, or %NULL
12582 */
12583 GdkWindow *
_gtk_widget_get_device_window(GtkWidget * widget,GdkDevice * device)12584 _gtk_widget_get_device_window (GtkWidget *widget,
12585 GdkDevice *device)
12586 {
12587 GdkWindow *window;
12588
12589 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
12590 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
12591
12592 if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
12593 return NULL;
12594
12595 window = gdk_device_get_last_event_window (device);
12596 if (window && is_my_window (widget, window))
12597 return window;
12598 else
12599 return NULL;
12600 }
12601
12602 static void
list_devices(GtkWidget * widget,GdkDeviceManager * device_manager,GdkDeviceType device_type,GList ** result)12603 list_devices (GtkWidget *widget,
12604 GdkDeviceManager *device_manager,
12605 GdkDeviceType device_type,
12606 GList **result)
12607 {
12608 GList *devices;
12609 GList *l;
12610
12611 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
12612 devices = gdk_device_manager_list_devices (device_manager, device_type);
12613 G_GNUC_END_IGNORE_DEPRECATIONS;
12614
12615 for (l = devices; l; l = l->next)
12616 {
12617 GdkDevice *device = l->data;
12618 if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
12619 {
12620 GdkWindow *window = gdk_device_get_last_event_window (device);
12621 if (window && is_my_window (widget, window))
12622 *result = g_list_prepend (*result, device);
12623 }
12624 }
12625 g_list_free (devices);
12626 }
12627
12628 /*
12629 * _gtk_widget_list_devices:
12630 * @widget: a #GtkWidget
12631 *
12632 * Returns the list of #GdkDevices that is currently on top
12633 * of any window belonging to @widget.
12634 * Free the list with g_list_free(), the elements are owned
12635 * by GTK+ and must not be freed.
12636 */
12637 GList *
_gtk_widget_list_devices(GtkWidget * widget)12638 _gtk_widget_list_devices (GtkWidget *widget)
12639 {
12640 GdkDisplay *display;
12641 GdkDeviceManager *device_manager;
12642 GList *result = NULL;
12643
12644 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
12645
12646 if (!_gtk_widget_get_mapped (widget))
12647 return NULL;
12648
12649 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
12650 display = gtk_widget_get_display (widget);
12651 device_manager = gdk_display_get_device_manager (display);
12652 G_GNUC_END_IGNORE_DEPRECATIONS;
12653
12654 list_devices (widget, device_manager, GDK_DEVICE_TYPE_MASTER, &result);
12655 /* Rare, but we can get events for grabbed slave devices */
12656 list_devices (widget, device_manager, GDK_DEVICE_TYPE_SLAVE, &result);
12657
12658 return result;
12659 }
12660
12661 static void
synth_crossing(GtkWidget * widget,GdkEventType type,GdkWindow * window,GdkDevice * device,GdkCrossingMode mode,GdkNotifyType detail)12662 synth_crossing (GtkWidget *widget,
12663 GdkEventType type,
12664 GdkWindow *window,
12665 GdkDevice *device,
12666 GdkCrossingMode mode,
12667 GdkNotifyType detail)
12668 {
12669 GdkEvent *event;
12670
12671 event = gdk_event_new (type);
12672
12673 event->crossing.window = g_object_ref (window);
12674 event->crossing.send_event = TRUE;
12675 event->crossing.subwindow = g_object_ref (window);
12676 event->crossing.time = GDK_CURRENT_TIME;
12677 gdk_device_get_position_double (device,
12678 NULL,
12679 &event->crossing.x_root,
12680 &event->crossing.y_root);
12681 gdk_window_get_device_position_double (window,
12682 device,
12683 &event->crossing.x,
12684 &event->crossing.y,
12685 NULL);
12686 event->crossing.mode = mode;
12687 event->crossing.detail = detail;
12688 event->crossing.focus = FALSE;
12689 event->crossing.state = 0;
12690 gdk_event_set_device (event, device);
12691
12692 if (!widget)
12693 widget = gtk_get_event_widget (event);
12694
12695 if (widget)
12696 gtk_widget_event_internal (widget, event);
12697
12698 gdk_event_free (event);
12699 }
12700
12701 /*
12702 * _gtk_widget_synthesize_crossing:
12703 * @from: the #GtkWidget the virtual pointer is leaving.
12704 * @to: the #GtkWidget the virtual pointer is moving to.
12705 * @mode: the #GdkCrossingMode to place on the synthesized events.
12706 *
12707 * Generate crossing event(s) on widget state (sensitivity) or GTK+ grab change.
12708 *
12709 * The real pointer window is the window that most recently received an enter notify
12710 * event. Windows that don’t select for crossing events can’t become the real
12711 * pointer window. The real pointer widget that owns the real pointer window. The
12712 * effective pointer window is the same as the real pointer window unless the real
12713 * pointer widget is either insensitive or there is a grab on a widget that is not
12714 * an ancestor of the real pointer widget (in which case the effective pointer
12715 * window should be the root window).
12716 *
12717 * When the effective pointer window is the same as the real pointer window, we
12718 * receive crossing events from the windowing system. When the effective pointer
12719 * window changes to become different from the real pointer window we synthesize
12720 * crossing events, attempting to follow X protocol rules:
12721 *
12722 * When the root window becomes the effective pointer window:
12723 * - leave notify on real pointer window, detail Ancestor
12724 * - leave notify on all of its ancestors, detail Virtual
12725 * - enter notify on root window, detail Inferior
12726 *
12727 * When the root window ceases to be the effective pointer window:
12728 * - leave notify on root window, detail Inferior
12729 * - enter notify on all ancestors of real pointer window, detail Virtual
12730 * - enter notify on real pointer window, detail Ancestor
12731 */
12732 void
_gtk_widget_synthesize_crossing(GtkWidget * from,GtkWidget * to,GdkDevice * device,GdkCrossingMode mode)12733 _gtk_widget_synthesize_crossing (GtkWidget *from,
12734 GtkWidget *to,
12735 GdkDevice *device,
12736 GdkCrossingMode mode)
12737 {
12738 GdkWindow *from_window = NULL, *to_window = NULL;
12739
12740 g_return_if_fail (from != NULL || to != NULL);
12741
12742 if (from != NULL)
12743 {
12744 from_window = _gtk_widget_get_device_window (from, device);
12745
12746 if (!from_window)
12747 from_window = from->priv->window;
12748 }
12749
12750 if (to != NULL)
12751 {
12752 to_window = _gtk_widget_get_device_window (to, device);
12753
12754 if (!to_window)
12755 to_window = to->priv->window;
12756 }
12757
12758 if (from_window == NULL && to_window == NULL)
12759 ;
12760 else if (from_window != NULL && to_window == NULL)
12761 {
12762 GList *from_ancestors = NULL, *list;
12763 GdkWindow *from_ancestor = from_window;
12764
12765 while (from_ancestor != NULL)
12766 {
12767 from_ancestor = gdk_window_get_effective_parent (from_ancestor);
12768 if (from_ancestor == NULL)
12769 break;
12770 from_ancestors = g_list_prepend (from_ancestors, from_ancestor);
12771 }
12772
12773 synth_crossing (from, GDK_LEAVE_NOTIFY, from_window,
12774 device, mode, GDK_NOTIFY_ANCESTOR);
12775 for (list = g_list_last (from_ancestors); list; list = list->prev)
12776 {
12777 synth_crossing (NULL, GDK_LEAVE_NOTIFY, (GdkWindow *) list->data,
12778 device, mode, GDK_NOTIFY_VIRTUAL);
12779 }
12780
12781 /* XXX: enter/inferior on root window? */
12782
12783 g_list_free (from_ancestors);
12784 }
12785 else if (from_window == NULL && to_window != NULL)
12786 {
12787 GList *to_ancestors = NULL, *list;
12788 GdkWindow *to_ancestor = to_window;
12789
12790 while (to_ancestor != NULL)
12791 {
12792 to_ancestor = gdk_window_get_effective_parent (to_ancestor);
12793 if (to_ancestor == NULL)
12794 break;
12795 to_ancestors = g_list_prepend (to_ancestors, to_ancestor);
12796 }
12797
12798 /* XXX: leave/inferior on root window? */
12799
12800 for (list = to_ancestors; list; list = list->next)
12801 {
12802 synth_crossing (NULL, GDK_ENTER_NOTIFY, (GdkWindow *) list->data,
12803 device, mode, GDK_NOTIFY_VIRTUAL);
12804 }
12805 synth_crossing (to, GDK_ENTER_NOTIFY, to_window,
12806 device, mode, GDK_NOTIFY_ANCESTOR);
12807
12808 g_list_free (to_ancestors);
12809 }
12810 else if (from_window == to_window)
12811 ;
12812 else
12813 {
12814 GList *from_ancestors = NULL, *to_ancestors = NULL, *list;
12815 GdkWindow *from_ancestor = from_window, *to_ancestor = to_window;
12816
12817 while (from_ancestor != NULL || to_ancestor != NULL)
12818 {
12819 if (from_ancestor != NULL)
12820 {
12821 from_ancestor = gdk_window_get_effective_parent (from_ancestor);
12822 if (from_ancestor == to_window)
12823 break;
12824 if (from_ancestor)
12825 from_ancestors = g_list_prepend (from_ancestors, from_ancestor);
12826 }
12827 if (to_ancestor != NULL)
12828 {
12829 to_ancestor = gdk_window_get_effective_parent (to_ancestor);
12830 if (to_ancestor == from_window)
12831 break;
12832 if (to_ancestor)
12833 to_ancestors = g_list_prepend (to_ancestors, to_ancestor);
12834 }
12835 }
12836 if (to_ancestor == from_window)
12837 {
12838 if (mode != GDK_CROSSING_GTK_UNGRAB)
12839 synth_crossing (from, GDK_LEAVE_NOTIFY, from_window,
12840 device, mode, GDK_NOTIFY_INFERIOR);
12841 for (list = to_ancestors; list; list = list->next)
12842 synth_crossing (NULL, GDK_ENTER_NOTIFY, (GdkWindow *) list->data,
12843 device, mode, GDK_NOTIFY_VIRTUAL);
12844 synth_crossing (to, GDK_ENTER_NOTIFY, to_window,
12845 device, mode, GDK_NOTIFY_ANCESTOR);
12846 }
12847 else if (from_ancestor == to_window)
12848 {
12849 synth_crossing (from, GDK_LEAVE_NOTIFY, from_window,
12850 device, mode, GDK_NOTIFY_ANCESTOR);
12851 for (list = g_list_last (from_ancestors); list; list = list->prev)
12852 {
12853 synth_crossing (NULL, GDK_LEAVE_NOTIFY, (GdkWindow *) list->data,
12854 device, mode, GDK_NOTIFY_VIRTUAL);
12855 }
12856 if (mode != GDK_CROSSING_GTK_GRAB)
12857 synth_crossing (to, GDK_ENTER_NOTIFY, to_window,
12858 device, mode, GDK_NOTIFY_INFERIOR);
12859 }
12860 else
12861 {
12862 while (from_ancestors != NULL && to_ancestors != NULL
12863 && from_ancestors->data == to_ancestors->data)
12864 {
12865 from_ancestors = g_list_delete_link (from_ancestors,
12866 from_ancestors);
12867 to_ancestors = g_list_delete_link (to_ancestors, to_ancestors);
12868 }
12869
12870 synth_crossing (from, GDK_LEAVE_NOTIFY, from_window,
12871 device, mode, GDK_NOTIFY_NONLINEAR);
12872
12873 for (list = g_list_last (from_ancestors); list; list = list->prev)
12874 {
12875 synth_crossing (NULL, GDK_LEAVE_NOTIFY, (GdkWindow *) list->data,
12876 device, mode, GDK_NOTIFY_NONLINEAR_VIRTUAL);
12877 }
12878 for (list = to_ancestors; list; list = list->next)
12879 {
12880 synth_crossing (NULL, GDK_ENTER_NOTIFY, (GdkWindow *) list->data,
12881 device, mode, GDK_NOTIFY_NONLINEAR_VIRTUAL);
12882 }
12883 synth_crossing (to, GDK_ENTER_NOTIFY, to_window,
12884 device, mode, GDK_NOTIFY_NONLINEAR);
12885 }
12886 g_list_free (from_ancestors);
12887 g_list_free (to_ancestors);
12888 }
12889 }
12890
12891 static void
gtk_widget_propagate_state(GtkWidget * widget,GtkStateData * data)12892 gtk_widget_propagate_state (GtkWidget *widget,
12893 GtkStateData *data)
12894 {
12895 GtkWidgetPrivate *priv = widget->priv;
12896 GtkStateFlags new_flags, old_flags = priv->state_flags;
12897 GtkStateType old_state;
12898 gint new_scale_factor = gtk_widget_get_scale_factor (widget);
12899
12900 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
12901 old_state = gtk_widget_get_state (widget);
12902 G_GNUC_END_IGNORE_DEPRECATIONS;
12903
12904 priv->state_flags |= data->flags_to_set;
12905 priv->state_flags &= ~(data->flags_to_unset);
12906
12907 /* make insensitivity unoverridable */
12908 if (!priv->sensitive)
12909 priv->state_flags |= GTK_STATE_FLAG_INSENSITIVE;
12910
12911 if (gtk_widget_is_focus (widget) && !gtk_widget_is_sensitive (widget))
12912 {
12913 GtkWidget *window;
12914
12915 window = _gtk_widget_get_toplevel (widget);
12916
12917 if (window && _gtk_widget_is_toplevel (window))
12918 gtk_window_set_focus (GTK_WINDOW (window), NULL);
12919 }
12920
12921 new_flags = priv->state_flags;
12922
12923 if (data->old_scale_factor != new_scale_factor)
12924 _gtk_widget_scale_changed (widget);
12925
12926 if (old_flags != new_flags)
12927 {
12928 g_object_ref (widget);
12929
12930 if (!gtk_widget_is_sensitive (widget) && gtk_widget_has_grab (widget))
12931 gtk_grab_remove (widget);
12932
12933 gtk_style_context_set_state (_gtk_widget_get_style_context (widget), new_flags);
12934
12935 g_signal_emit (widget, widget_signals[STATE_CHANGED], 0, old_state);
12936 g_signal_emit (widget, widget_signals[STATE_FLAGS_CHANGED], 0, old_flags);
12937
12938 if (!priv->shadowed &&
12939 (new_flags & GTK_STATE_FLAG_INSENSITIVE) != (old_flags & GTK_STATE_FLAG_INSENSITIVE))
12940 {
12941 GList *event_windows = NULL;
12942 GList *devices, *d;
12943
12944 devices = _gtk_widget_list_devices (widget);
12945
12946 for (d = devices; d; d = d->next)
12947 {
12948 GdkWindow *window;
12949 GdkDevice *device;
12950
12951 device = d->data;
12952 window = _gtk_widget_get_device_window (widget, device);
12953
12954 /* Do not propagate more than once to the
12955 * same window if non-multidevice aware.
12956 */
12957 if (!gdk_window_get_support_multidevice (window) &&
12958 g_list_find (event_windows, window))
12959 continue;
12960
12961 if (!gtk_widget_is_sensitive (widget))
12962 _gtk_widget_synthesize_crossing (widget, NULL, d->data,
12963 GDK_CROSSING_STATE_CHANGED);
12964 else
12965 _gtk_widget_synthesize_crossing (NULL, widget, d->data,
12966 GDK_CROSSING_STATE_CHANGED);
12967
12968 event_windows = g_list_prepend (event_windows, window);
12969 }
12970
12971 g_list_free (event_windows);
12972 g_list_free (devices);
12973 }
12974
12975 if (!gtk_widget_is_sensitive (widget))
12976 gtk_widget_reset_controllers (widget);
12977
12978 if (GTK_IS_CONTAINER (widget))
12979 {
12980 GtkStateData child_data;
12981
12982 /* Make sure to only propagate the right states further */
12983 child_data.old_scale_factor = new_scale_factor;
12984 child_data.flags_to_set = data->flags_to_set & GTK_STATE_FLAGS_DO_PROPAGATE;
12985 child_data.flags_to_unset = data->flags_to_unset & GTK_STATE_FLAGS_DO_PROPAGATE;
12986
12987 gtk_container_forall (GTK_CONTAINER (widget),
12988 (GtkCallback) gtk_widget_propagate_state,
12989 &child_data);
12990 }
12991
12992 g_object_unref (widget);
12993 }
12994 }
12995
12996 /**
12997 * gtk_widget_shape_combine_region:
12998 * @widget: a #GtkWidget
12999 * @region: (allow-none): shape to be added, or %NULL to remove an existing shape
13000 *
13001 * Sets a shape for this widget’s GDK window. This allows for
13002 * transparent windows etc., see gdk_window_shape_combine_region()
13003 * for more information.
13004 *
13005 * Since: 3.0
13006 **/
13007 void
gtk_widget_shape_combine_region(GtkWidget * widget,cairo_region_t * region)13008 gtk_widget_shape_combine_region (GtkWidget *widget,
13009 cairo_region_t *region)
13010 {
13011 GtkWidgetPrivate *priv;
13012
13013 g_return_if_fail (GTK_IS_WIDGET (widget));
13014 /* set_shape doesn't work on widgets without GDK window */
13015 g_return_if_fail (_gtk_widget_get_has_window (widget));
13016
13017 priv = widget->priv;
13018
13019 if (region == NULL)
13020 {
13021 priv->has_shape_mask = FALSE;
13022
13023 if (priv->window)
13024 gdk_window_shape_combine_region (priv->window, NULL, 0, 0);
13025
13026 g_object_set_qdata (G_OBJECT (widget), quark_shape_info, NULL);
13027 }
13028 else
13029 {
13030 priv->has_shape_mask = TRUE;
13031
13032 g_object_set_qdata_full (G_OBJECT (widget), quark_shape_info,
13033 cairo_region_copy (region),
13034 (GDestroyNotify) cairo_region_destroy);
13035
13036 /* set shape if widget has a GDK window already.
13037 * otherwise the shape is scheduled to be set by gtk_widget_realize().
13038 */
13039 if (priv->window)
13040 gdk_window_shape_combine_region (priv->window, region, 0, 0);
13041 }
13042 }
13043
13044 static void
gtk_widget_update_input_shape(GtkWidget * widget)13045 gtk_widget_update_input_shape (GtkWidget *widget)
13046 {
13047 GtkWidgetPrivate *priv = widget->priv;
13048
13049 /* set shape if widget has a GDK window already.
13050 * otherwise the shape is scheduled to be set by gtk_widget_realize().
13051 */
13052 if (priv->window)
13053 {
13054 cairo_region_t *region;
13055 cairo_region_t *csd_region;
13056 cairo_region_t *app_region;
13057 gboolean free_region;
13058
13059 app_region = g_object_get_qdata (G_OBJECT (widget), quark_input_shape_info);
13060 csd_region = g_object_get_data (G_OBJECT (widget), "csd-region");
13061
13062 free_region = FALSE;
13063
13064 if (app_region && csd_region)
13065 {
13066 free_region = TRUE;
13067 region = cairo_region_copy (app_region);
13068 cairo_region_intersect (region, csd_region);
13069 }
13070 else if (app_region)
13071 region = app_region;
13072 else if (csd_region)
13073 region = csd_region;
13074 else
13075 region = NULL;
13076
13077 gdk_window_input_shape_combine_region (priv->window, region, 0, 0);
13078
13079 if (free_region)
13080 cairo_region_destroy (region);
13081 }
13082 }
13083
13084 void
gtk_widget_set_csd_input_shape(GtkWidget * widget,const cairo_region_t * region)13085 gtk_widget_set_csd_input_shape (GtkWidget *widget,
13086 const cairo_region_t *region)
13087 {
13088 if (region == NULL)
13089 g_object_set_data (G_OBJECT (widget), "csd-region", NULL);
13090 else
13091 g_object_set_data_full (G_OBJECT (widget), "csd-region",
13092 cairo_region_copy (region),
13093 (GDestroyNotify) cairo_region_destroy);
13094 gtk_widget_update_input_shape (widget);
13095 }
13096
13097 /**
13098 * gtk_widget_input_shape_combine_region:
13099 * @widget: a #GtkWidget
13100 * @region: (allow-none): shape to be added, or %NULL to remove an existing shape
13101 *
13102 * Sets an input shape for this widget’s GDK window. This allows for
13103 * windows which react to mouse click in a nonrectangular region, see
13104 * gdk_window_input_shape_combine_region() for more information.
13105 *
13106 * Since: 3.0
13107 **/
13108 void
gtk_widget_input_shape_combine_region(GtkWidget * widget,cairo_region_t * region)13109 gtk_widget_input_shape_combine_region (GtkWidget *widget,
13110 cairo_region_t *region)
13111 {
13112 g_return_if_fail (GTK_IS_WIDGET (widget));
13113 /* set_shape doesn't work on widgets without GDK window */
13114 g_return_if_fail (_gtk_widget_get_has_window (widget));
13115
13116 if (region == NULL)
13117 g_object_set_qdata (G_OBJECT (widget), quark_input_shape_info, NULL);
13118 else
13119 g_object_set_qdata_full (G_OBJECT (widget), quark_input_shape_info,
13120 cairo_region_copy (region),
13121 (GDestroyNotify) cairo_region_destroy);
13122 gtk_widget_update_input_shape (widget);
13123 }
13124
13125
13126 /* style properties
13127 */
13128
13129 /**
13130 * gtk_widget_class_install_style_property_parser: (skip)
13131 * @klass: a #GtkWidgetClass
13132 * @pspec: the #GParamSpec for the style property
13133 * @parser: the parser for the style property
13134 *
13135 * Installs a style property on a widget class.
13136 **/
13137 void
gtk_widget_class_install_style_property_parser(GtkWidgetClass * klass,GParamSpec * pspec,GtkRcPropertyParser parser)13138 gtk_widget_class_install_style_property_parser (GtkWidgetClass *klass,
13139 GParamSpec *pspec,
13140 GtkRcPropertyParser parser)
13141 {
13142 g_return_if_fail (GTK_IS_WIDGET_CLASS (klass));
13143 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
13144 g_return_if_fail (pspec->flags & G_PARAM_READABLE);
13145 g_return_if_fail (!(pspec->flags & (G_PARAM_CONSTRUCT_ONLY | G_PARAM_CONSTRUCT)));
13146
13147 if (g_param_spec_pool_lookup (style_property_spec_pool, pspec->name, G_OBJECT_CLASS_TYPE (klass), FALSE))
13148 {
13149 g_warning (G_STRLOC ": class '%s' already contains a style property named '%s'",
13150 G_OBJECT_CLASS_NAME (klass),
13151 pspec->name);
13152 return;
13153 }
13154
13155 g_param_spec_ref_sink (pspec);
13156 g_param_spec_set_qdata (pspec, quark_property_parser, (gpointer) parser);
13157 g_param_spec_pool_insert (style_property_spec_pool, pspec, G_OBJECT_CLASS_TYPE (klass));
13158 }
13159
13160 /**
13161 * gtk_widget_class_install_style_property:
13162 * @klass: a #GtkWidgetClass
13163 * @pspec: the #GParamSpec for the property
13164 *
13165 * Installs a style property on a widget class. The parser for the
13166 * style property is determined by the value type of @pspec.
13167 **/
13168 void
gtk_widget_class_install_style_property(GtkWidgetClass * klass,GParamSpec * pspec)13169 gtk_widget_class_install_style_property (GtkWidgetClass *klass,
13170 GParamSpec *pspec)
13171 {
13172 GtkRcPropertyParser parser;
13173
13174 g_return_if_fail (GTK_IS_WIDGET_CLASS (klass));
13175 g_return_if_fail (G_IS_PARAM_SPEC (pspec));
13176
13177 parser = _gtk_rc_property_parser_from_type (G_PARAM_SPEC_VALUE_TYPE (pspec));
13178
13179 gtk_widget_class_install_style_property_parser (klass, pspec, parser);
13180 }
13181
13182 /**
13183 * gtk_widget_class_find_style_property:
13184 * @klass: a #GtkWidgetClass
13185 * @property_name: the name of the style property to find
13186 *
13187 * Finds a style property of a widget class by name.
13188 *
13189 * Returns: (transfer none): the #GParamSpec of the style property or
13190 * %NULL if @class has no style property with that name.
13191 *
13192 * Since: 2.2
13193 */
13194 GParamSpec*
gtk_widget_class_find_style_property(GtkWidgetClass * klass,const gchar * property_name)13195 gtk_widget_class_find_style_property (GtkWidgetClass *klass,
13196 const gchar *property_name)
13197 {
13198 g_return_val_if_fail (property_name != NULL, NULL);
13199
13200 return g_param_spec_pool_lookup (style_property_spec_pool,
13201 property_name,
13202 G_OBJECT_CLASS_TYPE (klass),
13203 TRUE);
13204 }
13205
13206 /**
13207 * gtk_widget_class_list_style_properties:
13208 * @klass: a #GtkWidgetClass
13209 * @n_properties: (out): location to return the number of style properties found
13210 *
13211 * Returns all style properties of a widget class.
13212 *
13213 * Returns: (array length=n_properties) (transfer container): a
13214 * newly allocated array of #GParamSpec*. The array must be
13215 * freed with g_free().
13216 *
13217 * Since: 2.2
13218 */
13219 GParamSpec**
gtk_widget_class_list_style_properties(GtkWidgetClass * klass,guint * n_properties)13220 gtk_widget_class_list_style_properties (GtkWidgetClass *klass,
13221 guint *n_properties)
13222 {
13223 GParamSpec **pspecs;
13224 guint n;
13225
13226 pspecs = g_param_spec_pool_list (style_property_spec_pool,
13227 G_OBJECT_CLASS_TYPE (klass),
13228 &n);
13229 if (n_properties)
13230 *n_properties = n;
13231
13232 return pspecs;
13233 }
13234
13235 /**
13236 * gtk_widget_style_get_property:
13237 * @widget: a #GtkWidget
13238 * @property_name: the name of a style property
13239 * @value: location to return the property value
13240 *
13241 * Gets the value of a style property of @widget.
13242 */
13243 void
gtk_widget_style_get_property(GtkWidget * widget,const gchar * property_name,GValue * value)13244 gtk_widget_style_get_property (GtkWidget *widget,
13245 const gchar *property_name,
13246 GValue *value)
13247 {
13248 GParamSpec *pspec;
13249
13250 g_return_if_fail (GTK_IS_WIDGET (widget));
13251 g_return_if_fail (property_name != NULL);
13252 g_return_if_fail (G_IS_VALUE (value));
13253
13254 g_object_ref (widget);
13255 pspec = g_param_spec_pool_lookup (style_property_spec_pool,
13256 property_name,
13257 G_OBJECT_TYPE (widget),
13258 TRUE);
13259 if (!pspec)
13260 g_warning ("%s: widget class '%s' has no property named '%s'",
13261 G_STRLOC,
13262 G_OBJECT_TYPE_NAME (widget),
13263 property_name);
13264 else
13265 {
13266 GtkStyleContext *context;
13267 const GValue *peek_value;
13268
13269 context = _gtk_widget_get_style_context (widget);
13270
13271 peek_value = _gtk_style_context_peek_style_property (context,
13272 G_OBJECT_TYPE (widget),
13273 pspec);
13274
13275 /* auto-conversion of the caller's value type
13276 */
13277 if (G_VALUE_TYPE (value) == G_PARAM_SPEC_VALUE_TYPE (pspec))
13278 g_value_copy (peek_value, value);
13279 else if (g_value_type_transformable (G_PARAM_SPEC_VALUE_TYPE (pspec), G_VALUE_TYPE (value)))
13280 g_value_transform (peek_value, value);
13281 else
13282 g_warning ("can't retrieve style property '%s' of type '%s' as value of type '%s'",
13283 pspec->name,
13284 g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)),
13285 G_VALUE_TYPE_NAME (value));
13286 }
13287 g_object_unref (widget);
13288 }
13289
13290 /**
13291 * gtk_widget_style_get_valist:
13292 * @widget: a #GtkWidget
13293 * @first_property_name: the name of the first property to get
13294 * @var_args: a va_list of pairs of property names and
13295 * locations to return the property values, starting with the location
13296 * for @first_property_name.
13297 *
13298 * Non-vararg variant of gtk_widget_style_get(). Used primarily by language
13299 * bindings.
13300 */
13301 void
gtk_widget_style_get_valist(GtkWidget * widget,const gchar * first_property_name,va_list var_args)13302 gtk_widget_style_get_valist (GtkWidget *widget,
13303 const gchar *first_property_name,
13304 va_list var_args)
13305 {
13306 GtkStyleContext *context;
13307 const gchar *name;
13308
13309 g_return_if_fail (GTK_IS_WIDGET (widget));
13310
13311 g_object_ref (widget);
13312 context = _gtk_widget_get_style_context (widget);
13313
13314 name = first_property_name;
13315 while (name)
13316 {
13317 const GValue *peek_value;
13318 GParamSpec *pspec;
13319 gchar *error;
13320
13321 pspec = g_param_spec_pool_lookup (style_property_spec_pool,
13322 name,
13323 G_OBJECT_TYPE (widget),
13324 TRUE);
13325 if (!pspec)
13326 {
13327 g_warning ("%s: widget class '%s' has no property named '%s'",
13328 G_STRLOC,
13329 G_OBJECT_TYPE_NAME (widget),
13330 name);
13331 break;
13332 }
13333 /* style pspecs are always readable so we can spare that check here */
13334
13335 peek_value = _gtk_style_context_peek_style_property (context,
13336 G_OBJECT_TYPE (widget),
13337 pspec);
13338
13339 G_VALUE_LCOPY (peek_value, var_args, 0, &error);
13340 if (error)
13341 {
13342 g_warning ("%s: %s", G_STRLOC, error);
13343 g_free (error);
13344 break;
13345 }
13346
13347 name = va_arg (var_args, gchar*);
13348 }
13349
13350 g_object_unref (widget);
13351 }
13352
13353 /**
13354 * gtk_widget_style_get:
13355 * @widget: a #GtkWidget
13356 * @first_property_name: the name of the first property to get
13357 * @...: pairs of property names and locations to return the
13358 * property values, starting with the location for
13359 * @first_property_name, terminated by %NULL.
13360 *
13361 * Gets the values of a multiple style properties of @widget.
13362 */
13363 void
gtk_widget_style_get(GtkWidget * widget,const gchar * first_property_name,...)13364 gtk_widget_style_get (GtkWidget *widget,
13365 const gchar *first_property_name,
13366 ...)
13367 {
13368 va_list var_args;
13369
13370 g_return_if_fail (GTK_IS_WIDGET (widget));
13371
13372 va_start (var_args, first_property_name);
13373 gtk_widget_style_get_valist (widget, first_property_name, var_args);
13374 va_end (var_args);
13375 }
13376
13377 /**
13378 * gtk_requisition_new:
13379 *
13380 * Allocates a new #GtkRequisition-struct and initializes its elements to zero.
13381 *
13382 * Returns: a new empty #GtkRequisition. The newly allocated #GtkRequisition should
13383 * be freed with gtk_requisition_free().
13384 *
13385 * Since: 3.0
13386 */
13387 GtkRequisition *
gtk_requisition_new(void)13388 gtk_requisition_new (void)
13389 {
13390 return g_slice_new0 (GtkRequisition);
13391 }
13392
13393 /**
13394 * gtk_requisition_copy:
13395 * @requisition: a #GtkRequisition
13396 *
13397 * Copies a #GtkRequisition.
13398 *
13399 * Returns: a copy of @requisition
13400 **/
13401 GtkRequisition *
gtk_requisition_copy(const GtkRequisition * requisition)13402 gtk_requisition_copy (const GtkRequisition *requisition)
13403 {
13404 return g_slice_dup (GtkRequisition, requisition);
13405 }
13406
13407 /**
13408 * gtk_requisition_free:
13409 * @requisition: a #GtkRequisition
13410 *
13411 * Frees a #GtkRequisition.
13412 **/
13413 void
gtk_requisition_free(GtkRequisition * requisition)13414 gtk_requisition_free (GtkRequisition *requisition)
13415 {
13416 g_slice_free (GtkRequisition, requisition);
13417 }
13418
G_DEFINE_BOXED_TYPE(GtkRequisition,gtk_requisition,gtk_requisition_copy,gtk_requisition_free)13419 G_DEFINE_BOXED_TYPE (GtkRequisition, gtk_requisition,
13420 gtk_requisition_copy,
13421 gtk_requisition_free)
13422
13423 /**
13424 * gtk_widget_class_set_accessible_type:
13425 * @widget_class: class to set the accessible type for
13426 * @type: The object type that implements the accessible for @widget_class
13427 *
13428 * Sets the type to be used for creating accessibles for widgets of
13429 * @widget_class. The given @type must be a subtype of the type used for
13430 * accessibles of the parent class.
13431 *
13432 * This function should only be called from class init functions of widgets.
13433 *
13434 * Since: 3.2
13435 **/
13436 void
13437 gtk_widget_class_set_accessible_type (GtkWidgetClass *widget_class,
13438 GType type)
13439 {
13440 GtkWidgetClassPrivate *priv;
13441
13442 g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
13443 g_return_if_fail (g_type_is_a (type, widget_class->priv->accessible_type));
13444
13445 priv = widget_class->priv;
13446
13447 priv->accessible_type = type;
13448 /* reset this - honoring the type's role is better. */
13449 priv->accessible_role = ATK_ROLE_INVALID;
13450 }
13451
13452 /**
13453 * gtk_widget_class_set_accessible_role:
13454 * @widget_class: class to set the accessible role for
13455 * @role: The role to use for accessibles created for @widget_class
13456 *
13457 * Sets the default #AtkRole to be set on accessibles created for
13458 * widgets of @widget_class. Accessibles may decide to not honor this
13459 * setting if their role reporting is more refined. Calls to
13460 * gtk_widget_class_set_accessible_type() will reset this value.
13461 *
13462 * In cases where you want more fine-grained control over the role of
13463 * accessibles created for @widget_class, you should provide your own
13464 * accessible type and use gtk_widget_class_set_accessible_type()
13465 * instead.
13466 *
13467 * If @role is #ATK_ROLE_INVALID, the default role will not be changed
13468 * and the accessible’s default role will be used instead.
13469 *
13470 * This function should only be called from class init functions of widgets.
13471 *
13472 * Since: 3.2
13473 **/
13474 void
gtk_widget_class_set_accessible_role(GtkWidgetClass * widget_class,AtkRole role)13475 gtk_widget_class_set_accessible_role (GtkWidgetClass *widget_class,
13476 AtkRole role)
13477 {
13478 GtkWidgetClassPrivate *priv;
13479
13480 g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
13481
13482 priv = widget_class->priv;
13483
13484 priv->accessible_role = role;
13485 }
13486
13487 /**
13488 * _gtk_widget_peek_accessible:
13489 * @widget: a #GtkWidget
13490 *
13491 * Gets the accessible for @widget, if it has been created yet.
13492 * Otherwise, this function returns %NULL. If the @widget’s implementation
13493 * does not use the default way to create accessibles, %NULL will always be
13494 * returned.
13495 *
13496 * Returns: (nullable): the accessible for @widget or %NULL if none has been
13497 * created yet.
13498 **/
13499 AtkObject *
_gtk_widget_peek_accessible(GtkWidget * widget)13500 _gtk_widget_peek_accessible (GtkWidget *widget)
13501 {
13502 return widget->priv->accessible;
13503 }
13504
13505 /**
13506 * gtk_widget_get_accessible:
13507 * @widget: a #GtkWidget
13508 *
13509 * Returns the accessible object that describes the widget to an
13510 * assistive technology.
13511 *
13512 * If accessibility support is not available, this #AtkObject
13513 * instance may be a no-op. Likewise, if no class-specific #AtkObject
13514 * implementation is available for the widget instance in question,
13515 * it will inherit an #AtkObject implementation from the first ancestor
13516 * class for which such an implementation is defined.
13517 *
13518 * The documentation of the
13519 * [ATK](http://developer.gnome.org/atk/stable/)
13520 * library contains more information about accessible objects and their uses.
13521 *
13522 * Returns: (transfer none): the #AtkObject associated with @widget
13523 */
13524 AtkObject*
gtk_widget_get_accessible(GtkWidget * widget)13525 gtk_widget_get_accessible (GtkWidget *widget)
13526 {
13527 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
13528
13529 return GTK_WIDGET_GET_CLASS (widget)->get_accessible (widget);
13530 }
13531
13532 static AtkObject*
gtk_widget_real_get_accessible(GtkWidget * widget)13533 gtk_widget_real_get_accessible (GtkWidget *widget)
13534 {
13535 AtkObject* accessible;
13536
13537 accessible = widget->priv->accessible;
13538
13539 if (!accessible)
13540 {
13541 GtkWidgetClass *widget_class;
13542 GtkWidgetClassPrivate *priv;
13543 AtkObjectFactory *factory;
13544 AtkRegistry *default_registry;
13545
13546 widget_class = GTK_WIDGET_GET_CLASS (widget);
13547 priv = widget_class->priv;
13548
13549 if (priv->accessible_type == GTK_TYPE_ACCESSIBLE)
13550 {
13551 default_registry = atk_get_default_registry ();
13552 factory = atk_registry_get_factory (default_registry,
13553 G_TYPE_FROM_INSTANCE (widget));
13554 accessible = atk_object_factory_create_accessible (factory, G_OBJECT (widget));
13555
13556 if (priv->accessible_role != ATK_ROLE_INVALID)
13557 atk_object_set_role (accessible, priv->accessible_role);
13558
13559 widget->priv->accessible = accessible;
13560 }
13561 else
13562 {
13563 accessible = g_object_new (priv->accessible_type,
13564 "widget", widget,
13565 NULL);
13566 if (priv->accessible_role != ATK_ROLE_INVALID)
13567 atk_object_set_role (accessible, priv->accessible_role);
13568
13569 widget->priv->accessible = accessible;
13570
13571 atk_object_initialize (accessible, widget);
13572
13573 /* Set the role again, since we don't want a role set
13574 * in some parent initialize() function to override
13575 * our own.
13576 */
13577 if (priv->accessible_role != ATK_ROLE_INVALID)
13578 atk_object_set_role (accessible, priv->accessible_role);
13579 }
13580
13581 }
13582
13583 return accessible;
13584 }
13585
13586 /*
13587 * Initialize a AtkImplementorIface instance’s virtual pointers as
13588 * appropriate to this implementor’s class (GtkWidget).
13589 */
13590 static void
gtk_widget_accessible_interface_init(AtkImplementorIface * iface)13591 gtk_widget_accessible_interface_init (AtkImplementorIface *iface)
13592 {
13593 iface->ref_accessible = gtk_widget_ref_accessible;
13594 }
13595
13596 static AtkObject*
gtk_widget_ref_accessible(AtkImplementor * implementor)13597 gtk_widget_ref_accessible (AtkImplementor *implementor)
13598 {
13599 AtkObject *accessible;
13600
13601 accessible = gtk_widget_get_accessible (GTK_WIDGET (implementor));
13602 if (accessible)
13603 g_object_ref (accessible);
13604 return accessible;
13605 }
13606
13607 /*
13608 * Expand flag management
13609 */
13610
13611 static void
gtk_widget_update_computed_expand(GtkWidget * widget)13612 gtk_widget_update_computed_expand (GtkWidget *widget)
13613 {
13614 GtkWidgetPrivate *priv;
13615
13616 priv = widget->priv;
13617
13618 if (priv->need_compute_expand)
13619 {
13620 gboolean h, v;
13621
13622 if (priv->hexpand_set)
13623 h = priv->hexpand;
13624 else
13625 h = FALSE;
13626
13627 if (priv->vexpand_set)
13628 v = priv->vexpand;
13629 else
13630 v = FALSE;
13631
13632 /* we don't need to use compute_expand if both expands are
13633 * forced by the app
13634 */
13635 if (!(priv->hexpand_set && priv->vexpand_set))
13636 {
13637 if (GTK_WIDGET_GET_CLASS (widget)->compute_expand != NULL)
13638 {
13639 gboolean ignored;
13640
13641 GTK_WIDGET_GET_CLASS (widget)->compute_expand (widget,
13642 priv->hexpand_set ? &ignored : &h,
13643 priv->vexpand_set ? &ignored : &v);
13644 }
13645 }
13646
13647 priv->need_compute_expand = FALSE;
13648 priv->computed_hexpand = h != FALSE;
13649 priv->computed_vexpand = v != FALSE;
13650 }
13651 }
13652
13653 /**
13654 * gtk_widget_queue_compute_expand:
13655 * @widget: a #GtkWidget
13656 *
13657 * Mark @widget as needing to recompute its expand flags. Call
13658 * this function when setting legacy expand child properties
13659 * on the child of a container.
13660 *
13661 * See gtk_widget_compute_expand().
13662 */
13663 void
gtk_widget_queue_compute_expand(GtkWidget * widget)13664 gtk_widget_queue_compute_expand (GtkWidget *widget)
13665 {
13666 GtkWidget *parent;
13667 gboolean changed_anything;
13668
13669 if (widget->priv->need_compute_expand)
13670 return;
13671
13672 changed_anything = FALSE;
13673 parent = widget;
13674 while (parent != NULL)
13675 {
13676 if (!parent->priv->need_compute_expand)
13677 {
13678 parent->priv->need_compute_expand = TRUE;
13679 changed_anything = TRUE;
13680 }
13681
13682 /* Note: if we had an invariant that "if a child needs to
13683 * compute expand, its parents also do" then we could stop going
13684 * up when we got to a parent that already needed to
13685 * compute. However, in general we compute expand lazily (as
13686 * soon as we see something in a subtree that is expand, we know
13687 * we're expanding) and so this invariant does not hold and we
13688 * have to always walk all the way up in case some ancestor
13689 * is not currently need_compute_expand.
13690 */
13691
13692 parent = parent->priv->parent;
13693 }
13694
13695 /* recomputing expand always requires
13696 * a relayout as well
13697 */
13698 if (changed_anything)
13699 gtk_widget_queue_resize (widget);
13700 }
13701
13702 /**
13703 * gtk_widget_compute_expand:
13704 * @widget: the widget
13705 * @orientation: expand direction
13706 *
13707 * Computes whether a container should give this widget extra space
13708 * when possible. Containers should check this, rather than
13709 * looking at gtk_widget_get_hexpand() or gtk_widget_get_vexpand().
13710 *
13711 * This function already checks whether the widget is visible, so
13712 * visibility does not need to be checked separately. Non-visible
13713 * widgets are not expanded.
13714 *
13715 * The computed expand value uses either the expand setting explicitly
13716 * set on the widget itself, or, if none has been explicitly set,
13717 * the widget may expand if some of its children do.
13718 *
13719 * Returns: whether widget tree rooted here should be expanded
13720 */
13721 gboolean
gtk_widget_compute_expand(GtkWidget * widget,GtkOrientation orientation)13722 gtk_widget_compute_expand (GtkWidget *widget,
13723 GtkOrientation orientation)
13724 {
13725 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
13726
13727 /* We never make a widget expand if not even showing. */
13728 if (!_gtk_widget_get_visible (widget))
13729 return FALSE;
13730
13731 gtk_widget_update_computed_expand (widget);
13732
13733 if (orientation == GTK_ORIENTATION_HORIZONTAL)
13734 return widget->priv->computed_hexpand;
13735 else
13736 return widget->priv->computed_vexpand;
13737 }
13738
13739 static void
gtk_widget_set_expand(GtkWidget * widget,GtkOrientation orientation,gboolean expand)13740 gtk_widget_set_expand (GtkWidget *widget,
13741 GtkOrientation orientation,
13742 gboolean expand)
13743 {
13744 gint expand_prop;
13745 gint expand_set_prop;
13746 gboolean was_both;
13747 GtkWidgetPrivate *priv;
13748
13749 g_return_if_fail (GTK_IS_WIDGET (widget));
13750
13751 priv = widget->priv;
13752
13753 expand = expand != FALSE;
13754
13755 was_both = priv->hexpand && priv->vexpand;
13756
13757 if (orientation == GTK_ORIENTATION_HORIZONTAL)
13758 {
13759 if (priv->hexpand_set &&
13760 priv->hexpand == expand)
13761 return;
13762
13763 priv->hexpand_set = TRUE;
13764 priv->hexpand = expand;
13765
13766 expand_prop = PROP_HEXPAND;
13767 expand_set_prop = PROP_HEXPAND_SET;
13768 }
13769 else
13770 {
13771 if (priv->vexpand_set &&
13772 priv->vexpand == expand)
13773 return;
13774
13775 priv->vexpand_set = TRUE;
13776 priv->vexpand = expand;
13777
13778 expand_prop = PROP_VEXPAND;
13779 expand_set_prop = PROP_VEXPAND_SET;
13780 }
13781
13782 gtk_widget_queue_compute_expand (widget);
13783
13784 g_object_freeze_notify (G_OBJECT (widget));
13785 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[expand_prop]);
13786 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[expand_set_prop]);
13787 if (was_both != (priv->hexpand && priv->vexpand))
13788 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_EXPAND]);
13789 g_object_thaw_notify (G_OBJECT (widget));
13790 }
13791
13792 static void
gtk_widget_set_expand_set(GtkWidget * widget,GtkOrientation orientation,gboolean set)13793 gtk_widget_set_expand_set (GtkWidget *widget,
13794 GtkOrientation orientation,
13795 gboolean set)
13796 {
13797 GtkWidgetPrivate *priv;
13798 gint prop;
13799
13800 priv = widget->priv;
13801
13802 set = set != FALSE;
13803
13804 if (orientation == GTK_ORIENTATION_HORIZONTAL)
13805 {
13806 if (set == priv->hexpand_set)
13807 return;
13808
13809 priv->hexpand_set = set;
13810 prop = PROP_HEXPAND_SET;
13811 }
13812 else
13813 {
13814 if (set == priv->vexpand_set)
13815 return;
13816
13817 priv->vexpand_set = set;
13818 prop = PROP_VEXPAND_SET;
13819 }
13820
13821 gtk_widget_queue_compute_expand (widget);
13822
13823 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[prop]);
13824 }
13825
13826 /**
13827 * gtk_widget_get_hexpand:
13828 * @widget: the widget
13829 *
13830 * Gets whether the widget would like any available extra horizontal
13831 * space. When a user resizes a #GtkWindow, widgets with expand=TRUE
13832 * generally receive the extra space. For example, a list or
13833 * scrollable area or document in your window would often be set to
13834 * expand.
13835 *
13836 * Containers should use gtk_widget_compute_expand() rather than
13837 * this function, to see whether a widget, or any of its children,
13838 * has the expand flag set. If any child of a widget wants to
13839 * expand, the parent may ask to expand also.
13840 *
13841 * This function only looks at the widget’s own hexpand flag, rather
13842 * than computing whether the entire widget tree rooted at this widget
13843 * wants to expand.
13844 *
13845 * Returns: whether hexpand flag is set
13846 */
13847 gboolean
gtk_widget_get_hexpand(GtkWidget * widget)13848 gtk_widget_get_hexpand (GtkWidget *widget)
13849 {
13850 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
13851
13852 return widget->priv->hexpand;
13853 }
13854
13855 /**
13856 * gtk_widget_set_hexpand:
13857 * @widget: the widget
13858 * @expand: whether to expand
13859 *
13860 * Sets whether the widget would like any available extra horizontal
13861 * space. When a user resizes a #GtkWindow, widgets with expand=TRUE
13862 * generally receive the extra space. For example, a list or
13863 * scrollable area or document in your window would often be set to
13864 * expand.
13865 *
13866 * Call this function to set the expand flag if you would like your
13867 * widget to become larger horizontally when the window has extra
13868 * room.
13869 *
13870 * By default, widgets automatically expand if any of their children
13871 * want to expand. (To see if a widget will automatically expand given
13872 * its current children and state, call gtk_widget_compute_expand(). A
13873 * container can decide how the expandability of children affects the
13874 * expansion of the container by overriding the compute_expand virtual
13875 * method on #GtkWidget.).
13876 *
13877 * Setting hexpand explicitly with this function will override the
13878 * automatic expand behavior.
13879 *
13880 * This function forces the widget to expand or not to expand,
13881 * regardless of children. The override occurs because
13882 * gtk_widget_set_hexpand() sets the hexpand-set property (see
13883 * gtk_widget_set_hexpand_set()) which causes the widget’s hexpand
13884 * value to be used, rather than looking at children and widget state.
13885 */
13886 void
gtk_widget_set_hexpand(GtkWidget * widget,gboolean expand)13887 gtk_widget_set_hexpand (GtkWidget *widget,
13888 gboolean expand)
13889 {
13890 g_return_if_fail (GTK_IS_WIDGET (widget));
13891
13892 gtk_widget_set_expand (widget, GTK_ORIENTATION_HORIZONTAL, expand);
13893 }
13894
13895 /**
13896 * gtk_widget_get_hexpand_set:
13897 * @widget: the widget
13898 *
13899 * Gets whether gtk_widget_set_hexpand() has been used to
13900 * explicitly set the expand flag on this widget.
13901 *
13902 * If hexpand is set, then it overrides any computed
13903 * expand value based on child widgets. If hexpand is not
13904 * set, then the expand value depends on whether any
13905 * children of the widget would like to expand.
13906 *
13907 * There are few reasons to use this function, but it’s here
13908 * for completeness and consistency.
13909 *
13910 * Returns: whether hexpand has been explicitly set
13911 */
13912 gboolean
gtk_widget_get_hexpand_set(GtkWidget * widget)13913 gtk_widget_get_hexpand_set (GtkWidget *widget)
13914 {
13915 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
13916
13917 return widget->priv->hexpand_set;
13918 }
13919
13920 /**
13921 * gtk_widget_set_hexpand_set:
13922 * @widget: the widget
13923 * @set: value for hexpand-set property
13924 *
13925 * Sets whether the hexpand flag (see gtk_widget_get_hexpand()) will
13926 * be used.
13927 *
13928 * The hexpand-set property will be set automatically when you call
13929 * gtk_widget_set_hexpand() to set hexpand, so the most likely
13930 * reason to use this function would be to unset an explicit expand
13931 * flag.
13932 *
13933 * If hexpand is set, then it overrides any computed
13934 * expand value based on child widgets. If hexpand is not
13935 * set, then the expand value depends on whether any
13936 * children of the widget would like to expand.
13937 *
13938 * There are few reasons to use this function, but it’s here
13939 * for completeness and consistency.
13940 */
13941 void
gtk_widget_set_hexpand_set(GtkWidget * widget,gboolean set)13942 gtk_widget_set_hexpand_set (GtkWidget *widget,
13943 gboolean set)
13944 {
13945 g_return_if_fail (GTK_IS_WIDGET (widget));
13946
13947 gtk_widget_set_expand_set (widget, GTK_ORIENTATION_HORIZONTAL, set);
13948 }
13949
13950
13951 /**
13952 * gtk_widget_get_vexpand:
13953 * @widget: the widget
13954 *
13955 * Gets whether the widget would like any available extra vertical
13956 * space.
13957 *
13958 * See gtk_widget_get_hexpand() for more detail.
13959 *
13960 * Returns: whether vexpand flag is set
13961 */
13962 gboolean
gtk_widget_get_vexpand(GtkWidget * widget)13963 gtk_widget_get_vexpand (GtkWidget *widget)
13964 {
13965 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
13966
13967 return widget->priv->vexpand;
13968 }
13969
13970 /**
13971 * gtk_widget_set_vexpand:
13972 * @widget: the widget
13973 * @expand: whether to expand
13974 *
13975 * Sets whether the widget would like any available extra vertical
13976 * space.
13977 *
13978 * See gtk_widget_set_hexpand() for more detail.
13979 */
13980 void
gtk_widget_set_vexpand(GtkWidget * widget,gboolean expand)13981 gtk_widget_set_vexpand (GtkWidget *widget,
13982 gboolean expand)
13983 {
13984 g_return_if_fail (GTK_IS_WIDGET (widget));
13985
13986 gtk_widget_set_expand (widget, GTK_ORIENTATION_VERTICAL, expand);
13987 }
13988
13989 /**
13990 * gtk_widget_get_vexpand_set:
13991 * @widget: the widget
13992 *
13993 * Gets whether gtk_widget_set_vexpand() has been used to
13994 * explicitly set the expand flag on this widget.
13995 *
13996 * See gtk_widget_get_hexpand_set() for more detail.
13997 *
13998 * Returns: whether vexpand has been explicitly set
13999 */
14000 gboolean
gtk_widget_get_vexpand_set(GtkWidget * widget)14001 gtk_widget_get_vexpand_set (GtkWidget *widget)
14002 {
14003 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
14004
14005 return widget->priv->vexpand_set;
14006 }
14007
14008 /**
14009 * gtk_widget_set_vexpand_set:
14010 * @widget: the widget
14011 * @set: value for vexpand-set property
14012 *
14013 * Sets whether the vexpand flag (see gtk_widget_get_vexpand()) will
14014 * be used.
14015 *
14016 * See gtk_widget_set_hexpand_set() for more detail.
14017 */
14018 void
gtk_widget_set_vexpand_set(GtkWidget * widget,gboolean set)14019 gtk_widget_set_vexpand_set (GtkWidget *widget,
14020 gboolean set)
14021 {
14022 g_return_if_fail (GTK_IS_WIDGET (widget));
14023
14024 gtk_widget_set_expand_set (widget, GTK_ORIENTATION_VERTICAL, set);
14025 }
14026
14027 /*
14028 * GtkBuildable implementation
14029 */
14030 static GQuark quark_builder_has_default = 0;
14031 static GQuark quark_builder_has_focus = 0;
14032 static GQuark quark_builder_atk_relations = 0;
14033 static GQuark quark_builder_set_name = 0;
14034
14035 static void
gtk_widget_buildable_interface_init(GtkBuildableIface * iface)14036 gtk_widget_buildable_interface_init (GtkBuildableIface *iface)
14037 {
14038 quark_builder_has_default = g_quark_from_static_string ("gtk-builder-has-default");
14039 quark_builder_has_focus = g_quark_from_static_string ("gtk-builder-has-focus");
14040 quark_builder_atk_relations = g_quark_from_static_string ("gtk-builder-atk-relations");
14041 quark_builder_set_name = g_quark_from_static_string ("gtk-builder-set-name");
14042
14043 iface->set_name = gtk_widget_buildable_set_name;
14044 iface->get_name = gtk_widget_buildable_get_name;
14045 iface->get_internal_child = gtk_widget_buildable_get_internal_child;
14046 iface->set_buildable_property = gtk_widget_buildable_set_buildable_property;
14047 iface->parser_finished = gtk_widget_buildable_parser_finished;
14048 iface->custom_tag_start = gtk_widget_buildable_custom_tag_start;
14049 iface->custom_finished = gtk_widget_buildable_custom_finished;
14050 }
14051
14052 static void
gtk_widget_buildable_set_name(GtkBuildable * buildable,const gchar * name)14053 gtk_widget_buildable_set_name (GtkBuildable *buildable,
14054 const gchar *name)
14055 {
14056 g_object_set_qdata_full (G_OBJECT (buildable), quark_builder_set_name,
14057 g_strdup (name), g_free);
14058 }
14059
14060 static const gchar *
gtk_widget_buildable_get_name(GtkBuildable * buildable)14061 gtk_widget_buildable_get_name (GtkBuildable *buildable)
14062 {
14063 return g_object_get_qdata (G_OBJECT (buildable), quark_builder_set_name);
14064 }
14065
14066 static GObject *
gtk_widget_buildable_get_internal_child(GtkBuildable * buildable,GtkBuilder * builder,const gchar * childname)14067 gtk_widget_buildable_get_internal_child (GtkBuildable *buildable,
14068 GtkBuilder *builder,
14069 const gchar *childname)
14070 {
14071 GtkWidgetClass *class;
14072 GSList *l;
14073 GType internal_child_type = 0;
14074
14075 if (strcmp (childname, "accessible") == 0)
14076 return G_OBJECT (gtk_widget_get_accessible (GTK_WIDGET (buildable)));
14077
14078 /* Find a widget type which has declared an automated child as internal by
14079 * the name 'childname', if any.
14080 */
14081 for (class = GTK_WIDGET_GET_CLASS (buildable);
14082 GTK_IS_WIDGET_CLASS (class);
14083 class = g_type_class_peek_parent (class))
14084 {
14085 GtkWidgetTemplate *template = class->priv->template;
14086
14087 if (!template)
14088 continue;
14089
14090 for (l = template->children; l && internal_child_type == 0; l = l->next)
14091 {
14092 AutomaticChildClass *child_class = l->data;
14093
14094 if (child_class->internal_child && strcmp (childname, child_class->name) == 0)
14095 internal_child_type = G_OBJECT_CLASS_TYPE (class);
14096 }
14097 }
14098
14099 /* Now return the 'internal-child' from the class which declared it, note
14100 * that gtk_widget_get_template_child() an API used to access objects
14101 * which are in the private scope of a given class.
14102 */
14103 if (internal_child_type != 0)
14104 return gtk_widget_get_template_child (GTK_WIDGET (buildable), internal_child_type, childname);
14105
14106 return NULL;
14107 }
14108
14109 static void
gtk_widget_buildable_set_buildable_property(GtkBuildable * buildable,GtkBuilder * builder,const gchar * name,const GValue * value)14110 gtk_widget_buildable_set_buildable_property (GtkBuildable *buildable,
14111 GtkBuilder *builder,
14112 const gchar *name,
14113 const GValue *value)
14114 {
14115 if (strcmp (name, "has-default") == 0 && g_value_get_boolean (value))
14116 g_object_set_qdata (G_OBJECT (buildable), quark_builder_has_default,
14117 GINT_TO_POINTER (TRUE));
14118 else if (strcmp (name, "has-focus") == 0 && g_value_get_boolean (value))
14119 g_object_set_qdata (G_OBJECT (buildable), quark_builder_has_focus,
14120 GINT_TO_POINTER (TRUE));
14121 else
14122 g_object_set_property (G_OBJECT (buildable), name, value);
14123 }
14124
14125 typedef struct
14126 {
14127 gchar *action_name;
14128 GString *description;
14129 gchar *context;
14130 gboolean translatable;
14131 } AtkActionData;
14132
14133 typedef struct
14134 {
14135 gchar *target;
14136 AtkRelationType type;
14137 gint line;
14138 gint col;
14139 } AtkRelationData;
14140
14141 static void
free_action(AtkActionData * data,gpointer user_data)14142 free_action (AtkActionData *data, gpointer user_data)
14143 {
14144 g_free (data->action_name);
14145 g_string_free (data->description, TRUE);
14146 g_free (data->context);
14147 g_slice_free (AtkActionData, data);
14148 }
14149
14150 static void
free_relation(AtkRelationData * data,gpointer user_data)14151 free_relation (AtkRelationData *data, gpointer user_data)
14152 {
14153 g_free (data->target);
14154 g_slice_free (AtkRelationData, data);
14155 }
14156
14157 static void
gtk_widget_buildable_parser_finished(GtkBuildable * buildable,GtkBuilder * builder)14158 gtk_widget_buildable_parser_finished (GtkBuildable *buildable,
14159 GtkBuilder *builder)
14160 {
14161 GSList *atk_relations;
14162
14163 if (g_object_get_qdata (G_OBJECT (buildable), quark_builder_has_default))
14164 {
14165 gtk_widget_grab_default (GTK_WIDGET (buildable));
14166 g_object_steal_qdata (G_OBJECT (buildable), quark_builder_has_default);
14167 }
14168
14169 if (g_object_get_qdata (G_OBJECT (buildable), quark_builder_has_focus))
14170 {
14171 gtk_widget_grab_focus (GTK_WIDGET (buildable));
14172 g_object_steal_qdata (G_OBJECT (buildable), quark_builder_has_focus);
14173 }
14174
14175 atk_relations = g_object_get_qdata (G_OBJECT (buildable),
14176 quark_builder_atk_relations);
14177 if (atk_relations)
14178 {
14179 AtkObject *accessible;
14180 AtkRelationSet *relation_set;
14181 GSList *l;
14182 GObject *target;
14183 AtkObject *target_accessible;
14184
14185 accessible = gtk_widget_get_accessible (GTK_WIDGET (buildable));
14186 relation_set = atk_object_ref_relation_set (accessible);
14187
14188 for (l = atk_relations; l; l = l->next)
14189 {
14190 AtkRelationData *relation = (AtkRelationData*)l->data;
14191
14192 target = _gtk_builder_lookup_object (builder, relation->target, relation->line, relation->col);
14193 if (!target)
14194 continue;
14195 target_accessible = gtk_widget_get_accessible (GTK_WIDGET (target));
14196 g_assert (target_accessible != NULL);
14197
14198 atk_relation_set_add_relation_by_type (relation_set, relation->type, target_accessible);
14199 }
14200 g_object_unref (relation_set);
14201
14202 g_slist_free_full (atk_relations, (GDestroyNotify) free_relation);
14203 g_object_steal_qdata (G_OBJECT (buildable), quark_builder_atk_relations);
14204 }
14205 }
14206
14207 typedef struct
14208 {
14209 GtkBuilder *builder;
14210 GSList *actions;
14211 GSList *relations;
14212 } AccessibilitySubParserData;
14213
14214 static void
accessibility_start_element(GMarkupParseContext * context,const gchar * element_name,const gchar ** names,const gchar ** values,gpointer user_data,GError ** error)14215 accessibility_start_element (GMarkupParseContext *context,
14216 const gchar *element_name,
14217 const gchar **names,
14218 const gchar **values,
14219 gpointer user_data,
14220 GError **error)
14221 {
14222 AccessibilitySubParserData *data = (AccessibilitySubParserData*)user_data;
14223
14224 if (strcmp (element_name, "relation") == 0)
14225 {
14226 gchar *target = NULL;
14227 gchar *type = NULL;
14228 AtkRelationData *relation;
14229 AtkRelationType relation_type;
14230
14231 if (!_gtk_builder_check_parent (data->builder, context, "accessibility", error))
14232 return;
14233
14234 if (!g_markup_collect_attributes (element_name, names, values, error,
14235 G_MARKUP_COLLECT_STRING, "target", &target,
14236 G_MARKUP_COLLECT_STRING, "type", &type,
14237 G_MARKUP_COLLECT_INVALID))
14238 {
14239 _gtk_builder_prefix_error (data->builder, context, error);
14240 return;
14241 }
14242
14243 relation_type = atk_relation_type_for_name (type);
14244 if (relation_type == ATK_RELATION_NULL)
14245 {
14246 g_set_error (error,
14247 GTK_BUILDER_ERROR,
14248 GTK_BUILDER_ERROR_INVALID_VALUE,
14249 "No such relation type: '%s'", type);
14250 _gtk_builder_prefix_error (data->builder, context, error);
14251 return;
14252 }
14253
14254 relation = g_slice_new (AtkRelationData);
14255 relation->target = g_strdup (target);
14256 relation->type = relation_type;
14257
14258 data->relations = g_slist_prepend (data->relations, relation);
14259 }
14260 else if (strcmp (element_name, "action") == 0)
14261 {
14262 const gchar *action_name;
14263 const gchar *description = NULL;
14264 const gchar *msg_context = NULL;
14265 gboolean translatable = FALSE;
14266 AtkActionData *action;
14267
14268 if (!_gtk_builder_check_parent (data->builder, context, "accessibility", error))
14269 return;
14270
14271 if (!g_markup_collect_attributes (element_name, names, values, error,
14272 G_MARKUP_COLLECT_STRING, "action_name", &action_name,
14273 G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "description", &description,
14274 G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "comments", NULL,
14275 G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "context", &msg_context,
14276 G_MARKUP_COLLECT_BOOLEAN|G_MARKUP_COLLECT_OPTIONAL, "translatable", &translatable,
14277 G_MARKUP_COLLECT_INVALID))
14278 {
14279 _gtk_builder_prefix_error (data->builder, context, error);
14280 return;
14281 }
14282
14283 action = g_slice_new (AtkActionData);
14284 action->action_name = g_strdup (action_name);
14285 action->description = g_string_new (description);
14286 action->context = g_strdup (msg_context);
14287 action->translatable = translatable;
14288
14289 data->actions = g_slist_prepend (data->actions, action);
14290 }
14291 else if (strcmp (element_name, "accessibility") == 0)
14292 {
14293 if (!_gtk_builder_check_parent (data->builder, context, "object", error))
14294 return;
14295
14296 if (!g_markup_collect_attributes (element_name, names, values, error,
14297 G_MARKUP_COLLECT_INVALID, NULL, NULL,
14298 G_MARKUP_COLLECT_INVALID))
14299 _gtk_builder_prefix_error (data->builder, context, error);
14300 }
14301 else
14302 {
14303 _gtk_builder_error_unhandled_tag (data->builder, context,
14304 "GtkWidget", element_name,
14305 error);
14306 }
14307 }
14308
14309 static void
accessibility_text(GMarkupParseContext * context,const gchar * text,gsize text_len,gpointer user_data,GError ** error)14310 accessibility_text (GMarkupParseContext *context,
14311 const gchar *text,
14312 gsize text_len,
14313 gpointer user_data,
14314 GError **error)
14315 {
14316 AccessibilitySubParserData *data = (AccessibilitySubParserData*)user_data;
14317
14318 if (strcmp (g_markup_parse_context_get_element (context), "action") == 0)
14319 {
14320 AtkActionData *action = data->actions->data;
14321
14322 g_string_append_len (action->description, text, text_len);
14323 }
14324 }
14325
14326 static const GMarkupParser accessibility_parser =
14327 {
14328 accessibility_start_element,
14329 NULL,
14330 accessibility_text,
14331 };
14332
14333 typedef struct
14334 {
14335 GObject *object;
14336 GtkBuilder *builder;
14337 guint key;
14338 guint modifiers;
14339 gchar *signal;
14340 } AccelGroupParserData;
14341
14342 static void
accel_group_start_element(GMarkupParseContext * context,const gchar * element_name,const gchar ** names,const gchar ** values,gpointer user_data,GError ** error)14343 accel_group_start_element (GMarkupParseContext *context,
14344 const gchar *element_name,
14345 const gchar **names,
14346 const gchar **values,
14347 gpointer user_data,
14348 GError **error)
14349 {
14350 AccelGroupParserData *data = (AccelGroupParserData*)user_data;
14351
14352 if (strcmp (element_name, "accelerator") == 0)
14353 {
14354 const gchar *key_str = NULL;
14355 const gchar *signal = NULL;
14356 const gchar *modifiers_str = NULL;
14357 guint key = 0;
14358 guint modifiers = 0;
14359
14360 if (!_gtk_builder_check_parent (data->builder, context, "object", error))
14361 return;
14362
14363 if (!g_markup_collect_attributes (element_name, names, values, error,
14364 G_MARKUP_COLLECT_STRING, "key", &key_str,
14365 G_MARKUP_COLLECT_STRING, "signal", &signal,
14366 G_MARKUP_COLLECT_STRING|G_MARKUP_COLLECT_OPTIONAL, "modifiers", &modifiers_str,
14367 G_MARKUP_COLLECT_INVALID))
14368 {
14369 _gtk_builder_prefix_error (data->builder, context, error);
14370 return;
14371 }
14372
14373 key = gdk_keyval_from_name (key_str);
14374 if (key == 0)
14375 {
14376 g_set_error (error,
14377 GTK_BUILDER_ERROR, GTK_BUILDER_ERROR_INVALID_VALUE,
14378 "Could not parse key '%s'", key_str);
14379 _gtk_builder_prefix_error (data->builder, context, error);
14380 return;
14381 }
14382
14383 if (modifiers_str != NULL)
14384 {
14385 GFlagsValue aliases[2] = {
14386 { 0, "primary", "primary" },
14387 { 0, NULL, NULL }
14388 };
14389
14390 aliases[0].value = _gtk_get_primary_accel_mod ();
14391
14392 if (!_gtk_builder_flags_from_string (GDK_TYPE_MODIFIER_TYPE, aliases,
14393 modifiers_str, &modifiers, error))
14394 {
14395 _gtk_builder_prefix_error (data->builder, context, error);
14396 return;
14397 }
14398 }
14399
14400 data->key = key;
14401 data->modifiers = modifiers;
14402 data->signal = g_strdup (signal);
14403 }
14404 else
14405 {
14406 _gtk_builder_error_unhandled_tag (data->builder, context,
14407 "GtkWidget", element_name,
14408 error);
14409 }
14410 }
14411
14412 static const GMarkupParser accel_group_parser =
14413 {
14414 accel_group_start_element,
14415 };
14416
14417 typedef struct
14418 {
14419 GtkBuilder *builder;
14420 GSList *classes;
14421 } StyleParserData;
14422
14423 static void
style_start_element(GMarkupParseContext * context,const gchar * element_name,const gchar ** names,const gchar ** values,gpointer user_data,GError ** error)14424 style_start_element (GMarkupParseContext *context,
14425 const gchar *element_name,
14426 const gchar **names,
14427 const gchar **values,
14428 gpointer user_data,
14429 GError **error)
14430 {
14431 StyleParserData *data = (StyleParserData *)user_data;
14432
14433 if (strcmp (element_name, "class") == 0)
14434 {
14435 const gchar *name;
14436
14437 if (!_gtk_builder_check_parent (data->builder, context, "style", error))
14438 return;
14439
14440 if (!g_markup_collect_attributes (element_name, names, values, error,
14441 G_MARKUP_COLLECT_STRING, "name", &name,
14442 G_MARKUP_COLLECT_INVALID))
14443 {
14444 _gtk_builder_prefix_error (data->builder, context, error);
14445 return;
14446 }
14447
14448 data->classes = g_slist_prepend (data->classes, g_strdup (name));
14449 }
14450 else if (strcmp (element_name, "style") == 0)
14451 {
14452 if (!_gtk_builder_check_parent (data->builder, context, "object", error))
14453 return;
14454
14455 if (!g_markup_collect_attributes (element_name, names, values, error,
14456 G_MARKUP_COLLECT_INVALID, NULL, NULL,
14457 G_MARKUP_COLLECT_INVALID))
14458 _gtk_builder_prefix_error (data->builder, context, error);
14459 }
14460 else
14461 {
14462 _gtk_builder_error_unhandled_tag (data->builder, context,
14463 "GtkWidget", element_name,
14464 error);
14465 }
14466 }
14467
14468 static const GMarkupParser style_parser =
14469 {
14470 style_start_element,
14471 };
14472
14473 static gboolean
gtk_widget_buildable_custom_tag_start(GtkBuildable * buildable,GtkBuilder * builder,GObject * child,const gchar * tagname,GMarkupParser * parser,gpointer * parser_data)14474 gtk_widget_buildable_custom_tag_start (GtkBuildable *buildable,
14475 GtkBuilder *builder,
14476 GObject *child,
14477 const gchar *tagname,
14478 GMarkupParser *parser,
14479 gpointer *parser_data)
14480 {
14481 if (strcmp (tagname, "accelerator") == 0)
14482 {
14483 AccelGroupParserData *data;
14484
14485 data = g_slice_new0 (AccelGroupParserData);
14486 data->object = G_OBJECT (g_object_ref (buildable));
14487 data->builder = builder;
14488
14489 *parser = accel_group_parser;
14490 *parser_data = data;
14491
14492 return TRUE;
14493 }
14494
14495 if (strcmp (tagname, "accessibility") == 0)
14496 {
14497 AccessibilitySubParserData *data;
14498
14499 data = g_slice_new0 (AccessibilitySubParserData);
14500 data->builder = builder;
14501
14502 *parser = accessibility_parser;
14503 *parser_data = data;
14504
14505 return TRUE;
14506 }
14507
14508 if (strcmp (tagname, "style") == 0)
14509 {
14510 StyleParserData *data;
14511
14512 data = g_slice_new0 (StyleParserData);
14513 data->builder = builder;
14514
14515 *parser = style_parser;
14516 *parser_data = data;
14517
14518 return TRUE;
14519 }
14520
14521 return FALSE;
14522 }
14523
14524 void
_gtk_widget_buildable_finish_accelerator(GtkWidget * widget,GtkWidget * toplevel,gpointer user_data)14525 _gtk_widget_buildable_finish_accelerator (GtkWidget *widget,
14526 GtkWidget *toplevel,
14527 gpointer user_data)
14528 {
14529 AccelGroupParserData *accel_data;
14530 GSList *accel_groups;
14531 GtkAccelGroup *accel_group;
14532
14533 g_return_if_fail (GTK_IS_WIDGET (widget));
14534 g_return_if_fail (GTK_IS_WIDGET (toplevel));
14535 g_return_if_fail (user_data != NULL);
14536
14537 accel_data = (AccelGroupParserData*)user_data;
14538 accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel));
14539 if (g_slist_length (accel_groups) == 0)
14540 {
14541 accel_group = gtk_accel_group_new ();
14542 gtk_window_add_accel_group (GTK_WINDOW (toplevel), accel_group);
14543 }
14544 else
14545 {
14546 g_assert (g_slist_length (accel_groups) == 1);
14547 accel_group = g_slist_nth_data (accel_groups, 0);
14548 }
14549
14550 gtk_widget_add_accelerator (GTK_WIDGET (accel_data->object),
14551 accel_data->signal,
14552 accel_group,
14553 accel_data->key,
14554 accel_data->modifiers,
14555 GTK_ACCEL_VISIBLE);
14556
14557 g_object_unref (accel_data->object);
14558 g_free (accel_data->signal);
14559 g_slice_free (AccelGroupParserData, accel_data);
14560 }
14561
14562 static void
gtk_widget_buildable_custom_finished(GtkBuildable * buildable,GtkBuilder * builder,GObject * child,const gchar * tagname,gpointer user_data)14563 gtk_widget_buildable_custom_finished (GtkBuildable *buildable,
14564 GtkBuilder *builder,
14565 GObject *child,
14566 const gchar *tagname,
14567 gpointer user_data)
14568 {
14569 if (strcmp (tagname, "accelerator") == 0)
14570 {
14571 AccelGroupParserData *accel_data;
14572 GtkWidget *toplevel;
14573
14574 accel_data = (AccelGroupParserData*)user_data;
14575 g_assert (accel_data->object);
14576
14577 toplevel = _gtk_widget_get_toplevel (GTK_WIDGET (accel_data->object));
14578
14579 _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), toplevel, user_data);
14580 }
14581 else if (strcmp (tagname, "accessibility") == 0)
14582 {
14583 AccessibilitySubParserData *a11y_data;
14584
14585 a11y_data = (AccessibilitySubParserData*)user_data;
14586
14587 if (a11y_data->actions)
14588 {
14589 AtkObject *accessible;
14590 AtkAction *action;
14591 gint i, n_actions;
14592 GSList *l;
14593
14594 accessible = gtk_widget_get_accessible (GTK_WIDGET (buildable));
14595
14596 if (ATK_IS_ACTION (accessible))
14597 {
14598 action = ATK_ACTION (accessible);
14599 n_actions = atk_action_get_n_actions (action);
14600
14601 for (l = a11y_data->actions; l; l = l->next)
14602 {
14603 AtkActionData *action_data = (AtkActionData*)l->data;
14604
14605 for (i = 0; i < n_actions; i++)
14606 if (strcmp (atk_action_get_name (action, i),
14607 action_data->action_name) == 0)
14608 break;
14609
14610 if (i < n_actions)
14611 {
14612 const gchar *description;
14613
14614 if (action_data->translatable && action_data->description->len)
14615 description = _gtk_builder_parser_translate (gtk_builder_get_translation_domain (builder),
14616 action_data->context,
14617 action_data->description->str);
14618 else
14619 description = action_data->description->str;
14620
14621 atk_action_set_description (action, i, description);
14622 }
14623 }
14624 }
14625 else
14626 g_warning ("accessibility action on a widget that does not implement AtkAction");
14627
14628 g_slist_free_full (a11y_data->actions, (GDestroyNotify) free_action);
14629 }
14630
14631 if (a11y_data->relations)
14632 g_object_set_qdata (G_OBJECT (buildable), quark_builder_atk_relations,
14633 a11y_data->relations);
14634
14635 g_slice_free (AccessibilitySubParserData, a11y_data);
14636 }
14637 else if (strcmp (tagname, "style") == 0)
14638 {
14639 StyleParserData *style_data = (StyleParserData *)user_data;
14640 GtkStyleContext *context;
14641 GSList *l;
14642
14643 context = _gtk_widget_get_style_context (GTK_WIDGET (buildable));
14644
14645 for (l = style_data->classes; l; l = l->next)
14646 gtk_style_context_add_class (context, (const gchar *)l->data);
14647
14648 gtk_widget_reset_style (GTK_WIDGET (buildable));
14649
14650 g_slist_free_full (style_data->classes, g_free);
14651 g_slice_free (StyleParserData, style_data);
14652 }
14653 }
14654
14655 static GtkSizeRequestMode
gtk_widget_real_get_request_mode(GtkWidget * widget)14656 gtk_widget_real_get_request_mode (GtkWidget *widget)
14657 {
14658 /* By default widgets don't trade size at all. */
14659 return GTK_SIZE_REQUEST_CONSTANT_SIZE;
14660 }
14661
14662 static void
gtk_widget_real_get_width(GtkWidget * widget,gint * minimum_size,gint * natural_size)14663 gtk_widget_real_get_width (GtkWidget *widget,
14664 gint *minimum_size,
14665 gint *natural_size)
14666 {
14667 *minimum_size = 0;
14668 *natural_size = 0;
14669 }
14670
14671 static void
gtk_widget_real_get_height(GtkWidget * widget,gint * minimum_size,gint * natural_size)14672 gtk_widget_real_get_height (GtkWidget *widget,
14673 gint *minimum_size,
14674 gint *natural_size)
14675 {
14676 *minimum_size = 0;
14677 *natural_size = 0;
14678 }
14679
14680 static void
gtk_widget_real_get_height_for_width(GtkWidget * widget,gint width,gint * minimum_height,gint * natural_height)14681 gtk_widget_real_get_height_for_width (GtkWidget *widget,
14682 gint width,
14683 gint *minimum_height,
14684 gint *natural_height)
14685 {
14686 GTK_WIDGET_GET_CLASS (widget)->get_preferred_height (widget, minimum_height, natural_height);
14687 }
14688
14689 static void
gtk_widget_real_get_width_for_height(GtkWidget * widget,gint height,gint * minimum_width,gint * natural_width)14690 gtk_widget_real_get_width_for_height (GtkWidget *widget,
14691 gint height,
14692 gint *minimum_width,
14693 gint *natural_width)
14694 {
14695 GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, minimum_width, natural_width);
14696 }
14697
14698 /**
14699 * gtk_widget_get_halign:
14700 * @widget: a #GtkWidget
14701 *
14702 * Gets the value of the #GtkWidget:halign property.
14703 *
14704 * For backwards compatibility reasons this method will never return
14705 * %GTK_ALIGN_BASELINE, but instead it will convert it to
14706 * %GTK_ALIGN_FILL. Baselines are not supported for horizontal
14707 * alignment.
14708 *
14709 * Returns: the horizontal alignment of @widget
14710 */
14711 GtkAlign
gtk_widget_get_halign(GtkWidget * widget)14712 gtk_widget_get_halign (GtkWidget *widget)
14713 {
14714 GtkAlign align;
14715
14716 g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_ALIGN_FILL);
14717
14718 align = widget->priv->halign;
14719 if (align == GTK_ALIGN_BASELINE)
14720 return GTK_ALIGN_FILL;
14721 return align;
14722 }
14723
14724 /**
14725 * gtk_widget_set_halign:
14726 * @widget: a #GtkWidget
14727 * @align: the horizontal alignment
14728 *
14729 * Sets the horizontal alignment of @widget.
14730 * See the #GtkWidget:halign property.
14731 */
14732 void
gtk_widget_set_halign(GtkWidget * widget,GtkAlign align)14733 gtk_widget_set_halign (GtkWidget *widget,
14734 GtkAlign align)
14735 {
14736 g_return_if_fail (GTK_IS_WIDGET (widget));
14737
14738 if (widget->priv->halign == align)
14739 return;
14740
14741 widget->priv->halign = align;
14742 gtk_widget_queue_allocate (widget);
14743 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HALIGN]);
14744 }
14745
14746 /**
14747 * gtk_widget_get_valign_with_baseline:
14748 * @widget: a #GtkWidget
14749 *
14750 * Gets the value of the #GtkWidget:valign property, including
14751 * %GTK_ALIGN_BASELINE.
14752 *
14753 * Returns: the vertical alignment of @widget
14754 *
14755 * Since: 3.10
14756 */
14757 GtkAlign
gtk_widget_get_valign_with_baseline(GtkWidget * widget)14758 gtk_widget_get_valign_with_baseline (GtkWidget *widget)
14759 {
14760 g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_ALIGN_FILL);
14761 return widget->priv->valign;
14762 }
14763
14764 /**
14765 * gtk_widget_get_valign:
14766 * @widget: a #GtkWidget
14767 *
14768 * Gets the value of the #GtkWidget:valign property.
14769 *
14770 * For backwards compatibility reasons this method will never return
14771 * %GTK_ALIGN_BASELINE, but instead it will convert it to
14772 * %GTK_ALIGN_FILL. If your widget want to support baseline aligned
14773 * children it must use gtk_widget_get_valign_with_baseline(), or
14774 * `g_object_get (widget, "valign", &value, NULL)`, which will
14775 * also report the true value.
14776 *
14777 * Returns: the vertical alignment of @widget, ignoring baseline alignment
14778 */
14779 GtkAlign
gtk_widget_get_valign(GtkWidget * widget)14780 gtk_widget_get_valign (GtkWidget *widget)
14781 {
14782 GtkAlign align;
14783
14784 align = gtk_widget_get_valign_with_baseline (widget);
14785 if (align == GTK_ALIGN_BASELINE)
14786 return GTK_ALIGN_FILL;
14787 return align;
14788 }
14789
14790 /**
14791 * gtk_widget_set_valign:
14792 * @widget: a #GtkWidget
14793 * @align: the vertical alignment
14794 *
14795 * Sets the vertical alignment of @widget.
14796 * See the #GtkWidget:valign property.
14797 */
14798 void
gtk_widget_set_valign(GtkWidget * widget,GtkAlign align)14799 gtk_widget_set_valign (GtkWidget *widget,
14800 GtkAlign align)
14801 {
14802 g_return_if_fail (GTK_IS_WIDGET (widget));
14803
14804 if (widget->priv->valign == align)
14805 return;
14806
14807 widget->priv->valign = align;
14808 gtk_widget_queue_allocate (widget);
14809 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_VALIGN]);
14810 }
14811
14812 /**
14813 * gtk_widget_get_margin_left:
14814 * @widget: a #GtkWidget
14815 *
14816 * Gets the value of the #GtkWidget:margin-left property.
14817 *
14818 * Returns: The left margin of @widget
14819 *
14820 * Deprecated: 3.12: Use gtk_widget_get_margin_start() instead.
14821 *
14822 * Since: 3.0
14823 */
14824 gint
gtk_widget_get_margin_left(GtkWidget * widget)14825 gtk_widget_get_margin_left (GtkWidget *widget)
14826 {
14827 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
14828
14829 return widget->priv->margin.left;
14830 }
14831
14832 /**
14833 * gtk_widget_set_margin_left:
14834 * @widget: a #GtkWidget
14835 * @margin: the left margin
14836 *
14837 * Sets the left margin of @widget.
14838 * See the #GtkWidget:margin-left property.
14839 *
14840 * Deprecated: 3.12: Use gtk_widget_set_margin_start() instead.
14841 *
14842 * Since: 3.0
14843 */
14844 void
gtk_widget_set_margin_left(GtkWidget * widget,gint margin)14845 gtk_widget_set_margin_left (GtkWidget *widget,
14846 gint margin)
14847 {
14848 gboolean rtl;
14849
14850 g_return_if_fail (GTK_IS_WIDGET (widget));
14851 g_return_if_fail (margin <= G_MAXINT16);
14852
14853 rtl = _gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
14854
14855 if (widget->priv->margin.left == margin)
14856 return;
14857
14858 widget->priv->margin.left = margin;
14859 gtk_widget_queue_resize (widget);
14860 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_MARGIN_LEFT]);
14861 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[rtl ? PROP_MARGIN_END : PROP_MARGIN_START]);
14862 }
14863
14864 /**
14865 * gtk_widget_get_margin_right:
14866 * @widget: a #GtkWidget
14867 *
14868 * Gets the value of the #GtkWidget:margin-right property.
14869 *
14870 * Returns: The right margin of @widget
14871 *
14872 * Deprecated: 3.12: Use gtk_widget_get_margin_end() instead.
14873 *
14874 * Since: 3.0
14875 */
14876 gint
gtk_widget_get_margin_right(GtkWidget * widget)14877 gtk_widget_get_margin_right (GtkWidget *widget)
14878 {
14879 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
14880
14881 return widget->priv->margin.right;
14882 }
14883
14884 /**
14885 * gtk_widget_set_margin_right:
14886 * @widget: a #GtkWidget
14887 * @margin: the right margin
14888 *
14889 * Sets the right margin of @widget.
14890 * See the #GtkWidget:margin-right property.
14891 *
14892 * Deprecated: 3.12: Use gtk_widget_set_margin_end() instead.
14893 *
14894 * Since: 3.0
14895 */
14896 void
gtk_widget_set_margin_right(GtkWidget * widget,gint margin)14897 gtk_widget_set_margin_right (GtkWidget *widget,
14898 gint margin)
14899 {
14900 gboolean rtl;
14901
14902 g_return_if_fail (GTK_IS_WIDGET (widget));
14903 g_return_if_fail (margin <= G_MAXINT16);
14904
14905 rtl = _gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
14906
14907 if (widget->priv->margin.right == margin)
14908 return;
14909
14910 widget->priv->margin.right = margin;
14911 gtk_widget_queue_resize (widget);
14912 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_MARGIN_RIGHT]);
14913 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[rtl ? PROP_MARGIN_START : PROP_MARGIN_END]);
14914 }
14915
14916 /**
14917 * gtk_widget_get_margin_start:
14918 * @widget: a #GtkWidget
14919 *
14920 * Gets the value of the #GtkWidget:margin-start property.
14921 *
14922 * Returns: The start margin of @widget
14923 *
14924 * Since: 3.12
14925 */
14926 gint
gtk_widget_get_margin_start(GtkWidget * widget)14927 gtk_widget_get_margin_start (GtkWidget *widget)
14928 {
14929 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
14930
14931 if (_gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
14932 return widget->priv->margin.right;
14933 else
14934 return widget->priv->margin.left;
14935 }
14936
14937 /**
14938 * gtk_widget_set_margin_start:
14939 * @widget: a #GtkWidget
14940 * @margin: the start margin
14941 *
14942 * Sets the start margin of @widget.
14943 * See the #GtkWidget:margin-start property.
14944 *
14945 * Since: 3.12
14946 */
14947 void
gtk_widget_set_margin_start(GtkWidget * widget,gint margin)14948 gtk_widget_set_margin_start (GtkWidget *widget,
14949 gint margin)
14950 {
14951 gint16 *start;
14952 gboolean rtl;
14953
14954 g_return_if_fail (GTK_IS_WIDGET (widget));
14955 g_return_if_fail (margin <= G_MAXINT16);
14956
14957 rtl = _gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
14958
14959 if (rtl)
14960 start = &widget->priv->margin.right;
14961 else
14962 start = &widget->priv->margin.left;
14963
14964 if (*start == margin)
14965 return;
14966
14967 *start = margin;
14968 gtk_widget_queue_resize (widget);
14969 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_MARGIN_START]);
14970 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[rtl ? PROP_MARGIN_RIGHT : PROP_MARGIN_LEFT]);
14971 }
14972
14973 /**
14974 * gtk_widget_get_margin_end:
14975 * @widget: a #GtkWidget
14976 *
14977 * Gets the value of the #GtkWidget:margin-end property.
14978 *
14979 * Returns: The end margin of @widget
14980 *
14981 * Since: 3.12
14982 */
14983 gint
gtk_widget_get_margin_end(GtkWidget * widget)14984 gtk_widget_get_margin_end (GtkWidget *widget)
14985 {
14986 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
14987
14988 if (_gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
14989 return widget->priv->margin.left;
14990 else
14991 return widget->priv->margin.right;
14992 }
14993
14994 /**
14995 * gtk_widget_set_margin_end:
14996 * @widget: a #GtkWidget
14997 * @margin: the end margin
14998 *
14999 * Sets the end margin of @widget.
15000 * See the #GtkWidget:margin-end property.
15001 *
15002 * Since: 3.12
15003 */
15004 void
gtk_widget_set_margin_end(GtkWidget * widget,gint margin)15005 gtk_widget_set_margin_end (GtkWidget *widget,
15006 gint margin)
15007 {
15008 gint16 *end;
15009 gboolean rtl;
15010
15011 g_return_if_fail (GTK_IS_WIDGET (widget));
15012 g_return_if_fail (margin <= G_MAXINT16);
15013
15014 rtl = _gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL;
15015
15016 if (rtl)
15017 end = &widget->priv->margin.left;
15018 else
15019 end = &widget->priv->margin.right;
15020
15021 if (*end == margin)
15022 return;
15023
15024 *end = margin;
15025 gtk_widget_queue_resize (widget);
15026 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_MARGIN_END]);
15027 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[rtl ? PROP_MARGIN_LEFT : PROP_MARGIN_RIGHT]);
15028 }
15029
15030 /**
15031 * gtk_widget_get_margin_top:
15032 * @widget: a #GtkWidget
15033 *
15034 * Gets the value of the #GtkWidget:margin-top property.
15035 *
15036 * Returns: The top margin of @widget
15037 *
15038 * Since: 3.0
15039 */
15040 gint
gtk_widget_get_margin_top(GtkWidget * widget)15041 gtk_widget_get_margin_top (GtkWidget *widget)
15042 {
15043 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
15044
15045 return widget->priv->margin.top;
15046 }
15047
15048 /**
15049 * gtk_widget_set_margin_top:
15050 * @widget: a #GtkWidget
15051 * @margin: the top margin
15052 *
15053 * Sets the top margin of @widget.
15054 * See the #GtkWidget:margin-top property.
15055 *
15056 * Since: 3.0
15057 */
15058 void
gtk_widget_set_margin_top(GtkWidget * widget,gint margin)15059 gtk_widget_set_margin_top (GtkWidget *widget,
15060 gint margin)
15061 {
15062 g_return_if_fail (GTK_IS_WIDGET (widget));
15063 g_return_if_fail (margin <= G_MAXINT16);
15064
15065 if (widget->priv->margin.top == margin)
15066 return;
15067
15068 widget->priv->margin.top = margin;
15069 gtk_widget_queue_resize (widget);
15070 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_MARGIN_TOP]);
15071 }
15072
15073 /**
15074 * gtk_widget_get_margin_bottom:
15075 * @widget: a #GtkWidget
15076 *
15077 * Gets the value of the #GtkWidget:margin-bottom property.
15078 *
15079 * Returns: The bottom margin of @widget
15080 *
15081 * Since: 3.0
15082 */
15083 gint
gtk_widget_get_margin_bottom(GtkWidget * widget)15084 gtk_widget_get_margin_bottom (GtkWidget *widget)
15085 {
15086 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
15087
15088 return widget->priv->margin.bottom;
15089 }
15090
15091 /**
15092 * gtk_widget_set_margin_bottom:
15093 * @widget: a #GtkWidget
15094 * @margin: the bottom margin
15095 *
15096 * Sets the bottom margin of @widget.
15097 * See the #GtkWidget:margin-bottom property.
15098 *
15099 * Since: 3.0
15100 */
15101 void
gtk_widget_set_margin_bottom(GtkWidget * widget,gint margin)15102 gtk_widget_set_margin_bottom (GtkWidget *widget,
15103 gint margin)
15104 {
15105 g_return_if_fail (GTK_IS_WIDGET (widget));
15106 g_return_if_fail (margin <= G_MAXINT16);
15107
15108 if (widget->priv->margin.bottom == margin)
15109 return;
15110
15111 widget->priv->margin.bottom = margin;
15112 gtk_widget_queue_resize (widget);
15113 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_MARGIN_BOTTOM]);
15114 }
15115
15116 /**
15117 * gtk_widget_get_clipboard:
15118 * @widget: a #GtkWidget
15119 * @selection: a #GdkAtom which identifies the clipboard
15120 * to use. %GDK_SELECTION_CLIPBOARD gives the
15121 * default clipboard. Another common value
15122 * is %GDK_SELECTION_PRIMARY, which gives
15123 * the primary X selection.
15124 *
15125 * Returns the clipboard object for the given selection to
15126 * be used with @widget. @widget must have a #GdkDisplay
15127 * associated with it, so must be attached to a toplevel
15128 * window.
15129 *
15130 * Returns: (transfer none): the appropriate clipboard object. If no
15131 * clipboard already exists, a new one will
15132 * be created. Once a clipboard object has
15133 * been created, it is persistent for all time.
15134 *
15135 * Since: 2.2
15136 **/
15137 GtkClipboard *
gtk_widget_get_clipboard(GtkWidget * widget,GdkAtom selection)15138 gtk_widget_get_clipboard (GtkWidget *widget, GdkAtom selection)
15139 {
15140 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
15141 g_return_val_if_fail (gtk_widget_has_screen (widget), NULL);
15142
15143 return gtk_clipboard_get_for_display (gtk_widget_get_display (widget),
15144 selection);
15145 }
15146
15147 /**
15148 * gtk_widget_list_mnemonic_labels:
15149 * @widget: a #GtkWidget
15150 *
15151 * Returns a newly allocated list of the widgets, normally labels, for
15152 * which this widget is the target of a mnemonic (see for example,
15153 * gtk_label_set_mnemonic_widget()).
15154
15155 * The widgets in the list are not individually referenced. If you
15156 * want to iterate through the list and perform actions involving
15157 * callbacks that might destroy the widgets, you
15158 * must call `g_list_foreach (result,
15159 * (GFunc)g_object_ref, NULL)` first, and then unref all the
15160 * widgets afterwards.
15161
15162 * Returns: (element-type GtkWidget) (transfer container): the list of
15163 * mnemonic labels; free this list
15164 * with g_list_free() when you are done with it.
15165 *
15166 * Since: 2.4
15167 **/
15168 GList *
gtk_widget_list_mnemonic_labels(GtkWidget * widget)15169 gtk_widget_list_mnemonic_labels (GtkWidget *widget)
15170 {
15171 GList *list = NULL;
15172 GSList *l;
15173
15174 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
15175
15176 for (l = g_object_get_qdata (G_OBJECT (widget), quark_mnemonic_labels); l; l = l->next)
15177 list = g_list_prepend (list, l->data);
15178
15179 return list;
15180 }
15181
15182 /**
15183 * gtk_widget_add_mnemonic_label:
15184 * @widget: a #GtkWidget
15185 * @label: a #GtkWidget that acts as a mnemonic label for @widget
15186 *
15187 * Adds a widget to the list of mnemonic labels for
15188 * this widget. (See gtk_widget_list_mnemonic_labels()). Note the
15189 * list of mnemonic labels for the widget is cleared when the
15190 * widget is destroyed, so the caller must make sure to update
15191 * its internal state at this point as well, by using a connection
15192 * to the #GtkWidget::destroy signal or a weak notifier.
15193 *
15194 * Since: 2.4
15195 **/
15196 void
gtk_widget_add_mnemonic_label(GtkWidget * widget,GtkWidget * label)15197 gtk_widget_add_mnemonic_label (GtkWidget *widget,
15198 GtkWidget *label)
15199 {
15200 GSList *old_list, *new_list;
15201
15202 g_return_if_fail (GTK_IS_WIDGET (widget));
15203 g_return_if_fail (GTK_IS_WIDGET (label));
15204
15205 old_list = g_object_steal_qdata (G_OBJECT (widget), quark_mnemonic_labels);
15206 new_list = g_slist_prepend (old_list, label);
15207
15208 g_object_set_qdata_full (G_OBJECT (widget), quark_mnemonic_labels,
15209 new_list, (GDestroyNotify) g_slist_free);
15210 }
15211
15212 /**
15213 * gtk_widget_remove_mnemonic_label:
15214 * @widget: a #GtkWidget
15215 * @label: a #GtkWidget that was previously set as a mnemonic label for
15216 * @widget with gtk_widget_add_mnemonic_label().
15217 *
15218 * Removes a widget from the list of mnemonic labels for
15219 * this widget. (See gtk_widget_list_mnemonic_labels()). The widget
15220 * must have previously been added to the list with
15221 * gtk_widget_add_mnemonic_label().
15222 *
15223 * Since: 2.4
15224 **/
15225 void
gtk_widget_remove_mnemonic_label(GtkWidget * widget,GtkWidget * label)15226 gtk_widget_remove_mnemonic_label (GtkWidget *widget,
15227 GtkWidget *label)
15228 {
15229 GSList *old_list, *new_list;
15230
15231 g_return_if_fail (GTK_IS_WIDGET (widget));
15232 g_return_if_fail (GTK_IS_WIDGET (label));
15233
15234 old_list = g_object_steal_qdata (G_OBJECT (widget), quark_mnemonic_labels);
15235 new_list = g_slist_remove (old_list, label);
15236
15237 if (new_list)
15238 g_object_set_qdata_full (G_OBJECT (widget), quark_mnemonic_labels,
15239 new_list, (GDestroyNotify) g_slist_free);
15240 }
15241
15242 /**
15243 * gtk_widget_get_no_show_all:
15244 * @widget: a #GtkWidget
15245 *
15246 * Returns the current value of the #GtkWidget:no-show-all property,
15247 * which determines whether calls to gtk_widget_show_all()
15248 * will affect this widget.
15249 *
15250 * Returns: the current value of the “no-show-all” property.
15251 *
15252 * Since: 2.4
15253 **/
15254 gboolean
gtk_widget_get_no_show_all(GtkWidget * widget)15255 gtk_widget_get_no_show_all (GtkWidget *widget)
15256 {
15257 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
15258
15259 return widget->priv->no_show_all;
15260 }
15261
15262 /**
15263 * gtk_widget_set_no_show_all:
15264 * @widget: a #GtkWidget
15265 * @no_show_all: the new value for the “no-show-all” property
15266 *
15267 * Sets the #GtkWidget:no-show-all property, which determines whether
15268 * calls to gtk_widget_show_all() will affect this widget.
15269 *
15270 * This is mostly for use in constructing widget hierarchies with externally
15271 * controlled visibility, see #GtkUIManager.
15272 *
15273 * Since: 2.4
15274 **/
15275 void
gtk_widget_set_no_show_all(GtkWidget * widget,gboolean no_show_all)15276 gtk_widget_set_no_show_all (GtkWidget *widget,
15277 gboolean no_show_all)
15278 {
15279 g_return_if_fail (GTK_IS_WIDGET (widget));
15280
15281 no_show_all = (no_show_all != FALSE);
15282
15283 if (widget->priv->no_show_all != no_show_all)
15284 {
15285 widget->priv->no_show_all = no_show_all;
15286
15287 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_NO_SHOW_ALL]);
15288 }
15289 }
15290
15291
15292 static void
gtk_widget_real_set_has_tooltip(GtkWidget * widget,gboolean has_tooltip,gboolean force)15293 gtk_widget_real_set_has_tooltip (GtkWidget *widget,
15294 gboolean has_tooltip,
15295 gboolean force)
15296 {
15297 GtkWidgetPrivate *priv = widget->priv;
15298
15299 if (priv->has_tooltip != has_tooltip || force)
15300 {
15301 priv->has_tooltip = has_tooltip;
15302
15303 if (priv->has_tooltip)
15304 {
15305 if (_gtk_widget_get_realized (widget) && !_gtk_widget_get_has_window (widget))
15306 gdk_window_set_events (priv->window,
15307 gdk_window_get_events (priv->window) |
15308 GDK_LEAVE_NOTIFY_MASK |
15309 GDK_POINTER_MOTION_MASK);
15310
15311 if (_gtk_widget_get_has_window (widget))
15312 gtk_widget_add_events (widget,
15313 GDK_LEAVE_NOTIFY_MASK |
15314 GDK_POINTER_MOTION_MASK);
15315 }
15316
15317 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_TOOLTIP]);
15318 }
15319 }
15320
15321 /**
15322 * gtk_widget_set_tooltip_window:
15323 * @widget: a #GtkWidget
15324 * @custom_window: (allow-none): a #GtkWindow, or %NULL
15325 *
15326 * Replaces the default window used for displaying
15327 * tooltips with @custom_window. GTK+ will take care of showing and
15328 * hiding @custom_window at the right moment, to behave likewise as
15329 * the default tooltip window. If @custom_window is %NULL, the default
15330 * tooltip window will be used.
15331 *
15332 * Since: 2.12
15333 */
15334 void
gtk_widget_set_tooltip_window(GtkWidget * widget,GtkWindow * custom_window)15335 gtk_widget_set_tooltip_window (GtkWidget *widget,
15336 GtkWindow *custom_window)
15337 {
15338 gboolean has_tooltip;
15339 gchar *tooltip_markup;
15340
15341 g_return_if_fail (GTK_IS_WIDGET (widget));
15342 g_return_if_fail (custom_window == NULL || GTK_IS_WINDOW (custom_window));
15343
15344 tooltip_markup = g_object_get_qdata (G_OBJECT (widget), quark_tooltip_markup);
15345
15346 if (custom_window)
15347 g_object_ref (custom_window);
15348
15349 g_object_set_qdata_full (G_OBJECT (widget), quark_tooltip_window,
15350 custom_window, g_object_unref);
15351
15352 has_tooltip = (custom_window != NULL || tooltip_markup != NULL);
15353 gtk_widget_real_set_has_tooltip (widget, has_tooltip, FALSE);
15354
15355 if (has_tooltip && _gtk_widget_get_visible (widget))
15356 gtk_widget_queue_tooltip_query (widget);
15357 }
15358
15359 /**
15360 * gtk_widget_get_tooltip_window:
15361 * @widget: a #GtkWidget
15362 *
15363 * Returns the #GtkWindow of the current tooltip. This can be the
15364 * GtkWindow created by default, or the custom tooltip window set
15365 * using gtk_widget_set_tooltip_window().
15366 *
15367 * Returns: (transfer none): The #GtkWindow of the current tooltip.
15368 *
15369 * Since: 2.12
15370 */
15371 GtkWindow *
gtk_widget_get_tooltip_window(GtkWidget * widget)15372 gtk_widget_get_tooltip_window (GtkWidget *widget)
15373 {
15374 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
15375
15376 return g_object_get_qdata (G_OBJECT (widget), quark_tooltip_window);
15377 }
15378
15379 /**
15380 * gtk_widget_trigger_tooltip_query:
15381 * @widget: a #GtkWidget
15382 *
15383 * Triggers a tooltip query on the display where the toplevel of @widget
15384 * is located. See gtk_tooltip_trigger_tooltip_query() for more
15385 * information.
15386 *
15387 * Since: 2.12
15388 */
15389 void
gtk_widget_trigger_tooltip_query(GtkWidget * widget)15390 gtk_widget_trigger_tooltip_query (GtkWidget *widget)
15391 {
15392 gtk_tooltip_trigger_tooltip_query (gtk_widget_get_display (widget));
15393 }
15394
15395 static guint tooltip_query_id;
15396 static GSList *tooltip_query_displays;
15397
15398 static gboolean
tooltip_query_idle(gpointer data)15399 tooltip_query_idle (gpointer data)
15400 {
15401 g_slist_foreach (tooltip_query_displays, (GFunc)gtk_tooltip_trigger_tooltip_query, NULL);
15402 g_slist_free_full (tooltip_query_displays, g_object_unref);
15403
15404 tooltip_query_displays = NULL;
15405 tooltip_query_id = 0;
15406
15407 return FALSE;
15408 }
15409
15410 static void
gtk_widget_queue_tooltip_query(GtkWidget * widget)15411 gtk_widget_queue_tooltip_query (GtkWidget *widget)
15412 {
15413 GdkDisplay *display;
15414
15415 display = gtk_widget_get_display (widget);
15416
15417 if (!g_slist_find (tooltip_query_displays, display))
15418 tooltip_query_displays = g_slist_prepend (tooltip_query_displays, g_object_ref (display));
15419
15420 if (tooltip_query_id == 0)
15421 {
15422 tooltip_query_id = gdk_threads_add_idle (tooltip_query_idle, NULL);
15423 g_source_set_name_by_id (tooltip_query_id, "[gtk+] tooltip_query_idle");
15424 }
15425 }
15426
15427 /**
15428 * gtk_widget_set_tooltip_text:
15429 * @widget: a #GtkWidget
15430 * @text: (allow-none): the contents of the tooltip for @widget
15431 *
15432 * Sets @text as the contents of the tooltip. This function will take
15433 * care of setting #GtkWidget:has-tooltip to %TRUE and of the default
15434 * handler for the #GtkWidget::query-tooltip signal.
15435 *
15436 * See also the #GtkWidget:tooltip-text property and gtk_tooltip_set_text().
15437 *
15438 * Since: 2.12
15439 */
15440 void
gtk_widget_set_tooltip_text(GtkWidget * widget,const gchar * text)15441 gtk_widget_set_tooltip_text (GtkWidget *widget,
15442 const gchar *text)
15443 {
15444 g_return_if_fail (GTK_IS_WIDGET (widget));
15445
15446 g_object_set (G_OBJECT (widget), "tooltip-text", text, NULL);
15447 }
15448
15449 /**
15450 * gtk_widget_get_tooltip_text:
15451 * @widget: a #GtkWidget
15452 *
15453 * Gets the contents of the tooltip for @widget.
15454 *
15455 * Returns: (nullable): the tooltip text, or %NULL. You should free the
15456 * returned string with g_free() when done.
15457 *
15458 * Since: 2.12
15459 */
15460 gchar *
gtk_widget_get_tooltip_text(GtkWidget * widget)15461 gtk_widget_get_tooltip_text (GtkWidget *widget)
15462 {
15463 gchar *text = NULL;
15464
15465 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
15466
15467 g_object_get (G_OBJECT (widget), "tooltip-text", &text, NULL);
15468
15469 return text;
15470 }
15471
15472 /**
15473 * gtk_widget_set_tooltip_markup:
15474 * @widget: a #GtkWidget
15475 * @markup: (allow-none): the contents of the tooltip for @widget, or %NULL
15476 *
15477 * Sets @markup as the contents of the tooltip, which is marked up with
15478 * the [Pango text markup language][PangoMarkupFormat].
15479 *
15480 * This function will take care of setting #GtkWidget:has-tooltip to %TRUE
15481 * and of the default handler for the #GtkWidget::query-tooltip signal.
15482 *
15483 * See also the #GtkWidget:tooltip-markup property and
15484 * gtk_tooltip_set_markup().
15485 *
15486 * Since: 2.12
15487 */
15488 void
gtk_widget_set_tooltip_markup(GtkWidget * widget,const gchar * markup)15489 gtk_widget_set_tooltip_markup (GtkWidget *widget,
15490 const gchar *markup)
15491 {
15492 g_return_if_fail (GTK_IS_WIDGET (widget));
15493
15494 g_object_set (G_OBJECT (widget), "tooltip-markup", markup, NULL);
15495 }
15496
15497 /**
15498 * gtk_widget_get_tooltip_markup:
15499 * @widget: a #GtkWidget
15500 *
15501 * Gets the contents of the tooltip for @widget.
15502 *
15503 * Returns: (nullable): the tooltip text, or %NULL. You should free the
15504 * returned string with g_free() when done.
15505 *
15506 * Since: 2.12
15507 */
15508 gchar *
gtk_widget_get_tooltip_markup(GtkWidget * widget)15509 gtk_widget_get_tooltip_markup (GtkWidget *widget)
15510 {
15511 gchar *text = NULL;
15512
15513 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
15514
15515 g_object_get (G_OBJECT (widget), "tooltip-markup", &text, NULL);
15516
15517 return text;
15518 }
15519
15520 /**
15521 * gtk_widget_set_has_tooltip:
15522 * @widget: a #GtkWidget
15523 * @has_tooltip: whether or not @widget has a tooltip.
15524 *
15525 * Sets the has-tooltip property on @widget to @has_tooltip. See
15526 * #GtkWidget:has-tooltip for more information.
15527 *
15528 * Since: 2.12
15529 */
15530 void
gtk_widget_set_has_tooltip(GtkWidget * widget,gboolean has_tooltip)15531 gtk_widget_set_has_tooltip (GtkWidget *widget,
15532 gboolean has_tooltip)
15533 {
15534 g_return_if_fail (GTK_IS_WIDGET (widget));
15535
15536 gtk_widget_real_set_has_tooltip (widget, has_tooltip, FALSE);
15537 }
15538
15539 /**
15540 * gtk_widget_get_has_tooltip:
15541 * @widget: a #GtkWidget
15542 *
15543 * Returns the current value of the has-tooltip property. See
15544 * #GtkWidget:has-tooltip for more information.
15545 *
15546 * Returns: current value of has-tooltip on @widget.
15547 *
15548 * Since: 2.12
15549 */
15550 gboolean
gtk_widget_get_has_tooltip(GtkWidget * widget)15551 gtk_widget_get_has_tooltip (GtkWidget *widget)
15552 {
15553 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
15554
15555 return widget->priv->has_tooltip;
15556 }
15557
15558 /**
15559 * gtk_widget_get_clip:
15560 * @widget: a #GtkWidget
15561 * @clip: (out): a pointer to a #GtkAllocation to copy to
15562 *
15563 * Retrieves the widget’s clip area.
15564 *
15565 * The clip area is the area in which all of @widget's drawing will
15566 * happen. Other toolkits call it the bounding box.
15567 *
15568 * Historically, in GTK+ the clip area has been equal to the allocation
15569 * retrieved via gtk_widget_get_allocation().
15570 *
15571 * Since: 3.14
15572 */
15573 void
gtk_widget_get_clip(GtkWidget * widget,GtkAllocation * clip)15574 gtk_widget_get_clip (GtkWidget *widget,
15575 GtkAllocation *clip)
15576 {
15577 GtkWidgetPrivate *priv;
15578
15579 g_return_if_fail (GTK_IS_WIDGET (widget));
15580 g_return_if_fail (clip != NULL);
15581
15582 priv = widget->priv;
15583
15584 *clip = priv->clip;
15585 }
15586
15587 /**
15588 * gtk_widget_set_clip:
15589 * @widget: a #GtkWidget
15590 * @clip: a pointer to a #GtkAllocation to copy from
15591 *
15592 * Sets the widget’s clip. This must not be used directly,
15593 * but from within a widget’s size_allocate method.
15594 * It must be called after gtk_widget_set_allocation() (or after chaining up
15595 * to the parent class), because that function resets the clip.
15596 *
15597 * The clip set should be the area that @widget draws on. If @widget is a
15598 * #GtkContainer, the area must contain all children's clips.
15599 *
15600 * If this function is not called by @widget during a ::size-allocate handler,
15601 * the clip will be set to @widget's allocation.
15602 *
15603 * Since: 3.14
15604 */
15605 void
gtk_widget_set_clip(GtkWidget * widget,const GtkAllocation * clip)15606 gtk_widget_set_clip (GtkWidget *widget,
15607 const GtkAllocation *clip)
15608 {
15609 GtkWidgetPrivate *priv;
15610
15611 g_return_if_fail (GTK_IS_WIDGET (widget));
15612 g_return_if_fail (_gtk_widget_get_visible (widget) || _gtk_widget_is_toplevel (widget));
15613 g_return_if_fail (clip != NULL);
15614
15615 priv = widget->priv;
15616
15617 #ifdef G_ENABLE_DEBUG
15618 if (GTK_DEBUG_CHECK (GEOMETRY))
15619 {
15620 gint depth;
15621 GtkWidget *parent;
15622 const gchar *name;
15623
15624 depth = 0;
15625 parent = widget;
15626 while (parent)
15627 {
15628 depth++;
15629 parent = _gtk_widget_get_parent (parent);
15630 }
15631
15632 name = g_type_name (G_OBJECT_TYPE (G_OBJECT (widget)));
15633 g_message ("gtk_widget_set_clip: %*s%s %d %d %d %d",
15634 2 * depth, " ", name,
15635 clip->x, clip->y,
15636 clip->width, clip->height);
15637 }
15638 #endif /* G_ENABLE_DEBUG */
15639
15640 priv->clip = *clip;
15641
15642 while (priv->parent &&
15643 _gtk_widget_get_window (widget) == _gtk_widget_get_window (priv->parent))
15644 {
15645 GtkWidgetPrivate *parent_priv = priv->parent->priv;
15646 GdkRectangle union_rect;
15647
15648 gdk_rectangle_union (&priv->clip,
15649 &parent_priv->clip,
15650 &union_rect);
15651
15652 if (gdk_rectangle_equal (&parent_priv->clip, &union_rect))
15653 break;
15654
15655 parent_priv->clip = union_rect;
15656 priv = parent_priv;
15657 }
15658 }
15659
15660 /*
15661 * _gtk_widget_set_simple_clip:
15662 * @widget: a #GtkWidget
15663 * @content_clip: (nullable): Clipping area of the contents
15664 * or %NULL, if the contents
15665 * do not extent the allocation.
15666 *
15667 * This is a convenience function for gtk_widget_set_clip(), if you
15668 * just want to set the clip for @widget based on its allocation,
15669 * CSS properties and - if the widget is a #GtkContainer - its
15670 * children. gtk_widget_set_allocation() must have been called
15671 * and all children must have been allocated with
15672 * gtk_widget_size_allocate() before calling this function.
15673 * It is therefore a good idea to call this function last in
15674 * your implementation of GtkWidget::size_allocate().
15675 *
15676 * If your widget overdraws its contents, you cannot use this
15677 * function and must call gtk_widget_set_clip() yourself.
15678 **/
15679 void
_gtk_widget_set_simple_clip(GtkWidget * widget,GtkAllocation * content_clip)15680 _gtk_widget_set_simple_clip (GtkWidget *widget,
15681 GtkAllocation *content_clip)
15682 {
15683 GtkStyleContext *context;
15684 GtkAllocation clip, allocation;
15685 GtkBorder extents;
15686
15687 context = _gtk_widget_get_style_context (widget);
15688
15689 _gtk_widget_get_allocation (widget, &allocation);
15690
15691 _gtk_css_shadows_value_get_extents (_gtk_style_context_peek_property (context,
15692 GTK_CSS_PROPERTY_BOX_SHADOW),
15693 &extents);
15694
15695 clip = allocation;
15696 clip.x -= extents.left;
15697 clip.y -= extents.top;
15698 clip.width += extents.left + extents.right;
15699 clip.height += extents.top + extents.bottom;
15700
15701 if (content_clip)
15702 gdk_rectangle_union (content_clip, &clip, &clip);
15703
15704 if (GTK_IS_CONTAINER (widget))
15705 {
15706 GdkRectangle children_clip;
15707
15708 gtk_container_get_children_clip (GTK_CONTAINER (widget), &children_clip);
15709
15710 if (_gtk_widget_get_has_window (widget))
15711 {
15712 children_clip.x += allocation.x;
15713 children_clip.y += allocation.y;
15714 }
15715
15716 gdk_rectangle_union (&children_clip, &clip, &clip);
15717 }
15718
15719 gtk_widget_set_clip (widget, &clip);
15720 }
15721
15722 /**
15723 * gtk_widget_get_allocated_size:
15724 * @widget: a #GtkWidget
15725 * @allocation: (out): a pointer to a #GtkAllocation to copy to
15726 * @baseline: (out) (allow-none): a pointer to an integer to copy to
15727 *
15728 * Retrieves the widget’s allocated size.
15729 *
15730 * This function returns the last values passed to
15731 * gtk_widget_size_allocate_with_baseline(). The value differs from
15732 * the size returned in gtk_widget_get_allocation() in that functions
15733 * like gtk_widget_set_halign() can adjust the allocation, but not
15734 * the value returned by this function.
15735 *
15736 * If a widget is not visible, its allocated size is 0.
15737 *
15738 * Since: 3.20
15739 */
15740 void
gtk_widget_get_allocated_size(GtkWidget * widget,GtkAllocation * allocation,int * baseline)15741 gtk_widget_get_allocated_size (GtkWidget *widget,
15742 GtkAllocation *allocation,
15743 int *baseline)
15744 {
15745 GtkWidgetPrivate *priv;
15746
15747 g_return_if_fail (GTK_IS_WIDGET (widget));
15748 g_return_if_fail (allocation != NULL);
15749
15750 priv = widget->priv;
15751
15752 *allocation = priv->allocated_size;
15753
15754 if (baseline)
15755 *baseline = priv->allocated_size_baseline;
15756 }
15757
15758 /**
15759 * gtk_widget_get_allocation:
15760 * @widget: a #GtkWidget
15761 * @allocation: (out): a pointer to a #GtkAllocation to copy to
15762 *
15763 * Retrieves the widget’s allocation.
15764 *
15765 * Note, when implementing a #GtkContainer: a widget’s allocation will
15766 * be its “adjusted” allocation, that is, the widget’s parent
15767 * container typically calls gtk_widget_size_allocate() with an
15768 * allocation, and that allocation is then adjusted (to handle margin
15769 * and alignment for example) before assignment to the widget.
15770 * gtk_widget_get_allocation() returns the adjusted allocation that
15771 * was actually assigned to the widget. The adjusted allocation is
15772 * guaranteed to be completely contained within the
15773 * gtk_widget_size_allocate() allocation, however. So a #GtkContainer
15774 * is guaranteed that its children stay inside the assigned bounds,
15775 * but not that they have exactly the bounds the container assigned.
15776 * There is no way to get the original allocation assigned by
15777 * gtk_widget_size_allocate(), since it isn’t stored; if a container
15778 * implementation needs that information it will have to track it itself.
15779 *
15780 * Since: 2.18
15781 */
15782 void
gtk_widget_get_allocation(GtkWidget * widget,GtkAllocation * allocation)15783 gtk_widget_get_allocation (GtkWidget *widget,
15784 GtkAllocation *allocation)
15785 {
15786 GtkWidgetPrivate *priv;
15787
15788 g_return_if_fail (GTK_IS_WIDGET (widget));
15789 g_return_if_fail (allocation != NULL);
15790
15791 priv = widget->priv;
15792
15793 *allocation = priv->allocation;
15794 }
15795
15796 /**
15797 * gtk_widget_set_allocation:
15798 * @widget: a #GtkWidget
15799 * @allocation: a pointer to a #GtkAllocation to copy from
15800 *
15801 * Sets the widget’s allocation. This should not be used
15802 * directly, but from within a widget’s size_allocate method.
15803 *
15804 * The allocation set should be the “adjusted” or actual
15805 * allocation. If you’re implementing a #GtkContainer, you want to use
15806 * gtk_widget_size_allocate() instead of gtk_widget_set_allocation().
15807 * The GtkWidgetClass::adjust_size_allocation virtual method adjusts the
15808 * allocation inside gtk_widget_size_allocate() to create an adjusted
15809 * allocation.
15810 *
15811 * Since: 2.18
15812 */
15813 void
gtk_widget_set_allocation(GtkWidget * widget,const GtkAllocation * allocation)15814 gtk_widget_set_allocation (GtkWidget *widget,
15815 const GtkAllocation *allocation)
15816 {
15817 GtkWidgetPrivate *priv;
15818
15819 g_return_if_fail (GTK_IS_WIDGET (widget));
15820 g_return_if_fail (_gtk_widget_get_visible (widget) || _gtk_widget_is_toplevel (widget));
15821 g_return_if_fail (allocation != NULL);
15822
15823 priv = widget->priv;
15824
15825 priv->allocation = *allocation;
15826 priv->clip = *allocation;
15827 }
15828
15829 /**
15830 * gtk_widget_get_allocated_width:
15831 * @widget: the widget to query
15832 *
15833 * Returns the width that has currently been allocated to @widget.
15834 * This function is intended to be used when implementing handlers
15835 * for the #GtkWidget::draw function.
15836 *
15837 * Returns: the width of the @widget
15838 **/
15839 int
gtk_widget_get_allocated_width(GtkWidget * widget)15840 gtk_widget_get_allocated_width (GtkWidget *widget)
15841 {
15842 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
15843
15844 return widget->priv->allocation.width;
15845 }
15846
15847 /**
15848 * gtk_widget_get_allocated_height:
15849 * @widget: the widget to query
15850 *
15851 * Returns the height that has currently been allocated to @widget.
15852 * This function is intended to be used when implementing handlers
15853 * for the #GtkWidget::draw function.
15854 *
15855 * Returns: the height of the @widget
15856 **/
15857 int
gtk_widget_get_allocated_height(GtkWidget * widget)15858 gtk_widget_get_allocated_height (GtkWidget *widget)
15859 {
15860 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
15861
15862 return widget->priv->allocation.height;
15863 }
15864
15865 /**
15866 * gtk_widget_get_allocated_baseline:
15867 * @widget: the widget to query
15868 *
15869 * Returns the baseline that has currently been allocated to @widget.
15870 * This function is intended to be used when implementing handlers
15871 * for the #GtkWidget::draw function, and when allocating child
15872 * widgets in #GtkWidget::size_allocate.
15873 *
15874 * Returns: the baseline of the @widget, or -1 if none
15875 *
15876 * Since: 3.10
15877 **/
15878 int
gtk_widget_get_allocated_baseline(GtkWidget * widget)15879 gtk_widget_get_allocated_baseline (GtkWidget *widget)
15880 {
15881 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
15882
15883 return widget->priv->allocated_baseline;
15884 }
15885
15886 /**
15887 * gtk_widget_get_requisition:
15888 * @widget: a #GtkWidget
15889 * @requisition: (out): a pointer to a #GtkRequisition to copy to
15890 *
15891 * Retrieves the widget’s requisition.
15892 *
15893 * This function should only be used by widget implementations in
15894 * order to figure whether the widget’s requisition has actually
15895 * changed after some internal state change (so that they can call
15896 * gtk_widget_queue_resize() instead of gtk_widget_queue_draw()).
15897 *
15898 * Normally, gtk_widget_size_request() should be used.
15899 *
15900 * Since: 2.20
15901 *
15902 * Deprecated: 3.0: The #GtkRequisition cache on the widget was
15903 * removed, If you need to cache sizes across requests and allocations,
15904 * add an explicit cache to the widget in question instead.
15905 */
15906 void
gtk_widget_get_requisition(GtkWidget * widget,GtkRequisition * requisition)15907 gtk_widget_get_requisition (GtkWidget *widget,
15908 GtkRequisition *requisition)
15909 {
15910 g_return_if_fail (GTK_IS_WIDGET (widget));
15911 g_return_if_fail (requisition != NULL);
15912
15913 gtk_widget_get_preferred_size (widget, requisition, NULL);
15914 }
15915
15916 /**
15917 * gtk_widget_set_window:
15918 * @widget: a #GtkWidget
15919 * @window: (transfer full): a #GdkWindow
15920 *
15921 * Sets a widget’s window. This function should only be used in a
15922 * widget’s #GtkWidget::realize implementation. The %window passed is
15923 * usually either new window created with gdk_window_new(), or the
15924 * window of its parent widget as returned by
15925 * gtk_widget_get_parent_window().
15926 *
15927 * Widgets must indicate whether they will create their own #GdkWindow
15928 * by calling gtk_widget_set_has_window(). This is usually done in the
15929 * widget’s init() function.
15930 *
15931 * Note that this function does not add any reference to @window.
15932 *
15933 * Since: 2.18
15934 */
15935 void
gtk_widget_set_window(GtkWidget * widget,GdkWindow * window)15936 gtk_widget_set_window (GtkWidget *widget,
15937 GdkWindow *window)
15938 {
15939 GtkWidgetPrivate *priv;
15940
15941 g_return_if_fail (GTK_IS_WIDGET (widget));
15942 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
15943
15944 priv = widget->priv;
15945
15946 if (priv->window != window)
15947 {
15948 priv->window = window;
15949
15950 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_WINDOW]);
15951 }
15952 }
15953
15954 /**
15955 * gtk_widget_register_window:
15956 * @widget: a #GtkWidget
15957 * @window: a #GdkWindow
15958 *
15959 * Registers a #GdkWindow with the widget and sets it up so that
15960 * the widget receives events for it. Call gtk_widget_unregister_window()
15961 * when destroying the window.
15962 *
15963 * Before 3.8 you needed to call gdk_window_set_user_data() directly to set
15964 * this up. This is now deprecated and you should use gtk_widget_register_window()
15965 * instead. Old code will keep working as is, although some new features like
15966 * transparency might not work perfectly.
15967 *
15968 * Since: 3.8
15969 */
15970 void
gtk_widget_register_window(GtkWidget * widget,GdkWindow * window)15971 gtk_widget_register_window (GtkWidget *widget,
15972 GdkWindow *window)
15973 {
15974 GtkWidgetPrivate *priv;
15975 gpointer user_data;
15976
15977 g_return_if_fail (GTK_IS_WIDGET (widget));
15978 g_return_if_fail (GDK_IS_WINDOW (window));
15979
15980 gdk_window_get_user_data (window, &user_data);
15981 g_assert (user_data == NULL);
15982
15983 priv = widget->priv;
15984
15985 gdk_window_set_user_data (window, widget);
15986 priv->registered_windows = g_list_prepend (priv->registered_windows, window);
15987 }
15988
15989 /**
15990 * gtk_widget_unregister_window:
15991 * @widget: a #GtkWidget
15992 * @window: a #GdkWindow
15993 *
15994 * Unregisters a #GdkWindow from the widget that was previously set up with
15995 * gtk_widget_register_window(). You need to call this when the window is
15996 * no longer used by the widget, such as when you destroy it.
15997 *
15998 * Since: 3.8
15999 */
16000 void
gtk_widget_unregister_window(GtkWidget * widget,GdkWindow * window)16001 gtk_widget_unregister_window (GtkWidget *widget,
16002 GdkWindow *window)
16003 {
16004 GtkWidgetPrivate *priv;
16005 gpointer user_data;
16006
16007 g_return_if_fail (GTK_IS_WIDGET (widget));
16008 g_return_if_fail (GDK_IS_WINDOW (window));
16009
16010 priv = widget->priv;
16011
16012 gdk_window_get_user_data (window, &user_data);
16013 g_assert (user_data == widget);
16014 gdk_window_set_user_data (window, NULL);
16015 priv->registered_windows = g_list_remove (priv->registered_windows, window);
16016 }
16017
16018 /**
16019 * gtk_widget_get_window:
16020 * @widget: a #GtkWidget
16021 *
16022 * Returns the widget’s window if it is realized, %NULL otherwise
16023 *
16024 * Returns: (transfer none) (nullable): @widget’s window.
16025 *
16026 * Since: 2.14
16027 */
16028 GdkWindow*
gtk_widget_get_window(GtkWidget * widget)16029 gtk_widget_get_window (GtkWidget *widget)
16030 {
16031 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
16032
16033 return widget->priv->window;
16034 }
16035
16036 /**
16037 * gtk_widget_get_support_multidevice:
16038 * @widget: a #GtkWidget
16039 *
16040 * Returns %TRUE if @widget is multiple pointer aware. See
16041 * gtk_widget_set_support_multidevice() for more information.
16042 *
16043 * Returns: %TRUE if @widget is multidevice aware.
16044 **/
16045 gboolean
gtk_widget_get_support_multidevice(GtkWidget * widget)16046 gtk_widget_get_support_multidevice (GtkWidget *widget)
16047 {
16048 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
16049
16050 return widget->priv->multidevice;
16051 }
16052
16053 /**
16054 * gtk_widget_set_support_multidevice:
16055 * @widget: a #GtkWidget
16056 * @support_multidevice: %TRUE to support input from multiple devices.
16057 *
16058 * Enables or disables multiple pointer awareness. If this setting is %TRUE,
16059 * @widget will start receiving multiple, per device enter/leave events. Note
16060 * that if custom #GdkWindows are created in #GtkWidget::realize,
16061 * gdk_window_set_support_multidevice() will have to be called manually on them.
16062 *
16063 * Since: 3.0
16064 **/
16065 void
gtk_widget_set_support_multidevice(GtkWidget * widget,gboolean support_multidevice)16066 gtk_widget_set_support_multidevice (GtkWidget *widget,
16067 gboolean support_multidevice)
16068 {
16069 GtkWidgetPrivate *priv;
16070
16071 g_return_if_fail (GTK_IS_WIDGET (widget));
16072
16073 priv = widget->priv;
16074 priv->multidevice = (support_multidevice == TRUE);
16075
16076 if (_gtk_widget_get_realized (widget))
16077 gdk_window_set_support_multidevice (priv->window, support_multidevice);
16078 }
16079
16080 /* There are multiple alpha related sources. First of all the user can specify alpha
16081 * in gtk_widget_set_opacity, secondly we can get it from the CSS opacity. These two
16082 * are multiplied together to form the total alpha. Secondly, the user can specify
16083 * an opacity group for a widget, which means we must essentially handle it as having alpha.
16084 */
16085
16086 static void
gtk_widget_update_alpha(GtkWidget * widget)16087 gtk_widget_update_alpha (GtkWidget *widget)
16088 {
16089 GtkWidgetPrivate *priv;
16090 GtkStyleContext *context;
16091 gdouble opacity;
16092 guint8 alpha;
16093
16094 priv = widget->priv;
16095
16096 context = _gtk_widget_get_style_context (widget);
16097 opacity =
16098 _gtk_css_number_value_get (_gtk_style_context_peek_property (context,
16099 GTK_CSS_PROPERTY_OPACITY),
16100 100);
16101 opacity = CLAMP (opacity, 0.0, 1.0);
16102 alpha = round (priv->user_alpha * opacity);
16103
16104 if (alpha == priv->alpha)
16105 return;
16106
16107 priv->alpha = alpha;
16108
16109 if (_gtk_widget_get_realized (widget))
16110 {
16111 if (_gtk_widget_is_toplevel (widget) &&
16112 gtk_widget_get_visual (widget) != gdk_screen_get_rgba_visual (gtk_widget_get_screen (widget)))
16113 gdk_window_set_opacity (priv->window, priv->alpha / 255.0);
16114
16115 gtk_widget_queue_draw (widget);
16116 }
16117 }
16118
16119 /**
16120 * gtk_widget_set_opacity:
16121 * @widget: a #GtkWidget
16122 * @opacity: desired opacity, between 0 and 1
16123 *
16124 * Request the @widget to be rendered partially transparent,
16125 * with opacity 0 being fully transparent and 1 fully opaque. (Opacity values
16126 * are clamped to the [0,1] range.).
16127 * This works on both toplevel widget, and child widgets, although there
16128 * are some limitations:
16129 *
16130 * For toplevel widgets this depends on the capabilities of the windowing
16131 * system. On X11 this has any effect only on X screens with a compositing manager
16132 * running. See gtk_widget_is_composited(). On Windows it should work
16133 * always, although setting a window’s opacity after the window has been
16134 * shown causes it to flicker once on Windows.
16135 *
16136 * For child widgets it doesn’t work if any affected widget has a native window, or
16137 * disables double buffering.
16138 *
16139 * Since: 3.8
16140 **/
16141 void
gtk_widget_set_opacity(GtkWidget * widget,gdouble opacity)16142 gtk_widget_set_opacity (GtkWidget *widget,
16143 gdouble opacity)
16144 {
16145 GtkWidgetPrivate *priv;
16146 guint8 alpha;
16147
16148 g_return_if_fail (GTK_IS_WIDGET (widget));
16149
16150 priv = widget->priv;
16151
16152 opacity = CLAMP (opacity, 0.0, 1.0);
16153
16154 alpha = round (opacity * 255);
16155
16156 if (alpha == priv->user_alpha)
16157 return;
16158
16159 priv->user_alpha = alpha;
16160
16161 gtk_widget_update_alpha (widget);
16162
16163 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_OPACITY]);
16164 }
16165
16166 /**
16167 * gtk_widget_get_opacity:
16168 * @widget: a #GtkWidget
16169 *
16170 * Fetches the requested opacity for this widget.
16171 * See gtk_widget_set_opacity().
16172 *
16173 * Returns: the requested opacity for this widget.
16174 *
16175 * Since: 3.8
16176 **/
16177 gdouble
gtk_widget_get_opacity(GtkWidget * widget)16178 gtk_widget_get_opacity (GtkWidget *widget)
16179 {
16180 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0.0);
16181
16182 return widget->priv->user_alpha / 255.0;
16183 }
16184
16185 static void
_gtk_widget_set_has_focus(GtkWidget * widget,gboolean has_focus)16186 _gtk_widget_set_has_focus (GtkWidget *widget,
16187 gboolean has_focus)
16188 {
16189 widget->priv->has_focus = has_focus;
16190
16191 if (has_focus)
16192 gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_FOCUSED, FALSE);
16193 else
16194 gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_FOCUSED);
16195 }
16196
16197 /**
16198 * gtk_widget_send_focus_change:
16199 * @widget: a #GtkWidget
16200 * @event: a #GdkEvent of type GDK_FOCUS_CHANGE
16201 *
16202 * Sends the focus change @event to @widget
16203 *
16204 * This function is not meant to be used by applications. The only time it
16205 * should be used is when it is necessary for a #GtkWidget to assign focus
16206 * to a widget that is semantically owned by the first widget even though
16207 * it’s not a direct child - for instance, a search entry in a floating
16208 * window similar to the quick search in #GtkTreeView.
16209 *
16210 * An example of its usage is:
16211 *
16212 * |[<!-- language="C" -->
16213 * GdkEvent *fevent = gdk_event_new (GDK_FOCUS_CHANGE);
16214 *
16215 * fevent->focus_change.type = GDK_FOCUS_CHANGE;
16216 * fevent->focus_change.in = TRUE;
16217 * fevent->focus_change.window = _gtk_widget_get_window (widget);
16218 * if (fevent->focus_change.window != NULL)
16219 * g_object_ref (fevent->focus_change.window);
16220 *
16221 * gtk_widget_send_focus_change (widget, fevent);
16222 *
16223 * gdk_event_free (event);
16224 * ]|
16225 *
16226 * Returns: the return value from the event signal emission: %TRUE
16227 * if the event was handled, and %FALSE otherwise
16228 *
16229 * Since: 2.20
16230 */
16231 gboolean
gtk_widget_send_focus_change(GtkWidget * widget,GdkEvent * event)16232 gtk_widget_send_focus_change (GtkWidget *widget,
16233 GdkEvent *event)
16234 {
16235 gboolean res;
16236
16237 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
16238 g_return_val_if_fail (event != NULL && event->type == GDK_FOCUS_CHANGE, FALSE);
16239
16240 g_object_ref (widget);
16241
16242 _gtk_widget_set_has_focus (widget, event->focus_change.in);
16243
16244 res = gtk_widget_event (widget, event);
16245
16246 g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HAS_FOCUS]);
16247
16248 g_object_unref (widget);
16249
16250 return res;
16251 }
16252
16253 /**
16254 * gtk_widget_in_destruction:
16255 * @widget: a #GtkWidget
16256 *
16257 * Returns whether the widget is currently being destroyed.
16258 * This information can sometimes be used to avoid doing
16259 * unnecessary work.
16260 *
16261 * Returns: %TRUE if @widget is being destroyed
16262 */
16263 gboolean
gtk_widget_in_destruction(GtkWidget * widget)16264 gtk_widget_in_destruction (GtkWidget *widget)
16265 {
16266 return widget->priv->in_destruction;
16267 }
16268
16269 gboolean
_gtk_widget_get_in_reparent(GtkWidget * widget)16270 _gtk_widget_get_in_reparent (GtkWidget *widget)
16271 {
16272 return widget->priv->in_reparent;
16273 }
16274
16275 void
_gtk_widget_set_in_reparent(GtkWidget * widget,gboolean in_reparent)16276 _gtk_widget_set_in_reparent (GtkWidget *widget,
16277 gboolean in_reparent)
16278 {
16279 widget->priv->in_reparent = in_reparent;
16280 }
16281
16282 gboolean
_gtk_widget_get_anchored(GtkWidget * widget)16283 _gtk_widget_get_anchored (GtkWidget *widget)
16284 {
16285 return widget->priv->anchored;
16286 }
16287
16288 void
_gtk_widget_set_anchored(GtkWidget * widget,gboolean anchored)16289 _gtk_widget_set_anchored (GtkWidget *widget,
16290 gboolean anchored)
16291 {
16292 widget->priv->anchored = anchored;
16293 }
16294
16295 gboolean
_gtk_widget_get_shadowed(GtkWidget * widget)16296 _gtk_widget_get_shadowed (GtkWidget *widget)
16297 {
16298 return widget->priv->shadowed;
16299 }
16300
16301 void
_gtk_widget_set_shadowed(GtkWidget * widget,gboolean shadowed)16302 _gtk_widget_set_shadowed (GtkWidget *widget,
16303 gboolean shadowed)
16304 {
16305 widget->priv->shadowed = shadowed;
16306 }
16307
16308 gboolean
_gtk_widget_get_alloc_needed(GtkWidget * widget)16309 _gtk_widget_get_alloc_needed (GtkWidget *widget)
16310 {
16311 return widget->priv->alloc_needed;
16312 }
16313
16314 static void
gtk_widget_set_alloc_needed(GtkWidget * widget)16315 gtk_widget_set_alloc_needed (GtkWidget *widget)
16316 {
16317 GtkWidgetPrivate *priv = widget->priv;
16318
16319 priv->alloc_needed = TRUE;
16320
16321 do
16322 {
16323 if (priv->alloc_needed_on_child)
16324 break;
16325
16326 priv->alloc_needed_on_child = TRUE;
16327
16328 if (!priv->visible)
16329 break;
16330
16331 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
16332 if (GTK_IS_RESIZE_CONTAINER (widget))
16333 {
16334 gtk_container_queue_resize_handler (GTK_CONTAINER (widget));
16335 break;
16336 }
16337 G_GNUC_END_IGNORE_DEPRECATIONS;
16338
16339 widget = priv->parent;
16340 if (widget == NULL)
16341 break;
16342
16343 priv = widget->priv;
16344 }
16345 while (TRUE);
16346 }
16347
16348 gboolean
gtk_widget_needs_allocate(GtkWidget * widget)16349 gtk_widget_needs_allocate (GtkWidget *widget)
16350 {
16351 GtkWidgetPrivate *priv = widget->priv;
16352
16353 if (!priv->visible || !priv->child_visible)
16354 return FALSE;
16355
16356 if (priv->resize_needed || priv->alloc_needed || priv->alloc_needed_on_child)
16357 return TRUE;
16358
16359 return FALSE;
16360 }
16361
16362 void
gtk_widget_ensure_allocate(GtkWidget * widget)16363 gtk_widget_ensure_allocate (GtkWidget *widget)
16364 {
16365 GtkWidgetPrivate *priv = widget->priv;
16366
16367 if (!gtk_widget_needs_allocate (widget))
16368 return;
16369
16370 gtk_widget_ensure_resize (widget);
16371
16372 /* This code assumes that we only reach here if the previous
16373 * allocation is still valid (ie no resize was queued).
16374 * If that wasn't true, the parent would have taken care of
16375 * things.
16376 */
16377 if (priv->alloc_needed)
16378 {
16379 GtkAllocation allocation;
16380 int baseline;
16381
16382 gtk_widget_get_allocated_size (widget, &allocation, &baseline);
16383 gtk_widget_size_allocate_with_baseline (widget, &allocation, baseline);
16384 }
16385 else if (priv->alloc_needed_on_child)
16386 {
16387 priv->alloc_needed_on_child = FALSE;
16388
16389 if (GTK_IS_CONTAINER (widget))
16390 gtk_container_forall (GTK_CONTAINER (widget),
16391 (GtkCallback) gtk_widget_ensure_allocate,
16392 NULL);
16393 }
16394 }
16395
16396 void
gtk_widget_queue_resize_on_widget(GtkWidget * widget)16397 gtk_widget_queue_resize_on_widget (GtkWidget *widget)
16398 {
16399 GtkWidgetPrivate *priv = widget->priv;
16400
16401 priv->resize_needed = TRUE;
16402 gtk_widget_set_alloc_needed (widget);
16403 }
16404
16405 void
gtk_widget_ensure_resize(GtkWidget * widget)16406 gtk_widget_ensure_resize (GtkWidget *widget)
16407 {
16408 GtkWidgetPrivate *priv = widget->priv;
16409
16410 if (!priv->resize_needed)
16411 return;
16412
16413 priv->resize_needed = FALSE;
16414 _gtk_size_request_cache_clear (&priv->requests);
16415 }
16416
16417 void
_gtk_widget_add_sizegroup(GtkWidget * widget,gpointer group)16418 _gtk_widget_add_sizegroup (GtkWidget *widget,
16419 gpointer group)
16420 {
16421 GSList *groups;
16422
16423 groups = g_object_get_qdata (G_OBJECT (widget), quark_size_groups);
16424 groups = g_slist_prepend (groups, group);
16425 g_object_set_qdata (G_OBJECT (widget), quark_size_groups, groups);
16426
16427 widget->priv->have_size_groups = TRUE;
16428 }
16429
16430 void
_gtk_widget_remove_sizegroup(GtkWidget * widget,gpointer group)16431 _gtk_widget_remove_sizegroup (GtkWidget *widget,
16432 gpointer group)
16433 {
16434 GSList *groups;
16435
16436 groups = g_object_get_qdata (G_OBJECT (widget), quark_size_groups);
16437 groups = g_slist_remove (groups, group);
16438 g_object_set_qdata (G_OBJECT (widget), quark_size_groups, groups);
16439
16440 widget->priv->have_size_groups = groups != NULL;
16441 }
16442
16443 GSList *
_gtk_widget_get_sizegroups(GtkWidget * widget)16444 _gtk_widget_get_sizegroups (GtkWidget *widget)
16445 {
16446 if (widget->priv->have_size_groups)
16447 return g_object_get_qdata (G_OBJECT (widget), quark_size_groups);
16448
16449 return NULL;
16450 }
16451
16452 void
_gtk_widget_add_attached_window(GtkWidget * widget,GtkWindow * window)16453 _gtk_widget_add_attached_window (GtkWidget *widget,
16454 GtkWindow *window)
16455 {
16456 widget->priv->attached_windows = g_list_prepend (widget->priv->attached_windows, window);
16457 }
16458
16459 void
_gtk_widget_remove_attached_window(GtkWidget * widget,GtkWindow * window)16460 _gtk_widget_remove_attached_window (GtkWidget *widget,
16461 GtkWindow *window)
16462 {
16463 widget->priv->attached_windows = g_list_remove (widget->priv->attached_windows, window);
16464 }
16465
16466 /**
16467 * gtk_widget_path_append_for_widget:
16468 * @path: a widget path
16469 * @widget: the widget to append to the widget path
16470 *
16471 * Appends the data from @widget to the widget hierarchy represented
16472 * by @path. This function is a shortcut for adding information from
16473 * @widget to the given @path. This includes setting the name or
16474 * adding the style classes from @widget.
16475 *
16476 * Returns: the position where the data was inserted
16477 *
16478 * Since: 3.2
16479 */
16480 gint
gtk_widget_path_append_for_widget(GtkWidgetPath * path,GtkWidget * widget)16481 gtk_widget_path_append_for_widget (GtkWidgetPath *path,
16482 GtkWidget *widget)
16483 {
16484 const GQuark *classes;
16485 guint n_classes, i;
16486 gint pos;
16487
16488 g_return_val_if_fail (path != NULL, 0);
16489 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
16490
16491 pos = gtk_widget_path_append_type (path, gtk_css_node_get_widget_type (widget->priv->cssnode));
16492 gtk_widget_path_iter_set_object_name (path, pos, gtk_css_node_get_name (widget->priv->cssnode));
16493
16494 if (widget->priv->name)
16495 gtk_widget_path_iter_set_name (path, pos, widget->priv->name);
16496
16497 gtk_widget_path_iter_set_state (path, pos, widget->priv->state_flags);
16498
16499 classes = gtk_css_node_list_classes (widget->priv->cssnode, &n_classes);
16500
16501 for (i = n_classes; i-- > 0;)
16502 gtk_widget_path_iter_add_qclass (path, pos, classes[i]);
16503
16504 return pos;
16505 }
16506
16507 GtkWidgetPath *
_gtk_widget_create_path(GtkWidget * widget)16508 _gtk_widget_create_path (GtkWidget *widget)
16509 {
16510 GtkWidget *parent;
16511
16512 parent = widget->priv->parent;
16513
16514 if (parent)
16515 return gtk_container_get_path_for_child (GTK_CONTAINER (parent), widget);
16516 else
16517 {
16518 /* Widget is either toplevel or unparented, treat both
16519 * as toplevels style wise, since there are situations
16520 * where style properties might be retrieved on that
16521 * situation.
16522 */
16523 GtkWidget *attach_widget = NULL;
16524 GtkWidgetPath *result;
16525
16526 if (GTK_IS_WINDOW (widget))
16527 attach_widget = gtk_window_get_attached_to (GTK_WINDOW (widget));
16528
16529 if (attach_widget != NULL)
16530 result = gtk_widget_path_copy (gtk_widget_get_path (attach_widget));
16531 else
16532 result = gtk_widget_path_new ();
16533
16534 gtk_widget_path_append_for_widget (result, widget);
16535
16536 return result;
16537 }
16538 }
16539
16540 /**
16541 * gtk_widget_get_path:
16542 * @widget: a #GtkWidget
16543 *
16544 * Returns the #GtkWidgetPath representing @widget, if the widget
16545 * is not connected to a toplevel widget, a partial path will be
16546 * created.
16547 *
16548 * Returns: (transfer none): The #GtkWidgetPath representing @widget
16549 **/
16550 GtkWidgetPath *
gtk_widget_get_path(GtkWidget * widget)16551 gtk_widget_get_path (GtkWidget *widget)
16552 {
16553 GtkWidgetPath *path;
16554
16555 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
16556
16557 path = (GtkWidgetPath*)g_object_get_qdata (G_OBJECT (widget), quark_widget_path);
16558 if (!path)
16559 {
16560 path = _gtk_widget_create_path (widget);
16561 g_object_set_qdata_full (G_OBJECT (widget),
16562 quark_widget_path,
16563 path,
16564 (GDestroyNotify)gtk_widget_path_free);
16565 }
16566
16567 return path;
16568 }
16569
16570 void
gtk_widget_clear_path(GtkWidget * widget)16571 gtk_widget_clear_path (GtkWidget *widget)
16572 {
16573 g_object_set_qdata (G_OBJECT (widget), quark_widget_path, NULL);
16574 }
16575
16576 /**
16577 * gtk_widget_class_set_css_name:
16578 * @widget_class: class to set the name on
16579 * @name: name to use
16580 *
16581 * Sets the name to be used for CSS matching of widgets.
16582 *
16583 * If this function is not called for a given class, the name
16584 * of the parent class is used.
16585 *
16586 * Since: 3.20
16587 */
16588 void
gtk_widget_class_set_css_name(GtkWidgetClass * widget_class,const char * name)16589 gtk_widget_class_set_css_name (GtkWidgetClass *widget_class,
16590 const char *name)
16591 {
16592 GtkWidgetClassPrivate *priv;
16593
16594 g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
16595 g_return_if_fail (name != NULL);
16596
16597 priv = widget_class->priv;
16598
16599 priv->css_name = g_intern_string (name);
16600 }
16601
16602 /**
16603 * gtk_widget_class_get_css_name:
16604 * @widget_class: class to set the name on
16605 *
16606 * Gets the name used by this class for matching in CSS code. See
16607 * gtk_widget_class_set_css_name() for details.
16608 *
16609 * Returns: the CSS name of the given class
16610 *
16611 * Since: 3.20
16612 */
16613 const char *
gtk_widget_class_get_css_name(GtkWidgetClass * widget_class)16614 gtk_widget_class_get_css_name (GtkWidgetClass *widget_class)
16615 {
16616 g_return_val_if_fail (GTK_IS_WIDGET_CLASS (widget_class), NULL);
16617
16618 return widget_class->priv->css_name;
16619 }
16620
16621 void
_gtk_widget_style_context_invalidated(GtkWidget * widget)16622 _gtk_widget_style_context_invalidated (GtkWidget *widget)
16623 {
16624 g_signal_emit (widget, widget_signals[STYLE_UPDATED], 0);
16625 }
16626
16627 GtkCssNode *
gtk_widget_get_css_node(GtkWidget * widget)16628 gtk_widget_get_css_node (GtkWidget *widget)
16629 {
16630 return widget->priv->cssnode;
16631 }
16632
16633 GtkStyleContext *
_gtk_widget_peek_style_context(GtkWidget * widget)16634 _gtk_widget_peek_style_context (GtkWidget *widget)
16635 {
16636 return widget->priv->context;
16637 }
16638
16639
16640 /**
16641 * gtk_widget_get_style_context:
16642 * @widget: a #GtkWidget
16643 *
16644 * Returns the style context associated to @widget. The returned object is
16645 * guaranteed to be the same for the lifetime of @widget.
16646 *
16647 * Returns: (transfer none): a #GtkStyleContext. This memory is owned by @widget and
16648 * must not be freed.
16649 **/
16650 GtkStyleContext *
gtk_widget_get_style_context(GtkWidget * widget)16651 gtk_widget_get_style_context (GtkWidget *widget)
16652 {
16653 GtkWidgetPrivate *priv;
16654
16655 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
16656
16657 priv = widget->priv;
16658
16659 if (G_UNLIKELY (priv->context == NULL))
16660 {
16661 GdkScreen *screen;
16662 GdkFrameClock *frame_clock;
16663
16664 priv->context = gtk_style_context_new_for_node (priv->cssnode);
16665
16666 gtk_style_context_set_id (priv->context, priv->name);
16667 gtk_style_context_set_state (priv->context, priv->state_flags);
16668 gtk_style_context_set_scale (priv->context, gtk_widget_get_scale_factor (widget));
16669
16670 screen = gtk_widget_get_screen (widget);
16671 if (screen)
16672 gtk_style_context_set_screen (priv->context, screen);
16673
16674 frame_clock = gtk_widget_get_frame_clock (widget);
16675 if (frame_clock)
16676 gtk_style_context_set_frame_clock (priv->context, frame_clock);
16677
16678 if (priv->parent)
16679 gtk_style_context_set_parent (priv->context,
16680 _gtk_widget_get_style_context (priv->parent));
16681 }
16682
16683 return widget->priv->context;
16684 }
16685
16686 void
_gtk_widget_invalidate_style_context(GtkWidget * widget,GtkCssChange change)16687 _gtk_widget_invalidate_style_context (GtkWidget *widget,
16688 GtkCssChange change)
16689 {
16690 gtk_css_node_invalidate (widget->priv->cssnode, change);
16691 }
16692
16693 /**
16694 * gtk_widget_get_modifier_mask:
16695 * @widget: a #GtkWidget
16696 * @intent: the use case for the modifier mask
16697 *
16698 * Returns the modifier mask the @widget’s windowing system backend
16699 * uses for a particular purpose.
16700 *
16701 * See gdk_keymap_get_modifier_mask().
16702 *
16703 * Returns: the modifier mask used for @intent.
16704 *
16705 * Since: 3.4
16706 **/
16707 GdkModifierType
gtk_widget_get_modifier_mask(GtkWidget * widget,GdkModifierIntent intent)16708 gtk_widget_get_modifier_mask (GtkWidget *widget,
16709 GdkModifierIntent intent)
16710 {
16711 GdkDisplay *display;
16712
16713 g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
16714
16715 display = gtk_widget_get_display (widget);
16716
16717 return gdk_keymap_get_modifier_mask (gdk_keymap_get_for_display (display),
16718 intent);
16719 }
16720
16721 GtkStyle *
_gtk_widget_get_style(GtkWidget * widget)16722 _gtk_widget_get_style (GtkWidget *widget)
16723 {
16724 return widget->priv->style;
16725 }
16726
16727 void
_gtk_widget_set_style(GtkWidget * widget,GtkStyle * style)16728 _gtk_widget_set_style (GtkWidget *widget,
16729 GtkStyle *style)
16730 {
16731 widget->priv->style = style;
16732 g_signal_emit (widget, widget_signals[STYLE_SET], 0, widget->priv->style);
16733 }
16734
16735 GtkActionMuxer *
_gtk_widget_get_parent_muxer(GtkWidget * widget,gboolean create)16736 _gtk_widget_get_parent_muxer (GtkWidget *widget,
16737 gboolean create)
16738 {
16739 GtkWidget *parent;
16740
16741 if (GTK_IS_WINDOW (widget))
16742 return gtk_application_get_parent_muxer_for_window (GTK_WINDOW (widget));
16743
16744 if (GTK_IS_MENU (widget))
16745 parent = gtk_menu_get_attach_widget (GTK_MENU (widget));
16746 else if (GTK_IS_POPOVER (widget))
16747 parent = gtk_popover_get_relative_to (GTK_POPOVER (widget));
16748 else
16749 parent = _gtk_widget_get_parent (widget);
16750
16751 if (parent)
16752 return _gtk_widget_get_action_muxer (parent, create);
16753
16754 return NULL;
16755 }
16756
16757 void
_gtk_widget_update_parent_muxer(GtkWidget * widget)16758 _gtk_widget_update_parent_muxer (GtkWidget *widget)
16759 {
16760 GtkActionMuxer *muxer;
16761
16762 muxer = (GtkActionMuxer*)g_object_get_qdata (G_OBJECT (widget), quark_action_muxer);
16763 if (muxer == NULL)
16764 return;
16765
16766 gtk_action_muxer_set_parent (muxer,
16767 _gtk_widget_get_parent_muxer (widget, TRUE));
16768 }
16769
16770 GtkActionMuxer *
_gtk_widget_get_action_muxer(GtkWidget * widget,gboolean create)16771 _gtk_widget_get_action_muxer (GtkWidget *widget,
16772 gboolean create)
16773 {
16774 GtkActionMuxer *muxer;
16775
16776 muxer = (GtkActionMuxer*)g_object_get_qdata (G_OBJECT (widget), quark_action_muxer);
16777 if (muxer)
16778 return muxer;
16779
16780 if (create)
16781 {
16782 muxer = gtk_action_muxer_new ();
16783 g_object_set_qdata_full (G_OBJECT (widget),
16784 quark_action_muxer,
16785 muxer,
16786 g_object_unref);
16787 _gtk_widget_update_parent_muxer (widget);
16788
16789 return muxer;
16790 }
16791 else
16792 return _gtk_widget_get_parent_muxer (widget, FALSE);
16793 }
16794
16795 /**
16796 * gtk_widget_insert_action_group:
16797 * @widget: a #GtkWidget
16798 * @name: the prefix for actions in @group
16799 * @group: (allow-none): a #GActionGroup, or %NULL
16800 *
16801 * Inserts @group into @widget. Children of @widget that implement
16802 * #GtkActionable can then be associated with actions in @group by
16803 * setting their “action-name” to
16804 * @prefix.`action-name`.
16805 *
16806 * If @group is %NULL, a previously inserted group for @name is removed
16807 * from @widget.
16808 *
16809 * Since: 3.6
16810 */
16811 void
gtk_widget_insert_action_group(GtkWidget * widget,const gchar * name,GActionGroup * group)16812 gtk_widget_insert_action_group (GtkWidget *widget,
16813 const gchar *name,
16814 GActionGroup *group)
16815 {
16816 GtkActionMuxer *muxer;
16817
16818 g_return_if_fail (GTK_IS_WIDGET (widget));
16819 g_return_if_fail (name != NULL);
16820
16821 muxer = _gtk_widget_get_action_muxer (widget, TRUE);
16822
16823 if (group)
16824 gtk_action_muxer_insert (muxer, name, group);
16825 else
16826 gtk_action_muxer_remove (muxer, name);
16827 }
16828
16829 /****************************************************************
16830 * GtkBuilder automated templates *
16831 ****************************************************************/
16832 static AutomaticChildClass *
template_child_class_new(const gchar * name,gboolean internal_child,gssize offset)16833 template_child_class_new (const gchar *name,
16834 gboolean internal_child,
16835 gssize offset)
16836 {
16837 AutomaticChildClass *child_class = g_slice_new0 (AutomaticChildClass);
16838
16839 child_class->name = g_strdup (name);
16840 child_class->internal_child = internal_child;
16841 child_class->offset = offset;
16842
16843 return child_class;
16844 }
16845
16846 static void
template_child_class_free(AutomaticChildClass * child_class)16847 template_child_class_free (AutomaticChildClass *child_class)
16848 {
16849 if (child_class)
16850 {
16851 g_free (child_class->name);
16852 g_slice_free (AutomaticChildClass, child_class);
16853 }
16854 }
16855
16856 static CallbackSymbol *
callback_symbol_new(const gchar * name,GCallback callback)16857 callback_symbol_new (const gchar *name,
16858 GCallback callback)
16859 {
16860 CallbackSymbol *cb = g_slice_new0 (CallbackSymbol);
16861
16862 cb->callback_name = g_strdup (name);
16863 cb->callback_symbol = callback;
16864
16865 return cb;
16866 }
16867
16868 static void
callback_symbol_free(CallbackSymbol * callback)16869 callback_symbol_free (CallbackSymbol *callback)
16870 {
16871 if (callback)
16872 {
16873 g_free (callback->callback_name);
16874 g_slice_free (CallbackSymbol, callback);
16875 }
16876 }
16877
16878 static void
template_data_free(GtkWidgetTemplate * template_data)16879 template_data_free (GtkWidgetTemplate *template_data)
16880 {
16881 if (template_data)
16882 {
16883 g_bytes_unref (template_data->data);
16884 g_slist_free_full (template_data->children, (GDestroyNotify)template_child_class_free);
16885 g_slist_free_full (template_data->callbacks, (GDestroyNotify)callback_symbol_free);
16886
16887 if (template_data->connect_data &&
16888 template_data->destroy_notify)
16889 template_data->destroy_notify (template_data->connect_data);
16890
16891 g_slice_free (GtkWidgetTemplate, template_data);
16892 }
16893 }
16894
16895 static GHashTable *
get_auto_child_hash(GtkWidget * widget,GType type,gboolean create)16896 get_auto_child_hash (GtkWidget *widget,
16897 GType type,
16898 gboolean create)
16899 {
16900 GHashTable *auto_children;
16901 GHashTable *auto_child_hash;
16902
16903 auto_children = (GHashTable *)g_object_get_qdata (G_OBJECT (widget), quark_auto_children);
16904 if (auto_children == NULL)
16905 {
16906 if (!create)
16907 return NULL;
16908
16909 auto_children = g_hash_table_new_full (g_direct_hash,
16910 NULL,
16911 NULL, (GDestroyNotify)g_hash_table_destroy);
16912 g_object_set_qdata_full (G_OBJECT (widget),
16913 quark_auto_children,
16914 auto_children,
16915 (GDestroyNotify)g_hash_table_destroy);
16916 }
16917
16918 auto_child_hash =
16919 g_hash_table_lookup (auto_children, GSIZE_TO_POINTER (type));
16920
16921 if (!auto_child_hash && create)
16922 {
16923 auto_child_hash = g_hash_table_new_full (g_str_hash,
16924 g_str_equal,
16925 NULL,
16926 (GDestroyNotify)g_object_unref);
16927
16928 g_hash_table_insert (auto_children,
16929 GSIZE_TO_POINTER (type),
16930 auto_child_hash);
16931 }
16932
16933 return auto_child_hash;
16934 }
16935
16936 static gboolean
setup_template_child(GtkWidgetTemplate * template_data,GType class_type,AutomaticChildClass * child_class,GtkWidget * widget,GtkBuilder * builder)16937 setup_template_child (GtkWidgetTemplate *template_data,
16938 GType class_type,
16939 AutomaticChildClass *child_class,
16940 GtkWidget *widget,
16941 GtkBuilder *builder)
16942 {
16943 GHashTable *auto_child_hash;
16944 GObject *object;
16945
16946 object = gtk_builder_get_object (builder, child_class->name);
16947 if (!object)
16948 {
16949 g_critical ("Unable to retrieve object '%s' from class template for type '%s' while building a '%s'",
16950 child_class->name, g_type_name (class_type), G_OBJECT_TYPE_NAME (widget));
16951 return FALSE;
16952 }
16953
16954 /* Insert into the hash so that it can be fetched with
16955 * gtk_widget_get_template_child() and also in automated
16956 * implementations of GtkBuildable.get_internal_child()
16957 */
16958 auto_child_hash = get_auto_child_hash (widget, class_type, TRUE);
16959 g_hash_table_insert (auto_child_hash, child_class->name, g_object_ref (object));
16960
16961 if (child_class->offset != 0)
16962 {
16963 gpointer field_p;
16964
16965 /* Assign 'object' to the specified offset in the instance (or private) data */
16966 field_p = G_STRUCT_MEMBER_P (widget, child_class->offset);
16967 (* (gpointer *) field_p) = object;
16968 }
16969
16970 return TRUE;
16971 }
16972
16973 /**
16974 * gtk_widget_init_template:
16975 * @widget: a #GtkWidget
16976 *
16977 * Creates and initializes child widgets defined in templates. This
16978 * function must be called in the instance initializer for any
16979 * class which assigned itself a template using gtk_widget_class_set_template()
16980 *
16981 * It is important to call this function in the instance initializer
16982 * of a #GtkWidget subclass and not in #GObject.constructed() or
16983 * #GObject.constructor() for two reasons.
16984 *
16985 * One reason is that generally derived widgets will assume that parent
16986 * class composite widgets have been created in their instance
16987 * initializers.
16988 *
16989 * Another reason is that when calling g_object_new() on a widget with
16990 * composite templates, it’s important to build the composite widgets
16991 * before the construct properties are set. Properties passed to g_object_new()
16992 * should take precedence over properties set in the private template XML.
16993 *
16994 * Since: 3.10
16995 */
16996 void
gtk_widget_init_template(GtkWidget * widget)16997 gtk_widget_init_template (GtkWidget *widget)
16998 {
16999 GtkWidgetTemplate *template;
17000 GtkBuilder *builder;
17001 GError *error = NULL;
17002 GObject *object;
17003 GSList *l;
17004 GType class_type;
17005
17006 g_return_if_fail (GTK_IS_WIDGET (widget));
17007
17008 object = G_OBJECT (widget);
17009 class_type = G_OBJECT_TYPE (widget);
17010
17011 template = GTK_WIDGET_GET_CLASS (widget)->priv->template;
17012 g_return_if_fail (template != NULL);
17013
17014 builder = gtk_builder_new ();
17015
17016 /* Add any callback symbols declared for this GType to the GtkBuilder namespace */
17017 for (l = template->callbacks; l; l = l->next)
17018 {
17019 CallbackSymbol *callback = l->data;
17020
17021 gtk_builder_add_callback_symbol (builder, callback->callback_name, callback->callback_symbol);
17022 }
17023
17024 /* This will build the template XML as children to the widget instance, also it
17025 * will validate that the template is created for the correct GType and assert that
17026 * there is no infinite recursion.
17027 */
17028 if (!gtk_builder_extend_with_template (builder, widget, class_type,
17029 (const gchar *)g_bytes_get_data (template->data, NULL),
17030 g_bytes_get_size (template->data),
17031 &error))
17032 {
17033 g_critical ("Error building template class '%s' for an instance of type '%s': %s",
17034 g_type_name (class_type), G_OBJECT_TYPE_NAME (object), error->message);
17035 g_error_free (error);
17036
17037 /* This should never happen, if the template XML cannot be built
17038 * then it is a critical programming error.
17039 */
17040 g_object_unref (builder);
17041 return;
17042 }
17043
17044 /* Build the automatic child data
17045 */
17046 for (l = template->children; l; l = l->next)
17047 {
17048 AutomaticChildClass *child_class = l->data;
17049
17050 /* This will setup the pointer of an automated child, and cause
17051 * it to be available in any GtkBuildable.get_internal_child()
17052 * invocations which may follow by reference in child classes.
17053 */
17054 if (!setup_template_child (template,
17055 class_type,
17056 child_class,
17057 widget,
17058 builder))
17059 {
17060 g_object_unref (builder);
17061 return;
17062 }
17063 }
17064
17065 /* Connect signals. All signal data from a template receive the
17066 * template instance as user data automatically.
17067 *
17068 * A GtkBuilderConnectFunc can be provided to gtk_widget_class_set_signal_connect_func()
17069 * in order for templates to be usable by bindings.
17070 */
17071 if (template->connect_func)
17072 gtk_builder_connect_signals_full (builder, template->connect_func, template->connect_data);
17073 else
17074 gtk_builder_connect_signals (builder, object);
17075
17076 g_object_unref (builder);
17077 }
17078
17079 /**
17080 * gtk_widget_class_set_template:
17081 * @widget_class: A #GtkWidgetClass
17082 * @template_bytes: A #GBytes holding the #GtkBuilder XML
17083 *
17084 * This should be called at class initialization time to specify
17085 * the GtkBuilder XML to be used to extend a widget.
17086 *
17087 * For convenience, gtk_widget_class_set_template_from_resource() is also provided.
17088 *
17089 * Note that any class that installs templates must call gtk_widget_init_template()
17090 * in the widget’s instance initializer.
17091 *
17092 * Since: 3.10
17093 */
17094 void
gtk_widget_class_set_template(GtkWidgetClass * widget_class,GBytes * template_bytes)17095 gtk_widget_class_set_template (GtkWidgetClass *widget_class,
17096 GBytes *template_bytes)
17097 {
17098 g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
17099 g_return_if_fail (widget_class->priv->template == NULL);
17100 g_return_if_fail (template_bytes != NULL);
17101
17102 widget_class->priv->template = g_slice_new0 (GtkWidgetTemplate);
17103 widget_class->priv->template->data = g_bytes_ref (template_bytes);
17104 }
17105
17106 /**
17107 * gtk_widget_class_set_template_from_resource:
17108 * @widget_class: A #GtkWidgetClass
17109 * @resource_name: The name of the resource to load the template from
17110 *
17111 * A convenience function to call gtk_widget_class_set_template().
17112 *
17113 * Note that any class that installs templates must call gtk_widget_init_template()
17114 * in the widget’s instance initializer.
17115 *
17116 * Since: 3.10
17117 */
17118 void
gtk_widget_class_set_template_from_resource(GtkWidgetClass * widget_class,const gchar * resource_name)17119 gtk_widget_class_set_template_from_resource (GtkWidgetClass *widget_class,
17120 const gchar *resource_name)
17121 {
17122 GError *error = NULL;
17123 GBytes *bytes = NULL;
17124
17125 g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
17126 g_return_if_fail (widget_class->priv->template == NULL);
17127 g_return_if_fail (resource_name && resource_name[0]);
17128
17129 /* This is a hack, because class initializers now access resources
17130 * and GIR/gtk-doc initializes classes without initializing GTK+,
17131 * we ensure that our base resources are registered here and
17132 * avoid warnings which building GIRs/documentation.
17133 */
17134 _gtk_ensure_resources ();
17135
17136 bytes = g_resources_lookup_data (resource_name, 0, &error);
17137 if (!bytes)
17138 {
17139 g_critical ("Unable to load resource for composite template for type '%s': %s",
17140 G_OBJECT_CLASS_NAME (widget_class), error->message);
17141 g_error_free (error);
17142 return;
17143 }
17144
17145 gtk_widget_class_set_template (widget_class, bytes);
17146 g_bytes_unref (bytes);
17147 }
17148
17149 /**
17150 * gtk_widget_class_bind_template_callback_full:
17151 * @widget_class: A #GtkWidgetClass
17152 * @callback_name: The name of the callback as expected in the template XML
17153 * @callback_symbol: (scope async): The callback symbol
17154 *
17155 * Declares a @callback_symbol to handle @callback_name from the template XML
17156 * defined for @widget_type. See gtk_builder_add_callback_symbol().
17157 *
17158 * Note that this must be called from a composite widget classes class
17159 * initializer after calling gtk_widget_class_set_template().
17160 *
17161 * Since: 3.10
17162 */
17163 void
gtk_widget_class_bind_template_callback_full(GtkWidgetClass * widget_class,const gchar * callback_name,GCallback callback_symbol)17164 gtk_widget_class_bind_template_callback_full (GtkWidgetClass *widget_class,
17165 const gchar *callback_name,
17166 GCallback callback_symbol)
17167 {
17168 CallbackSymbol *cb;
17169
17170 g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
17171 g_return_if_fail (widget_class->priv->template != NULL);
17172 g_return_if_fail (callback_name && callback_name[0]);
17173 g_return_if_fail (callback_symbol != NULL);
17174
17175 cb = callback_symbol_new (callback_name, callback_symbol);
17176 widget_class->priv->template->callbacks = g_slist_prepend (widget_class->priv->template->callbacks, cb);
17177 }
17178
17179 /**
17180 * gtk_widget_class_set_connect_func:
17181 * @widget_class: A #GtkWidgetClass
17182 * @connect_func: The #GtkBuilderConnectFunc to use when connecting signals in the class template
17183 * @connect_data: The data to pass to @connect_func
17184 * @connect_data_destroy: The #GDestroyNotify to free @connect_data, this will only be used at
17185 * class finalization time, when no classes of type @widget_type are in use anymore.
17186 *
17187 * For use in language bindings, this will override the default #GtkBuilderConnectFunc to be
17188 * used when parsing GtkBuilder XML from this class’s template data.
17189 *
17190 * Note that this must be called from a composite widget classes class
17191 * initializer after calling gtk_widget_class_set_template().
17192 *
17193 * Since: 3.10
17194 */
17195 void
gtk_widget_class_set_connect_func(GtkWidgetClass * widget_class,GtkBuilderConnectFunc connect_func,gpointer connect_data,GDestroyNotify connect_data_destroy)17196 gtk_widget_class_set_connect_func (GtkWidgetClass *widget_class,
17197 GtkBuilderConnectFunc connect_func,
17198 gpointer connect_data,
17199 GDestroyNotify connect_data_destroy)
17200 {
17201 g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
17202 g_return_if_fail (widget_class->priv->template != NULL);
17203
17204 /* Defensive, destroy any previously set data */
17205 if (widget_class->priv->template->connect_data &&
17206 widget_class->priv->template->destroy_notify)
17207 widget_class->priv->template->destroy_notify (widget_class->priv->template->connect_data);
17208
17209 widget_class->priv->template->connect_func = connect_func;
17210 widget_class->priv->template->connect_data = connect_data;
17211 widget_class->priv->template->destroy_notify = connect_data_destroy;
17212 }
17213
17214 /**
17215 * gtk_widget_class_bind_template_child_full:
17216 * @widget_class: A #GtkWidgetClass
17217 * @name: The “id” of the child defined in the template XML
17218 * @internal_child: Whether the child should be accessible as an “internal-child”
17219 * when this class is used in GtkBuilder XML
17220 * @struct_offset: The structure offset into the composite widget’s instance public or private structure
17221 * where the automated child pointer should be set, or 0 to not assign the pointer.
17222 *
17223 * Automatically assign an object declared in the class template XML to be set to a location
17224 * on a freshly built instance’s private data, or alternatively accessible via gtk_widget_get_template_child().
17225 *
17226 * The struct can point either into the public instance, then you should use G_STRUCT_OFFSET(WidgetType, member)
17227 * for @struct_offset, or in the private struct, then you should use G_PRIVATE_OFFSET(WidgetType, member).
17228 *
17229 * An explicit strong reference will be held automatically for the duration of your
17230 * instance’s life cycle, it will be released automatically when #GObjectClass.dispose() runs
17231 * on your instance and if a @struct_offset that is != 0 is specified, then the automatic location
17232 * in your instance public or private data will be set to %NULL. You can however access an automated child
17233 * pointer the first time your classes #GObjectClass.dispose() runs, or alternatively in
17234 * #GtkWidgetClass.destroy().
17235 *
17236 * If @internal_child is specified, #GtkBuildableIface.get_internal_child() will be automatically
17237 * implemented by the #GtkWidget class so there is no need to implement it manually.
17238 *
17239 * The wrapper macros gtk_widget_class_bind_template_child(), gtk_widget_class_bind_template_child_internal(),
17240 * gtk_widget_class_bind_template_child_private() and gtk_widget_class_bind_template_child_internal_private()
17241 * might be more convenient to use.
17242 *
17243 * Note that this must be called from a composite widget classes class
17244 * initializer after calling gtk_widget_class_set_template().
17245 *
17246 * Since: 3.10
17247 */
17248 void
gtk_widget_class_bind_template_child_full(GtkWidgetClass * widget_class,const gchar * name,gboolean internal_child,gssize struct_offset)17249 gtk_widget_class_bind_template_child_full (GtkWidgetClass *widget_class,
17250 const gchar *name,
17251 gboolean internal_child,
17252 gssize struct_offset)
17253 {
17254 AutomaticChildClass *child_class;
17255
17256 g_return_if_fail (GTK_IS_WIDGET_CLASS (widget_class));
17257 g_return_if_fail (widget_class->priv->template != NULL);
17258 g_return_if_fail (name && name[0]);
17259
17260 child_class = template_child_class_new (name,
17261 internal_child,
17262 struct_offset);
17263 widget_class->priv->template->children =
17264 g_slist_prepend (widget_class->priv->template->children, child_class);
17265 }
17266
17267 /**
17268 * gtk_widget_get_template_child:
17269 * @widget: A #GtkWidget
17270 * @widget_type: The #GType to get a template child for
17271 * @name: The “id” of the child defined in the template XML
17272 *
17273 * Fetch an object build from the template XML for @widget_type in this @widget instance.
17274 *
17275 * This will only report children which were previously declared with
17276 * gtk_widget_class_bind_template_child_full() or one of its
17277 * variants.
17278 *
17279 * This function is only meant to be called for code which is private to the @widget_type which
17280 * declared the child and is meant for language bindings which cannot easily make use
17281 * of the GObject structure offsets.
17282 *
17283 * Returns: (transfer none): The object built in the template XML with the id @name
17284 */
17285 GObject *
gtk_widget_get_template_child(GtkWidget * widget,GType widget_type,const gchar * name)17286 gtk_widget_get_template_child (GtkWidget *widget,
17287 GType widget_type,
17288 const gchar *name)
17289 {
17290 GHashTable *auto_child_hash;
17291 GObject *ret = NULL;
17292
17293 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
17294 g_return_val_if_fail (g_type_name (widget_type) != NULL, NULL);
17295 g_return_val_if_fail (name && name[0], NULL);
17296
17297 auto_child_hash = get_auto_child_hash (widget, widget_type, FALSE);
17298
17299 if (auto_child_hash)
17300 ret = g_hash_table_lookup (auto_child_hash, name);
17301
17302 return ret;
17303 }
17304
17305 /**
17306 * gtk_widget_list_action_prefixes:
17307 * @widget: A #GtkWidget
17308 *
17309 * Retrieves a %NULL-terminated array of strings containing the prefixes of
17310 * #GActionGroup's available to @widget.
17311 *
17312 * Returns: (transfer container): a %NULL-terminated array of strings.
17313 *
17314 * Since: 3.16
17315 */
17316 const gchar **
gtk_widget_list_action_prefixes(GtkWidget * widget)17317 gtk_widget_list_action_prefixes (GtkWidget *widget)
17318 {
17319 GtkActionMuxer *muxer;
17320
17321 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
17322
17323 muxer = _gtk_widget_get_action_muxer (widget, FALSE);
17324 if (muxer)
17325 return gtk_action_muxer_list_prefixes (muxer);
17326
17327 return g_new0 (const gchar *, 1);
17328 }
17329
17330 /**
17331 * gtk_widget_get_action_group:
17332 * @widget: A #GtkWidget
17333 * @prefix: The “prefix” of the action group.
17334 *
17335 * Retrieves the #GActionGroup that was registered using @prefix. The resulting
17336 * #GActionGroup may have been registered to @widget or any #GtkWidget in its
17337 * ancestry.
17338 *
17339 * If no action group was found matching @prefix, then %NULL is returned.
17340 *
17341 * Returns: (transfer none) (nullable): A #GActionGroup or %NULL.
17342 *
17343 * Since: 3.16
17344 */
17345 GActionGroup *
gtk_widget_get_action_group(GtkWidget * widget,const gchar * prefix)17346 gtk_widget_get_action_group (GtkWidget *widget,
17347 const gchar *prefix)
17348 {
17349 GtkActionMuxer *muxer;
17350
17351 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
17352 g_return_val_if_fail (prefix, NULL);
17353
17354 muxer = _gtk_widget_get_action_muxer (widget, FALSE);
17355 if (muxer)
17356 return gtk_action_muxer_lookup (muxer, prefix);
17357
17358 return NULL;
17359 }
17360
17361 static void
event_controller_grab_notify(GtkWidget * widget,gboolean was_grabbed,EventControllerData * data)17362 event_controller_grab_notify (GtkWidget *widget,
17363 gboolean was_grabbed,
17364 EventControllerData *data)
17365 {
17366 GdkDevice *device = NULL;
17367
17368 if (GTK_IS_GESTURE (data->controller))
17369 device = gtk_gesture_get_device (GTK_GESTURE (data->controller));
17370
17371 if (!device || !gtk_widget_device_is_shadowed (widget, device))
17372 return;
17373
17374 gtk_event_controller_reset (data->controller);
17375 }
17376
17377 static void
_gtk_widget_update_evmask(GtkWidget * widget)17378 _gtk_widget_update_evmask (GtkWidget *widget)
17379 {
17380 if (_gtk_widget_get_realized (widget))
17381 {
17382 gint events = GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (widget),
17383 quark_event_mask));
17384 gtk_widget_add_events_internal (widget, NULL, events);
17385 }
17386 }
17387
17388 static void
event_controller_sequence_state_changed(GtkGesture * gesture,GdkEventSequence * sequence,GtkEventSequenceState state,GtkWidget * widget)17389 event_controller_sequence_state_changed (GtkGesture *gesture,
17390 GdkEventSequence *sequence,
17391 GtkEventSequenceState state,
17392 GtkWidget *widget)
17393 {
17394 gboolean handled = FALSE;
17395 GtkWidget *event_widget;
17396 const GdkEvent *event;
17397
17398 handled = _gtk_widget_set_sequence_state_internal (widget, sequence,
17399 state, gesture);
17400
17401 if (!handled || state != GTK_EVENT_SEQUENCE_CLAIMED)
17402 return;
17403
17404 event = _gtk_widget_get_last_event (widget, sequence);
17405
17406 if (!event)
17407 return;
17408
17409 event_widget = gtk_get_event_widget ((GdkEvent *) event);
17410 cancel_event_sequence_on_hierarchy (widget, event_widget, sequence);
17411 }
17412
17413 static EventControllerData *
_gtk_widget_has_controller(GtkWidget * widget,GtkEventController * controller)17414 _gtk_widget_has_controller (GtkWidget *widget,
17415 GtkEventController *controller)
17416 {
17417 EventControllerData *data;
17418 GtkWidgetPrivate *priv;
17419 GList *l;
17420
17421 priv = widget->priv;
17422
17423 for (l = priv->event_controllers; l; l = l->next)
17424 {
17425 data = l->data;
17426
17427 if (data->controller == controller)
17428 return data;
17429 }
17430
17431 return NULL;
17432 }
17433
17434 void
_gtk_widget_add_controller(GtkWidget * widget,GtkEventController * controller)17435 _gtk_widget_add_controller (GtkWidget *widget,
17436 GtkEventController *controller)
17437 {
17438 EventControllerData *data;
17439 GtkWidgetPrivate *priv;
17440
17441 g_return_if_fail (GTK_IS_WIDGET (widget));
17442 g_return_if_fail (GTK_IS_EVENT_CONTROLLER (controller));
17443 g_return_if_fail (widget == gtk_event_controller_get_widget (controller));
17444
17445 priv = widget->priv;
17446 data = _gtk_widget_has_controller (widget, controller);
17447
17448 if (data)
17449 return;
17450
17451 data = g_new0 (EventControllerData, 1);
17452 data->controller = controller;
17453 data->grab_notify_id =
17454 g_signal_connect (widget, "grab-notify",
17455 G_CALLBACK (event_controller_grab_notify), data);
17456
17457 g_object_add_weak_pointer (G_OBJECT (data->controller), (gpointer *) &data->controller);
17458
17459 if (GTK_IS_GESTURE (controller))
17460 {
17461 data->sequence_state_changed_id =
17462 g_signal_connect (controller, "sequence-state-changed",
17463 G_CALLBACK (event_controller_sequence_state_changed),
17464 widget);
17465 }
17466
17467 priv->event_controllers = g_list_prepend (priv->event_controllers, data);
17468 _gtk_widget_update_evmask (widget);
17469 }
17470
17471 void
_gtk_widget_remove_controller(GtkWidget * widget,GtkEventController * controller)17472 _gtk_widget_remove_controller (GtkWidget *widget,
17473 GtkEventController *controller)
17474 {
17475 EventControllerData *data;
17476
17477 g_return_if_fail (GTK_IS_WIDGET (widget));
17478 g_return_if_fail (GTK_IS_EVENT_CONTROLLER (controller));
17479
17480 data = _gtk_widget_has_controller (widget, controller);
17481
17482 if (!data)
17483 return;
17484
17485 g_object_remove_weak_pointer (G_OBJECT (data->controller), (gpointer *) &data->controller);
17486
17487 if (g_signal_handler_is_connected (widget, data->grab_notify_id))
17488 g_signal_handler_disconnect (widget, data->grab_notify_id);
17489
17490 if (data->sequence_state_changed_id)
17491 g_signal_handler_disconnect (data->controller, data->sequence_state_changed_id);
17492
17493 data->controller = NULL;
17494 }
17495
17496 GList *
_gtk_widget_list_controllers(GtkWidget * widget,GtkPropagationPhase phase)17497 _gtk_widget_list_controllers (GtkWidget *widget,
17498 GtkPropagationPhase phase)
17499 {
17500 EventControllerData *data;
17501 GtkWidgetPrivate *priv;
17502 GList *l, *retval = NULL;
17503
17504 g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
17505
17506 priv = widget->priv;
17507
17508 for (l = priv->event_controllers; l; l = l->next)
17509 {
17510 data = l->data;
17511
17512 if (data->controller != NULL &&
17513 phase == gtk_event_controller_get_propagation_phase (data->controller))
17514 retval = g_list_prepend (retval, data->controller);
17515 }
17516
17517 return retval;
17518 }
17519
17520 gboolean
_gtk_widget_consumes_motion(GtkWidget * widget,GdkEventSequence * sequence)17521 _gtk_widget_consumes_motion (GtkWidget *widget,
17522 GdkEventSequence *sequence)
17523 {
17524 EventControllerData *data;
17525 GtkWidgetPrivate *priv;
17526 GList *l;
17527
17528 g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
17529
17530 priv = widget->priv;
17531
17532 for (l = priv->event_controllers; l; l = l->next)
17533 {
17534 data = l->data;
17535
17536 if (data->controller == NULL)
17537 continue;
17538
17539 if ((!GTK_IS_GESTURE_SINGLE (data->controller) ||
17540 GTK_IS_GESTURE_DRAG (data->controller) ||
17541 GTK_IS_GESTURE_SWIPE (data->controller)) &&
17542 gtk_gesture_handles_sequence (GTK_GESTURE (data->controller), sequence))
17543 return TRUE;
17544 }
17545
17546 return FALSE;
17547 }
17548
17549 void
gtk_widget_reset_controllers(GtkWidget * widget)17550 gtk_widget_reset_controllers (GtkWidget *widget)
17551 {
17552 EventControllerData *controller_data;
17553 GtkWidgetPrivate *priv = widget->priv;
17554 GList *l;
17555
17556 /* Reset all controllers */
17557 for (l = priv->event_controllers; l; l = l->next)
17558 {
17559 controller_data = l->data;
17560
17561 if (controller_data->controller == NULL)
17562 continue;
17563
17564 gtk_event_controller_reset (controller_data->controller);
17565 }
17566 }
17567
17568 void
gtk_widget_render(GtkWidget * widget,GdkWindow * window,const cairo_region_t * region)17569 gtk_widget_render (GtkWidget *widget,
17570 GdkWindow *window,
17571 const cairo_region_t *region)
17572 {
17573 GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
17574 GdkDrawingContext *context;
17575 gboolean do_clip;
17576 cairo_t *cr;
17577 int x, y;
17578 gboolean is_double_buffered;
17579
17580 /* We take the value here, in case somebody manages to changes
17581 * the double_buffered value inside a ::draw call, and ends up
17582 * breaking everything.
17583 */
17584 is_double_buffered = priv->double_buffered;
17585 if (is_double_buffered)
17586 {
17587 /* We only render double buffered on native windows */
17588 if (!gdk_window_has_native (window))
17589 return;
17590
17591 context = gdk_window_begin_draw_frame (window, region);
17592 cr = gdk_drawing_context_get_cairo_context (context);
17593 }
17594 else
17595 {
17596 /* This is annoying, but it has to stay because Firefox
17597 * disables double buffering on a top-level GdkWindow,
17598 * which breaks the drawing context.
17599 *
17600 * Candidate for deletion in the next major API bump.
17601 */
17602 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
17603 cr = gdk_cairo_create (window);
17604 G_GNUC_END_IGNORE_DEPRECATIONS
17605 }
17606
17607 do_clip = _gtk_widget_get_translation_to_window (widget, window, &x, &y);
17608 cairo_translate (cr, -x, -y);
17609
17610 gtk_widget_draw_internal (widget, cr, do_clip);
17611
17612 if (is_double_buffered)
17613 gdk_window_end_draw_frame (window, context);
17614 else
17615 cairo_destroy (cr);
17616 }
17617