generalize the window managing process into window_manage, which handles dock apps and the like

This commit is contained in:
Dana Jansens 2008-01-31 14:39:50 -05:00
parent 45e2039a58
commit e0c1978c51
8 changed files with 170 additions and 129 deletions

View file

@ -174,96 +174,16 @@ void client_set_list(void)
stacking_set_list();
}
void client_manage_all(void)
{
guint i, j, nchild;
Window w, *children;
XWMHints *wmhints;
XWindowAttributes attrib;
XQueryTree(obt_display, RootWindow(obt_display, ob_screen),
&w, &w, &children, &nchild);
/* remove all icon windows from the list */
for (i = 0; i < nchild; i++) {
if (children[i] == None) continue;
wmhints = XGetWMHints(obt_display, children[i]);
if (wmhints) {
if ((wmhints->flags & IconWindowHint) &&
(wmhints->icon_window != children[i]))
for (j = 0; j < nchild; j++)
if (children[j] == wmhints->icon_window) {
children[j] = None;
break;
}
XFree(wmhints);
}
}
/* manage windows in reverse order from how they were originally mapped.
this is an attempt to manage children windows before their parents, so
that when the parent is mapped, it can find the child */
for (i = 0; i < nchild; ++i) {
if (children[i] == None)
continue;
if (XGetWindowAttributes(obt_display, children[i], &attrib)) {
if (attrib.override_redirect) continue;
if (attrib.map_state != IsUnmapped)
client_manage(children[i]);
}
}
XFree(children);
}
void client_manage(Window window)
{
ObClient *self;
XEvent e;
XWindowAttributes attrib;
XSetWindowAttributes attrib_set;
XWMHints *wmhint;
gboolean activate = FALSE;
ObAppSettings *settings;
gboolean transient = FALSE;
Rect place, *monitor;
Time launch_time, map_time;
grab_server(TRUE);
/* check if it has already been unmapped by the time we started
mapping. the grab does a sync so we don't have to here */
if (XCheckTypedWindowEvent(obt_display, window, DestroyNotify, &e) ||
XCheckTypedWindowEvent(obt_display, window, UnmapNotify, &e))
{
XPutBackEvent(obt_display, &e);
ob_debug("Trying to manage unmapped window. Aborting that.\n");
grab_server(FALSE);
return; /* don't manage it */
}
/* make sure it isn't an override-redirect window */
if (!XGetWindowAttributes(obt_display, window, &attrib) ||
attrib.override_redirect)
{
grab_server(FALSE);
return; /* don't manage it */
}
/* is the window a docking app */
if ((wmhint = XGetWMHints(obt_display, window))) {
if ((wmhint->flags & StateHint) &&
wmhint->initial_state == WithdrawnState)
{
dock_add(window, wmhint);
grab_server(FALSE);
XFree(wmhint);
return;
}
XFree(wmhint);
}
ob_debug("Managing window: 0x%lx", window);
map_time = event_get_server_time();
@ -625,8 +545,6 @@ void client_manage(Window window)
ob_debug("Managed window 0x%lx plate 0x%x (%s)",
window, self->frame->window, self->class);
return;
}

View file

@ -319,10 +319,7 @@ typedef void (*ObClientCallback)(ObClient *client, gpointer data);
void client_add_destroy_notify(ObClientCallback func, gpointer data);
void client_remove_destroy_notify(ObClientCallback func);
/*! Manages all existing windows */
void client_manage_all();
/*! Manages a given window
*/
/*! Manages a given window */
void client_manage(Window win);
/*! Unmanages all managed windows */
void client_unmanage_all();

View file

@ -50,6 +50,9 @@ static void dock_app_grab_button(ObDockApp *app, gboolean grab)
}
}
static guint window_hash(Window *w) { return *w; }
static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
void dock_startup(gboolean reconfig)
{
XSetWindowAttributes attrib;
@ -82,6 +85,9 @@ void dock_startup(gboolean reconfig)
dock->hidden = TRUE;
dock->dock_map = g_hash_table_new((GHashFunc)window_hash,
(GEqualFunc)window_comp);
attrib.event_mask = DOCK_EVENT_MASK;
attrib.override_redirect = True;
attrib.do_not_propagate_mask = DOCK_NOPROPAGATEMASK;
@ -117,24 +123,25 @@ void dock_shutdown(gboolean reconfig)
return;
}
g_hash_table_destroy(dock->dock_map);
XDestroyWindow(obt_display, dock->frame);
RrAppearanceFree(dock->a_frame);
window_remove(dock->frame);
stacking_remove(dock);
}
void dock_add(Window win, XWMHints *wmhints)
void dock_manage(Window icon_win, Window name_win)
{
ObDockApp *app;
XWindowAttributes attrib;
gchar **data;
app = g_new0(ObDockApp, 1);
app->win = win;
app->icon_win = (wmhints->flags & IconWindowHint) ?
wmhints->icon_window : win;
app->name_win = name_win;
app->icon_win = icon_win;
if (OBT_PROP_GETSS(app->win, WM_CLASS, locale, &data)) {
if (OBT_PROP_GETSS(app->name_win, WM_CLASS, locale, &data)) {
if (data[0]) {
app->name = g_strdup(data[0]);
if (data[1])
@ -154,6 +161,7 @@ void dock_add(Window win, XWMHints *wmhints)
}
dock->dock_apps = g_list_append(dock->dock_apps, app);
g_hash_table_insert(dock->dock_map, &app->icon_win, app);
dock_configure();
XReparentWindow(obt_display, app->icon_win, dock->frame, app->x, app->y);
@ -166,32 +174,34 @@ void dock_add(Window win, XWMHints *wmhints)
*/
if (ob_state() == OB_STATE_STARTING)
app->ignore_unmaps += 2;
if (app->win != app->icon_win) {
/* have to map it so that it can be re-managed on a restart */
XMoveWindow(obt_display, app->win, -1000, -1000);
XMapWindow(obt_display, app->win);
}
XChangeSaveSet(obt_display, app->icon_win, SetModeInsert);
XMapWindow(obt_display, app->icon_win);
if (app->name_win != app->icon_win) {
XReparentWindow(obt_display, app->name_win, dock->frame, -1000, -1000);
XChangeSaveSet(obt_display, app->name_win, SetModeInsert);
XMapWindow(obt_display, app->name_win);
}
XSync(obt_display, False);
/* specify that if we exit, the window should not be destroyed and should
be reparented back to root automatically */
XChangeSaveSet(obt_display, app->icon_win, SetModeInsert);
XSelectInput(obt_display, app->icon_win, DOCKAPP_EVENT_MASK);
dock_app_grab_button(app, TRUE);
ob_debug("Managed Dock App: 0x%lx (%s)", app->icon_win, app->class);
ob_debug("Managed Dock App: 0x%lx 0x%lx (%s)",
app->icon_win, app->name_win, app->class);
grab_server(FALSE);
}
void dock_remove_all(void)
void dock_unmanage_all(void)
{
while (dock->dock_apps)
dock_remove(dock->dock_apps->data, TRUE);
dock_unmanage(dock->dock_apps->data, TRUE);
}
void dock_remove(ObDockApp *app, gboolean reparent)
void dock_unmanage(ObDockApp *app, gboolean reparent)
{
dock_app_grab_button(app, FALSE);
XSelectInput(obt_display, app->icon_win, NoEventMask);
@ -199,11 +209,15 @@ void dock_remove(ObDockApp *app, gboolean reparent)
XChangeSaveSet(obt_display, app->icon_win, SetModeDelete);
XSync(obt_display, False);
if (reparent)
XReparentWindow(obt_display, app->icon_win,
obt_root(ob_screen), app->x, app->y);
if (reparent) {
XReparentWindow(obt_display, app->icon_win, obt_root(ob_screen), 0, 0);
if (app->name_win != app->icon_win)
XReparentWindow(obt_display, app->name_win,
obt_root(ob_screen), 0, 0);
}
dock->dock_apps = g_list_remove(dock->dock_apps, app);
g_hash_table_remove(dock->dock_map, &app->icon_win);
dock_configure();
ob_debug("Unmanaged Dock App: 0x%lx (%s)", app->icon_win, app->class);
@ -657,13 +671,5 @@ void dock_get_area(Rect *a)
ObDockApp* dock_find_dockapp(Window xwin)
{
GList *it;
/* there are never that many dock apps, so we can use a list here instead
of a hash table */
for (it = dock->dock_apps; it; it = g_list_next(it)) {
ObDockApp *app = it->data;
if (app->icon_win == xwin)
return app;
}
return NULL;
return g_hash_table_lookup(dock->dock_map, &xwin);
}

View file

@ -44,13 +44,14 @@ struct _ObDock
gboolean hidden;
GList *dock_apps;
GHashTable *dock_map;
};
struct _ObDockApp {
gint ignore_unmaps;
Window icon_win;
Window win;
Window name_win;
gchar *name;
gchar *class;
@ -69,10 +70,10 @@ void dock_shutdown(gboolean reconfig);
void dock_configure();
void dock_hide(gboolean hide);
void dock_add(Window win, XWMHints *wmhints);
void dock_manage(Window icon_win, Window name_win);
void dock_remove_all();
void dock_remove(ObDockApp *app, gboolean reparent);
void dock_unmanage_all();
void dock_unmanage(ObDockApp *app, gboolean reparent);
void dock_app_drag(ObDockApp *app, XMotionEvent *e);
void dock_app_configure(ObDockApp *app, gint w, gint h);

View file

@ -161,7 +161,13 @@ static Window event_get_window(XEvent *e)
case SelectionClear:
window = obt_root(ob_screen);
break;
case CreateNotify:
window = e->xcreatewindow.window;
break;
case MapRequest:
window = e->xmaprequest.window;
break;
case MapNotify:
window = e->xmap.window;
break;
case UnmapNotify:
@ -639,7 +645,7 @@ static void event_process(const XEvent *ec, gpointer data)
else if (window == obt_root(ob_screen))
event_handle_root(e);
else if (e->type == MapRequest)
client_manage(window);
window_manage(window);
else if (e->type == MappingNotify) {
/* keyboard layout changes for modifier mapping changes. reload the
modifier map, and rebind all the key bindings as appropriate */
@ -1625,13 +1631,13 @@ static void event_handle_dockapp(ObDockApp *app, XEvent *e)
app->ignore_unmaps--;
break;
}
dock_remove(app, TRUE);
dock_unmanage(app, TRUE);
break;
case DestroyNotify:
dock_remove(app, FALSE);
dock_unmanage(app, FALSE);
break;
case ReparentNotify:
dock_remove(app, FALSE);
dock_unmanage(app, FALSE);
break;
case ConfigureNotify:
dock_app_configure(app, e->xconfigure.width, e->xconfigure.height);

View file

@ -294,7 +294,7 @@ gint main(gint argc, gchar **argv)
ObWindow *w;
/* get all the existing windows */
client_manage_all();
window_manage_all();
focus_nothing();
/* focus what was focused if a wm was already running */
@ -327,10 +327,8 @@ gint main(gint argc, gchar **argv)
obt_main_loop_run(ob_main_loop);
state = OB_STATE_EXITING;
if (!reconfigure) {
dock_remove_all();
client_unmanage_all();
}
if (!reconfigure)
window_unmanage_all();
menu_shutdown(reconfigure);
menu_frame_shutdown(reconfigure);

View file

@ -22,6 +22,9 @@
#include "dock.h"
#include "client.h"
#include "frame.h"
#include "openbox.h"
#include "debug.h"
#include "grab.h"
static GHashTable *window_map;
@ -91,3 +94,111 @@ void window_remove(Window xwin)
g_assert(xwin != None);
g_hash_table_remove(window_map, &xwin);
}
void window_manage_all(void)
{
guint i, j, nchild;
Window w, *children;
XWMHints *wmhints;
XWindowAttributes attrib;
if (!XQueryTree(obt_display, RootWindow(obt_display, ob_screen),
&w, &w, &children, &nchild)) {
ob_debug("XQueryTree failed in window_manage_all");
nchild = 0;
}
/* remove all icon windows from the list */
for (i = 0; i < nchild; i++) {
if (children[i] == None) continue;
wmhints = XGetWMHints(obt_display, children[i]);
if (wmhints) {
if ((wmhints->flags & IconWindowHint) &&
(wmhints->icon_window != children[i]))
for (j = 0; j < nchild; j++)
if (children[j] == wmhints->icon_window) {
/* XXX watch the window though */
children[j] = None;
break;
}
XFree(wmhints);
}
}
for (i = 0; i < nchild; ++i) {
if (children[i] == None) continue;
if (window_find(children[i])) continue; /* skip our own windows */
if (XGetWindowAttributes(obt_display, children[i], &attrib)) {
if (attrib.map_state == IsUnmapped)
;
else
window_manage(children[i]);
}
}
if (children) XFree(children);
}
void window_manage(Window win)
{
XEvent e;
XWindowAttributes attrib;
gboolean no_manage = FALSE;
gboolean is_dockapp = FALSE;
Window icon_win = None;
grab_server(TRUE);
/* check if it has already been unmapped by the time we started
mapping. the grab does a sync so we don't have to here */
if (XCheckTypedWindowEvent(obt_display, win, DestroyNotify, &e) ||
XCheckTypedWindowEvent(obt_display, win, UnmapNotify, &e))
{
XPutBackEvent(obt_display, &e);
ob_debug("Trying to manage unmapped window. Aborting that.\n");
no_manage = TRUE;
}
if (!XGetWindowAttributes(obt_display, win, &attrib))
no_manage = TRUE;
else {
XWMHints *wmhints;
/* is the window a docking app */
is_dockapp = FALSE;
if ((wmhints = XGetWMHints(obt_display, win))) {
if ((wmhints->flags & StateHint) &&
wmhints->initial_state == WithdrawnState)
{
if (wmhints->flags & IconWindowHint)
icon_win = wmhints->icon_window;
is_dockapp = TRUE;
}
XFree(wmhints);
}
}
if (!no_manage) {
if (attrib.override_redirect) {
ob_debug("not managing override redirect window 0x%x\n", win);
grab_server(FALSE);
}
else if (is_dockapp) {
if (!icon_win)
icon_win = win;
dock_manage(icon_win, win);
}
else
client_manage(win);
}
else {
grab_server(FALSE);
ob_debug("FAILED to manage window 0x%x\n", win);
}
}
void window_unmanage_all(void)
{
dock_unmanage_all();
client_unmanage_all();
}

View file

@ -80,4 +80,8 @@ struct _ObInternalWindow {
Window window;
};
void window_manage_all(void);
void window_manage(Window win);
void window_unmanage_all(void);
#endif