support for _NET_WM_USER_TIME_WINDOW round 2 ! yay abstraction
This commit is contained in:
parent
cdb108c76d
commit
851555348e
6 changed files with 188 additions and 38 deletions
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
121
openbox/propwin.c
Normal file
121
openbox/propwin.c
Normal file
|
@ -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;
|
||||
}
|
40
openbox/propwin.h
Normal file
40
openbox/propwin.h
Normal file
|
@ -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 <glib.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
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
|
Loading…
Reference in a new issue