} ClientCallback;
GList *client_list = NULL;
+GHashTable *client_user_time_window_map;
static GSList *client_destructors = NULL;
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)
/* 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 */
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);
}
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
*/
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);
}
}
/*! 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);
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);
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);
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;
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:
/* 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)
}
}
-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);
}
}
+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;
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);
#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)
GSList *members;
};
-extern GHashTable *group_map;
-
void group_startup(gboolean reconfig);
void group_shutdown(gboolean reconfig);
/* 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");
/* 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 */
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
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)