Build contrib binary archive again because it isn't included in FreeBSD
[AROS.git] / rom / hyperlayers / movesizelayer.c
bloba620d506fd36c1c150f8ad414ce6fa1f203eb3ce
1 /*
2 Copyright © 1995-2001, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc:
6 Lang: english
7 */
8 #include <aros/libcall.h>
9 #include <aros/debug.h>
10 #include <proto/layers.h>
11 #include <proto/exec.h>
12 #include <proto/graphics.h>
13 #include <proto/utility.h>
14 #include <exec/memory.h>
15 #include <graphics/rastport.h>
16 #include <graphics/clip.h>
17 #include "layers_intern.h"
18 #include "basicfuncs.h"
21 /*****************************************************************************
23 NAME */
25 AROS_LH5(LONG, MoveSizeLayer,
27 /* SYNOPSIS */
28 AROS_LHA(struct Layer *, l , A0),
29 AROS_LHA(LONG , dx, D0),
30 AROS_LHA(LONG , dy, D1),
31 AROS_LHA(LONG , dw, D2),
32 AROS_LHA(LONG , dh, D3),
34 /* LOCATION */
35 struct LayersBase *, LayersBase, 30, Layers)
37 /* FUNCTION
38 Moves and resizes the layer in one step. Collects damage lists
39 for those layers that become visible and are simple layers.
40 If the layer to be moved is becoming larger the additional
41 areas are added to a damagelist if it is a non-superbitmap
42 layer. Refresh is also triggered for this layer.
44 INPUTS
45 l - pointer to layer to be moved
46 dx - delta to add to current x position
47 dy - delta to add to current y position
48 dw - delta to add to current width
49 dw - delta to add to current height
51 RESULT
52 result - TRUE everyting went alright
53 FALSE an error occurred (out of memory)
55 NOTES
57 EXAMPLE
59 BUGS
61 SEE ALSO
63 INTERNALS
65 HISTORY
66 27-11-96 digulla automatically created from
67 layers_lib.fd and clib/layers_protos.h
69 *****************************************************************************/
71 AROS_LIBFUNC_INIT
72 AROS_LIBBASE_EXT_DECL(struct LayersBase *,LayersBase)
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 if ((olddamage = CopyRegion(l->DamageList)))
106 _TranslateRect(&olddamage->bounds, l->bounds.MinX, l->bounds.MinY);
107 AndRegionRegion(l->VisibleRegion, olddamage);
108 AndRegionRegion(l->visibleshape, olddamage);
109 _TranslateRect(&olddamage->bounds, -l->bounds.MinX, -l->bounds.MinY);
111 IL(l)->intflags |= INTFLAG_AVOID_BACKFILL;
116 * First Create the new region of the layer:
117 * adjust its size and position.
121 /* First create newshape with 0,0 origin, because l->shaperegion is in layer coords */
123 newshape = NewRectRegion(0,
125 l->bounds.MaxX - l->bounds.MinX + dw,
126 l->bounds.MaxY - l->bounds.MinY + dh);
127 if (IL(l)->shapehook)
129 struct ShapeHookMsg msg;
131 if ((dx || dy) && (dw || dh))
133 msg.Action = SHAPEHOOKACTION_MOVESIZELAYER;
135 else if (dx || dy)
137 msg.Action = SHAPEHOOKACTION_MOVELAYER;
139 else
141 msg.Action = SHAPEHOOKACTION_SIZELAYER;
144 msg.Layer = l;
145 msg.ActualShape = l->shaperegion;
146 msg.NewBounds.MinX = l->bounds.MinX + dx;
147 msg.NewBounds.MinY = l->bounds.MinY + dy;
148 msg.NewBounds.MaxX = l->bounds.MaxX + dx + dw;
149 msg.NewBounds.MaxY = l->bounds.MaxY + dy + dh;
150 msg.OldBounds.MinX = l->bounds.MinX;
151 msg.OldBounds.MinY = l->bounds.MinY;
152 msg.OldBounds.MaxX = l->bounds.MaxX;
153 msg.OldBounds.MaxY = l->bounds.MaxY;
155 l->shaperegion = (struct Region *)CallHookPkt(IL(l)->shapehook, l, &msg);
158 if (l->shaperegion)
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 */
166 if (dw > 0)
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;
174 if (dh > 0)
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
188 * and NOT later!
190 _l = first;
191 while (1)
193 if (IS_VISIBLE(_l))
195 SetRegion(_l->VisibleRegion, &r);
196 break;
199 if (l == _l)
200 break;
202 _l = _l->back;
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.
214 lparent = l->parent;
215 _l = l->back;
217 #if 0
218 kprintf("\t\t%s: Backing up parts of layers that are behind the layer!\n",
219 __FUNCTION__);
220 #endif
221 while (1)
223 if (IS_VISIBLE(_l) && DO_OVERLAP(&cutnewshape.bounds, &_l->shape->bounds))
224 _BackupPartsOfLayer(_l, &cutnewshape, 0, FALSE, LayersBase);
225 else
226 ClearRegionRegion(&cutnewshape, _l->VisibleRegion);
228 if (_l == lparent)
230 if (IS_VISIBLE(_l) || (NULL == lparent->parent))
231 break;
232 else
233 lparent = lparent->parent;
235 _l = _l->back;
238 SetRegion(&cutnewshape, l->visibleshape);
239 ClearRegion(&cutnewshape);
242 * Now I need to move the layer and all its familiy to the new
243 * location.
245 oldshape = l->shape;
246 l->shape = newshape;
248 _l = l;
250 while (1)
252 struct ClipRect * cr;
254 #if 0
255 kprintf("\t\t%s: BACKING up parts of THE LAYER TO BE MOVED!\n",
256 __FUNCTION__);
257 #endif
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.
273 cr = _l->ClipRect;
274 while (cr)
276 _TranslateRect(&cr->bounds, dx, dy);
277 cr = cr->Next;
280 cr = _l->_cliprects;
281 while (cr)
283 _TranslateRect(&cr->bounds, dx, dy);
284 cr = cr->Next;
287 if (l != _l)
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);
298 if (_l == first)
299 break;
301 _l = _l->front;
304 l->bounds.MaxX += dw;
305 l->bounds.MaxY += dh;
306 l->Width += dw;
307 l->Height += dh;
311 * Now make them visible again.
313 _l = first;
315 while (1)
317 if (IS_VISIBLE(_l))
319 #if 0
320 kprintf("\t\t%s: SHOWING parts of THE LAYER TO BE MOVED (children)!\n",
321 __FUNCTION__);
322 #endif
323 ClearRegion(_l->VisibleRegion);
324 _ShowPartsOfLayer(_l, &r, LayersBase);
326 if (l == _l)
327 break;
329 ClearRegionRegion(_l->visibleshape, &r);
332 if (l == _l)
333 break;
335 _l = _l->back;
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);
344 _l = l->back;
345 lparent = l->parent;
347 while (1)
349 #if 0
350 kprintf("\t\t%s: SHOWING parts of the layers behind the layer to be moved!\n",
351 __FUNCTION__);
352 #endif
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);
360 else
361 SetRegion(&r, _l->VisibleRegion);
363 if (IS_VISIBLE(_l) || IS_ROOTLAYER(_l))
364 AndRegionRegion(_l->VisibleRegion, oldshape);
366 #if 0
367 if (IS_ROOTLAYER(_l))
368 kprintf("root reached! %p\n",_l);
369 #endif
371 if (_l == lparent)
373 if (IS_VISIBLE(_l) || (NULL == lparent->parent))
374 break;
375 else
376 lparent = lparent->parent;
379 if (IS_VISIBLE(_l))
380 ClearRegionRegion(_l->visibleshape, &r);
382 _l = _l->back;
385 ClearRegion(&rtmp);
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))
406 ClearRegion(&r);
407 if (dw > 0)
408 OrRectRegion(&r, &rectw);
410 if (dh > 0)
411 OrRectRegion(&r, &recth);
413 _BackFillRegion(l, &r, TRUE, LayersBase);
416 ClearRegion(&r);
418 if (olddamage)
420 struct Region *newdamage = CopyRegion(l->DamageList);
422 IL(l)->intflags &= ~INTFLAG_AVOID_BACKFILL;
423 if (newdamage)
425 ClearRegionRegion(olddamage, newdamage);
426 _TranslateRect(&newdamage->bounds, l->bounds.MinX, l->bounds.MinY);
427 _BackFillRegion(l, newdamage, FALSE, LayersBase);
429 DisposeRegion(newdamage);
431 DisposeRegion(olddamage);
434 if (clipregion)
435 _InternalInstallClipRegion(l, clipregion, 0, 0, LayersBase);
437 UnlockLayers(l->LayerInfo);
439 return TRUE;
441 AROS_LIBFUNC_EXIT
442 } /* MoveSizeLayer */