1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 window.c for the Openbox window manager
4 Copyright (c) 2003-2007 Dana Jansens
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 See the COPYING file for a copy of the GNU General Public License.
20 #include "menuframe.h"
24 #include "unmanaged.h"
25 #include "composite.h"
31 #include "obt/xqueue.h"
33 static GHashTable *window_map;
35 static guint window_hash(Window *w) { return *w; }
36 static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }
38 void window_startup(gboolean reconfig)
42 window_map = g_hash_table_new((GHashFunc)window_hash,
43 (GEqualFunc)window_comp);
46 void window_shutdown(gboolean reconfig)
50 g_hash_table_destroy(window_map);
53 ObWindow* window_new_size(ObWindowClass type, gsize size)
57 g_assert(size >= sizeof(ObWindow));
58 self = g_slice_alloc0(size);
64 void window_set_abstract(ObWindow *self,
66 const ObStackingLayer *layer,
70 g_assert(!self->top && !self->layer && !self->depth && !self->alpha);
77 /* set up any things in ObWindow that require use of the abstract pointers
80 composite_window_setup(self);
83 void window_cleanup(ObWindow *self)
85 composite_window_cleanup(self);
88 void window_free(ObWindow *self)
90 /* The abstract pointers must not be used here, they are likely invalid
93 g_slice_free1(self->size, self);
96 ObWindow* window_find(Window xwin)
98 return g_hash_table_lookup(window_map, &xwin);
101 void wfe(gpointer k, gpointer v, gpointer data)
103 ((ObWindowForeachFunc)data)(v);
106 void window_foreach(ObWindowForeachFunc func)
108 g_hash_table_foreach(window_map, wfe, func);
111 void window_add(Window *xwin, ObWindow *win)
113 g_assert(xwin != NULL);
114 g_assert(win != NULL);
115 g_hash_table_insert(window_map, xwin, win);
118 void window_remove(Window xwin)
120 g_assert(xwin != None);
121 g_hash_table_remove(window_map, &xwin);
124 ObInternalWindow* window_internal_new(Window window, int depth)
126 ObInternalWindow *self;
128 self = window_new(OB_WINDOW_CLASS_INTERNAL, ObInternalWindow);
129 self->window = window;
130 self->layer = OB_STACKING_LAYER_INTERNAL;
132 window_set_abstract(INTERNAL_AS_WINDOW(self),
133 &self->window, /* top-most window */
134 &self->layer, /* stacking layer */
135 &self->depth, /* window depth */
140 void window_manage_all(void)
145 XWindowAttributes attrib;
147 if (!XQueryTree(obt_display, RootWindow(obt_display, ob_screen),
148 &w, &w, &children, &nchild)) {
149 ob_debug("XQueryTree failed in window_manage_all");
153 /* remove all icon windows from the list */
154 for (i = 0; i < nchild; i++) {
155 if (children[i] == None) continue;
156 wmhints = XGetWMHints(obt_display, children[i]);
158 if ((wmhints->flags & IconWindowHint) &&
159 (wmhints->icon_window != children[i]))
160 for (j = 0; j < nchild; j++)
161 if (children[j] == wmhints->icon_window) {
162 /* XXX watch the window though */
170 for (i = 0; i < nchild; ++i) {
171 if (children[i] == None) continue;
172 if (window_find(children[i])) continue; /* skip our own windows */
173 if (XGetWindowAttributes(obt_display, children[i], &attrib)) {
174 if (attrib.map_state == IsUnmapped)
177 window_manage(children[i]);
181 if (children) XFree(children);
184 static gboolean check_unmap(XEvent *e, gpointer data)
186 const Window win = *(Window*)data;
187 return ((e->type == DestroyNotify && e->xdestroywindow.window == win) ||
188 (e->type == UnmapNotify && e->xunmap.window == win));
191 void window_manage(Window win)
193 XWindowAttributes attrib;
194 gboolean no_manage = FALSE;
195 gboolean is_dockapp = FALSE;
196 Window icon_win = None;
200 /* check if it has already been unmapped by the time we started
201 mapping. the grab does a sync so we don't have to here */
202 if (xqueue_exists_local(check_unmap, &win)) {
203 ob_debug("Trying to manage unmapped window. Aborting that.");
206 else if (!XGetWindowAttributes(obt_display, win, &attrib))
211 /* is the window a docking app */
213 if ((wmhints = XGetWMHints(obt_display, win))) {
214 if ((wmhints->flags & StateHint) &&
215 wmhints->initial_state == WithdrawnState)
217 if (wmhints->flags & IconWindowHint)
218 icon_win = wmhints->icon_window;
226 if (attrib.override_redirect) {
227 ob_debug("not managing override redirect window 0x%x", win);
230 else if (is_dockapp) {
233 dock_manage(icon_win, win);
236 client_manage(win, NULL);
240 ob_debug("FAILED to manage window 0x%x", win);
244 void window_unmanage_all(void)
247 client_unmanage_all();
248 unmanaged_destroy_all();