it looks an awful lot like glxcompmgr somehow..
$(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 ##
--- /dev/null
+/* -*- 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
--- /dev/null
+/* -*- 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;
+}
+
--- /dev/null
+/* -*- 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
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;
}
#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
--- /dev/null
+#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);
+}
--- /dev/null
+/* -*- 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
--- /dev/null
+#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;
+}
--- /dev/null
+/* -*- 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
--- /dev/null
+/* -*- 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;
+ }
+}
--- /dev/null
+/* -*- 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
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)
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);
}
}
+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)
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);
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();
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 */
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;
actions_shutdown(reconfigure);
} while (reconfigure);
+ loco_stop_screen(ob_screen);
loco_shutdown();
}