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