all repos — openbox @ 9d6e3907650f4bc05ebf147aeec92573d7b88758

openbox fork - make it a bit more like ryudo

add the _NET_WM_USER_TIME property support. When focus_new is enabled, don't focus new windows if the user is doing something in another window since it launched. If we can tell when it launched, either from the _NET_WM_USER_TIME or from startup notification.
Dana Jansens danakj@orodu.net
commit

9d6e3907650f4bc05ebf147aeec92573d7b88758

parent

bd19fd06db8905ef835109414314ef928370a7d7

M openbox/client.copenbox/client.c

@@ -57,8 +57,10 @@ ObClientDestructor func;

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 @@

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 @@ a window maps since its not based on an action from the user like

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(); + /* 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); + 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 @@ client_update_class(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)

@@ -1802,6 +1816,26 @@ }

if (self->frame) 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)
M openbox/client.hopenbox/client.h

@@ -269,6 +269,8 @@ /*! Icons for the client as specified on the client window */

ObClientIcon *icons; /*! The number of icons in icons */ guint nicons; + + guint32 user_time; }; struct _ObAppSettings

@@ -530,6 +532,8 @@ /*! Updates the strut for the client */

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).
M openbox/event.copenbox/event.c

@@ -1148,6 +1148,9 @@ }

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); }
M openbox/prop.copenbox/prop.c

@@ -84,6 +84,7 @@ CREATE(net_wm_strut_partial, "_NET_WM_STRUT_PARTIAL");

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"); */
M openbox/prop.hopenbox/prop.h

@@ -92,6 +92,7 @@ Atom net_wm_strut_partial;

Atom net_wm_icon; /* Atom net_wm_pid; */ Atom net_wm_allowed_actions; + Atom net_wm_user_time; Atom net_frame_extents; /* application protocols */
M openbox/screen.copenbox/screen.c

@@ -204,7 +204,7 @@ PROP_SET32(screen_support_win, net_supporting_wm_check,

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 @@ supported[i++] = prop_atoms.net_wm_state_below;

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);
M openbox/startupnotify.copenbox/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 @@ if (change)

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 @@ if ((seqid && id && !strcmp(seqid, id)) ||

(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)
M openbox/startupnotify.hopenbox/startupnotify.h

@@ -20,6 +20,7 @@ #ifndef ob__startupnotify_h

#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 @@

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 */