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