generalize the window managing process into window_manage, which handles dock apps...
authorDana Jansens <danakj@orodu.net>
Thu, 31 Jan 2008 19:39:50 +0000 (14:39 -0500)
committerDana Jansens <danakj@orodu.net>
Thu, 31 Jan 2008 21:50:54 +0000 (16:50 -0500)
openbox/client.c
openbox/client.h
openbox/dock.c
openbox/dock.h
openbox/event.c
openbox/openbox.c
openbox/window.c
openbox/window.h

index 507c1e7..9809b51 100644 (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;
 }
 
 
index 0efeb19..c66aaf0 100644 (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();
index 82b085a..ee1202c 100644 (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;
+    XChangeSaveSet(obt_display, app->icon_win, SetModeInsert);
+    XMapWindow(obt_display, app->icon_win);
 
-    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);
+    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);
     }
-    XMapWindow(obt_display, app->icon_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);
 }
index 25e31c0..d632ee7 100644 (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);
index 2838194..5207e09 100644 (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);
index 829960e..95a5819 100644 (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);
index e13638e..28b0857 100644 (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();
+}
index 252145b..c7bfc89 100644 (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