gtk: Add a GTK_STATE_FLAG_WINDOW_UNFOCUSED widget state flag

This allows themes to style widgets differently according to whether the
toplevel window they are in is presented as focused.

https://bugzilla.gnome.org/show_bug.cgi?id=661428
This commit is contained in:
Rui Matos 2011-10-28 23:45:38 +01:00
parent 95648fd194
commit 70f87b8bd5
5 changed files with 37 additions and 7 deletions

View File

@ -2007,6 +2007,7 @@ parse_selector_pseudo_class (GtkCssScanner *scanner,
{ "inconsistent", 0, GTK_STATE_FLAG_INCONSISTENT }, { "inconsistent", 0, GTK_STATE_FLAG_INCONSISTENT },
{ "focused", 0, GTK_STATE_FLAG_FOCUSED }, { "focused", 0, GTK_STATE_FLAG_FOCUSED },
{ "focus", 0, GTK_STATE_FLAG_FOCUSED }, { "focus", 0, GTK_STATE_FLAG_FOCUSED },
{ "window-unfocused", 0, GTK_STATE_FLAG_WINDOW_UNFOCUSED },
{ NULL, } { NULL, }
}, nth_child_classes[] = { }, nth_child_classes[] = {
{ "first", GTK_REGION_FIRST, 0 }, { "first", GTK_REGION_FIRST, 0 },

View File

@ -153,7 +153,8 @@ _gtk_css_selector_print (const GtkCssSelector *selector,
"selected", "selected",
"insensitive", "insensitive",
"inconsistent", "inconsistent",
"focus" "focus",
"window-unfocused"
}; };
guint i; guint i;

View File

@ -842,6 +842,7 @@ typedef enum
* @GTK_STATE_FLAG_INSENSITIVE: Widget is insensitive. * @GTK_STATE_FLAG_INSENSITIVE: Widget is insensitive.
* @GTK_STATE_FLAG_INCONSISTENT: Widget is inconsistent. * @GTK_STATE_FLAG_INCONSISTENT: Widget is inconsistent.
* @GTK_STATE_FLAG_FOCUSED: Widget has the keyboard focus. * @GTK_STATE_FLAG_FOCUSED: Widget has the keyboard focus.
* @GTK_STATE_FLAG_WINDOW_UNFOCUSED: Widget's toplevel window is unfocused.
* *
* Describes a widget state. * Describes a widget state.
*/ */
@ -853,7 +854,8 @@ typedef enum
GTK_STATE_FLAG_SELECTED = 1 << 2, GTK_STATE_FLAG_SELECTED = 1 << 2,
GTK_STATE_FLAG_INSENSITIVE = 1 << 3, GTK_STATE_FLAG_INSENSITIVE = 1 << 3,
GTK_STATE_FLAG_INCONSISTENT = 1 << 4, GTK_STATE_FLAG_INCONSISTENT = 1 << 4,
GTK_STATE_FLAG_FOCUSED = 1 << 5 GTK_STATE_FLAG_FOCUSED = 1 << 5,
GTK_STATE_FLAG_WINDOW_UNFOCUSED = 1 << 6
} GtkStateFlags; } GtkStateFlags;
/** /**

View File

@ -307,13 +307,14 @@
#define WIDGET_CLASS(w) GTK_WIDGET_GET_CLASS (w) #define WIDGET_CLASS(w) GTK_WIDGET_GET_CLASS (w)
#define GTK_STATE_FLAGS_BITS 7
struct _GtkWidgetPrivate struct _GtkWidgetPrivate
{ {
/* The state of the widget. There are actually only /* The state of the widget. Needs to be able to hold all GtkStateFlags bits
* 5 widget states (defined in "gtkenums.h") * (defined in "gtkenums.h").
* so 3 bits.
*/ */
guint state_flags : 6; guint state_flags : GTK_STATE_FLAGS_BITS;
guint direction : 2; guint direction : 2;
@ -529,7 +530,7 @@ enum {
struct _GtkStateData struct _GtkStateData
{ {
guint flags : 6; guint flags : GTK_STATE_FLAGS_BITS;
guint operation : 2; guint operation : 2;
guint use_forall : 1; guint use_forall : 1;
}; };

View File

@ -474,6 +474,8 @@ static void gtk_window_get_preferred_height (GtkWidget *widget,
gint *minimum_size, gint *minimum_size,
gint *natural_size); gint *natural_size);
static void ensure_state_flag_window_unfocused (GtkWidget *widget);
G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN, G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN,
G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
gtk_window_buildable_interface_init)) gtk_window_buildable_interface_init))
@ -4817,6 +4819,8 @@ gtk_window_map (GtkWidget *widget)
gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent)); gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent));
else else
gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS); gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS);
ensure_state_flag_window_unfocused (widget);
} }
static gboolean static gboolean
@ -5463,6 +5467,9 @@ gtk_window_state_event (GtkWidget *widget,
{ {
update_grip_visibility (GTK_WINDOW (widget)); update_grip_visibility (GTK_WINDOW (widget));
if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED)
ensure_state_flag_window_unfocused (widget);
return FALSE; return FALSE;
} }
@ -9618,3 +9625,21 @@ gtk_window_set_has_user_ref_count (GtkWindow *window,
window->priv->has_user_ref_count = setting; window->priv->has_user_ref_count = setting;
} }
static void
ensure_state_flag_window_unfocused (GtkWidget *widget)
{
GdkWindow *window;
gboolean window_focused = TRUE;
window = gtk_widget_get_window (widget);
window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED;
if (!window_focused)
gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED, FALSE);
else
gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED);
gtk_widget_queue_draw (widget);
}