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