]> Dogcows Code - chaz/openbox/blob - openbox/frame.c
add an obscured flag that tracks if the frame is at all obscured
[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("root", name))
607 return OB_FRAME_CONTEXT_ROOT;
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)) return OB_FRAME_CONTEXT_ROOT;
644 if (client == NULL) return OB_FRAME_CONTEXT_NONE;
645 if (win == client->window) {
646 /* conceptually, this is the root window, as far as users are
647 concerned */
648 if (client->type == OB_CLIENT_TYPE_DESKTOP)
649 return OB_FRAME_CONTEXT_ROOT;
650 return OB_FRAME_CONTEXT_CLIENT;
651 }
652
653 self = client->frame;
654 if (win == self->plate) {
655 /* conceptually, this is the root window, as far as users are
656 concerned */
657 if (client->type == OB_CLIENT_TYPE_DESKTOP)
658 return OB_FRAME_CONTEXT_ROOT;
659 return OB_FRAME_CONTEXT_CLIENT;
660 }
661
662 if (win == self->window) return OB_FRAME_CONTEXT_FRAME;
663 if (win == self->title) return OB_FRAME_CONTEXT_TITLEBAR;
664 if (win == self->label) return OB_FRAME_CONTEXT_TITLEBAR;
665 if (win == self->handle) return OB_FRAME_CONTEXT_HANDLE;
666 if (win == self->lgrip) return OB_FRAME_CONTEXT_BLCORNER;
667 if (win == self->rgrip) return OB_FRAME_CONTEXT_BRCORNER;
668 if (win == self->tlresize) return OB_FRAME_CONTEXT_TLCORNER;
669 if (win == self->trresize) return OB_FRAME_CONTEXT_TRCORNER;
670 if (win == self->max) return OB_FRAME_CONTEXT_MAXIMIZE;
671 if (win == self->iconify) return OB_FRAME_CONTEXT_ICONIFY;
672 if (win == self->close) return OB_FRAME_CONTEXT_CLOSE;
673 if (win == self->icon) return OB_FRAME_CONTEXT_ICON;
674 if (win == self->desk) return OB_FRAME_CONTEXT_ALLDESKTOPS;
675 if (win == self->shade) return OB_FRAME_CONTEXT_SHADE;
676
677 return OB_FRAME_CONTEXT_NONE;
678 }
679
680 void frame_client_gravity(ObFrame *self, int *x, int *y)
681 {
682 /* horizontal */
683 switch (self->client->gravity) {
684 default:
685 case NorthWestGravity:
686 case SouthWestGravity:
687 case WestGravity:
688 break;
689
690 case NorthGravity:
691 case SouthGravity:
692 case CenterGravity:
693 *x -= (self->size.left + self->size.right) / 2;
694 break;
695
696 case NorthEastGravity:
697 case SouthEastGravity:
698 case EastGravity:
699 *x -= self->size.left + self->size.right;
700 break;
701
702 case ForgetGravity:
703 case StaticGravity:
704 *x -= self->size.left;
705 break;
706 }
707
708 /* vertical */
709 switch (self->client->gravity) {
710 default:
711 case NorthWestGravity:
712 case NorthEastGravity:
713 case NorthGravity:
714 break;
715
716 case CenterGravity:
717 case EastGravity:
718 case WestGravity:
719 *y -= (self->size.top + self->size.bottom) / 2;
720 break;
721
722 case SouthWestGravity:
723 case SouthEastGravity:
724 case SouthGravity:
725 *y -= self->size.top + self->size.bottom;
726 break;
727
728 case ForgetGravity:
729 case StaticGravity:
730 *y -= self->size.top;
731 break;
732 }
733 }
734
735 void frame_frame_gravity(ObFrame *self, int *x, int *y)
736 {
737 /* horizontal */
738 switch (self->client->gravity) {
739 default:
740 case NorthWestGravity:
741 case WestGravity:
742 case SouthWestGravity:
743 break;
744 case NorthGravity:
745 case CenterGravity:
746 case SouthGravity:
747 *x += (self->size.left + self->size.right) / 2;
748 break;
749 case NorthEastGravity:
750 case EastGravity:
751 case SouthEastGravity:
752 *x += self->size.left + self->size.right;
753 break;
754 case StaticGravity:
755 case ForgetGravity:
756 *x += self->size.left;
757 break;
758 }
759
760 /* vertical */
761 switch (self->client->gravity) {
762 default:
763 case NorthWestGravity:
764 case NorthGravity:
765 case NorthEastGravity:
766 break;
767 case WestGravity:
768 case CenterGravity:
769 case EastGravity:
770 *y += (self->size.top + self->size.bottom) / 2;
771 break;
772 case SouthWestGravity:
773 case SouthGravity:
774 case SouthEastGravity:
775 *y += self->size.top + self->size.bottom;
776 break;
777 case StaticGravity:
778 case ForgetGravity:
779 *y += self->size.top;
780 break;
781 }
782 }
This page took 0.067596 seconds and 4 git commands to generate.