1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 window.c for the Openbox window manager
4 Copyright (c) 2008 Derek Foreman
5 Copyright (c) 2008 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
25 static void pixmap_create(LocoWindow *lw);
26 static void texture_create(LocoWindow *lw);
27 static void texture_destroy(LocoWindow *lw);
28 static void pixmap_destroy(LocoWindow *lw);
29 static Bool look_for_destroy(Display *d, XEvent *e, XPointer arg);
31 LocoWindow* loco_window_new(Window xwin, LocoScreen *screen)
34 XWindowAttributes attrib;
36 if (!XGetWindowAttributes(obt_display, xwin, &attrib))
39 lw = g_new0(LocoWindow, 1);
43 lw->input_only = attrib.class == InputOnly;
47 lw->h = attrib.height;
48 lw->depth = attrib.depth;
50 if (!lw->input_only) {
51 glGenTextures(1, &lw->texname);
52 /*glTexImage2D(TARGET, 0, GL_RGB, lw->w, lw->h,
53 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);*/
54 lw->damage = XDamageCreate(obt_display, lw->id, XDamageReportNonEmpty);
57 loco_screen_add_window(lw->screen, lw);
59 if (attrib.map_state != IsUnmapped)
65 void loco_window_ref(LocoWindow *lw)
70 void loco_window_unref(LocoWindow *lw)
72 if (lw && --lw->ref == 0) {
73 if (!lw->input_only) {
77 glDeleteTextures(1, &lw->texname);
79 obt_display_ignore_errors(TRUE);
80 XDamageDestroy(obt_display, lw->damage);
81 obt_display_ignore_errors(FALSE);
84 loco_screen_remove_window(lw->screen, lw);
90 void loco_window_show(LocoWindow *lw) {
96 /* get the window's semantic type (for different effects!) */
97 lw->type = 0; /* XXX set this to the default type */
98 if (OBT_PROP_GETA32(lw->id, NET_WM_WINDOW_TYPE, ATOM, &type, &ntype)) {
99 /* use the first value that we know about in the array */
100 for (i = 0; i < ntype; ++i) {
101 /* XXX SET THESE TO AN ENUM'S VALUES */
102 if (type[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DESKTOP))
104 if (type[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_MENU))
106 /* XXX there are more TYPES that need to be added to prop.h */
111 loco_screen_redraw(lw->screen);
114 void loco_window_hide(LocoWindow *lw, gboolean gone)
116 /* if gone = TRUE, then the window is no longer available and we
121 /* leave the glx texture alone though.. */
125 loco_screen_redraw(lw->screen);
128 loco_screen_zombie_window(lw->screen, lw);
133 void loco_window_configure(LocoWindow *lw, const XConfigureEvent *e)
135 LocoList *above, *pos;
137 pos = loco_screen_find_stacking(lw->screen, e->window);
138 above = loco_screen_find_stacking(lw->screen, e->above);
140 g_assert(pos != NULL && pos->window != NULL);
142 if (e->above && !above)
143 g_print("missing windows from the stacking list!!\n");
145 if ((lw->x != e->x) || (lw->y != e->y)) {
149 loco_screen_redraw(lw->screen);
152 if ((lw->w != e->width) || (lw->h != e->height)) {
156 /* leave the glx texture alone though.. */
160 loco_screen_redraw(lw->screen);
163 if (pos->next != above) {
164 //printf("Window 0x%lx above 0x%lx\n", pos->window->id,
165 // above ? above->window->id : 0);
166 loco_list_move_before(&lw->screen->stacking_top,
167 &lw->screen->stacking_bottom,
170 loco_screen_redraw(lw->screen);
174 static Bool look_for_destroy(Display *d, XEvent *e, XPointer arg)
176 const Window w = (Window)*arg;
177 return e->type == DestroyNotify && e->xdestroywindow.window == w;
180 static void pixmap_create(LocoWindow *lw)
184 if (lw->pixmap) return;
186 /* make sure the window exists */
187 XGrabServer(obt_display);
188 XSync(obt_display, FALSE);
190 if (!XCheckIfEvent(obt_display, &ce, look_for_destroy, (XPointer)&lw->id))
191 lw->pixmap = XCompositeNameWindowPixmap(obt_display, lw->id);
192 XUngrabServer(obt_display);
195 static void texture_create(LocoWindow *lw)
197 static const int attrs[] = {
198 GLX_TEXTURE_FORMAT_EXT,
199 GLX_TEXTURE_FORMAT_RGBA_EXT,
203 if (lw->glpixmap) return;
205 g_assert(lw->pixmap);
207 if (!lw->screen->glxFBConfig[lw->depth]) {
208 g_print("no glxFBConfig for depth %d for window 0x%lx\n",
213 lw->glpixmap = glXCreatePixmap(obt_display,
214 lw->screen->glxFBConfig[lw->depth],
216 if (!lw->glpixmap) return;
219 if (screen->queryDrawable (screen->display->display,
221 GLX_TEXTURE_TARGET_EXT,
224 fprintf (stderr, "%s: glXQueryDrawable failed\n", programName);
226 glXDestroyGLXPixmap (screen->display->display, texture->pixmap);
227 texture->pixmap = None;
233 glBindTexture(GL_TEXTURE_2D, lw->texname);
235 lw->screen->bindTexImageEXT(obt_display, lw->glpixmap,
236 GLX_FRONT_LEFT_EXT, NULL);
238 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
239 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
243 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
245 glBindTexture(GL_TEXTURE_2D, 0);
248 static void texture_destroy(LocoWindow *lw)
250 if (!lw->glpixmap) return;
252 glBindTexture(GL_TEXTURE_2D, lw->texname);
254 lw->screen->releaseTexImageEXT(obt_display, lw->glpixmap,
257 glBindTexture(GL_TEXTURE_2D, 0);
259 obt_display_ignore_errors(TRUE);
260 glXDestroyGLXPixmap(obt_display, lw->glpixmap);
261 obt_display_ignore_errors(FALSE);
266 static void pixmap_destroy(LocoWindow *lw)
268 if (!lw->pixmap) return;
270 XFreePixmap(obt_display, lw->pixmap);
274 void loco_window_update_pixmap(LocoWindow *lw)
276 if (loco_window_is_zombie(lw)) return;
278 if (lw->stale || lw->glpixmap == None) {
279 g_assert(lw->pixmap == None);
288 gboolean loco_window_is_zombie(LocoWindow *lw)
290 return lw->id == None;