window: add an appears-focused property, redraw shadows when it changes

We need to redraw a window's shadow any time the value of
meta_window_appears_focused() changes. So make that into a property so
we can get notifications on it.

https://bugzilla.gnome.org/show_bug.cgi?id=636904
This commit is contained in:
Dan Winship 2011-03-24 21:36:47 -04:00
parent db055c6029
commit f464b85ffc
4 changed files with 89 additions and 40 deletions

View File

@ -373,6 +373,14 @@ window_decorated_notify (MetaWindow *mw,
meta_window_actor_constructed (G_OBJECT (self)); meta_window_actor_constructed (G_OBJECT (self));
} }
static void
window_appears_focused_notify (MetaWindow *mw,
GParamSpec *arg1,
gpointer data)
{
clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
}
static void static void
meta_window_actor_constructed (GObject *object) meta_window_actor_constructed (GObject *object)
{ {
@ -422,6 +430,8 @@ meta_window_actor_constructed (GObject *object)
g_signal_connect (priv->window, "notify::decorated", g_signal_connect (priv->window, "notify::decorated",
G_CALLBACK (window_decorated_notify), self); G_CALLBACK (window_decorated_notify), self);
g_signal_connect (priv->window, "notify::appears-focused",
G_CALLBACK (window_appears_focused_notify), self);
} }
else else
{ {

View File

@ -253,11 +253,9 @@ struct _MetaWindow
/* EWHH demands attention flag */ /* EWHH demands attention flag */
guint wm_state_demands_attention : 1; guint wm_state_demands_attention : 1;
/* this flag tracks receipt of focus_in focus_out and /* this flag tracks receipt of focus_in focus_out */
* determines whether we draw the focus
*/
guint has_focus : 1; guint has_focus : 1;
/* Have we placed this window? */ /* Have we placed this window? */
guint placed : 1; guint placed : 1;
@ -389,6 +387,9 @@ struct _MetaWindow
MetaGroup *group; MetaGroup *group;
GObject *compositor_private; GObject *compositor_private;
/* Focused window that is (directly or indirectly) attached to this one */
MetaWindow *attached_focus_window;
}; };
struct _MetaWindowClass struct _MetaWindowClass
@ -634,4 +635,7 @@ void meta_window_update_net_wm_type (MetaWindow *window);
void meta_window_update_monitor (MetaWindow *window); void meta_window_update_monitor (MetaWindow *window);
void meta_window_update_on_all_workspaces (MetaWindow *window); void meta_window_update_on_all_workspaces (MetaWindow *window);
void meta_window_propagate_focus_appearance (MetaWindow *window,
gboolean focused);
#endif #endif

View File

@ -1466,6 +1466,9 @@ reload_transient_for (MetaWindow *window,
MetaPropValue *value, MetaPropValue *value,
gboolean initial) gboolean initial)
{ {
if (window->has_focus && window->xtransient_for != None)
meta_window_propagate_focus_appearance (window, FALSE);
window->xtransient_for = None; window->xtransient_for = None;
if (value->type != META_PROP_VALUE_INVALID) if (value->type != META_PROP_VALUE_INVALID)
@ -1509,6 +1512,9 @@ reload_transient_for (MetaWindow *window,
if (!window->constructing && !window->override_redirect) if (!window->constructing && !window->override_redirect)
meta_window_queue (window, META_QUEUE_MOVE_RESIZE); meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
if (window->has_focus && window->xtransient_for != None)
meta_window_propagate_focus_appearance (window, TRUE);
} }
/** /**

View File

@ -154,7 +154,8 @@ enum {
PROP_USER_TIME, PROP_USER_TIME,
PROP_DEMANDS_ATTENTION, PROP_DEMANDS_ATTENTION,
PROP_URGENT, PROP_URGENT,
PROP_MUTTER_HINTS PROP_MUTTER_HINTS,
PROP_APPEARS_FOCUSED
}; };
enum enum
@ -239,6 +240,9 @@ meta_window_get_property(GObject *object,
case PROP_MUTTER_HINTS: case PROP_MUTTER_HINTS:
g_value_set_string (value, win->mutter_hints); g_value_set_string (value, win->mutter_hints);
break; break;
case PROP_APPEARS_FOCUSED:
g_value_set_boolean (value, meta_window_appears_focused (win));
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
@ -366,6 +370,14 @@ meta_window_class_init (MetaWindowClass *klass)
"Contents of the _MUTTER_HINTS property of this window", "Contents of the _MUTTER_HINTS property of this window",
NULL, NULL,
G_PARAM_READABLE)); G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_APPEARS_FOCUSED,
g_param_spec_boolean ("appears-focused",
"Appears focused",
"Whether the window is drawn as being focused",
FALSE,
G_PARAM_READABLE));
window_signals[WORKSPACE_CHANGED] = window_signals[WORKSPACE_CHANGED] =
g_signal_new ("workspace-changed", g_signal_new ("workspace-changed",
G_TYPE_FROM_CLASS (object_class), G_TYPE_FROM_CLASS (object_class),
@ -856,6 +868,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->frame = NULL; window->frame = NULL;
window->has_focus = FALSE; window->has_focus = FALSE;
window->attached_focus_window = NULL;
window->maximized_horizontally = FALSE; window->maximized_horizontally = FALSE;
window->maximized_vertically = FALSE; window->maximized_vertically = FALSE;
@ -1488,6 +1501,7 @@ meta_window_unmanage (MetaWindow *window,
meta_workspace_focus_default_window (window->screen->active_workspace, meta_workspace_focus_default_window (window->screen->active_workspace,
window, window,
timestamp); timestamp);
meta_window_propagate_focus_appearance (window, FALSE);
} }
else if (window->display->expected_focus_window == window) else if (window->display->expected_focus_window == window)
{ {
@ -6359,20 +6373,46 @@ meta_window_client_message (MetaWindow *window,
return FALSE; return FALSE;
} }
static void void
check_ancestor_focus_appearance (MetaWindow *window) meta_window_propagate_focus_appearance (MetaWindow *window,
gboolean focused)
{ {
MetaWindow *parent = meta_window_get_transient_for (window); MetaWindow *child, *parent;
if (!meta_prefs_get_attach_modal_dialogs ()) if (!meta_prefs_get_attach_modal_dialogs ())
return; return;
if (window->type != META_WINDOW_MODAL_DIALOG || !parent || parent == window) child = window;
return; parent = meta_window_get_transient_for (child);
if (parent->frame) while (child->type == META_WINDOW_MODAL_DIALOG && parent)
meta_frame_queue_draw (parent->frame); {
gboolean child_focus_state_changed;
check_ancestor_focus_appearance (parent); if (focused)
{
if (parent->attached_focus_window == window)
break;
child_focus_state_changed = (parent->attached_focus_window == NULL);
parent->attached_focus_window = window;
}
else
{
if (parent->attached_focus_window != window)
break;
child_focus_state_changed = (parent->attached_focus_window != NULL);
parent->attached_focus_window = NULL;
}
if (child_focus_state_changed && !parent->has_focus)
{
g_object_notify (G_OBJECT (parent), "appears-focused");
if (parent->frame)
meta_frame_queue_draw (parent->frame);
}
child = parent;
parent = meta_window_get_transient_for (child);
}
} }
gboolean gboolean
@ -6517,11 +6557,16 @@ meta_window_notify_focus (MetaWindow *window,
!meta_prefs_get_raise_on_click()) !meta_prefs_get_raise_on_click())
meta_display_ungrab_focus_window_button (window->display, window); meta_display_ungrab_focus_window_button (window->display, window);
/* parent window become active. */
check_ancestor_focus_appearance (window);
g_signal_emit (window, window_signals[FOCUS], 0); g_signal_emit (window, window_signals[FOCUS], 0);
g_object_notify (G_OBJECT (window->display), "focus-window"); g_object_notify (G_OBJECT (window->display), "focus-window");
if (!window->attached_focus_window)
{
g_object_notify (G_OBJECT (window), "appears-focused");
if (window->frame)
meta_frame_queue_draw (window->frame);
}
meta_window_propagate_focus_appearance (window, TRUE);
} }
} }
else if (event->type == FocusOut || else if (event->type == FocusOut ||
@ -6549,11 +6594,14 @@ meta_window_notify_focus (MetaWindow *window,
window->display->focus_window = NULL; window->display->focus_window = NULL;
g_object_notify (G_OBJECT (window->display), "focus-window"); g_object_notify (G_OBJECT (window->display), "focus-window");
window->has_focus = FALSE; window->has_focus = FALSE;
/* parent window become inactive. */
check_ancestor_focus_appearance (window);
if (window->frame) if (!window->attached_focus_window)
meta_frame_queue_draw (window->frame); {
g_object_notify (G_OBJECT (window), "appears-focused");
if (window->frame)
meta_frame_queue_draw (window->frame);
}
meta_window_propagate_focus_appearance (window, FALSE);
meta_error_trap_push (window->display); meta_error_trap_push (window->display);
XUninstallColormap (window->display->xdisplay, XUninstallColormap (window->display->xdisplay,
@ -9692,16 +9740,6 @@ meta_window_get_frame (MetaWindow *window)
return window->frame; return window->frame;
} }
static gboolean
transient_has_focus (MetaWindow *window,
void *data)
{
if (window->type == META_WINDOW_MODAL_DIALOG && meta_window_appears_focused (window))
*((gboolean *)data) = TRUE;
return FALSE;
}
/** /**
* meta_window_appears_focused: * meta_window_appears_focused:
* @window: a #MetaWindow * @window: a #MetaWindow
@ -9715,16 +9753,7 @@ transient_has_focus (MetaWindow *window,
gboolean gboolean
meta_window_appears_focused (MetaWindow *window) meta_window_appears_focused (MetaWindow *window)
{ {
/* FIXME: meta_window_foreach_transient() iterates over all windows; we return window->has_focus || (window->attached_focus_window != NULL);
* should eat the complexity to cache a bit for this.
*/
if (!window->has_focus && meta_prefs_get_attach_modal_dialogs ())
{
gboolean focus = FALSE;
meta_window_foreach_transient (window, transient_has_focus, &focus);
return focus;
}
return window->has_focus;
} }
gboolean gboolean