]> Dogcows Code - chaz/openbox/blob - openbox/frame.c
use strcmp instead of collate, since collate is slower and we're only doing an =...
[chaz/openbox] / openbox / frame.c
1 #include "frame.h"
2 #include "openbox.h"
3 #include "extensions.h"
4 #include "framerender.h"
5 #include "render/theme.h"
6
7 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
8 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
9 ButtonPressMask | ButtonReleaseMask)
10 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
11 ButtonMotionMask | ExposureMask)
12
13 static void layout_title(Frame *self);
14
15 void frame_startup()
16 {
17 }
18
19 void frame_shutdown()
20 {
21 }
22
23 static Window createWindow(Window parent, unsigned long mask,
24 XSetWindowAttributes *attrib)
25 {
26 return XCreateWindow(ob_display, parent, 0, 0, 1, 1, 0,
27 RrDepth(ob_rr_inst), InputOutput,
28 RrVisual(ob_rr_inst), mask, attrib);
29
30 }
31
32 Frame *frame_new()
33 {
34 XSetWindowAttributes attrib;
35 unsigned long mask;
36 Frame *self;
37
38 self = g_new(Frame, 1);
39
40 self->visible = FALSE;
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(ob_root, mask, &attrib);
48
49 mask = 0;
50 self->plate = createWindow(self->window, mask, &attrib);
51
52 mask = CWEventMask;
53 attrib.event_mask = ELEMENT_EVENTMASK;
54 self->title = createWindow(self->window, mask, &attrib);
55 self->label = createWindow(self->title, mask, &attrib);
56 self->max = createWindow(self->title, mask, &attrib);
57 self->close = createWindow(self->title, mask, &attrib);
58 self->desk = createWindow(self->title, mask, &attrib);
59 self->shade = createWindow(self->title, mask, &attrib);
60 self->icon = createWindow(self->title, mask, &attrib);
61 self->iconify = createWindow(self->title, mask, &attrib);
62 self->handle = createWindow(self->window, mask, &attrib);
63 mask |= CWCursor;
64 attrib.cursor = ob_cursors.bl;
65 self->lgrip = createWindow(self->handle, mask, &attrib);
66 attrib.cursor = ob_cursors.br;
67 self->rgrip = createWindow(self->handle, mask, &attrib);
68
69 self->focused = FALSE;
70
71 /* the other stuff is shown based on decor settings */
72 XMapWindow(ob_display, self->plate);
73 XMapWindow(ob_display, self->lgrip);
74 XMapWindow(ob_display, self->rgrip);
75 XMapWindow(ob_display, self->label);
76
77 /* set colors/appearance/sizes for stuff that doesn't change */
78 XSetWindowBorder(ob_display, self->window, ob_rr_theme->b_color->pixel);
79 XSetWindowBorder(ob_display, self->label, ob_rr_theme->b_color->pixel);
80 XSetWindowBorder(ob_display, self->rgrip, ob_rr_theme->b_color->pixel);
81 XSetWindowBorder(ob_display, self->lgrip, ob_rr_theme->b_color->pixel);
82
83 XResizeWindow(ob_display, self->max,
84 ob_rr_theme->button_size, ob_rr_theme->button_size);
85 XResizeWindow(ob_display, self->iconify,
86 ob_rr_theme->button_size, ob_rr_theme->button_size);
87 XResizeWindow(ob_display, self->icon,
88 ob_rr_theme->button_size + 2, ob_rr_theme->button_size + 2);
89 XResizeWindow(ob_display, self->close,
90 ob_rr_theme->button_size, ob_rr_theme->button_size);
91 XResizeWindow(ob_display, self->desk,
92 ob_rr_theme->button_size, ob_rr_theme->button_size);
93 XResizeWindow(ob_display, self->shade,
94 ob_rr_theme->button_size, ob_rr_theme->button_size);
95 XResizeWindow(ob_display, self->lgrip,
96 ob_rr_theme->grip_width, ob_rr_theme->handle_height);
97 XResizeWindow(ob_display, self->rgrip,
98 ob_rr_theme->grip_width, ob_rr_theme->handle_height);
99
100 /* set up the dynamic appearances */
101 self->a_unfocused_title = RrAppearanceCopy(ob_rr_theme->a_unfocused_title);
102 self->a_focused_title = RrAppearanceCopy(ob_rr_theme->a_focused_title);
103 self->a_unfocused_label = RrAppearanceCopy(ob_rr_theme->a_unfocused_label);
104 self->a_focused_label = RrAppearanceCopy(ob_rr_theme->a_focused_label);
105 self->a_unfocused_handle =
106 RrAppearanceCopy(ob_rr_theme->a_unfocused_handle);
107 self->a_focused_handle = RrAppearanceCopy(ob_rr_theme->a_focused_handle);
108 self->a_icon = RrAppearanceCopy(ob_rr_theme->a_icon);
109
110 self->max_press = self->close_press = self->desk_press =
111 self->iconify_press = self->shade_press = FALSE;
112
113 return (Frame*)self;
114 }
115
116 static void frame_free(Frame *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(Frame *self)
132 {
133 if (!self->visible) {
134 self->visible = TRUE;
135 XMapWindow(ob_display, self->window);
136 }
137 }
138
139 void frame_hide(Frame *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(Frame *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 & 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 & 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(Frame *self, gboolean moved, gboolean resized)
195 {
196 if (resized) {
197 self->decorations = self->client->decorations;
198 if (self->decorations & 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 & 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 & Decor_Handle) {
241 XMoveResizeWindow(ob_display, self->handle,
242 -self->bwidth, FRAME_HANDLE_Y(self),
243 self->width, ob_rr_theme->handle_height);
244 XMoveWindow(ob_display, self->lgrip,
245 -self->bwidth, -self->bwidth);
246 XMoveWindow(ob_display, self->rgrip,
247 -self->bwidth + self->width -
248 ob_rr_theme->grip_width, -self->bwidth);
249 self->innersize.bottom += ob_rr_theme->handle_height +
250 self->bwidth;
251 XMapWindow(ob_display, self->handle);
252
253 /* XXX make a subwindow with these dimentions?
254 ob_rr_theme->grip_width + self->bwidth, 0,
255 self->width - (ob_rr_theme->grip_width + self->bwidth) * 2,
256 ob_rr_theme->handle_height);
257 */
258 } else
259 XUnmapWindow(ob_display, self->handle);
260 }
261
262 if (resized) {
263 /* move and resize the plate */
264 XMoveResizeWindow(ob_display, self->plate,
265 self->innersize.left - self->cbwidth,
266 self->innersize.top - self->cbwidth,
267 self->client->area.width,
268 self->client->area.height);
269 /* when the client has StaticGravity, it likes to move around. */
270 XMoveWindow(ob_display, self->client->window, 0, 0);
271 }
272
273 if (resized) {
274 STRUT_SET(self->size,
275 self->innersize.left + self->bwidth,
276 self->innersize.top + self->bwidth,
277 self->innersize.right + self->bwidth,
278 self->innersize.bottom + self->bwidth);
279 }
280
281 /* shading can change without being moved or resized */
282 RECT_SET_SIZE(self->area,
283 self->client->area.width +
284 self->size.left + self->size.right,
285 (self->client->shaded ? ob_rr_theme->title_height + self->bwidth*2:
286 self->client->area.height +
287 self->size.top + self->size.bottom));
288
289 if (moved) {
290 /* find the new coordinates, done after setting the frame.size, for
291 frame_client_gravity. */
292 self->area.x = self->client->area.x;
293 self->area.y = self->client->area.y;
294 frame_client_gravity((Frame*)self,
295 &self->area.x, &self->area.y);
296 }
297
298 /* move and resize the top level frame.
299 shading can change without being moved or resized */
300 XMoveResizeWindow(ob_display, self->window,
301 self->area.x, self->area.y,
302 self->width,
303 self->area.height - self->bwidth * 2);
304
305 if (resized) {
306 framerender_frame(self);
307
308 frame_adjust_shape(self);
309 }
310 }
311
312 void frame_adjust_state(Frame *self)
313 {
314 framerender_frame(self);
315 }
316
317 void frame_adjust_focus(Frame *self, gboolean hilite)
318 {
319 self->focused = hilite;
320 framerender_frame(self);
321 }
322
323 void frame_adjust_title(Frame *self)
324 {
325 framerender_frame(self);
326 }
327
328 void frame_adjust_icon(Frame *self)
329 {
330 framerender_frame(self);
331 }
332
333 void frame_grab_client(Frame *self, Client *client)
334 {
335 self->client = client;
336
337 /* reparent the client to the frame */
338 XReparentWindow(ob_display, client->window, self->plate, 0, 0);
339 /*
340 When reparenting the client window, it is usually not mapped yet, since
341 this occurs from a MapRequest. However, in the case where Openbox is
342 starting up, the window is already mapped, so we'll see unmap events for
343 it. There are 2 unmap events generated that we see, one with the 'event'
344 member set the root window, and one set to the client, but both get
345 handled and need to be ignored.
346 */
347 if (ob_state == State_Starting)
348 client->ignore_unmaps += 2;
349
350 /* select the event mask on the client's parent (to receive config/map
351 req's) the ButtonPress is to catch clicks on the client border */
352 XSelectInput(ob_display, self->plate, PLATE_EVENTMASK);
353
354 /* map the client so it maps when the frame does */
355 XMapWindow(ob_display, client->window);
356
357 frame_adjust_area(self, TRUE, TRUE);
358
359 /* set all the windows for the frame in the window_map */
360 g_hash_table_insert(window_map, &self->window, client);
361 g_hash_table_insert(window_map, &self->plate, client);
362 g_hash_table_insert(window_map, &self->title, client);
363 g_hash_table_insert(window_map, &self->label, client);
364 g_hash_table_insert(window_map, &self->max, client);
365 g_hash_table_insert(window_map, &self->close, client);
366 g_hash_table_insert(window_map, &self->desk, client);
367 g_hash_table_insert(window_map, &self->shade, client);
368 g_hash_table_insert(window_map, &self->icon, client);
369 g_hash_table_insert(window_map, &self->iconify, client);
370 g_hash_table_insert(window_map, &self->handle, client);
371 g_hash_table_insert(window_map, &self->lgrip, client);
372 g_hash_table_insert(window_map, &self->rgrip, client);
373 }
374
375 void frame_release_client(Frame *self, Client *client)
376 {
377 XEvent ev;
378
379 g_assert(self->client == client);
380
381 /* check if the app has already reparented its window away */
382 if (XCheckTypedWindowEvent(ob_display, client->window,
383 ReparentNotify, &ev)) {
384 XPutBackEvent(ob_display, &ev);
385
386 /* re-map the window since the unmanaging process unmaps it */
387
388 /* XXX ... um no it doesnt it unmaps its parent, the window itself
389 retains its mapped state, no?! XXX
390 XMapWindow(ob_display, client->window); */
391 } else {
392 /* according to the ICCCM - if the client doesn't reparent itself,
393 then we will reparent the window to root for them */
394 XReparentWindow(ob_display, client->window, ob_root,
395 client->area.x,
396 client->area.y);
397 }
398
399 /* remove all the windows for the frame from the window_map */
400 g_hash_table_remove(window_map, &self->window);
401 g_hash_table_remove(window_map, &self->plate);
402 g_hash_table_remove(window_map, &self->title);
403 g_hash_table_remove(window_map, &self->label);
404 g_hash_table_remove(window_map, &self->max);
405 g_hash_table_remove(window_map, &self->close);
406 g_hash_table_remove(window_map, &self->desk);
407 g_hash_table_remove(window_map, &self->shade);
408 g_hash_table_remove(window_map, &self->icon);
409 g_hash_table_remove(window_map, &self->iconify);
410 g_hash_table_remove(window_map, &self->handle);
411 g_hash_table_remove(window_map, &self->lgrip);
412 g_hash_table_remove(window_map, &self->rgrip);
413
414 frame_free(self);
415 }
416
417 static void layout_title(Frame *self)
418 {
419 char *lc;
420 int x;
421 gboolean n, d, i, l, m, c, s;
422
423 n = d = i = l = m = c = s = FALSE;
424
425 /* figure out whats being shown, and the width of the label */
426 self->label_width = self->width - (ob_rr_theme->bevel + 1) * 2;
427 for (lc = ob_rr_theme->title_layout; *lc != '\0'; ++lc) {
428 switch (*lc) {
429 case 'N':
430 if (!(self->decorations & Decor_Icon)) break;
431 if (n) { *lc = ' '; break; } /* rm duplicates */
432 n = TRUE;
433 self->label_width -= (ob_rr_theme->button_size + 2 +
434 ob_rr_theme->bevel + 1);
435 break;
436 case 'D':
437 if (!(self->decorations & Decor_AllDesktops)) break;
438 if (d) { *lc = ' '; break; } /* rm duplicates */
439 d = TRUE;
440 self->label_width -= (ob_rr_theme->button_size +
441 ob_rr_theme->bevel + 1);
442 break;
443 case 'S':
444 if (!(self->decorations & Decor_Shade)) break;
445 if (s) { *lc = ' '; break; } /* rm duplicates */
446 s = TRUE;
447 self->label_width -= (ob_rr_theme->button_size +
448 ob_rr_theme->bevel + 1);
449 break;
450 case 'I':
451 if (!(self->decorations & Decor_Iconify)) break;
452 if (i) { *lc = ' '; break; } /* rm duplicates */
453 i = TRUE;
454 self->label_width -= (ob_rr_theme->button_size +
455 ob_rr_theme->bevel + 1);
456 break;
457 case 'L':
458 if (l) { *lc = ' '; break; } /* rm duplicates */
459 l = TRUE;
460 break;
461 case 'M':
462 if (!(self->decorations & Decor_Maximize)) break;
463 if (m) { *lc = ' '; break; } /* rm duplicates */
464 m = TRUE;
465 self->label_width -= (ob_rr_theme->button_size +
466 ob_rr_theme->bevel + 1);
467 break;
468 case 'C':
469 if (!(self->decorations & Decor_Close)) break;
470 if (c) { *lc = ' '; break; } /* rm duplicates */
471 c = TRUE;
472 self->label_width -= (ob_rr_theme->button_size +
473 ob_rr_theme->bevel + 1);
474 break;
475 }
476 }
477 if (self->label_width < 1) self->label_width = 1;
478
479 XResizeWindow(ob_display, self->label, self->label_width,
480 ob_rr_theme->label_height);
481
482 if (!n) XUnmapWindow(ob_display, self->icon);
483 if (!d) XUnmapWindow(ob_display, self->desk);
484 if (!s) XUnmapWindow(ob_display, self->shade);
485 if (!i) XUnmapWindow(ob_display, self->iconify);
486 if (!l) XUnmapWindow(ob_display, self->label);
487 if (!m) XUnmapWindow(ob_display, self->max);
488 if (!c) XUnmapWindow(ob_display, self->close);
489
490 x = ob_rr_theme->bevel + 1;
491 for (lc = ob_rr_theme->title_layout; *lc != '\0'; ++lc) {
492 switch (*lc) {
493 case 'N':
494 if (!n) break;
495 self->icon_x = x;
496 XMapWindow(ob_display, self->icon);
497 XMoveWindow(ob_display, self->icon, x, ob_rr_theme->bevel);
498 x += ob_rr_theme->button_size + 2 + ob_rr_theme->bevel + 1;
499 break;
500 case 'D':
501 if (!d) break;
502 self->desk_x = x;
503 XMapWindow(ob_display, self->desk);
504 XMoveWindow(ob_display, self->desk, x, ob_rr_theme->bevel + 1);
505 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
506 break;
507 case 'S':
508 if (!s) break;
509 self->shade_x = x;
510 XMapWindow(ob_display, self->shade);
511 XMoveWindow(ob_display, self->shade, x, ob_rr_theme->bevel + 1);
512 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
513 break;
514 case 'I':
515 if (!i) break;
516 self->iconify_x = x;
517 XMapWindow(ob_display, self->iconify);
518 XMoveWindow(ob_display, self->iconify, x, ob_rr_theme->bevel + 1);
519 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
520 break;
521 case 'L':
522 if (!l) break;
523 self->label_x = x;
524 XMapWindow(ob_display, self->label);
525 XMoveWindow(ob_display, self->label, x, ob_rr_theme->bevel);
526 x += self->label_width + ob_rr_theme->bevel + 1;
527 break;
528 case 'M':
529 if (!m) break;
530 self->max_x = x;
531 XMapWindow(ob_display, self->max);
532 XMoveWindow(ob_display, self->max, x, ob_rr_theme->bevel + 1);
533 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
534 break;
535 case 'C':
536 if (!c) break;
537 self->close_x = x;
538 XMapWindow(ob_display, self->close);
539 XMoveWindow(ob_display, self->close, x, ob_rr_theme->bevel + 1);
540 x += ob_rr_theme->button_size + ob_rr_theme->bevel + 1;
541 break;
542 }
543 }
544 }
545
546 Context frame_context_from_string(char *name)
547 {
548 if (!g_ascii_strcasecmp("root", name))
549 return Context_Root;
550 else if (!g_ascii_strcasecmp("client", name))
551 return Context_Client;
552 else if (!g_ascii_strcasecmp("titlebar", name))
553 return Context_Titlebar;
554 else if (!g_ascii_strcasecmp("handle", name))
555 return Context_Handle;
556 else if (!g_ascii_strcasecmp("frame", name))
557 return Context_Frame;
558 else if (!g_ascii_strcasecmp("blcorner", name))
559 return Context_BLCorner;
560 else if (!g_ascii_strcasecmp("tlcorner", name))
561 return Context_TLCorner;
562 else if (!g_ascii_strcasecmp("brcorner", name))
563 return Context_BRCorner;
564 else if (!g_ascii_strcasecmp("trcorner", name))
565 return Context_TRCorner;
566 else if (!g_ascii_strcasecmp("maximize", name))
567 return Context_Maximize;
568 else if (!g_ascii_strcasecmp("alldesktops", name))
569 return Context_AllDesktops;
570 else if (!g_ascii_strcasecmp("shade", name))
571 return Context_Shade;
572 else if (!g_ascii_strcasecmp("iconify", name))
573 return Context_Iconify;
574 else if (!g_ascii_strcasecmp("icon", name))
575 return Context_Icon;
576 else if (!g_ascii_strcasecmp("close", name))
577 return Context_Close;
578 return Context_None;
579 }
580
581 Context frame_context(Client *client, Window win)
582 {
583 Frame *self;
584
585 if (win == ob_root) return Context_Root;
586 if (client == NULL) return Context_None;
587 if (win == client->window) return Context_Client;
588
589 self = client->frame;
590 if (win == self->window) return Context_Frame;
591 if (win == self->plate) return Context_Client;
592 if (win == self->title) return Context_Titlebar;
593 if (win == self->label) return Context_Titlebar;
594 if (win == self->handle) return Context_Handle;
595 if (win == self->lgrip) return Context_BLCorner;
596 if (win == self->rgrip) return Context_BRCorner;
597 if (win == self->max) return Context_Maximize;
598 if (win == self->iconify)return Context_Iconify;
599 if (win == self->close) return Context_Close;
600 if (win == self->icon) return Context_Icon;
601 if (win == self->desk) return Context_AllDesktops;
602 if (win == self->shade) return Context_Shade;
603
604 return Context_None;
605 }
606
607 void frame_client_gravity(Frame *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(Frame *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.070156 seconds and 4 git commands to generate.