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.
This commit is contained in:
parent
bd19fd06db
commit
9d6e390765
8 changed files with 66 additions and 15 deletions
|
@ -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();
|
||||
/* 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 @@ 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];
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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"); */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue