[gnome-terminal] Turn off demands-attention state after unrealizing/realizing
- From: Owen Taylor <otaylor src gnome org>
- To: svn-commits-list gnome org
- Subject: [gnome-terminal] Turn off demands-attention state after unrealizing/realizing
- Date: Tue, 23 Jun 2009 13:16:05 -0400 (EDT)
commit f4a3c7e8665b32f0e9aed04def3784bb5c7a8d57
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Thu Jun 18 17:51:57 2009 -0400
Turn off demands-attention state after unrealizing/realizing
Unrealizing and realizing the window is likely to cause the window
to be focus-stealing-preventing and start blinking in the taskbar.
There's no obvious way to prevent this, so just turn off the
_NET_WM_STATE_DEMANDS_ATTENTION after the window is remapped.
http://bugzilla.gnome.org/show_bug.cgi?id=564648
src/terminal-util.c | 34 ++++++++++++++++++++++++++++++++++
src/terminal-util.h | 2 ++
src/terminal-window.c | 41 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 77 insertions(+), 0 deletions(-)
---
diff --git a/src/terminal-util.c b/src/terminal-util.c
index 587d1d7..fbaf372 100644
--- a/src/terminal-util.c
+++ b/src/terminal-util.c
@@ -984,4 +984,38 @@ terminal_util_x11_set_net_wm_desktop (GdkWindow *window,
XFlush (xdisplay);
}
+/* Asks the window manager to turn off the "demands attention" state on the window.
+ *
+ * This only works for windows that are currently window managed; if the window
+ * is unmapped (in the withdrawn state) it would be necessary to change _NET_WM_STATE
+ * directly.
+ */
+void
+terminal_util_x11_clear_demands_attention (GdkWindow *window)
+{
+ GdkScreen *screen = gdk_drawable_get_screen (window);
+ GdkDisplay *display = gdk_screen_get_display (screen);
+ XClientMessageEvent xclient;
+
+ memset (&xclient, 0, sizeof (xclient));
+ xclient.type = ClientMessage;
+ xclient.serial = 0;
+ xclient.send_event = True;
+ xclient.window = GDK_WINDOW_XWINDOW (window);
+ xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE");
+ xclient.format = 32;
+
+ xclient.data.l[0] = 0; /* _NET_WM_STATE_REMOVE */
+ xclient.data.l[1] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_STATE_DEMANDS_ATTENTION");
+ xclient.data.l[2] = 0;
+ xclient.data.l[3] = 0;
+ xclient.data.l[4] = 0;
+
+ XSendEvent (GDK_DISPLAY_XDISPLAY (display),
+ GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen)),
+ False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ (XEvent *)&xclient);
+}
+
#endif /* GDK_WINDOWING_X11 */
diff --git a/src/terminal-util.h b/src/terminal-util.h
index acfd437..71743f9 100644
--- a/src/terminal-util.h
+++ b/src/terminal-util.h
@@ -105,4 +105,6 @@ gboolean terminal_util_x11_get_net_wm_desktop (GdkWindow *window,
void terminal_util_x11_set_net_wm_desktop (GdkWindow *window,
guint32 desktop);
+void terminal_util_x11_clear_demands_attention (GdkWindow *window);
+
#endif /* TERMINAL_UTIL_H */
diff --git a/src/terminal-window.c b/src/terminal-window.c
index 95db45a..5d0345f 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -77,6 +77,11 @@ struct _TerminalWindowPrivate
/* Compositing manager integration */
guint have_argb_visual : 1;
+ /* Used to clear stray "demands attention" flashing on our window when we
+ * unmap and map it to switch to an ARGB visual.
+ */
+ guint clear_demands_attention : 1;
+
guint disposed : 1;
guint present_on_insert : 1;
@@ -1425,6 +1430,32 @@ terminal_window_realize (GtkWidget *widget)
GTK_WIDGET_CLASS (terminal_window_parent_class)->realize (widget);
}
+
+static gboolean
+terminal_window_map_event (GtkWidget *widget,
+ GdkEventAny *event)
+{
+ gboolean (* map_event) (GtkWidget *, GdkEventAny *) =
+ GTK_WIDGET_CLASS (terminal_window_parent_class)->map_event;
+
+ TerminalWindow *window = TERMINAL_WINDOW (widget);
+ TerminalWindowPrivate *priv = window->priv;
+
+ if (priv->clear_demands_attention)
+ {
+#ifdef GDK_WINDOWING_X11
+ terminal_util_x11_clear_demands_attention (widget->window);
+#endif
+
+ priv->clear_demands_attention = FALSE;
+ }
+
+ if (map_event)
+ return map_event (widget, event);
+
+ return FALSE;
+}
+
static gboolean
terminal_window_state_event (GtkWidget *widget,
@@ -1513,6 +1544,15 @@ terminal_window_composited_changed_cb (GdkScreen *screen,
gtk_widget_show (widget);
if (have_desktop)
terminal_util_x11_set_net_wm_desktop (widget->window, desktop);
+
+ /* Mapping the window is likely to have set the "demands-attention" state.
+ * In particular, Metacity will always set the state if a window is mapped,
+ * is not given the focus (because of an old user time), and is covered
+ * by some other window. We have no way of preventing this, so we just
+ * wait for our window to be mapped, and then tell the window manager
+ * to turn off the bit. If it wasn't set, no harm.
+ */
+ priv->clear_demands_attention = TRUE;
}
}
@@ -1921,6 +1961,7 @@ terminal_window_class_init (TerminalWindowClass *klass)
widget_class->show = terminal_window_show;
widget_class->realize = terminal_window_realize;
+ widget_class->map_event = terminal_window_map_event;
widget_class->window_state_event = terminal_window_state_event;
widget_class->screen_changed = terminal_window_screen_changed;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]