]> Dogcows Code - chaz/openbox/blob - openbox/slit.c
98eb010e8b4047072b5e5779a56070cb3228738a
[chaz/openbox] / openbox / slit.c
1 #include "slit.h"
2 #include "screen.h"
3 #include "openbox.h"
4 #include "render/theme.h"
5 #include "render/render.h"
6
7 #define SLIT_EVENT_MASK (EnterNotifyMask | LeaveNotifyMask)
8 #define SLITAPP_EVENT_MASK (StructureNotifyMask)
9
10 struct Slit {
11 Window frame;
12
13 /* user-requested position stuff */
14 SlitPosition pos;
15 int gravity;
16 int user_x, user_y;
17
18 /* actual position (when not auto-hidden) */
19 int x, y;
20 int w, h;
21
22 gboolean horz;
23 gboolean hide;
24 gboolean hidden;
25
26 Appearance *a_frame;
27
28 GList *slit_apps;
29 };
30
31 GHashTable *slit_map = NULL;
32 GHashTable *slit_app_map = NULL;
33
34 static Slit *slit;
35 static int nslits;
36
37 static void slit_configure(Slit *self);
38
39 void slit_startup()
40 {
41 XSetWindowAttributes attrib;
42 int i;
43
44 slit_map = g_hash_table_new(g_int_hash, g_int_equal);
45 slit_app_map = g_hash_table_new(g_int_hash, g_int_equal);
46
47 nslits = 1;
48 slit = g_new0(struct Slit, nslits);
49
50 for (i = 0; i < nslits; ++i) {
51 slit[i].horz = FALSE;
52 slit[i].hide = TRUE;
53 slit[i].hidden = FALSE;
54 slit[i].pos = SlitPos_TopRight;
55
56 attrib.override_redirect = True;
57 slit[i].frame = XCreateWindow(ob_display, ob_root, 0, 0, 1, 1, 0,
58 render_depth, InputOutput, render_visual,
59 CWOverrideRedirect, &attrib);
60 slit[i].a_frame = appearance_copy(theme_a_unfocused_title);
61 XSetWindowBorder(ob_display, slit[i].frame, theme_b_color->pixel);
62 XSetWindowBorderWidth(ob_display, slit[i].frame, theme_bwidth);
63
64 g_hash_table_insert(slit_map, &slit[i].frame, &slit[i]);
65 }
66 }
67
68 void slit_shutdown()
69 {
70 int i;
71
72 for (i = 0; i < nslits; ++i) {
73 XDestroyWindow(ob_display, slit[i].frame);
74 appearance_free(slit[i].a_frame);
75 g_hash_table_remove(slit_map, &slit[i].frame);
76 }
77 g_hash_table_destroy(slit_app_map);
78 g_hash_table_destroy(slit_map);
79 }
80
81 void slit_add(Window win, XWMHints *wmhints, XWindowAttributes *attrib)
82 {
83 Slit *s;
84 SlitApp *app;
85
86 /* XXX pick a slit */
87 s = &slit[0];
88
89 app = g_new0(SlitApp, 1);
90 app->slit = s;
91 app->win = win;
92 app->icon_win = (wmhints->flags & IconWindowHint) ?
93 wmhints->icon_window : win;
94
95 app->w = attrib->width;
96 app->h = attrib->height;
97
98 s->slit_apps = g_list_append(s->slit_apps, app);
99 slit_configure(s);
100
101 XReparentWindow(ob_display, app->icon_win, s->frame, app->x, app->y);
102 /*
103 This is the same case as in frame.c for client windows. When Openbox is
104 starting, the window is already mapped so we see unmap events occur for
105 it. There are 2 unmap events generated that we see, one with the 'event'
106 member set the root window, and one set to the client, but both get
107 handled and need to be ignored.
108 */
109 if (ob_state == State_Starting)
110 app->ignore_unmaps += 2;
111
112 if (app->win != app->icon_win) {
113 /* have to map it so that it can be re-managed on a restart */
114 XMoveWindow(ob_display, app->win, -1000, -1000);
115 XMapWindow(ob_display, app->win);
116 }
117 g_message(" Slitting 0x%lx 0x%lx", app->icon_win, app->win);
118 XMapWindow(ob_display, app->icon_win);
119 XSync(ob_display, False);
120
121 /* specify that if we exit, the window should not be destroyed and should
122 be reparented back to root automatically */
123 XChangeSaveSet(ob_display, app->icon_win, SetModeInsert);
124 XSelectInput(ob_display, app->icon_win, SLITAPP_EVENT_MASK);
125
126 g_hash_table_insert(slit_app_map, &app->icon_win, app);
127
128 g_message("Managed Slit App: 0x%lx", app->icon_win);
129 }
130
131 void slit_remove_all()
132 {
133 int i;
134
135 for (i = 0; i < nslits; ++i)
136 while (slit[i].slit_apps)
137 slit_remove(slit[i].slit_apps->data, TRUE);
138 }
139
140 void slit_remove(SlitApp *app, gboolean reparent)
141 {
142 XSelectInput(ob_display, app->icon_win, NoEventMask);
143 /* remove the window from our save set */
144 XChangeSaveSet(ob_display, app->icon_win, SetModeDelete);
145 XSync(ob_display, False);
146
147 g_hash_table_remove(slit_app_map, &app->icon_win);
148
149 if (reparent)
150 XReparentWindow(ob_display, app->icon_win, ob_root, app->x, app->y);
151
152 app->slit->slit_apps = g_list_remove(app->slit->slit_apps, app);
153 slit_configure(app->slit);
154
155 g_message("Unmanaged Slit App: 0x%lx", app->icon_win);
156
157 g_free(app);
158 }
159
160 void slit_configure_all()
161 {
162 int i; for (i = 0; i < nslits; ++i) slit_configure(&slit[i]);
163 }
164
165 static void slit_configure(Slit *self)
166 {
167 GList *it;
168 int spot;
169
170 self->w = self->h = spot = 0;
171
172 for (it = self->slit_apps; it; it = it->next) {
173 struct SlitApp *app = it->data;
174 if (self->horz) {
175 app->x = spot;
176 app->y = 0;
177 self->w += app->w;
178 self->h = MAX(self->h, app->h);
179 spot += app->w;
180 } else {
181 app->x = 0;
182 app->y = spot;
183 self->w = MAX(self->h, app->w);
184 self->h += app->h;
185 spot += app->h;
186 }
187
188 XMoveWindow(ob_display, app->icon_win, app->x, app->y);
189 }
190
191 /* used for calculating offsets */
192 self->w += theme_bwidth * 2;
193 self->h += theme_bwidth * 2;
194
195 /* calculate position */
196 switch (self->pos) {
197 case SlitPos_Floating:
198 self->x = self->user_x;
199 self->y = self->user_y;
200 break;
201 case SlitPos_TopLeft:
202 self->x = 0;
203 self->y = 0;
204 self->gravity = NorthWestGravity;
205 break;
206 case SlitPos_Top:
207 self->x = screen_physical_size.width / 2;
208 self->y = 0;
209 self->gravity = NorthGravity;
210 break;
211 case SlitPos_TopRight:
212 self->x = screen_physical_size.width;
213 self->y = 0;
214 self->gravity = NorthEastGravity;
215 break;
216 case SlitPos_Left:
217 self->x = 0;
218 self->y = screen_physical_size.height / 2;
219 self->gravity = WestGravity;
220 break;
221 case SlitPos_Right:
222 self->x = screen_physical_size.width;
223 self->y = screen_physical_size.height / 2;
224 self->gravity = EastGravity;
225 break;
226 case SlitPos_BottomLeft:
227 self->x = 0;
228 self->y = screen_physical_size.height;
229 self->gravity = SouthWestGravity;
230 break;
231 case SlitPos_Bottom:
232 self->x = screen_physical_size.width / 2;
233 self->y = screen_physical_size.height;
234 self->gravity = SouthGravity;
235 break;
236 case SlitPos_BottomRight:
237 self->x = screen_physical_size.width;
238 self->y = screen_physical_size.height;
239 self->gravity = SouthEastGravity;
240 break;
241 }
242
243 switch(self->gravity) {
244 case NorthGravity:
245 case CenterGravity:
246 case SouthGravity:
247 self->x -= self->w / 2;
248 break;
249 case NorthEastGravity:
250 case EastGravity:
251 case SouthEastGravity:
252 self->x -= self->w;
253 break;
254 }
255 switch(self->gravity) {
256 case WestGravity:
257 case CenterGravity:
258 case EastGravity:
259 self->y -= self->h / 2;
260 break;
261 case SouthWestGravity:
262 case SouthGravity:
263 case SouthEastGravity:
264 self->y -= self->h;
265 break;
266 }
267
268 if (self->hide && self->hidden) {
269 g_message("hidden");
270 switch (self->pos) {
271 case SlitPos_Floating:
272 break;
273 case SlitPos_TopLeft:
274 if (self->horz)
275 self->y -= self->h - theme_bwidth;
276 else
277 self->x -= self->w - theme_bwidth;
278 break;
279 case SlitPos_Top:
280 self->y -= self->h - theme_bwidth;
281 break;
282 case SlitPos_TopRight:
283 if (self->horz)
284 self->y -= self->h - theme_bwidth;
285 else
286 self->x += self->w - theme_bwidth;
287 break;
288 case SlitPos_Left:
289 self->x -= self->w - theme_bwidth;
290 break;
291 case SlitPos_Right:
292 self->x += self->w - theme_bwidth;
293 break;
294 case SlitPos_BottomLeft:
295 if (self->horz)
296 self->y += self->h - theme_bwidth;
297 else
298 self->x -= self->w - theme_bwidth;
299 break;
300 case SlitPos_Bottom:
301 self->y += self->h - theme_bwidth;
302 break;
303 case SlitPos_BottomRight:
304 if (self->horz)
305 self->y += self->h - theme_bwidth;
306 else
307 self->x += self->w - theme_bwidth;
308 break;
309 }
310 }
311
312 /* not used for actually sizing shit */
313 self->w -= theme_bwidth * 2;
314 self->h -= theme_bwidth * 2;
315
316 if (self->w > 0 && self->h > 0) {
317 RECT_SET(self->a_frame->area, 0, 0, self->w, self->h);
318 XMoveResizeWindow(ob_display, self->frame,
319 self->x, self->y, self->w, self->h);
320
321 paint(self->frame, self->a_frame);
322 XMapWindow(ob_display, self->frame);
323 } else
324 XUnmapWindow(ob_display, self->frame);
325 }
326
327 void slit_app_configure(SlitApp *app, int w, int h)
328 {
329 app->w = w;
330 app->h = h;
331 slit_configure(app->slit);
332 }
This page took 0.045043 seconds and 3 git commands to generate.