]> Dogcows Code - chaz/openbox/blob - openbox/frame.c
rename the 'root' context to 'desktop'
[chaz/openbox] / openbox / frame.c
1 #include "frame.h"
2 #include "client.h"
3 #include "openbox.h"
4 #include "extensions.h"
5 #include "config.h"
6 #include "framerender.h"
7 #include "render/theme.h"
8
9 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
10 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
11 ButtonPressMask | ButtonReleaseMask | \
12 VisibilityChangeMask)
13 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
14 ButtonMotionMask | ExposureMask | \
15 EnterWindowMask | LeaveWindowMask)
16
17 #define FRAME_HANDLE_Y(f) (f->innersize.top + f->client->area.height + \
18 f->cbwidth_y)
19
20 static void layout_title(ObFrame *self);
21
22 static Window createWindow(Window parent, unsigned long mask,
23 XSetWindowAttributes *attrib)
24 {
25 return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
26 RrDepth(ob_rr_inst), InputOutput,
27 RrVisual(ob_rr_inst), mask, attrib);
28
29 }
30
31 ObFrame *frame_new()
32 {
33 XSetWindowAttributes attrib;
34 unsigned long mask;
35 ObFrame *self;
36
37 self = g_new(ObFrame, 1);
38
39 self->visible = FALSE;
40 self->obscured = TRUE;
41 self->decorations = 0;
42
43 /* create all of the decor windows */
44 mask = CWOverrideRedirect | CWEventMask;
45 attrib.event_mask = FRAME_EVENTMASK;
46 attrib.override_redirect = TRUE;
47 self->window = createWindow(RootWindow(ob_display, ob_screen),
48 mask, &attrib);
49
50 mask = 0;
51 self->plate = createWindow(self->window, mask, &attrib);
52
53 mask = CWEventMask;
54 attrib.event_mask = ELEMENT_EVENTMASK;
55 self->title = createWindow(self->window, mask, &attrib);
56
57 mask |= CWCursor;
58 attrib.cursor = ob_cursor(OB_CURSOR_NORTHWEST);
59 self->tlresize = createWindow(self->title, mask, &attrib);
60 attrib.cursor = ob_cursor(OB_CURSOR_NORTHEAST);
61 self->trresize = createWindow(self->title, mask, &attrib);
62
63 mask &= ~CWCursor;
64 self->label = createWindow(self->title, mask, &attrib);
65 self->max = createWindow(self->title, mask, &attrib);
66 self->close = createWindow(self->title, mask, &attrib);
67 self->desk = createWindow(self->title, mask, &attrib);
68 self->shade = createWindow(self->title, mask, &attrib);
69 self->icon = createWindow(self->title, mask, &attrib);
70 self->iconify = createWindow(self->title, mask, &attrib);
71 self->handle = createWindow(self->window, mask, &attrib);
72
73 mask |= CWCursor;
74 attrib.cursor = ob_cursor(OB_CURSOR_SOUTHWEST);
75 self->lgrip = createWindow(self->handle, mask, &attrib);
76 attrib.cursor = ob_cursor(OB_CURSOR_SOUTHEAST);
77 self->rgrip = createWindow(self->handle, mask, &attrib);
78
79 self->focused = FALSE;
80
81 /* the other stuff is shown based on decor settings */
82 XMapWindow(ob_display, self->plate);
83 XMapWindow(ob_display, self->lgrip);
84 XMapWindow(ob_display, self->rgrip);
85 XMapWindow(ob_display, self->label);
86
87 /* set colors/appearance/sizes for stuff that doesn't change */
88 XSetWindowBorder(ob_display, self->window, ob_rr_theme->b_color->pixel);
89 XSetWindowBorder(ob_display, self->title, ob_rr_theme->b_color->pixel);
90 XSetWindowBorder(ob_display, self->handle, ob_rr_theme->b_color->pixel);
91 XSetWindowBorder(ob_display, self->rgrip, ob_rr_theme->b_color->pixel);
92 XSetWindowBorder(ob_display, self->lgrip, ob_rr_theme->b_color->pixel);
93
94 XResizeWindow(ob_display, self->max,
95 ob_rr_theme->button_size, ob_rr_theme->button_size);
96 XResizeWindow(ob_display, self->iconify,
97 ob_rr_theme->button_size, ob_rr_theme->button_size);
98 XResizeWindow(ob_display, self->icon,
99 ob_rr_theme->button_size + 2, ob_rr_theme->button_size + 2);
100 XResizeWindow(ob_display, self->close,
101 ob_rr_theme->button_size, ob_rr_theme->button_size);
102 XResizeWindow(ob_display, self->desk,
103 ob_rr_theme->button_size, ob_rr_theme->button_size);
104 XResizeWindow(ob_display, self->shade,
105 ob_rr_theme->button_size, ob_rr_theme->button_size);
106 XResizeWindow(ob_display, self->lgrip,
107 ob_rr_theme->grip_width, ob_rr_theme->handle_height);
108 XResizeWindow(ob_display, self->rgrip,
109 ob_rr_theme->grip_width, ob_rr_theme->handle_height);
110 XResizeWindow(ob_display, self->tlresize,
111 ob_rr_theme->grip_width, ob_rr_theme->handle_height);
112 XResizeWindow(ob_display, self->trresize,
113 ob_rr_theme->grip_width, ob_rr_theme->handle_height);
114
115 /* set up the dynamic appearances */
116 self->a_unfocused_title = RrAppearanceCopy(ob_rr_theme->a_unfocused_title);
117 self->a_focused_title = RrAppearanceCopy(ob_rr_theme->a_focused_title);
118 self->a_unfocused_label = RrAppearanceCopy(ob_rr_theme->a_unfocused_label);
119 self->a_focused_label = RrAppearanceCopy(ob_rr_theme->a_focused_label);
120 self->a_unfocused_handle =
121 RrAppearanceCopy(ob_rr_theme->a_unfocused_handle);
122 self->a_focused_handle = RrAppearanceCopy(ob_rr_theme->a_focused_handle);
123 self->a_icon = RrAppearanceCopy(ob_rr_theme->a_icon);
124
125 self->max_press = self->close_press = self->desk_press =
126 self->iconify_press = self->shade_press = FALSE;
127 self->max_hover = self->close_hover = self->desk_hover =
128 self->iconify_hover = self->shade_hover = FALSE;
129
130 return (ObFrame*)self;
131 }
132
133 static void frame_free(ObFrame *self)
134 {
135 RrAppearanceFree(self->a_unfocused_title);
136 RrAppearanceFree(self->a_focused_title);
137 RrAppearanceFree(self->a_unfocused_label);
138 RrAppearanceFree(self->a_focused_label);
139 RrAppearanceFree(self->a_unfocused_handle);
140 RrAppearanceFree(self->a_focused_handle);
141 RrAppearanceFree(self->a_icon);
142
143 XDestroyWindow(ob_display, self->window);
144
145 g_free(self);
146 }
147
148 void frame_show(ObFrame *self)
149 {
150 if (!self->visible) {
151 self->visible = TRUE;
152 XMapWindow(ob_display, self->window);
153 }
154 }
155
156 void frame_hide(ObFrame *self)
157 {
158 if (self->visible) {
159 self->visible = FALSE;
160 self->client->ignore_unmaps++;
161 XUnmapWindow(ob_display, self->window);
162 }
163 }
164
165 void frame_adjust_shape(ObFrame *self)
166 {
167 #ifdef SHAPE
168 int num;
169 XRectangle xrect[2];
170
171 if (!self->client->shaped) {
172 /* clear the shape on the frame window */
173 XShapeCombineMask(ob_display, self->window, ShapeBounding,
174 self->innersize.left,
175 self->innersize.top,
176 None, ShapeSet);
177 } else {
178 /* make the frame's shape match the clients */
179 XShapeCombineShape(ob_display, self->window, ShapeBounding,
180 self->innersize.left,
181 self->innersize.top,
182 self->client->window,
183 ShapeBounding, ShapeSet);
184
185 num = 0;
186 if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
187 xrect[0].x = -ob_rr_theme->bwidth;
188 xrect[0].y = -ob_rr_theme->bwidth;
189 xrect[0].width = self->width + self->rbwidth * 2;
190 xrect[0].height = ob_rr_theme->title_height +
191 self->bwidth * 2;
192 ++num;
193 }
194
195 if (self->decorations & OB_FRAME_DECOR_HANDLE) {
196 xrect[1].x = -ob_rr_theme->bwidth;
197 xrect[1].y = FRAME_HANDLE_Y(self);
198 xrect[1].width = self->width + self->rbwidth * 2;
199 xrect[1].height = ob_rr_theme->handle_height +
200 self->bwidth * 2;
201 ++num;
202 }
203
204 XShapeCombineRectangles(ob_display, self->window,
205 ShapeBounding, 0, 0, xrect, num,
206 ShapeUnion, Unsorted);
207 }
208 #endif
209 }
210
211 void frame_adjust_area(ObFrame *self, gboolean moved,
212 gboolean resized, gboolean fake)
213 {
214 if (resized) {
215 self->decorations = self->client->decorations;
216
217 if (self->decorations & OB_FRAME_DECOR_BORDER) {
218 self->bwidth = ob_rr_theme->bwidth;
219 self->cbwidth_x = self->cbwidth_y = ob_rr_theme->cbwidth;
220 } else {
221 self->bwidth = self->cbwidth_x = self->cbwidth_y = 0;
222 }
223 self->rbwidth = self->bwidth;
224
225 if (self->client->max_vert && self->client->max_horz)
226 self->decorations &= ~OB_FRAME_DECOR_HANDLE;
227
228 if (self->client->max_horz)
229 self->bwidth = self->cbwidth_x = 0;
230
231 STRUT_SET(self->innersize,
232 self->cbwidth_x,
233 self->cbwidth_y,
234 self->cbwidth_x,
235 self->cbwidth_y);
236 self->width = self->client->area.width + self->cbwidth_x * 2 -
237 (self->client->max_horz ? self->rbwidth * 2 : 0);
238 self->width = MAX(self->width, 1); /* no lower than 1 */
239
240 /* set border widths */
241 if (!fake) {
242 XSetWindowBorderWidth(ob_display, self->window, self->bwidth);
243 XSetWindowBorderWidth(ob_display, self->title, self->rbwidth);
244 XSetWindowBorderWidth(ob_display, self->handle, self->rbwidth);
245 XSetWindowBorderWidth(ob_display, self->lgrip, self->rbwidth);
246 XSetWindowBorderWidth(ob_display, self->rgrip, self->rbwidth);
247 }
248
249 if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
250 self->innersize.top += ob_rr_theme->title_height + self->rbwidth +
251 (self->rbwidth - self->bwidth);
252 if (self->decorations & OB_FRAME_DECOR_HANDLE)
253 self->innersize.bottom += ob_rr_theme->handle_height +
254 self->rbwidth + (self->rbwidth - self->bwidth);
255
256 /* they all default off, they're turned on in layout_title */
257 self->icon_x = -1;
258 self->desk_x = -1;
259 self->shade_x = -1;
260 self->iconify_x = -1;
261 self->label_x = -1;
262 self->max_x = -1;
263 self->close_x = -1;
264
265 /* position/size and map/unmap all the windows */
266
267 if (!fake) {
268 if (self->decorations & OB_FRAME_DECOR_TITLEBAR) {
269 XMoveResizeWindow(ob_display, self->title,
270 -self->bwidth, -self->bwidth,
271 self->width, ob_rr_theme->title_height);
272 XMapWindow(ob_display, self->title);
273
274 if (self->decorations & OB_FRAME_DECOR_GRIPS) {
275 XMoveWindow(ob_display, self->tlresize, 0, 0);
276 XMoveWindow(ob_display, self->trresize,
277 self->width - ob_rr_theme->grip_width, 0);
278 XMapWindow(ob_display, self->tlresize);
279 XMapWindow(ob_display, self->trresize);
280 } else {
281 XUnmapWindow(ob_display, self->tlresize);
282 XUnmapWindow(ob_display, self->trresize);
283 }
284 } else
285 XUnmapWindow(ob_display, self->title);
286 }
287
288 if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
289 /* layout the title bar elements */
290 layout_title(self);
291
292 if (!fake) {
293 if (self->decorations & OB_FRAME_DECOR_HANDLE) {
294 XMoveResizeWindow(ob_display, self->handle,
295 -self->bwidth, FRAME_HANDLE_Y(self),
296 self->width, ob_rr_theme->handle_height);
297 XMapWindow(ob_display, self->handle);
298
299 if (self->decorations & OB_FRAME_DECOR_GRIPS) {
300 XMoveWindow(ob_display, self->lgrip,
301 -self->rbwidth, -self->rbwidth);
302 XMoveWindow(ob_display, self->rgrip,
303 -self->rbwidth + self->width -
304 ob_rr_theme->grip_width, -self->rbwidth);
305 XMapWindow(ob_display, self->lgrip);
306 XMapWindow(ob_display, self->rgrip);
307 } else {
308 XUnmapWindow(ob_display, self->lgrip);
309 XUnmapWindow(ob_display, self->rgrip);
310 }
311
312 /* XXX make a subwindow with these dimentions?
313 ob_rr_theme->grip_width + self->bwidth, 0,
314 self->width - (ob_rr_theme->grip_width + self->bwidth) * 2,
315 ob_rr_theme->handle_height);
316 */
317 } else
318 XUnmapWindow(ob_display, self->handle);
319
320 /* move and resize the plate */
321 XMoveResizeWindow(ob_display, self->plate,
322 self->innersize.left - self->cbwidth_x,
323 self->innersize.top - self->cbwidth_y,
324 self->client->area.width + self->cbwidth_x * 2,
325 self->client->area.height + self->cbwidth_y * 2);
326 /* when the client has StaticGravity, it likes to move around. */
327 XMoveWindow(ob_display, self->client->window,
328 self->cbwidth_x, self->cbwidth_y);
329 }
330
331 STRUT_SET(self->size,
332 self->innersize.left + self->bwidth,
333 self->innersize.top + self->bwidth,
334 self->innersize.right + self->bwidth,
335 self->innersize.bottom + self->bwidth);
336 }
337
338 /* shading can change without being moved or resized */
339 RECT_SET_SIZE(self->area,
340 self->client->area.width +
341 self->size.left + self->size.right,
342 (self->client->shaded ?
343 ob_rr_theme->title_height + self->bwidth*2:
344 self->client->area.height +
345 self->size.top + self->size.bottom));
346
347 if (moved) {
348 /* find the new coordinates, done after setting the frame.size, for
349 frame_client_gravity. */
350 self->area.x = self->client->area.x;
351 self->area.y = self->client->area.y;
352 frame_client_gravity(self, &self->area.x, &self->area.y);
353 }
354
355 if (!fake) {
356 /* move and resize the top level frame.
357 shading can change without being moved or resized */
358 XMoveResizeWindow(ob_display, self->window,
359 self->area.x, self->area.y,
360 self->area.width - self->bwidth * 2,
361 self->area.height - self->bwidth * 2);
362
363 if (resized) {
364 framerender_frame(self);
365
366 frame_adjust_shape(self);
367 }
368 }
369 }
370
371 void frame_adjust_state(ObFrame *self)
372 {
373 framerender_frame(self);
374 }
375
376 void frame_adjust_focus(ObFrame *self, gboolean hilite)
377 {
378 self->focused = hilite;
379 framerender_frame(self);
380 }
381
382 void frame_adjust_title(ObFrame *self)
383 {
384 framerender_frame(self);
385 }
386
387 void frame_adjust_icon(ObFrame *self)
388 {
389 framerender_frame(self);
390 }
391
392 void frame_grab_client(ObFrame *self, ObClient *client)
393 {
394 self->client = client;
395
396 /* reparent the client to the frame */
397 XReparentWindow(ob_display, client->window, self->plate, 0, 0);
398 /*
399 When reparenting the client window, it is usually not mapped yet, since
400 this occurs from a MapRequest. However, in the case where Openbox is
401 starting up, the window is already mapped, so we'll see unmap events for
402 it. There are 2 unmap events generated that we see, one with the 'event'
403 member set the root window, and one set to the client, but both get
404 handled and need to be ignored.
405 */
406 if (ob_state() == OB_STATE_STARTING)
407 client->ignore_unmaps += 2;
408
409 /* select the event mask on the client's parent (to receive config/map
410 req's) the ButtonPress is to catch clicks on the client border */
411 XSelectInput(ob_display, self->plate, PLATE_EVENTMASK);
412
413 /* map the client so it maps when the frame does */
414 XMapWindow(ob_display, client->window);
415
416 frame_adjust_area(self, TRUE, TRUE, FALSE);
417
418 /* set all the windows for the frame in the window_map */
419 g_hash_table_insert(window_map, &self->window, client);
420 g_hash_table_insert(window_map, &self->plate, client);
421 g_hash_table_insert(window_map, &self->title, client);
422 g_hash_table_insert(window_map, &self->label, client);
423 g_hash_table_insert(window_map, &self->max, client);
424 g_hash_table_insert(window_map, &self->close, client);
425 g_hash_table_insert(window_map, &self->desk, client);
426 g_hash_table_insert(window_map, &self->shade, client);
427 g_hash_table_insert(window_map, &self->icon, client);
428 g_hash_table_insert(window_map, &self->iconify, client);
429 g_hash_table_insert(window_map, &self->handle, client);
430 g_hash_table_insert(window_map, &self->lgrip, client);
431 g_hash_table_insert(window_map, &self->rgrip, client);
432 g_hash_table_insert(window_map, &self->tlresize, client);
433 g_hash_table_insert(window_map, &self->trresize, client);
434 }
435
436 void frame_release_client(ObFrame *self, ObClient *client)
437 {
438 XEvent ev;
439
440 g_assert(self->client == client);
441
442 /* check if the app has already reparented its window away */
443 if (XCheckTypedWindowEvent(ob_display, client->window,
444 ReparentNotify, &ev)) {
445 XPutBackEvent(ob_display, &ev);
446
447 /* re-map the window since the unmanaging process unmaps it */
448
449 /* XXX ... um no it doesnt it unmaps its parent, the window itself
450 retains its mapped state, no?! XXX
451 XMapWindow(ob_display, client->window); */
452 } else {
453 /* according to the ICCCM - if the client doesn't reparent itself,
454 then we will reparent the window to root for them */
455 XReparentWindow(ob_display, client->window,
456 RootWindow(ob_display, ob_screen),
457 client->area.x,
458 client->area.y);
459 }
460
461 /* remove all the windows for the frame from the window_map */
462 g_hash_table_remove(window_map, &self->window);
463 g_hash_table_remove(window_map, &self->plate);
464 g_hash_table_remove(window_map, &self->title);
465 g_hash_table_remove(window_map, &self->label);
466 g_hash_table_remove(window_map, &self->max);
467 g_hash_table_remove(window_map, &self->close);
468 g_hash_table_remove(window_map, &self->desk);
469 g_hash_table_remove(window_map, &self->shade);
470 g_hash_table_remove(window_map, &self->icon);
471 g_hash_table_remove(window_map, &self->iconify);
472 g_hash_table_remove(window_map, &self->handle);
473 g_hash_table_remove(window_map, &self->lgrip);
474 g_hash_table_remove(window_map, &self->rgrip);
475 g_hash_table_remove(window_map, &self->tlresize);
476 g_hash_table_remove(window_map, &self->trresize);
477
478 frame_free(self);
479 }
480
481 static void layout_title(ObFrame *self)
482 {
483 char *lc;
484 int x;
485 gboolean n, d, i, l, m, c, s;
486
487 n = d = i = l = m = c = s = FALSE;
488
489 /* figure out whats being shown, and the width of the label */
490 self->label_width = self->width - (ob_rr_theme->bevel + 1) * 2;
491 for (lc = config_title_layout; *lc != '\0'; ++lc) {
492 switch (*lc) {
493 case 'N':
494 if (n) { *lc = ' '; break; } /* rm duplicates */
495 n = TRUE;
496 self->label_width -= (ob_rr_theme->button_size + 2 +
497 ob_rr_theme->bevel + 1);
498 break;
499 case 'D':
500 if (d) { *lc = ' '; break; } /* rm duplicates */
501 d = TRUE;
502 self->label_width -= (ob_rr_theme->button_size +
503 ob_rr_theme->bevel + 1);
504 break;
505 case 'S':
506 if (s) { *lc = ' '; break; } /* rm duplicates */
507 s = TRUE;
508 self->label_width -= (ob_rr_theme->button_size +
509 ob_rr_theme->bevel + 1);
510 break;
511 case 'I':
512 if (i) { *lc = ' '; break; } /* rm duplicates */
513 i = TRUE;
514 self->label_width -= (ob_rr_theme->button_size +
515 ob_rr_theme->bevel + 1);
516 break;
517 case 'L':
518 if (l) { *lc = ' '; break; } /* rm duplicates */
519 l = TRUE;
520 break;
521 case 'M':
522 if (m) { *lc = ' '; break; } /* rm duplicates */
523 m = TRUE;
524 self->label_width -= (ob_rr_theme->button_size +
525 ob_rr_theme->bevel + 1);
526 break;
527 case 'C':
528 if (c) { *lc = ' '; break; } /* rm duplicates */
529 c = TRUE;
530 self->label_width -= (ob_rr_theme->button_size +
531 ob_rr_theme->bevel + 1);
532 break;
533 }
534 }
535 if (self->label_width < 1) self->label_width = 1;
536
537 XResizeWindow(ob_display, self->label, self->label_width,
538 ob_rr_theme->label_height);
539
540 if (!n) XUnmapWindow(ob_display, self->icon);
541 if (!d) XUnmapWindow(ob_display, self->desk);
542 if (!s) XUnmapWindow(ob_display, self->shade);
543 if (!i) XUnmapWindow(ob_display, self->iconify);
544 if (!l) XUnmapWindow(ob_display, self->label);
545 if (!m) XUnmapWindow(ob_display, self->max);
546 if (!c) XUnmapWindow(ob_display, self->close);
547
548 x = ob_rr_theme->bevel + 1;
549 for (lc = config_title_layout; *lc != '\0'; ++lc) {
550 switch (*lc) {
551 case 'N':
552 if (!n) break;
553 self->icon_x = x;
554 XMapWindow(ob_display, self->icon);
555 XMoveWindow(ob_display, self->icon, x, ob_rr_theme->bevel);
556 x += ob_rr_theme->button_size + 2 + ob_rr_theme->bevel + 1;
557 break;
558 case 'D':
559 if (!d) break;
560 self->desk_x = x;
561 XMapWindow(ob_display, self->desk);
562 XMoveWindow(ob_display, self->desk, x, ob_rr_theme->bevel + 1);
563 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
564 break;
565 case 'S':
566 if (!s) break;
567 self->shade_x = x;
568 XMapWindow(ob_display, self->shade);
569 XMoveWindow(ob_display, self->shade, x, ob_rr_theme->bevel + 1);
570 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
571 break;
572 case 'I':
573 if (!i) break;
574 self->iconify_x = x;
575 XMapWindow(ob_display, self->iconify);
576 XMoveWindow(ob_display, self->iconify, x, ob_rr_theme->bevel + 1);
577 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
578 break;
579 case 'L':
580 if (!l) break;
581 self->label_x = x;
582 XMapWindow(ob_display, self->label);
583 XMoveWindow(ob_display, self->label, x, ob_rr_theme->bevel);
584 x += self->label_width + ob_rr_theme->bevel + 1;
585 break;
586 case 'M':
587 if (!m) break;
588 self->max_x = x;
589 XMapWindow(ob_display, self->max);
590 XMoveWindow(ob_display, self->max, x, ob_rr_theme->bevel + 1);
591 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
592 break;
593 case 'C':
594 if (!c) break;
595 self->close_x = x;
596 XMapWindow(ob_display, self->close);
597 XMoveWindow(ob_display, self->close, x, ob_rr_theme->bevel + 1);
598 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
599 break;
600 }
601 }
602 }
603
604 ObFrameContext frame_context_from_string(char *name)
605 {
606 if (!g_ascii_strcasecmp("desktop", name))
607 return OB_FRAME_CONTEXT_DESKTOP;
608 else if (!g_ascii_strcasecmp("client", name))
609 return OB_FRAME_CONTEXT_CLIENT;
610 else if (!g_ascii_strcasecmp("titlebar", name))
611 return OB_FRAME_CONTEXT_TITLEBAR;
612 else if (!g_ascii_strcasecmp("handle", name))
613 return OB_FRAME_CONTEXT_HANDLE;
614 else if (!g_ascii_strcasecmp("frame", name))
615 return OB_FRAME_CONTEXT_FRAME;
616 else if (!g_ascii_strcasecmp("tlcorner", name))
617 return OB_FRAME_CONTEXT_TLCORNER;
618 else if (!g_ascii_strcasecmp("trcorner", name))
619 return OB_FRAME_CONTEXT_TRCORNER;
620 else if (!g_ascii_strcasecmp("blcorner", name))
621 return OB_FRAME_CONTEXT_BLCORNER;
622 else if (!g_ascii_strcasecmp("brcorner", name))
623 return OB_FRAME_CONTEXT_BRCORNER;
624 else if (!g_ascii_strcasecmp("maximize", name))
625 return OB_FRAME_CONTEXT_MAXIMIZE;
626 else if (!g_ascii_strcasecmp("alldesktops", name))
627 return OB_FRAME_CONTEXT_ALLDESKTOPS;
628 else if (!g_ascii_strcasecmp("shade", name))
629 return OB_FRAME_CONTEXT_SHADE;
630 else if (!g_ascii_strcasecmp("iconify", name))
631 return OB_FRAME_CONTEXT_ICONIFY;
632 else if (!g_ascii_strcasecmp("icon", name))
633 return OB_FRAME_CONTEXT_ICON;
634 else if (!g_ascii_strcasecmp("close", name))
635 return OB_FRAME_CONTEXT_CLOSE;
636 return OB_FRAME_CONTEXT_NONE;
637 }
638
639 ObFrameContext frame_context(ObClient *client, Window win)
640 {
641 ObFrame *self;
642
643 if (win == RootWindow(ob_display, ob_screen))
644 return OB_FRAME_CONTEXT_DESKTOP;
645 if (client == NULL) return OB_FRAME_CONTEXT_NONE;
646 if (win == client->window) {
647 /* conceptually, this is the desktop, as far as users are
648 concerned */
649 if (client->type == OB_CLIENT_TYPE_DESKTOP)
650 return OB_FRAME_CONTEXT_DESKTOP;
651 return OB_FRAME_CONTEXT_CLIENT;
652 }
653
654 self = client->frame;
655 if (win == self->plate) {
656 /* conceptually, this is the desktop, as far as users are
657 concerned */
658 if (client->type == OB_CLIENT_TYPE_DESKTOP)
659 return OB_FRAME_CONTEXT_DESKTOP;
660 return OB_FRAME_CONTEXT_CLIENT;
661 }
662
663 if (win == self->window) return OB_FRAME_CONTEXT_FRAME;
664 if (win == self->title) return OB_FRAME_CONTEXT_TITLEBAR;
665 if (win == self->label) return OB_FRAME_CONTEXT_TITLEBAR;
666 if (win == self->handle) return OB_FRAME_CONTEXT_HANDLE;
667 if (win == self->lgrip) return OB_FRAME_CONTEXT_BLCORNER;
668 if (win == self->rgrip) return OB_FRAME_CONTEXT_BRCORNER;
669 if (win == self->tlresize) return OB_FRAME_CONTEXT_TLCORNER;
670 if (win == self->trresize) return OB_FRAME_CONTEXT_TRCORNER;
671 if (win == self->max) return OB_FRAME_CONTEXT_MAXIMIZE;
672 if (win == self->iconify) return OB_FRAME_CONTEXT_ICONIFY;
673 if (win == self->close) return OB_FRAME_CONTEXT_CLOSE;
674 if (win == self->icon) return OB_FRAME_CONTEXT_ICON;
675 if (win == self->desk) return OB_FRAME_CONTEXT_ALLDESKTOPS;
676 if (win == self->shade) return OB_FRAME_CONTEXT_SHADE;
677
678 return OB_FRAME_CONTEXT_NONE;
679 }
680
681 void frame_client_gravity(ObFrame *self, int *x, int *y)
682 {
683 /* horizontal */
684 switch (self->client->gravity) {
685 default:
686 case NorthWestGravity:
687 case SouthWestGravity:
688 case WestGravity:
689 break;
690
691 case NorthGravity:
692 case SouthGravity:
693 case CenterGravity:
694 *x -= (self->size.left + self->size.right) / 2;
695 break;
696
697 case NorthEastGravity:
698 case SouthEastGravity:
699 case EastGravity:
700 *x -= self->size.left + self->size.right;
701 break;
702
703 case ForgetGravity:
704 case StaticGravity:
705 *x -= self->size.left;
706 break;
707 }
708
709 /* vertical */
710 switch (self->client->gravity) {
711 default:
712 case NorthWestGravity:
713 case NorthEastGravity:
714 case NorthGravity:
715 break;
716
717 case CenterGravity:
718 case EastGravity:
719 case WestGravity:
720 *y -= (self->size.top + self->size.bottom) / 2;
721 break;
722
723 case SouthWestGravity:
724 case SouthEastGravity:
725 case SouthGravity:
726 *y -= self->size.top + self->size.bottom;
727 break;
728
729 case ForgetGravity:
730 case StaticGravity:
731 *y -= self->size.top;
732 break;
733 }
734 }
735
736 void frame_frame_gravity(ObFrame *self, int *x, int *y)
737 {
738 /* horizontal */
739 switch (self->client->gravity) {
740 default:
741 case NorthWestGravity:
742 case WestGravity:
743 case SouthWestGravity:
744 break;
745 case NorthGravity:
746 case CenterGravity:
747 case SouthGravity:
748 *x += (self->size.left + self->size.right) / 2;
749 break;
750 case NorthEastGravity:
751 case EastGravity:
752 case SouthEastGravity:
753 *x += self->size.left + self->size.right;
754 break;
755 case StaticGravity:
756 case ForgetGravity:
757 *x += self->size.left;
758 break;
759 }
760
761 /* vertical */
762 switch (self->client->gravity) {
763 default:
764 case NorthWestGravity:
765 case NorthGravity:
766 case NorthEastGravity:
767 break;
768 case WestGravity:
769 case CenterGravity:
770 case EastGravity:
771 *y += (self->size.top + self->size.bottom) / 2;
772 break;
773 case SouthWestGravity:
774 case SouthGravity:
775 case SouthEastGravity:
776 *y += self->size.top + self->size.bottom;
777 break;
778 case StaticGravity:
779 case ForgetGravity:
780 *y += self->size.top;
781 break;
782 }
783 }
This page took 0.0681850000000001 seconds and 4 git commands to generate.