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