don't make windows owned by a screen, make them globally owned so they have a more...
authorDana Jansens <danakj@orodu.net>
Sat, 9 Feb 2008 08:40:17 +0000 (03:40 -0500)
committerDana Jansens <danakj@orodu.net>
Sat, 9 Feb 2008 08:40:17 +0000 (03:40 -0500)
loco/loco.c
loco/screen.c
loco/screen.h
loco/window.c
loco/window.h

index 85d93bd..152e0c0 100644 (file)
@@ -32,6 +32,7 @@
 
 static LocoScreen **screens = NULL;
 static ObtMainLoop *mainloop = NULL;
+static GList       *windows = NULL;
 
 /* XXX stop removing windows from the stacking until they have no more refs */
 
@@ -44,30 +45,36 @@ void COMPOSTER_RAWR(const XEvent *e, gpointer data)
 
     switch (e->type) {
     case CreateNotify:
-        if (e->xcreatewindow.parent == sc->root)
-            loco_screen_add_window(sc, e->xcreatewindow.window);
+        if (e->xcreatewindow.parent == sc->root) {
+            lw = loco_window_new(e->xcreatewindow.window, sc);
+            windows = g_list_prepend(windows, lw);
+        }
         break;
     case DestroyNotify:
         lw = loco_screen_find_window(sc, e->xdestroywindow.window);
         if (lw) {
             loco_window_hide(lw, TRUE);
-            loco_screen_remove_window(sc, lw);
+            loco_window_unref(lw);
+            windows = g_list_remove(windows, lw);
         }
         else
             g_print("destroy notify for unknown window 0x%lx\n",
                     e->xdestroywindow.window);
         break;
     case ReparentNotify:
-        if (e->xreparent.parent == sc->root)
+        if (e->xreparent.parent == sc->root) {
             /* reparented to root */
-            loco_screen_add_window(sc, e->xreparent.window);
+            lw = loco_window_new(e->xreparent.window, sc);
+            windows = g_list_prepend(windows, lw);
+        }
         else {
             /* reparented away from root */
             lw = loco_screen_find_window(sc, e->xreparent.window);
             if (lw) {
                 g_print("window 0x%lx reparented from root\n", lw->id);
-                loco_window_hide(lw, FALSE);
-                loco_screen_remove_window(sc, lw);
+                loco_window_hide(lw, TRUE);
+                loco_window_unref(lw);
+                windows = g_list_remove(windows, lw);
             }
             else
                 g_print("reparent notify away from root for unknown window "
@@ -107,6 +114,25 @@ void COMPOSTER_RAWR(const XEvent *e, gpointer data)
     }
 }
 
+static void find_all_windows(LocoScreen *sc)
+{
+    guint i, nchild;
+    Window w, *children;
+
+    if (!XQueryTree(obt_display, sc->root, &w, &w, &children, &nchild))
+        nchild = 0;
+
+    for (i = 0; i < nchild; ++i)
+        if (children[i] != None) {
+            LocoWindow *lw;
+
+            lw = loco_window_new(children[i], sc);
+            windows = g_list_prepend(windows, lw);
+        }
+
+    if (children) XFree(children);
+}
+
 static gboolean compositor_timeout(gpointer data)
 {
     LocoScreen *sc = data;
@@ -141,6 +167,8 @@ void loco_start_screen(gint number)
         if (!paint_setup(screens[number]))
             loco_stop_screen(number);
         else {
+            find_all_windows(screens[number]);
+
             obt_main_loop_x_add(mainloop, COMPOSTER_RAWR,
                                 screens[number], NULL);
             obt_main_loop_timeout_add(mainloop, REFRESH_RATE,
@@ -152,11 +180,21 @@ void loco_start_screen(gint number)
 
 void loco_stop_screen(gint number)
 {
+    GList *it, *next;
+
     obt_main_loop_x_remove_data(mainloop, COMPOSTER_RAWR, screens[number]);
     obt_main_loop_timeout_remove_data(mainloop,
                                       compositor_timeout, screens[number],
                                       FALSE);
 
+    for (it = windows; it; it = next) {
+        next = g_list_next(it);
+        if (((LocoWindow*)it->data)->screen->number == number) {
+            loco_window_unref(it->data);
+            windows = g_list_delete_link(windows, it);
+        }
+    }
+
     loco_screen_unref(screens[number]);
     screens[number] = NULL;
 }
index b44f316..14938af 100644 (file)
@@ -3,7 +3,6 @@
 #include "list.h"
 #include "obt/display.h"
 
-static void find_all_windows(LocoScreen *sc);
 static void find_visuals(LocoScreen *sc);
 
 static guint window_hash(Window *w) { return *w; }
@@ -43,6 +42,8 @@ LocoScreen* loco_screen_new(gint number)
     //sc->root = loco_window_new(obt_root(number));
     sc->stacking_map = g_hash_table_new((GHashFunc)window_hash,
                                         (GEqualFunc)window_comp);
+    sc->stacking_map_ptr = g_hash_table_new((GHashFunc)g_direct_hash,
+                                            (GEqualFunc)g_direct_equal);
     sc->bindTexImageEXT = (BindEXTFunc)
         glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
     sc->releaseTexImageEXT = (ReleaseEXTFunc)
@@ -63,7 +64,6 @@ LocoScreen* loco_screen_new(gint number)
         XFixesDestroyRegion(obt_display, region);
     }
 
-    find_all_windows(sc);
     loco_screen_redraw(sc);
 
     return sc;
@@ -83,26 +83,12 @@ void loco_screen_unref(LocoScreen *sc)
             XCompositeReleaseOverlayWindow(obt_display, sc->overlay);
 
         g_hash_table_destroy(sc->stacking_map);
+        g_hash_table_destroy(sc->stacking_map_ptr);
 
         g_free(sc);
     }
 }
 
-static void find_all_windows(LocoScreen *sc)
-{
-    guint i, nchild;
-    Window w, *children;
-
-    if (!XQueryTree(obt_display, sc->root, &w, &w, &children, &nchild))
-        nchild = 0;
-
-    for (i = 0; i < nchild; ++i)
-        if (children[i] != None)
-            loco_screen_add_window(sc, children[i]);
-
-    if (children) XFree(children);
-}
-
 static void find_visuals(LocoScreen *sc)
 {
     gint db, stencil, depth;
@@ -170,38 +156,41 @@ static void find_visuals(LocoScreen *sc)
     XFree(fbcons);
 }
 
-void loco_screen_add_window(LocoScreen *sc, Window xwin)
+void loco_screen_add_window(LocoScreen *sc, LocoWindow *lw)
 {
-    LocoWindow *lw;
     LocoList *it;
 
-    if (loco_screen_find_window(sc, xwin)) return;
+    g_print("add window 0x%lx\n", lw->id);
 
-    g_print("add window 0x%lx\n", xwin);
+    /* new windows are at the top */
+    it = loco_list_prepend(&sc->stacking_top, &sc->stacking_bottom, lw);
+    g_hash_table_insert(sc->stacking_map, &lw->id, it);
+    g_hash_table_insert(sc->stacking_map_ptr, &lw, it);
 
-    lw = loco_window_new(xwin, sc);
-    if (lw) {
-        /* new windows are at the top */
-        it = loco_list_prepend(&sc->stacking_top, &sc->stacking_bottom, lw);
-        g_hash_table_insert(sc->stacking_map, &lw->id, it);
-    }
+    loco_window_ref(lw);
+}
 
-    //print_stacking();
+void loco_screen_zombie_window(LocoScreen *sc, LocoWindow *lw)
+{
+    g_print("zombie window 0x%lx\n", lw->id);
+
+    /* the id will no longer be useful, so remove it from the hash */
+    g_hash_table_remove(sc->stacking_map, &lw->id);
 }
 
 void loco_screen_remove_window(LocoScreen *sc, LocoWindow *lw)
 {
-    LocoList *pos = loco_screen_find_stacking(sc, lw->id);
-    g_assert(pos);
+    LocoList *pos;
 
     g_print("remove window 0x%lx\n", lw->id);
 
+    pos = loco_screen_find_stacking_ptr(sc, lw);
+    g_assert(pos);
     loco_list_delete_link(&sc->stacking_top, &sc->stacking_bottom, pos);
     g_hash_table_remove(sc->stacking_map, &lw->id);
+    g_hash_table_remove(sc->stacking_map_ptr, &lw);
 
     loco_window_unref(lw);
-
-    //print_stacking();
 }
 
 struct _LocoWindow* loco_screen_find_window(LocoScreen *sc, Window xwin)
@@ -217,6 +206,11 @@ struct _LocoList* loco_screen_find_stacking(LocoScreen *sc, Window xwin)
     return g_hash_table_lookup(sc->stacking_map, &xwin);
 }
 
+struct _LocoList* loco_screen_find_stacking_ptr(LocoScreen *sc, LocoWindow *lw)
+{
+    return g_hash_table_lookup(sc->stacking_map_ptr, &lw);
+}
+
 void loco_screen_redraw(LocoScreen *sc)
 {
     sc->redraw = TRUE;
index ff46aa5..1cdf6ee 100644 (file)
@@ -47,6 +47,7 @@ typedef struct _LocoScreen {
     /* Maps X Window ID -> LocoList* which is in the stacking_top/bottom list
      */
     GHashTable       *stacking_map;
+    GHashTable       *stacking_map_ptr;
     /* The stacking list goes from top-most to bottom-most window */
     struct _LocoList *stacking_top;
     struct _LocoList *stacking_bottom;
@@ -59,11 +60,14 @@ LocoScreen* loco_screen_new(gint number);
 void loco_screen_ref(LocoScreen *sc);
 void loco_screen_unref(LocoScreen *sc);
 
-void loco_screen_add_window(LocoScreen *sc, Window xwin);
+void loco_screen_add_window(LocoScreen *sc, struct _LocoWindow *lw);
+void loco_screen_zombie_window(LocoScreen *sc, struct _LocoWindow *lw);
 void loco_screen_remove_window(LocoScreen *sc, struct _LocoWindow *lw);
 
 struct _LocoWindow* loco_screen_find_window(LocoScreen *sc, Window xwin);
 struct _LocoList* loco_screen_find_stacking(LocoScreen *sc, Window xwin);
+struct _LocoList* loco_screen_find_stacking_ptr(LocoScreen *sc,
+                                                struct _LocoWindow *lw);
 
 void loco_screen_redraw(LocoScreen *sc);
 
index 92e013f..618c373 100644 (file)
@@ -54,6 +54,8 @@ LocoWindow* loco_window_new(Window xwin, LocoScreen *screen)
         lw->damage = XDamageCreate(obt_display, lw->id, XDamageReportNonEmpty);
     }
 
+    loco_screen_add_window(lw->screen, lw);
+
     if (attrib.map_state != IsUnmapped)
         loco_window_show(lw);
 
@@ -69,6 +71,9 @@ void loco_window_unref(LocoWindow *lw)
 {
     if (lw && --lw->ref == 0) {
         if (!lw->input_only) {
+            texture_destroy(lw);
+            pixmap_destroy(lw);
+
             glDeleteTextures(1, &lw->texname);
 
             obt_display_ignore_errors(TRUE);
@@ -76,6 +81,8 @@ void loco_window_unref(LocoWindow *lw)
             obt_display_ignore_errors(FALSE);
         }
 
+        loco_screen_remove_window(lw->screen, lw);
+
         g_free(lw);
     }
 }
@@ -104,9 +111,10 @@ void loco_window_show(LocoWindow *lw) {
     loco_screen_redraw(lw->screen);
 }
 
-void loco_window_hide(LocoWindow *lw, gboolean destroyed)
+void loco_window_hide(LocoWindow *lw, gboolean gone)
 {
-    /* if destroyed = TRUE, then the window is no longer available */
+    /* if gone = TRUE, then the window is no longer available and we
+       become a zombie */
 
     lw->visible = FALSE;
 
@@ -115,6 +123,11 @@ void loco_window_hide(LocoWindow *lw, gboolean destroyed)
     pixmap_destroy(lw);
 
     loco_screen_redraw(lw->screen);
+
+    if (gone) {
+        loco_screen_zombie_window(lw->screen, lw);
+        lw->id = 0;
+    }
 }
 
 void loco_window_configure(LocoWindow *lw, const XConfigureEvent *e)
index f3c1fc5..1953df5 100644 (file)
@@ -57,7 +57,7 @@ void loco_window_ref(LocoWindow *lw);
 void loco_window_unref(LocoWindow *lw);
 
 void loco_window_show(LocoWindow *lw);
-void loco_window_hide(LocoWindow *lw, gboolean destroyed);
+void loco_window_hide(LocoWindow *lw, gboolean gone);
 
 void loco_window_configure(LocoWindow *lw, const XConfigureEvent *e);
 void loco_window_damage(LocoWindow *lw);