4 * Copyright (c) Tuomo Valkonen 1999-2009.
6 * See the included file LICENSE for details.
12 #include <libtu/objp.h>
13 #include <libtu/minmax.h>
14 #include <libextl/extl.h>
15 #include <libmainloop/defer.h>
30 #define XOR_RESIZE (!ioncore_g.opaque_resize)
33 extern int ioncore_edge_resistance
;
36 /*{{{ Size/position display and rubberband */
39 static void draw_rubberbox(WRootWin
*rw
, const WRectangle
*rect
)
45 fpts
[1].x
=rect
->x
+rect
->w
;
47 fpts
[2].x
=rect
->x
+rect
->w
;
48 fpts
[2].y
=rect
->y
+rect
->h
;
50 fpts
[3].y
=rect
->y
+rect
->h
;
54 XDrawLines(ioncore_g
.dpy
, WROOTWIN_ROOT(rw
), rw
->xor_gc
, fpts
, 5,
59 static int max_width(GrBrush
*brush
, const char *str
)
63 while(str
&& *str
!='\0'){
64 w
=grbrush_get_text_width(brush
, str
, 1);
74 static int chars_for_num(int d
)
87 static WInfoWin
*setup_moveres_display(WWindow
*parent
, int cx
, int cy
)
94 fp
.mode
=REGION_FIT_EXACT
;
100 infowin
=create_infowin(parent
, &fp
, "moveres_display");
105 grbrush_get_border_widths(INFOWIN_BRUSH(infowin
), &bdw
);
106 grbrush_get_font_extents(INFOWIN_BRUSH(infowin
), &fnte
);
108 /* Create move/resize position/size display window */
110 fp
.g
.w
+=chars_for_num(REGION_GEOM(parent
).w
);
111 fp
.g
.w
+=chars_for_num(REGION_GEOM(parent
).h
);
112 fp
.g
.w
*=max_width(INFOWIN_BRUSH(infowin
), "0123456789x+");
113 fp
.g
.w
+=bdw
.left
+bdw
.right
;
114 fp
.g
.h
=fnte
.max_height
+bdw
.top
+bdw
.bottom
;;
119 region_fitrep((WRegion
*)infowin
, NULL
, &fp
);
120 region_map((WRegion
*)infowin
);
126 static void moveres_draw_infowin(WMoveresMode
*mode
)
130 if(mode
->infowin
==NULL
)
133 buf
=INFOWIN_BUFFER(mode
->infowin
);
138 if(mode
->mode
==MOVERES_SIZE
){
144 if(mode
->hints
.base_set
){
145 w
=MAXOF(0, w
-mode
->hints
.base_width
);
146 h
=MAXOF(0, h
-mode
->hints
.base_height
);
149 if(mode
->hints
.inc_set
){
150 w
/=MAXOF(1, mode
->hints
.width_inc
);
151 h
/=MAXOF(1, mode
->hints
.height_inc
);
154 snprintf(buf
, INFOWIN_BUFFER_LEN
, "%dx%d", w
, h
);
156 snprintf(buf
, INFOWIN_BUFFER_LEN
, "%+d %+d",
157 mode
->geom
.x
, mode
->geom
.y
);
160 window_draw((WWindow
*)mode
->infowin
, TRUE
);
164 static void moveres_draw_rubberband(WMoveresMode
*mode
)
166 WRectangle rgeom
=mode
->geom
;
167 WRootWin
*rootwin
=(mode
->reg
==NULL
169 : region_rootwin_of(mode
->reg
));
174 rgeom
.x
+=mode
->parent_rx
;
175 rgeom
.y
+=mode
->parent_ry
;
177 if(mode
->rubfn
==NULL
)
178 draw_rubberbox(rootwin
, &rgeom
);
180 mode
->rubfn(rootwin
, &rgeom
);
187 /*{{{ Move/resize mode */
190 WMoveresMode
*tmpmode
=NULL
;
194 IMPLCLASS(WMoveresMode
, Obj
, NULL
, NULL
);
197 WMoveresMode
*moveres_mode(WRegion
*reg
)
201 return ((reg
==NULL
|| tmpmode
->reg
==reg
) ? tmpmode
: NULL
);
205 WRegion
*moveresmode_target(WMoveresMode
*mode
)
211 static bool moveresmode_init(WMoveresMode
*mode
, WRegion
*reg
,
212 WDrawRubberbandFn
*rubfn
, bool cumulative
)
220 parent
=REGION_PARENT(reg
);
227 mode
->snap_enabled
=FALSE
;
228 region_size_hints(reg
, &mode
->hints
);
230 region_rootpos((WRegion
*)parent
, &mode
->parent_rx
, &mode
->parent_ry
);
232 mode
->geom
=REGION_GEOM(reg
);
233 mode
->origgeom
=REGION_GEOM(reg
);
239 mode
->resize_cumulative
=cumulative
;
240 mode
->rqflags
=(XOR_RESIZE
? REGION_RQGEOM_TRYONLY
: 0);
242 mode
->mode
=MOVERES_SIZE
;
244 /* Get snapping geometry */
245 mgr
=REGION_MANAGER(reg
);
248 mode
->snapgeom
=REGION_GEOM(mgr
);
250 if(mgr
==(WRegion
*)parent
){
253 /*mode->snap_enabled=FALSE;*/
255 mode
->snap_enabled
=TRUE
;
258 if(!mode
->hints
.min_set
|| mode
->hints
.min_width
<1)
259 mode
->hints
.min_width
=1;
260 if(!mode
->hints
.min_set
|| mode
->hints
.min_height
<1)
261 mode
->hints
.min_height
=1;
263 /* Set up info window */
265 int x
=mode
->geom
.x
+mode
->geom
.w
/2;
266 int y
=mode
->geom
.y
+mode
->geom
.h
/2;
267 mode
->infowin
=setup_moveres_display(parent
, x
, y
);
270 moveres_draw_infowin(mode
);
273 XGrabServer(ioncore_g
.dpy
);
274 moveres_draw_rubberband(mode
);
281 static WMoveresMode
*create_moveresmode(WRegion
*reg
,
282 WDrawRubberbandFn
*rubfn
,
285 CREATEOBJ_IMPL(WMoveresMode
, moveresmode
, (p
, reg
, rubfn
, cumulative
));
289 WMoveresMode
*region_begin_resize(WRegion
*reg
, WDrawRubberbandFn
*rubfn
,
292 WMoveresMode
*mode
=create_moveresmode(reg
, rubfn
, cumulative
);
295 mode
->mode
=MOVERES_SIZE
;
296 ioncore_change_grab_cursor(IONCORE_CURSOR_RESIZE
);
303 WMoveresMode
*region_begin_move(WRegion
*reg
, WDrawRubberbandFn
*rubfn
,
306 WMoveresMode
*mode
=create_moveresmode(reg
, rubfn
, cumulative
);
309 mode
->mode
=MOVERES_POS
;
310 ioncore_change_grab_cursor(IONCORE_CURSOR_MOVE
);
317 static void moveresmode_setorig(WMoveresMode
*mode
)
323 mode
->origgeom
=mode
->geom
;
327 static void moveresmode_do_newgeom(WMoveresMode
*mode
, WRQGeomParams
*rq
)
330 moveres_draw_rubberband(mode
);
333 rq
->flags
|=mode
->rqflags
;
334 region_rqgeom(mode
->reg
, rq
, &mode
->geom
);
337 moveres_draw_infowin(mode
);
340 moveres_draw_rubberband(mode
);
344 static int clamp_up(int t
, int low
, int high
)
346 return (t
< high
&& t
> low
? high
: t
);
350 static void moveresmode_delta(WMoveresMode
*mode
,
351 int dx1
, int dx2
, int dy1
, int dy2
,
354 int realdx1
, realdx2
, realdy1
, realdy2
;
355 WRQGeomParams rq
=RQGEOMPARAMS_INIT
;
356 int er
=ioncore_edge_resistance
;
359 realdx1
=(mode
->dx1
+=dx1
);
360 realdx2
=(mode
->dx2
+=dx2
);
361 realdy1
=(mode
->dy1
+=dy1
);
362 realdy2
=(mode
->dy2
+=dy2
);
363 rq
.geom
=mode
->origgeom
;
366 if(mode
->snap_enabled
){
367 WRectangle
*sg
=&mode
->snapgeom
;
369 if(mode
->dx1
!=0 && rq
.geom
.x
+mode
->dx1
<sg
->x
&& rq
.geom
.x
+mode
->dx1
>sg
->x
-er
)
370 realdx1
=sg
->x
-rq
.geom
.x
;
371 if(mode
->dx2
!=0 && rq
.geom
.x
+rq
.geom
.w
+mode
->dx2
>sg
->x
+sg
->w
&& rq
.geom
.x
+rq
.geom
.w
+mode
->dx2
<sg
->x
+sg
->w
+er
)
372 realdx2
=sg
->x
+sg
->w
-rq
.geom
.x
-rq
.geom
.w
;
373 if(mode
->dy1
!=0 && rq
.geom
.y
+mode
->dy1
<sg
->y
&& rq
.geom
.y
+mode
->dy1
>sg
->y
-er
)
374 realdy1
=sg
->y
-rq
.geom
.y
;
375 if(mode
->dy2
!=0 && rq
.geom
.y
+rq
.geom
.h
+mode
->dy2
>sg
->y
+sg
->h
&& rq
.geom
.y
+rq
.geom
.h
+mode
->dy2
<sg
->y
+sg
->h
+er
)
376 realdy2
=sg
->y
+sg
->h
-rq
.geom
.y
-rq
.geom
.h
;
379 w
=MAXOF(1, mode
->origgeom
.w
-realdx1
+realdx2
);
380 h
=MAXOF(1, mode
->origgeom
.h
-realdy1
+realdy2
);
382 if(mode
->snap_enabled
&& mode
->hints
.base_set
){
383 w
=clamp_up(w
, mode
->hints
.base_width
-er
, mode
->hints
.base_width
);
384 h
=clamp_up(h
, mode
->hints
.base_height
-er
, mode
->hints
.base_height
);
388 sizehints_correct(&mode
->hints
, &w
, &h
, TRUE
, TRUE
);
390 /* Do not modify coordinates and sizes that were not requested to be
394 if(mode
->dx1
==mode
->dx2
){
395 if(mode
->dx1
==0 || realdx1
!=mode
->dx1
)
401 if(mode
->dx1
==0 || realdx1
!=mode
->dx1
)
404 rq
.geom
.x
+=mode
->origgeom
.w
-rq
.geom
.w
;
408 if(mode
->dy1
==mode
->dy2
){
409 if(mode
->dy1
==0 || realdy1
!=mode
->dy1
)
415 if(mode
->dy1
==0 || realdy1
!=mode
->dy1
)
418 rq
.geom
.y
+=mode
->origgeom
.h
-rq
.geom
.h
;
421 moveresmode_do_newgeom(mode
, &rq
);
423 if(!mode
->resize_cumulative
)
424 moveresmode_setorig(mode
);
431 void moveresmode_delta_resize(WMoveresMode
*mode
,
432 int dx1
, int dx2
, int dy1
, int dy2
,
435 mode
->mode
=MOVERES_SIZE
;
436 moveresmode_delta(mode
, dx1
, dx2
, dy1
, dy2
, rret
);
440 void moveresmode_delta_move(WMoveresMode
*mode
,
441 int dx
, int dy
, WRectangle
*rret
)
443 mode
->mode
=MOVERES_POS
;
444 moveresmode_delta(mode
, dx
, dx
, dy
, dy
, rret
);
448 void moveresmode_rqgeom(WMoveresMode
*mode
, WRQGeomParams
*rq
,
449 WRectangle
*UNUSED(rret
))
451 mode
->mode
=MOVERES_SIZE
;
452 moveresmode_do_newgeom(mode
, rq
);
453 moveresmode_setorig(mode
);
457 /* It is ugly to do this here, but it will have to do for now... */
458 static void set_saved(WMoveresMode
*mode
, WRegion
*reg
)
462 if(!OBJ_IS(reg
, WFrame
))
467 /* Restore saved sizes from the beginning of the resize action */
468 if(mode
->origgeom
.w
!=mode
->geom
.w
){
469 frame
->saved_geom
.x
=mode
->origgeom
.x
;
470 frame
->saved_geom
.w
=mode
->origgeom
.w
;
473 if(mode
->origgeom
.h
!=mode
->geom
.h
){
474 frame
->saved_geom
.y
=mode
->origgeom
.y
;
475 frame
->saved_geom
.h
=mode
->origgeom
.h
;
480 bool moveresmode_do_end(WMoveresMode
*mode
, bool apply
)
482 WRegion
*reg
=mode
->reg
;
485 assert(tmpmode
==mode
);
490 moveres_draw_rubberband(mode
);
492 WRQGeomParams rq
=RQGEOMPARAMS_INIT
;
495 rq
.flags
=mode
->rqflags
&~REGION_RQGEOM_TRYONLY
;
497 region_rqgeom(reg
, &rq
, &mode
->geom
);
499 XUngrabServer(ioncore_g
.dpy
);
502 set_saved(mode
, reg
);
504 if(mode
->infowin
!=NULL
){
505 mainloop_defer_destroy((Obj
*)mode
->infowin
);
508 destroy_obj((Obj
*)mode
);
517 /*{{{ Request and other dynfuns */
520 void region_rqgeom(WRegion
*reg
, const WRQGeomParams
*rq
,
523 WRegion
*mgr
=REGION_MANAGER(reg
);
526 if(rq
->flags
®ION_RQGEOM_ABSOLUTE
)
527 region_managed_rqgeom_absolute(mgr
, reg
, rq
, geomret
);
529 region_managed_rqgeom(mgr
, reg
, rq
, geomret
);
533 if(rq
->flags
®ION_RQGEOM_ABSOLUTE
)
534 region_absolute_geom_to_parent(reg
, &rq
->geom
, &tmp
);
541 if(!(rq
->flags
®ION_RQGEOM_TRYONLY
))
542 region_fit(reg
, &tmp
, REGION_FIT_EXACT
);
547 void rqgeomparams_from_table(WRQGeomParams
*rq
,
548 const WRectangle
*origg
, ExtlTab g
)
551 rq
->flags
=REGION_RQGEOM_WEAK_ALL
;
553 if(extl_table_gets_i(g
, "x", &(rq
->geom
.x
)))
554 rq
->flags
&=~REGION_RQGEOM_WEAK_X
;
555 if(extl_table_gets_i(g
, "y", &(rq
->geom
.y
)))
556 rq
->flags
&=~REGION_RQGEOM_WEAK_Y
;
557 if(extl_table_gets_i(g
, "w", &(rq
->geom
.w
)))
558 rq
->flags
&=~REGION_RQGEOM_WEAK_W
;
559 if(extl_table_gets_i(g
, "h", &(rq
->geom
.h
)))
560 rq
->flags
&=~REGION_RQGEOM_WEAK_H
;
562 rq
->geom
.w
=MAXOF(1, rq
->geom
.w
);
563 rq
->geom
.h
=MAXOF(1, rq
->geom
.h
);
568 * Attempt to resize and/or move \var{reg}. The table \var{g} is a usual
569 * geometry specification (fields \var{x}, \var{y}, \var{w} and \var{h}),
570 * but may contain missing fields, in which case, \var{reg}'s manager may
571 * attempt to leave that attribute unchanged.
573 EXTL_EXPORT_AS(WRegion
, rqgeom
)
574 ExtlTab
region_rqgeom_extl(WRegion
*reg
, ExtlTab g
)
576 WRQGeomParams rq
=RQGEOMPARAMS_INIT
;
579 rqgeomparams_from_table(&rq
, ®ION_GEOM(reg
), g
);
581 region_rqgeom(reg
, &rq
, &res
);
583 return extl_table_from_rectangle(&res
);
587 void region_managed_rqgeom(WRegion
*mgr
, WRegion
*reg
,
588 const WRQGeomParams
*rq
,
591 CALL_DYN(region_managed_rqgeom
, mgr
, (mgr
, reg
, rq
, geomret
));
595 void region_managed_rqgeom_absolute(WRegion
*mgr
, WRegion
*reg
,
596 const WRQGeomParams
*rq
,
599 CALL_DYN(region_managed_rqgeom_absolute
, mgr
,
600 (mgr
, reg
, rq
, geomret
));
604 void region_managed_rqgeom_allow(WRegion
*UNUSED(mgr
), WRegion
*reg
,
605 const WRQGeomParams
*rq
,
611 if(!(rq
->flags
®ION_RQGEOM_TRYONLY
))
612 region_fit(reg
, &rq
->geom
, REGION_FIT_EXACT
);
616 void region_managed_rqgeom_unallow(WRegion
*UNUSED(mgr
), WRegion
*reg
,
617 const WRQGeomParams
*UNUSED(rq
),
621 *geomret
=REGION_GEOM(reg
);
625 void region_managed_rqgeom_absolute_default(WRegion
*mgr
, WRegion
*reg
,
626 const WRQGeomParams
*rq
,
629 WRQGeomParams rq2
=RQGEOMPARAMS_INIT
;
631 rq2
.flags
=rq
->flags
&~REGION_RQGEOM_ABSOLUTE
;
632 region_absolute_geom_to_parent(reg
, &rq
->geom
, &rq2
.geom
);
634 region_managed_rqgeom(mgr
, reg
, &rq2
, geomret
);
638 bool region_managed_maximize(WRegion
*mgr
, WRegion
*reg
, int dir
, int action
)
641 CALL_DYN_RET(ret
, bool, region_managed_maximize
, mgr
, (mgr
, reg
, dir
, action
));
646 void region_size_hints(WRegion
*reg
, WSizeHints
*hints_ret
)
648 sizehints_clear(hints_ret
);
651 CALL_DYN(region_size_hints
, reg
, (reg
, hints_ret
));
654 if(!hints_ret
->min_set
){
655 hints_ret
->min_width
=1;
656 hints_ret
->min_height
=1;
658 if(!hints_ret
->base_set
){
659 hints_ret
->base_width
=0;
660 hints_ret
->base_height
=0;
662 if(!hints_ret
->max_set
){
663 hints_ret
->max_width
=INT_MAX
;
664 hints_ret
->max_height
=INT_MAX
;
669 void region_size_hints_correct(WRegion
*reg
,
670 int *wp
, int *hp
, bool min
)
674 region_size_hints(reg
, &hints
);
676 sizehints_correct(&hints
, wp
, hp
, min
, FALSE
);
680 int region_orientation(WRegion
*reg
)
682 int ret
=REGION_ORIENTATION_NONE
;
684 CALL_DYN_RET(ret
, int, region_orientation
, reg
, (reg
));
691 * Returns size hints for \var{reg}. The returned table always contains the
692 * fields \code{min_?}, \code{base_?} and sometimes the fields \code{max_?},
693 * \code{base_?} and \code{inc_?}, where \code{?}=\code{w}, \code{h}.
696 EXTL_EXPORT_AS(WRegion
, size_hints
)
697 ExtlTab
region_size_hints_extl(WRegion
*reg
)
702 region_size_hints(reg
, &hints
);
704 tab
=extl_create_table();
707 extl_table_sets_i(tab
, "base_w", hints
.base_width
);
708 extl_table_sets_i(tab
, "base_h", hints
.base_height
);
711 extl_table_sets_i(tab
, "min_w", hints
.min_width
);
712 extl_table_sets_i(tab
, "min_h", hints
.min_height
);
715 extl_table_sets_i(tab
, "max_w", hints
.max_width
);
716 extl_table_sets_i(tab
, "max_h", hints
.max_height
);
719 extl_table_sets_i(tab
, "inc_w", hints
.width_inc
);
720 extl_table_sets_i(tab
, "inc_h", hints
.height_inc
);
729 /*{{{ Restore size, maximize, shade */
732 static bool rqh(WFrame
*frame
, int y
, int h
)
734 WRQGeomParams rq
=RQGEOMPARAMS_INIT
;
738 rq
.flags
=REGION_RQGEOM_VERT_ONLY
;
740 rq
.geom
.x
=REGION_GEOM(frame
).x
;
741 rq
.geom
.w
=REGION_GEOM(frame
).w
;
746 region_size_hints_correct((WRegion
*)frame
, &dummy_w
, &(rq
.geom
.h
), TRUE
);
748 region_rqgeom((WRegion
*)frame
, &rq
, &rgeom
);
750 return (abs(rgeom
.y
-REGION_GEOM(frame
).y
)>1 ||
751 abs(rgeom
.h
-REGION_GEOM(frame
).h
)>1);
756 * Attempt to toggle vertical maximisation of \var{frame}.
759 void frame_maximize_vert(WFrame
*frame
)
761 WRegion
*mp
=REGION_MANAGER(frame
);
764 if(frame
->flags
&FRAME_SHADED
|| frame
->flags
&FRAME_MAXED_VERT
){
765 if(frame
->flags
&FRAME_SHADED
)
766 frame
->flags
|=FRAME_SHADED_TOGGLE
;
767 if(frame
->flags
&FRAME_SAVED_VERT
){
768 if(mp
!=NULL
&& region_managed_maximize(mp
, (WRegion
*)frame
, VERTICAL
, VERIFY
))
769 region_managed_maximize(mp
, (WRegion
*)frame
, VERTICAL
, RESTORE
);
771 rqh(frame
, frame
->saved_geom
.y
, frame
->saved_geom
.h
);
773 frame
->flags
&=~(FRAME_MAXED_VERT
|FRAME_SAVED_VERT
|FRAME_SHADED_TOGGLE
);
774 region_goto((WRegion
*)frame
);
781 oy
=REGION_GEOM(frame
).y
;
782 oh
=REGION_GEOM(frame
).h
;
784 region_managed_maximize(mp
, (WRegion
*)frame
, VERTICAL
, SAVE
);
785 rqh(frame
, 0, REGION_GEOM(mp
).h
);
786 region_managed_maximize(mp
, (WRegion
*)frame
, VERTICAL
, RM_KEEP
);
788 frame
->flags
|=(FRAME_MAXED_VERT
|FRAME_SAVED_VERT
);
789 frame
->saved_geom
.y
=oy
;
790 frame
->saved_geom
.h
=oh
;
792 region_goto((WRegion
*)frame
);
795 static bool rqw(WFrame
*frame
, int x
, int w
)
797 WRQGeomParams rq
=RQGEOMPARAMS_INIT
;
801 rq
.flags
=REGION_RQGEOM_HORIZ_ONLY
;
805 rq
.geom
.y
=REGION_GEOM(frame
).y
;
806 rq
.geom
.h
=REGION_GEOM(frame
).h
;
809 region_size_hints_correct((WRegion
*)frame
, &(rq
.geom
.w
), &dummy_h
, TRUE
);
811 region_rqgeom((WRegion
*)frame
, &rq
, &rgeom
);
813 return (abs(rgeom
.x
-REGION_GEOM(frame
).x
)>1 ||
814 abs(rgeom
.w
-REGION_GEOM(frame
).w
)>1);
819 * Attempt to toggle horizontal maximisation of \var{frame}.
822 void frame_maximize_horiz(WFrame
*frame
)
824 WRegion
*mp
=REGION_MANAGER(frame
);
827 if(frame
->flags
&FRAME_MIN_HORIZ
|| frame
->flags
&FRAME_MAXED_HORIZ
){
828 if(frame
->flags
&FRAME_SAVED_HORIZ
){
829 if(mp
!=NULL
&& region_managed_maximize(mp
, (WRegion
*)frame
, HORIZONTAL
, VERIFY
))
830 region_managed_maximize(mp
, (WRegion
*)frame
, HORIZONTAL
, RESTORE
);
832 rqw(frame
, frame
->saved_geom
.x
, frame
->saved_geom
.w
);
834 frame
->flags
&=~(FRAME_MAXED_HORIZ
|FRAME_SAVED_HORIZ
);
835 region_goto((WRegion
*)frame
);
842 ox
=REGION_GEOM(frame
).x
;
843 ow
=REGION_GEOM(frame
).w
;
845 region_managed_maximize(mp
, (WRegion
*)frame
, HORIZONTAL
, SAVE
);
846 rqw(frame
, 0, REGION_GEOM(mp
).w
);
847 region_managed_maximize(mp
, (WRegion
*)frame
, HORIZONTAL
, RM_KEEP
);
849 frame
->flags
|=(FRAME_MAXED_HORIZ
|FRAME_SAVED_HORIZ
);
850 frame
->saved_geom
.x
=ox
;
851 frame
->saved_geom
.w
=ow
;
853 region_goto((WRegion
*)frame
);
864 uint
region_min_h(WRegion
*reg
)
867 region_size_hints(reg
, &hints
);
868 return hints
.min_height
;
872 uint
region_min_w(WRegion
*reg
)
875 region_size_hints(reg
, &hints
);
876 return hints
.min_width
;
880 void region_convert_root_geom(WRegion
*reg
, WRectangle
*geom
)
884 region_rootpos(reg
, &rx
, &ry
);
891 void region_absolute_geom_to_parent(WRegion
*reg
, const WRectangle
*rgeom
,
894 WRegion
*parent
=REGION_PARENT_REG(reg
);
903 region_rootpos(reg
, &pgeom
->x
, &pgeom
->y
);
904 pgeom
->x
=rgeom
->x
-pgeom
->x
;
905 pgeom
->y
=rgeom
->y
-pgeom
->y
;