Show unmanaged windows in composite. *Stacking will be broken though still!!*
authorDana Jansens <danakj@orodu.net>
Thu, 10 Jun 2010 23:26:52 +0000 (19:26 -0400)
committerDana Jansens <danakj@orodu.net>
Sat, 26 Jun 2010 23:30:48 +0000 (01:30 +0200)
adds window_cleanup() that subclasses of ObWindow call to tell the parent they are going away, allowing it to clean up using the abstract pointers.

unmanaged windows get OB_STACKING_LAYER_ALL, but the stacking code is not made to handle this value yet.  unexpected behaviour may result !

16 files changed:
Makefile.am
openbox/client.c
openbox/composite.c
openbox/composite.h
openbox/dock.c
openbox/event.c
openbox/focus_cycle_indicator.c
openbox/focus_cycle_popup.c
openbox/menuframe.c
openbox/popup.c
openbox/stacking.c
openbox/stacking.h
openbox/unmanaged.c [new file with mode: 0644]
openbox/unmanaged.h [new file with mode: 0644]
openbox/window.c
openbox/window.h

index 9e8ed5f7c6ab237203a28e8e14854dfe4deb5493..8e2b1b556e20a445ba2ddd9d437f0721abaed12b 100644 (file)
@@ -347,6 +347,8 @@ openbox_openbox_SOURCES = \
        openbox/startupnotify.h \
        openbox/translate.c \
        openbox/translate.h \
+       openbox/unmanaged.c \
+       openbox/unmanaged.h \
        openbox/window.c \
        openbox/window.h
 
index 79ca23424abc4082b1d3c3de9feb3aef037a439f..5c19684a6890bed2819ac6d86da52919caa5be55 100644 (file)
@@ -563,6 +563,8 @@ void client_unmanage(ObClient *self)
        don't generate more events */
     XSelectInput(obt_display, self->window, NoEventMask);
 
+    window_cleanup(CLIENT_AS_WINDOW(self));
+
     /* ignore enter events from the unmap so it doesnt mess with the focus */
     if (!config_focus_under_mouse)
         ignore_start = event_start_ignore_all_enters();
@@ -702,6 +704,7 @@ void client_fake_unmanage(ObClient *self)
 {
     /* this is all that got allocated to get the decorations */
 
+    window_cleanup(CLIENT_AS_WINDOW(self));
     frame_free(self->frame);
     window_free(CLIENT_AS_WINDOW(self));
 }
index cf2bdd0324c12a49f49d5b95f0678d843acf0807..ab5aef0b92dc26b646f1a31340ffbdeced9c23f6 100644 (file)
@@ -24,6 +24,7 @@
 #include "screen.h"
 #include "event.h"
 #include "client.h"
+#include "window.h"
 #include "frame.h"
 #include "geom.h"
 #include "gettext.h"
@@ -417,6 +418,7 @@ time_fix(&dif);
     }
     glXSwapBuffers(obt_display, obcomp.overlay);
     glFinish();
+    usleep(10000);
     GLenum gler;
     while ((gler = glGetError()) != GL_NO_ERROR) {
         printf("gl error %d\n", gler);
@@ -426,3 +428,32 @@ time_fix(&dif);
 #endif
     return TRUE;
 }
+
+Window composite_overlay(void)
+{
+#ifdef USE_COMPOSITING
+    return obcomp.overlay;
+#else
+    return 0;
+#endif
+}
+
+void composite_redir(ObWindow *w, gboolean on)
+{
+#ifdef USE_COMPOSITING
+    if (on) {
+        if (w->redir) return;
+        XCompositeRedirectWindow(obt_display, window_top(w),
+                                 CompositeRedirectManual);
+        w->redir = TRUE;
+    }
+    else {
+        if (!w->redir) return;
+        XCompositeUnredirectWindow(obt_display, window_top(w),
+                                   CompositeRedirectManual);
+        w->redir = FALSE;
+    }
+#endif
+}
+        
+
index 26146334f38c473758dea0b2610f6e0a48c142c6..7b41e3836e2968915e3f7a9d8c3ccbfa61650f65 100644 (file)
@@ -27,6 +27,8 @@
 
 #include "geom.h"
 
+struct _ObWindow;
+
 #define MAX_DEPTH 32
 
 typedef GLXPixmap (*CreatePixmapT)(Display *display,
@@ -74,5 +76,7 @@ struct ObCompositor {
 
 void composite_startup(gboolean reconfig);
 void composite_shutdown(gboolean reconfig);
+Window composite_overlay(void);
+void composite_redir(struct _ObWindow *w, gboolean on);
 
 #endif
index 068c65d504f37de1104ba1588f7e99910a90c7de..b54ed437ac4b759ba707cd0f5419664d72cbc91d 100644 (file)
@@ -130,6 +130,8 @@ void dock_shutdown(gboolean reconfig)
         return;
     }
 
+    window_cleanup(DOCK_AS_WINDOW(dock));
+
     g_hash_table_destroy(dock->dock_map);
 
     XDestroyWindow(obt_display, dock->frame);
index 5c7a1952d1a29add43930e02b5c7281e2b5e36ba..a508abfafa84eca11d3957b553e6ee2841e5ed39 100644 (file)
@@ -38,6 +38,7 @@
 #include "moveresize.h"
 #include "group.h"
 #include "stacking.h"
+#include "unmanaged.h"
 #include "ping.h"
 #include "obt/display.h"
 #include "obt/xqueue.h"
@@ -88,6 +89,7 @@ static gboolean event_handle_prompt(ObPrompt *p, 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_unmanaged(ObUnmanaged *um, XEvent *e);
 static gboolean event_handle_user_input(ObClient *client, XEvent *e);
 static gboolean is_enter_focus_event_ignored(gulong serial);
 static void event_ignore_enter_range(gulong start, gulong end);
@@ -457,6 +459,7 @@ static void event_process(const XEvent *ec, gpointer data)
     ObWindow *obwin = NULL;
     ObMenuFrame *menu = NULL;
     ObPrompt *prompt = NULL;
+    ObUnmanaged *um = NULL;
     gboolean used;
 
     /* make a copy we can mangle */
@@ -485,6 +488,9 @@ static void event_process(const XEvent *ec, gpointer data)
         case OB_WINDOW_CLASS_PROMPT:
             prompt = WINDOW_AS_PROMPT(obwin);
             break;
+        case OB_WINDOW_CLASS_UNMANAGED:
+            um = WINDOW_AS_UNMANAGED(obwin);
+            break;
         }
     }
     else
@@ -621,16 +627,22 @@ static void event_process(const XEvent *ec, gpointer data)
         if (client && client != focus_client)
             frame_adjust_focus(client->frame, FALSE);
     }
-#ifdef USE_COMPOSITING
-    else if ((e->type == CreateNotify) && obwin &&
-             obwin->type != OB_WINDOW_CLASS_PROMPT &&
-             e->xcreatewindow.window == window_top(obwin))
-    {
+    else if (e->type == CreateNotify) {
         XCreateWindowEvent const *xe = &e->xcreatewindow;
-        obwin->mapped = 0;
-        RECT_SET(obwin->area, xe->x, xe->y, xe->width, xe->height);
-        obwin->border = xe->border_width;
-        if (!obwin->texture) glGenTextures(1, &obwin->texture);
+
+        if (!obwin && xe->parent == obt_root(ob_screen))
+            obwin = UNMANAGED_AS_WINDOW(unmanaged_new(xe->window));
+
+        if (obwin && xe->window == window_top(obwin) &&
+            obwin->type != OB_WINDOW_CLASS_PROMPT)
+        {
+            obwin->mapped = 0;
+            RECT_SET(obwin->area, xe->x, xe->y, xe->width, xe->height);
+            obwin->border = xe->border_width;
+#ifdef USE_COMPOSITING
+            if (!obwin->texture) glGenTextures(1, &obwin->texture);
+#endif
+        }
     }
     else if ((obwin && obwin->type != OB_WINDOW_CLASS_PROMPT) &&
                ((e->type == ConfigureNotify &&
@@ -659,6 +671,7 @@ static void event_process(const XEvent *ec, gpointer data)
         }
 
         if (pixchange) {
+#ifdef USE_COMPOSITING
             if (obwin->gpixmap != None) {
                 glXDestroyGLXPixmap(obt_display, obwin->gpixmap);
                 obwin->gpixmap = None;
@@ -667,6 +680,7 @@ static void event_process(const XEvent *ec, gpointer data)
                 XFreePixmap(obt_display, obwin->pixmap);
                 obwin->pixmap = None;
             }
+#endif
         }
     } else if ((e->type == UnmapNotify) && obwin &&
                obwin->type != OB_WINDOW_CLASS_PROMPT &&
@@ -674,7 +688,8 @@ static void event_process(const XEvent *ec, gpointer data)
     {
         obwin->mapped = FALSE;
     }
-#endif
+    else if (um)
+        event_handle_unmanaged(um, e);
     else if (client)
         event_handle_client(client, e);
     else if (dockapp)
@@ -685,8 +700,6 @@ static void event_process(const XEvent *ec, gpointer data)
         event_handle_menu(menu, e);
     else if (window == obt_root(ob_screen))
         event_handle_root(e);
-    else if (e->type == MapRequest)
-        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 */
@@ -1408,6 +1421,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
             break;
         }
         client_unmanage(client);
+        unmanaged_new(e->xunmap.window);
         break;
     case DestroyNotify:
         ob_debug("DestroyNotify for window 0x%x", client->window);
@@ -1426,6 +1440,7 @@ static void event_handle_client(ObClient *client, XEvent *e)
 
         ob_debug("ReparentNotify for window 0x%x", client->window);
         client_unmanage(client);
+        unmanaged_new(e->xreparent.window);
         break;
     case MapRequest:
         ob_debug("MapRequest for 0x%lx", client->window);
@@ -1782,6 +1797,22 @@ static void event_handle_dock(ObDock *s, XEvent *e)
     }
 }
 
+static void event_handle_unmanaged(ObUnmanaged *um, XEvent *e)
+{
+    Window w;
+
+    switch (e->type) {
+    case DestroyNotify:
+        unmanaged_destroy(um);
+        break;
+    case MapRequest:
+        w = window_top(um);
+        unmanaged_destroy(um);
+        window_manage(w);
+        break;
+    }
+}
+
 static void event_handle_dockapp(ObDockApp *app, XEvent *e)
 {
     switch (e->type) {
index 655b87f8b70b741dd994d3b20969cfc5ba79a127..8ffe90e359bd553483a8ccb5c04e7e246e23f48d 100644 (file)
@@ -116,6 +116,11 @@ void focus_cycle_indicator_shutdown(gboolean reconfig)
 
     RrAppearanceFree(a_focus_indicator);
 
+    window_cleanup(INTERNAL_AS_WINDOW(focus_indicator.top));
+    window_cleanup(INTERNAL_AS_WINDOW(focus_indicator.left));
+    window_cleanup(INTERNAL_AS_WINDOW(focus_indicator.right));
+    window_cleanup(INTERNAL_AS_WINDOW(focus_indicator.bottom));
+
     window_remove(focus_indicator.top->window);
     window_remove(focus_indicator.left->window);
     window_remove(focus_indicator.right->window);
index f30ba8b7c54605e9a96db965dfca9ec646b97a9e..3de68d67f131aad05d8f65c79a87af1e636c389c 100644 (file)
@@ -222,6 +222,8 @@ void focus_cycle_popup_shutdown(gboolean reconfig)
 {
     icon_popup_free(single_popup);
 
+    window_cleanup(INTERNAL_AS_WINDOW(popup));
+
     window_remove(popup->bg);
     stacking_remove(INTERNAL_AS_WINDOW(&popup));
 
index 10e7ca9b3e3e843c9f0b8a5e5a2fbebbcb32ddc1..9413e8008113fc8c3e7c89bdf558fd10f276d484 100644 (file)
@@ -152,6 +152,8 @@ void menu_frame_free(ObMenuFrame *self)
             self->entries = g_list_delete_link(self->entries, self->entries);
         }
 
+        window_cleanup(MENUFRAME_AS_WINDOW(self));
+
         stacking_remove(MENUFRAME_AS_WINDOW(self));
         window_remove(self->window);
 
index b87a4ad83598b980be95ff0a24529260f3a60b91..297fc529705e9489edcbb04fb4f3ad990ec35d6c 100644 (file)
@@ -73,6 +73,7 @@ void popup_free(ObPopup *self)
     if (self) {
         popup_hide(self); /* make sure it's not showing or is being delayed and
                              will be shown */
+        window_cleanup(INTERNAL_AS_WINDOW(self));
         XDestroyWindow(obt_display, self->bg);
         XDestroyWindow(obt_display, self->text);
         RrAppearanceFree(self->a_bg);
index 58a85ecade840762317ba5cadf64c3f8ec8f32d3..7c8f216edcce0ac616449a8dbcc156248107c5dd 100644 (file)
@@ -74,7 +74,11 @@ static void do_restack(GList *wins, GList *before)
     g_assert(wins);
     /* pls only restack stuff in the same layer at a time */
     for (it = wins; it; it = next) {
+        while (it && window_layer(it->data) == OB_STACKING_LAYER_ALL)
+            it = g_list_next(it);
         next = g_list_next(it);
+        while (next && window_layer(next->data) == OB_STACKING_LAYER_ALL)
+            next = g_list_next(next);
         if (!next) break;
         g_assert (window_layer(it->data) == window_layer(next->data));
     }
@@ -101,7 +105,11 @@ static void do_restack(GList *wins, GList *before)
 #ifdef DEBUG
     /* some debug checking of the stacking list's order */
     for (it = stacking_list; ; it = next) {
+        while (it && window_layer(it->data) == OB_STACKING_LAYER_ALL)
+            it = g_list_next(it);
         next = g_list_next(it);
+        while (next && window_layer(next->data) == OB_STACKING_LAYER_ALL)
+            next = g_list_next(next);
         if (!next) break;
         g_assert(window_layer(it->data) >= window_layer(next->data));
     }
@@ -445,10 +453,13 @@ void stacking_add(ObWindow *win)
     /* don't add windows that are being unmanaged ! */
     if (WINDOW_IS_CLIENT(win)) g_assert(WINDOW_AS_CLIENT(win)->managed);
 
-    stacking_list = g_list_append(stacking_list, win);
-
-    stacking_raise(win);
-    /* stacking_list_tail set by stacking_raise() */
+    if (WINDOW_IS_UNMANAGED(win))
+        stacking_list = g_list_prepend(stacking_list, win);
+    else {
+        stacking_list = g_list_append(stacking_list, win);
+        stacking_raise(win);
+        /* stacking_list_tail set by stacking_raise() */
+    }
 }
 
 static GList *find_highest_relative(ObClient *client)
index c14aa2eddb59e62819f73ae4eb45e2e14a5d92e2..be247f346eaac303a9be8902fe29961c21777107 100644 (file)
@@ -35,7 +35,8 @@ typedef enum {
     OB_STACKING_LAYER_ABOVE,            /*!< 3 - normal windows w/ above */
     OB_STACKING_LAYER_FULLSCREEN,       /*!< 4 - fullscreeen windows */
     OB_STACKING_LAYER_INTERNAL,         /*!< 5 - openbox windows/menus */
-    OB_NUM_STACKING_LAYERS
+    OB_NUM_STACKING_LAYERS,
+    OB_STACKING_LAYER_ALL = 0xffffffff  /*!< 0xffffffff - unmamnaged windows */
 } ObStackingLayer;
 
 /* list of ObWindow*s in stacking order from highest to lowest */
diff --git a/openbox/unmanaged.c b/openbox/unmanaged.c
new file mode 100644 (file)
index 0000000..4c99d87
--- /dev/null
@@ -0,0 +1,66 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   unmanaged.c for the Openbox window manager
+   Copyright (c) 2010        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 "unmanaged.h"
+#include "composite.h"
+#include "window.h"
+#include "obt/display.h"
+
+struct _ObUnmanaged {
+    ObWindow super;
+    Window win;
+    ObStackingLayer layer;
+    gint depth;
+
+};
+
+ObUnmanaged* unmanaged_new(Window w)
+{
+    XWindowAttributes at;
+    ObUnmanaged *self;
+
+    if (w == composite_overlay())
+        return NULL;
+    if (!XGetWindowAttributes(obt_display, w, &at))
+        return NULL;        
+    if (at.class == InputOnly)
+        return NULL;
+
+    self = window_new(OB_WINDOW_CLASS_UNMANAGED, ObUnmanaged);
+    self->win = w;
+    self->layer = OB_STACKING_LAYER_ALL;
+    self->depth = at.depth;
+    
+    window_set_abstract(UNMANAGED_AS_WINDOW(self),
+                        &self->win,
+                        &self->layer,
+                        &self->depth);
+
+    window_add(&self->win, UNMANAGED_AS_WINDOW(self));
+    stacking_add(UNMANAGED_AS_WINDOW(self));
+
+    return self;
+}
+
+void unmanaged_destroy(ObUnmanaged *self)
+{
+    window_cleanup(UNMANAGED_AS_WINDOW(self));
+    stacking_remove(UNMANAGED_AS_WINDOW(self));
+    window_remove(self->win);
+    window_free(UNMANAGED_AS_WINDOW(self));
+}
diff --git a/openbox/unmanaged.h b/openbox/unmanaged.h
new file mode 100644 (file)
index 0000000..a1a3b97
--- /dev/null
@@ -0,0 +1,31 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   unmanaged.h for the Openbox window manager
+   Copyright (c) 2010        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 __unmanaged_h
+#define __unmanaged_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+
+typedef struct _ObUnmanaged ObUnmanaged;
+
+/*! Create a new structure to watch an unmanaged window */
+ObUnmanaged* unmanaged_new(Window w);
+void unmanaged_destroy(ObUnmanaged *self);
+
+#endif
index 0656816b6ab7facaf161964b962dfb49bfdbaa66..967e92be78b821cb59a2a8f641e6ee7b7bea3659 100644 (file)
@@ -73,13 +73,17 @@ void window_set_abstract(ObWindow *self,
 
 #ifdef USE_COMPOSITING
     if (self->type != OB_WINDOW_CLASS_PROMPT) {
-        self->damage = XDamageCreate(obt_display, *self->top,
+        self->damage = XDamageCreate(obt_display, window_top(self),
                                      XDamageReportNonEmpty);
-
-        XCompositeRedirectWindow(obt_display, *self->top,
-                                 CompositeRedirectManual);
     }
 #endif
+
+    composite_redir(self, TRUE);
+}
+
+void window_cleanup(ObWindow *self)
+{
+    composite_redir(self, FALSE);
 }
 
 void window_free(ObWindow *self)
index a88768033dc1baca8fca2a9b6d17c3d7efc1e97e..946525c3ccd20ceb40c6aa71efd492994a8879a5 100644 (file)
@@ -39,6 +39,7 @@ typedef enum {
     OB_WINDOW_CLASS_DOCK,
     OB_WINDOW_CLASS_CLIENT,
     OB_WINDOW_CLASS_INTERNAL,
+    OB_WINDOW_CLASS_UNMANAGED,
     OB_WINDOW_CLASS_PROMPT
 } ObWindowClass;
 
@@ -66,6 +67,7 @@ struct _ObWindow {
     Rect area;
     gint border;
     gboolean mapped;
+    gboolean redir;
 #endif
 };
 
@@ -77,6 +79,8 @@ struct _ObWindow {
     (((ObWindow*)win)->type == OB_WINDOW_CLASS_CLIENT)
 #define WINDOW_IS_INTERNAL(win) \
     (((ObWindow*)win)->type == OB_WINDOW_CLASS_INTERNAL)
+#define WINDOW_IS_UNMANAGED(win) \
+    (((ObWindow*)win)->type == OB_WINDOW_CLASS_UNMANAGED)
 #define WINDOW_IS_PROMPT(win) \
     (((ObWindow*)win)->type == OB_WINDOW_CLASS_PROMPT)
 
@@ -90,12 +94,14 @@ struct _ObPrompt;
 #define WINDOW_AS_DOCK(win) ((struct _ObDock*)win)
 #define WINDOW_AS_CLIENT(win) ((struct _ObClient*)win)
 #define WINDOW_AS_INTERNAL(win) ((struct _ObInternalWindow*)win)
+#define WINDOW_AS_UNMANAGED(win) ((struct _ObUnmanaged*)win)
 #define WINDOW_AS_PROMPT(win) ((struct _ObPrompt*)win)
 
 #define MENUFRAME_AS_WINDOW(menu) ((ObWindow*)menu)
 #define DOCK_AS_WINDOW(dock) ((ObWindow*)dock)
 #define CLIENT_AS_WINDOW(client) ((ObWindow*)client)
 #define INTERNAL_AS_WINDOW(intern) ((ObWindow*)intern)
+#define UNMANAGED_AS_WINDOW(um) ((ObWindow*)um)
 #define PROMPT_AS_WINDOW(prompt) ((ObWindow*)prompt)
 
 void window_startup (gboolean reconfig);
@@ -109,6 +115,10 @@ void      window_set_abstract(ObWindow *self,
                               const Window *top,
                               const ObStackingLayer *layer,
                               const int *depth);
+/*! A subclass of ObWindow must call this when it is going to be destroying
+  itself, but _before_ it destroys the members it sets in
+  window_set_abstract() */
+void      window_cleanup(ObWindow *self);
 void      window_free(ObWindow *self);
 
 ObWindow* window_find  (Window xwin);