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