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 */
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 "
}
}
+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;
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,
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;
}
#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; }
//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)
XFixesDestroyRegion(obt_display, region);
}
- find_all_windows(sc);
loco_screen_redraw(sc);
return 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;
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)
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;
/* 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;
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);
lw->damage = XDamageCreate(obt_display, lw->id, XDamageReportNonEmpty);
}
+ loco_screen_add_window(lw->screen, lw);
+
if (attrib.map_state != IsUnmapped)
loco_window_show(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);
obt_display_ignore_errors(FALSE);
}
+ loco_screen_remove_window(lw->screen, lw);
+
g_free(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;
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)
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);