]> icculus.org git repositories - dana/openbox.git/blob - loco/screen.c
don't make windows owned by a screen, make them globally owned so they have a more...
[dana/openbox.git] / loco / screen.c
1 #include "screen.h"
2 #include "window.h"
3 #include "list.h"
4 #include "obt/display.h"
5
6 static void find_visuals(LocoScreen *sc);
7
8 static guint window_hash(Window *w) { return *w; }
9 static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
10
11 static const int drawable_tfp_attrs[] = {
12     GLX_CONFIG_CAVEAT, GLX_NONE,
13     GLX_DOUBLEBUFFER, FALSE,
14     GLX_DEPTH_SIZE, 0,
15     GLX_RED_SIZE, 1,
16     GLX_GREEN_SIZE, 1,
17     GLX_BLUE_SIZE, 1,
18     GLX_ALPHA_SIZE, 1,
19     GLX_RENDER_TYPE, GLX_RGBA_BIT,
20     GLX_BIND_TO_TEXTURE_RGBA_EXT, TRUE, /* For TextureFromPixmap */
21     None
22 };
23
24 LocoScreen* loco_screen_new(gint number)
25 {
26     LocoScreen *sc;
27
28     /* try get the root redirect */
29     obt_display_ignore_errors(TRUE);
30     XCompositeRedirectSubwindows(obt_display, obt_root(number),
31                                  CompositeRedirectManual);
32     obt_display_ignore_errors(FALSE);
33     if (obt_display_error_occured) {
34         g_message("Another composite manager is running on screen %d", number);
35         return NULL;
36     }
37
38     sc = g_new0(LocoScreen, 1);
39     sc->ref = 1;
40     sc->number = number;
41     sc->root = obt_root(number);
42     //sc->root = loco_window_new(obt_root(number));
43     sc->stacking_map = g_hash_table_new((GHashFunc)window_hash,
44                                         (GEqualFunc)window_comp);
45     sc->stacking_map_ptr = g_hash_table_new((GHashFunc)g_direct_hash,
46                                             (GEqualFunc)g_direct_equal);
47     sc->bindTexImageEXT = (BindEXTFunc)
48         glXGetProcAddress((const guchar*)"glXBindTexImageEXT");
49     sc->releaseTexImageEXT = (ReleaseEXTFunc)
50         glXGetProcAddress((const guchar*)"glXReleaseTexImageEXT");
51
52     find_visuals(sc);
53
54     sc->overlay = XCompositeGetOverlayWindow(obt_display, sc->root);
55
56     if (sc->overlay) {
57         XserverRegion region;
58
59         region = XFixesCreateRegion(obt_display, NULL, 0);
60         XFixesSetWindowShapeRegion(obt_display, sc->overlay,
61                                    ShapeBounding, 0, 0, 0);
62         XFixesSetWindowShapeRegion(obt_display, sc->overlay,
63                                    ShapeInput, 0, 0, region);
64         XFixesDestroyRegion(obt_display, region);
65     }
66
67     loco_screen_redraw(sc);
68
69     return sc;
70 }
71
72 void loco_screen_ref(LocoScreen *sc)
73 {
74     ++sc->ref;
75 }
76
77 void loco_screen_unref(LocoScreen *sc)
78 {
79     if (sc && --sc->ref == 0) {
80         /*XXX loco_window_unref(sc->root);*/
81
82         if (sc->overlay)
83             XCompositeReleaseOverlayWindow(obt_display, sc->overlay);
84
85         g_hash_table_destroy(sc->stacking_map);
86         g_hash_table_destroy(sc->stacking_map_ptr);
87
88         g_free(sc);
89     }
90 }
91
92 static void find_visuals(LocoScreen *sc)
93 {
94     gint db, stencil, depth;
95     gint i, j, value, count;
96     XVisualInfo tvis, *visinfo;
97     GLXFBConfig *fbcons;
98     gint numfb;
99
100     fbcons = glXChooseFBConfig(obt_display, sc->number,
101                                drawable_tfp_attrs, &numfb);
102
103     db = 32767;
104     stencil = 32767;
105     depth = 32767;
106     for (i = 0; i <= LOCO_SCREEN_MAX_DEPTH; i++) {
107         VisualID vid;
108
109         vid = 0;
110         sc->glxFBConfig[i] = 0;
111
112         tvis.depth = i;
113         visinfo = XGetVisualInfo(obt_display, VisualDepthMask, &tvis, &count);
114         /* pick the nicest visual for the depth */
115         for (j = 0; j < count; j++) {
116             glXGetConfig(obt_display, &visinfo[j], GLX_USE_GL, &value);
117             if (!value)
118                 continue;
119
120             glXGetConfig(obt_display, &visinfo[j], GLX_DOUBLEBUFFER, &value);
121             if (value > db)
122                 continue;
123             db = value;
124
125             glXGetConfig(obt_display, &visinfo[j], GLX_STENCIL_SIZE, &value);
126             if (value > stencil)
127                 continue;
128             stencil = value;
129
130             glXGetConfig(obt_display, &visinfo[j], GLX_DEPTH_SIZE, &value);
131             if (value > depth)
132                 continue;
133             depth = value;
134
135             /* use this visual */
136             vid = visinfo[j].visualid;
137         }
138
139         if (!vid)
140             continue;
141
142         g_print("found visual %d\n", i);
143
144         /* find the fbconfig for this depth/visual */
145         for(j = 0; j < numfb; ++j) {
146             glXGetFBConfigAttrib(obt_display, fbcons[j],
147                                  GLX_VISUAL_ID, &value);
148             if (value == (int)vid) {
149                 sc->glxFBConfig[i] = fbcons[j]; /* save it */
150                 g_print("supporting depth %d\n", i);
151                 break; /* next depth */
152             }
153         }
154     }
155
156     XFree(fbcons);
157 }
158
159 void loco_screen_add_window(LocoScreen *sc, LocoWindow *lw)
160 {
161     LocoList *it;
162
163     g_print("add window 0x%lx\n", lw->id);
164
165     /* new windows are at the top */
166     it = loco_list_prepend(&sc->stacking_top, &sc->stacking_bottom, lw);
167     g_hash_table_insert(sc->stacking_map, &lw->id, it);
168     g_hash_table_insert(sc->stacking_map_ptr, &lw, it);
169
170     loco_window_ref(lw);
171 }
172
173 void loco_screen_zombie_window(LocoScreen *sc, LocoWindow *lw)
174 {
175     g_print("zombie window 0x%lx\n", lw->id);
176
177     /* the id will no longer be useful, so remove it from the hash */
178     g_hash_table_remove(sc->stacking_map, &lw->id);
179 }
180
181 void loco_screen_remove_window(LocoScreen *sc, LocoWindow *lw)
182 {
183     LocoList *pos;
184
185     g_print("remove window 0x%lx\n", lw->id);
186
187     pos = loco_screen_find_stacking_ptr(sc, lw);
188     g_assert(pos);
189     loco_list_delete_link(&sc->stacking_top, &sc->stacking_bottom, pos);
190     g_hash_table_remove(sc->stacking_map, &lw->id);
191     g_hash_table_remove(sc->stacking_map_ptr, &lw);
192
193     loco_window_unref(lw);
194 }
195
196 struct _LocoWindow* loco_screen_find_window(LocoScreen *sc, Window xwin)
197 {
198     LocoList *it;
199
200     it = g_hash_table_lookup(sc->stacking_map, &xwin);
201     return (it ? it->window : NULL);
202 }
203
204 struct _LocoList* loco_screen_find_stacking(LocoScreen *sc, Window xwin)
205 {
206     return g_hash_table_lookup(sc->stacking_map, &xwin);
207 }
208
209 struct _LocoList* loco_screen_find_stacking_ptr(LocoScreen *sc, LocoWindow *lw)
210 {
211     return g_hash_table_lookup(sc->stacking_map_ptr, &lw);
212 }
213
214 void loco_screen_redraw(LocoScreen *sc)
215 {
216     sc->redraw = TRUE;
217 }
218
219 void loco_screen_redraw_done(LocoScreen *sc)
220 {
221     sc->redraw = TRUE;
222 }