all repos — openbox @ 029628087fa0090e7c3b1598786a1bf1712e0db9

openbox fork - make it a bit more like ryudo

openbox/window.c (raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
/* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-

   window.c for the Openbox window manager
   Copyright (c) 2003-2007   Dana Jansens

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   See the COPYING file for a copy of the GNU General Public License.
*/

#include "window.h"
#include "menuframe.h"
#include "config.h"
#include "dock.h"
#include "client.h"
#include "frame.h"
#include "openbox.h"
#include "prompt.h"
#include "debug.h"
#include "grab.h"

static GHashTable *window_map;

static guint window_hash(Window *w) { return *w; }
static gboolean window_comp(Window *w1, Window *w2) { return *w1 == *w2; }

void window_startup(gboolean reconfig)
{
    if (reconfig) return;

    window_map = g_hash_table_new((GHashFunc)window_hash,
                                  (GEqualFunc)window_comp);
}

void window_shutdown(gboolean reconfig)
{
    if (reconfig) return;

    g_hash_table_destroy(window_map);
}

Window window_top(ObWindow *self)
{
    switch (self->type) {
    case OB_WINDOW_CLASS_MENUFRAME:
        return WINDOW_AS_MENUFRAME(self)->window;
    case OB_WINDOW_CLASS_DOCK:
        return WINDOW_AS_DOCK(self)->frame;
    case OB_WINDOW_CLASS_CLIENT:
        return WINDOW_AS_CLIENT(self)->frame->window;
    case OB_WINDOW_CLASS_INTERNAL:
        return WINDOW_AS_INTERNAL(self)->window;
    case OB_WINDOW_CLASS_PROMPT:
        return WINDOW_AS_PROMPT(self)->super.window;
    }
    g_assert_not_reached();
    return None;
}

ObStackingLayer window_layer(ObWindow *self)
{
    switch (self->type) {
    case OB_WINDOW_CLASS_DOCK:
        return config_dock_layer;
    case OB_WINDOW_CLASS_CLIENT:
        return ((ObClient*)self)->layer;
    case OB_WINDOW_CLASS_MENUFRAME:
    case OB_WINDOW_CLASS_INTERNAL:
        return OB_STACKING_LAYER_INTERNAL;
    case OB_WINDOW_CLASS_PROMPT:
        /* not used directly for stacking, prompts are managed as clients */
        g_assert_not_reached();
        break;
    }
    g_assert_not_reached();
    return None;
}

ObWindow* window_find(Window xwin)
{
    return g_hash_table_lookup(window_map, &xwin);
}

void window_add(Window *xwin, ObWindow *win)
{
    g_assert(xwin != NULL);
    g_assert(win != NULL);
    g_hash_table_insert(window_map, xwin, win);
}

void window_remove(Window xwin)
{
    g_assert(xwin != None);
    g_hash_table_remove(window_map, &xwin);
}

void window_manage_all(void)
{
    guint i, j, nchild;
    Window w, *children;
    XWMHints *wmhints;
    XWindowAttributes attrib;

    if (!XQueryTree(obt_display, RootWindow(obt_display, ob_screen),
                    &w, &w, &children, &nchild)) {
        ob_debug("XQueryTree failed in window_manage_all");
        nchild = 0;
    }

    /* remove all icon windows from the list */
    for (i = 0; i < nchild; i++) {
        if (children[i] == None) continue;
        wmhints = XGetWMHints(obt_display, children[i]);
        if (wmhints) {
            if ((wmhints->flags & IconWindowHint) &&
                (wmhints->icon_window != children[i]))
                for (j = 0; j < nchild; j++)
                    if (children[j] == wmhints->icon_window) {
                        /* XXX watch the window though */
                        children[j] = None;
                        break;
                    }
            XFree(wmhints);
        }
    }

    for (i = 0; i < nchild; ++i) {
        if (children[i] == None) continue;
        if (window_find(children[i])) continue; /* skip our own windows */
        if (XGetWindowAttributes(obt_display, children[i], &attrib)) {
            if (attrib.map_state == IsUnmapped)
                ;
            else
                window_manage(children[i]);
        }
    }

    if (children) XFree(children);
}

static Bool check_unmap(Display *d, XEvent *e, XPointer arg)
{
    const Window win = *(Window*)arg;
    return ((e->type == DestroyNotify && e->xdestroywindow.window == win) ||
            (e->type == UnmapNotify && e->xunmap.window == win));
}

void window_manage(Window win)
{
    XEvent e;
    XWindowAttributes attrib;
    gboolean no_manage = FALSE;
    gboolean is_dockapp = FALSE;
    Window icon_win = None;

    grab_server(TRUE);

    /* check if it has already been unmapped by the time we started
       mapping. the grab does a sync so we don't have to here */
    if (XCheckIfEvent(obt_display, &e, check_unmap, (XPointer)&win)) {
        ob_debug("Trying to manage unmapped window. Aborting that.");
        no_manage = TRUE;
    }

    if (!XGetWindowAttributes(obt_display, win, &attrib))
        no_manage = TRUE;
    else {
        XWMHints *wmhints;

        /* is the window a docking app */
        is_dockapp = FALSE;
        if ((wmhints = XGetWMHints(obt_display, win))) {
            if ((wmhints->flags & StateHint) &&
                wmhints->initial_state == WithdrawnState)
            {
                if (wmhints->flags & IconWindowHint)
                    icon_win = wmhints->icon_window;
                is_dockapp = TRUE;
            }
            XFree(wmhints);
        }
    }

    if (!no_manage) {
        if (attrib.override_redirect) {
            ob_debug("not managing override redirect window 0x%x", win);
            grab_server(FALSE);
        }
        else if (is_dockapp) {
            if (!icon_win)
                icon_win = win;
            dock_manage(icon_win, win);
        }
        else
            client_manage(win, NULL);
    }
    else {
        grab_server(FALSE);
        ob_debug("FAILED to manage window 0x%x", win);
    }
}

void window_unmanage_all(void)
{
    dock_unmanage_all();
    client_unmanage_all();
}