]> Dogcows Code - chaz/openbox/blob - openbox/frame.c
a couple frame layout bugfixes hidden inside all this.. wee
[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_y)
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->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 XMoveWindow(ob_display, self->tlresize, 0, 0);
275 XMoveWindow(ob_display, self->trresize,
276 self->width - ob_rr_theme->grip_width, 0);
277
278 } else
279 XUnmapWindow(ob_display, self->title);
280 }
281
282 if (self->decorations & OB_FRAME_DECOR_TITLEBAR)
283 /* layout the title bar elements */
284 layout_title(self);
285
286 if (!fake) {
287 if (self->decorations & OB_FRAME_DECOR_HANDLE) {
288 XMoveResizeWindow(ob_display, self->handle,
289 -self->bwidth, FRAME_HANDLE_Y(self),
290 self->width, ob_rr_theme->handle_height);
291 XMapWindow(ob_display, self->handle);
292
293 if (self->decorations & OB_FRAME_DECOR_GRIPS) {
294 XMoveWindow(ob_display, self->lgrip,
295 -self->rbwidth, -self->rbwidth);
296 XMoveWindow(ob_display, self->rgrip,
297 -self->rbwidth + self->width -
298 ob_rr_theme->grip_width, -self->rbwidth);
299 XMapWindow(ob_display, self->lgrip);
300 XMapWindow(ob_display, self->rgrip);
301 } else {
302 XUnmapWindow(ob_display, self->lgrip);
303 XUnmapWindow(ob_display, self->rgrip);
304 }
305
306 /* XXX make a subwindow with these dimentions?
307 ob_rr_theme->grip_width + self->bwidth, 0,
308 self->width - (ob_rr_theme->grip_width + self->bwidth) * 2,
309 ob_rr_theme->handle_height);
310 */
311 } else
312 XUnmapWindow(ob_display, self->handle);
313
314 /* move and resize the plate */
315 XMoveResizeWindow(ob_display, self->plate,
316 self->innersize.left - self->cbwidth_x,
317 self->innersize.top - self->cbwidth_y,
318 self->client->area.width + self->cbwidth_x * 2,
319 self->client->area.height + self->cbwidth_y * 2);
320 /* when the client has StaticGravity, it likes to move around. */
321 XMoveWindow(ob_display, self->client->window,
322 self->cbwidth_x, self->cbwidth_y);
323 }
324
325 STRUT_SET(self->size,
326 self->innersize.left + self->bwidth,
327 self->innersize.top + self->bwidth,
328 self->innersize.right + self->bwidth,
329 self->innersize.bottom + self->bwidth);
330 }
331
332 /* shading can change without being moved or resized */
333 RECT_SET_SIZE(self->area,
334 self->client->area.width +
335 self->size.left + self->size.right,
336 (self->client->shaded ?
337 ob_rr_theme->title_height + self->bwidth*2:
338 self->client->area.height +
339 self->size.top + self->size.bottom));
340
341 if (moved) {
342 /* find the new coordinates, done after setting the frame.size, for
343 frame_client_gravity. */
344 self->area.x = self->client->area.x;
345 self->area.y = self->client->area.y;
346 frame_client_gravity(self, &self->area.x, &self->area.y);
347 }
348
349 if (!fake) {
350 /* move and resize the top level frame.
351 shading can change without being moved or resized */
352 XMoveResizeWindow(ob_display, self->window,
353 self->area.x, self->area.y,
354 self->area.width - self->bwidth * 2,
355 self->area.height - self->bwidth * 2);
356
357 if (resized) {
358 framerender_frame(self);
359
360 frame_adjust_shape(self);
361 }
362 }
363 }
364
365 void frame_adjust_state(ObFrame *self)
366 {
367 framerender_frame(self);
368 }
369
370 void frame_adjust_focus(ObFrame *self, gboolean hilite)
371 {
372 self->focused = hilite;
373 framerender_frame(self);
374 }
375
376 void frame_adjust_title(ObFrame *self)
377 {
378 framerender_frame(self);
379 }
380
381 void frame_adjust_icon(ObFrame *self)
382 {
383 framerender_frame(self);
384 }
385
386 void frame_grab_client(ObFrame *self, ObClient *client)
387 {
388 self->client = client;
389
390 /* reparent the client to the frame */
391 XReparentWindow(ob_display, client->window, self->plate, 0, 0);
392 /*
393 When reparenting the client window, it is usually not mapped yet, since
394 this occurs from a MapRequest. However, in the case where Openbox is
395 starting up, the window is already mapped, so we'll see unmap events for
396 it. There are 2 unmap events generated that we see, one with the 'event'
397 member set the root window, and one set to the client, but both get
398 handled and need to be ignored.
399 */
400 if (ob_state() == OB_STATE_STARTING)
401 client->ignore_unmaps += 2;
402
403 /* select the event mask on the client's parent (to receive config/map
404 req's) the ButtonPress is to catch clicks on the client border */
405 XSelectInput(ob_display, self->plate, PLATE_EVENTMASK);
406
407 /* map the client so it maps when the frame does */
408 XMapWindow(ob_display, client->window);
409
410 frame_adjust_area(self, TRUE, TRUE, FALSE);
411
412 /* set all the windows for the frame in the window_map */
413 g_hash_table_insert(window_map, &self->window, client);
414 g_hash_table_insert(window_map, &self->plate, client);
415 g_hash_table_insert(window_map, &self->title, client);
416 g_hash_table_insert(window_map, &self->label, client);
417 g_hash_table_insert(window_map, &self->max, client);
418 g_hash_table_insert(window_map, &self->close, client);
419 g_hash_table_insert(window_map, &self->desk, client);
420 g_hash_table_insert(window_map, &self->shade, client);
421 g_hash_table_insert(window_map, &self->icon, client);
422 g_hash_table_insert(window_map, &self->iconify, client);
423 g_hash_table_insert(window_map, &self->handle, client);
424 g_hash_table_insert(window_map, &self->lgrip, client);
425 g_hash_table_insert(window_map, &self->rgrip, client);
426 g_hash_table_insert(window_map, &self->tlresize, client);
427 g_hash_table_insert(window_map, &self->trresize, client);
428 }
429
430 void frame_release_client(ObFrame *self, ObClient *client)
431 {
432 XEvent ev;
433
434 g_assert(self->client == client);
435
436 /* check if the app has already reparented its window away */
437 if (XCheckTypedWindowEvent(ob_display, client->window,
438 ReparentNotify, &ev)) {
439 XPutBackEvent(ob_display, &ev);
440
441 /* re-map the window since the unmanaging process unmaps it */
442
443 /* XXX ... um no it doesnt it unmaps its parent, the window itself
444 retains its mapped state, no?! XXX
445 XMapWindow(ob_display, client->window); */
446 } else {
447 /* according to the ICCCM - if the client doesn't reparent itself,
448 then we will reparent the window to root for them */
449 XReparentWindow(ob_display, client->window,
450 RootWindow(ob_display, ob_screen),
451 client->area.x,
452 client->area.y);
453 }
454
455 /* remove all the windows for the frame from the window_map */
456 g_hash_table_remove(window_map, &self->window);
457 g_hash_table_remove(window_map, &self->plate);
458 g_hash_table_remove(window_map, &self->title);
459 g_hash_table_remove(window_map, &self->label);
460 g_hash_table_remove(window_map, &self->max);
461 g_hash_table_remove(window_map, &self->close);
462 g_hash_table_remove(window_map, &self->desk);
463 g_hash_table_remove(window_map, &self->shade);
464 g_hash_table_remove(window_map, &self->icon);
465 g_hash_table_remove(window_map, &self->iconify);
466 g_hash_table_remove(window_map, &self->handle);
467 g_hash_table_remove(window_map, &self->lgrip);
468 g_hash_table_remove(window_map, &self->rgrip);
469 g_hash_table_remove(window_map, &self->tlresize);
470 g_hash_table_remove(window_map, &self->trresize);
471
472 frame_free(self);
473 }
474
475 static void layout_title(ObFrame *self)
476 {
477 char *lc;
478 int x;
479 gboolean n, d, i, l, m, c, s;
480
481 n = d = i = l = m = c = s = FALSE;
482
483 /* figure out whats being shown, and the width of the label */
484 self->label_width = self->width - (ob_rr_theme->bevel + 1) * 2;
485 for (lc = config_title_layout; *lc != '\0'; ++lc) {
486 switch (*lc) {
487 case 'N':
488 if (n) { *lc = ' '; break; } /* rm duplicates */
489 n = TRUE;
490 self->label_width -= (ob_rr_theme->button_size + 2 +
491 ob_rr_theme->bevel + 1);
492 break;
493 case 'D':
494 if (d) { *lc = ' '; break; } /* rm duplicates */
495 d = TRUE;
496 self->label_width -= (ob_rr_theme->button_size +
497 ob_rr_theme->bevel + 1);
498 break;
499 case 'S':
500 if (s) { *lc = ' '; break; } /* rm duplicates */
501 s = TRUE;
502 self->label_width -= (ob_rr_theme->button_size +
503 ob_rr_theme->bevel + 1);
504 break;
505 case 'I':
506 if (i) { *lc = ' '; break; } /* rm duplicates */
507 i = TRUE;
508 self->label_width -= (ob_rr_theme->button_size +
509 ob_rr_theme->bevel + 1);
510 break;
511 case 'L':
512 if (l) { *lc = ' '; break; } /* rm duplicates */
513 l = TRUE;
514 break;
515 case 'M':
516 if (m) { *lc = ' '; break; } /* rm duplicates */
517 m = TRUE;
518 self->label_width -= (ob_rr_theme->button_size +
519 ob_rr_theme->bevel + 1);
520 break;
521 case 'C':
522 if (c) { *lc = ' '; break; } /* rm duplicates */
523 c = TRUE;
524 self->label_width -= (ob_rr_theme->button_size +
525 ob_rr_theme->bevel + 1);
526 break;
527 }
528 }
529 if (self->label_width < 1) self->label_width = 1;
530
531 XResizeWindow(ob_display, self->label, self->label_width,
532 ob_rr_theme->label_height);
533
534 if (!n) XUnmapWindow(ob_display, self->icon);
535 if (!d) XUnmapWindow(ob_display, self->desk);
536 if (!s) XUnmapWindow(ob_display, self->shade);
537 if (!i) XUnmapWindow(ob_display, self->iconify);
538 if (!l) XUnmapWindow(ob_display, self->label);
539 if (!m) XUnmapWindow(ob_display, self->max);
540 if (!c) XUnmapWindow(ob_display, self->close);
541
542 x = ob_rr_theme->bevel + 1;
543 for (lc = config_title_layout; *lc != '\0'; ++lc) {
544 switch (*lc) {
545 case 'N':
546 if (!n) break;
547 self->icon_x = x;
548 XMapWindow(ob_display, self->icon);
549 XMoveWindow(ob_display, self->icon, x, ob_rr_theme->bevel);
550 x += ob_rr_theme->button_size + 2 + ob_rr_theme->bevel + 1;
551 break;
552 case 'D':
553 if (!d) break;
554 self->desk_x = x;
555 XMapWindow(ob_display, self->desk);
556 XMoveWindow(ob_display, self->desk, x, ob_rr_theme->bevel + 1);
557 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
558 break;
559 case 'S':
560 if (!s) break;
561 self->shade_x = x;
562 XMapWindow(ob_display, self->shade);
563 XMoveWindow(ob_display, self->shade, x, ob_rr_theme->bevel + 1);
564 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
565 break;
566 case 'I':
567 if (!i) break;
568 self->iconify_x = x;
569 XMapWindow(ob_display, self->iconify);
570 XMoveWindow(ob_display, self->iconify, x, ob_rr_theme->bevel + 1);
571 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
572 break;
573 case 'L':
574 if (!l) break;
575 self->label_x = x;
576 XMapWindow(ob_display, self->label);
577 XMoveWindow(ob_display, self->label, x, ob_rr_theme->bevel);
578 x += self->label_width + ob_rr_theme->bevel + 1;
579 break;
580 case 'M':
581 if (!m) break;
582 self->max_x = x;
583 XMapWindow(ob_display, self->max);
584 XMoveWindow(ob_display, self->max, x, ob_rr_theme->bevel + 1);
585 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
586 break;
587 case 'C':
588 if (!c) break;
589 self->close_x = x;
590 XMapWindow(ob_display, self->close);
591 XMoveWindow(ob_display, self->close, x, ob_rr_theme->bevel + 1);
592 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
593 break;
594 }
595 }
596 }
597
598 ObFrameContext frame_context_from_string(char *name)
599 {
600 if (!g_ascii_strcasecmp("root", name))
601 return OB_FRAME_CONTEXT_ROOT;
602 else if (!g_ascii_strcasecmp("client", name))
603 return OB_FRAME_CONTEXT_CLIENT;
604 else if (!g_ascii_strcasecmp("titlebar", name))
605 return OB_FRAME_CONTEXT_TITLEBAR;
606 else if (!g_ascii_strcasecmp("handle", name))
607 return OB_FRAME_CONTEXT_HANDLE;
608 else if (!g_ascii_strcasecmp("frame", name))
609 return OB_FRAME_CONTEXT_FRAME;
610 else if (!g_ascii_strcasecmp("tlcorner", name))
611 return OB_FRAME_CONTEXT_TLCORNER;
612 else if (!g_ascii_strcasecmp("trcorner", name))
613 return OB_FRAME_CONTEXT_TRCORNER;
614 else if (!g_ascii_strcasecmp("blcorner", name))
615 return OB_FRAME_CONTEXT_BLCORNER;
616 else if (!g_ascii_strcasecmp("brcorner", name))
617 return OB_FRAME_CONTEXT_BRCORNER;
618 else if (!g_ascii_strcasecmp("maximize", name))
619 return OB_FRAME_CONTEXT_MAXIMIZE;
620 else if (!g_ascii_strcasecmp("alldesktops", name))
621 return OB_FRAME_CONTEXT_ALLDESKTOPS;
622 else if (!g_ascii_strcasecmp("shade", name))
623 return OB_FRAME_CONTEXT_SHADE;
624 else if (!g_ascii_strcasecmp("iconify", name))
625 return OB_FRAME_CONTEXT_ICONIFY;
626 else if (!g_ascii_strcasecmp("icon", name))
627 return OB_FRAME_CONTEXT_ICON;
628 else if (!g_ascii_strcasecmp("close", name))
629 return OB_FRAME_CONTEXT_CLOSE;
630 return OB_FRAME_CONTEXT_NONE;
631 }
632
633 ObFrameContext frame_context(ObClient *client, Window win)
634 {
635 ObFrame *self;
636
637 if (win == RootWindow(ob_display, ob_screen)) return OB_FRAME_CONTEXT_ROOT;
638 if (client == NULL) return OB_FRAME_CONTEXT_NONE;
639 if (win == client->window) return OB_FRAME_CONTEXT_CLIENT;
640
641 self = client->frame;
642 if (win == self->window) return OB_FRAME_CONTEXT_FRAME;
643 if (win == self->plate) return OB_FRAME_CONTEXT_CLIENT;
644 if (win == self->title) return OB_FRAME_CONTEXT_TITLEBAR;
645 if (win == self->label) return OB_FRAME_CONTEXT_TITLEBAR;
646 if (win == self->handle) return OB_FRAME_CONTEXT_HANDLE;
647 if (win == self->lgrip) return OB_FRAME_CONTEXT_BLCORNER;
648 if (win == self->rgrip) return OB_FRAME_CONTEXT_BRCORNER;
649 if (win == self->tlresize) return OB_FRAME_CONTEXT_TLCORNER;
650 if (win == self->trresize) return OB_FRAME_CONTEXT_TRCORNER;
651 if (win == self->max) return OB_FRAME_CONTEXT_MAXIMIZE;
652 if (win == self->iconify) return OB_FRAME_CONTEXT_ICONIFY;
653 if (win == self->close) return OB_FRAME_CONTEXT_CLOSE;
654 if (win == self->icon) return OB_FRAME_CONTEXT_ICON;
655 if (win == self->desk) return OB_FRAME_CONTEXT_ALLDESKTOPS;
656 if (win == self->shade) return OB_FRAME_CONTEXT_SHADE;
657
658 return OB_FRAME_CONTEXT_NONE;
659 }
660
661 void frame_client_gravity(ObFrame *self, int *x, int *y)
662 {
663 /* horizontal */
664 switch (self->client->gravity) {
665 default:
666 case NorthWestGravity:
667 case SouthWestGravity:
668 case WestGravity:
669 break;
670
671 case NorthGravity:
672 case SouthGravity:
673 case CenterGravity:
674 *x -= (self->size.left + self->size.right) / 2;
675 break;
676
677 case NorthEastGravity:
678 case SouthEastGravity:
679 case EastGravity:
680 *x -= self->size.left + self->size.right;
681 break;
682
683 case ForgetGravity:
684 case StaticGravity:
685 *x -= self->size.left;
686 break;
687 }
688
689 /* vertical */
690 switch (self->client->gravity) {
691 default:
692 case NorthWestGravity:
693 case NorthEastGravity:
694 case NorthGravity:
695 break;
696
697 case CenterGravity:
698 case EastGravity:
699 case WestGravity:
700 *y -= (self->size.top + self->size.bottom) / 2;
701 break;
702
703 case SouthWestGravity:
704 case SouthEastGravity:
705 case SouthGravity:
706 *y -= self->size.top + self->size.bottom;
707 break;
708
709 case ForgetGravity:
710 case StaticGravity:
711 *y -= self->size.top;
712 break;
713 }
714 }
715
716 void frame_frame_gravity(ObFrame *self, int *x, int *y)
717 {
718 /* horizontal */
719 switch (self->client->gravity) {
720 default:
721 case NorthWestGravity:
722 case WestGravity:
723 case SouthWestGravity:
724 break;
725 case NorthGravity:
726 case CenterGravity:
727 case SouthGravity:
728 *x += (self->size.left + self->size.right) / 2;
729 break;
730 case NorthEastGravity:
731 case EastGravity:
732 case SouthEastGravity:
733 *x += self->size.left + self->size.right;
734 break;
735 case StaticGravity:
736 case ForgetGravity:
737 *x += self->size.left;
738 break;
739 }
740
741 /* vertical */
742 switch (self->client->gravity) {
743 default:
744 case NorthWestGravity:
745 case NorthGravity:
746 case NorthEastGravity:
747 break;
748 case WestGravity:
749 case CenterGravity:
750 case EastGravity:
751 *y += (self->size.top + self->size.bottom) / 2;
752 break;
753 case SouthWestGravity:
754 case SouthGravity:
755 case SouthEastGravity:
756 *y += self->size.top + self->size.bottom;
757 break;
758 case StaticGravity:
759 case ForgetGravity:
760 *y += self->size.top;
761 break;
762 }
763 }
This page took 0.075383 seconds and 4 git commands to generate.