From 851555348ec39a01a0e150d2e12b71212b8d338b Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Wed, 9 May 2007 17:58:58 +0000 Subject: [PATCH] support for _NET_WM_USER_TIME_WINDOW round 2 ! yay abstraction --- Makefile.am | 2 + openbox/client.c | 39 ++++----------- openbox/event.c | 21 ++++---- openbox/openbox.c | 3 ++ openbox/propwin.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++ openbox/propwin.h | 40 +++++++++++++++ 6 files changed, 188 insertions(+), 38 deletions(-) create mode 100644 openbox/propwin.c create mode 100644 openbox/propwin.h diff --git a/Makefile.am b/Makefile.am index a30248eb..35ccca9c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -204,6 +204,8 @@ openbox_openbox_SOURCES = \ openbox/popup.h \ openbox/prop.c \ openbox/prop.h \ + openbox/propwin.c \ + openbox/propwin.h \ openbox/resist.c \ openbox/resist.h \ openbox/screen.c \ diff --git a/openbox/client.c b/openbox/client.c index aac52e2d..3f3f161d 100644 --- a/openbox/client.c +++ b/openbox/client.c @@ -32,6 +32,7 @@ #include "event.h" #include "grab.h" #include "focus.h" +#include "propwin.h" #include "stacking.h" #include "openbox.h" #include "group.h" @@ -62,7 +63,6 @@ typedef struct } ClientCallback; GList *client_list = NULL; -GHashTable *client_user_time_window_map; static GSList *client_destructors = NULL; @@ -95,23 +95,16 @@ 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) @@ -512,10 +505,6 @@ 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 */ @@ -529,6 +518,9 @@ void client_unmanage(ObClient *self) /* remove the window from our save set */ XChangeSaveSet(ob_display, self->window, SetModeDelete); + /* kill the property windows */ + propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self); + /* update the focus lists */ focus_order_remove(self); if (client_focused(self)) { @@ -2058,17 +2050,14 @@ void client_update_user_time(ObClient *self) 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; - } + /* remove the old window */ + propwin_remove(self->user_time_window, OB_PROPWIN_USER_TIME, self); + self->user_time_window = None; if (self->group && self->group->leader == w) { ob_debug_type(OB_DEBUG_APP_BUGS, "Window is setting its " @@ -2080,20 +2069,12 @@ void client_update_user_time_window(ObClient *self) "_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 */ - } + /* add the new window */ + propwin_add(w, OB_PROPWIN_USER_TIME, self); 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); - } + /* and update from it */ client_update_user_time(self); } } diff --git a/openbox/event.c b/openbox/event.c index 3b318b01..babb5197 100644 --- a/openbox/event.c +++ b/openbox/event.c @@ -32,6 +32,7 @@ #include "menuframe.h" #include "keyboard.h" #include "modkeys.h" +#include "propwin.h" #include "mouse.h" #include "mainloop.h" #include "framerender.h" @@ -81,7 +82,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_user_time_window_client(ObClient *c, XEvent *e); +static void event_handle_user_time_window_clients(GSList *l, XEvent *e); static void event_handle_user_input(ObClient *client, XEvent *e); static void focus_delay_dest(gpointer data); @@ -410,7 +411,7 @@ static void event_process(const XEvent *ec, gpointer data) ObDock *dock = NULL; ObDockApp *dockapp = NULL; ObWindow *obwin = NULL; - ObClient *timewinclient = NULL; + GSList *timewinclients = NULL; XEvent ee, *e; ObEventData *ed = data; @@ -420,8 +421,8 @@ static void event_process(const XEvent *ec, gpointer data) window = event_get_window(e); if (e->type != PropertyNotify || - !(timewinclient = - g_hash_table_lookup(client_user_time_window_map, &window))) + !(timewinclients = propwin_get_clients(window, + OB_PROPWIN_USER_TIME))) if ((obwin = g_hash_table_lookup(window_map, &window))) { switch (obwin->type) { case Window_Dock: @@ -555,8 +556,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 (timewinclient) - event_handle_user_time_window_client(timewinclient, e); + } else if (timewinclients) + event_handle_user_time_window_clients(timewinclients, e); else if (client) event_handle_client(client, e); else if (dockapp) @@ -690,11 +691,13 @@ void event_enter_client(ObClient *client) } } -static void event_handle_user_time_window_client(ObClient *client, XEvent *e) +static void event_handle_user_time_window_clients(GSList *l, XEvent *e) { g_assert(e->type == PropertyNotify); - if (e->xproperty.atom == prop_atoms.net_wm_user_time) - client_update_user_time(client); + if (e->xproperty.atom == prop_atoms.net_wm_user_time) { + for (; l; l = g_slist_next(l)) + client_update_user_time(l->data); + } } static void event_handle_client(ObClient *client, XEvent *e) diff --git a/openbox/openbox.c b/openbox/openbox.c index 9cb38b56..db26f0d2 100644 --- a/openbox/openbox.c +++ b/openbox/openbox.c @@ -38,6 +38,7 @@ #include "menuframe.h" #include "grab.h" #include "group.h" +#include "propwin.h" #include "config.h" #include "mainloop.h" #include "gettext.h" @@ -282,6 +283,7 @@ gint main(gint argc, gchar **argv) sn_startup(reconfigure); screen_startup(reconfigure); grab_startup(reconfigure); + propwin_startup(reconfigure); group_startup(reconfigure); client_startup(reconfigure); dock_startup(reconfigure); @@ -339,6 +341,7 @@ gint main(gint argc, gchar **argv) dock_shutdown(reconfigure); client_shutdown(reconfigure); group_shutdown(reconfigure); + propwin_shutdown(reconfigure); grab_shutdown(reconfigure); screen_shutdown(reconfigure); focus_shutdown(reconfigure); diff --git a/openbox/propwin.c b/openbox/propwin.c new file mode 100644 index 00000000..0bf74b2a --- /dev/null +++ b/openbox/propwin.c @@ -0,0 +1,121 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + propwin.c for the Openbox window manager + Copyright (c) 2006 Mikael Magnusson + Copyright (c) 2003-2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#include "propwin.h" +#include "openbox.h" + +typedef struct _ObPropWin ObPropWin; +typedef struct _ObPropWinData ObPropWinData; + +struct _ObPropWinData +{ + GSList *clients; +}; + +struct _ObPropWin +{ + Window win; + ObPropWinData data[OB_NUM_PROPWIN_TYPES]; +}; + +/*! A hash table that maps a window to an ObPropWin */ +static GHashTable *propwin_map; + +static guint window_hash(Window *w) { return *w; } +static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; } + +void propwin_startup(gboolean reconfig) +{ + if (!reconfig) + propwin_map = g_hash_table_new_full((GHashFunc)window_hash, + (GEqualFunc)window_comp, + NULL, + g_free); +} + +void propwin_shutdown(gboolean reconfig) +{ + if (!reconfig) + g_hash_table_destroy(propwin_map); + else + g_assert(g_hash_table_size(propwin_map) == 0); +} + +void propwin_add(Window win, ObPropWinType type, struct _ObClient *client) +{ + ObPropWin *p; + + if (!win) return; + + g_assert(client); + g_assert(type < OB_NUM_PROPWIN_TYPES); + + p = g_hash_table_lookup(propwin_map, &win); + if (!p) { + p = g_new0(ObPropWin, 1); + p->win = win; + g_hash_table_insert(propwin_map, &p->win, p); + /* get property changes on this window */ + XSelectInput(ob_display, win, PropertyChangeMask); + } else + g_assert(g_slist_find(p->data[type].clients, client) == NULL); + + /* add it to the clients list */ + p->data[type].clients = g_slist_prepend(p->data[type].clients, client); +} + +void propwin_remove(Window win, ObPropWinType type, struct _ObClient *client) +{ + ObPropWin *p; + + if (!win) return; + + p = g_hash_table_lookup(propwin_map, &win); + g_assert(p); + + /* remove it to the clients list */ + g_assert(g_slist_find(p->data[type].clients, client) != NULL); + p->data[type].clients = g_slist_remove(p->data[type].clients, client); + + /* no more clients left for this type */ + if (p->data[type].clients == NULL) { + guint i; + gboolean none = TRUE; + + for (i = 0; i < OB_NUM_PROPWIN_TYPES; ++i) + if (p->data[i].clients != NULL) + none = FALSE; /* another type still has a client for this + window */ + + if (none) { + /* don't get events for this window any more */ + XSelectInput(ob_display, win, NoEventMask); + g_hash_table_remove(propwin_map, &win); + } + } +} + +GSList* propwin_get_clients(Window win, ObPropWinType type) +{ + ObPropWin *p = g_hash_table_lookup(propwin_map, &win); + if (p) + return p->data[type].clients; + else + return NULL; +} diff --git a/openbox/propwin.h b/openbox/propwin.h new file mode 100644 index 00000000..1e014aaa --- /dev/null +++ b/openbox/propwin.h @@ -0,0 +1,40 @@ +/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*- + + propwin.h for the Openbox window manager + Copyright (c) 2007 Dana Jansens + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + See the COPYING file for a copy of the GNU General Public License. +*/ + +#ifndef __propwin_h +#define __propwin_h + +#include +#include + +struct _ObClient; + +typedef enum { + OB_PROPWIN_USER_TIME, + OB_NUM_PROPWIN_TYPES +} ObPropWinType; + +void propwin_startup(gboolean reconfig); +void propwin_shutdown(gboolean reconfig); + +void propwin_add(Window win, ObPropWinType type, struct _ObClient *client); +void propwin_remove(Window win, ObPropWinType type, struct _ObClient *client); + +GSList* propwin_get_clients(Window win, ObPropWinType type); + +#endif -- 2.39.2