split loco into a bunch of files.
authorDana Jansens <danakj@orodu.net>
Sat, 9 Feb 2008 07:28:06 +0000 (02:28 -0500)
committerDana Jansens <danakj@orodu.net>
Sat, 9 Feb 2008 07:28:25 +0000 (02:28 -0500)
it looks an awful lot like glxcompmgr somehow..

16 files changed:
Makefile.am
loco/glerror.h [new file with mode: 0644]
loco/list.c [new file with mode: 0644]
loco/list.h [new file with mode: 0644]
loco/loco.c
loco/loco.h
loco/paint.c [new file with mode: 0644]
loco/paint.h [new file with mode: 0644]
loco/screen.c [new file with mode: 0644]
loco/screen.h [new file with mode: 0644]
loco/window.c [new file with mode: 0644]
loco/window.h [new file with mode: 0644]
obt/display.c
obt/mainloop.c
obt/mainloop.h
openbox/openbox.c

index f8c1a17..dc38093 100644 (file)
@@ -164,7 +164,16 @@ loco_liboco_la_LIBADD = \
        $(XCOMPOSITE_LIBS) \
        $(GLIB_LIBS)
 loco_liboco_la_SOURCES = \
-       loco/loco.c
+       loco/list.c \
+       loco/list.h \
+       loco/loco.c \
+       loco/loco.h \
+       loco/paint.c \
+       loco/paint.h \
+       loco/screen.c \
+       loco/screen.h \
+       loco/window.c \
+       loco/window.h
 
 ## openbox ##
 
diff --git a/loco/glerror.h b/loco/glerror.h
new file mode 100644 (file)
index 0000000..9d1c719
--- /dev/null
@@ -0,0 +1,38 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   glerror.h for the Openbox compositor
+   Copyright (c) 2008        Derek Foreman
+   Copyright (c) 2008        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 loco__glerror_h
+#define loco__glerror_h
+
+#include <GL/glx.h>
+
+#define glError()                                      \
+{                                                      \
+    /*const GLchar *err_file = strrchr(err_path, '/');*/ \
+    GLenum        gl_error = glGetError();             \
+                                                       \
+    /*++err_file;*/                                        \
+                                                       \
+    for (; (gl_error); gl_error = glGetError())        \
+      g_print("%s: %d caught at line %u\n",    \
+              __FUNCTION__, gl_error, __LINE__);       \
+              /*(const GLchar*)gluErrorString(gl_error)*/ \
+}
+
+#endif
diff --git a/loco/list.c b/loco/list.c
new file mode 100644 (file)
index 0000000..f9bbfb7
--- /dev/null
@@ -0,0 +1,90 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   list.c for the Openbox window manager
+   Copyright (c) 2008        Derek Foreman
+   Copyright (c) 2008        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 "list.h"
+#include "window.h"
+
+LocoList* loco_list_prepend(LocoList **top, LocoList **bottom,
+                            LocoWindow *window)
+{
+    LocoList *n = g_new(LocoList, 1);
+    n->window = window;
+
+    n->prev = NULL;
+    n->next = *top;
+    if (n->next) n->next->prev = n;
+
+    *top = n;
+    if (!*bottom) *bottom = n;
+    return n;
+}
+
+void loco_list_delete_link(LocoList **top, LocoList **bottom,
+                           LocoList *pos)
+{
+    LocoList *prev = pos->prev;
+    LocoList *next = pos->next;
+
+    if (next)
+        next->prev = prev;
+    if (prev)
+        prev->next = next;
+    if (!next)
+        *bottom = prev;
+    if (!prev)
+        *top = next;
+
+    g_free(pos);
+}
+
+void loco_list_move_before(LocoList **top, LocoList **bottom,
+                           LocoList *move, LocoList *before)
+{
+    LocoList *prev, *next;
+
+    /* these won't move it anywhere */
+    if (move == before || move->next == before) return;
+
+    prev = move->prev;
+    next = move->next;
+
+    /* remove it from the list */
+    if (next) next->prev = prev;
+    else      *bottom = prev;
+    if (prev) prev->next = next;
+    else      *top = next;
+
+    /* reinsert it */
+    if (before) {
+        move->next = before;
+        move->prev = before->prev;
+        move->next->prev = move;
+        if (move->prev) move->prev->next = move;
+    }
+    else {
+        /* after the bottom */
+        move->prev = *bottom;
+        move->next = NULL;
+        if (move->prev) move->prev->next = move;
+        *bottom = move;
+    }
+
+    if (!move->prev) *top = move;
+}
+
diff --git a/loco/list.h b/loco/list.h
new file mode 100644 (file)
index 0000000..11d5ddb
--- /dev/null
@@ -0,0 +1,43 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   list.h for the Openbox compositor
+   Copyright (c) 2008        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 loco__list_h
+#define loco__list_h
+
+struct _LocoWindow;
+
+/* To make a new LocoList, create 2 pointers: one for the head, one for the
+   tail.  Initialize them both to NULL.  Then pass them to loco_list_prepend.
+*/
+
+typedef struct _LocoList {
+    struct _LocoList   *next;
+    struct _LocoList   *prev;
+    struct _LocoWindow *window;
+} LocoList;
+
+LocoList* loco_list_prepend(LocoList **top, LocoList **bottom,
+                            struct _LocoWindow *window);
+
+void loco_list_delete_link(LocoList **top, LocoList **bottom,
+                           LocoList *pos);
+
+void loco_list_move_before(LocoList **top, LocoList **bottom,
+                           LocoList *move, LocoList *before);
+
+#endif
index b28f4ef..85d93bd 100644 (file)
    See the COPYING file for a copy of the GNU General Public License.
 */
 
-#include <stdio.h>
+#include "loco.h"
+#include "screen.h"
+#include "window.h"
+#include "paint.h"
+
 #include "obt/mainloop.h"
 #include "obt/display.h"
-#include "obt/mainloop.h"
 #include "obt/prop.h"
-#include <glib.h>
-#include <GL/glx.h>
-#include <GL/glext.h>
-#include <GL/glxext.h>
-#include <GL/glxtokens.h>
-/*
-<dana> you want CreateNotify, DestroyNotify, MapNotify, UnmapNotify, and
-          ConfigureNotify
-          <dana> and then xdamage or whatever
-
-*/
-
-#define glError()                                      \
-{                                                      \
-    /*const GLchar *err_file = strrchr(err_path, '/');*/ \
-    GLenum        gl_error = glGetError();             \
-                                                       \
-    /*++err_file;*/                                        \
-                                                       \
-    for (; (gl_error); gl_error = glGetError())        \
-      fprintf(stderr, "%s: %d caught at line %u\n",    \
-              __FUNCTION__, gl_error, __LINE__);       \
-              /*(const GLchar*)gluErrorString(gl_error)*/ \
-}
 
+#include <glib.h>
 
-#define MAX_DEPTH 32
 #define REFRESH_RATE (G_USEC_PER_SEC/60)
 
-typedef struct {
-    Window id;
-    gint x, y, w, h;
-    gint depth;
-    gboolean input_only;
-    gboolean visible;
-    gint type; /* XXX make this an enum */
-    GLuint texname;
-    Damage damage;
-    Pixmap pixmap;
-    GLXPixmap glpixmap;
-    gboolean damaged;
-} LocoWindow;
-
-typedef struct _LocoList {
-    struct _LocoList *next;
-    struct _LocoList *prev;
-    LocoWindow *window;
-} LocoList;
-
-static Window      loco_root;
-static Window      loco_overlay;
-/* Maps X Window ID -> LocoWindow* */
-static GHashTable *window_map;
-/* Maps X Window ID -> LocoList* which is in the stacking_top/bottom list */
-static GHashTable *stacking_map;
-/* From top to bottom */
-static LocoList   *stacking_top;
-static LocoList   *stacking_bottom;
-static GLXFBConfig glxFBConfig[MAX_DEPTH + 1];
-static int loco_screen_num;
-static gboolean full_redraw_required;
-static gboolean redraw_required;
-
-typedef void (*BindEXTFunc)(Display *, GLXDrawable, int, const int *);
-typedef void (*ReleaseEXTFunc)(Display *, GLXDrawable, int);
-
-BindEXTFunc    BindTexImageEXT;
-ReleaseEXTFunc ReleaseTexImageEXT;
-
-static void show_window(LocoWindow *lw);
-static void remove_window(LocoWindow *lw);
-
-/*
-static void print_stacking()
-{
-    LocoList *it;
-
-    for (it = stacking_top; it; it = it->next) {
-        printf("0x%lx\n", it->window->id);
-    }
-}
-*/
-
-static glong timecompare(GTimeVal *a, GTimeVal *b)
-{
-    glong r;
-    if ((r = a->tv_sec - b->tv_sec)) return r;
-    return a->tv_usec - b->tv_usec;
-}
-
-static void timeadd(GTimeVal *t, glong microseconds)
-{
-    t->tv_usec += microseconds;
-    while (t->tv_usec >= G_USEC_PER_SEC) {
-        t->tv_usec -= G_USEC_PER_SEC;
-        ++t->tv_sec;
-    }
-    while (t->tv_usec < 0) {
-        t->tv_usec += G_USEC_PER_SEC;
-        --t->tv_sec;
-    }
-}
-
-static Bool look_for_destroy_notify(Display *d, XEvent *e, XPointer arg)
-{
-    const Window w = (Window)*arg;
-    return e->type == DestroyNotify && e->xdestroywindow.window == w;
-}
-
-gboolean create_glxpixmap(LocoWindow *lw)
-{
-    static const int attrs[] =
-        { GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT, None };
-    XEvent ce;
-
-    if (!glxFBConfig[lw->depth]) {
-        printf("no glxFBConfig for depth %d for window 0x%lx\n",
-               lw->depth, lw->id);
-        return FALSE;
-    }
-
-    /* make sure the window exists */
-    XGrabServer(obt_display);
-    XSync(obt_display, FALSE);
-
-    if (!XCheckIfEvent(obt_display, &ce, look_for_destroy_notify,
-                       (XPointer)&lw->id))
-    {
-        lw->pixmap = XCompositeNameWindowPixmap(obt_display, lw->id);
-        lw->glpixmap = glXCreatePixmap(obt_display, glxFBConfig[lw->depth],
-                                       lw->pixmap, attrs);
-        if (!lw->glpixmap) {
-            XFreePixmap(obt_display, lw->pixmap);
-            lw->pixmap = None;
-        }
-    }
-
-    XUngrabServer(obt_display);
-    XFlush(obt_display);
-
-    return !!lw->glpixmap;
-}
-
-int bindPixmapToTexture(LocoWindow *lw)
-{
-    if (lw->glpixmap != None)
-        return 1; /* already bound */
-
-    if (!create_glxpixmap(lw))
-        return 0; /* horrible failure */
-
-/*
-    if (screen->queryDrawable (screen->display->display,
-                              texture->pixmap,
-                              GLX_TEXTURE_TARGET_EXT,
-                              &target))
-    {
-       fprintf (stderr, "%s: glXQueryDrawable failed\n", programName);
-
-       glXDestroyGLXPixmap (screen->display->display, texture->pixmap);
-       texture->pixmap = None;
-
-       return FALSE;
-    }
-*/
-
-    glBindTexture(GL_TEXTURE_2D, lw->texname);
-glError();
-    BindTexImageEXT(obt_display, lw->glpixmap, GLX_FRONT_LEFT_EXT, NULL);
-
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-    return 1;
-}
-
-void destroy_glxpixmap(LocoWindow *lw)
-{
-    if (lw->glpixmap) {
-        glBindTexture(GL_TEXTURE_2D, lw->texname);
-        ReleaseTexImageEXT(obt_display, lw->glpixmap, GLX_FRONT_LEFT_EXT);
-        glBindTexture(GL_TEXTURE_2D, 0);
-
-               obt_display_ignore_errors(TRUE);
-        glXDestroyGLXPixmap(obt_display, lw->glpixmap);
-        obt_display_ignore_errors(FALSE);
-
-        XFreePixmap(obt_display, lw->pixmap);
-
-        lw->pixmap = None;
-        lw->glpixmap = None;
-    }
-}
-
-static void full_composite(void)
-{
-    int ret;
-    LocoList *it;
-
-    /* XXX if (full_redraw_required) */
-        glClear(GL_COLOR_BUFFER_BIT);
-
-    for (it = stacking_bottom; it != stacking_top; it = it->prev) {
-        if (it->window->input_only) continue;
-        if (!it->window->visible)   continue;
-        /* XXX if (!full_redraw_required && !it->window->damaged) continue; */
-
-        if (!full_redraw_required) {
-            /* XXX if the window is transparent, then clear the background
-               behind it */
-        }
-
-        glBindTexture(GL_TEXTURE_2D, it->window->texname);
-        ret = bindPixmapToTexture(it->window);
-        if (ret) {
-            glBegin(GL_QUADS);
-            glColor3f(1.0, 1.0, 1.0);
-            glVertex2i(it->window->x, it->window->y);
-            glTexCoord2f(1, 0);
-            glVertex2i(it->window->x + it->window->w, it->window->y);
-            glTexCoord2f(1, 1);
-            glVertex2i(it->window->x + it->window->w,
-                       it->window->y + it->window->h);
-            glTexCoord2f(0, 1);
-            glVertex2i(it->window->x, it->window->y + it->window->h);
-            glTexCoord2f(0, 0);
-            glEnd();
-        }
-
-        it->window->damaged = FALSE;
-    }
-    glXSwapBuffers(obt_display, loco_overlay);
-
-    full_redraw_required = redraw_required = FALSE;
-}
-
-static LocoList* loco_list_prepend(LocoList **top, LocoList **bottom,
-                                   LocoWindow *window)
-{
-    LocoList *n = g_new(LocoList, 1);
-    n->window = window;
-
-    n->prev = NULL;
-    n->next = *top;
-    if (n->next) n->next->prev = n;
-
-    *top = n;
-    if (!*bottom) *bottom = n;
-    return n;
-}
-
-static void loco_list_delete_link(LocoList **top, LocoList **bottom,
-                                  LocoList *pos)
-{
-    LocoList *prev = pos->prev;
-    LocoList *next = pos->next;
-
-    if (next)
-        next->prev = prev;
-    if (prev)
-        prev->next = next;
-    if (!next)
-        *bottom = prev;
-    if (!prev)
-        *top = next;
-
-    g_free(pos);
-}
-
-static void loco_list_move_before(LocoList **top, LocoList **bottom,
-                                  LocoList *move, LocoList *before)
-{
-    LocoList *prev, *next;
-
-    /* these won't move it anywhere */
-    if (move == before || move->next == before) return;
-
-    prev = move->prev;
-    next = move->next;
-
-    /* remove it from the list */
-    if (next) next->prev = prev;
-    else      *bottom = prev;
-    if (prev) prev->next = next;
-    else      *top = next;
-
-    /* reinsert it */
-    if (before) {
-        move->next = before;
-        move->prev = before->prev;
-        move->next->prev = move;
-        if (move->prev) move->prev->next = move;
-    }
-    else {
-        /* after the bottom */
-        move->prev = *bottom;
-        move->next = NULL;
-        if (move->prev) move->prev->next = move;
-        *bottom = move;
-    }
-
-    if (!move->prev) *top = move;
-}
-
-/* Returns a LocoWindow structure */
-static LocoWindow* find_window(Window window)
-{
-    return g_hash_table_lookup(window_map, &window);
-}
-
-/* Returns a node from the stacking_top/bottom list */
-static LocoList* find_stacking(Window window)
-{
-    return g_hash_table_lookup(stacking_map, &window);
-}
-
-static void add_window(Window window)
-{
-    LocoWindow *lw;
-    LocoList *it;
-    XWindowAttributes attrib;
+static LocoScreen **screens = NULL;
+static ObtMainLoop *mainloop = NULL;
 
-    printf("add window 0x%lx\n", window);
-
-    if (!XGetWindowAttributes(obt_display, window, &attrib))
-        return;
-
-    lw = g_new0(LocoWindow, 1);
-    lw->id = window;
-    lw->input_only = attrib.class == InputOnly;
-    lw->x = attrib.x;
-    lw->y = attrib.y;
-    lw->w = attrib.width;
-    lw->h = attrib.height;
-    lw->depth = attrib.depth;
-
-    g_hash_table_insert(window_map, &lw->id, lw);
-    /* new windows are at the top */
-    it = loco_list_prepend(&stacking_top, &stacking_bottom, lw);
-    g_hash_table_insert(stacking_map, &lw->id, it);
-
-    if (!lw->input_only) {
-        glGenTextures(1, &lw->texname);
-        //  glTexImage2D(TARGET, 0, GL_RGB, lw->w, lw->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
-        lw->damage = XDamageCreate(obt_display, window, XDamageReportNonEmpty);
-    }
-
-    //print_stacking();
-
-    if (attrib.map_state != IsUnmapped)
-        show_window(lw);
-}
-
-static void remove_window(LocoWindow *lw)
-{
-    printf("remove window 0x%lx\n", lw->id);
-
-    LocoList *pos = find_stacking(lw->id);
-    g_assert(pos);
-
-    if (!lw->input_only) {
-        glDeleteTextures(1, &lw->texname);
-               obt_display_ignore_errors(TRUE);
-               XDamageDestroy(obt_display, lw->damage);
-        obt_display_ignore_errors(FALSE);
-    }
-
-    loco_list_delete_link(&stacking_top, &stacking_bottom, pos);
-    g_hash_table_remove(stacking_map, &lw->id);
-    g_hash_table_remove(window_map, &lw->id);
-
-    g_free(lw);
-
-    //print_stacking();
-}
-
-static void show_window(LocoWindow *lw)
-{
-    guint32 *type;
-    guint i, ntype;
-
-    lw->visible = TRUE;
-
-    /* get the window's semantic type (for different effects!) */
-    lw->type = 0; /* XXX set this to the default type */
-    if (OBT_PROP_GETA32(lw->id, NET_WM_WINDOW_TYPE, ATOM, &type, &ntype)) {
-        /* use the first value that we know about in the array */
-        for (i = 0; i < ntype; ++i) {
-            /* XXX SET THESE TO AN ENUM'S VALUES */
-            if (type[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DESKTOP))
-                lw->type = 1;
-            if (type[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_MENU))
-                lw->type = 2;
-            /* XXX there are more TYPES that need to be added to prop.h */
-        }
-        g_free(type);
-    }
-
-    full_redraw_required = redraw_required = TRUE;
-}
-
-static void hide_window(LocoWindow *lw, gboolean destroyed)
-{
-    /* if destroyed, then the window is no longer available */
-    lw->visible = FALSE;
-    destroy_glxpixmap(lw);
-
-    full_redraw_required = redraw_required = TRUE;
-}
-
-static void configure_window(LocoWindow *lw, const XConfigureEvent *e)
-{
-    LocoList *above, *pos;
-
-    pos = find_stacking(e->window);
-    above = find_stacking(e->above);
-
-    g_assert(pos != NULL && pos->window != NULL);
-    if (e->above && !above)
-        printf("missing windows from the stacking list!!\n");
-
-    if ((lw->x != e->x) || (lw->y != e->y)) {
-        lw->x = e->x;
-        lw->y = e->y;
-
-        full_redraw_required = redraw_required = TRUE;
-    }
-        
-    if ((lw->w != e->width) || (lw->h != e->height)) {
-        lw->w = e->width;
-        lw->h = e->height;
-
-        destroy_glxpixmap(lw);
-
-        full_redraw_required = redraw_required = TRUE;
-    }
-
-    if (pos->next != above) {
-        //printf("Window 0x%lx above 0x%lx\n", pos->window->id,
-        //       above ? above->window->id : 0);
-        loco_list_move_before(&stacking_top, &stacking_bottom, pos, above);
-
-        full_redraw_required = redraw_required = TRUE;
-    }
-}
-
-static void damage_window(LocoWindow *lw)
-{
-    LocoList *it, *pos;
-
-    pos = find_stacking(lw->id);
-
-    /* XXX if it is transparent, then damage any windows below it that
-       intersect */
-
-    /* damage any windows above it that intersect */
-    for (it = pos; it; it = it->prev) {
-        const LocoWindow *lwa = it->window;
-        if (lwa->x < lw->x + lw->w && lwa->x + lwa->w > lw->x &&
-            lwa->y < lw->y + lw->h && lwa->y + lwa->h > lw->y)
-        {
-            it->window->damaged = TRUE;
-        }
-    }
-
-    /* mark the damage as fixed - we know about it now */
-    obt_display_ignore_errors(TRUE);
-    XDamageSubtract(obt_display, lw->damage, None, None);
-    obt_display_ignore_errors(FALSE);
-
-    lw->damaged = TRUE;
-    redraw_required = TRUE;
-}
+/* XXX stop removing windows from the stacking until they have no more refs */
 
 void COMPOSTER_RAWR(const XEvent *e, gpointer data)
 {
-    //g_print("COMPOSTER_RAWR() %d\n", e->type);
+    LocoScreen *sc = data;
+    LocoWindow *lw = NULL;
 
-    if (e->type == ConfigureNotify) {
-        LocoWindow *lw;
+    /*g_print("COMPOSTER_RAWR() %d\n", e->type);*/
 
-        lw = find_window(e->xconfigure.window);
-        if (lw)
-            configure_window(lw, &e->xconfigure);
-        //print_stacking();
-    }
-    else if (e->type == CreateNotify) {
-        add_window(e->xmap.window);
-    }
-    else if (e->type == DestroyNotify) {
-        LocoWindow *lw = find_window(e->xdestroywindow.window);
+    switch (e->type) {
+    case CreateNotify:
+        if (e->xcreatewindow.parent == sc->root)
+            loco_screen_add_window(sc, e->xcreatewindow.window);
+        break;
+    case DestroyNotify:
+        lw = loco_screen_find_window(sc, e->xdestroywindow.window);
         if (lw) {
-            hide_window(lw, TRUE);
-            remove_window(lw);
+            loco_window_hide(lw, TRUE);
+            loco_screen_remove_window(sc, lw);
         }
         else
-            printf("destroy notify for unknown window 0x%lx\n",
-                   e->xdestroywindow.window);
-    }
-    else if (e->type == ReparentNotify) {
-        if (e->xreparent.parent == loco_root)
-            add_window(e->xreparent.window);
+            g_print("destroy notify for unknown window 0x%lx\n",
+                    e->xdestroywindow.window);
+        break;
+    case ReparentNotify:
+        if (e->xreparent.parent == sc->root)
+            /* reparented to root */
+            loco_screen_add_window(sc, e->xreparent.window);
         else {
-            LocoWindow *lw = find_window(e->xreparent.window);
+            /* reparented away from root */
+            lw = loco_screen_find_window(sc, e->xreparent.window);
             if (lw) {
-                printf("window 0x%lx reparented from root\n", lw->id);
-                hide_window(lw, FALSE);
-                remove_window(lw);
+                g_print("window 0x%lx reparented from root\n", lw->id);
+                loco_window_hide(lw, FALSE);
+                loco_screen_remove_window(sc, lw);
             }
             else
-                printf("reparent notify away from root for unknown window "
-                       "0x%lx\n", e->xreparent.window);
+                g_print("reparent notify away from root for unknown window "
+                        "0x%lx\n", e->xreparent.window);
         }
-    }
-
-    else if (e->type == MapNotify) {
-        LocoWindow *lw = find_window(e->xmap.window);
-        if (lw)
-            show_window(lw);
-        else
-            printf("map notify for unknown window 0x%lx\n",
-                   e->xmap.window);
-    }
-    else if (e->type == UnmapNotify) {
-        LocoWindow *lw = find_window(e->xunmap.window);
-        if (lw)
-            hide_window(lw, FALSE);
-        else
-            printf("unmap notify for unknown window 0x%lx\n",
-                   e->xunmap.window);
-    }
-    else if (e->type == obt_display_extension_damage_basep + XDamageNotify) {
-        const XDamageNotifyEvent *de;
-        LocoWindow *lw;
-
-        de = (const XDamageNotifyEvent*)e;
-        lw = find_window(de->drawable);
-        if (lw) {
-            damage_window(lw);
-        }
-        else if (de->drawable == loco_root) {
+        break;
+    case MapNotify:
+        lw = loco_screen_find_window(sc, e->xmap.window);
+        if (lw) loco_window_show(lw);
+        else g_print("map notify for unknown window 0x%lx\n", e->xmap.window);
+        break;
+    case UnmapNotify:
+        lw = loco_screen_find_window(sc, e->xunmap.window);
+        if (lw) loco_window_hide(lw, FALSE);
+        else g_print("unmap notify for unknown window 0x%lx\n",
+                     e->xunmap.window);
+        break;
+    case ConfigureNotify:
+        lw = loco_screen_find_window(sc, e->xconfigure.window);
+        if (lw) loco_window_configure(lw, &e->xconfigure);
+        break;
+    default:
+        if (e->type == obt_display_extension_damage_basep + XDamageNotify) {
+            const XDamageNotifyEvent *de = (const XDamageNotifyEvent*)e;
+
+            lw = loco_screen_find_window(sc, de->drawable);
+            if (de->drawable == sc->root)
+                loco_screen_redraw(sc);
+            else if (lw)
+                loco_screen_redraw(sc);
+
+            /* mark the damage as fixed - we know about it now */
+            obt_display_ignore_errors(TRUE);
             XDamageSubtract(obt_display, de->damage, None, None);
-            full_redraw_required = redraw_required = TRUE;
+            obt_display_ignore_errors(FALSE);
         }
     }
 }
 
-static void find_all_windows(gint screen)
+static gboolean compositor_timeout(gpointer data)
 {
-    guint i, nchild;
-    Window w, *children;
+    LocoScreen *sc = data;
 
-    if (!XQueryTree(obt_display, loco_root, &w, &w, &children, &nchild))
-        nchild = 0;
+    if (sc->redraw)
+        paint_everything(sc);
 
-    for (i = 0; i < nchild; ++i)
-        if (children[i] != None) add_window(children[i]);
-
-    if (children) XFree(children);
+    return TRUE; /* repeat */
 }
 
-static gboolean compositor_timeout(gpointer data)
+void loco_startup(ObtMainLoop *loop)
 {
-    if (redraw_required)
-        full_composite();
-    return TRUE; /* repeat */
+    mainloop = loop;
+    screens = g_new0(LocoScreen*, ScreenCount(obt_display));
 }
 
-static guint window_hash(Window *w) { return *w; }
-static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
-
-void loco_set_mainloop(gint screen_num, ObtMainLoop *loop)
+void loco_shutdown()
 {
-    int db, stencil, depth;
-    int i, j, value, count;
-    int w, h;
-    XVisualInfo *vi, tvis, *visinfo;
-    GLXFBConfig *allfbconfigs;
-    int numfbconfigs;
-    GLXContext cont;
-    static int config[] =
-        { GLX_DEPTH_SIZE, 1, GLX_DOUBLEBUFFER, GLX_RGBA, None };
-    static const int drawable_tfp_attrs[] =
-        {
-            GLX_CONFIG_CAVEAT, GLX_NONE,
-            GLX_DOUBLEBUFFER, False,
-            GLX_DEPTH_SIZE, 0,
-            GLX_RED_SIZE, 1,
-            GLX_GREEN_SIZE, 1,
-            GLX_BLUE_SIZE, 1,
-            GLX_ALPHA_SIZE, 1,
-            GLX_RENDER_TYPE, GLX_RGBA_BIT,
-            GLX_BIND_TO_TEXTURE_RGBA_EXT, True, // additional for tfp
-            None
-        };
-
-    loco_screen_num = screen_num;
-    loco_root = obt_root(screen_num);
-    loco_overlay = XCompositeGetOverlayWindow(obt_display, loco_root);
-    XserverRegion region = XFixesCreateRegion(obt_display, NULL, 0);
-
-    XFixesSetWindowShapeRegion (obt_display,
-                                loco_overlay,
-                                ShapeBounding,
-                                0, 0,
-                                0);
-    XFixesSetWindowShapeRegion (obt_display,
-                                loco_overlay,
-                                ShapeInput,
-                                0, 0,
-                                region);
-
-    XFixesDestroyRegion (obt_display, region);
-
-    vi = glXChooseVisual(obt_display, screen_num, config);
-    cont = glXCreateContext(obt_display, vi, NULL, GL_TRUE);
-    if (cont == NULL)
-        printf("context creation failed\n");
-    glXMakeCurrent(obt_display, loco_overlay, cont);
+    int i;
+    for (i = 0; i < ScreenCount(obt_display); ++i)
+        loco_screen_unref(screens[i]);
 
-    BindTexImageEXT = (BindEXTFunc)
-        glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
-    ReleaseTexImageEXT = (ReleaseEXTFunc)
-        glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
-
-    w = WidthOfScreen(ScreenOfDisplay(obt_display, screen_num));
-    h = HeightOfScreen(ScreenOfDisplay(obt_display, screen_num));
-    glViewport(0, 0, w, h);
-    glMatrixMode(GL_PROJECTION);
-    glLoadIdentity();
-printf("Setting up an orthographic projection of %dx%d\n", w, h);
-    glOrtho(0, w, h, 0.0, -1.0, 100.0);
-    glMatrixMode(GL_MODELVIEW);
-    glLoadIdentity();
-    glClear(GL_COLOR_BUFFER_BIT);
-    glEnable(GL_TEXTURE_2D);
-glError();
-    glXSwapBuffers(obt_display, loco_overlay);
-    glClearColor(1.0, 0.0, 0.0, 1.0);
-//    glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
-//    glEnable(GL_BLEND);
-
-    allfbconfigs = glXChooseFBConfig(obt_display,
-                                     loco_screen_num,
-                                     drawable_tfp_attrs,
-                                     &numfbconfigs);
-
-    db = 32767;
-    stencil = 32767;
-    depth = 32767;
-    for (i = 0; i <= MAX_DEPTH; i++) {
-        VisualID vid;
-
-        vid = 0;
-        glxFBConfig[i] = 0;
-
-        tvis.depth = i;
-        visinfo = XGetVisualInfo(obt_display, VisualDepthMask, &tvis, &count);
-        /* pick the nicest visual for the depth */
-        for (j = 0; j < count; j++) {
-            glXGetConfig(obt_display, &visinfo[j], GLX_USE_GL, &value);
-            if (!value)
-                continue;
-
-            glXGetConfig(obt_display, &visinfo[j], GLX_DOUBLEBUFFER, &value);
-            if (value > db)
-                continue;
-            db = value;
-
-            glXGetConfig(obt_display, &visinfo[j], GLX_STENCIL_SIZE, &value);
-            if (value > stencil)
-                continue;
-            stencil = value;
-
-            glXGetConfig(obt_display, &visinfo[j], GLX_DEPTH_SIZE, &value);
-            if (value > depth)
-                continue;
-            depth = value;
-
-            /* use this visual */
-            vid = visinfo[j].visualid;
-        }
-
-        if (!vid)
-            continue;
-
-        printf("found visual %d\n", i);
+    g_free(screens);
+    screens = NULL;
+}
 
-        /* find the fbconfig for this depth/visual */
-        for(j = 0; j < numfbconfigs; ++j) {
-            glXGetFBConfigAttrib(obt_display, allfbconfigs[j],
-                                 GLX_VISUAL_ID, &value);
-            if (value == (int)vid) {
-                glxFBConfig[i] = allfbconfigs[j]; /* save it */
-                printf("supporting depth %d\n", i);
-                break; /* next depth */
-            }
+void loco_start_screen(gint number)
+{
+    if (!screens[number])
+        screens[number] = loco_screen_new(number);
+    if (screens[number]) {
+        if (!paint_setup(screens[number]))
+            loco_stop_screen(number);
+        else {
+            obt_main_loop_x_add(mainloop, COMPOSTER_RAWR,
+                                screens[number], NULL);
+            obt_main_loop_timeout_add(mainloop, REFRESH_RATE,
+                                      (GSourceFunc)compositor_timeout,
+                                      screens[number], g_direct_equal, NULL);
         }
     }
+}
 
-    XFree(allfbconfigs);
-
-    obt_main_loop_x_add(loop, COMPOSTER_RAWR, NULL, NULL);
-    window_map = g_hash_table_new((GHashFunc)window_hash,
-                                  (GEqualFunc)window_comp);
-    stacking_map = g_hash_table_new((GHashFunc)window_hash,
-                                    (GEqualFunc)window_comp);
-    stacking_top = stacking_bottom = NULL;
-
-    XGrabServer(obt_display);
-
-    XCompositeRedirectSubwindows(obt_display, loco_root,
-                                 CompositeRedirectManual);
-    find_all_windows(screen_num);
-
-    XUngrabServer(obt_display);
+void loco_stop_screen(gint number)
+{
+    obt_main_loop_x_remove_data(mainloop, COMPOSTER_RAWR, screens[number]);
+    obt_main_loop_timeout_remove_data(mainloop,
+                                      compositor_timeout, screens[number],
+                                      FALSE);
 
-    full_redraw_required = redraw_required = TRUE;
+    loco_screen_unref(screens[number]);
+    screens[number] = NULL;
+}
 
-    obt_main_loop_timeout_add(loop, REFRESH_RATE,
-                              (GSourceFunc)compositor_timeout,
-                              NULL, NULL, NULL);
+void loco_reconfigure_screen(gint number)
+{
+    /* reload stuff.. */
 }
 
-void loco_shutdown(void)
+gboolean loco_on_screen(gint number)
 {
+    return screens[number] != NULL;
 }
index 8d64529..80d3f15 100644 (file)
 #ifndef loco__loco_h
 #define loco__loco_h
 
+#include <glib.h>
+
 struct _ObtMainLoop;
 
-void loco_set_mainloop(gint ob_screen, struct _ObtMainLoop *loop);
-void loco_shutdown(void);
+void loco_startup(struct _ObtMainLoop *loop);
+void loco_shutdown();
+
+void loco_start_screen(gint number);
+void loco_stop_screen(gint number);
+
+void loco_reconfigure_screen(gint number);
+
+gboolean loco_on_screen(gint number);
 
 
 #endif
diff --git a/loco/paint.c b/loco/paint.c
new file mode 100644 (file)
index 0000000..dc87f08
--- /dev/null
@@ -0,0 +1,102 @@
+#include "paint.h"
+#include "screen.h"
+#include "list.h"
+#include "window.h"
+#include "glerror.h"
+
+#include "obt/display.h"
+
+#include <GL/glx.h>
+#include <GL/glext.h>
+#include <GL/glxext.h>
+#include <GL/glxtokens.h>
+
+static int context_visual_config[] = {
+    GLX_DEPTH_SIZE, 1,
+    GLX_DOUBLEBUFFER,
+    GLX_RGBA,
+    None
+};
+
+gboolean paint_setup(LocoScreen *sc)
+{
+    XVisualInfo *vi;
+    GLXContext context;
+    gint w, h;
+    
+    w = WidthOfScreen(ScreenOfDisplay(obt_display, sc->number));
+    h = HeightOfScreen(ScreenOfDisplay(obt_display, sc->number));
+
+    vi = glXChooseVisual(obt_display, sc->number, context_visual_config);
+    context = glXCreateContext(obt_display, vi, NULL, GL_TRUE);
+    if (context == NULL) {
+        g_print("context creation failed\n");
+        return FALSE;
+    }
+    glXMakeCurrent(obt_display, sc->overlay, context);
+
+    glViewport(0, 0, w, h);
+    glMatrixMode(GL_PROJECTION);
+    glLoadIdentity();
+    g_print("Setting up an orthographic projection of %dx%d\n", w, h);
+    glOrtho(0, w, h, 0.0, -1.0, 100.0);
+    glMatrixMode(GL_MODELVIEW);
+    glLoadIdentity();
+    glClear(GL_COLOR_BUFFER_BIT);
+    glEnable(GL_TEXTURE_2D);
+glError();
+    glXSwapBuffers(obt_display, sc->overlay);
+    glClearColor(0.4, 0.4, 0.4, 1.0);
+/*
+    glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+    glEnable(GL_BLEND);
+*/
+    return TRUE;
+}
+
+void paint_everything(LocoScreen *sc)
+{
+    int ret;
+    LocoList *it;
+
+    /* XXX if (full_redraw_required) */
+        glClear(GL_COLOR_BUFFER_BIT);
+
+    for (it = sc->stacking_bottom; it != NULL; it = it->prev) {
+        if (it->window->id == sc->overlay) continue;
+        if (it->window->input_only) continue;
+        if (!it->window->visible)   continue;
+        /* XXX if (!full_redraw_required && !it->window->damaged) continue; */
+
+        /* XXX if (!full_redraw_required) {
+           /\* XXX if the window is transparent, then clear the background
+           behind it *\/
+        }*/
+
+        /* get the window's updated contents
+           XXX if animating the window, then don't do this, depending
+        */
+        loco_window_update_pixmap(it->window);
+
+        glBindTexture(GL_TEXTURE_2D, it->window->texname);
+        if (ret) {
+            glBegin(GL_QUADS);
+            glColor3f(1.0, 1.0, 1.0);
+            glVertex2i(it->window->x, it->window->y);
+            glTexCoord2f(1, 0);
+            glVertex2i(it->window->x + it->window->w, it->window->y);
+            glTexCoord2f(1, 1);
+            glVertex2i(it->window->x + it->window->w,
+                       it->window->y + it->window->h);
+            glTexCoord2f(0, 1);
+            glVertex2i(it->window->x, it->window->y + it->window->h);
+            glTexCoord2f(0, 0);
+            glEnd();
+        }
+
+        it->window->damaged = FALSE;
+    }
+    glXSwapBuffers(obt_display, sc->overlay);
+
+    loco_screen_redraw_done(sc);
+}
diff --git a/loco/paint.h b/loco/paint.h
new file mode 100644 (file)
index 0000000..30ade3e
--- /dev/null
@@ -0,0 +1,30 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   paint.h for the Openbox compositor
+   Copyright (c) 2008        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 loco__paint_h
+#define loco__paint_h
+
+#include <glib.h>
+
+struct _LocoScreen;
+
+gboolean paint_setup(struct _LocoScreen *sc);
+
+void paint_everything(struct _LocoScreen *sc);
+
+#endif
diff --git a/loco/screen.c b/loco/screen.c
new file mode 100644 (file)
index 0000000..b44f316
--- /dev/null
@@ -0,0 +1,228 @@
+#include "screen.h"
+#include "window.h"
+#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; }
+static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
+
+static const int drawable_tfp_attrs[] = {
+    GLX_CONFIG_CAVEAT, GLX_NONE,
+    GLX_DOUBLEBUFFER, FALSE,
+    GLX_DEPTH_SIZE, 0,
+    GLX_RED_SIZE, 1,
+    GLX_GREEN_SIZE, 1,
+    GLX_BLUE_SIZE, 1,
+    GLX_ALPHA_SIZE, 1,
+    GLX_RENDER_TYPE, GLX_RGBA_BIT,
+    GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
+    None
+};
+
+LocoScreen* loco_screen_new(gint number)
+{
+    LocoScreen *sc;
+
+    /* try get the root redirect */
+    obt_display_ignore_errors(TRUE);
+    XCompositeRedirectSubwindows(obt_display, obt_root(number),
+                                 CompositeRedirectManual);
+    obt_display_ignore_errors(FALSE);
+    if (obt_display_error_occured) {
+        g_message("Another composite manager is running on screen %d", number);
+        return NULL;
+    }
+
+    sc = g_new0(LocoScreen, 1);
+    sc->ref = 1;
+    sc->number = number;
+    sc->root = obt_root(number);
+    //sc->root = loco_window_new(obt_root(number));
+    sc->stacking_map = g_hash_table_new((GHashFunc)window_hash,
+                                        (GEqualFunc)window_comp);
+    sc->bindTexImageEXT = (BindEXTFunc)
+        glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
+    sc->releaseTexImageEXT = (ReleaseEXTFunc)
+        glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
+
+    find_visuals(sc);
+
+    sc->overlay = XCompositeGetOverlayWindow(obt_display, sc->root);
+
+    if (sc->overlay) {
+        XserverRegion region;
+
+        region = XFixesCreateRegion(obt_display, NULL, 0);
+        XFixesSetWindowShapeRegion(obt_display, sc->overlay,
+                                   ShapeBounding, 0, 0, 0);
+        XFixesSetWindowShapeRegion(obt_display, sc->overlay,
+                                   ShapeInput, 0, 0, region);
+        XFixesDestroyRegion(obt_display, region);
+    }
+
+    find_all_windows(sc);
+    loco_screen_redraw(sc);
+
+    return sc;
+}
+
+void loco_screen_ref(LocoScreen *sc)
+{
+    ++sc->ref;
+}
+
+void loco_screen_unref(LocoScreen *sc)
+{
+    if (sc && --sc->ref == 0) {
+        /*XXX loco_window_unref(sc->root);*/
+
+        if (sc->overlay)
+            XCompositeReleaseOverlayWindow(obt_display, sc->overlay);
+
+        g_hash_table_destroy(sc->stacking_map);
+
+        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;
+    gint i, j, value, count;
+    XVisualInfo tvis, *visinfo;
+    GLXFBConfig *fbcons;
+    gint numfb;
+
+    fbcons = glXChooseFBConfig(obt_display, sc->number,
+                               drawable_tfp_attrs, &numfb);
+
+    db = 32767;
+    stencil = 32767;
+    depth = 32767;
+    for (i = 0; i <= LOCO_SCREEN_MAX_DEPTH; i++) {
+        VisualID vid;
+
+        vid = 0;
+        sc->glxFBConfig[i] = 0;
+
+        tvis.depth = i;
+        visinfo = XGetVisualInfo(obt_display, VisualDepthMask, &tvis, &count);
+        /* pick the nicest visual for the depth */
+        for (j = 0; j < count; j++) {
+            glXGetConfig(obt_display, &visinfo[j], GLX_USE_GL, &value);
+            if (!value)
+                continue;
+
+            glXGetConfig(obt_display, &visinfo[j], GLX_DOUBLEBUFFER, &value);
+            if (value > db)
+                continue;
+            db = value;
+
+            glXGetConfig(obt_display, &visinfo[j], GLX_STENCIL_SIZE, &value);
+            if (value > stencil)
+                continue;
+            stencil = value;
+
+            glXGetConfig(obt_display, &visinfo[j], GLX_DEPTH_SIZE, &value);
+            if (value > depth)
+                continue;
+            depth = value;
+
+            /* use this visual */
+            vid = visinfo[j].visualid;
+        }
+
+        if (!vid)
+            continue;
+
+        g_print("found visual %d\n", i);
+
+        /* find the fbconfig for this depth/visual */
+        for(j = 0; j < numfb; ++j) {
+            glXGetFBConfigAttrib(obt_display, fbcons[j],
+                                 GLX_VISUAL_ID, &value);
+            if (value == (int)vid) {
+                sc->glxFBConfig[i] = fbcons[j]; /* save it */
+                g_print("supporting depth %d\n", i);
+                break; /* next depth */
+            }
+        }
+    }
+
+    XFree(fbcons);
+}
+
+void loco_screen_add_window(LocoScreen *sc, Window xwin)
+{
+    LocoWindow *lw;
+    LocoList *it;
+
+    if (loco_screen_find_window(sc, xwin)) return;
+
+    g_print("add window 0x%lx\n", xwin);
+
+    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);
+    }
+
+    //print_stacking();
+}
+
+void loco_screen_remove_window(LocoScreen *sc, LocoWindow *lw)
+{
+    LocoList *pos = loco_screen_find_stacking(sc, lw->id);
+    g_assert(pos);
+
+    g_print("remove window 0x%lx\n", lw->id);
+
+    loco_list_delete_link(&sc->stacking_top, &sc->stacking_bottom, pos);
+    g_hash_table_remove(sc->stacking_map, &lw->id);
+
+    loco_window_unref(lw);
+
+    //print_stacking();
+}
+
+struct _LocoWindow* loco_screen_find_window(LocoScreen *sc, Window xwin)
+{
+    LocoList *it;
+
+    it = g_hash_table_lookup(sc->stacking_map, &xwin);
+    return (it ? it->window : NULL);
+}
+
+struct _LocoList* loco_screen_find_stacking(LocoScreen *sc, Window xwin)
+{
+    return g_hash_table_lookup(sc->stacking_map, &xwin);
+}
+
+void loco_screen_redraw(LocoScreen *sc)
+{
+    sc->redraw = TRUE;
+}
+
+void loco_screen_redraw_done(LocoScreen *sc)
+{
+    sc->redraw = TRUE;
+}
diff --git a/loco/screen.h b/loco/screen.h
new file mode 100644 (file)
index 0000000..ff46aa5
--- /dev/null
@@ -0,0 +1,72 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   screen.h for the Openbox compositor
+   Copyright (c) 2008        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 loco__screen_h
+#define loco__screen_h
+
+#include <X11/Xlib.h>
+#include <glib.h>
+#include <GL/glx.h>
+
+#define LOCO_SCREEN_MAX_DEPTH 32
+
+struct _LocoWindow;
+struct _LocoList;
+
+typedef void (*BindEXTFunc)(Display *, GLXDrawable, int, const int *);
+typedef void (*ReleaseEXTFunc)(Display *, GLXDrawable, int);
+
+typedef struct _LocoScreen {
+    gint         ref;
+
+    gint         number;
+
+    //struct _Window *root;
+    Window          root;
+    Window          overlay;
+
+    GLXFBConfig  glxFBConfig[LOCO_SCREEN_MAX_DEPTH + 1];
+
+    gboolean     redraw;
+
+    /* Maps X Window ID -> LocoList* which is in the stacking_top/bottom list
+     */
+    GHashTable       *stacking_map;
+    /* The stacking list goes from top-most to bottom-most window */
+    struct _LocoList *stacking_top;
+    struct _LocoList *stacking_bottom;
+
+    BindEXTFunc    bindTexImageEXT;
+    ReleaseEXTFunc releaseTexImageEXT;
+} LocoScreen;
+
+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_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);
+
+void loco_screen_redraw(LocoScreen *sc);
+
+void loco_screen_redraw_done(LocoScreen *sc);
+
+#endif
diff --git a/loco/window.c b/loco/window.c
new file mode 100644 (file)
index 0000000..92e013f
--- /dev/null
@@ -0,0 +1,271 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   window.c for the Openbox window manager
+   Copyright (c) 2008        Derek Foreman
+   Copyright (c) 2008        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 "window.h"
+#include "screen.h"
+#include "list.h"
+#include "obt/prop.h"
+
+static void pixmap_create(LocoWindow *lw);
+static void texture_create(LocoWindow *lw);
+static void texture_destroy(LocoWindow *lw);
+static void pixmap_destroy(LocoWindow *lw);
+static Bool look_for_destroy(Display *d, XEvent *e, XPointer arg);
+
+LocoWindow* loco_window_new(Window xwin, LocoScreen *screen)
+{
+    LocoWindow *lw;
+    XWindowAttributes attrib;
+
+    if (!XGetWindowAttributes(obt_display, xwin, &attrib))
+        return NULL;
+
+    lw = g_new0(LocoWindow, 1);
+    lw->ref = 1;
+    lw->id = xwin;
+    lw->screen = screen;
+    lw->input_only = attrib.class == InputOnly;
+    lw->x = attrib.x;
+    lw->y = attrib.y;
+    lw->w = attrib.width;
+    lw->h = attrib.height;
+    lw->depth = attrib.depth;
+
+    if (!lw->input_only) {
+        glGenTextures(1, &lw->texname);
+        /*glTexImage2D(TARGET, 0, GL_RGB, lw->w, lw->h,
+                       0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);*/
+        lw->damage = XDamageCreate(obt_display, lw->id, XDamageReportNonEmpty);
+    }
+
+    if (attrib.map_state != IsUnmapped)
+        loco_window_show(lw);
+
+    return lw;
+}
+
+void loco_window_ref(LocoWindow *lw)
+{
+    ++lw->ref;
+}
+
+void loco_window_unref(LocoWindow *lw)
+{
+    if (lw && --lw->ref == 0) {
+        if (!lw->input_only) {
+            glDeleteTextures(1, &lw->texname);
+
+            obt_display_ignore_errors(TRUE);
+            XDamageDestroy(obt_display, lw->damage);
+            obt_display_ignore_errors(FALSE);
+        }
+
+        g_free(lw);
+    }
+}
+
+void loco_window_show(LocoWindow *lw) {
+    guint32 *type;
+    guint i, ntype;
+
+    lw->visible = TRUE;
+
+    /* get the window's semantic type (for different effects!) */
+    lw->type = 0; /* XXX set this to the default type */
+    if (OBT_PROP_GETA32(lw->id, NET_WM_WINDOW_TYPE, ATOM, &type, &ntype)) {
+        /* use the first value that we know about in the array */
+        for (i = 0; i < ntype; ++i) {
+            /* XXX SET THESE TO AN ENUM'S VALUES */
+            if (type[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DESKTOP))
+                lw->type = 1;
+            if (type[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_MENU))
+                lw->type = 2;
+            /* XXX there are more TYPES that need to be added to prop.h */
+        }
+        g_free(type);
+    }
+
+    loco_screen_redraw(lw->screen);
+}
+
+void loco_window_hide(LocoWindow *lw, gboolean destroyed)
+{
+    /* if destroyed = TRUE, then the window is no longer available */
+
+    lw->visible = FALSE;
+
+    /* leave the glx texture alone though.. */
+    lw->stale = TRUE;
+    pixmap_destroy(lw);
+
+    loco_screen_redraw(lw->screen);
+}
+
+void loco_window_configure(LocoWindow *lw, const XConfigureEvent *e)
+{
+    LocoList *above, *pos;
+
+    pos = loco_screen_find_stacking(lw->screen, e->window);
+    above = loco_screen_find_stacking(lw->screen, e->above);
+
+    g_assert(pos != NULL && pos->window != NULL);
+
+    if (e->above && !above)
+        g_error("missing windows from the stacking list!!\n");
+
+    if ((lw->x != e->x) || (lw->y != e->y)) {
+        lw->x = e->x;
+        lw->y = e->y;
+
+        loco_screen_redraw(lw->screen);
+    }
+        
+    if ((lw->w != e->width) || (lw->h != e->height)) {
+        lw->w = e->width;
+        lw->h = e->height;
+
+        /* leave the glx texture alone though.. */
+        lw->stale = TRUE;
+        pixmap_destroy(lw);
+
+        loco_screen_redraw(lw->screen);
+    }
+
+    if (pos->next != above) {
+        //printf("Window 0x%lx above 0x%lx\n", pos->window->id,
+        //       above ? above->window->id : 0);
+        loco_list_move_before(&lw->screen->stacking_top,
+                              &lw->screen->stacking_bottom,
+                              pos, above);
+
+        loco_screen_redraw(lw->screen);
+    }
+}
+
+static Bool look_for_destroy(Display *d, XEvent *e, XPointer arg)
+{
+    const Window w = (Window)*arg;
+    return e->type == DestroyNotify && e->xdestroywindow.window == w;
+}
+
+static void pixmap_create(LocoWindow *lw)
+{
+    XEvent ce;
+
+    if (lw->pixmap) return;
+
+    /* make sure the window exists */
+    XGrabServer(obt_display);
+    XSync(obt_display, FALSE);
+
+    if (!XCheckIfEvent(obt_display, &ce, look_for_destroy, (XPointer)&lw->id))
+        lw->pixmap = XCompositeNameWindowPixmap(obt_display, lw->id);
+    XUngrabServer(obt_display);
+}
+
+static void texture_create(LocoWindow *lw)
+{
+    static const int attrs[] = {
+        GLX_TEXTURE_FORMAT_EXT,
+        GLX_TEXTURE_FORMAT_RGBA_EXT,
+        None
+    };
+
+    if (lw->glpixmap) return;
+
+    g_assert(lw->pixmap);
+
+    if (!lw->screen->glxFBConfig[lw->depth]) {
+        g_print("no glxFBConfig for depth %d for window 0x%lx\n",
+                lw->depth, lw->id);
+        return;
+    }
+    
+    lw->glpixmap = glXCreatePixmap(obt_display,
+                                   lw->screen->glxFBConfig[lw->depth],
+                                   lw->pixmap, attrs);
+    if (!lw->glpixmap) return;
+
+#if 0
+    if (screen->queryDrawable (screen->display->display,
+                              texture->pixmap,
+                              GLX_TEXTURE_TARGET_EXT,
+                              &target))
+    {
+       fprintf (stderr, "%s: glXQueryDrawable failed\n", programName);
+
+       glXDestroyGLXPixmap (screen->display->display, texture->pixmap);
+       texture->pixmap = None;
+
+       return FALSE;
+    }
+#endif
+
+    glBindTexture(GL_TEXTURE_2D, lw->texname);
+
+    lw->screen->bindTexImageEXT(obt_display, lw->glpixmap,
+                                GLX_FRONT_LEFT_EXT, NULL);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+
+    glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+static void texture_destroy(LocoWindow *lw)
+{
+    if (!lw->glpixmap) return;
+
+    glBindTexture(GL_TEXTURE_2D, lw->texname);
+
+    lw->screen->releaseTexImageEXT(obt_display, lw->glpixmap,
+                                   GLX_FRONT_LEFT_EXT);
+
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    obt_display_ignore_errors(TRUE);
+    glXDestroyGLXPixmap(obt_display, lw->glpixmap);
+    obt_display_ignore_errors(FALSE);
+
+    lw->glpixmap = None;
+}
+
+static void pixmap_destroy(LocoWindow *lw)
+{
+    if (!lw->pixmap) return;
+
+    XFreePixmap(obt_display, lw->pixmap);
+    lw->pixmap = None;
+}
+
+void loco_window_update_pixmap(LocoWindow *lw)
+{
+    if (lw->stale || lw->glpixmap == None) {
+        g_assert(lw->pixmap == None);
+
+        texture_destroy(lw);
+        pixmap_create(lw);
+        texture_create(lw);
+        lw->stale = FALSE;
+    }
+}
diff --git a/loco/window.h b/loco/window.h
new file mode 100644 (file)
index 0000000..f3c1fc5
--- /dev/null
@@ -0,0 +1,67 @@
+/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
+
+   window.h for the Openbox compositor
+   Copyright (c) 2008        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 loco__window_h
+#define loco__window_h
+
+#include "obt/display.h"
+#include <X11/Xlib.h>
+#include <GL/glx.h>
+
+struct _LocoScreen;
+
+typedef enum {
+    a /* XXX fill this in */
+} LocoWindowType;
+
+typedef struct _LocoWindow {
+    gint      ref;
+
+    Window    id;
+    gint      type; /* XXX make this an enum */
+
+    struct _LocoScreen *screen;
+
+    gint      x, y, w, h;
+
+    gint      depth;
+
+    gboolean  input_only;
+    gboolean  visible;
+    gboolean  damaged;
+    gboolean  stale;      /* glpixmap is out of date */
+
+    GLuint    texname;
+    Damage    damage;
+    Pixmap    pixmap;
+    GLXPixmap glpixmap;
+} LocoWindow;
+
+LocoWindow* loco_window_new(Window xwin, struct _LocoScreen *screen);
+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_configure(LocoWindow *lw, const XConfigureEvent *e);
+void loco_window_damage(LocoWindow *lw);
+
+void loco_window_update_pixmap(LocoWindow *lw);
+
+#endif
index 22f97db..bc5a625 100644 (file)
@@ -120,11 +120,13 @@ gboolean obt_display_open(const char *display_name)
         if (XCompositeQueryExtension(d, &obt_display_extension_composite_basep,
                                      &junk))
         {
-            gint major = 0, minor = 2;
+            gint major = 0, minor = 3;
             XCompositeQueryVersion(d, &major, &minor);
             /* Version 0.2 is the first version to have the
                XCompositeNameWindowPixmap() request. */
-            if (major > 0 || minor >= 2)
+            /* Version 0.3 is the first version to have the
+               composite overlay window */
+            if (major > 0 || minor >= 3)
                 obt_display_extension_composite = TRUE;
         }
         if (!obt_display_extension_composite)
index 64972dd..3139794 100644 (file)
@@ -352,15 +352,16 @@ void obt_main_loop_x_add(ObtMainLoop *loop,
     loop->x_handlers = g_slist_prepend(loop->x_handlers, h);
 }
 
-void obt_main_loop_x_remove(ObtMainLoop *loop,
-                            ObtMainLoopXHandler handler)
+static void obt_main_loop_x_remove_intern(ObtMainLoop *loop,
+                                          ObtMainLoopXHandler handler,
+                                          gboolean bydata, gpointer data)
 {
     GSList *it, *next;
 
     for (it = loop->x_handlers; it; it = next) {
         ObtMainLoopXHandlerType *h = it->data;
         next = g_slist_next(it);
-        if (h->func == handler) {
+        if (h->func == handler && (!bydata || data == h->data)) {
             loop->x_handlers = g_slist_delete_link(loop->x_handlers, it);
             if (h->destroy) h->destroy(h->data);
             g_free(h);
@@ -373,6 +374,19 @@ void obt_main_loop_x_remove(ObtMainLoop *loop,
     }
 }
 
+void obt_main_loop_x_remove_data(ObtMainLoop *loop,
+                                 ObtMainLoopXHandler handler,
+                                 gpointer data)
+{
+    obt_main_loop_x_remove_intern(loop, handler, TRUE, data);
+}
+
+void obt_main_loop_x_remove(ObtMainLoop *loop,
+                            ObtMainLoopXHandler handler)
+{
+    obt_main_loop_x_remove_intern(loop, handler, FALSE, NULL);
+}
+
 /*** SIGNAL WATCHERS ***/
 
 static void sighandler(gint sig)
index cce7d5b..2976388 100644 (file)
@@ -39,6 +39,9 @@ void obt_main_loop_x_add(ObtMainLoop *loop,
                          GDestroyNotify notify);
 void obt_main_loop_x_remove(ObtMainLoop *loop,
                             ObtMainLoopXHandler handler);
+void obt_main_loop_x_remove_data(ObtMainLoop *loop,
+                                 ObtMainLoopXHandler handler,
+                                 gpointer data);
 
 typedef void (*ObtMainLoopFdHandler) (gint fd, gpointer data);
 
index 041ef85..b8cfbbe 100644 (file)
@@ -200,8 +200,7 @@ gint main(gint argc, gchar **argv)
                                                XC_top_left_corner);
 
     if (screen_annex()) { /* it will be ours! */
-        loco_set_mainloop(ob_screen, ob_main_loop);
-
+        loco_startup(ob_main_loop);
         do {
             if (reconfigure) obt_keyboard_reload();
 
@@ -283,6 +282,7 @@ gint main(gint argc, gchar **argv)
                     frame_adjust_theme(c->frame);
                 }
             }
+
             event_startup(reconfigure);
             /* focus_backup is used for stacking, so this needs to come before
                anything that calls stacking_add */
@@ -304,6 +304,15 @@ gint main(gint argc, gchar **argv)
             menu_frame_startup(reconfigure);
             menu_startup(reconfigure);
 
+            /* XXX check config */
+            if (!loco_on_screen(ob_screen) && TRUE)
+                loco_start_screen(ob_screen);
+            else if (loco_on_screen(ob_screen) && FALSE)
+                loco_stop_screen(ob_screen);
+
+            if (loco_on_screen(ob_screen) && reconfigure)
+                loco_reconfigure_screen(ob_screen);
+
             if (!reconfigure) {
                 guint32 xid;
                 ObWindow *w;
@@ -367,6 +376,7 @@ gint main(gint argc, gchar **argv)
             actions_shutdown(reconfigure);
         } while (reconfigure);
 
+        loco_stop_screen(ob_screen);
         loco_shutdown();
     }