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