2 Copyright © 1995-2013, The AROS Development Team. All rights reserved.
9 #include <aros/libcall.h>
10 #include <aros/debug.h>
11 #include <proto/layers.h>
12 #include <proto/exec.h>
13 #include <proto/graphics.h>
14 #include <proto/utility.h>
15 #include <exec/memory.h>
16 #include <graphics/rastport.h>
17 #include <graphics/clip.h>
19 #include "layers_intern.h"
20 #include "basicfuncs.h"
22 /*****************************************************************************
26 AROS_LH5(LONG
, MoveSizeLayer
,
29 AROS_LHA(struct Layer
*, l
, A0
),
30 AROS_LHA(LONG
, dx
, D0
),
31 AROS_LHA(LONG
, dy
, D1
),
32 AROS_LHA(LONG
, dw
, D2
),
33 AROS_LHA(LONG
, dh
, D3
),
36 struct LayersBase
*, LayersBase
, 30, Layers
)
39 Moves and resizes the layer in one step. Collects damage lists
40 for those layers that become visible and are simple layers.
41 If the layer to be moved is becoming larger the additional
42 areas are added to a damagelist if it is a non-superbitmap
43 layer. Refresh is also triggered for this layer.
46 l - pointer to layer to be moved
47 dx - delta to add to current x position
48 dy - delta to add to current y position
49 dw - delta to add to current width
50 dw - delta to add to current height
53 result - TRUE if everything went right
54 FALSE if an error occurred (out of memory)
66 *****************************************************************************/
70 struct Layer
* first
, *_l
, *lparent
;
71 struct Region
* newshape
, * oldshape
, r
, rtmp
, cutnewshape
;
72 struct Region
*clipregion
, *olddamage
= NULL
;
73 struct Rectangle rectw
, recth
;
77 InitRegion(&cutnewshape
);
79 LockLayers(l
->LayerInfo
);
81 clipregion
= _InternalInstallClipRegion(l
, NULL
, 0, 0, LayersBase
);
83 /* There's a little problem with CopyClipRectsToClipRects(). It
84 may call the backfill hook for the whole DamageList region.
85 Layers should never do this. It should call backfill hook only
86 for *new* damage, a layer operation causes. But not for those
87 areas which were part of the damage already before the layer
88 operation. Otherwise those latter areas might end up being
89 backfilled multiple times -> flickering. As fixing CopyClipRects-
90 ToClipRects() seems kinda complicated, I use a little trick: Set
91 a flag which tells the layer's backfillhook calling function not to do
92 that. Before executing the movesizelayer operation I backup the old
93 damage region, and after executing of movesizelayer operation is done
94 I can use it to find out what areas were added to the damageregion.
95 I'll clear that special layer flag, and call the backfill hook for the
96 new damage areas. (stegerg) */
98 if (IS_SIMPLEREFRESH(l
))
100 olddamage
= NewRegion();
103 OrRegionRegion(l
->DamageList
, olddamage
);
104 _TranslateRect(&olddamage
->bounds
, l
->bounds
.MinX
, l
->bounds
.MinY
);
105 AndRegionRegion(l
->VisibleRegion
, olddamage
);
106 AndRegionRegion(l
->visibleshape
, olddamage
);
107 _TranslateRect(&olddamage
->bounds
, -l
->bounds
.MinX
, -l
->bounds
.MinY
);
109 IL(l
)->intflags
|= INTFLAG_AVOID_BACKFILL
;
114 * First Create the new region of the layer:
115 * adjust its size and position.
119 /* First create newshape with 0,0 origin, because l->shaperegion is in layer coords */
121 newshape
= NewRectRegion(0,
123 l
->bounds
.MaxX
- l
->bounds
.MinX
+ dw
,
124 l
->bounds
.MaxY
- l
->bounds
.MinY
+ dh
);
126 if (IL(l
)->shapehook
)
128 struct ShapeHookMsg msg
;
129 struct Rectangle NewBounds
;
131 if ((dx
|| dy
) && (dw
|| dh
))
133 msg
.Action
= SHAPEHOOKACTION_MOVESIZELAYER
;
137 msg
.Action
= SHAPEHOOKACTION_MOVELAYER
;
141 msg
.Action
= SHAPEHOOKACTION_SIZELAYER
;
144 msg
.NewShape
= l
->shaperegion
;
145 msg
.OldShape
= l
->shaperegion
;
146 msg
.NewBounds
= &NewBounds
;
147 msg
.OldBounds
= &l
->bounds
;
149 NewBounds
.MinX
= l
->bounds
.MinX
+ dx
;
150 NewBounds
.MinY
= l
->bounds
.MinY
+ dy
;
151 NewBounds
.MaxX
= l
->bounds
.MaxX
+ dx
+ dw
;
152 NewBounds
.MaxY
= l
->bounds
.MaxY
+ dy
+ dh
;
154 if (CallHookPkt(IL(l
)->shapehook
, l
, &msg
))
155 l
->shaperegion
= msg
.NewShape
;
159 AndRegionRegion(l
->shaperegion
, newshape
);
161 /* Now make newshape relative to old(!!) layer screen coords */
162 _TranslateRect(&newshape
->bounds
, l
->bounds
.MinX
+dx
, l
->bounds
.MinY
+dy
);
164 /* rectw and recth are now only needed for backfilling if layer got bigger -> see end of func */
168 rectw
.MinX
= dx
+l
->bounds
.MaxX
+1;
169 rectw
.MinY
= dy
+l
->bounds
.MinY
;
170 rectw
.MaxX
= rectw
.MinX
+ dw
- 1;
171 rectw
.MaxY
= dy
+l
->bounds
.MaxY
+dh
;
176 recth
.MinX
= dx
+l
->bounds
.MinX
;
177 recth
.MinY
= dy
+l
->bounds
.MaxY
+ 1;
178 recth
.MaxX
= dx
+l
->bounds
.MaxX
+dw
;
179 recth
.MaxY
= recth
.MinY
+ dh
- 1;
182 SetRegion(newshape
, &cutnewshape
);
183 AndRegionRegion(l
->parent
->visibleshape
, &cutnewshape
);
185 first
= GetFirstFamilyMember(l
);
187 * Must make a copy of the VisibleRegion of the first visible layer here
195 SetRegion(_l
->VisibleRegion
, &r
);
204 //kprintf("%s called for layer %p, first = %p!\n",__FUNCTION__,l,first);
207 * First back up parts of layers that are behind the layer
208 * family. Only need to do this if layer is moving or
209 * getting bigger in size. Only need to visit those layers
210 * that overlap with the new shape of the layer.
218 kprintf("\t\t%s: Backing up parts of layers that are behind the layer!\n",
223 if (IS_VISIBLE(_l
) && DO_OVERLAP(&cutnewshape
.bounds
, &_l
->shape
->bounds
))
224 _BackupPartsOfLayer(_l
, &cutnewshape
, 0, FALSE
, LayersBase
);
226 ClearRegionRegion(&cutnewshape
, _l
->VisibleRegion
);
230 if (IS_VISIBLE(_l
) || (NULL
== lparent
->parent
))
233 lparent
= lparent
->parent
;
238 SetRegion(&cutnewshape
, l
->visibleshape
);
239 ClearRegion(&cutnewshape
);
242 * Now I need to move the layer and all its familiy to the new
252 struct ClipRect
* cr
;
255 kprintf("\t\t%s: BACKING up parts of THE LAYER TO BE MOVED!\n",
259 if (1/* IS_VISIBLE(_l) */)
261 ClearRegion(_l
->VisibleRegion
);
262 _BackupPartsOfLayer(_l
, _l
->shape
, dx
, TRUE
, LayersBase
);
265 * Effectively move the layer...
267 _TranslateRect(&_l
->bounds
, dx
, dy
);
271 * ...and also its cliprects.
276 _TranslateRect(&cr
->bounds
, dx
, dy
);
283 _TranslateRect(&cr
->bounds
, dx
, dy
);
289 _TranslateRect(&_l
->shape
->bounds
, dx
, dy
);
292 * Also calculate the visible shape!
294 SetRegion(_l
->shape
, _l
->visibleshape
);
295 AndRegionRegion(_l
->parent
->visibleshape
, _l
->visibleshape
);
304 l
->bounds
.MaxX
+= dw
;
305 l
->bounds
.MaxY
+= dh
;
311 * Now make them visible again.
320 kprintf("\t\t%s: SHOWING parts of THE LAYER TO BE MOVED (children)!\n",
323 ClearRegion(_l
->VisibleRegion
);
324 _ShowPartsOfLayer(_l
, &r
, LayersBase
);
329 ClearRegionRegion(_l
->visibleshape
, &r
);
339 * Now make those parts of the layers after l up to and including
340 * its parent visible.
342 SetRegion(l
->VisibleRegion
, &r
);
343 ClearRegionRegion(l
->visibleshape
, &r
);
350 kprintf("\t\t%s: SHOWING parts of the layers behind the layer to be moved!\n",
353 if (IS_VISIBLE(_l
) &&
354 ( DO_OVERLAP(&l
->visibleshape
->bounds
, &_l
->shape
->bounds
) ||
355 DO_OVERLAP( &oldshape
->bounds
, &_l
->shape
->bounds
) ))
357 ClearRegion(_l
->VisibleRegion
);
358 _ShowPartsOfLayer(_l
, &r
, LayersBase
);
361 SetRegion(&r
, _l
->VisibleRegion
);
363 if (IS_VISIBLE(_l
) || IS_ROOTLAYER(_l
))
364 AndRegionRegion(_l
->VisibleRegion
, oldshape
);
367 if (IS_ROOTLAYER(_l
))
368 kprintf("root reached! %p\n",_l
);
373 if (IS_VISIBLE(_l
) || (NULL
== lparent
->parent
))
376 lparent
= lparent
->parent
;
380 ClearRegionRegion(_l
->visibleshape
, &r
);
388 * Now I need to clear the old layer at its previous place..
389 * But I may only clear those parts where no layer has become
390 * visible in the meantime.
392 if (!IS_EMPTYREGION(oldshape
))
394 if (lparent
&& IS_ROOTLAYER(lparent
))
395 _BackFillRegion(l
->parent
, oldshape
, TRUE
, LayersBase
);
398 DisposeRegion(oldshape
);
401 * If the size of the layer became larger clear the
402 * new area where it is visible.
404 if ((dw
> 0 || dh
> 0) && !IS_SUPERREFRESH(l
))
408 OrRectRegion(&r
, &rectw
);
411 OrRectRegion(&r
, &recth
);
413 _BackFillRegion(l
, &r
, TRUE
, LayersBase
);
420 struct Region
*newdamage
= NewRegion();
422 IL(l
)->intflags
&= ~INTFLAG_AVOID_BACKFILL
;
425 OrRegionRegion(l
->DamageList
, newdamage
);
426 ClearRegionRegion(olddamage
, newdamage
);
427 _TranslateRect(&newdamage
->bounds
, l
->bounds
.MinX
, l
->bounds
.MinY
);
428 _BackFillRegion(l
, newdamage
, FALSE
, LayersBase
);
430 DisposeRegion(newdamage
);
432 DisposeRegion(olddamage
);
436 _InternalInstallClipRegion(l
, clipregion
, 0, 0, LayersBase
);
438 UnlockLayers(l
->LayerInfo
);
443 } /* MoveSizeLayer */