]> Dogcows Code - chaz/openbox/blob - openbox/frame.c
d714b69772bdd6a2b22acb65378c767c5291760c
[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
460 /* re-map the window since the unmanaging process unmaps it */
461
462 /* XXX ... um no it doesnt it unmaps its parent, the window itself
463 retains its mapped state, no?! XXX
464 XMapWindow(ob_display, client->window); */
465 } else {
466 /* according to the ICCCM - if the client doesn't reparent itself,
467 then we will reparent the window to root for them */
468 XReparentWindow(ob_display, client->window, ob_root,
469 client->area.x,
470 client->area.y);
471 }
472
473 /* remove all the windows for the frame from the client_map */
474 g_hash_table_remove(client_map, &self->window);
475 g_hash_table_remove(client_map, &self->plate);
476 g_hash_table_remove(client_map, &self->title);
477 g_hash_table_remove(client_map, &self->label);
478 g_hash_table_remove(client_map, &self->max);
479 g_hash_table_remove(client_map, &self->close);
480 g_hash_table_remove(client_map, &self->desk);
481 g_hash_table_remove(client_map, &self->shade);
482 g_hash_table_remove(client_map, &self->icon);
483 g_hash_table_remove(client_map, &self->iconify);
484 g_hash_table_remove(client_map, &self->handle);
485 g_hash_table_remove(client_map, &self->lgrip);
486 g_hash_table_remove(client_map, &self->rgrip);
487
488 frame_free(self);
489 }
490
491 static void layout_title(Frame *self)
492 {
493 char *lc;
494 int x;
495 gboolean n, d, i, l, m, c, s;
496
497 n = d = i = l = m = c = s = FALSE;
498
499 /* figure out whats being shown, and the width of the label */
500 self->label_width = self->width - (theme_bevel + 1) * 2;
501 for (lc = theme_title_layout; *lc != '\0'; ++lc) {
502 switch (*lc) {
503 case 'N':
504 if (!(self->client->decorations & Decor_Icon)) break;
505 if (n) { *lc = ' '; break; } /* rm duplicates */
506 n = TRUE;
507 self->label_width -= theme_button_size + 2 + theme_bevel + 1;
508 break;
509 case 'D':
510 if (!(self->client->decorations & Decor_AllDesktops)) break;
511 if (d) { *lc = ' '; break; } /* rm duplicates */
512 d = TRUE;
513 self->label_width -= theme_button_size + theme_bevel + 1;
514 break;
515 case 'S':
516 if (!(self->client->decorations & Decor_Shade)) break;
517 if (s) { *lc = ' '; break; } /* rm duplicates */
518 s = TRUE;
519 self->label_width -= theme_button_size + theme_bevel + 1;
520 break;
521 case 'I':
522 if (!(self->client->decorations & Decor_Iconify)) break;
523 if (i) { *lc = ' '; break; } /* rm duplicates */
524 i = TRUE;
525 self->label_width -= theme_button_size + theme_bevel + 1;
526 break;
527 case 'L':
528 if (l) { *lc = ' '; break; } /* rm duplicates */
529 l = TRUE;
530 break;
531 case 'M':
532 if (!(self->client->decorations & Decor_Maximize)) break;
533 if (m) { *lc = ' '; break; } /* rm duplicates */
534 m = TRUE;
535 self->label_width -= theme_button_size + theme_bevel + 1;
536 break;
537 case 'C':
538 if (!(self->client->decorations & Decor_Close)) break;
539 if (c) { *lc = ' '; break; } /* rm duplicates */
540 c = TRUE;
541 self->label_width -= theme_button_size + theme_bevel + 1;
542 break;
543 }
544 }
545 if (self->label_width < 1) self->label_width = 1;
546
547 XResizeWindow(ob_display, self->label, self->label_width,
548 theme_label_height);
549
550 if (!n) XUnmapWindow(ob_display, self->icon);
551 if (!d) XUnmapWindow(ob_display, self->desk);
552 if (!s) XUnmapWindow(ob_display, self->shade);
553 if (!i) XUnmapWindow(ob_display, self->iconify);
554 if (!l) XUnmapWindow(ob_display, self->label);
555 if (!m) XUnmapWindow(ob_display, self->max);
556 if (!c) XUnmapWindow(ob_display, self->close);
557
558 x = theme_bevel + 1;
559 for (lc = theme_title_layout; *lc != '\0'; ++lc) {
560 switch (*lc) {
561 case 'N':
562 if (!n) break;
563 self->icon_x = x;
564 RECT_SET(self->a_icon->area, 0, 0,
565 theme_button_size + 2, theme_button_size + 2);
566 XMapWindow(ob_display, self->icon);
567 XMoveWindow(ob_display, self->icon, x, theme_bevel);
568 x += theme_button_size + 2 + theme_bevel + 1;
569 break;
570 case 'D':
571 if (!d) break;
572 self->desk_x = x;
573 XMapWindow(ob_display, self->desk);
574 XMoveWindow(ob_display, self->desk, x, theme_bevel + 1);
575 x += theme_button_size + theme_bevel + 1;
576 break;
577 case 'S':
578 if (!s) break;
579 self->shade_x = x;
580 XMapWindow(ob_display, self->shade);
581 XMoveWindow(ob_display, self->shade, x, theme_bevel + 1);
582 x += theme_button_size + theme_bevel + 1;
583 break;
584 case 'I':
585 if (!i) break;
586 self->iconify_x = x;
587 XMapWindow(ob_display, self->iconify);
588 XMoveWindow(ob_display, self->iconify, x, theme_bevel + 1);
589 x += theme_button_size + theme_bevel + 1;
590 break;
591 case 'L':
592 if (!l) break;
593 self->label_x = x;
594 XMapWindow(ob_display, self->label);
595 XMoveWindow(ob_display, self->label, x, theme_bevel);
596 x += self->label_width + theme_bevel + 1;
597 break;
598 case 'M':
599 if (!m) break;
600 self->max_x = x;
601 XMapWindow(ob_display, self->max);
602 XMoveWindow(ob_display, self->max, x, theme_bevel + 1);
603 x += theme_button_size + theme_bevel + 1;
604 break;
605 case 'C':
606 if (!c) break;
607 self->close_x = x;
608 XMapWindow(ob_display, self->close);
609 XMoveWindow(ob_display, self->close, x, theme_bevel + 1);
610 x += theme_button_size + theme_bevel + 1;
611 break;
612 }
613 }
614
615 RECT_SET(self->a_focused_label->area, 0, 0,
616 self->label_width, theme_label_height);
617 RECT_SET(self->a_unfocused_label->area, 0, 0,
618 self->label_width, theme_label_height);
619 }
620
621 Context frame_context_from_string(char *name)
622 {
623 if (!g_ascii_strcasecmp("root", name))
624 return Context_Root;
625 else if (!g_ascii_strcasecmp("client", name))
626 return Context_Client;
627 else if (!g_ascii_strcasecmp("titlebar", name))
628 return Context_Titlebar;
629 else if (!g_ascii_strcasecmp("handle", name))
630 return Context_Handle;
631 else if (!g_ascii_strcasecmp("frame", name))
632 return Context_Frame;
633 else if (!g_ascii_strcasecmp("blcorner", name))
634 return Context_BLCorner;
635 else if (!g_ascii_strcasecmp("tlcorner", name))
636 return Context_TLCorner;
637 else if (!g_ascii_strcasecmp("brcorner", name))
638 return Context_BRCorner;
639 else if (!g_ascii_strcasecmp("trcorner", name))
640 return Context_TRCorner;
641 else if (!g_ascii_strcasecmp("maximize", name))
642 return Context_Maximize;
643 else if (!g_ascii_strcasecmp("alldesktops", name))
644 return Context_AllDesktops;
645 else if (!g_ascii_strcasecmp("shade", name))
646 return Context_Shade;
647 else if (!g_ascii_strcasecmp("iconify", name))
648 return Context_Iconify;
649 else if (!g_ascii_strcasecmp("icon", name))
650 return Context_Icon;
651 else if (!g_ascii_strcasecmp("close", name))
652 return Context_Close;
653 return Context_None;
654 }
655
656 Context frame_context(Client *client, Window win)
657 {
658 Frame *self;
659
660 if (win == ob_root) return Context_Root;
661 if (client == NULL) return Context_None;
662 if (win == client->window) return Context_Client;
663
664 self = client->frame;
665 if (win == self->window) return Context_Frame;
666 if (win == self->plate) return Context_Client;
667 if (win == self->title) return Context_Titlebar;
668 if (win == self->label) return Context_Titlebar;
669 if (win == self->handle) return Context_Handle;
670 if (win == self->lgrip) return Context_BLCorner;
671 if (win == self->rgrip) return Context_BRCorner;
672 if (win == self->max) return Context_Maximize;
673 if (win == self->iconify)return Context_Iconify;
674 if (win == self->close) return Context_Close;
675 if (win == self->icon) return Context_Icon;
676 if (win == self->desk) return Context_AllDesktops;
677 if (win == self->shade) return Context_Shade;
678
679 return Context_None;
680 }
681
682 void frame_client_gravity(Frame *self, int *x, int *y)
683 {
684 /* horizontal */
685 switch (self->client->gravity) {
686 default:
687 case NorthWestGravity:
688 case SouthWestGravity:
689 case WestGravity:
690 break;
691
692 case NorthGravity:
693 case SouthGravity:
694 case CenterGravity:
695 *x -= (self->size.left + self->size.right) / 2;
696 break;
697
698 case NorthEastGravity:
699 case SouthEastGravity:
700 case EastGravity:
701 *x -= self->size.left + self->size.right;
702 break;
703
704 case ForgetGravity:
705 case StaticGravity:
706 *x -= self->size.left;
707 break;
708 }
709
710 /* vertical */
711 switch (self->client->gravity) {
712 default:
713 case NorthWestGravity:
714 case NorthEastGravity:
715 case NorthGravity:
716 break;
717
718 case CenterGravity:
719 case EastGravity:
720 case WestGravity:
721 *y -= (self->size.top + self->size.bottom) / 2;
722 break;
723
724 case SouthWestGravity:
725 case SouthEastGravity:
726 case SouthGravity:
727 *y -= self->size.top + self->size.bottom;
728 break;
729
730 case ForgetGravity:
731 case StaticGravity:
732 *y -= self->size.top;
733 break;
734 }
735 }
736
737 void frame_frame_gravity(Frame *self, int *x, int *y)
738 {
739 /* horizontal */
740 switch (self->client->gravity) {
741 default:
742 case NorthWestGravity:
743 case WestGravity:
744 case SouthWestGravity:
745 break;
746 case NorthGravity:
747 case CenterGravity:
748 case SouthGravity:
749 *x += (self->size.left + self->size.right) / 2;
750 break;
751 case NorthEastGravity:
752 case EastGravity:
753 case SouthEastGravity:
754 *x += self->size.left + self->size.right;
755 break;
756 case StaticGravity:
757 case ForgetGravity:
758 *x += self->size.left;
759 break;
760 }
761
762 /* vertical */
763 switch (self->client->gravity) {
764 default:
765 case NorthWestGravity:
766 case WestGravity:
767 case SouthWestGravity:
768 break;
769 case NorthGravity:
770 case CenterGravity:
771 case SouthGravity:
772 *y += (self->size.top + self->size.bottom) / 2;
773 break;
774 case NorthEastGravity:
775 case EastGravity:
776 case SouthEastGravity:
777 *y += self->size.top + self->size.bottom;
778 break;
779 case StaticGravity:
780 case ForgetGravity:
781 *y += self->size.top;
782 break;
783 }
784 }
This page took 0.067989 seconds and 3 git commands to generate.