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