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:
Dana Jansens 2007-03-11 02:06:34 +00:00
parent bd19fd06db
commit 9d6e390765
8 changed files with 66 additions and 15 deletions

View file

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

View file

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

View file

@ -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);
}

View file

@ -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"); */

View file

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

View file

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

View file

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

View file

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