3 #include "extensions.h"
4 #include "framerender.h"
5 #include "render/theme.h"
7 #define PLATE_EVENTMASK (SubstructureRedirectMask | ButtonPressMask)
8 #define FRAME_EVENTMASK (EnterWindowMask | LeaveWindowMask | \
9 ButtonPressMask | ButtonReleaseMask)
10 #define ELEMENT_EVENTMASK (ButtonPressMask | ButtonReleaseMask | \
11 ButtonMotionMask | ExposureMask)
13 static void layout_title(Frame
*self
);
23 static Window
createWindow(Window parent
, unsigned long mask
,
24 XSetWindowAttributes
*attrib
)
26 return XCreateWindow(ob_display
, parent
, 0, 0, 1, 1, 0,
27 RrDepth(ob_rr_inst
), InputOutput
,
28 RrVisual(ob_rr_inst
), mask
, attrib
);
34 XSetWindowAttributes attrib
;
38 self
= g_new(Frame
, 1);
40 self
->visible
= FALSE
;
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
);
49 self
->plate
= createWindow(self
->window
, mask
, &attrib
);
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
);
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
);
68 self
->focused
= FALSE
;
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
);
76 /* set colors/appearance/sizes for stuff that doesn't change */
77 XSetWindowBorder(ob_display
, self
->window
, ob_rr_theme
->b_color
->pixel
);
78 XSetWindowBorder(ob_display
, self
->label
, ob_rr_theme
->b_color
->pixel
);
79 XSetWindowBorder(ob_display
, self
->rgrip
, ob_rr_theme
->b_color
->pixel
);
80 XSetWindowBorder(ob_display
, self
->lgrip
, ob_rr_theme
->b_color
->pixel
);
82 XResizeWindow(ob_display
, self
->max
,
83 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
84 XResizeWindow(ob_display
, self
->iconify
,
85 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
86 XResizeWindow(ob_display
, self
->icon
,
87 ob_rr_theme
->button_size
+ 2, ob_rr_theme
->button_size
+ 2);
88 XResizeWindow(ob_display
, self
->close
,
89 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
90 XResizeWindow(ob_display
, self
->desk
,
91 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
92 XResizeWindow(ob_display
, self
->shade
,
93 ob_rr_theme
->button_size
, ob_rr_theme
->button_size
);
94 XResizeWindow(ob_display
, self
->lgrip
,
95 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
96 XResizeWindow(ob_display
, self
->rgrip
,
97 ob_rr_theme
->grip_width
, ob_rr_theme
->handle_height
);
99 /* set up the dynamic appearances */
100 self
->a_unfocused_title
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_title
);
101 self
->a_focused_title
= RrAppearanceCopy(ob_rr_theme
->a_focused_title
);
102 self
->a_unfocused_label
= RrAppearanceCopy(ob_rr_theme
->a_unfocused_label
);
103 self
->a_focused_label
= RrAppearanceCopy(ob_rr_theme
->a_focused_label
);
104 self
->a_unfocused_handle
=
105 RrAppearanceCopy(ob_rr_theme
->a_unfocused_handle
);
106 self
->a_focused_handle
= RrAppearanceCopy(ob_rr_theme
->a_focused_handle
);
107 self
->a_icon
= RrAppearanceCopy(ob_rr_theme
->a_icon
);
109 self
->max_press
= self
->close_press
= self
->desk_press
=
110 self
->iconify_press
= self
->shade_press
= FALSE
;
115 static void frame_free(Frame
*self
)
117 RrAppearanceFree(self
->a_unfocused_title
);
118 RrAppearanceFree(self
->a_focused_title
);
119 RrAppearanceFree(self
->a_unfocused_label
);
120 RrAppearanceFree(self
->a_focused_label
);
121 RrAppearanceFree(self
->a_unfocused_handle
);
122 RrAppearanceFree(self
->a_focused_handle
);
123 RrAppearanceFree(self
->a_icon
);
125 XDestroyWindow(ob_display
, self
->window
);
130 void frame_show(Frame
*self
)
132 if (!self
->visible
) {
133 self
->visible
= TRUE
;
134 XMapWindow(ob_display
, self
->window
);
138 void frame_hide(Frame
*self
)
141 self
->visible
= FALSE
;
142 self
->client
->ignore_unmaps
++;
143 XUnmapWindow(ob_display
, self
->window
);
147 void frame_adjust_shape(Frame
*self
)
153 if (!self
->client
->shaped
) {
154 /* clear the shape on the frame window */
155 XShapeCombineMask(ob_display
, self
->window
, ShapeBounding
,
156 self
->innersize
.left
,
160 /* make the frame's shape match the clients */
161 XShapeCombineShape(ob_display
, self
->window
, ShapeBounding
,
162 self
->innersize
.left
,
164 self
->client
->window
,
165 ShapeBounding
, ShapeSet
);
168 if (self
->client
->decorations
& Decor_Titlebar
) {
169 xrect
[0].x
= -ob_rr_theme
->bevel
;
170 xrect
[0].y
= -ob_rr_theme
->bevel
;
171 xrect
[0].width
= self
->width
+ self
->bwidth
* 2;
172 xrect
[0].height
= ob_rr_theme
->title_height
+
177 if (self
->client
->decorations
& Decor_Handle
) {
178 xrect
[1].x
= -ob_rr_theme
->bevel
;
179 xrect
[1].y
= FRAME_HANDLE_Y(self
);
180 xrect
[1].width
= self
->width
+ self
->bwidth
* 2;
181 xrect
[1].height
= ob_rr_theme
->handle_height
+
186 XShapeCombineRectangles(ob_display
, self
->window
,
187 ShapeBounding
, 0, 0, xrect
, num
,
188 ShapeUnion
, Unsorted
);
193 void frame_adjust_area(Frame
*self
, gboolean moved
, gboolean resized
)
196 if (self
->client
->decorations
& Decor_Border
) {
197 self
->bwidth
= ob_rr_theme
->bwidth
;
198 self
->cbwidth
= ob_rr_theme
->cbwidth
;
200 self
->bwidth
= self
->cbwidth
= 0;
202 STRUT_SET(self
->innersize
, self
->cbwidth
, self
->cbwidth
,
203 self
->cbwidth
, self
->cbwidth
);
204 self
->width
= self
->client
->area
.width
+ self
->cbwidth
* 2;
205 g_assert(self
->width
> 0);
207 /* set border widths */
208 XSetWindowBorderWidth(ob_display
, self
->plate
, self
->cbwidth
);
209 XSetWindowBorderWidth(ob_display
, self
->window
, self
->bwidth
);
210 XSetWindowBorderWidth(ob_display
, self
->title
, self
->bwidth
);
211 XSetWindowBorderWidth(ob_display
, self
->handle
, self
->bwidth
);
212 XSetWindowBorderWidth(ob_display
, self
->lgrip
, self
->bwidth
);
213 XSetWindowBorderWidth(ob_display
, self
->rgrip
, self
->bwidth
);
215 /* position/size and map/unmap all the windows */
217 /* they all default off, they're turned on in layout_title */
221 self
->iconify_x
= -1;
226 if (self
->client
->decorations
& Decor_Titlebar
) {
227 XMoveResizeWindow(ob_display
, self
->title
,
228 -self
->bwidth
, -self
->bwidth
,
229 self
->width
, ob_rr_theme
->title_height
);
230 self
->innersize
.top
+= ob_rr_theme
->title_height
+ self
->bwidth
;
231 XMapWindow(ob_display
, self
->title
);
233 /* layout the title bar elements */
236 XUnmapWindow(ob_display
, self
->title
);
238 if (self
->client
->decorations
& Decor_Handle
) {
239 XMoveResizeWindow(ob_display
, self
->handle
,
240 -self
->bwidth
, FRAME_HANDLE_Y(self
),
241 self
->width
, ob_rr_theme
->handle_height
);
242 XMoveWindow(ob_display
, self
->lgrip
,
243 -self
->bwidth
, -self
->bwidth
);
244 XMoveWindow(ob_display
, self
->rgrip
,
245 -self
->bwidth
+ self
->width
-
246 ob_rr_theme
->grip_width
, -self
->bwidth
);
247 self
->innersize
.bottom
+= ob_rr_theme
->handle_height
+
249 XMapWindow(ob_display
, self
->handle
);
251 /* XXX make a subwindow with these dimentions?
252 ob_rr_theme->grip_width + self->bwidth, 0,
253 self->width - (ob_rr_theme->grip_width + self->bwidth) * 2,
254 ob_rr_theme->handle_height);
257 XUnmapWindow(ob_display
, self
->handle
);
261 /* move and resize the plate */
262 XMoveResizeWindow(ob_display
, self
->plate
,
263 self
->innersize
.left
- self
->cbwidth
,
264 self
->innersize
.top
- self
->cbwidth
,
265 self
->client
->area
.width
,
266 self
->client
->area
.height
);
267 /* when the client has StaticGravity, it likes to move around. */
268 XMoveWindow(ob_display
, self
->client
->window
, 0, 0);
272 STRUT_SET(self
->size
,
273 self
->innersize
.left
+ self
->bwidth
,
274 self
->innersize
.top
+ self
->bwidth
,
275 self
->innersize
.right
+ self
->bwidth
,
276 self
->innersize
.bottom
+ self
->bwidth
);
279 /* shading can change without being moved or resized */
280 RECT_SET_SIZE(self
->area
,
281 self
->client
->area
.width
+
282 self
->size
.left
+ self
->size
.right
,
283 (self
->client
->shaded
? ob_rr_theme
->title_height
+ self
->bwidth
*2:
284 self
->client
->area
.height
+
285 self
->size
.top
+ self
->size
.bottom
));
288 /* find the new coordinates, done after setting the frame.size, for
289 frame_client_gravity. */
290 self
->area
.x
= self
->client
->area
.x
;
291 self
->area
.y
= self
->client
->area
.y
;
292 frame_client_gravity((Frame
*)self
,
293 &self
->area
.x
, &self
->area
.y
);
296 /* move and resize the top level frame.
297 shading can change without being moved or resized */
298 XMoveResizeWindow(ob_display
, self
->window
,
299 self
->area
.x
, self
->area
.y
,
301 self
->area
.height
- self
->bwidth
* 2);
304 framerender_frame(self
);
306 frame_adjust_shape(self
);
310 void frame_adjust_state(Frame
*self
)
312 framerender_frame(self
);
315 void frame_adjust_focus(Frame
*self
, gboolean hilite
)
317 self
->focused
= hilite
;
318 framerender_frame(self
);
321 void frame_adjust_title(Frame
*self
)
323 framerender_frame(self
);
326 void frame_adjust_icon(Frame
*self
)
328 framerender_frame(self
);
331 void frame_grab_client(Frame
*self
, Client
*client
)
333 self
->client
= client
;
335 /* reparent the client to the frame */
336 XReparentWindow(ob_display
, client
->window
, self
->plate
, 0, 0);
338 When reparenting the client window, it is usually not mapped yet, since
339 this occurs from a MapRequest. However, in the case where Openbox is
340 starting up, the window is already mapped, so we'll see unmap events for
341 it. There are 2 unmap events generated that we see, one with the 'event'
342 member set the root window, and one set to the client, but both get
343 handled and need to be ignored.
345 if (ob_state
== State_Starting
)
346 client
->ignore_unmaps
+= 2;
348 /* select the event mask on the client's parent (to receive config/map
349 req's) the ButtonPress is to catch clicks on the client border */
350 XSelectInput(ob_display
, self
->plate
, PLATE_EVENTMASK
);
352 /* map the client so it maps when the frame does */
353 XMapWindow(ob_display
, client
->window
);
355 frame_adjust_area(self
, TRUE
, TRUE
);
357 /* set all the windows for the frame in the window_map */
358 g_hash_table_insert(window_map
, &self
->window
, client
);
359 g_hash_table_insert(window_map
, &self
->plate
, client
);
360 g_hash_table_insert(window_map
, &self
->title
, client
);
361 g_hash_table_insert(window_map
, &self
->label
, client
);
362 g_hash_table_insert(window_map
, &self
->max
, client
);
363 g_hash_table_insert(window_map
, &self
->close
, client
);
364 g_hash_table_insert(window_map
, &self
->desk
, client
);
365 g_hash_table_insert(window_map
, &self
->shade
, client
);
366 g_hash_table_insert(window_map
, &self
->icon
, client
);
367 g_hash_table_insert(window_map
, &self
->iconify
, client
);
368 g_hash_table_insert(window_map
, &self
->handle
, client
);
369 g_hash_table_insert(window_map
, &self
->lgrip
, client
);
370 g_hash_table_insert(window_map
, &self
->rgrip
, client
);
373 void frame_release_client(Frame
*self
, Client
*client
)
377 g_assert(self
->client
== client
);
379 /* check if the app has already reparented its window away */
380 if (XCheckTypedWindowEvent(ob_display
, client
->window
,
381 ReparentNotify
, &ev
)) {
382 XPutBackEvent(ob_display
, &ev
);
384 /* re-map the window since the unmanaging process unmaps it */
386 /* XXX ... um no it doesnt it unmaps its parent, the window itself
387 retains its mapped state, no?! XXX
388 XMapWindow(ob_display, client->window); */
390 /* according to the ICCCM - if the client doesn't reparent itself,
391 then we will reparent the window to root for them */
392 XReparentWindow(ob_display
, client
->window
, ob_root
,
397 /* remove all the windows for the frame from the window_map */
398 g_hash_table_remove(window_map
, &self
->window
);
399 g_hash_table_remove(window_map
, &self
->plate
);
400 g_hash_table_remove(window_map
, &self
->title
);
401 g_hash_table_remove(window_map
, &self
->label
);
402 g_hash_table_remove(window_map
, &self
->max
);
403 g_hash_table_remove(window_map
, &self
->close
);
404 g_hash_table_remove(window_map
, &self
->desk
);
405 g_hash_table_remove(window_map
, &self
->shade
);
406 g_hash_table_remove(window_map
, &self
->icon
);
407 g_hash_table_remove(window_map
, &self
->iconify
);
408 g_hash_table_remove(window_map
, &self
->handle
);
409 g_hash_table_remove(window_map
, &self
->lgrip
);
410 g_hash_table_remove(window_map
, &self
->rgrip
);
415 static void layout_title(Frame
*self
)
419 gboolean n
, d
, i
, l
, m
, c
, s
;
421 n
= d
= i
= l
= m
= c
= s
= FALSE
;
423 /* figure out whats being shown, and the width of the label */
424 self
->label_width
= self
->width
- (ob_rr_theme
->bevel
+ 1) * 2;
425 for (lc
= ob_rr_theme
->title_layout
; *lc
!= '\0'; ++lc
) {
428 if (!(self
->client
->decorations
& Decor_Icon
)) break;
429 if (n
) { *lc
= ' '; break; } /* rm duplicates */
431 self
->label_width
-= (ob_rr_theme
->button_size
+ 2 +
432 ob_rr_theme
->bevel
+ 1);
435 if (!(self
->client
->decorations
& Decor_AllDesktops
)) break;
436 if (d
) { *lc
= ' '; break; } /* rm duplicates */
438 self
->label_width
-= (ob_rr_theme
->button_size
+
439 ob_rr_theme
->bevel
+ 1);
442 if (!(self
->client
->decorations
& Decor_Shade
)) break;
443 if (s
) { *lc
= ' '; break; } /* rm duplicates */
445 self
->label_width
-= (ob_rr_theme
->button_size
+
446 ob_rr_theme
->bevel
+ 1);
449 if (!(self
->client
->decorations
& Decor_Iconify
)) break;
450 if (i
) { *lc
= ' '; break; } /* rm duplicates */
452 self
->label_width
-= (ob_rr_theme
->button_size
+
453 ob_rr_theme
->bevel
+ 1);
456 if (l
) { *lc
= ' '; break; } /* rm duplicates */
460 if (!(self
->client
->decorations
& Decor_Maximize
)) break;
461 if (m
) { *lc
= ' '; break; } /* rm duplicates */
463 self
->label_width
-= (ob_rr_theme
->button_size
+
464 ob_rr_theme
->bevel
+ 1);
467 if (!(self
->client
->decorations
& Decor_Close
)) break;
468 if (c
) { *lc
= ' '; break; } /* rm duplicates */
470 self
->label_width
-= (ob_rr_theme
->button_size
+
471 ob_rr_theme
->bevel
+ 1);
475 if (self
->label_width
< 1) self
->label_width
= 1;
477 XResizeWindow(ob_display
, self
->label
, self
->label_width
,
478 ob_rr_theme
->label_height
);
480 if (!n
) XUnmapWindow(ob_display
, self
->icon
);
481 if (!d
) XUnmapWindow(ob_display
, self
->desk
);
482 if (!s
) XUnmapWindow(ob_display
, self
->shade
);
483 if (!i
) XUnmapWindow(ob_display
, self
->iconify
);
484 if (!l
) XUnmapWindow(ob_display
, self
->label
);
485 if (!m
) XUnmapWindow(ob_display
, self
->max
);
486 if (!c
) XUnmapWindow(ob_display
, self
->close
);
488 x
= ob_rr_theme
->bevel
+ 1;
489 for (lc
= ob_rr_theme
->title_layout
; *lc
!= '\0'; ++lc
) {
494 XMapWindow(ob_display
, self
->icon
);
495 XMoveWindow(ob_display
, self
->icon
, x
, ob_rr_theme
->bevel
);
496 x
+= ob_rr_theme
->button_size
+ 2 + ob_rr_theme
->bevel
+ 1;
501 XMapWindow(ob_display
, self
->desk
);
502 XMoveWindow(ob_display
, self
->desk
, x
, ob_rr_theme
->bevel
+ 1);
503 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
508 XMapWindow(ob_display
, self
->shade
);
509 XMoveWindow(ob_display
, self
->shade
, x
, ob_rr_theme
->bevel
+ 1);
510 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
515 XMapWindow(ob_display
, self
->iconify
);
516 XMoveWindow(ob_display
, self
->iconify
, x
, ob_rr_theme
->bevel
+ 1);
517 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
522 XMapWindow(ob_display
, self
->label
);
523 XMoveWindow(ob_display
, self
->label
, x
, ob_rr_theme
->bevel
);
524 x
+= self
->label_width
+ ob_rr_theme
->bevel
+ 1;
529 XMapWindow(ob_display
, self
->max
);
530 XMoveWindow(ob_display
, self
->max
, x
, ob_rr_theme
->bevel
+ 1);
531 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
536 XMapWindow(ob_display
, self
->close
);
537 XMoveWindow(ob_display
, self
->close
, x
, ob_rr_theme
->bevel
+ 1);
538 x
+= ob_rr_theme
->button_size
+ ob_rr_theme
->bevel
+ 1;
544 Context
frame_context_from_string(char *name
)
546 if (!g_ascii_strcasecmp("root", name
))
548 else if (!g_ascii_strcasecmp("client", name
))
549 return Context_Client
;
550 else if (!g_ascii_strcasecmp("titlebar", name
))
551 return Context_Titlebar
;
552 else if (!g_ascii_strcasecmp("handle", name
))
553 return Context_Handle
;
554 else if (!g_ascii_strcasecmp("frame", name
))
555 return Context_Frame
;
556 else if (!g_ascii_strcasecmp("blcorner", name
))
557 return Context_BLCorner
;
558 else if (!g_ascii_strcasecmp("tlcorner", name
))
559 return Context_TLCorner
;
560 else if (!g_ascii_strcasecmp("brcorner", name
))
561 return Context_BRCorner
;
562 else if (!g_ascii_strcasecmp("trcorner", name
))
563 return Context_TRCorner
;
564 else if (!g_ascii_strcasecmp("maximize", name
))
565 return Context_Maximize
;
566 else if (!g_ascii_strcasecmp("alldesktops", name
))
567 return Context_AllDesktops
;
568 else if (!g_ascii_strcasecmp("shade", name
))
569 return Context_Shade
;
570 else if (!g_ascii_strcasecmp("iconify", name
))
571 return Context_Iconify
;
572 else if (!g_ascii_strcasecmp("icon", name
))
574 else if (!g_ascii_strcasecmp("close", name
))
575 return Context_Close
;
579 Context
frame_context(Client
*client
, Window win
)
583 if (win
== ob_root
) return Context_Root
;
584 if (client
== NULL
) return Context_None
;
585 if (win
== client
->window
) return Context_Client
;
587 self
= client
->frame
;
588 if (win
== self
->window
) return Context_Frame
;
589 if (win
== self
->plate
) return Context_Client
;
590 if (win
== self
->title
) return Context_Titlebar
;
591 if (win
== self
->label
) return Context_Titlebar
;
592 if (win
== self
->handle
) return Context_Handle
;
593 if (win
== self
->lgrip
) return Context_BLCorner
;
594 if (win
== self
->rgrip
) return Context_BRCorner
;
595 if (win
== self
->max
) return Context_Maximize
;
596 if (win
== self
->iconify
)return Context_Iconify
;
597 if (win
== self
->close
) return Context_Close
;
598 if (win
== self
->icon
) return Context_Icon
;
599 if (win
== self
->desk
) return Context_AllDesktops
;
600 if (win
== self
->shade
) return Context_Shade
;
605 void frame_client_gravity(Frame
*self
, int *x
, int *y
)
608 switch (self
->client
->gravity
) {
610 case NorthWestGravity
:
611 case SouthWestGravity
:
618 *x
-= (self
->size
.left
+ self
->size
.right
) / 2;
621 case NorthEastGravity
:
622 case SouthEastGravity
:
624 *x
-= self
->size
.left
+ self
->size
.right
;
629 *x
-= self
->size
.left
;
634 switch (self
->client
->gravity
) {
636 case NorthWestGravity
:
637 case NorthEastGravity
:
644 *y
-= (self
->size
.top
+ self
->size
.bottom
) / 2;
647 case SouthWestGravity
:
648 case SouthEastGravity
:
650 *y
-= self
->size
.top
+ self
->size
.bottom
;
655 *y
-= self
->size
.top
;
660 void frame_frame_gravity(Frame
*self
, int *x
, int *y
)
663 switch (self
->client
->gravity
) {
665 case NorthWestGravity
:
667 case SouthWestGravity
:
672 *x
+= (self
->size
.left
+ self
->size
.right
) / 2;
674 case NorthEastGravity
:
676 case SouthEastGravity
:
677 *x
+= self
->size
.left
+ self
->size
.right
;
681 *x
+= self
->size
.left
;
686 switch (self
->client
->gravity
) {
688 case NorthWestGravity
:
690 case SouthWestGravity
:
695 *y
+= (self
->size
.top
+ self
->size
.bottom
) / 2;
697 case NorthEastGravity
:
699 case SouthEastGravity
:
700 *y
+= self
->size
.top
+ self
->size
.bottom
;
704 *y
+= self
->size
.top
;