* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
-#undef GDK_DISABLE_DEPRECATED /* gdk_input_set_extension_events() */
-
#include "config.h"
+
#include <stdarg.h>
#include <string.h>
#include <locale.h>
+
+#include <gobject/gvaluecollector.h>
+#include <gobject/gobjectnotifyqueue.c>
+#include <cairo-gobject.h>
+
#include "gtkcontainer.h"
#include "gtkaccelmap.h"
#include "gtkclipboard.h"
#include "gtkiconfactory.h"
#include "gtkintl.h"
-#include "gtkmain.h"
+#include "gtkmainprivate.h"
#include "gtkmarshalers.h"
#include "gtkrc.h"
-#include "gtkselection.h"
-#include "gtksettings.h"
+#include "gtkselectionprivate.h"
+#include "gtksettingsprivate.h"
#include "gtksizegroup-private.h"
#include "gtkwidget.h"
#include "gtkwidgetprivate.h"
-#include "gtkwindow.h"
+#include "gtkwindowprivate.h"
#include "gtkbindings.h"
#include "gtkprivate.h"
-#include "gdk/gdk.h"
-#include "gdk/gdkprivate.h" /* Used in gtk_reset_shapes_recurse to avoid copy */
-#include <gobject/gvaluecollector.h>
-#include <gobject/gobjectnotifyqueue.c>
-#include <cairo-gobject.h>
-#include "gdk/gdkkeysyms.h"
#include "gtkaccessible.h"
#include "gtktooltip.h"
#include "gtkinvisible.h"
#include "gtkbuildable.h"
#include "gtkbuilderprivate.h"
#include "gtksizerequest.h"
-#include "gtkstylecontext.h"
+#include "gtkstylecontextprivate.h"
+#include "gtksymboliccolor.h"
#include "gtkcssprovider.h"
+#include "gtkanimationdescription.h"
+#include "gtkmodifierstyle.h"
#include "gtkversion.h"
#include "gtkdebug.h"
+#include "gtktypebuiltins.h"
/**
* 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_width_get_preferred_width().
+ * 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
* 5 widget states (defined in "gtkenums.h")
* so 3 bits.
*/
- guint state : 3;
-
- /* The saved state of the widget. When a widget's state
- * is changed to GTK_STATE_INSENSITIVE via
- * "gtk_widget_set_state" or "gtk_widget_set_sensitive"
- * the old state is kept around in this field. The state
- * will be restored once the widget gets sensitive again.
- */
- guint saved_state : 3;
+ guint state_flags : 6;
guint direction : 2;
guint has_grab : 1;
guint shadowed : 1;
guint rc_style : 1;
- guint user_style : 1;
+ guint style_update_pending : 1;
guint app_paintable : 1;
guint double_buffered : 1;
guint redraw_on_alloc : 1;
* the font to use for text.
*/
GtkStyle *style;
+ GtkStyleContext *context;
/* The widget's allocated size.
*/
/* The widget's parent.
*/
GtkWidget *parent;
+
+#ifdef G_ENABLE_DEBUG
+ /* Number of gtk_widget_push_verify_invariants () */
+ guint verifying_invariants_count;
+#endif /* G_ENABLE_DEBUG */
+
+ /* Widget's path for styling */
+ GtkWidgetPath *path;
};
enum {
REALIZE,
UNREALIZE,
SIZE_ALLOCATE,
+ STATE_FLAGS_CHANGED,
STATE_CHANGED,
PARENT_SET,
HIERARCHY_CHANGED,
COMPOSITED_CHANGED,
QUERY_TOOLTIP,
DRAG_FAILED,
+ STYLE_UPDATED,
LAST_SIGNAL
};
PROP_COMPOSITE_CHILD,
PROP_STYLE,
PROP_EVENTS,
- PROP_EXTENSION_EVENTS,
PROP_NO_SHOW_ALL,
PROP_HAS_TOOLTIP,
PROP_TOOLTIP_MARKUP,
typedef struct _GtkStateData GtkStateData;
+enum {
+ STATE_CHANGE_REPLACE,
+ STATE_CHANGE_SET,
+ STATE_CHANGE_UNSET
+};
+
struct _GtkStateData
{
- GtkStateType state;
- guint state_restoration : 1;
+ guint flags : 6;
+ guint operation : 2;
guint parent_sensitive : 1;
guint use_forall : 1;
};
gint y,
gboolean keyboard_tip,
GtkTooltip *tooltip);
+static void gtk_widget_real_style_updated (GtkWidget *widget);
static gboolean gtk_widget_real_show_help (GtkWidget *widget,
GtkWidgetHelpType help_type);
GtkDirectionType direction);
static gboolean gtk_widget_real_keynav_failed (GtkWidget *widget,
GtkDirectionType direction);
+#ifdef G_ENABLE_DEBUG
+static void gtk_widget_verify_invariants (GtkWidget *widget);
+static void gtk_widget_push_verify_invariants (GtkWidget *widget);
+static void gtk_widget_pop_verify_invariants (GtkWidget *widget);
+#else
+#define gtk_widget_verify_invariants(widget)
+#define gtk_widget_push_verify_invariants(widget)
+#define gtk_widget_pop_verify_invariants(widget)
+#endif
static PangoContext* gtk_widget_peek_pango_context (GtkWidget *widget);
static void gtk_widget_update_pango_context (GtkWidget *widget);
static void gtk_widget_propagate_state (GtkWidget *widget,
GtkStateData *data);
-static void gtk_widget_reset_rc_style (GtkWidget *widget);
-static void gtk_widget_set_style_internal (GtkWidget *widget,
- GtkStyle *style,
- gboolean initial_emission);
+;
static gint gtk_widget_event_internal (GtkWidget *widget,
GdkEvent *event);
static gboolean gtk_widget_real_mnemonic_activate (GtkWidget *widget,
gint *natural_size);
static void gtk_widget_real_adjust_size_allocation (GtkWidget *widget,
GtkOrientation orientation,
+ gint *minimum_size,
gint *natural_size,
gint *allocated_pos,
gint *allocated_size);
static void gtk_widget_add_events_internal (GtkWidget *widget,
GdkDevice *device,
gint events);
+static void gtk_widget_set_device_enabled_internal (GtkWidget *widget,
+ GdkDevice *device,
+ gboolean recurse,
+ gboolean enabled);
/* --- variables --- */
static gpointer gtk_widget_parent_class = NULL;
static GQuark quark_accel_closures = 0;
static GQuark quark_event_mask = 0;
static GQuark quark_device_event_mask = 0;
-static GQuark quark_extension_event_mode = 0;
static GQuark quark_parent_window = 0;
static GQuark quark_pointer_window = 0;
static GQuark quark_shape_info = 0;
static GQuark quark_has_tooltip = 0;
static GQuark quark_tooltip_window = 0;
static GQuark quark_visual = 0;
-static GQuark quark_style_context = 0;
+static GQuark quark_modifier_style = 0;
+static GQuark quark_enabled_devices = 0;
GParamSpecPool *_gtk_widget_child_property_pool = NULL;
GObjectNotifyContext *_gtk_widget_child_property_notify_context = NULL;
quark_accel_closures = g_quark_from_static_string ("gtk-accel-closures");
quark_event_mask = g_quark_from_static_string ("gtk-event-mask");
quark_device_event_mask = g_quark_from_static_string ("gtk-device-event-mask");
- quark_extension_event_mode = g_quark_from_static_string ("gtk-extension-event-mode");
quark_parent_window = g_quark_from_static_string ("gtk-parent-window");
quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
quark_shape_info = g_quark_from_static_string ("gtk-shape-info");
quark_has_tooltip = g_quark_from_static_string ("gtk-has-tooltip");
quark_tooltip_window = g_quark_from_static_string ("gtk-tooltip-window");
quark_visual = g_quark_from_static_string ("gtk-widget-visual");
- quark_style_context = g_quark_from_static_string ("gtk-style-context");
+ quark_modifier_style = g_quark_from_static_string ("gtk-widget-modifier-style");
+ quark_enabled_devices = g_quark_from_static_string ("gtk-widget-enabled-devices");
style_property_spec_pool = g_param_spec_pool_new (FALSE);
_gtk_widget_child_property_pool = g_param_spec_pool_new (TRUE);
klass->can_activate_accel = gtk_widget_real_can_activate_accel;
klass->grab_broken_event = NULL;
klass->query_tooltip = gtk_widget_real_query_tooltip;
+ klass->style_updated = gtk_widget_real_style_updated;
klass->show_help = gtk_widget_real_show_help;
GDK_TYPE_EVENT_MASK,
GDK_STRUCTURE_MASK,
GTK_PARAM_READWRITE));
- g_object_class_install_property (gobject_class,
- PROP_EXTENSION_EVENTS,
- g_param_spec_enum ("extension-events",
- P_("Extension events"),
- P_("The mask that decides what kind of extension events this widget gets"),
- GDK_TYPE_EXTENSION_MODE,
- GDK_EXTENSION_EVENTS_NONE,
- GTK_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_NO_SHOW_ALL,
g_param_spec_boolean ("no-show-all",
*
* The ::state-changed signal is emitted when the widget state changes.
* See gtk_widget_get_state().
+ *
+ * Deprecated: 3.0. Use #GtkWidget::state-flags-changed instead.
*/
widget_signals[STATE_CHANGED] =
g_signal_new (I_("state-changed"),
G_TYPE_NONE, 1,
GTK_TYPE_STATE_TYPE);
+ /**
+ * GtkWidget::state-flags-changed:
+ * @widget: the object which received the signal.
+ * @flags: The previous state flags.
+ *
+ * The ::state-flags-changed signal is emitted when the widget state
+ * changes, see gtk_widget_get_state_flags().
+ *
+ * Since: 3.0
+ */
+ widget_signals[STATE_FLAGS_CHANGED] =
+ g_signal_new (I_("state-flags-changed"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkWidgetClass, state_flags_changed),
+ NULL, NULL,
+ _gtk_marshal_VOID__FLAGS,
+ G_TYPE_NONE, 1,
+ GTK_TYPE_STATE_FLAGS);
+
/**
* GtkWidget::parent-set:
* @widget: the object on which the signal is emitted
* The ::style-set signal is emitted when a new style has been set
* on a widget. Note that style-modifying functions like
* gtk_widget_modify_base() also cause this signal to be emitted.
+ *
+ * Note that this signal is emitted for changes to the deprecated
+ * #GtkStyle. To track changes to the #GtkStyleContext associated
+ * with a widget, use the #GtkWidget::style-updated signal.
+ *
+ * Deprecated:3.0: Use the #GtkWidget::style-updated signal
*/
widget_signals[STYLE_SET] =
g_signal_new (I_("style-set"),
G_TYPE_NONE, 1,
GTK_TYPE_STYLE);
+ /**
+ * GtkWidget::style-updated:
+ * @widget: the object on which the signal is emitted
+ *
+ * The ::style-updated signal is emitted when the #GtkStyleContext
+ * of a widget is changed. Note that style-modifying functions like
+ * gtk_widget_override_color() also cause this signal to be emitted.
+ *
+ * Since: 3.0
+ */
+ widget_signals[STYLE_UPDATED] =
+ g_signal_new (I_("style-updated"),
+ G_TYPE_FROM_CLASS (gobject_class),
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (GtkWidgetClass, style_updated),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
/**
* GtkWidget::direction-changed:
* @widget: the object on which the signal is emitted
* @widget: the object which received the signal
* @event: (type Gdk.EventAny): the #GdkEventAny which triggered this signal
*
- * The ::unmap-event signal may be emitted when the @widget's window is
+ * The ::unmap-event signal will be emitted when the @widget's window is
* unmapped. A window is unmapped when it becomes invisible on the screen.
*
- * For performance reasons GTK+ may not emit ::unmap-event, so one
- * should always also implement ::unrealize in order to release
- * resources and disconnect signal handlers.
- *
* To receive this signal, the #GdkWindow associated to the widget needs
* to enable the #GDK_STRUCTURE_MASK mask. GDK will enable this mask
* automatically for all new windows.
g_signal_new (I_("drag-failed"),
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
- 0, _gtk_boolean_handled_accumulator, NULL,
+ G_STRUCT_OFFSET (GtkWidgetClass, drag_failed),
+ _gtk_boolean_handled_accumulator, NULL,
_gtk_marshal_BOOLEAN__OBJECT_ENUM,
G_TYPE_BOOLEAN, 2,
GDK_TYPE_DRAG_CONTEXT,
if (!gtk_widget_get_realized (widget) && gtk_widget_get_has_window (widget))
gtk_widget_set_events (widget, g_value_get_flags (value));
break;
- case PROP_EXTENSION_EVENTS:
- gtk_widget_set_extension_events (widget, g_value_get_enum (value));
- break;
case PROP_NO_SHOW_ALL:
gtk_widget_set_no_show_all (widget, g_value_get_boolean (value));
break;
switch (prop_id)
{
gpointer *eventp;
- gpointer *modep;
case PROP_NAME:
if (priv->name)
eventp = g_object_get_qdata (G_OBJECT (widget), quark_event_mask);
g_value_set_flags (value, GPOINTER_TO_INT (eventp));
break;
- case PROP_EXTENSION_EVENTS:
- modep = g_object_get_qdata (G_OBJECT (widget), quark_extension_event_mode);
- g_value_set_enum (value, GPOINTER_TO_INT (modep));
- break;
case PROP_NO_SHOW_ALL:
g_value_set_boolean (value, gtk_widget_get_no_show_all (widget));
break;
priv = widget->priv;
priv->child_visible = TRUE;
- priv->state = GTK_STATE_NORMAL;
- priv->saved_state = GTK_STATE_NORMAL;
priv->name = NULL;
priv->allocation.x = -1;
priv->allocation.y = -1;
if (priv->parent == NULL)
return;
- /* keep this function in sync with gtk_menu_detach()
- */
+ /* keep this function in sync with gtk_menu_detach() */
+
+ gtk_widget_push_verify_invariants (widget);
g_object_freeze_notify (G_OBJECT (widget));
nqueue = g_object_notify_queue_freeze (G_OBJECT (widget), _gtk_widget_child_property_notify_context);
if (gtk_container_get_focus_child (GTK_CONTAINER (priv->parent)) == widget)
gtk_container_set_focus_child (GTK_CONTAINER (priv->parent), NULL);
- /* If we are unanchoring the child, we save around the toplevel
- * to emit hierarchy changed
- */
- if (priv->parent->priv->anchored)
- g_object_ref (toplevel);
- else
- toplevel = NULL;
-
gtk_widget_queue_draw_child (widget);
/* Reset the width and height here, to force reallocation if we
gtk_widget_unrealize (widget);
}
+ /* If we are unanchoring the child, we save around the toplevel
+ * to emit hierarchy changed
+ */
+ if (priv->parent->priv->anchored)
+ g_object_ref (toplevel);
+ else
+ toplevel = NULL;
+
/* Removing a widget from a container restores the child visible
* flag to the default state, so it doesn't affect the child
* in the next parent.
old_parent = priv->parent;
priv->parent = NULL;
- gtk_widget_set_parent_window (widget, NULL);
/* parent may no longer expand if the removed
* child was expand=TRUE and could therefore
g_object_unref (toplevel);
}
+ /* Now that the parent pointer is nullified and the hierarchy-changed
+ * already passed, go ahead and unset the parent window, if we are unparenting
+ * an embeded GtkWindow the window will become toplevel again and hierarchy-changed
+ * will fire again for the new subhierarchy.
+ */
+ gtk_widget_set_parent_window (widget, NULL);
+
g_object_notify (G_OBJECT (widget), "parent");
g_object_thaw_notify (G_OBJECT (widget));
if (!priv->parent)
g_object_notify_queue_clear (G_OBJECT (widget), nqueue);
g_object_notify_queue_thaw (G_OBJECT (widget), nqueue);
+
+ gtk_widget_pop_verify_invariants (widget);
g_object_unref (widget);
}
if (!gtk_widget_get_visible (widget))
{
g_object_ref (widget);
+ gtk_widget_push_verify_invariants (widget);
+
if (!gtk_widget_is_toplevel (widget))
- gtk_widget_queue_resize (widget);
+ gtk_widget_queue_resize (widget);
/* see comment in set_parent() for why this should and can be
* conditional
g_signal_emit (widget, widget_signals[SHOW], 0);
g_object_notify (G_OBJECT (widget), "visible");
+
+ gtk_widget_pop_verify_invariants (widget);
g_object_unref (widget);
}
}
GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
g_object_ref (widget);
+ gtk_widget_push_verify_invariants (widget);
+
if (toplevel != widget && gtk_widget_is_toplevel (toplevel))
- _gtk_window_unset_focus_and_default (GTK_WINDOW (toplevel), widget);
+ _gtk_window_unset_focus_and_default (GTK_WINDOW (toplevel), widget);
/* a parent may now be expand=FALSE since we're hidden. */
if (widget->priv->need_compute_expand ||
if (!gtk_widget_is_toplevel (widget))
gtk_widget_queue_resize (widget);
g_object_notify (G_OBJECT (widget), "visible");
+
+ gtk_widget_pop_verify_invariants (widget);
g_object_unref (widget);
}
}
class->show_all (widget);
}
+static void
+_gtk_widget_notify_state_change (GtkWidget *widget,
+ GtkStateFlags flag,
+ gboolean target)
+{
+ GtkStateType state;
+
+ switch (flag)
+ {
+ case GTK_STATE_FLAG_ACTIVE:
+ state = GTK_STATE_ACTIVE;
+ break;
+ case GTK_STATE_FLAG_PRELIGHT:
+ state = GTK_STATE_PRELIGHT;
+ break;
+ case GTK_STATE_FLAG_SELECTED:
+ state = GTK_STATE_SELECTED;
+ break;
+ case GTK_STATE_FLAG_INSENSITIVE:
+ state = GTK_STATE_INSENSITIVE;
+ break;
+ case GTK_STATE_FLAG_INCONSISTENT:
+ state = GTK_STATE_INCONSISTENT;
+ break;
+ case GTK_STATE_FLAG_FOCUSED:
+ state = GTK_STATE_FOCUSED;
+ break;
+ default:
+ return;
+ }
+
+ gtk_style_context_notify_state_change (widget->priv->context,
+ gtk_widget_get_window (widget),
+ NULL, state, target);
+}
+
+/* Initializes state transitions for those states that
+ * were enabled before mapping and have a looping animation.
+ */
+static void
+_gtk_widget_start_state_transitions (GtkWidget *widget)
+{
+ GtkStateFlags state, flag;
+
+ if (!widget->priv->context)
+ return;
+
+ state = gtk_widget_get_state_flags (widget);
+ flag = GTK_STATE_FLAG_FOCUSED;
+
+ while (flag)
+ {
+ GtkAnimationDescription *animation_desc;
+
+ if ((state & flag) == 0)
+ {
+ flag >>= 1;
+ continue;
+ }
+
+ gtk_style_context_get (widget->priv->context, state,
+ "transition", &animation_desc,
+ NULL);
+
+ if (animation_desc)
+ {
+ if (_gtk_animation_description_get_loop (animation_desc))
+ _gtk_widget_notify_state_change (widget, flag, TRUE);
+
+ _gtk_animation_description_unref (animation_desc);
+ }
+
+ flag >>= 1;
+ }
+}
+
/**
* gtk_widget_map:
* @widget: a #GtkWidget
if (!gtk_widget_get_mapped (widget))
{
+ gtk_widget_push_verify_invariants (widget);
+
if (!gtk_widget_get_realized (widget))
- gtk_widget_realize (widget);
+ gtk_widget_realize (widget);
g_signal_emit (widget, widget_signals[MAP], 0);
if (!gtk_widget_get_has_window (widget))
- gdk_window_invalidate_rect (priv->window, &priv->allocation, FALSE);
+ gdk_window_invalidate_rect (priv->window, &priv->allocation, FALSE);
+
+ gtk_widget_pop_verify_invariants (widget);
+
+ _gtk_widget_start_state_transitions (widget);
}
}
if (gtk_widget_get_mapped (widget))
{
+ gtk_widget_push_verify_invariants (widget);
+
if (!gtk_widget_get_has_window (widget))
gdk_window_invalidate_rect (priv->window, &priv->allocation, FALSE);
_gtk_tooltip_hide (widget);
g_signal_emit (widget, widget_signals[UNMAP], 0);
- }
-}
-
-static void
-gtk_widget_set_extension_events_internal (GtkWidget *widget,
- GdkExtensionMode mode,
- GList *window_list)
-{
- GtkWidgetPrivate *priv = widget->priv;
- GList *free_list = NULL;
- GList *l;
- if (window_list == NULL)
- {
- if (gtk_widget_get_has_window (widget))
- window_list = g_list_prepend (NULL, priv->window);
- else
- window_list = gdk_window_get_children (priv->window);
-
- free_list = window_list;
- }
-
- for (l = window_list; l != NULL; l = l->next)
- {
- GdkWindow *window = l->data;
- gpointer user_data;
-
- gdk_window_get_user_data (window, &user_data);
- if (user_data == widget)
- {
- GList *children;
-
- gdk_input_set_extension_events (window,
- gdk_window_get_events (window),
- mode);
+ gtk_widget_pop_verify_invariants (widget);
- children = gdk_window_get_children (window);
- if (children)
- {
- gtk_widget_set_extension_events_internal (widget, mode, children);
- g_list_free (children);
- }
- }
+ if (priv->context)
+ gtk_style_context_cancel_animations (priv->context, NULL);
}
-
- if (free_list)
- g_list_free (free_list);
}
static void
}
}
+static GList *
+get_widget_windows (GtkWidget *widget)
+{
+ GList *window_list, *last, *l, *children, *ret;
+
+ if (gtk_widget_get_has_window (widget))
+ window_list = g_list_prepend (NULL, gtk_widget_get_window (widget));
+ else
+ window_list = gdk_window_peek_children (gtk_widget_get_window (widget));
+
+ last = g_list_last (window_list);
+ ret = NULL;
+
+ for (l = window_list; l; l = l->next)
+ {
+ GtkWidget *window_widget = NULL;
+
+ gdk_window_get_user_data (l->data, (gpointer *) &window_widget);
+
+ if (widget != window_widget)
+ continue;
+
+ ret = g_list_prepend (ret, l->data);
+ children = gdk_window_peek_children (GDK_WINDOW (l->data));
+
+ if (children)
+ {
+ last = g_list_concat (last, children);
+ last = g_list_last (last);
+ }
+ }
+
+ g_list_free (window_list);
+
+ return ret;
+}
+
+static void
+device_enable_foreach (GtkWidget *widget,
+ gpointer user_data)
+{
+ GdkDevice *device = user_data;
+ gtk_widget_set_device_enabled_internal (widget, device, TRUE, TRUE);
+}
+
+static void
+device_disable_foreach (GtkWidget *widget,
+ gpointer user_data)
+{
+ GdkDevice *device = user_data;
+ gtk_widget_set_device_enabled_internal (widget, device, TRUE, FALSE);
+}
+
+static void
+gtk_widget_set_device_enabled_internal (GtkWidget *widget,
+ GdkDevice *device,
+ gboolean recurse,
+ gboolean enabled)
+{
+ GList *window_list, *l;
+
+ window_list = get_widget_windows (widget);
+
+ for (l = window_list; l; l = l->next)
+ {
+ GdkEventMask events = 0;
+ GdkWindow *window;
+
+ window = l->data;
+
+ if (enabled)
+ events = gdk_window_get_events (window);
+
+ gdk_window_set_device_events (window, device, events);
+ }
+
+ if (recurse && GTK_IS_CONTAINER (widget))
+ {
+ if (enabled)
+ gtk_container_forall (GTK_CONTAINER (widget), device_enable_foreach, device);
+ else
+ gtk_container_forall (GTK_CONTAINER (widget), device_disable_foreach, device);
+ }
+
+ g_list_free (window_list);
+}
+
+static void
+gtk_widget_update_devices_mask (GtkWidget *widget,
+ gboolean recurse)
+{
+ GList *enabled_devices, *l;
+
+ enabled_devices = g_object_get_qdata (G_OBJECT (widget), quark_enabled_devices);
+
+ for (l = enabled_devices; l; l = l->next)
+ gtk_widget_set_device_enabled_internal (widget, GDK_DEVICE (l->data), recurse, TRUE);
+}
+
/**
* gtk_widget_realize:
* @widget: a #GtkWidget
gtk_widget_realize (GtkWidget *widget)
{
GtkWidgetPrivate *priv;
- GdkExtensionMode mode;
cairo_region_t *region;
- GtkStyleContext *context;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (widget->priv->anchored ||
if (!gtk_widget_get_realized (widget))
{
+ gtk_widget_push_verify_invariants (widget);
+
/*
if (GTK_IS_CONTAINER (widget) && gtk_widget_get_has_window (widget))
g_message ("gtk_widget_realize(%s)", G_OBJECT_TYPE_NAME (widget));
gtk_widget_ensure_style (widget);
+ if (priv->style_update_pending)
+ g_signal_emit (widget, widget_signals[STYLE_UPDATED], 0);
+
g_signal_emit (widget, widget_signals[REALIZE], 0);
gtk_widget_real_set_has_tooltip (widget,
if (region)
gdk_window_input_shape_combine_region (priv->window, region, 0, 0);
- mode = gtk_widget_get_extension_events (widget);
- if (mode != GDK_EXTENSION_EVENTS_NONE)
- gtk_widget_set_extension_events_internal (widget, mode, NULL);
-
if (priv->multidevice)
gdk_window_set_support_multidevice (priv->window, TRUE);
_gtk_widget_enable_device_events (widget);
+ gtk_widget_update_devices_mask (widget, TRUE);
+
+ gtk_widget_pop_verify_invariants (widget);
}
}
{
g_return_if_fail (GTK_IS_WIDGET (widget));
+ gtk_widget_push_verify_invariants (widget);
+
if (widget->priv->has_shape_mask)
gtk_widget_shape_combine_region (widget, NULL);
if (gtk_widget_get_realized (widget))
{
g_object_ref (widget);
- _gtk_tooltip_hide (widget);
+
+ if (widget->priv->mapped)
+ gtk_widget_unmap (widget);
+
g_signal_emit (widget, widget_signals[UNREALIZE], 0);
+ g_assert (!widget->priv->mapped);
gtk_widget_set_realized (widget, FALSE);
- gtk_widget_set_mapped (widget, FALSE);
+
g_object_unref (widget);
}
+
+ gtk_widget_pop_verify_invariants (widget);
}
/*****************************************
* Normally you would only use this function in widget
* implementations. You might also use it to schedule a redraw of a
* #GtkDrawingArea or some portion thereof.
+ *
+ * Since: 3.0
**/
void
gtk_widget_queue_draw_region (GtkWidget *widget,
/**
* gtk_widget_size_allocate:
* @widget: a #GtkWidget
- * @allocation: (inout): position and size to be allocated to @widget
+ * @allocation: position and size to be allocated to @widget
*
* This function is only used by #GtkContainer subclasses, to assign a size
* and position to their child widgets.
gboolean alloc_needed;
gboolean size_changed;
gboolean position_changed;
- gint natural_width, natural_height;
+ gint natural_width, natural_height, dummy;
gint min_width, min_height;
priv = widget->priv;
g_return_if_fail (GTK_IS_WIDGET (widget));
+ gtk_widget_push_verify_invariants (widget);
+
#ifdef G_ENABLE_DEBUG
if (gtk_get_debug_flags () & GTK_DEBUG_GEOMETRY)
{
* when aligning implicitly.
*/
gtk_widget_get_preferred_width (widget, &min_width, &natural_width);
- gtk_widget_get_preferred_height_for_width (widget, real_allocation.width, NULL, &natural_height);
+ gtk_widget_get_preferred_height_for_width (widget, real_allocation.width, &dummy, &natural_height);
}
else
{
* when aligning implicitly.
*/
gtk_widget_get_preferred_height (widget, &min_height, &natural_height);
- gtk_widget_get_preferred_width_for_height (widget, real_allocation.height, NULL, &natural_width);
+ gtk_widget_get_preferred_width_for_height (widget, real_allocation.height, &dummy, &natural_width);
}
/* Now that we have the right natural height and width, go ahead and remove any margins from the
* allocated sizes and possibly limit them to the natural sizes */
GTK_WIDGET_GET_CLASS (widget)->adjust_size_allocation (widget,
GTK_ORIENTATION_HORIZONTAL,
+ &dummy,
&natural_width,
&adjusted_allocation.x,
&adjusted_allocation.width);
GTK_WIDGET_GET_CLASS (widget)->adjust_size_allocation (widget,
GTK_ORIENTATION_VERTICAL,
+ &dummy,
&natural_height,
&adjusted_allocation.y,
&adjusted_allocation.height);
old_allocation.y != real_allocation.y);
if (!alloc_needed && !size_changed && !position_changed)
- return;
+ goto out;
g_signal_emit (widget, widget_signals[SIZE_ALLOCATE], 0, &real_allocation);
cairo_region_destroy (invalidate);
}
}
+
+ if (size_changed || position_changed)
+ {
+ GtkStyleContext *context;
+
+ context = gtk_widget_get_style_context (widget);
+ _gtk_style_context_invalidate_animation_areas (context);
+ }
}
if ((size_changed || position_changed) && priv->parent &&
gtk_widget_invalidate_widget_windows (priv->parent, invalidate);
cairo_region_destroy (invalidate);
}
+
+out:
+ gtk_widget_pop_verify_invariants (widget);
}
/**
static void
adjust_for_margin(gint start_margin,
gint end_margin,
+ gint *minimum_size,
gint *natural_size,
gint *allocated_pos,
gint *allocated_size)
{
+ *minimum_size -= (start_margin + end_margin);
*natural_size -= (start_margin + end_margin);
*allocated_pos += start_margin;
*allocated_size -= (start_margin + end_margin);
static void
gtk_widget_real_adjust_size_allocation (GtkWidget *widget,
GtkOrientation orientation,
+ gint *minimum_size,
gint *natural_size,
gint *allocated_pos,
gint *allocated_size)
{
adjust_for_margin (aux_info->margin.left,
aux_info->margin.right,
- natural_size, allocated_pos, allocated_size);
+ minimum_size, natural_size,
+ allocated_pos, allocated_size);
adjust_for_align (aux_info->halign,
natural_size, allocated_pos, allocated_size);
}
{
adjust_for_margin (aux_info->margin.top,
aux_info->margin.bottom,
- natural_size, allocated_pos, allocated_size);
+ minimum_size, natural_size,
+ allocated_pos, allocated_size);
adjust_for_align (aux_info->valign,
natural_size, allocated_pos, allocated_size);
}
* use "else if" statements to check which window should be drawn.
*
* Returns: %TRUE if @window should be drawn
+ *
+ * Since: 3.0
**/
gboolean
gtk_cairo_should_draw_window (cairo_t *cr,
cairo_t *cr,
gboolean clip_to_size)
{
+ GtkStyleContext *context;
+
if (!gtk_widget_is_drawable (widget))
return;
0, cr,
&result);
}
+
+ context = gtk_widget_get_style_context (widget);
+ _gtk_style_context_coalesce_animation_areas (context, widget);
}
/**
* <note><para>Special purpose widgets may contain special code for
* rendering to the screen and might appear differently on screen
* and when rendered using gtk_widget_draw().</para></note>
+ *
+ * Since: 3.0
**/
void
gtk_widget_draw (GtkWidget *widget,
}
/* Returns TRUE if a translation should be done */
-static gboolean
-gtk_widget_get_translation_to_window (GtkWidget *widget,
- GdkWindow *window,
- int *x,
- int *y)
+gboolean
+_gtk_widget_get_translation_to_window (GtkWidget *widget,
+ GdkWindow *window,
+ int *x,
+ int *y)
{
GdkWindow *w, *widget_window;
* preparing an expose event to be emitted with the #GtkWidget::draw
* signal. It is intended to help porting multiwindow widgets from
* GTK+ 2 to the rendering architecture of GTK+ 3.
+ *
+ * Since: 3.0
**/
void
gtk_cairo_transform_to_window (cairo_t *cr,
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GDK_IS_WINDOW (window));
- if (gtk_widget_get_translation_to_window (widget, window, &x, &y))
+ if (_gtk_widget_get_translation_to_window (widget, window, &x, &y))
cairo_translate (cr, x, y);
}
gdk_cairo_region (cr, event->expose.region);
cairo_clip (cr);
- do_clip = gtk_widget_get_translation_to_window (widget,
- event->expose.window,
- &x, &y);
+ do_clip = _gtk_widget_get_translation_to_window (widget,
+ event->expose.window,
+ &x, &y);
cairo_translate (cr, -x, -y);
_gtk_widget_draw_internal (widget, cr, do_clip);
return FALSE;
}
+static void
+gtk_widget_real_style_updated (GtkWidget *widget)
+{
+ if (gtk_widget_get_realized (widget))
+ {
+ /* Trigger ::style-set for old
+ * widgets not listening to this
+ */
+ g_signal_emit (widget,
+ widget_signals[STYLE_SET],
+ 0,
+ widget->priv->style);
+ }
+
+ if (widget->priv->context)
+ {
+ gtk_style_context_invalidate (widget->priv->context);
+
+ if (gtk_widget_get_realized (widget) &&
+ gtk_widget_get_has_window (widget))
+ gtk_style_context_set_background (widget->priv->context,
+ widget->priv->window);
+ }
+
+ if (widget->priv->anchored)
+ gtk_widget_queue_resize (widget);
+}
+
static gboolean
gtk_widget_real_show_help (GtkWidget *widget,
GtkWidgetHelpType help_type)
* @name: name for the widget
*
* Widgets can be named, which allows you to refer to them from a
- * gtkrc file. You can apply a style to widgets with a particular name
- * in the gtkrc file. See the documentation for gtkrc files (on the
- * same page as the docs for #GtkRcStyle).
+ * CSS file. You can apply a style to widgets with a particular name
+ * in the CSS file. See the documentation for the CSS syntax (on the
+ * same page as the docs for #GtkStyleContext).
*
- * Note that widget names are separated by periods in paths (see
- * gtk_widget_path()), so names with embedded periods may cause confusion.
+ * Note that the CSS syntax has certain special characters to delimit
+ * and represent elements in a selector (period, #, >, *...),
+ * so using these will make your widget impossible to match by name.
+ * Any combination of alphanumeric symbols, dashes and underscores will
+ * suffice.
**/
void
gtk_widget_set_name (GtkWidget *widget,
g_free (priv->name);
priv->name = new_name;
- if (priv->rc_style)
- gtk_widget_reset_rc_style (widget);
+ if (priv->path)
+ {
+ guint pos;
+
+ pos = gtk_widget_path_length (priv->path) - 1;
+ gtk_widget_path_iter_set_name (priv->path, pos,
+ priv->name);
+ }
+
+ if (priv->context)
+ gtk_style_context_set_path (priv->context, priv->path);
g_object_notify (G_OBJECT (widget), "name");
}
return G_OBJECT_TYPE_NAME (widget);
}
-/**
- * gtk_widget_set_state:
- * @widget: a #GtkWidget
- * @state: new state for @widget
- *
- * This function is for use in widget implementations. Sets the state
- * of a widget (insensitive, prelighted, etc.) Usually you should set
- * the state using wrapper functions such as gtk_widget_set_sensitive().
- **/
-void
-gtk_widget_set_state (GtkWidget *widget,
- GtkStateType state)
+static void
+_gtk_widget_update_state_flags (GtkWidget *widget,
+ GtkStateFlags flags,
+ guint operation)
{
GtkWidgetPrivate *priv;
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
priv = widget->priv;
- if (state == gtk_widget_get_state (widget))
- return;
+ /* Handle insensitive first, since it is propagated
+ * differently throughout the widget hierarchy.
+ */
+ if ((flags & GTK_STATE_FLAG_INSENSITIVE) !=
+ (priv->state_flags & GTK_STATE_FLAG_INSENSITIVE))
+ gtk_widget_set_sensitive (widget,
+ operation != STATE_CHANGE_UNSET);
- if (state == GTK_STATE_INSENSITIVE)
- gtk_widget_set_sensitive (widget, FALSE);
- else
+ if (operation != STATE_CHANGE_REPLACE)
+ flags &= ~(GTK_STATE_FLAG_INSENSITIVE);
+
+ if (flags != 0 ||
+ operation == STATE_CHANGE_REPLACE)
{
GtkStateData data;
- data.state = state;
- data.state_restoration = FALSE;
+ data.flags = flags;
+ data.operation = operation;
data.use_forall = FALSE;
+
if (priv->parent)
data.parent_sensitive = (gtk_widget_is_sensitive (priv->parent) != FALSE);
else
}
}
+/**
+ * gtk_widget_set_state_flags:
+ * @widget: a #GtkWidget
+ * @flags: State flags to turn on
+ * @clear: Whether to clear state before turning on @flags
+ *
+ * This function is for use in widget implementations. Turns on flag
+ * values in the current widget state (insensitive, prelighted, etc.).
+ *
+ * It is worth mentioning that any other state than %GTK_STATE_FLAG_INSENSITIVE,
+ * will be propagated down to all non-internal children if @widget is a
+ * #GtkContainer, while %GTK_STATE_FLAG_INSENSITIVE itself will be propagated
+ * down to all #GtkContainer children by different means than turning on the
+ * state flag down the hierarchy, both gtk_widget_get_state_flags() and
+ * gtk_widget_is_sensitive() will make use of these.
+ *
+ * Since: 3.0
+ **/
+void
+gtk_widget_set_state_flags (GtkWidget *widget,
+ GtkStateFlags flags,
+ gboolean clear)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if ((!clear && (widget->priv->state_flags & flags) == flags) ||
+ (clear && widget->priv->state_flags == flags))
+ return;
+
+ if (clear)
+ _gtk_widget_update_state_flags (widget, flags, STATE_CHANGE_REPLACE);
+ else
+ _gtk_widget_update_state_flags (widget, flags, STATE_CHANGE_SET);
+}
+
+/**
+ * gtk_widget_unset_state_flags:
+ * @widget: a #GtkWidget
+ * @flags: State flags to turn off
+ *
+ * This function is for use in widget implementations. Turns off flag
+ * values for the current widget state (insensitive, prelighted, etc.).
+ * See gtk_widget_set_state_flags().
+ *
+ * Since: 3.0
+ **/
+void
+gtk_widget_unset_state_flags (GtkWidget *widget,
+ GtkStateFlags flags)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ if ((widget->priv->state_flags & flags) == 0)
+ return;
+
+ _gtk_widget_update_state_flags (widget, flags, STATE_CHANGE_UNSET);
+}
+
+/**
+ * gtk_widget_get_state_flags:
+ * @widget: a #GtkWidget
+ *
+ * Returns the widget state as a flag set. It is worth mentioning
+ * that the effective %GTK_STATE_FLAG_INSENSITIVE state will be
+ * returned, that is, also based on parent insensitivity, even if
+ * @widget itself is sensitive.
+ *
+ * Returns: The state flags for widget
+ *
+ * Since: 3.0
+ **/
+GtkStateFlags
+gtk_widget_get_state_flags (GtkWidget *widget)
+{
+ GtkStateFlags flags;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
+
+ flags = widget->priv->state_flags;
+
+ if (!gtk_widget_is_sensitive (widget))
+ flags |= GTK_STATE_FLAG_INSENSITIVE;
+
+ if (gtk_widget_has_focus (widget))
+ flags |= GTK_STATE_FLAG_FOCUSED;
+
+ return flags;
+}
+
+/**
+ * gtk_widget_set_state:
+ * @widget: a #GtkWidget
+ * @state: new state for @widget
+ *
+ * This function is for use in widget implementations. Sets the state
+ * of a widget (insensitive, prelighted, etc.) Usually you should set
+ * the state using wrapper functions such as gtk_widget_set_sensitive().
+ *
+ * Deprecated: 3.0. Use gtk_widget_set_state_flags() instead.
+ **/
+void
+gtk_widget_set_state (GtkWidget *widget,
+ GtkStateType state)
+{
+ GtkStateFlags flags;
+
+ if (state == gtk_widget_get_state (widget))
+ return;
+
+ switch (state)
+ {
+ case GTK_STATE_ACTIVE:
+ flags = GTK_STATE_FLAG_ACTIVE;
+ break;
+ case GTK_STATE_PRELIGHT:
+ flags = GTK_STATE_FLAG_PRELIGHT;
+ break;
+ case GTK_STATE_SELECTED:
+ flags = GTK_STATE_FLAG_SELECTED;
+ break;
+ case GTK_STATE_INSENSITIVE:
+ flags = GTK_STATE_FLAG_INSENSITIVE;
+ break;
+ case GTK_STATE_INCONSISTENT:
+ flags = GTK_STATE_FLAG_INCONSISTENT;
+ break;
+ case GTK_STATE_FOCUSED:
+ flags = GTK_STATE_FLAG_FOCUSED;
+ break;
+ case GTK_STATE_NORMAL:
+ default:
+ flags = 0;
+ break;
+ }
+
+ _gtk_widget_update_state_flags (widget, flags, STATE_CHANGE_REPLACE);
+}
+
/**
* gtk_widget_get_state:
* @widget: a #GtkWidget
* Returns: the state of @widget.
*
* Since: 2.18
+ *
+ * Deprecated: 3.0. Use gtk_widget_get_state_flags() instead.
*/
GtkStateType
gtk_widget_get_state (GtkWidget *widget)
{
+ GtkStateFlags flags;
+
g_return_val_if_fail (GTK_IS_WIDGET (widget), GTK_STATE_NORMAL);
- return widget->priv->state;
+ flags = gtk_widget_get_state_flags (widget);
+
+ if (flags & GTK_STATE_FLAG_INSENSITIVE)
+ return GTK_STATE_INSENSITIVE;
+ else if (flags & GTK_STATE_FLAG_INCONSISTENT)
+ return GTK_STATE_INCONSISTENT;
+ else if (flags & GTK_STATE_FLAG_ACTIVE)
+ return GTK_STATE_ACTIVE;
+ else if (flags & GTK_STATE_FLAG_SELECTED)
+ return GTK_STATE_SELECTED;
+ else if (flags & GTK_STATE_FLAG_FOCUSED)
+ return GTK_STATE_FOCUSED;
+ else if (flags & GTK_STATE_FLAG_PRELIGHT)
+ return GTK_STATE_PRELIGHT;
+ else
+ return GTK_STATE_NORMAL;
}
/**
* gtk_widget_is_toplevel:
* @widget: a #GtkWidget
*
- * Determines whether @widget is a toplevel widget. Currently only
- * #GtkWindow and #GtkInvisible are toplevel widgets. Toplevel
- * widgets have no parent widget.
+ * Determines whether @widget is a toplevel widget.
+ *
+ * Currently only #GtkWindow and #GtkInvisible (and out-of-process
+ * #GtkPlugs) are toplevel widgets. Toplevel widgets have no parent
+ * widget.
*
* Return value: %TRUE if @widget is a toplevel, %FALSE otherwise
*
if (widget->priv->sensitive == sensitive)
return;
+ data.flags = GTK_STATE_FLAG_INSENSITIVE;
+
if (sensitive)
{
widget->priv->sensitive = TRUE;
- data.state = priv->saved_state;
+ data.operation = STATE_CHANGE_UNSET;
}
else
{
widget->priv->sensitive = FALSE;
- data.state = gtk_widget_get_state (widget);
+ data.operation = STATE_CHANGE_SET;
}
- data.state_restoration = TRUE;
+
data.use_forall = TRUE;
if (priv->parent)
data.parent_sensitive = TRUE;
gtk_widget_propagate_state (widget, &data);
+
if (gtk_widget_is_drawable (widget))
gtk_widget_queue_draw (widget);
return widget->priv->sensitive && widget->priv->parent_sensitive;
}
+static void
+_gtk_widget_update_path (GtkWidget *widget)
+{
+ if (widget->priv->path)
+ {
+ gtk_widget_path_free (widget->priv->path);
+ widget->priv->path = NULL;
+ }
+
+ gtk_widget_get_path (widget);
+}
+
/**
* gtk_widget_set_parent:
* @widget: a #GtkWidget
gtk_widget_set_parent (GtkWidget *widget,
GtkWidget *parent)
{
+ GtkStateFlags parent_flags;
GtkWidgetPrivate *priv;
GtkStateData data;
- GtkStyleContext *context;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GTK_IS_WIDGET (parent));
*/
g_object_ref_sink (widget);
+
+ gtk_widget_push_verify_invariants (widget);
+
priv->parent = parent;
- if (gtk_widget_get_state (parent) != GTK_STATE_NORMAL)
- data.state = gtk_widget_get_state (parent);
- else
- data.state = gtk_widget_get_state (widget);
- data.state_restoration = FALSE;
+ parent_flags = gtk_widget_get_state_flags (parent);
+
+ /* Merge both old state and current parent state,
+ * We don't want the insensitive flag to propagate
+ * to the new child though */
+ data.flags = parent_flags & ~GTK_STATE_FLAG_INSENSITIVE;
+ data.flags |= priv->state_flags;
+
+ data.operation = STATE_CHANGE_REPLACE;
data.parent_sensitive = (gtk_widget_is_sensitive (parent) != FALSE);
data.use_forall = gtk_widget_is_sensitive (parent) != gtk_widget_is_sensitive (widget);
-
gtk_widget_propagate_state (widget, &data);
gtk_widget_reset_rc_styles (widget);
gtk_widget_queue_compute_expand (parent);
}
- context = g_object_get_qdata (G_OBJECT (widget),
- quark_style_context);
- if (context)
+ if (widget->priv->context)
{
- GtkWidgetPath *path;
+ _gtk_widget_update_path (widget);
+ gtk_style_context_set_path (widget->priv->context, widget->priv->path);
- path = gtk_widget_get_path (widget);
- gtk_style_context_set_path (context, path);
- gtk_widget_path_free (path);
-
- gtk_style_context_set_screen (context,
+ gtk_style_context_set_screen (widget->priv->context,
gtk_widget_get_screen (widget));
}
+
+ gtk_widget_pop_verify_invariants (widget);
}
/**
* (finally #GtkWidget) would attach the style itself.
*
* Since: 2.20
+ *
+ * Deprecated: 3.0. This step is unnecessary with #GtkStyleContext.
**/
void
gtk_widget_style_attach (GtkWidget *widget)
* mechanism, %FALSE otherwise.
*
* Since: 2.20
+ *
+ * Deprecated:3.0: Use #GtkStyleContext instead
**/
gboolean
gtk_widget_has_rc_style (GtkWidget *widget)
/**
* gtk_widget_set_style:
* @widget: a #GtkWidget
- * @style: (allow-none): a #GtkStyle, or %NULL to remove the effect of a previous
- * gtk_widget_set_style() and go back to the default style
+ * @style: (allow-none): a #GtkStyle, or %NULL to remove the effect
+ * of a previous call to gtk_widget_set_style() and go back to
+ * the default style
*
- * Sets the #GtkStyle for a widget (@widget->style). You probably don't
- * want to use this function; it interacts badly with themes, because
- * themes work by replacing the #GtkStyle. Instead, use
- * gtk_widget_modify_style().
- **/
+ * Sets the #GtkStyle for a widget (@widget->style).
+ *
+ * You probably don't want to use this function; it interacts
+ * badly with themes, because themes work by replacing the #GtkStyle.
+ * Instead, use gtk_widget_modify_style().
+ *
+ * Deprecated:3.0: Use #GtkStyleContext instead
+ */
void
gtk_widget_set_style (GtkWidget *widget,
- GtkStyle *style)
+ GtkStyle *style)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
-
- if (style)
- {
- gboolean initial_emission;
-
- initial_emission = !widget->priv->rc_style && !widget->priv->user_style;
-
- widget->priv->rc_style = FALSE;
- widget->priv->user_style = TRUE;
-
- gtk_widget_set_style_internal (widget, style, initial_emission);
- }
- else
- {
- if (widget->priv->user_style)
- gtk_widget_reset_rc_style (widget);
- }
}
/**
* gtk_widget_ensure_style:
* @widget: a #GtkWidget
*
- * Ensures that @widget has a style (@widget->style). Not a very useful
- * function; most of the time, if you want the style, the widget is
- * realized, and realized widgets are guaranteed to have a style
- * already.
- **/
+ * Ensures that @widget has a style (@widget->style).
+ *
+ * Not a very useful function; most of the time, if you
+ * want the style, the widget is realized, and realized
+ * widgets are guaranteed to have a style already.
+ *
+ * Deprecated:3.0: Use #GtkStyleContext instead
+ */
void
gtk_widget_ensure_style (GtkWidget *widget)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
- if (!widget->priv->rc_style && !widget->priv->user_style)
- gtk_widget_reset_rc_style (widget);
-}
+ if (!widget->priv->style ||
+ widget->priv->style == gtk_widget_get_default_style ())
+ {
+ GtkStyle *style;
-/* Look up the RC style for this widget, unsetting any user style that
- * may be in effect currently
- **/
-static void
-gtk_widget_reset_rc_style (GtkWidget *widget)
-{
- GtkWidgetPrivate *priv = widget->priv;
- GtkStyle *new_style = NULL;
- gboolean initial_emission;
+ if (widget->priv->style)
+ g_object_unref (widget->priv->style);
- initial_emission = !priv->rc_style && !priv->user_style;
+ style = g_object_new (GTK_TYPE_STYLE,
+ "context", gtk_widget_get_style_context (widget),
+ NULL);
- priv->user_style = FALSE;
- priv->rc_style = TRUE;
+ widget->priv->style = g_object_ref (style);
- if (gtk_widget_has_screen (widget))
- new_style = gtk_rc_get_style (widget);
- if (!new_style)
- new_style = gtk_widget_get_default_style ();
+ g_signal_emit (widget,
+ widget_signals[STYLE_SET],
+ 0, NULL);
- if (initial_emission || new_style != priv->style)
- gtk_widget_set_style_internal (widget, new_style, initial_emission);
+ g_object_unref (style);
+ }
}
/**
* Simply an accessor function that returns @widget->style.
*
* Return value: (transfer none): the widget's #GtkStyle
- **/
+ *
+ * Deprecated:3.0: Use #GtkStyleContext instead
+ */
GtkStyle*
gtk_widget_get_style (GtkWidget *widget)
{
* @widget: a #GtkWidget
* @style: the #GtkRcStyle holding the style modifications
*
- * Modifies style values on the widget. Modifications made using this
- * technique take precedence over style values set via an RC file,
- * however, they will be overriden if a style is explicitely set on
- * the widget using gtk_widget_set_style(). The #GtkRcStyle structure
- * is designed so each field can either be set or unset, so it is
- * possible, using this function, to modify some style values and
- * leave the others unchanged.
+ * Modifies style values on the widget.
+ *
+ * Modifications made using this technique take precedence over
+ * style values set via an RC file, however, they will be overridden
+ * if a style is explicitely set on the widget using gtk_widget_set_style().
+ * The #GtkRcStyle structure is designed so each field can either be
+ * set or unset, so it is possible, using this function, to modify some
+ * style values and leave the others unchanged.
*
* Note that modifications made with this function are not cumulative
* with previous calls to gtk_widget_modify_style() or with such
* if you first call gtk_widget_modify_style(), subsequent calls
* to such functions gtk_widget_modify_fg() will have a cumulative
* effect with the initial modifications.
- **/
+ *
+ * Deprecated:3.0: Use #GtkStyleContext with a custom #GtkStyleProvider instead
+ */
void
gtk_widget_modify_style (GtkWidget *widget,
- GtkRcStyle *style)
+ GtkRcStyle *style)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (GTK_IS_RC_STYLE (style));
g_object_set_qdata_full (G_OBJECT (widget),
- quark_rc_style,
- gtk_rc_style_copy (style),
- (GDestroyNotify) g_object_unref);
-
- /* note that "style" may be invalid here if it was the old
- * modifier style and the only reference was our own.
- */
-
- if (widget->priv->rc_style)
- gtk_widget_reset_rc_style (widget);
+ quark_rc_style,
+ gtk_rc_style_copy (style),
+ (GDestroyNotify) g_object_unref);
}
/**
* thus dropping any reference to the old modifier style. Add a reference
* to the modifier style if you want to keep it alive.
*
- * Return value: (transfer none): the modifier style for the widget. This rc style is
- * owned by the widget. If you want to keep a pointer to value this
- * around, you must add a refcount using g_object_ref().
- **/
+ * Return value: (transfer none): the modifier style for the widget.
+ * This rc style is owned by the widget. If you want to keep a
+ * pointer to value this around, you must add a refcount using
+ * g_object_ref().
+ *
+ * Deprecated:3.0: Use #GtkStyleContext with a custom #GtkStyleProvider instead
+ */
GtkRcStyle *
-gtk_widget_get_modifier_style (GtkWidget *widget)
+gtk_widget_get_modifier_style (GtkWidget *widget)
{
GtkRcStyle *rc_style;
{
rc_style = gtk_rc_style_new ();
g_object_set_qdata_full (G_OBJECT (widget),
- quark_rc_style,
- rc_style,
- (GDestroyNotify) g_object_unref);
+ quark_rc_style,
+ rc_style,
+ (GDestroyNotify) g_object_unref);
}
return rc_style;
static void
gtk_widget_modify_color_component (GtkWidget *widget,
- GtkRcFlags component,
- GtkStateType state,
- const GdkColor *color)
+ GtkRcFlags component,
+ GtkStateType state,
+ const GdkColor *color)
{
GtkRcStyle *rc_style = gtk_widget_get_modifier_style (widget);
if (color)
{
switch (component)
- {
- case GTK_RC_FG:
- rc_style->fg[state] = *color;
- break;
- case GTK_RC_BG:
- rc_style->bg[state] = *color;
- break;
- case GTK_RC_TEXT:
- rc_style->text[state] = *color;
- break;
- case GTK_RC_BASE:
- rc_style->base[state] = *color;
- break;
- default:
- g_assert_not_reached();
- }
+ {
+ case GTK_RC_FG:
+ rc_style->fg[state] = *color;
+ break;
+ case GTK_RC_BG:
+ rc_style->bg[state] = *color;
+ break;
+ case GTK_RC_TEXT:
+ rc_style->text[state] = *color;
+ break;
+ case GTK_RC_BASE:
+ rc_style->base[state] = *color;
+ break;
+ default:
+ g_assert_not_reached();
+ }
rc_style->color_flags[state] |= component;
}
gtk_widget_modify_style (widget, rc_style);
}
+static void
+modifier_style_changed (GtkModifierStyle *style,
+ GtkWidget *widget)
+{
+ GtkStyleContext *context;
+
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_invalidate (context);
+}
+
+static GtkModifierStyle *
+_gtk_widget_get_modifier_properties (GtkWidget *widget)
+{
+ GtkModifierStyle *style;
+
+ style = g_object_get_qdata (G_OBJECT (widget), quark_modifier_style);
+
+ if (G_UNLIKELY (!style))
+ {
+ GtkStyleContext *context;
+
+ style = gtk_modifier_style_new ();
+ g_object_set_qdata_full (G_OBJECT (widget),
+ quark_modifier_style,
+ style,
+ (GDestroyNotify) g_object_unref);
+
+ g_signal_connect (style, "changed",
+ G_CALLBACK (modifier_style_changed), widget);
+
+ context = gtk_widget_get_style_context (widget);
+
+ gtk_style_context_add_provider (context,
+ GTK_STYLE_PROVIDER (style),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+ }
+
+ return style;
+}
+
+/**
+ * gtk_widget_override_color:
+ * @widget: a #GtkWidget
+ * @state: the state for which to set the color
+ * @color: the color to assign, or %NULL to undo the effect
+ * of previous calls to gtk_widget_override_color()
+ *
+ * Sets the color to use for a widget.
+ *
+ * All other style values are left untouched.
+ *
+ * <note><para>
+ * This API is mostly meant as a quick way for applications to
+ * change a widget appearance. If you are developing a widgets
+ * library and intend this change to be themeable, it is better
+ * done by setting meaningful CSS classes and regions in your
+ * widget/container implementation through gtk_style_context_add_class()
+ * and gtk_style_context_add_region().
+ * </para><para>
+ * This way, your widget library can install a #GtkCssProvider
+ * with the %GTK_STYLE_PROVIDER_PRIORITY_FALLBACK priority in order
+ * to provide a default styling for those widgets that need so, and
+ * this theming may fully overridden by the user's theme.
+ * </para></note>
+ * <note><para>
+ * Note that for complex widgets this may bring in undesired
+ * results (such as uniform background color everywhere), in
+ * these cases it is better to fully style such widgets through a
+ * #GtkCssProvider with the %GTK_STYLE_PROVIDER_PRIORITY_APPLICATION
+ * priority.
+ * </para></note>
+ *
+ * Since: 3.0
+ */
+void
+gtk_widget_override_color (GtkWidget *widget,
+ GtkStateFlags state,
+ const GdkRGBA *color)
+{
+ GtkModifierStyle *style;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ style = _gtk_widget_get_modifier_properties (widget);
+ gtk_modifier_style_set_color (style, state, color);
+}
+
+/**
+ * gtk_widget_override_background_color:
+ * @widget: a #GtkWidget
+ * @state: the state for which to set the background color
+ * @color: the color to assign, or %NULL to undo the effect
+ * of previous calls to gtk_widget_override_background_color()
+ *
+ * Sets the background color to use for a widget.
+ *
+ * All other style values are left untouched.
+ * See gtk_widget_override_color().
+ *
+ * Since: 3.0
+ */
+void
+gtk_widget_override_background_color (GtkWidget *widget,
+ GtkStateFlags state,
+ const GdkRGBA *color)
+{
+ GtkModifierStyle *style;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ style = _gtk_widget_get_modifier_properties (widget);
+ gtk_modifier_style_set_background_color (style, state, color);
+}
+
+/**
+ * gtk_widget_override_font:
+ * @widget: a #GtkWidget
+ * @font_desc: the font descriptiong to use, or %NULL to undo
+ * the effect of previous calls to gtk_widget_override_font()
+ *
+ * Sets the font to use for a widget. All other style values are
+ * left untouched. See gtk_widget_override_color().
+ *
+ * Since: 3.0
+ */
+void
+gtk_widget_override_font (GtkWidget *widget,
+ const PangoFontDescription *font_desc)
+{
+ GtkModifierStyle *style;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ style = _gtk_widget_get_modifier_properties (widget);
+ gtk_modifier_style_set_font (style, font_desc);
+}
+
/**
- * gtk_widget_modify_symbolic_color:
+ * gtk_widget_override_symbolic_color:
* @widget: a #GtkWidget
* @name: the name of the symbolic color to modify
- * @color: (allow-none): the color to assign (does not need to be allocated),
- * or %NULL to undo the effect of previous calls to
- * of gtk_widget_modify_symbolic_color().
+ * @color: (allow-none): the color to assign (does not need
+ * to be allocated), or %NULL to undo the effect of previous
+ * calls to gtk_widget_override_symbolic_color()
*
* Sets a symbolic color for a widget.
- * All other style values are left untouched. See also
- * gtk_widget_modify_style().
+ *
+ * All other style values are left untouched.
+ * See gtk_widget_override_color() for overriding the foreground
+ * or background color.
*
* Since: 3.0
- **/
+ */
void
-gtk_widget_modify_symbolic_color (GtkWidget *widget,
- const gchar *name,
- const GdkColor *color)
+gtk_widget_override_symbolic_color (GtkWidget *widget,
+ const gchar *name,
+ const GdkRGBA *color)
{
- GtkRcStyle *rc_style = gtk_widget_get_modifier_style (widget);
+ GtkModifierStyle *style;
- _gtk_rc_style_set_symbolic_color (rc_style, name, color);
+ g_return_if_fail (GTK_IS_WIDGET (widget));
- gtk_widget_modify_style (widget, rc_style);
+ style = _gtk_widget_get_modifier_properties (widget);
+ gtk_modifier_style_map_color (style, name, color);
+}
+
+/**
+ * gtk_widget_override_cursor:
+ * @widget: a #GtkWidget
+ * @cursor: the color to use for primary cursor (does not need to be
+ * allocated), or %NULL to undo the effect of previous calls to
+ * of gtk_widget_override_cursor().
+ * @secondary_cursor: the color to use for secondary cursor (does not
+ * need to be allocated), or %NULL to undo the effect of previous
+ * calls to of gtk_widget_override_cursor().
+ *
+ * Sets the cursor color to use in a widget, overriding the
+ * #GtkWidget:cursor-color and #GtkWidget:secondary-cursor-color
+ * style properties. All other style values are left untouched.
+ * See also gtk_widget_modify_style().
+ *
+ * Note that the underlying properties have the #GdkColor type,
+ * so the alpha value in @primary and @secondary will be ignored.
+ *
+ * Since: 3.0
+ */
+void
+gtk_widget_override_cursor (GtkWidget *widget,
+ const GdkRGBA *cursor,
+ const GdkRGBA *secondary_cursor)
+{
+ GtkModifierStyle *style;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ style = _gtk_widget_get_modifier_properties (widget);
+ gtk_modifier_style_set_color_property (style,
+ GTK_TYPE_WIDGET,
+ "cursor-color", cursor);
+ gtk_modifier_style_set_color_property (style,
+ GTK_TYPE_WIDGET,
+ "secondary-cursor-color",
+ secondary_cursor);
}
/**
* @widget: a #GtkWidget
* @state: the state for which to set the foreground color
* @color: (allow-none): the color to assign (does not need to be allocated),
- * or %NULL to undo the effect of previous calls to
- * of gtk_widget_modify_fg().
+ * or %NULL to undo the effect of previous calls to
+ * of gtk_widget_modify_fg().
*
* Sets the foreground color for a widget in a particular state.
- * All other style values are left untouched. See also
- * gtk_widget_modify_style().
- **/
+ *
+ * All other style values are left untouched.
+ * See also gtk_widget_modify_style().
+ *
+ * Deprecated:3.0: Use gtk_widget_override_color() instead
+ */
void
gtk_widget_modify_fg (GtkWidget *widget,
- GtkStateType state,
- const GdkColor *color)
+ GtkStateType state,
+ const GdkColor *color)
{
+ GtkStateFlags flags;
+ GdkRGBA rgba;
+
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (state >= GTK_STATE_NORMAL && state <= GTK_STATE_INSENSITIVE);
- gtk_widget_modify_color_component (widget, GTK_RC_FG, state, color);
+ switch (state)
+ {
+ case GTK_STATE_ACTIVE:
+ flags = GTK_STATE_FLAG_ACTIVE;
+ break;
+ case GTK_STATE_PRELIGHT:
+ flags = GTK_STATE_FLAG_PRELIGHT;
+ break;
+ case GTK_STATE_SELECTED:
+ flags = GTK_STATE_FLAG_SELECTED;
+ break;
+ case GTK_STATE_INSENSITIVE:
+ flags = GTK_STATE_FLAG_INSENSITIVE;
+ break;
+ case GTK_STATE_NORMAL:
+ default:
+ flags = 0;
+ }
+
+ if (color)
+ {
+ rgba.red = color->red / 65535.;
+ rgba.green = color->green / 65535.;
+ rgba.blue = color->blue / 65535.;
+ rgba.alpha = 1;
+
+ gtk_widget_override_color (widget, flags, &rgba);
+ }
+ else
+ gtk_widget_override_color (widget, flags, NULL);
}
/**
* gtk_widget_modify_bg:
* @widget: a #GtkWidget
* @state: the state for which to set the background color
- * @color: (allow-none): the color to assign (does not need to be allocated),
- * or %NULL to undo the effect of previous calls to
- * of gtk_widget_modify_bg().
+ * @color: (allow-none): the color to assign (does not need
+ * to be allocated), or %NULL to undo the effect of previous
+ * calls to of gtk_widget_modify_bg().
*
* Sets the background color for a widget in a particular state.
- * All other style values are left untouched. See also
- * gtk_widget_modify_style().
*
- * Note that "no window" widgets (which have the %GTK_NO_WINDOW flag set)
- * draw on their parent container's window and thus may not draw any
- * background themselves. This is the case for e.g. #GtkLabel. To modify
- * the background of such widgets, you have to set the background color
- * on their parent; if you want to set the background of a rectangular
- * area around a label, try placing the label in a #GtkEventBox widget
- * and setting the background color on that.
- **/
+ * All other style values are left untouched.
+ * See also gtk_widget_modify_style().
+ *
+ * <note><para>
+ * Note that "no window" widgets (which have the %GTK_NO_WINDOW
+ * flag set) draw on their parent container's window and thus may
+ * not draw any background themselves. This is the case for e.g.
+ * #GtkLabel.
+ * </para><para>
+ * To modify the background of such widgets, you have to set the
+ * background color on their parent; if you want to set the background
+ * of a rectangular area around a label, try placing the label in
+ * a #GtkEventBox widget and setting the background color on that.
+ * </para></note>
+ *
+ * Deprecated:3.0: Use gtk_widget_override_background_color() instead
+ */
void
gtk_widget_modify_bg (GtkWidget *widget,
- GtkStateType state,
- const GdkColor *color)
+ GtkStateType state,
+ const GdkColor *color)
{
+ GtkStateFlags flags;
+ GdkRGBA rgba;
+
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (state >= GTK_STATE_NORMAL && state <= GTK_STATE_INSENSITIVE);
- gtk_widget_modify_color_component (widget, GTK_RC_BG, state, color);
+ switch (state)
+ {
+ case GTK_STATE_ACTIVE:
+ flags = GTK_STATE_FLAG_ACTIVE;
+ break;
+ case GTK_STATE_PRELIGHT:
+ flags = GTK_STATE_FLAG_PRELIGHT;
+ break;
+ case GTK_STATE_SELECTED:
+ flags = GTK_STATE_FLAG_SELECTED;
+ break;
+ case GTK_STATE_INSENSITIVE:
+ flags = GTK_STATE_FLAG_INSENSITIVE;
+ break;
+ case GTK_STATE_NORMAL:
+ default:
+ flags = 0;
+ }
+
+ if (color)
+ {
+ rgba.red = color->red / 65535.;
+ rgba.green = color->green / 65535.;
+ rgba.blue = color->blue / 65535.;
+ rgba.alpha = 1;
+
+ gtk_widget_override_background_color (widget, flags, &rgba);
+ }
+ else
+ gtk_widget_override_background_color (widget, flags, NULL);
}
/**
* gtk_widget_modify_text:
* @widget: a #GtkWidget
* @state: the state for which to set the text color
- * @color: (allow-none): the color to assign (does not need to be allocated),
- * or %NULL to undo the effect of previous calls to
- * of gtk_widget_modify_text().
+ * @color: (allow-none): the color to assign (does not need to
+ * be allocated), or %NULL to undo the effect of previous
+ * calls to of gtk_widget_modify_text().
*
- * Sets the text color for a widget in a particular state. All other
- * style values are left untouched. The text color is the foreground
- * color used along with the base color (see gtk_widget_modify_base())
- * for widgets such as #GtkEntry and #GtkTextView. See also
- * gtk_widget_modify_style().
- **/
+ * Sets the text color for a widget in a particular state.
+ *
+ * All other style values are left untouched.
+ * The text color is the foreground color used along with the
+ * base color (see gtk_widget_modify_base()) for widgets such
+ * as #GtkEntry and #GtkTextView.
+ * See also gtk_widget_modify_style().
+ *
+ * Deprecated:3.0: Use gtk_widget_override_color() instead
+ */
void
gtk_widget_modify_text (GtkWidget *widget,
- GtkStateType state,
- const GdkColor *color)
+ GtkStateType state,
+ const GdkColor *color)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (state >= GTK_STATE_NORMAL && state <= GTK_STATE_INSENSITIVE);
* gtk_widget_modify_base:
* @widget: a #GtkWidget
* @state: the state for which to set the base color
- * @color: (allow-none): the color to assign (does not need to be allocated),
- * or %NULL to undo the effect of previous calls to
- * of gtk_widget_modify_base().
+ * @color: (allow-none): the color to assign (does not need to
+ * be allocated), or %NULL to undo the effect of previous
+ * calls to of gtk_widget_modify_base().
*
* Sets the base color for a widget in a particular state.
* All other style values are left untouched. The base color
* (see gtk_widget_modify_text()) for widgets such as #GtkEntry
* and #GtkTextView. See also gtk_widget_modify_style().
*
- * Note that "no window" widgets (which have the %GTK_NO_WINDOW flag set)
- * draw on their parent container's window and thus may not draw any
- * background themselves. This is the case for e.g. #GtkLabel. To modify
- * the background of such widgets, you have to set the base color on their
- * parent; if you want to set the background of a rectangular area around
- * a label, try placing the label in a #GtkEventBox widget and setting
- * the base color on that.
- **/
+ * <note><para>
+ * Note that "no window" widgets (which have the %GTK_NO_WINDOW
+ * flag set) draw on their parent container's window and thus may
+ * not draw any background themselves. This is the case for e.g.
+ * #GtkLabel.
+ * </para><para>
+ * To modify the background of such widgets, you have to set the
+ * base color on their parent; if you want to set the background
+ * of a rectangular area around a label, try placing the label in
+ * a #GtkEventBox widget and setting the base color on that.
+ * </para></note>
+ *
+ * Deprecated:3.0: Use gtk_widget_override_background_color() instead
+ */
void
gtk_widget_modify_base (GtkWidget *widget,
- GtkStateType state,
- const GdkColor *color)
+ GtkStateType state,
+ const GdkColor *color)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (state >= GTK_STATE_NORMAL && state <= GTK_STATE_INSENSITIVE);
gtk_widget_modify_color_component (widget, GTK_RC_BASE, state, color);
}
-static void
-modify_color_property (GtkWidget *widget,
- GtkRcStyle *rc_style,
- const char *name,
- const GdkColor *color)
-{
- GQuark type_name = g_type_qname (G_OBJECT_TYPE (widget));
- GQuark property_name = g_quark_from_string (name);
-
- if (color)
- {
- GtkRcProperty rc_property = {0};
- char *color_name;
-
- rc_property.type_name = type_name;
- rc_property.property_name = property_name;
- rc_property.origin = NULL;
-
- color_name = gdk_color_to_string (color);
- g_value_init (&rc_property.value, G_TYPE_STRING);
- g_value_take_string (&rc_property.value, color_name);
-
- _gtk_rc_style_set_rc_property (rc_style, &rc_property);
-
- g_value_unset (&rc_property.value);
- }
- else
- _gtk_rc_style_unset_rc_property (rc_style, type_name, property_name);
-}
-
/**
* gtk_widget_modify_cursor:
* @widget: a #GtkWidget
* @primary: the color to use for primary cursor (does not need to be
- * allocated), or %NULL to undo the effect of previous calls to
- * of gtk_widget_modify_cursor().
+ * allocated), or %NULL to undo the effect of previous calls to
+ * of gtk_widget_modify_cursor().
* @secondary: the color to use for secondary cursor (does not need to be
- * allocated), or %NULL to undo the effect of previous calls to
- * of gtk_widget_modify_cursor().
+ * allocated), or %NULL to undo the effect of previous calls to
+ * of gtk_widget_modify_cursor().
*
* Sets the cursor color to use in a widget, overriding the
* #GtkWidget:cursor-color and #GtkWidget:secondary-cursor-color
- * style properties. All other style values are left untouched.
+ * style properties.
+ *
+ * All other style values are left untouched.
* See also gtk_widget_modify_style().
*
* Since: 2.12
- **/
+ *
+ * Deprecated: 3.0. Use gtk_widget_override_cursor() instead.
+ */
void
gtk_widget_modify_cursor (GtkWidget *widget,
- const GdkColor *primary,
- const GdkColor *secondary)
+ const GdkColor *primary,
+ const GdkColor *secondary)
{
- GtkRcStyle *rc_style;
+ GdkRGBA primary_rgba, secondary_rgba;
g_return_if_fail (GTK_IS_WIDGET (widget));
- rc_style = gtk_widget_get_modifier_style (widget);
+ primary_rgba.red = primary->red / 65535.;
+ primary_rgba.green = primary->green / 65535.;
+ primary_rgba.blue = primary->blue / 65535.;
+ primary_rgba.alpha = 1;
- modify_color_property (widget, rc_style, "cursor-color", primary);
- modify_color_property (widget, rc_style, "secondary-cursor-color", secondary);
+ secondary_rgba.red = secondary->red / 65535.;
+ secondary_rgba.green = secondary->green / 65535.;
+ secondary_rgba.blue = secondary->blue / 65535.;
+ secondary_rgba.alpha = 1;
- gtk_widget_modify_style (widget, rc_style);
+ gtk_widget_override_cursor (widget, &primary_rgba, &secondary_rgba);
}
/**
* gtk_widget_modify_font:
* @widget: a #GtkWidget
- * @font_desc: (allow-none): the font description to use, or %NULL to undo
- * the effect of previous calls to gtk_widget_modify_font().
+ * @font_desc: (allow-none): the font description to use, or %NULL
+ * to undo the effect of previous calls to gtk_widget_modify_font()
*
- * Sets the font to use for a widget. All other style values are left
- * untouched. See also gtk_widget_modify_style().
- **/
+ * Sets the font to use for a widget.
+ *
+ * All other style values are left untouched.
+ * See also gtk_widget_modify_style().
+ *
+ * Deprecated:3.0: Use gtk_widget_override_font() instead
+ */
void
gtk_widget_modify_font (GtkWidget *widget,
- PangoFontDescription *font_desc)
+ PangoFontDescription *font_desc)
{
- GtkRcStyle *rc_style;
-
g_return_if_fail (GTK_IS_WIDGET (widget));
- rc_style = gtk_widget_get_modifier_style (widget);
-
- if (rc_style->font_desc)
- pango_font_description_free (rc_style->font_desc);
-
- if (font_desc)
- rc_style->font_desc = pango_font_description_copy (font_desc);
- else
- rc_style->font_desc = NULL;
-
- gtk_widget_modify_style (widget, rc_style);
+ gtk_widget_override_font (widget, font_desc);
}
static void
gtk_widget_real_style_set (GtkWidget *widget,
GtkStyle *previous_style)
{
- GtkWidgetPrivate *priv = widget->priv;
-
- if (gtk_widget_get_realized (widget) &&
- gtk_widget_get_has_window (widget))
- gtk_style_set_background (priv->style, priv->window, priv->state);
-}
-
-static void
-gtk_widget_set_style_internal (GtkWidget *widget,
- GtkStyle *style,
- gboolean initial_emission)
-{
- GtkWidgetPrivate *priv = widget->priv;
-
- g_object_ref (widget);
- g_object_freeze_notify (G_OBJECT (widget));
-
- if (priv->style != style)
- {
- GtkStyle *previous_style;
-
- if (gtk_widget_get_realized (widget))
- {
- gtk_widget_reset_shapes (widget);
- gtk_style_detach (priv->style);
- }
-
- previous_style = priv->style;
- priv->style = style;
- g_object_ref (priv->style);
-
- if (gtk_widget_get_realized (widget))
- priv->style = gtk_style_attach (priv->style, priv->window);
-
- gtk_widget_update_pango_context (widget);
- g_signal_emit (widget,
- widget_signals[STYLE_SET],
- 0,
- initial_emission ? NULL : previous_style);
- g_object_unref (previous_style);
-
- if (priv->anchored && !initial_emission)
- gtk_widget_queue_resize (widget);
- }
- else if (initial_emission)
- {
- gtk_widget_update_pango_context (widget);
- g_signal_emit (widget,
- widget_signals[STYLE_SET],
- 0,
- NULL);
- }
- g_object_notify (G_OBJECT (widget), "style");
- g_object_thaw_notify (G_OBJECT (widget));
- g_object_unref (widget);
}
typedef struct {
_gtk_tooltip_hide (widget);
context = gtk_widget_get_style_context (widget);
- gtk_style_context_set_screen (context, new_screen);
+ gtk_style_context_set_screen (context, gtk_widget_get_screen (widget));
g_signal_emit (widget, widget_signals[SCREEN_CHANGED], 0, old_screen);
}
}
static void
-reset_rc_styles_recurse (GtkWidget *widget, gpointer data)
+reset_style_recurse (GtkWidget *widget, gpointer data)
{
- if (widget->priv->rc_style)
- gtk_widget_reset_rc_style (widget);
+ if (widget->priv->context)
+ {
+ _gtk_widget_update_path (widget);
+ gtk_style_context_set_path (widget->priv->context,
+ widget->priv->path);
+ }
if (GTK_IS_CONTAINER (widget))
gtk_container_forall (GTK_CONTAINER (widget),
- reset_rc_styles_recurse,
+ reset_style_recurse,
NULL);
}
+/**
+ * gtk_widget_reset_style:
+ * @widget: a #GtkWidget
+ *
+ * Updates the style context of @widget and all descendents
+ * by updating its widget path. #GtkContainer<!-- -->s may want
+ * to use this on a child when reordering it in a way that a different
+ * style might apply to it. See also gtk_container_get_path_for_child().
+ *
+ * Since: 3.0
+ */
+void
+gtk_widget_reset_style (GtkWidget *widget)
+{
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+
+ reset_style_recurse (widget, NULL);
+}
/**
* gtk_widget_reset_rc_styles:
* for the currently loaded RC file settings.
*
* This function is not useful for applications.
+ *
+ * Deprecated:3.0: Use #GtkStyleContext instead
*/
void
gtk_widget_reset_rc_styles (GtkWidget *widget)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
- reset_rc_styles_recurse (widget, NULL);
+ reset_style_recurse (widget, NULL);
}
/**
*
* Returns the default style used by all widgets initially.
*
- * Returns: (transfer none): the default style. This #GtkStyle object is owned
- * by GTK+ and should not be modified or freed.
+ * Returns: (transfer none): the default style. This #GtkStyle
+ * object is owned by GTK+ and should not be modified or freed.
+ *
+ * Deprecated:3.0: Use #GtkStyleContext instead
*/
GtkStyle*
gtk_widget_get_default_style (void)
gtk_default_style = gtk_style_new ();
g_object_ref (gtk_default_style);
}
-
- return gtk_default_style;
+
+ return gtk_default_style;
+}
+
+#ifdef G_ENABLE_DEBUG
+
+/* Verify invariants, see docs/widget_system.txt for notes on much of
+ * this. Invariants may be temporarily broken while we're in the
+ * process of updating state, of course, so you can only
+ * verify_invariants() after a given operation is complete.
+ * Use push/pop_verify_invariants to help with that.
+ */
+static void
+gtk_widget_verify_invariants (GtkWidget *widget)
+{
+ GtkWidget *parent;
+
+ if (widget->priv->verifying_invariants_count > 0)
+ return;
+
+ parent = widget->priv->parent;
+
+ if (widget->priv->mapped)
+ {
+ /* Mapped implies ... */
+
+ if (!widget->priv->realized)
+ g_warning ("%s %p is mapped but not realized",
+ G_OBJECT_TYPE_NAME (widget), widget);
+
+ if (!widget->priv->visible)
+ g_warning ("%s %p is mapped but not visible",
+ G_OBJECT_TYPE_NAME (widget), widget);
+
+ if (!widget->priv->toplevel)
+ {
+ if (!widget->priv->child_visible)
+ g_warning ("%s %p is mapped but not child_visible",
+ G_OBJECT_TYPE_NAME (widget), widget);
+ }
+ }
+ else
+ {
+ /* Not mapped implies... */
+
+#if 0
+ /* This check makes sense for normal toplevels, but for
+ * something like a toplevel that is embedded within a clutter
+ * state, mapping may depend on external factors.
+ */
+ if (widget->priv->toplevel)
+ {
+ if (widget->priv->visible)
+ g_warning ("%s %p toplevel is visible but not mapped",
+ G_OBJECT_TYPE_NAME (widget), widget);
+ }
+#endif
+ }
+
+ /* Parent related checks aren't possible if parent has
+ * verifying_invariants_count > 0 because parent needs to recurse
+ * children first before the invariants will hold.
+ */
+ if (parent == NULL || parent->priv->verifying_invariants_count == 0)
+ {
+ if (parent &&
+ parent->priv->realized)
+ {
+ /* Parent realized implies... */
+
+#if 0
+ /* This is in widget_system.txt but appears to fail
+ * because there's no gtk_container_realize() that
+ * realizes all children... instead we just lazily
+ * wait for map to fix things up.
+ */
+ if (!widget->priv->realized)
+ g_warning ("%s %p is realized but child %s %p is not realized",
+ G_OBJECT_TYPE_NAME (parent), parent,
+ G_OBJECT_TYPE_NAME (widget), widget);
+#endif
+ }
+ else if (!widget->priv->toplevel)
+ {
+ /* No parent or parent not realized on non-toplevel implies... */
+
+ if (widget->priv->realized && !widget->priv->in_reparent)
+ g_warning ("%s %p is not realized but child %s %p is realized",
+ parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
+ G_OBJECT_TYPE_NAME (widget), widget);
+ }
+
+ if (parent &&
+ parent->priv->mapped &&
+ widget->priv->visible &&
+ widget->priv->child_visible)
+ {
+ /* Parent mapped and we are visible implies... */
+
+ if (!widget->priv->mapped)
+ g_warning ("%s %p is mapped but visible child %s %p is not mapped",
+ G_OBJECT_TYPE_NAME (parent), parent,
+ G_OBJECT_TYPE_NAME (widget), widget);
+ }
+ else if (!widget->priv->toplevel)
+ {
+ /* No parent or parent not mapped on non-toplevel implies... */
+
+ if (widget->priv->mapped && !widget->priv->in_reparent)
+ g_warning ("%s %p is mapped but visible=%d child_visible=%d parent %s %p mapped=%d",
+ G_OBJECT_TYPE_NAME (widget), widget,
+ widget->priv->visible,
+ widget->priv->child_visible,
+ parent ? G_OBJECT_TYPE_NAME (parent) : "no parent", parent,
+ parent ? parent->priv->mapped : FALSE);
+ }
+ }
+
+ if (!widget->priv->realized)
+ {
+ /* Not realized implies... */
+
+#if 0
+ /* widget_system.txt says these hold, but they don't. */
+ if (widget->priv->resize_pending)
+ g_warning ("%s %p resize pending but not realized",
+ G_OBJECT_TYPE_NAME (widget), widget);
+
+ if (widget->priv->alloc_needed)
+ g_warning ("%s %p alloc needed but not realized",
+ G_OBJECT_TYPE_NAME (widget), widget);
+
+ if (widget->priv->width_request_needed)
+ g_warning ("%s %p width request needed but not realized",
+ G_OBJECT_TYPE_NAME (widget), widget);
+
+ if (widget->priv->height_request_needed)
+ g_warning ("%s %p height request needed but not realized",
+ G_OBJECT_TYPE_NAME (widget), widget);
+#endif
+ }
+}
+
+/* The point of this push/pop is that invariants may not hold while
+ * we're busy making changes. So we only check at the outermost call
+ * on the call stack, after we finish updating everything.
+ */
+static void
+gtk_widget_push_verify_invariants (GtkWidget *widget)
+{
+ widget->priv->verifying_invariants_count += 1;
+}
+
+static void
+gtk_widget_verify_child_invariants (GtkWidget *widget,
+ gpointer client_data)
+{
+ /* We don't recurse further; this is a one-level check. */
+ gtk_widget_verify_invariants (widget);
+}
+
+static void
+gtk_widget_pop_verify_invariants (GtkWidget *widget)
+{
+ g_assert (widget->priv->verifying_invariants_count > 0);
+
+ widget->priv->verifying_invariants_count -= 1;
+
+ if (widget->priv->verifying_invariants_count == 0)
+ {
+ gtk_widget_verify_invariants (widget);
+
+ if (GTK_IS_CONTAINER (widget))
+ {
+ /* Check one level of children, because our
+ * push_verify_invariants() will have prevented some of the
+ * checks. This does not recurse because if recursion is
+ * needed, it will happen naturally as each child has a
+ * push/pop on that child. For example if we're recursively
+ * mapping children, we'll push/pop on each child as we map
+ * it.
+ */
+ gtk_container_forall (GTK_CONTAINER (widget),
+ gtk_widget_verify_child_invariants,
+ NULL);
+ }
+ }
}
+#endif /* G_ENABLE_DEBUG */
static PangoContext *
gtk_widget_peek_pango_context (GtkWidget *widget)
*
* If you create and keep a #PangoLayout using this context, you must
* deal with changes to the context by calling pango_layout_context_changed()
- * on the layout in response to the #GtkWidget::style-set and
+ * on the layout in response to the #GtkWidget::style-updated and
* #GtkWidget::direction-changed signals for the widget.
*
* Return value: (transfer none): the #PangoContext for the widget.
update_pango_context (GtkWidget *widget,
PangoContext *context)
{
- GtkWidgetPrivate *priv = widget->priv;
+ PangoFontDescription *font_desc;
+ GtkStyleContext *style_context;
- pango_context_set_font_description (context, priv->style->font_desc);
+ style_context = gtk_widget_get_style_context (widget);
+
+ gtk_style_context_get (style_context,
+ gtk_widget_get_state_flags (widget),
+ "font", &font_desc,
+ NULL);
+
+ pango_context_set_font_description (context, font_desc);
pango_context_set_base_dir (context,
gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR ?
PANGO_DIRECTION_LTR : PANGO_DIRECTION_RTL);
+
+ pango_font_description_free (font_desc);
}
static void
* If you keep a #PangoLayout created in this way around, in order to
* notify the layout of changes to the base direction or font of this
* widget, you must call pango_layout_context_changed() in response to
- * the #GtkWidget::style-set and #GtkWidget::direction-changed signals
+ * the #GtkWidget::style-updated and #GtkWidget::direction-changed signals
* for the widget.
*
* Return value: (transfer full): the new #PangoLayout
}
/**
- * gtk_widget_render_icon:
+ * gtk_widget_render_icon_pixbuf:
* @widget: a #GtkWidget
* @stock_id: a stock ID
* @size: (type int): a stock size. A size of (GtkIconSize)-1 means
* render at the size of the source and don't scale (if there are
* multiple source sizes, GTK+ picks one of the available sizes).
- * @detail: (allow-none): render detail to pass to theme engine
*
- * A convenience function that uses the theme engine and RC file
+ * A convenience function that uses the theme engine and style
* settings for @widget to look up @stock_id and render it to
* a pixbuf. @stock_id should be a stock icon ID such as
* #GTK_STOCK_OPEN or #GTK_STOCK_OK. @size should be a size
- * such as #GTK_ICON_SIZE_MENU. @detail should be a string that
- * identifies the widget or code doing the rendering, so that
- * theme engines can special-case rendering for that widget or code.
+ * such as #GTK_ICON_SIZE_MENU.
*
* The pixels in the returned #GdkPixbuf are shared with the rest of
* the application and should not be modified. The pixbuf should be freed
*
* Return value: (transfer full): a new pixbuf, or %NULL if the
* stock ID wasn't known
+ *
+ * Since: 3.0
**/
GdkPixbuf*
-gtk_widget_render_icon (GtkWidget *widget,
- const gchar *stock_id,
- GtkIconSize size,
- const gchar *detail)
+gtk_widget_render_icon_pixbuf (GtkWidget *widget,
+ const gchar *stock_id,
+ GtkIconSize size)
{
- GtkWidgetPrivate *priv;
+ GtkStyleContext *context;
GtkIconSet *icon_set;
- GdkPixbuf *retval;
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
g_return_val_if_fail (stock_id != NULL, NULL);
g_return_val_if_fail (size > GTK_ICON_SIZE_INVALID || size == -1, NULL);
- priv = widget->priv;
-
- gtk_widget_ensure_style (widget);
-
- icon_set = gtk_style_lookup_icon_set (priv->style, stock_id);
+ context = gtk_widget_get_style_context (widget);
+ icon_set = gtk_style_context_lookup_icon_set (context, stock_id);
if (icon_set == NULL)
return NULL;
- retval = gtk_icon_set_render_icon (icon_set,
- priv->style,
- gtk_widget_get_direction (widget),
- gtk_widget_get_state (widget),
- size,
- widget,
- detail);
+ return gtk_icon_set_render_icon_pixbuf (icon_set, context, size);
+}
- return retval;
+/**
+ * gtk_widget_render_icon:
+ * @widget: a #GtkWidget
+ * @stock_id: a stock ID
+ * @size: (type int): a stock size. A size of (GtkIconSize)-1 means
+ * render at the size of the source and don't scale (if there are
+ * multiple source sizes, GTK+ picks one of the available sizes).
+ * @detail: (allow-none): render detail to pass to theme engine
+ *
+ * A convenience function that uses the theme engine and RC file
+ * settings for @widget to look up @stock_id and render it to
+ * a pixbuf. @stock_id should be a stock icon ID such as
+ * #GTK_STOCK_OPEN or #GTK_STOCK_OK. @size should be a size
+ * such as #GTK_ICON_SIZE_MENU. @detail should be a string that
+ * identifies the widget or code doing the rendering, so that
+ * theme engines can special-case rendering for that widget or code.
+ *
+ * The pixels in the returned #GdkPixbuf are shared with the rest of
+ * the application and should not be modified. The pixbuf should be freed
+ * after use with g_object_unref().
+ *
+ * Return value: (transfer full): a new pixbuf, or %NULL if the
+ * stock ID wasn't known
+ *
+ * Deprecated: 3.0: Use gtk_widget_render_icon_pixbuf() instead.
+ **/
+GdkPixbuf*
+gtk_widget_render_icon (GtkWidget *widget,
+ const gchar *stock_id,
+ GtkIconSize size,
+ const gchar *detail)
+{
+ return gtk_widget_render_icon_pixbuf (widget, stock_id, size);
}
/**
* @parent_window: the new parent window.
*
* Sets a non default parent window for @widget.
+ *
+ * For GtkWindow classes, setting a @parent_window effects whether
+ * the window is a toplevel window or can be embedded into other
+ * widgets.
+ *
+ * <note><para>
+ * For GtkWindow classes, this needs to be called before the
+ * window is realized.
+ * </para></note>
+ *
**/
void
gtk_widget_set_parent_window (GtkWidget *widget,
g_object_unref (old_parent_window);
if (parent_window)
g_object_ref (parent_window);
+
+ /* Unset toplevel flag when adding a parent window to a widget,
+ * this is the primary entry point to allow toplevels to be
+ * embeddable.
+ */
+ if (GTK_IS_WINDOW (widget) && !GTK_IS_PLUG (widget))
+ _gtk_window_set_is_toplevel (GTK_WINDOW (widget), parent_window == NULL);
}
}
priv = widget->priv;
g_object_ref (widget);
+ gtk_widget_verify_invariants (widget);
if (is_visible)
priv->child_visible = TRUE;
gtk_widget_unmap (widget);
}
+ gtk_widget_verify_invariants (widget);
g_object_unref (widget);
}
g_hash_table_insert (device_events, device, GUINT_TO_POINTER (events));
}
+/**
+ * gtk_widget_enable_device:
+ * @widget: a #GtkWidget
+ * @device: a #GdkDevice
+ *
+ * Enables a #GdkDevice to interact with @widget and
+ * all its children, it does so by descending through
+ * the #GdkWindow hierarchy and enabling the same mask
+ * that is has for core events (i.e. the one that
+ * gdk_window_get_events() returns).
+ *
+ * Since: 3.0
+ **/
+void
+gtk_widget_set_device_enabled (GtkWidget *widget,
+ GdkDevice *device,
+ gboolean enabled)
+{
+ GList *enabled_devices;
+
+ g_return_if_fail (GTK_IS_WIDGET (widget));
+ g_return_if_fail (GDK_IS_DEVICE (device));
+
+ enabled_devices = g_object_get_qdata (G_OBJECT (widget), quark_enabled_devices);
+ enabled_devices = g_list_append (enabled_devices, device);
+
+ g_object_set_qdata_full (G_OBJECT (widget), quark_enabled_devices,
+ enabled_devices, (GDestroyNotify) g_list_free);;
+
+ if (gtk_widget_get_realized (widget))
+ gtk_widget_set_device_enabled_internal (widget, device, TRUE, enabled);
+}
+
+gboolean
+gtk_widget_get_device_enabled (GtkWidget *widget,
+ GdkDevice *device)
+{
+ GList *enabled_devices;
+
+ g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE);
+ g_return_val_if_fail (GDK_IS_DEVICE (device), FALSE);
+
+ enabled_devices = g_object_get_qdata (G_OBJECT (widget), quark_enabled_devices);
+
+ return g_list_find (enabled_devices, device) != NULL;
+}
+
static void
gtk_widget_add_events_internal_list (GtkWidget *widget,
GdkDevice *device,
GINT_TO_POINTER (old_events | events));
if (gtk_widget_get_realized (widget))
- gtk_widget_add_events_internal (widget, NULL, events);
+ {
+ gtk_widget_add_events_internal (widget, NULL, events);
+ gtk_widget_update_devices_mask (widget, FALSE);
+ }
g_object_notify (G_OBJECT (widget), "events");
}
g_object_notify (G_OBJECT (widget), "events");
}
-/**
- * gtk_widget_set_extension_events:
- * @widget: a #GtkWidget
- * @mode: bitfield of extension events to receive
- *
- * Sets the extension events mask to @mode. See #GdkExtensionMode
- * and gdk_input_set_extension_events().
- **/
-void
-gtk_widget_set_extension_events (GtkWidget *widget,
- GdkExtensionMode mode)
-{
- g_return_if_fail (GTK_IS_WIDGET (widget));
-
- if (gtk_widget_get_realized (widget))
- gtk_widget_set_extension_events_internal (widget, mode, NULL);
-
- g_object_set_qdata (G_OBJECT (widget), quark_extension_event_mode,
- GINT_TO_POINTER (mode));
- g_object_notify (G_OBJECT (widget), "extension-events");
-}
-
/**
* gtk_widget_get_toplevel:
* @widget: a #GtkWidget
return GPOINTER_TO_UINT (g_hash_table_lookup (device_events, device));
}
-/**
- * gtk_widget_get_extension_events:
- * @widget: a #GtkWidget
- *
- * Retrieves the extension events the widget will receive; see
- * gdk_input_set_extension_events().
- *
- * Return value: extension events for @widget
- **/
-GdkExtensionMode
-gtk_widget_get_extension_events (GtkWidget *widget)
-{
- g_return_val_if_fail (GTK_IS_WIDGET (widget), 0);
-
- return GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (widget), quark_extension_event_mode));
-}
-
/**
* gtk_widget_get_pointer:
* @widget: a #GtkWidget
widget->priv->direction = dir;
if (old_dir != gtk_widget_get_direction (widget))
- gtk_widget_emit_direction_changed (widget, old_dir);
+ {
+ if (widget->priv->context)
+ gtk_style_context_set_direction (widget->priv->context,
+ gtk_widget_get_direction (widget));
+
+ gtk_widget_emit_direction_changed (widget, old_dir);
+ }
}
/**
if (accessible)
g_object_unref (accessible);
+ if (priv->path)
+ gtk_widget_path_free (priv->path);
+
+ if (priv->context)
+ g_object_unref (priv->context);
+
if (g_object_is_floating (object))
g_warning ("A floating object was finalized. This means that someone\n"
"called g_object_unref() on an object that had only a floating\n"
{
GtkWidgetPrivate *priv = widget->priv;
- if (gtk_widget_get_mapped (widget))
- gtk_widget_real_unmap (widget);
-
- gtk_widget_set_mapped (widget, FALSE);
+ g_assert (!widget->priv->mapped);
/* printf ("unrealizing %s\n", g_type_name (G_TYPE_FROM_INSTANCE (widget)));
*/
}
static void
-gtk_widget_propagate_state (GtkWidget *widget,
- GtkStateData *data)
+gtk_widget_propagate_state (GtkWidget *widget,
+ GtkStateData *data)
{
GtkWidgetPrivate *priv = widget->priv;
- guint8 old_state = gtk_widget_get_state (widget);
- guint8 old_saved_state = priv->saved_state;
+ GtkStateFlags new_flags, old_flags = priv->state_flags;
+ GtkStateType old_state;
- /* don't call this function with state==GTK_STATE_INSENSITIVE,
- * parent_sensitive==TRUE on a sensitive widget
- */
+ old_state = gtk_widget_get_state (widget);
+ if (!priv->parent_sensitive)
+ old_flags |= GTK_STATE_FLAG_INSENSITIVE;
priv->parent_sensitive = data->parent_sensitive;
- if (gtk_widget_is_sensitive (widget))
- {
- if (data->state_restoration)
- priv->state = priv->saved_state;
- else
- priv->state = data->state;
- }
- else
+ switch (data->operation)
{
- if (!data->state_restoration)
- {
- if (data->state != GTK_STATE_INSENSITIVE)
- priv->saved_state = data->state;
- }
- else if (gtk_widget_get_state (widget) != GTK_STATE_INSENSITIVE)
- priv->saved_state = gtk_widget_get_state (widget);
- priv->state = GTK_STATE_INSENSITIVE;
+ case STATE_CHANGE_REPLACE:
+ priv->state_flags = data->flags;
+ break;
+ case STATE_CHANGE_SET:
+ priv->state_flags |= data->flags;
+ break;
+ case STATE_CHANGE_UNSET:
+ priv->state_flags &= ~(data->flags);
+ break;
}
if (gtk_widget_is_focus (widget) && !gtk_widget_is_sensitive (widget))
GtkWidget *window;
window = gtk_widget_get_toplevel (widget);
+
if (window && gtk_widget_is_toplevel (window))
- gtk_window_set_focus (GTK_WINDOW (window), NULL);
+ gtk_window_set_focus (GTK_WINDOW (window), NULL);
}
- if (old_state != gtk_widget_get_state (widget) ||
- old_saved_state != priv->saved_state)
+ new_flags = gtk_widget_get_state_flags (widget);
+
+ if (old_flags != new_flags)
{
g_object_ref (widget);
if (!gtk_widget_is_sensitive (widget) && gtk_widget_has_grab (widget))
- gtk_grab_remove (widget);
+ gtk_grab_remove (widget);
g_signal_emit (widget, widget_signals[STATE_CHANGED], 0, old_state);
+ g_signal_emit (widget, widget_signals[STATE_FLAGS_CHANGED], 0, old_flags);
if (!priv->shadowed)
{
if (!gtk_widget_is_sensitive (widget))
_gtk_widget_synthesize_crossing (widget, NULL, d->data,
GDK_CROSSING_STATE_CHANGED);
- else if (old_state == GTK_STATE_INSENSITIVE)
+ else if (old_flags & GTK_STATE_FLAG_INSENSITIVE)
_gtk_widget_synthesize_crossing (NULL, widget, d->data,
GDK_CROSSING_STATE_CHANGED);
}
if (GTK_IS_CONTAINER (widget))
- {
- data->parent_sensitive = (gtk_widget_is_sensitive (widget) != FALSE);
- if (data->use_forall)
- gtk_container_forall (GTK_CONTAINER (widget),
- (GtkCallback) gtk_widget_propagate_state,
- data);
- else
- gtk_container_foreach (GTK_CONTAINER (widget),
- (GtkCallback) gtk_widget_propagate_state,
- data);
- }
+ {
+ data->parent_sensitive = gtk_widget_is_sensitive (widget);
+
+ /* Do not propagate insensitive state further */
+ data->flags &= ~(GTK_STATE_FLAG_INSENSITIVE | GTK_STATE_FLAG_FOCUSED);
+
+ if (data->use_forall)
+ gtk_container_forall (GTK_CONTAINER (widget),
+ (GtkCallback) gtk_widget_propagate_state,
+ data);
+ else
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ (GtkCallback) gtk_widget_propagate_state,
+ data);
+ }
+
+ /* Trigger state change transitions for the widget */
+ if (priv->context &&
+ gtk_widget_get_mapped (widget))
+ {
+ gint diff, flag = 1;
+
+ diff = old_flags ^ new_flags;
+
+ while (diff != 0)
+ {
+ if ((diff & flag) != 0)
+ {
+ gboolean target;
+
+ target = ((new_flags & flag) != 0);
+ _gtk_widget_notify_state_change (widget, flag, target);
+
+ diff &= ~flag;
+ }
+
+ flag <<= 1;
+ }
+ }
+
g_object_unref (widget);
}
}
}
-static void
-gtk_reset_shapes_recurse (GtkWidget *widget,
- GdkWindow *window)
-{
- gpointer data;
- GList *list;
-
- gdk_window_get_user_data (window, &data);
- if (data != widget)
- return;
-
- gdk_window_shape_combine_region (window, NULL, 0, 0);
- for (list = gdk_window_peek_children (window); list; list = list->next)
- gtk_reset_shapes_recurse (widget, list->data);
-}
-
-/**
- * gtk_widget_reset_shapes:
- * @widget: a #GtkWidget
- *
- * Recursively resets the shape on this widget and its descendants.
- **/
-void
-gtk_widget_reset_shapes (GtkWidget *widget)
-{
- GtkWidgetPrivate *priv;
-
- g_return_if_fail (GTK_IS_WIDGET (widget));
- g_return_if_fail (gtk_widget_get_realized (widget));
-
- priv = widget->priv;
-
- if (!priv->has_shape_mask)
- gtk_reset_shapes_recurse (widget, priv->window);
-}
-
/* style properties
*/
/**
- * gtk_widget_class_install_style_property_parser:
+ * gtk_widget_class_install_style_property_parser: (skip)
* @klass: a #GtkWidgetClass
* @pspec: the #GParamSpec for the style property
* @parser: the parser for the style property
* gtk_widget_class_find_style_property:
* @klass: a #GtkWidgetClass
* @property_name: the name of the style property to find
- * @returns: (allow-none): the #GParamSpec of the style property or %NULL if @class has no
- * style property with that name.
+ * @returns: (transfer none): the #GParamSpec of the style property or
+ * %NULL if @class has no style property with that name.
*
* Finds a style property of a widget class by name.
*
* gtk_widget_class_list_style_properties:
* @klass: a #GtkWidgetClass
* @n_properties: location to return the number of style properties found
- * @returns: an newly allocated array of #GParamSpec*. The array must
- * be freed with g_free().
+ * @returns: (array length=n_properties) (transfer container): an
+ * newly allocated array of #GParamSpec*. The array must be
+ * freed with g_free().
*
* Returns all style properties of a widget class.
*
{
GtkStyleContext *context;
const GValue *peek_value;
+ GtkStateFlags state;
context = gtk_widget_get_style_context (widget);
+ state = gtk_widget_get_state_flags (widget);
+
peek_value = _gtk_style_context_peek_style_property (context,
G_OBJECT_TYPE (widget),
- pspec);
+ state, pspec);
/* auto-conversion of the caller's value type
*/
va_list var_args)
{
GtkStyleContext *context;
+ GtkStateFlags state;
const gchar *name;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_object_ref (widget);
context = gtk_widget_get_style_context (widget);
+ state = gtk_widget_get_state_flags (widget);
name = first_property_name;
while (name)
peek_value = _gtk_style_context_peek_style_property (context,
G_OBJECT_TYPE (widget),
- pspec);
+ state, pspec);
G_VALUE_LCOPY (peek_value, var_args, 0, &error);
if (error)
/**
* gtk_widget_path:
* @widget: a #GtkWidget
- * @path_length: (out) (allow-none): location to store length of the path, or %NULL
- * @path: (out) (allow-none): location to store allocated path string, or %NULL
- * @path_reversed: (out) (allow-none): location to store allocated reverse path string, or %NULL
+ * @path_length: (out) (allow-none): location to store length of the path,
+ * or %NULL
+ * @path: (out) (allow-none): location to store allocated path string,
+ * or %NULL
+ * @path_reversed: (out) (allow-none): location to store allocated reverse
+ * path string, or %NULL
*
* Obtains the full path to @widget. The path is simply the name of a
* widget and all its parents in the container hierarchy, separated by
* file. @path_reversed_p fills in the path in reverse order,
* i.e. starting with @widget's name instead of starting with the name
* of @widget's outermost ancestor.
+ *
+ * Deprecated:3.0: Use gtk_widget_get_path() instead
**/
void
gtk_widget_path (GtkWidget *widget,
/**
* gtk_widget_class_path:
* @widget: a #GtkWidget
- * @path_length: (out) (allow-none): location to store the length of the class path, or %NULL
- * @path: (out) (allow-none): location to store the class path as an allocated string, or %NULL
- * @path_reversed: (out) (allow-none): location to store the reverse class path as an allocated
- * string, or %NULL
+ * @path_length: (out) (allow-none): location to store the length of the
+ * class path, or %NULL
+ * @path: (out) (allow-none): location to store the class path as an
+ * allocated string, or %NULL
+ * @path_reversed: (out) (allow-none): location to store the reverse
+ * class path as an allocated string, or %NULL
*
* Same as gtk_widget_path(), but always uses the name of a widget's type,
* never uses a custom name set with gtk_widget_set_name().
*
+ * Deprecated:3.0: Use gtk_widget_get_path() instead
**/
void
gtk_widget_class_path (GtkWidget *widget,
*
* There are few reasons to use this function, but it's here
* for completeness and consistency.
- *
- * Return value: whether hexpand has been explicitly set
*/
void
gtk_widget_set_hexpand_set (GtkWidget *widget,
* be used.
*
* See gtk_widget_set_hexpand_set() for more detail.
- *
- * Return value: whether vexpand has been explicitly set
*/
void
gtk_widget_set_vexpand_set (GtkWidget *widget,
* Returns %TRUE if @widget is multiple pointer aware. See
* gtk_widget_set_support_multidevice() for more information.
*
- * Returns: %TRUE is @widget is multidevice aware.
+ * Returns: %TRUE if @widget is multidevice aware.
**/
gboolean
gtk_widget_get_support_multidevice (GtkWidget *widget)
g_return_if_fail (GTK_IS_WIDGET (widget));
priv = widget->priv;
-
- if (support_multidevice)
- {
- priv->multidevice = TRUE;
- gtk_widget_set_extension_events (widget, GDK_EXTENSION_EVENTS_ALL);
- }
- else
- {
- priv->multidevice = FALSE;
- gtk_widget_set_extension_events (widget, GDK_EXTENSION_EVENTS_NONE);
- }
+ priv->multidevice = (support_multidevice == TRUE);
if (gtk_widget_get_realized (widget))
gdk_window_set_support_multidevice (priv->window, support_multidevice);
gboolean has_focus)
{
widget->priv->has_focus = has_focus;
+
+ if (has_focus)
+ gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_FOCUSED, FALSE);
+ else
+ gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_FOCUSED);
}
/**
widget->priv->height_request_needed = height_request_needed;
}
+/**
+ * gtk_widget_get_path:
+ * @widget: a #GtkWidget
+ *
+ * Returns the #GtkWidgetPath representing @widget, if the widget
+ * is not connected to a toplevel widget, a partial path will be
+ * created.
+ *
+ * Returns: (transfer none): The #GtkWidgetPath representing @widget
+ **/
GtkWidgetPath *
gtk_widget_get_path (GtkWidget *widget)
{
- GtkStyleContext *context;
- GtkWidgetPath *path;
- GtkWidget *parent;
- GList *regions, *reg;
-
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- g_return_val_if_fail ((widget->parent || gtk_widget_is_toplevel (widget)), NULL);
- parent = widget->priv->parent;
+ /* As strange as it may seem, this may happen on object construction.
+ * init() implementations of parent types may eventually call this function,
+ * each with its corresponding GType, which could leave a child
+ * implementation with a wrong widget type in the widget path
+ */
+ if (widget->priv->path &&
+ G_OBJECT_TYPE (widget) != gtk_widget_path_get_object_type (widget->priv->path))
+ {
+ gtk_widget_path_free (widget->priv->path);
+ widget->priv->path = NULL;
+ }
+
+ if (!widget->priv->path)
+ {
+ GtkWidget *parent;
+ guint pos;
+
+ parent = widget->priv->parent;
- path = gtk_widget_path_new ();
- gtk_widget_path_prepend_type (path, G_OBJECT_TYPE (widget));
- regions = reg = NULL;
+ if (parent)
+ widget->priv->path = gtk_container_get_path_for_child (GTK_CONTAINER (parent), widget);
+ else
+ {
+ /* Widget is either toplevel or unparented, treat both
+ * as toplevels style wise, since there are situations
+ * where style properties might be retrieved on that
+ * situation.
+ */
+ widget->priv->path = gtk_widget_path_new ();
+ }
- if (widget->priv->name)
- gtk_widget_path_iter_set_name (path, 0, widget->priv->name);
+ pos = gtk_widget_path_append_type (widget->priv->path, G_OBJECT_TYPE (widget));
- context = g_object_get_qdata (G_OBJECT (widget),
- quark_style_context);
+ if (widget->priv->name)
+ gtk_widget_path_iter_set_name (widget->priv->path, pos, widget->priv->name);
- if (context)
- regions = reg = gtk_style_context_list_child_classes (context);
+ if (widget->priv->context)
+ {
+ GList *classes, *l;
- while (reg)
- {
- GtkChildClassFlags flags;
- const gchar *region_name;
+ /* Also add any persistent classes in
+ * the style context the widget path
+ */
+ classes = gtk_style_context_list_classes (widget->priv->context);
- region_name = reg->data;
- reg = reg->next;
+ for (l = classes; l; l = l->next)
+ gtk_widget_path_iter_add_class (widget->priv->path, pos, l->data);
- gtk_style_context_has_child_class (context, region_name, &flags);
- gtk_widget_path_iter_add_region (path, 0, region_name, flags);
- }
+ gtk_style_context_set_path (widget->priv->context,
+ widget->priv->path);
- g_list_free (regions);
+ g_list_free (classes);
+ }
+ }
- while (parent)
- {
- guint position;
+ return widget->priv->path;
+}
- position = gtk_widget_path_prepend_type (path, G_OBJECT_TYPE (parent));
+static void
+style_context_changed (GtkStyleContext *context,
+ gpointer user_data)
+{
+ GtkWidget *widget = user_data;
- if (parent->priv->name)
- gtk_widget_path_iter_set_name (path, position, parent->priv->name);
+ gtk_widget_update_pango_context (widget);
- parent = parent->priv->parent;
+ if (gtk_widget_get_realized (widget))
+ g_signal_emit (widget, widget_signals[STYLE_UPDATED], 0);
+ else
+ {
+ /* Compress all style updates so it
+ * is only emitted once pre-realize.
+ */
+ widget->priv->style_update_pending = TRUE;
}
- return path;
+ if (widget->priv->anchored)
+ gtk_widget_queue_resize (widget);
}
+/**
+ * gtk_widget_get_style_context:
+ * @widget: a #GtkWidget
+ *
+ * Returns the style context associated to @widget.
+ *
+ * Returns: (transfer none): a #GtkStyleContext. This memory is owned by @widget and
+ * must not be freed.
+ **/
GtkStyleContext *
gtk_widget_get_style_context (GtkWidget *widget)
{
- GtkStyleContext *context;
-
g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);
- context = g_object_get_qdata (G_OBJECT (widget),
- quark_style_context);
-
- if (G_UNLIKELY (!context))
+ if (G_UNLIKELY (!widget->priv->context))
{
- static GtkCssProvider *css_provider = NULL;
-
- context = g_object_new (GTK_TYPE_STYLE_CONTEXT, NULL);
- g_object_set_qdata_full (G_OBJECT (widget),
- quark_style_context, context,
- (GDestroyNotify) g_object_unref);
-
- /* Add provider for user file */
- if (G_UNLIKELY (!css_provider))
- {
- GFile *home_dir, *css_file;
- gchar *filename;
-
- css_provider = gtk_css_provider_new ();
- home_dir = g_file_new_for_path (g_get_home_dir ());
-
- filename = g_strdup_printf (".gtk-%d.0.css", GTK_MAJOR_VERSION);
- css_file = g_file_get_child (home_dir, filename);
- g_free (filename);
-
- if (g_file_query_exists (css_file, NULL))
- gtk_css_provider_load_from_file (css_provider, css_file, NULL);
-
- g_object_unref (home_dir);
- g_object_unref (css_file);
- }
-
- gtk_style_context_add_provider (context,
- GTK_STYLE_PROVIDER (css_provider),
- GTK_STYLE_PROVIDER_PRIORITY_USER);
+ widget->priv->context = g_object_new (GTK_TYPE_STYLE_CONTEXT,
+ "direction", gtk_widget_get_direction (widget),
+ NULL);
- if (widget->parent ||
- gtk_widget_is_toplevel (widget))
- {
- GtkWidgetPath *path;
+ g_signal_connect (widget->priv->context, "changed",
+ G_CALLBACK (style_context_changed), widget);
- path = gtk_widget_get_path (widget);
- gtk_style_context_set_path (context, path);
- gtk_widget_path_free (path);
+ gtk_style_context_set_screen (widget->priv->context,
+ gtk_widget_get_screen (widget));
- gtk_style_context_set_screen (context,
- gtk_widget_get_screen (widget));
- }
+ _gtk_widget_update_path (widget);
+ gtk_style_context_set_path (widget->priv->context,
+ widget->priv->path);
+ }
+ else
+ {
+ /* Force widget path regeneration if needed, the
+ * context will be updated within this function.
+ */
+ gtk_widget_get_path (widget);
}
- return context;
+ return widget->priv->context;
}