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