]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libmemlayer/lorigin.c
libaml: fix gc bug, need to amltake()/amldrop() temporary buffer
[plan9front.git] / sys / src / libmemlayer / lorigin.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <memlayer.h>
6
7 /*
8  * Place i so i->r.min = log, i->layer->screenr.min == scr.
9 */
10 int
11 memlorigin(Memimage *i, Point log, Point scr)
12 {
13         Memlayer *l;
14         Memscreen *s;
15         Memimage *t, *shad, *nsave;
16         Rectangle x, newr, oldr;
17         Point delta;
18         int overlap, eqlog, eqscr, wasclear;
19
20         l = i->layer;
21         s = l->screen;
22         oldr = l->screenr;
23         newr = Rect(scr.x, scr.y, scr.x+Dx(oldr), scr.y+Dy(oldr));
24         eqscr = eqpt(scr, oldr.min);
25         eqlog = eqpt(log, i->r.min);
26         if(eqscr && eqlog)
27                 return 0;
28         nsave = nil;
29         if(eqlog==0 && l->save!=nil){
30                 nsave = allocmemimage(Rect(log.x, log.y, log.x+Dx(oldr), log.y+Dy(oldr)), i->chan);
31                 if(nsave == nil)
32                         return -1;
33         }
34
35         /*
36          * Bring it to front and move logical coordinate system.
37          */
38         memltofront(i);
39         wasclear = l->clear;
40         if(nsave){
41                 if(!wasclear)
42                         memimagedraw(nsave, nsave->r, l->save, l->save->r.min, nil, Pt(0,0), S);
43                 freememimage(l->save);
44                 l->save = nsave;
45         }
46         delta = subpt(log, i->r.min);
47         i->r = rectaddpt(i->r, delta);
48         i->clipr = rectaddpt(i->clipr, delta);
49         l->delta = subpt(l->screenr.min, i->r.min);
50         if(eqscr)
51                 return 0;
52
53         /*
54          * To clean up old position, make a shadow window there, don't paint it,
55          * push it behind this one, and (later) delete it.  Because the refresh function
56          * for this fake window is a no-op, this will cause no graphics action except
57          * to restore the background and expose the windows previously hidden.
58          */
59         shad = memlalloc(s, oldr, memlnorefresh, nil, DNofill);
60         if(shad == nil)
61                 return -1;
62         s->frontmost = i;
63         if(s->rearmost == i)
64                 s->rearmost = shad;
65         else
66                 l->rear->layer->front = shad;
67         shad->layer->front = i;
68         shad->layer->rear = l->rear;
69         l->rear = shad;
70         l->front = nil;
71         shad->layer->clear = 0;
72
73         /*
74          * Shadow is now holding down the fort at the old position.
75          * Move the window and hide things obscured by new position.
76          */
77         for(t=l->rear->layer->rear; t!=nil; t=t->layer->rear){
78                 x = newr;
79                 overlap = rectclip(&x, t->layer->screenr);
80                 if(overlap){
81                         memlhide(t, x);
82                         t->layer->clear = 0;
83                 }
84         }
85         l->screenr = newr;
86         l->delta = subpt(scr, i->r.min);
87         l->clear = rectinrect(newr, l->screen->image->clipr);
88
89         /*
90          * Everything's covered.  Copy to new position and delete shadow window.
91          */
92         if(wasclear)
93                 memdraw(s->image, newr, s->image, oldr.min, nil, Pt(0,0), S);
94         else
95                 memlexpose(i, newr);
96         memldelete(shad);
97
98         return 1;
99 }
100
101 void
102 memlnorefresh(Memimage *l, Rectangle r, void *v)
103 {
104         USED(l);
105         USED(r.min.x);
106         USED(v);
107 }