/* GTK - The GIMP Toolkit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ /* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. See the ChangeLog * files for a list of changes. These files are distributed with * GTK+ at ftp://ftp.gtk.org/pub/gtk/. */ #include "config.h" #include "gtkwidgetprivate.h" #include "gtkaccelgroupprivate.h" #include "gtkaccessibleprivate.h" #include "gtkactionobserverprivate.h" #include "gtkapplicationprivate.h" #include "gtkbuildable.h" #include "gtkbuilderprivate.h" #include "gtkconstraint.h" #include "gtkcssboxesprivate.h" #include "gtkcssfiltervalueprivate.h" #include "gtkcsstransformvalueprivate.h" #include "gtkcsspositionvalueprivate.h" #include "gtkcssfontvariationsvalueprivate.h" #include "gtkcssnumbervalueprivate.h" #include "gtkcsswidgetnodeprivate.h" #include "gtkdebug.h" #include "gtkgesturedrag.h" #include "gtkgestureprivate.h" #include "gtkgesturesingle.h" #include "gtkgestureswipe.h" #include "gtkgestureprivate.h" #include "gtkintl.h" #include "gtklayoutmanagerprivate.h" #include "gtkmain.h" #include "gtkmarshalers.h" #include "gtknative.h" #include "gtkpopover.h" #include "gtkprivate.h" #include "gtkrenderbackgroundprivate.h" #include "gtkrenderborderprivate.h" #include "gtkrootprivate.h" #include "gtknativeprivate.h" #include "gtkscrollable.h" #include "gtksettingsprivate.h" #include "gtkshortcut.h" #include "gtkshortcutcontrollerprivate.h" #include "gtkshortcutmanager.h" #include "gtkshortcutmanagerprivate.h" #include "gtkshortcuttrigger.h" #include "gtksizegroup-private.h" #include "gtksnapshotprivate.h" #include "gtkstylecontextprivate.h" #include "gtktooltipprivate.h" #include "gsktransformprivate.h" #include "gtktypebuiltins.h" #include "gtkversion.h" #include "gtkwidgetpaintableprivate.h" #include "gtkwindowgroup.h" #include "gtkwindowprivate.h" #include "gtktestatcontextprivate.h" #include "inspector/window.h" #include "gdk/gdkeventsprivate.h" #include "gdk/gdkprofilerprivate.h" #include "gsk/gskdebugprivate.h" #include "gsk/gskrendererprivate.h" #include #include #include #include #include /** * GtkWidget: * * The base class for all widgets. * * `GtkWidget` is the base class all widgets in GTK derive from. It manages the * widget lifecycle, layout, states and style. * * ### Height-for-width Geometry Management * * GTK uses a height-for-width (and width-for-height) geometry management * system. Height-for-width means that a widget can change how much * vertical space it needs, depending on the amount of horizontal space * that it is given (and similar for width-for-height). The most common * example is a label that reflows to fill up the available width, wraps * to fewer lines, and therefore needs less height. * * Height-for-width geometry management is implemented in GTK by way * of two virtual methods: * * - [vfunc@Gtk.Widget.get_request_mode] * - [vfunc@Gtk.Widget.measure] * * There are some important things to keep in mind when implementing * height-for-width and when using it in widget implementations. * * If you implement a direct `GtkWidget` subclass that supports * height-for-width or width-for-height geometry management for itself * or its child widgets, the [vfunc@Gtk.Widget.get_request_mode] virtual * function must be implemented as well and return the widget's preferred * request mode. The default implementation of this virtual function * returns %GTK_SIZE_REQUEST_CONSTANT_SIZE, which means that the widget will * only ever get -1 passed as the for_size value to its * [vfunc@Gtk.Widget.measure] implementation. * * The geometry management system will query a widget hierarchy in * only one orientation at a time. When widgets are initially queried * for their minimum sizes it is generally done in two initial passes * in the [enum@Gtk.SizeRequestMode] chosen by the toplevel. * * For example, when queried in the normal %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH mode: * * First, the default minimum and natural width for each widget * in the interface will be computed using [id@gtk_widget_measure] with an * orientation of %GTK_ORIENTATION_HORIZONTAL and a for_size of -1. * Because the preferred widths for each widget depend on the preferred * widths of their children, this information propagates up the hierarchy, * and finally a minimum and natural width is determined for the entire * toplevel. Next, the toplevel will use the minimum width to query for the * minimum height contextual to that width using [id@gtk_widget_measure] with an * orientation of %GTK_ORIENTATION_VERTICAL and a for_size of the just computed * width. This will also be a highly recursive operation. The minimum height * for the minimum width is normally used to set the minimum size constraint * on the toplevel. * * After the toplevel window has initially requested its size in both * dimensions it can go on to allocate itself a reasonable size (or a size * previously specified with [method@Gtk.Window.set_default_size]). During the * recursive allocation process it’s important to note that request cycles * will be recursively executed while widgets allocate their children. * Each widget, once allocated a size, will go on to first share the * space in one orientation among its children and then request each child's * height for its target allocated width or its width for allocated height, * depending. In this way a `GtkWidget` will typically be requested its size * a number of times before actually being allocated a size. The size a * widget is finally allocated can of course differ from the size it has * requested. For this reason, `GtkWidget` caches a small number of results * to avoid re-querying for the same sizes in one allocation cycle. * * If a widget does move content around to intelligently use up the * allocated size then it must support the request in both * `GtkSizeRequestMode`s even if the widget in question only * trades sizes in a single orientation. * * For instance, a [class@Gtk.Label] that does height-for-width word wrapping * will not expect to have [vfunc@Gtk.Widget.measure] with an orientation of * %GTK_ORIENTATION_VERTICAL called because that call is specific to a * width-for-height request. In this case the label must return the height * required for its own minimum possible width. By following this rule any * widget that handles height-for-width or width-for-height requests will * always be allocated at least enough space to fit its own content. * * Here are some examples of how a %GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH widget * generally deals with width-for-height requests: * * ```c * static void * foo_widget_measure (GtkWidget *widget, * GtkOrientation orientation, * int for_size, * int *minimum_size, * int *natural_size, * int *minimum_baseline, * int *natural_baseline) * { * if (orientation == GTK_ORIENTATION_HORIZONTAL) * { * // Calculate minimum and natural width * } * else // VERTICAL * { * if (i_am_in_height_for_width_mode) * { * int min_width, dummy; * * // First, get the minimum width of our widget * GTK_WIDGET_GET_CLASS (widget)->measure (widget, GTK_ORIENTATION_HORIZONTAL, -1, * &min_width, &dummy, &dummy, &dummy); * * // Now use the minimum width to retrieve the minimum and natural height to display * // that width. * GTK_WIDGET_GET_CLASS (widget)->measure (widget, GTK_ORIENTATION_VERTICAL, min_width, * minimum_size, natural_size, &dummy, &dummy); * } * else * { * // ... some widgets do both. * } * } * } * ``` * * Often a widget needs to get its own request during size request or * allocation. For example, when computing height it may need to also * compute width. Or when deciding how to use an allocation, the widget * may need to know its natural size. In these cases, the widget should * be careful to call its virtual methods directly, like in the code * example above. * * It will not work to use the wrapper function [method@Gtk.Widget.measure] * inside your own [vfunc@Gtk.Widget.size_allocate] implementation. * These return a request adjusted by [class@Gtk.SizeGroup], the widget's * align and expand flags, as well as its CSS style. * * If a widget used the wrappers inside its virtual method implementations, * then the adjustments (such as widget margins) would be applied * twice. GTK therefore does not allow this and will warn if you try * to do it. * * Of course if you are getting the size request for another widget, such * as a child widget, you must use [id@gtk_widget_measure]; otherwise, you * would not properly consider widget margins, [class@Gtk.SizeGroup], and * so forth. * * GTK also supports baseline vertical alignment of widgets. This * means that widgets are positioned such that the typographical baseline of * widgets in the same row are aligned. This happens if a widget supports * baselines, has a vertical alignment of %GTK_ALIGN_BASELINE, and is inside * a widget that supports baselines and has a natural “row” that it aligns to * the baseline, or a baseline assigned to it by the grandparent. * * Baseline alignment support for a widget is also done by the * [vfunc@Gtk.Widget.measure] virtual function. It allows you to report * both a minimum and natural size. * * If a widget ends up baseline aligned it will be allocated all the space in * the parent as if it was %GTK_ALIGN_FILL, but the selected baseline can be * found via [id@gtk_widget_get_allocated_baseline]. If the baseline has a * value other than -1 you need to align the widget such that the baseline * appears at the position. * * ### GtkWidget as GtkBuildable * * The `GtkWidget` implementation of the `GtkBuildable` interface * supports various custom elements to specify additional aspects of widgets * that are not directly expressed as properties. * * If the widget uses a [class@Gtk.LayoutManager], `GtkWidget` supports * a custom `` element, used to define layout properties: * * ```xml * * * * Description * * 0 * 0 * 1 * 1 * * * * * * * 1 * 0 * 1 * 1 * * * * * ``` * * `GtkWidget` allows style information such as style classes to * be associated with widgets, using the custom ` * * ``` * * `GtkWidget` allows defining accessibility information, such as properties, * relations, and states, using the custom `` element: * * ```xml * * * Download * label1 * * * ``` * * ### Building composite widgets from template XML * * `GtkWidget `exposes some facilities to automate the procedure * of creating composite widgets using "templates". * * To create composite widgets with `GtkBuilder` XML, one must associate * the interface description with the widget class at class initialization * time using [method@Gtk.WidgetClass.set_template]. * * The interface description semantics expected in composite template descriptions * is slightly different from regular [class@Gtk.Builder] XML. * * Unlike regular interface descriptions, [method@Gtk.WidgetClass.set_template] will * expect a `