]> icculus.org git repositories - dana/openbox.git/blob - loco/loco.c
don't make windows owned by a screen, make them globally owned so they have a more...
[dana/openbox.git] / loco / loco.c
1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
2
3    loco.c for the Openbox window manager
4    Copyright (c) 2008        Derek Foreman
5    Copyright (c) 2008        Dana Jansens
6
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.
11
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.
16
17    See the COPYING file for a copy of the GNU General Public License.
18 */
19
20 #include "loco.h"
21 #include "screen.h"
22 #include "window.h"
23 #include "paint.h"
24
25 #include "obt/mainloop.h"
26 #include "obt/display.h"
27 #include "obt/prop.h"
28
29 #include <glib.h>
30
31 #define REFRESH_RATE (G_USEC_PER_SEC/60)
32
33 static LocoScreen **screens = NULL;
34 static ObtMainLoop *mainloop = NULL;
35 static GList       *windows = NULL;
36
37 /* XXX stop removing windows from the stacking until they have no more refs */
38
39 void COMPOSTER_RAWR(const XEvent *e, gpointer data)
40 {
41     LocoScreen *sc = data;
42     LocoWindow *lw = NULL;
43
44     /*g_print("COMPOSTER_RAWR() %d\n", e->type);*/
45
46     switch (e->type) {
47     case CreateNotify:
48         if (e->xcreatewindow.parent == sc->root) {
49             lw = loco_window_new(e->xcreatewindow.window, sc);
50             windows = g_list_prepend(windows, lw);
51         }
52         break;
53     case DestroyNotify:
54         lw = loco_screen_find_window(sc, e->xdestroywindow.window);
55         if (lw) {
56             loco_window_hide(lw, TRUE);
57             loco_window_unref(lw);
58             windows = g_list_remove(windows, lw);
59         }
60         else
61             g_print("destroy notify for unknown window 0x%lx\n",
62                     e->xdestroywindow.window);
63         break;
64     case ReparentNotify:
65         if (e->xreparent.parent == sc->root) {
66             /* reparented to root */
67             lw = loco_window_new(e->xreparent.window, sc);
68             windows = g_list_prepend(windows, lw);
69         }
70         else {
71             /* reparented away from root */
72             lw = loco_screen_find_window(sc, e->xreparent.window);
73             if (lw) {
74                 g_print("window 0x%lx reparented from root\n", lw->id);
75                 loco_window_hide(lw, TRUE);
76                 loco_window_unref(lw);
77                 windows = g_list_remove(windows, lw);
78             }
79             else
80                 g_print("reparent notify away from root for unknown window "
81                         "0x%lx\n", e->xreparent.window);
82         }
83         break;
84     case MapNotify:
85         lw = loco_screen_find_window(sc, e->xmap.window);
86         if (lw) loco_window_show(lw);
87         else g_print("map notify for unknown window 0x%lx\n", e->xmap.window);
88         break;
89     case UnmapNotify:
90         lw = loco_screen_find_window(sc, e->xunmap.window);
91         if (lw) loco_window_hide(lw, FALSE);
92         else g_print("unmap notify for unknown window 0x%lx\n",
93                      e->xunmap.window);
94         break;
95     case ConfigureNotify:
96         lw = loco_screen_find_window(sc, e->xconfigure.window);
97         if (lw) loco_window_configure(lw, &e->xconfigure);
98         break;
99     default:
100         if (e->type == obt_display_extension_damage_basep + XDamageNotify) {
101             const XDamageNotifyEvent *de = (const XDamageNotifyEvent*)e;
102
103             lw = loco_screen_find_window(sc, de->drawable);
104             if (de->drawable == sc->root)
105                 loco_screen_redraw(sc);
106             else if (lw)
107                 loco_screen_redraw(sc);
108
109             /* mark the damage as fixed - we know about it now */
110             obt_display_ignore_errors(TRUE);
111             XDamageSubtract(obt_display, de->damage, None, None);
112             obt_display_ignore_errors(FALSE);
113         }
114     }
115 }
116
117 static void find_all_windows(LocoScreen *sc)
118 {
119     guint i, nchild;
120     Window w, *children;
121
122     if (!XQueryTree(obt_display, sc->root, &w, &w, &children, &nchild))
123         nchild = 0;
124
125     for (i = 0; i < nchild; ++i)
126         if (children[i] != None) {
127             LocoWindow *lw;
128
129             lw = loco_window_new(children[i], sc);
130             windows = g_list_prepend(windows, lw);
131         }
132
133     if (children) XFree(children);
134 }
135
136 static gboolean compositor_timeout(gpointer data)
137 {
138     LocoScreen *sc = data;
139
140     if (sc->redraw)
141         paint_everything(sc);
142
143     return TRUE; /* repeat */
144 }
145
146 void loco_startup(ObtMainLoop *loop)
147 {
148     mainloop = loop;
149     screens = g_new0(LocoScreen*, ScreenCount(obt_display));
150 }
151
152 void loco_shutdown()
153 {
154     int i;
155     for (i = 0; i < ScreenCount(obt_display); ++i)
156         loco_screen_unref(screens[i]);
157
158     g_free(screens);
159     screens = NULL;
160 }
161
162 void loco_start_screen(gint number)
163 {
164     if (!screens[number])
165         screens[number] = loco_screen_new(number);
166     if (screens[number]) {
167         if (!paint_setup(screens[number]))
168             loco_stop_screen(number);
169         else {
170             find_all_windows(screens[number]);
171
172             obt_main_loop_x_add(mainloop, COMPOSTER_RAWR,
173                                 screens[number], NULL);
174             obt_main_loop_timeout_add(mainloop, REFRESH_RATE,
175                                       (GSourceFunc)compositor_timeout,
176                                       screens[number], g_direct_equal, NULL);
177         }
178     }
179 }
180
181 void loco_stop_screen(gint number)
182 {
183     GList *it, *next;
184
185     obt_main_loop_x_remove_data(mainloop, COMPOSTER_RAWR, screens[number]);
186     obt_main_loop_timeout_remove_data(mainloop,
187                                       compositor_timeout, screens[number],
188                                       FALSE);
189
190     for (it = windows; it; it = next) {
191         next = g_list_next(it);
192         if (((LocoWindow*)it->data)->screen->number == number) {
193             loco_window_unref(it->data);
194             windows = g_list_delete_link(windows, it);
195         }
196     }
197
198     loco_screen_unref(screens[number]);
199     screens[number] = NULL;
200 }
201
202 void loco_reconfigure_screen(gint number)
203 {
204     /* reload stuff.. */
205 }
206
207 gboolean loco_on_screen(gint number)
208 {
209     return screens[number] != NULL;
210 }