Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

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