From cdb108c76d20e8272bfbd15919e32e609d685322 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 9 May 2007 17:01:30 +0000 Subject: [PATCH] add support for _NET_WM_USER_TIME_WINDOW. round 1 ! ding. --- openbox/client.c | 73 ++++++++++++++++++++++++++++++++++++++++++++---- openbox/client.h | 10 +++++-- openbox/event.c | 33 +++++++++++----------- openbox/group.c | 10 +++---- openbox/group.h | 2 -- openbox/prop.c | 1 + openbox/prop.h | 1 + openbox/screen.c | 1 + openbox/window.c | 6 +++- 9 files changed, 106 insertions(+), 31 deletions(-) diff --git a/openbox/client.c b/openbox/client.c index 66ed0d9f..aac52e2d 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -62,6 +62,7 @@ typedef struct } ClientCallback; GList *client_list = NULL; +GHashTable *client_user_time_window_map; static GSList *client_destructors = NULL; @@ -94,15 +95,23 @@ static GSList *client_search_all_top_parents_internal(ObClient *self, gboolean bylayer, ObStackingLayer layer); +static guint window_hash(Window *w) { return *w; } +static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; } + void client_startup(gboolean reconfig) { if (reconfig) return; + client_user_time_window_map = g_hash_table_new((GHashFunc)window_hash, + (GEqualFunc)window_comp); client_set_list(); } void client_shutdown(gboolean reconfig) { + if (reconfig) return; + + g_hash_table_destroy(client_user_time_window_map); } void client_add_destructor(ObClientCallback func, gpointer data) @@ -503,6 +512,10 @@ void client_unmanage(ObClient *self) /* we dont want events no more. do this before hiding the frame so we don't generate more events */ XSelectInput(ob_display, self->window, NoEventMask); + if (self->user_time_window) { + XSelectInput(ob_display, self->user_time_window, NoEventMask); + g_hash_table_remove(client_user_time_window_map, &w); + } frame_hide(self->frame); /* flush to send the hide to the server quickly */ @@ -1002,7 +1015,9 @@ static void client_get_all(ObClient *self) client_update_title(self); client_update_strut(self); client_update_icons(self); - client_update_user_time(self); + client_update_user_time_window(self); + if (!self->user_time_window) /* check if this would have been called */ + client_update_user_time(self); client_update_icon_geometry(self); } @@ -2019,8 +2034,15 @@ void client_update_icons(ObClient *self) void client_update_user_time(ObClient *self) { guint32 time; + gboolean got = FALSE; + + if (self->user_time_window) + got = PROP_GET32(self->user_time_window, + net_wm_user_time, cardinal, &time); + if (!got) + got = PROP_GET32(self->window, net_wm_user_time, cardinal, &time); - if (PROP_GET32(self->window, net_wm_user_time, cardinal, &time)) { + if (got) { /* 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 @@ -2029,9 +2051,50 @@ void client_update_user_time(ObClient *self) */ self->user_time = time; - /* - ob_debug("window %s user time %u\n", self->title, time); - */ + /*ob_debug("window %s user time %u\n", self->title, time);*/ + } +} + +void client_update_user_time_window(ObClient *self) +{ + guint32 w; + ObClient *c; + + if (!PROP_GET32(self->window, net_wm_user_time_window, window, &w)) + w = None; + + if (w != self->user_time_window) { + if (self->user_time_window) { + XSelectInput(ob_display, self->user_time_window, NoEventMask); + g_hash_table_remove(client_user_time_window_map, &w); + self->user_time_window = None; + } + + if (self->group && self->group->leader == w) { + ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its " + "_NET_WM_USER_TYPE_WINDOW to its group leader\n"); + /* do it anyways..? */ + } + else if (w == self->window) { + ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its " + "_NET_WM_USER_TIME_WINDOW to itself\n"); + w = None; /* don't do it */ + } + else if (((c = g_hash_table_lookup(client_user_time_window_map,&w)))) { + ob_debug_type(OB_DEBUG_APP_BUGS, "Client %s is trying to use " + "the _NET_WM_USER_TIME_WINDOW of %s\n", + self->title, c->title); + w = None; /* don't do it */ + } + + self->user_time_window = w; + if (self->user_time_window != None) { + XSelectInput(ob_display,self->user_time_window,PropertyChangeMask); + g_hash_table_insert(client_user_time_window_map, + &self->user_time_window, self); + } + + client_update_user_time(self); } } diff --git a/openbox/client.h b/openbox/client.h index 4ee239f0..f9a19483 100644 --- a/openbox/client.h +++ b/openbox/client.h @@ -289,13 +289,17 @@ struct _ObClient /*! The number of icons in icons */ guint nicons; - /* Where the window should iconify to/from */ + /*! Where the window should iconify to/from */ Rect icon_geometry; + /*! The time when the client last received user interaction */ guint32 user_time; + /*! A separate window for the client to update it's user_time on */ + Window user_time_window; }; -extern GList *client_list; +extern GList *client_list; +extern GHashTable *client_user_time_window_map; void client_startup(gboolean reconfig); void client_shutdown(gboolean reconfig); @@ -585,6 +589,8 @@ void client_update_strut(ObClient *self); void client_update_icons(ObClient *self); /*! Updates the window's user time */ void client_update_user_time(ObClient *self); +/*! Updates the window's user time window */ +void client_update_user_time_window(ObClient *self); /*! Updates the window's icon geometry (where to iconify to/from) */ void client_update_icon_geometry(ObClient *self); diff --git a/openbox/event.c b/openbox/event.c index a4090b0c..3b318b01 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -81,7 +81,7 @@ static gboolean event_handle_menu(XEvent *e); static void event_handle_dock(ObDock *s, XEvent *e); static void event_handle_dockapp(ObDockApp *app, XEvent *e); static void event_handle_client(ObClient *c, XEvent *e); -static void event_handle_group(ObGroup *g, XEvent *e); +static void event_handle_user_time_window_client(ObClient *c, XEvent *e); static void event_handle_user_input(ObClient *client, XEvent *e); static void focus_delay_dest(gpointer data); @@ -406,11 +406,11 @@ static gboolean event_ignore(XEvent *e, ObClient *client) static void event_process(const XEvent *ec, gpointer data) { Window window; - ObGroup *group = NULL; ObClient *client = NULL; ObDock *dock = NULL; ObDockApp *dockapp = NULL; ObWindow *obwin = NULL; + ObClient *timewinclient = NULL; XEvent ee, *e; ObEventData *ed = data; @@ -419,8 +419,9 @@ static void event_process(const XEvent *ec, gpointer data) e = ⅇ window = event_get_window(e); - if (!(e->type == PropertyNotify && - (group = g_hash_table_lookup(group_map, &window)))) + if (e->type != PropertyNotify || + !(timewinclient = + g_hash_table_lookup(client_user_time_window_map, &window))) if ((obwin = g_hash_table_lookup(window_map, &window))) { switch (obwin->type) { case Window_Dock: @@ -554,8 +555,8 @@ static void event_process(const XEvent *ec, gpointer data) /* focus_set_client has already been called for sure */ client_calc_layer(client); } - } else if (group) - event_handle_group(group, e); + } else if (timewinclient) + event_handle_user_time_window_client(timewinclient, e); else if (client) event_handle_client(client, e); else if (dockapp) @@ -662,16 +663,6 @@ static void event_handle_root(XEvent *e) } } -static void event_handle_group(ObGroup *group, XEvent *e) -{ - GSList *it; - - g_assert(e->type == PropertyNotify); - - for (it = group->members; it; it = g_slist_next(it)) - event_handle_client(it->data, e); -} - void event_enter_client(ObClient *client) { g_assert(config_focus_follow); @@ -699,6 +690,13 @@ void event_enter_client(ObClient *client) } } +static void event_handle_user_time_window_client(ObClient *client, XEvent *e) +{ + g_assert(e->type == PropertyNotify); + if (e->xproperty.atom == prop_atoms.net_wm_user_time) + client_update_user_time(client); +} + static void event_handle_client(ObClient *client, XEvent *e) { XEvent ce; @@ -1191,6 +1189,9 @@ static void event_handle_client(ObClient *client, XEvent *e) else if (msgtype == prop_atoms.net_wm_user_time) { client_update_user_time(client); } + else if (msgtype == prop_atoms.net_wm_user_time_window) { + client_update_user_time_window(client); + } #ifdef SYNC else if (msgtype == prop_atoms.net_wm_sync_request_counter) { client_update_sync_request_counter(client); diff --git a/openbox/group.c b/openbox/group.c index f70b84b7..c0ba6ed7 100644 --- a/openbox/group.c +++ b/openbox/group.c @@ -19,17 +19,17 @@ #include "group.h" #include "client.h" -GHashTable *group_map = NULL; +static GHashTable *group_map; -static guint map_hash(Window *w) { return *w; } -static gboolean map_key_comp(Window *w1, Window *w2) { return *w1 == *w2; } +static guint window_hash(Window *w) { return *w; } +static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; } void group_startup(gboolean reconfig) { if (reconfig) return; - group_map = g_hash_table_new((GHashFunc)map_hash, - (GEqualFunc)map_key_comp); + group_map = g_hash_table_new((GHashFunc)window_hash, + (GEqualFunc)window_comp); } void group_shutdown(gboolean reconfig) diff --git a/openbox/group.h b/openbox/group.h index 844b629b..86b36b4c 100644 --- a/openbox/group.h +++ b/openbox/group.h @@ -34,8 +34,6 @@ struct _ObGroup GSList *members; }; -extern GHashTable *group_map; - void group_startup(gboolean reconfig); void group_shutdown(gboolean reconfig); diff --git a/openbox/prop.c b/openbox/prop.c index 0485045e..704c9109 100644 --- a/openbox/prop.c +++ b/openbox/prop.c @@ -92,6 +92,7 @@ void prop_startup() /* 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_wm_user_time_window, "_NET_WM_USER_TIME_WINDOW"); CREATE(kde_net_wm_frame_strut, "_KDE_NET_WM_FRAME_STRUT"); CREATE(net_frame_extents, "_NET_FRAME_EXTENTS"); diff --git a/openbox/prop.h b/openbox/prop.h index eaa1bf2d..f8b44a73 100644 --- a/openbox/prop.h +++ b/openbox/prop.h @@ -130,6 +130,7 @@ typedef struct Atoms { /* Atom net_wm_pid; */ Atom net_wm_allowed_actions; Atom net_wm_user_time; + Atom net_wm_user_time_window; Atom net_frame_extents; /* application protocols */ diff --git a/openbox/screen.c b/openbox/screen.c index 7814dce4..9265c73b 100644 --- a/openbox/screen.c +++ b/openbox/screen.c @@ -273,6 +273,7 @@ gboolean screen_annex(const gchar *program_name) 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_wm_user_time_window; supported[i++] = prop_atoms.net_frame_extents; supported[i++] = prop_atoms.net_startup_id; #ifdef SYNC diff --git a/openbox/window.c b/openbox/window.c index 7b3428bd..19b39c09 100644 --- a/openbox/window.c +++ b/openbox/window.c @@ -25,11 +25,15 @@ GHashTable *window_map; +static guint window_hash(Window *w) { return *w; } +static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; } + void window_startup(gboolean reconfig) { if (reconfig) return; - window_map = g_hash_table_new(g_int_hash, g_int_equal); + window_map = g_hash_table_new((GHashFunc)window_hash, + (GEqualFunc)window_comp); } void window_shutdown(gboolean reconfig) -- 2.39.2