aboutsummaryrefslogtreecommitdiff
path: root/src/libdraw/ml-lorigin.c
blob: 0926ee8d216bd66119a4dc3c1a2932e2bb587287 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#include <memlayer.h>

/*
 * Place i so i->r.min = log, i->layer->screenr.min == scr.
*/
int
memlorigin(Memimage *i, Point log, Point scr)
{
	Memlayer *l;
	Memscreen *s;
	Memimage *t, *shad, *nsave;
	Rectangle x, newr, oldr;
	Point delta;
	int overlap, eqlog, eqscr, wasclear;

	l = i->layer;
	s = l->screen;
	oldr = l->screenr;
	newr = Rect(scr.x, scr.y, scr.x+Dx(oldr), scr.y+Dy(oldr));
	eqscr = eqpt(scr, oldr.min);
	eqlog = eqpt(log, i->r.min);
	if(eqscr && eqlog)
		return 0;
	nsave = nil;
	if(eqlog==0 && l->save!=nil){
		nsave = allocmemimage(Rect(log.x, log.y, log.x+Dx(oldr), log.y+Dy(oldr)), i->chan);
		if(nsave == nil)
			return -1;
	}

	/*
	 * Bring it to front and move logical coordinate system.
	 */
	memltofront(i);
	wasclear = l->clear;
	if(nsave){
		if(!wasclear)
			memimagedraw(nsave, nsave->r, l->save, l->save->r.min, nil, Pt(0,0), S);
		freememimage(l->save);
		l->save = nsave;
	}
	delta = subpt(log, i->r.min);
	i->r = rectaddpt(i->r, delta);
	i->clipr = rectaddpt(i->clipr, delta);
	l->delta = subpt(l->screenr.min, i->r.min);
	if(eqscr)
		return 0;

	/*
	 * To clean up old position, make a shadow window there, don't paint it,
	 * push it behind this one, and (later) delete it.  Because the refresh function
	 * for this fake window is a no-op, this will cause no graphics action except
	 * to restore the background and expose the windows previously hidden.
	 */
	shad = memlalloc(s, oldr, memlnorefresh, nil, DNofill);
	if(shad == nil)
		return -1;
	s->frontmost = i;
	if(s->rearmost == i)
		s->rearmost = shad;
	else
		l->rear->layer->front = shad;
	shad->layer->front = i;
	shad->layer->rear = l->rear;
	l->rear = shad;
	l->front = nil;
	shad->layer->clear = 0;

	/*
	 * Shadow is now holding down the fort at the old position.
	 * Move the window and hide things obscured by new position.
	 */
	for(t=l->rear->layer->rear; t!=nil; t=t->layer->rear){
		x = newr;
		overlap = rectclip(&x, t->layer->screenr);
		if(overlap){
			memlhide(t, x);
			t->layer->clear = 0;
		}
	}
	l->screenr = newr;
	l->delta = subpt(scr, i->r.min);
	l->clear = rectinrect(newr, l->screen->image->clipr);

	/*
	 * Everything's covered.  Copy to new position and delete shadow window.
	 */
	if(wasclear)
		memdraw(s->image, newr, s->image, oldr.min, nil, Pt(0,0), S);
	else
		memlexpose(i, newr);
	memldelete(shad);

	return 1;
}

void
memlnorefresh(Memimage *l, Rectangle r, void *v)
{
	USED(l);
	USED(r.min.x);
	USED(v);
}