Minor fixes to comments.
[AROS.git] / rom / hyperlayers / movesizelayer.c
blobfe3a832b5aff028164513b941ca6625b22cef899
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
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 /*****************************************************************************
24 NAME */
26 AROS_LH5(LONG, MoveSizeLayer,
28 /* SYNOPSIS */
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),
35 /* LOCATION */
36 struct LayersBase *, LayersBase, 30, Layers)
38 /* FUNCTION
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.
45 INPUTS
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
52 RESULT
53 result - TRUE everyting went alright
54 FALSE an error occurred (out of memory)
56 NOTES
58 EXAMPLE
60 BUGS
62 SEE ALSO
64 INTERNALS
66 HISTORY
67 27-11-96 digulla automatically created from
68 layers_lib.fd and clib/layers_protos.h
70 *****************************************************************************/
72 AROS_LIBFUNC_INIT
74 struct Layer * first, *_l, *lparent;
75 struct Region * newshape, * oldshape, r, rtmp, cutnewshape;
76 struct Region *clipregion, *olddamage = NULL;
77 struct Rectangle rectw, recth;
79 InitRegion(&r);
80 InitRegion(&rtmp);
81 InitRegion(&cutnewshape);
83 LockLayers(l->LayerInfo);
85 clipregion = _InternalInstallClipRegion(l, NULL, 0, 0, LayersBase);
87 /* There's a little problem with CopyClipRectsToClipRects(). It
88 may call the backfill hook for the whole DamageList region.
89 Layers should never do this. It should call backfill hook only
90 for *new* damage, a layer operation causes. But not for those
91 areas which were part of the damage already before the layer
92 operation. Otherwise those latter areas might end up being
93 backfilled multiple times -> flickering. As fixing CopyClipRects-
94 ToClipRects() seems kinda complicated, I use a little trick: Set
95 a flag which tells the layers backfillhook calling function, not do
96 that. Before executing the movesizelayer operation I backup the old
97 damage region, and after executing of movesizelayer operation is done
98 I can use it to find out what areas where added to the damageregion.
99 i'll clear that special layer flag, and call the backfill hook for the
100 new damage areas. (stegerg) */
102 if (IS_SIMPLEREFRESH(l))
104 olddamage = NewRegion();
105 if (olddamage)
107 OrRegionRegion(l->DamageList, olddamage);
108 _TranslateRect(&olddamage->bounds, l->bounds.MinX, l->bounds.MinY);
109 AndRegionRegion(l->VisibleRegion, olddamage);
110 AndRegionRegion(l->visibleshape, olddamage);
111 _TranslateRect(&olddamage->bounds, -l->bounds.MinX, -l->bounds.MinY);
113 IL(l)->intflags |= INTFLAG_AVOID_BACKFILL;
118 * First Create the new region of the layer:
119 * adjust its size and position.
123 /* First create newshape with 0,0 origin, because l->shaperegion is in layer coords */
125 newshape = NewRectRegion(0,
127 l->bounds.MaxX - l->bounds.MinX + dw,
128 l->bounds.MaxY - l->bounds.MinY + dh);
130 if (IL(l)->shapehook)
132 struct ShapeHookMsg msg;
133 struct Rectangle NewBounds;
135 if ((dx || dy) && (dw || dh))
137 msg.Action = SHAPEHOOKACTION_MOVESIZELAYER;
139 else if (dx || dy)
141 msg.Action = SHAPEHOOKACTION_MOVELAYER;
143 else
145 msg.Action = SHAPEHOOKACTION_SIZELAYER;
148 msg.NewShape = l->shaperegion;
149 msg.OldShape = l->shaperegion;
150 msg.NewBounds = &NewBounds;
151 msg.OldBounds = &l->bounds;
153 NewBounds.MinX = l->bounds.MinX + dx;
154 NewBounds.MinY = l->bounds.MinY + dy;
155 NewBounds.MaxX = l->bounds.MaxX + dx + dw;
156 NewBounds.MaxY = l->bounds.MaxY + dy + dh;
158 if (CallHookPkt(IL(l)->shapehook, l, &msg))
159 l->shaperegion = msg.NewShape;
162 if (l->shaperegion)
163 AndRegionRegion(l->shaperegion, newshape);
165 /* Now make newshape relative to old(!!) layer screen coords */
166 _TranslateRect(&newshape->bounds, l->bounds.MinX+dx, l->bounds.MinY+dy);
168 /* rectw and recth are now only needed for backfilling if layer got bigger -> see end of func */
170 if (dw > 0)
172 rectw.MinX = dx+l->bounds.MaxX+1;
173 rectw.MinY = dy+l->bounds.MinY;
174 rectw.MaxX = rectw.MinX + dw - 1;
175 rectw.MaxY = dy+l->bounds.MaxY+dh;
178 if (dh > 0)
180 recth.MinX = dx+l->bounds.MinX;
181 recth.MinY = dy+l->bounds.MaxY + 1;
182 recth.MaxX = dx+l->bounds.MaxX+dw;
183 recth.MaxY = recth.MinY + dh - 1;
186 SetRegion(newshape, &cutnewshape);
187 AndRegionRegion(l->parent->visibleshape, &cutnewshape);
189 first = GetFirstFamilyMember(l);
191 * Must make a copy of the VisibleRegion of the first visible layer here
192 * and NOT later!
194 _l = first;
195 while (1)
197 if (IS_VISIBLE(_l))
199 SetRegion(_l->VisibleRegion, &r);
200 break;
203 if (l == _l)
204 break;
206 _l = _l->back;
208 //kprintf("%s called for layer %p, first = %p!\n",__FUNCTION__,l,first);
211 * First back up parts of layers that are behind the layer
212 * family. Only need to do this if layer is moving or
213 * getting bigger in size. Only need to visit those layers
214 * that overlap with the new shape of the layer.
218 lparent = l->parent;
219 _l = l->back;
221 #if 0
222 kprintf("\t\t%s: Backing up parts of layers that are behind the layer!\n",
223 __FUNCTION__);
224 #endif
225 while (1)
227 if (IS_VISIBLE(_l) && DO_OVERLAP(&cutnewshape.bounds, &_l->shape->bounds))
228 _BackupPartsOfLayer(_l, &cutnewshape, 0, FALSE, LayersBase);
229 else
230 ClearRegionRegion(&cutnewshape, _l->VisibleRegion);
232 if (_l == lparent)
234 if (IS_VISIBLE(_l) || (NULL == lparent->parent))
235 break;
236 else
237 lparent = lparent->parent;
239 _l = _l->back;
242 SetRegion(&cutnewshape, l->visibleshape);
243 ClearRegion(&cutnewshape);
246 * Now I need to move the layer and all its familiy to the new
247 * location.
249 oldshape = l->shape;
250 l->shape = newshape;
252 _l = l;
254 while (1)
256 struct ClipRect * cr;
258 #if 0
259 kprintf("\t\t%s: BACKING up parts of THE LAYER TO BE MOVED!\n",
260 __FUNCTION__);
261 #endif
263 if (1/* IS_VISIBLE(_l) */)
265 ClearRegion(_l->VisibleRegion);
266 _BackupPartsOfLayer(_l, _l->shape, dx, TRUE, LayersBase);
269 * Effectively move the layer...
271 _TranslateRect(&_l->bounds, dx, dy);
275 * ...and also its cliprects.
277 cr = _l->ClipRect;
278 while (cr)
280 _TranslateRect(&cr->bounds, dx, dy);
281 cr = cr->Next;
284 cr = _l->_cliprects;
285 while (cr)
287 _TranslateRect(&cr->bounds, dx, dy);
288 cr = cr->Next;
291 if (l != _l)
293 _TranslateRect(&_l->shape->bounds, dx, dy);
296 * Also calculate the visible shape!
298 SetRegion(_l->shape, _l->visibleshape);
299 AndRegionRegion(_l->parent->visibleshape, _l->visibleshape);
302 if (_l == first)
303 break;
305 _l = _l->front;
308 l->bounds.MaxX += dw;
309 l->bounds.MaxY += dh;
310 l->Width += dw;
311 l->Height += dh;
315 * Now make them visible again.
317 _l = first;
319 while (1)
321 if (IS_VISIBLE(_l))
323 #if 0
324 kprintf("\t\t%s: SHOWING parts of THE LAYER TO BE MOVED (children)!\n",
325 __FUNCTION__);
326 #endif
327 ClearRegion(_l->VisibleRegion);
328 _ShowPartsOfLayer(_l, &r, LayersBase);
330 if (l == _l)
331 break;
333 ClearRegionRegion(_l->visibleshape, &r);
336 if (l == _l)
337 break;
339 _l = _l->back;
343 * Now make those parts of the layers after l up to and including
344 * its parent visible.
346 SetRegion(l->VisibleRegion, &r);
347 ClearRegionRegion(l->visibleshape, &r);
348 _l = l->back;
349 lparent = l->parent;
351 while (1)
353 #if 0
354 kprintf("\t\t%s: SHOWING parts of the layers behind the layer to be moved!\n",
355 __FUNCTION__);
356 #endif
357 if (IS_VISIBLE(_l) &&
358 ( DO_OVERLAP(&l->visibleshape->bounds, &_l->shape->bounds) ||
359 DO_OVERLAP( &oldshape->bounds, &_l->shape->bounds) ))
361 ClearRegion(_l->VisibleRegion);
362 _ShowPartsOfLayer(_l, &r, LayersBase);
364 else
365 SetRegion(&r, _l->VisibleRegion);
367 if (IS_VISIBLE(_l) || IS_ROOTLAYER(_l))
368 AndRegionRegion(_l->VisibleRegion, oldshape);
370 #if 0
371 if (IS_ROOTLAYER(_l))
372 kprintf("root reached! %p\n",_l);
373 #endif
375 if (_l == lparent)
377 if (IS_VISIBLE(_l) || (NULL == lparent->parent))
378 break;
379 else
380 lparent = lparent->parent;
383 if (IS_VISIBLE(_l))
384 ClearRegionRegion(_l->visibleshape, &r);
386 _l = _l->back;
389 ClearRegion(&rtmp);
392 * Now I need to clear the old layer at its previous place..
393 * But I may only clear those parts where no layer has become
394 * visible in the meantime.
396 if (!IS_EMPTYREGION(oldshape))
398 if (lparent && IS_ROOTLAYER(lparent))
399 _BackFillRegion(l->parent, oldshape, TRUE, LayersBase);
402 DisposeRegion(oldshape);
405 * If the size of the layer became larger clear the
406 * new area where it is visible.
408 if ((dw > 0 || dh > 0) && !IS_SUPERREFRESH(l))
410 ClearRegion(&r);
411 if (dw > 0)
412 OrRectRegion(&r, &rectw);
414 if (dh > 0)
415 OrRectRegion(&r, &recth);
417 _BackFillRegion(l, &r, TRUE, LayersBase);
420 ClearRegion(&r);
422 if (olddamage)
424 struct Region *newdamage = NewRegion();
426 IL(l)->intflags &= ~INTFLAG_AVOID_BACKFILL;
427 if (newdamage)
429 OrRegionRegion(l->DamageList, newdamage);
430 ClearRegionRegion(olddamage, newdamage);
431 _TranslateRect(&newdamage->bounds, l->bounds.MinX, l->bounds.MinY);
432 _BackFillRegion(l, newdamage, FALSE, LayersBase);
434 DisposeRegion(newdamage);
436 DisposeRegion(olddamage);
439 if (clipregion)
440 _InternalInstallClipRegion(l, clipregion, 0, 0, LayersBase);
442 UnlockLayers(l->LayerInfo);
444 return TRUE;
446 AROS_LIBFUNC_EXIT
447 } /* MoveSizeLayer */