rsc | 324891a | 2006-06-25 18:58:06 +0000 | [diff] [blame] | 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 | } |