]> Dogcows Code - chaz/openbox/blob - openbox/frame.c
0d5ddb2e6ac2592b96835750c69e8d83d4981bc2
[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) {
644 /* conceptually, this is the root window, as far as users are
645 concerned */
646 if (client->type == OB_CLIENT_TYPE_DESKTOP)
647 return OB_FRAME_CONTEXT_ROOT;
648 return OB_FRAME_CONTEXT_CLIENT;
649 }
650
651 self = client->frame;
652 if (win == self->plate) {
653 /* conceptually, this is the root window, as far as users are
654 concerned */
655 if (client->type == OB_CLIENT_TYPE_DESKTOP)
656 return OB_FRAME_CONTEXT_ROOT;
657 return OB_FRAME_CONTEXT_CLIENT;
658 }
659
660 if (win == self->window) return OB_FRAME_CONTEXT_FRAME;
661 if (win == self->title) return OB_FRAME_CONTEXT_TITLEBAR;
662 if (win == self->label) return OB_FRAME_CONTEXT_TITLEBAR;
663 if (win == self->handle) return OB_FRAME_CONTEXT_HANDLE;
664 if (win == self->lgrip) return OB_FRAME_CONTEXT_BLCORNER;
665 if (win == self->rgrip) return OB_FRAME_CONTEXT_BRCORNER;
666 if (win == self->tlresize) return OB_FRAME_CONTEXT_TLCORNER;
667 if (win == self->trresize) return OB_FRAME_CONTEXT_TRCORNER;
668 if (win == self->max) return OB_FRAME_CONTEXT_MAXIMIZE;
669 if (win == self->iconify) return OB_FRAME_CONTEXT_ICONIFY;
670 if (win == self->close) return OB_FRAME_CONTEXT_CLOSE;
671 if (win == self->icon) return OB_FRAME_CONTEXT_ICON;
672 if (win == self->desk) return OB_FRAME_CONTEXT_ALLDESKTOPS;
673 if (win == self->shade) return OB_FRAME_CONTEXT_SHADE;
674
675 return OB_FRAME_CONTEXT_NONE;
676 }
677
678 void frame_client_gravity(ObFrame *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(ObFrame *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 NorthGravity:
763 case NorthEastGravity:
764 break;
765 case WestGravity:
766 case CenterGravity:
767 case EastGravity:
768 *y += (self->size.top + self->size.bottom) / 2;
769 break;
770 case SouthWestGravity:
771 case SouthGravity:
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.068345 seconds and 3 git commands to generate.