1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 loco.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 #include "obt/mainloop.h"
26 #include "obt/display.h"
31 #define REFRESH_RATE (G_USEC_PER_SEC/60)
33 static LocoScreen **screens = NULL;
34 static ObtMainLoop *mainloop = NULL;
35 static GList *windows = NULL;
37 /* XXX stop removing windows from the stacking until they have no more refs */
39 void COMPOSTER_RAWR(const XEvent *e, gpointer data)
41 LocoScreen *sc = data;
42 LocoWindow *lw = NULL;
44 /*g_print("COMPOSTER_RAWR() %d\n", e->type);*/
48 if (e->xcreatewindow.parent == sc->root) {
49 lw = loco_window_new(e->xcreatewindow.window, sc);
50 windows = g_list_prepend(windows, lw);
54 lw = loco_screen_find_window(sc, e->xdestroywindow.window);
56 loco_window_hide(lw, TRUE);
57 loco_window_unref(lw);
58 windows = g_list_remove(windows, lw);
61 g_print("destroy notify for unknown window 0x%lx\n",
62 e->xdestroywindow.window);
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);
71 /* reparented away from root */
72 lw = loco_screen_find_window(sc, e->xreparent.window);
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);
80 g_print("reparent notify away from root for unknown window "
81 "0x%lx\n", e->xreparent.window);
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);
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",
96 lw = loco_screen_find_window(sc, e->xconfigure.window);
97 if (lw) loco_window_configure(lw, &e->xconfigure);
100 if (e->type == obt_display_extension_damage_basep + XDamageNotify) {
101 const XDamageNotifyEvent *de = (const XDamageNotifyEvent*)e;
103 lw = loco_screen_find_window(sc, de->drawable);
104 if (de->drawable == sc->root)
105 loco_screen_redraw(sc);
107 loco_screen_redraw(sc);
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);
117 static void find_all_windows(LocoScreen *sc)
122 if (!XQueryTree(obt_display, sc->root, &w, &w, &children, &nchild))
125 for (i = 0; i < nchild; ++i)
126 if (children[i] != None) {
129 lw = loco_window_new(children[i], sc);
130 windows = g_list_prepend(windows, lw);
133 if (children) XFree(children);
136 static gboolean compositor_timeout(gpointer data)
138 LocoScreen *sc = data;
141 paint_everything(sc);
143 return TRUE; /* repeat */
146 void loco_startup(ObtMainLoop *loop)
149 screens = g_new0(LocoScreen*, ScreenCount(obt_display));
155 for (i = 0; i < ScreenCount(obt_display); ++i)
156 loco_screen_unref(screens[i]);
162 void loco_start_screen(gint number)
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);
170 find_all_windows(screens[number]);
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);
181 void loco_stop_screen(gint number)
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],
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);
198 loco_screen_unref(screens[number]);
199 screens[number] = NULL;
202 void loco_reconfigure_screen(gint number)
207 gboolean loco_on_screen(gint number)
209 return screens[number] != NULL;