| #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); |
| } |