From 5e17e6367bc6235884d14418f1a42d9406804491 Mon Sep 17 00:00:00 2001 From: Dana Jansens Date: Sat, 9 Feb 2008 03:40:17 -0500 Subject: [PATCH] don't make windows owned by a screen, make them globally owned so they have a more clear ownership path --- loco/loco.c | 52 ++++++++++++++++++++++++++++++++++++++------- loco/screen.c | 58 +++++++++++++++++++++++---------------------------- loco/screen.h | 6 +++++- loco/window.c | 17 +++++++++++++-- loco/window.h | 2 +- 5 files changed, 92 insertions(+), 43 deletions(-) diff --git a/loco/loco.c b/loco/loco.c index 85d93bdb..152e0c0e 100644 --- a/loco/loco.c +++ b/loco/loco.c @@ -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; } diff --git a/loco/screen.c b/loco/screen.c index b44f3165..14938aff 100644 --- a/loco/screen.c +++ b/loco/screen.c @@ -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; diff --git a/loco/screen.h b/loco/screen.h index ff46aa54..1cdf6ee0 100644 --- a/loco/screen.h +++ b/loco/screen.h @@ -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); diff --git a/loco/window.c b/loco/window.c index 92e013f0..618c3738 100644 --- a/loco/window.c +++ b/loco/window.c @@ -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) diff --git a/loco/window.h b/loco/window.h index f3c1fc5a..1953df5d 100644 --- a/loco/window.h +++ b/loco/window.h @@ -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); -- 2.39.2