/* 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 #include #include #include #include #include #include #include "gtkcontainer.h" #include "gtkaccelmapprivate.h" #include "gtkaccelgroupprivate.h" #include "gtkclipboard.h" #include "gtkcssstylepropertyprivate.h" #include "gtkcssnumbervalueprivate.h" #include "gtkintl.h" #include "gtkmarshalers.h" #include "gtkselectionprivate.h" #include "gtksettingsprivate.h" #include "gtksizegroup-private.h" #include "gtksizerequestcacheprivate.h" #include "gtkwidget.h" #include "gtkwidgetprivate.h" #include "gtkwindowprivate.h" #include "gtkcontainerprivate.h" #include "gtkbindings.h" #include "gtkprivate.h" #include "gtkaccessible.h" #include "gtktooltip.h" #include "gtkinvisible.h" #include "gtkbuildable.h" #include "gtkbuilderprivate.h" #include "gtksizerequest.h" #include "gtkstylecontextprivate.h" #include "gtkcssprovider.h" #include "gtkmodifierstyle.h" #include "gtkversion.h" #include "gtkdebug.h" #include "gtkplug.h" #include "gtktypebuiltins.h" #include "a11y/gtkwidgetaccessible.h" #include "gtkapplicationprivate.h" /* 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 five virtual methods: * * - #GtkWidgetClass.get_request_mode() * - #GtkWidgetClass.get_preferred_width() * - #GtkWidgetClass.get_preferred_height() * - #GtkWidgetClass.get_preferred_height_for_width() * - #GtkWidgetClass.get_preferred_width_for_height() * - #GtkWidgetClass.get_preferred_height_and_baseline_for_width() * * There are some important things to keep in mind when implementing * height-for-width and when using it in container implementations. * * The geometry management system will query a widget hierarchy in * 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_get_preferred_width(). * Because the preferred widths for each container 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_get_preferred_height_for_width(), which will also be a highly * recursive operation. The minimum height for the minimum width is normally * used to set the minimum size constraint on the toplevel * (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 container widgets allocate their children. * Each container 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. * * See * [GtkContainer’s geometry management section][container-geometry-management] * to learn more about how height-for-width allocations are performed * by container widgets. * * 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.get_preferred_height() 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, for #GtkWidgetClass.get_preferred_height() * it will do: * * |[ * static void * foo_widget_get_preferred_height (GtkWidget *widget, * gint *min_height, * gint *nat_height) * { * if (i_am_in_height_for_width_mode) * { * gint min_width, nat_width; * * GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, * &min_width, * &nat_width); * GTK_WIDGET_GET_CLASS (widget)->get_preferred_height_for_width * (widget, * min_width, * min_height, * nat_height); * } * else * { * ... some widgets do both. For instance, if a GtkLabel is * rotated to 90 degrees it will return the minimum and * natural height for the rotated label here. * } * } * ]| * * And in #GtkWidgetClass.get_preferred_width_for_height() it will simply return * the minimum and natural width: * |[ * static void * foo_widget_get_preferred_width_for_height (GtkWidget *widget, * gint for_height, * gint *min_width, * gint *nat_width) * { * if (i_am_in_height_for_width_mode) * { * GTK_WIDGET_GET_CLASS (widget)->get_preferred_width (widget, * min_width, * nat_width); * } * else * { * ... again if a widget is sometimes operating in * width-for-height mode (like a rotated GtkLabel) it can go * ahead and do its real width for height calculation here. * } * } * ]| * * 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 this: * * |[ * GTK_WIDGET_GET_CLASS(widget)->get_preferred_width (widget, * &min, * &natural); * ]| * * It will not work to use the wrapper functions, such as * gtk_widget_get_preferred_width() inside your own size request * implementation. These return a request adjusted by #GtkSizeGroup * and by the #GtkWidgetClass.adjust_size_request() virtual method. 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 of a * container, you must use the wrapper APIs. * Otherwise, you would not properly consider widget margins, * #GtkSizeGroup, and so forth. * * Since 3.10 Gtk+ also supports baseline vertical alignment of widgets. This * means that widgets are positioned such that the typographical baseline of * widgets in the same row are aligned. This happens if a widget supports baselines, * has a vertical alignment of %GTK_ALIGN_BASELINE, and is inside a container * 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 done by the #GtkWidgetClass.get_preferred_height_and_baseline_for_width() * virtual function. It allows you to report a baseline in combination with the * minimum and natural height. If there is no baseline you can return -1 to indicate * this. The default implementation of this virtual function calls into the * #GtkWidgetClass.get_preferred_height() and #GtkWidgetClass.get_preferred_height_for_width(), * so if baselines are not supported it doesn’t need to be implemented. * * 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. * * # Style Properties * * #GtkWidget introduces “style * properties” - these are basically object properties that are stored * not on the object, but in the style object associated to the widget. Style * properties are set in [resource files][gtk3-Resource-Files]. * This mechanism is used for configuring such things as the location of the * scrollbar arrows through the theme, giving theme authors more control over the * look of applications without the need to write a theme engine in C. * * Use gtk_widget_class_install_style_property() to install style properties for * a widget class, gtk_widget_class_find_style_property() or * gtk_widget_class_list_style_properties() to get information about existing * style properties and gtk_widget_style_get_property(), gtk_widget_style_get() or * gtk_widget_style_get_valist() to obtain the value of a style property. * * # 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 * * * * ]| * * Finally, GtkWidget allows style information such as style classes to * be associated with widgets, using the custom * * ]| * * # Building composite widgets from template XML * * GtkWidget exposes some facilities to automate the proceedure * 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 regulare #GtkBuilder XML. * * Unlike regular interface descriptions, gtk_widget_class_set_template() will * expect a