Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <memdraw.h>
5 #include <memlayer.h>
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;
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 }
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;
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;
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);
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);
98 return 1;
99 }
101 void
102 memlnorefresh(Memimage *l, Rectangle r, void *v)
104 USED(l);
105 USED(r.min.x);
106 USED(v);