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 if (attrib.map_state != IsUnmapped)
63 void loco_window_ref(LocoWindow *lw)
68 void loco_window_unref(LocoWindow *lw)
70 if (lw && --lw->ref == 0) {
71 if (!lw->input_only) {
72 glDeleteTextures(1, &lw->texname);
74 obt_display_ignore_errors(TRUE);
75 XDamageDestroy(obt_display, lw->damage);
76 obt_display_ignore_errors(FALSE);
83 void loco_window_show(LocoWindow *lw) {
89 /* get the window's semantic type (for different effects!) */
90 lw->type = 0; /* XXX set this to the default type */
91 if (OBT_PROP_GETA32(lw->id, NET_WM_WINDOW_TYPE, ATOM, &type, &ntype)) {
92 /* use the first value that we know about in the array */
93 for (i = 0; i < ntype; ++i) {
94 /* XXX SET THESE TO AN ENUM'S VALUES */
95 if (type[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DESKTOP))
97 if (type[i] == OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_MENU))
99 /* XXX there are more TYPES that need to be added to prop.h */
104 loco_screen_redraw(lw->screen);
107 void loco_window_hide(LocoWindow *lw, gboolean destroyed)
109 /* if destroyed = TRUE, then the window is no longer available */
113 /* leave the glx texture alone though.. */
117 loco_screen_redraw(lw->screen);
120 void loco_window_configure(LocoWindow *lw, const XConfigureEvent *e)
122 LocoList *above, *pos;
124 pos = loco_screen_find_stacking(lw->screen, e->window);
125 above = loco_screen_find_stacking(lw->screen, e->above);
127 g_assert(pos != NULL && pos->window != NULL);
129 if (e->above && !above)
130 g_error("missing windows from the stacking list!!\n");
132 if ((lw->x != e->x) || (lw->y != e->y)) {
136 loco_screen_redraw(lw->screen);
139 if ((lw->w != e->width) || (lw->h != e->height)) {
143 /* leave the glx texture alone though.. */
147 loco_screen_redraw(lw->screen);
150 if (pos->next != above) {
151 //printf("Window 0x%lx above 0x%lx\n", pos->window->id,
152 // above ? above->window->id : 0);
153 loco_list_move_before(&lw->screen->stacking_top,
154 &lw->screen->stacking_bottom,
157 loco_screen_redraw(lw->screen);
161 static Bool look_for_destroy(Display *d, XEvent *e, XPointer arg)
163 const Window w = (Window)*arg;
164 return e->type == DestroyNotify && e->xdestroywindow.window == w;
167 static void pixmap_create(LocoWindow *lw)
171 if (lw->pixmap) return;
173 /* make sure the window exists */
174 XGrabServer(obt_display);
175 XSync(obt_display, FALSE);
177 if (!XCheckIfEvent(obt_display, &ce, look_for_destroy, (XPointer)&lw->id))
178 lw->pixmap = XCompositeNameWindowPixmap(obt_display, lw->id);
179 XUngrabServer(obt_display);
182 static void texture_create(LocoWindow *lw)
184 static const int attrs[] = {
185 GLX_TEXTURE_FORMAT_EXT,
186 GLX_TEXTURE_FORMAT_RGBA_EXT,
190 if (lw->glpixmap) return;
192 g_assert(lw->pixmap);
194 if (!lw->screen->glxFBConfig[lw->depth]) {
195 g_print("no glxFBConfig for depth %d for window 0x%lx\n",
200 lw->glpixmap = glXCreatePixmap(obt_display,
201 lw->screen->glxFBConfig[lw->depth],
203 if (!lw->glpixmap) return;
206 if (screen->queryDrawable (screen->display->display,
208 GLX_TEXTURE_TARGET_EXT,
211 fprintf (stderr, "%s: glXQueryDrawable failed\n", programName);
213 glXDestroyGLXPixmap (screen->display->display, texture->pixmap);
214 texture->pixmap = None;
220 glBindTexture(GL_TEXTURE_2D, lw->texname);
222 lw->screen->bindTexImageEXT(obt_display, lw->glpixmap,
223 GLX_FRONT_LEFT_EXT, NULL);
225 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
226 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
228 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
229 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
230 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
232 glBindTexture(GL_TEXTURE_2D, 0);
235 static void texture_destroy(LocoWindow *lw)
237 if (!lw->glpixmap) return;
239 glBindTexture(GL_TEXTURE_2D, lw->texname);
241 lw->screen->releaseTexImageEXT(obt_display, lw->glpixmap,
244 glBindTexture(GL_TEXTURE_2D, 0);
246 obt_display_ignore_errors(TRUE);
247 glXDestroyGLXPixmap(obt_display, lw->glpixmap);
248 obt_display_ignore_errors(FALSE);
253 static void pixmap_destroy(LocoWindow *lw)
255 if (!lw->pixmap) return;
257 XFreePixmap(obt_display, lw->pixmap);
261 void loco_window_update_pixmap(LocoWindow *lw)
263 if (lw->stale || lw->glpixmap == None) {
264 g_assert(lw->pixmap == None);