/* 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 "gtkaccelmapprivate.h" #include "gtkaccelgroupprivate.h" #include "gtkaccessible.h" #include "gtkapplicationprivate.h" #include "gtkbindings.h" #include "gtkbuildable.h" #include "gtkbuilderprivate.h" #include "gtkcontainerprivate.h" #include "gtkcssboxesprivate.h" #include "gtkcssfiltervalueprivate.h" #include "gtkcsstransformvalueprivate.h" #include "gtkcssfontvariationsvalueprivate.h" #include "gtkcssnumbervalueprivate.h" #include "gtkcssshadowsvalueprivate.h" #include "gtkcssstylepropertyprivate.h" #include "gtkcsswidgetnodeprivate.h" #include "gtkdebug.h" #include "gtkgesturedrag.h" #include "gtkgestureprivate.h" #include "gtkgesturesingle.h" #include "gtkgestureswipe.h" #include "gtkintl.h" #include "gtklayoutmanagerprivate.h" #include "gtkmain.h" #include "gtkmarshalers.h" #include "gtkmenu.h" #include "gtkpopover.h" #include "gtkprivate.h" #include "gtkrenderbackgroundprivate.h" #include "gtkrenderborderprivate.h" #include "gtkrootprivate.h" #include "gtknativeprivate.h" #include "gtkscrollable.h" #include "gtkselection.h" #include "gtksettingsprivate.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 "gtkwidgetpathprivate.h" #include "gtkwindowgroup.h" #include "gtkwindowprivate.h" #include "gtknativeprivate.h" #include "a11y/gtkwidgetaccessible.h" #include "inspector/window.h" #include "gdk/gdkeventsprivate.h" #include "gsk/gskdebugprivate.h" #include "gsk/gskrendererprivate.h" #include #include #include #include #include #include #include /* for the use of round() */ #include "fallback-c89.c" /** * SECTION:gtkwidget * @Short_description: Base class for all widgets * @Title: GtkWidget * * GtkWidget is the base class all widgets in GTK+ derive from. It manages the * widget lifecycle, states and style. * * # Height-for-width Geometry Management # {#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: * * - #GtkWidgetClass.get_request_mode() * - #GtkWidgetClass.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 #GtkWidgetClass.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 #GtkWidgetClass.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 #GtkSizeRequestMode 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 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 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 * (unless gtk_window_set_geometry_hints() is explicitly used instead). * * 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 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 * #GtkSizeRequestModes even if the widget in question only * trades sizes in a single orientation. * * For instance, a #GtkLabel that does height-for-width word wrapping * will not expect to have #GtkWidgetClass.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: * * |[ * 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 gtk_widget_measure() * inside your own #GtkWidgetClass.size-allocate() implementation. * These return a request adjusted by #GtkSizeGroup, 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 gtk_widget_measure(). * Otherwise, you would not properly consider widget margins, * #GtkSizeGroup, 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 #GtkWidgetClass.measure() * virtual function. It allows you to report a both a minimum and natural * * If a widget ends up baseline aligned it will be allocated all the space in the parent * as if it was %GTK_ALIGN_FILL, but the selected baseline can be found via gtk_widget_get_allocated_baseline(). * If this has a value other than -1 you need to align the widget such that the baseline * appears at the position. * * # GtkWidget as GtkBuildable * * The GtkWidget implementation of the GtkBuildable interface supports a * custom element, which has attributes named ”key”, ”modifiers” * and ”signal” and allows to specify accelerators. * * An example of a UI definition fragment specifying an accelerator: * |[ * * * * ]| * * In addition to accelerators, GtkWidget also support a custom * element, which supports actions and relations. Properties on the accessible * implementation of an object can be set by accessing the internal child * “accessible” of a #GtkWidget. * * An example of a UI definition fragment specifying an accessible: * |[ * * I am a Label for a Button * * * * Click the button. * * * * * Clickable Button * * * * ]| * * If the parent widget uses a #GtkLayoutManager, #GtkWidget supports a * custom element, used to define layout properties: * * |[ * * * * Description * * 0 * 0 * 1 * 1 * * * * * * * 1 * 0 * 1 * 1 * * * * * ]| * * Finally, GtkWidget allows style information such as style classes to * be associated with widgets, using the custom * * ]| * * # Building composite widgets from template XML ## {#composite-templates} * * GtkWidget exposes some facilities to automate the procedure * of creating composite widgets using #GtkBuilder interface description * language. * * To create composite widgets with #GtkBuilder XML, one must associate * the interface description with the widget class at class initialization * time using gtk_widget_class_set_template(). * * The interface description semantics expected in composite template descriptions * is slightly different from regular #GtkBuilder XML. * * Unlike regular interface descriptions, gtk_widget_class_set_template() will * expect a