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