diff --git a/gtk/gtkcssprovider.c b/gtk/gtkcssprovider.c index 555a4b523b..839fa7c596 100644 --- a/gtk/gtkcssprovider.c +++ b/gtk/gtkcssprovider.c @@ -2007,6 +2007,7 @@ parse_selector_pseudo_class (GtkCssScanner *scanner, { "inconsistent", 0, GTK_STATE_FLAG_INCONSISTENT }, { "focused", 0, GTK_STATE_FLAG_FOCUSED }, { "focus", 0, GTK_STATE_FLAG_FOCUSED }, + { "window-unfocused", 0, GTK_STATE_FLAG_WINDOW_UNFOCUSED }, { NULL, } }, nth_child_classes[] = { { "first", GTK_REGION_FIRST, 0 }, diff --git a/gtk/gtkcssselector.c b/gtk/gtkcssselector.c index 2abe0923a7..b3ccb44e47 100644 --- a/gtk/gtkcssselector.c +++ b/gtk/gtkcssselector.c @@ -153,7 +153,8 @@ _gtk_css_selector_print (const GtkCssSelector *selector, "selected", "insensitive", "inconsistent", - "focus" + "focus", + "window-unfocused" }; guint i; diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h index dbc0e90ea0..7045f922c2 100644 --- a/gtk/gtkenums.h +++ b/gtk/gtkenums.h @@ -842,6 +842,7 @@ typedef enum * @GTK_STATE_FLAG_INSENSITIVE: Widget is insensitive. * @GTK_STATE_FLAG_INCONSISTENT: Widget is inconsistent. * @GTK_STATE_FLAG_FOCUSED: Widget has the keyboard focus. + * @GTK_STATE_FLAG_WINDOW_UNFOCUSED: Widget's toplevel window is unfocused. * * Describes a widget state. */ @@ -853,7 +854,8 @@ typedef enum GTK_STATE_FLAG_SELECTED = 1 << 2, GTK_STATE_FLAG_INSENSITIVE = 1 << 3, 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; /** diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index b481f927d0..49e28fbf40 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -307,13 +307,14 @@ #define WIDGET_CLASS(w) GTK_WIDGET_GET_CLASS (w) +#define GTK_STATE_FLAGS_BITS 7 + struct _GtkWidgetPrivate { - /* The state of the widget. There are actually only - * 5 widget states (defined in "gtkenums.h") - * so 3 bits. + /* The state of the widget. Needs to be able to hold all GtkStateFlags bits + * (defined in "gtkenums.h"). */ - guint state_flags : 6; + guint state_flags : GTK_STATE_FLAGS_BITS; guint direction : 2; @@ -529,7 +530,7 @@ enum { struct _GtkStateData { - guint flags : 6; + guint flags : GTK_STATE_FLAGS_BITS; guint operation : 2; guint use_forall : 1; }; diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 25a5f9f076..0d245b3e2c 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -474,6 +474,8 @@ static void gtk_window_get_preferred_height (GtkWidget *widget, gint *minimum_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_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, 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)); else gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS); + + ensure_state_flag_window_unfocused (widget); } static gboolean @@ -5463,6 +5467,9 @@ gtk_window_state_event (GtkWidget *widget, { update_grip_visibility (GTK_WINDOW (widget)); + if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED) + ensure_state_flag_window_unfocused (widget); + return FALSE; } @@ -9618,3 +9625,21 @@ gtk_window_set_has_user_ref_count (GtkWindow *window, 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); +}