summaryrefslogtreecommitdiff
path: root/openbox
diff options
context:
space:
mode:
Diffstat (limited to 'openbox')
-rw-r--r--openbox/client.c58
-rw-r--r--openbox/client.h4
-rw-r--r--openbox/event.c3
-rw-r--r--openbox/prop.c1
-rw-r--r--openbox/prop.h1
-rw-r--r--openbox/screen.c3
-rw-r--r--openbox/startupnotify.c10
-rw-r--r--openbox/startupnotify.h3
8 files changed, 67 insertions, 16 deletions
diff --git a/openbox/client.c b/openbox/client.c
index 27e63292..bfb9f790 100644
--- a/openbox/client.c
+++ b/openbox/client.c
@@ -57,8 +57,10 @@ typedef struct
gpointer data;
} Destructor;
-GList *client_list = NULL;
-GSList *client_destructors = NULL;
+GList *client_list = NULL;
+
+static GSList *client_destructors = NULL;
+static Time client_last_user_time = CurrentTime;
static void client_get_all(ObClient *self);
static void client_toggle_border(ObClient *self, gboolean show);
@@ -298,7 +300,7 @@ void client_manage(Window window)
client_get_all(self);
client_restore_session_state(self);
- sn_app_started(self->startup_id, self->class);
+ self->user_time = sn_app_started(self->startup_id, self->class);
/* update the focus lists, do this before the call to change_state or
it can end up in the list twice! */
@@ -459,15 +461,26 @@ void client_manage(Window window)
clicking a window to activate is. so keep the new window out of the way
but do focus it. */
if (activate) {
- /* if using focus_delay, stop the timer now so that focus doesn't go
- moving on us */
- event_halt_focus_delay();
-
- client_focus(self);
- /* since focus can change the stacking orders, if we focus the window
- then the standard raise it gets is not enough, we need to queue one
- for after the focus change takes place */
- client_raise(self);
+ /* This is focus stealing prevention, if a user_time has been set */
+ if (self->user_time == CurrentTime ||
+ self->user_time > client_last_user_time)
+ {
+ /* if using focus_delay, stop the timer now so that focus doesn't
+ go moving on us */
+ event_halt_focus_delay();
+
+ client_focus(self);
+ /* since focus can change the stacking orders, if we focus the
+ window then the standard raise it gets is not enough, we need
+ to queue one for after the focus change takes place */
+ client_raise(self);
+ } else {
+ ob_debug("Focus stealing prevention activated for %s\n",
+ self->title);
+ /* if the client isn't focused, then hilite it so the user
+ knows it is there */
+ client_hilite(self, TRUE);
+ }
}
/* client_activate does this but we aret using it so we have to do it
@@ -857,6 +870,7 @@ static void client_get_all(ObClient *self)
client_update_sm_client_id(self);
client_update_strut(self);
client_update_icons(self);
+ client_update_user_time(self, FALSE);
}
static void client_get_startup_id(ObClient *self)
@@ -1804,6 +1818,26 @@ void client_update_icons(ObClient *self)
frame_adjust_icon(self->frame);
}
+void client_update_user_time(ObClient *self, gboolean new_event)
+{
+ guint32 time;
+
+ if (PROP_GET32(self->window, net_wm_user_time, cardinal, &time)) {
+ self->user_time = time;
+ /* we set this every time, not just when it grows, because in practice
+ sometimes time goes backwards! (ntpdate.. yay....) so.. if it goes
+ backward we don't want all windows to stop focusing. we'll just
+ assume noone is setting times older than the last one, cuz that
+ would be pretty stupid anyways
+ However! This is called when a window is mapped to get its user time
+ but it's an old number, it's not changing it from new user
+ interaction, so in that case, don't change the last user time.
+ */
+ if (new_event)
+ client_last_user_time = time;
+ }
+}
+
static void client_change_state(ObClient *self)
{
gulong state[2];
diff --git a/openbox/client.h b/openbox/client.h
index a5011cb6..cb6eed53 100644
--- a/openbox/client.h
+++ b/openbox/client.h
@@ -269,6 +269,8 @@ struct _ObClient
ObClientIcon *icons;
/*! The number of icons in icons */
guint nicons;
+
+ guint32 user_time;
};
struct _ObAppSettings
@@ -530,6 +532,8 @@ void client_update_class(ObClient *self);
void client_update_strut(ObClient *self);
/*! Updates the window's icons */
void client_update_icons(ObClient *self);
+/*! Updates the window's user time */
+void client_update_user_time(ObClient *self, gboolean new_event);
/*! Set up what decor should be shown on the window and what functions should
be allowed (ObClient::decorations and ObClient::functions).
diff --git a/openbox/event.c b/openbox/event.c
index 558872e8..9faf9403 100644
--- a/openbox/event.c
+++ b/openbox/event.c
@@ -1148,6 +1148,9 @@ static void event_handle_client(ObClient *client, XEvent *e)
else if (msgtype == prop_atoms.net_wm_icon) {
client_update_icons(client);
}
+ else if (msgtype == prop_atoms.net_wm_user_time) {
+ client_update_user_time(client, TRUE);
+ }
else if (msgtype == prop_atoms.sm_client_id) {
client_update_sm_client_id(client);
}
diff --git a/openbox/prop.c b/openbox/prop.c
index 977dbe95..686404d4 100644
--- a/openbox/prop.c
+++ b/openbox/prop.c
@@ -84,6 +84,7 @@ void prop_startup()
CREATE(net_wm_icon, "_NET_WM_ICON");
/* CREATE(net_wm_pid, "_NET_WM_PID"); */
CREATE(net_wm_allowed_actions, "_NET_WM_ALLOWED_ACTIONS");
+ CREATE(net_wm_user_time, "_NET_WM_USER_TIME");
CREATE(net_frame_extents, "_NET_FRAME_EXTENTS");
/* CREATE(net_wm_ping, "_NET_WM_PING"); */
diff --git a/openbox/prop.h b/openbox/prop.h
index 2c36b624..1931cb65 100644
--- a/openbox/prop.h
+++ b/openbox/prop.h
@@ -92,6 +92,7 @@ typedef struct Atoms {
Atom net_wm_icon;
/* Atom net_wm_pid; */
Atom net_wm_allowed_actions;
+ Atom net_wm_user_time;
Atom net_frame_extents;
/* application protocols */
diff --git a/openbox/screen.c b/openbox/screen.c
index c1c61ed5..a4dfb76e 100644
--- a/openbox/screen.c
+++ b/openbox/screen.c
@@ -204,7 +204,7 @@ gboolean screen_annex()
window, screen_support_win);
/* set the _NET_SUPPORTED_ATOMS hint */
- num_support = 53;
+ num_support = 54;
i = 0;
supported = g_new(gulong, num_support);
supported[i++] = prop_atoms.net_current_desktop;
@@ -258,6 +258,7 @@ gboolean screen_annex()
supported[i++] = prop_atoms.net_wm_state_demands_attention;
supported[i++] = prop_atoms.net_moveresize_window;
supported[i++] = prop_atoms.net_wm_moveresize;
+ supported[i++] = prop_atoms.net_wm_user_time;
supported[i++] = prop_atoms.net_frame_extents;
supported[i++] = prop_atoms.ob_wm_state_undecorated;
g_assert(i == num_support);
diff --git a/openbox/startupnotify.c b/openbox/startupnotify.c
index dbb633ef..1e5c45a8 100644
--- a/openbox/startupnotify.c
+++ b/openbox/startupnotify.c
@@ -24,7 +24,10 @@
void sn_startup(gboolean reconfig) {}
void sn_shutdown(gboolean reconfig) {}
gboolean sn_app_starting() { return FALSE; }
-void sn_app_started(gchar *wmclass) {}
+Time sn_app_started(const gchar *id, const gchar *wmclass)
+{
+ return CurrentTime;
+}
gboolean sn_get_desktop(gchar *id, guint *desktop) { return FALSE; }
#else
@@ -188,9 +191,10 @@ static void sn_event_func(SnMonitorEvent *ev, gpointer data)
screen_set_root_cursor();
}
-void sn_app_started(const gchar *id, const gchar *wmclass)
+Time sn_app_started(const gchar *id, const gchar *wmclass)
{
GSList *it;
+ Time t = CurrentTime;
for (it = sn_waits; it; it = g_slist_next(it)) {
ObWaitData *d = it->data;
@@ -201,9 +205,11 @@ void sn_app_started(const gchar *id, const gchar *wmclass)
(seqclass && wmclass && !strcmp(seqclass, wmclass)))
{
sn_startup_sequence_complete(d->seq);
+ t = sn_startup_sequence_get_timestamp(d->seq);
break;
}
}
+ return t;
}
gboolean sn_get_desktop(gchar *id, guint *desktop)
diff --git a/openbox/startupnotify.h b/openbox/startupnotify.h
index 1a6d47a1..cf238354 100644
--- a/openbox/startupnotify.h
+++ b/openbox/startupnotify.h
@@ -20,6 +20,7 @@
#define ob__startupnotify_h
#include <glib.h>
+#include <X11/Xlib.h>
void sn_startup(gboolean reconfig);
void sn_shutdown(gboolean reconfig);
@@ -27,7 +28,7 @@ void sn_shutdown(gboolean reconfig);
gboolean sn_app_starting();
/*! Notify that an app has started */
-void sn_app_started(const gchar *id, const gchar *wmclass);
+Time sn_app_started(const gchar *id, const gchar *wmclass);
/*! Get the desktop requested via the startup-notiication protocol if one
was requested */