jehanne/sys/src/kern/port/swcursor.c

149 lines
3.8 KiB
C

/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
/* Portions of this file are Copyright (C) 9front's team.
* See /doc/license/9front-mit for details about the licensing.
* See http://git.9front.org/plan9front/plan9front/HEAD/info.html for a list of authors.
*/
#include "u.h"
#include "../port/lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#define Image IMAGE
#include <draw.h>
#include <memdraw.h>
#include <cursor.h>
#include "screen.h"
extern Memimage* gscreen;
/*
* Software cursor.
*/
static Memimage* swback; /* screen under cursor */
static Memimage* swimg; /* cursor image */
static Memimage* swmask; /* cursor mask */
static Memimage* swimg1;
static Memimage* swmask1;
static Point swoffset;
static Rectangle swrect; /* screen rectangle in swback */
static Point swvispt; /* actual cursor location */
static int swvisible; /* is the cursor visible? */
/*
* called with drawlock locked for us, most of the time.
* kernel prints at inopportune times might mean we don't
* hold the lock, but memimagedraw is now reentrant so
* that should be okay: worst case we get cursor droppings.
*/
void
swcursorhide(void)
{
if(swvisible == 0)
return;
if(swback == nil || gscreen == nil)
return;
swvisible = 0;
memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
}
void
swcursoravoid(Rectangle r)
{
if(swvisible && rectXrect(r, swrect)){
swcursorhide();
mouseredraw(); /* schedule cursor redraw after we release drawlock */
}
}
void
swcursordraw(Point p)
{
Rectangle flushr;
if(swvisible)
return;
if(swback == nil || swimg1 == nil || swmask1 == nil || gscreen == nil)
return;
assert(!canqlock(&drawlock));
swvispt = addpt(swoffset, p);
flushr = swrect;
swrect = rectaddpt(Rect(0,0,16,16), swvispt);
combinerect(&flushr, swrect);
memimagedraw(swback, swback->r, gscreen, swvispt, memopaque, ZP, S);
memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
flushmemscreen(flushr);
swvisible = 1;
}
void
swcursorload(Cursor *curs)
{
uint8_t *ip, *mp;
int i, j, set, clr;
if(swimg == nil || swmask == nil || swimg1 == nil || swmask1 == nil)
return;
/*
* Build cursor image and mask.
* Image is just the usual cursor image
* but mask is a transparent alpha mask.
*
* The 16x16x8 memimages do not have
* padding at the end of their scan lines.
*/
ip = byteaddr(swimg, ZP);
mp = byteaddr(swmask, ZP);
for(i=0; i<32; i++){
set = curs->set[i];
clr = curs->clr[i];
for(j=0x80; j; j>>=1){
*ip++ = set&j ? 0x00 : 0xFF;
*mp++ = (clr|set)&j ? 0xFF : 0x00;
}
}
swoffset = curs->offset;
memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
mouseredraw();
}
void
swcursorinit(void)
{
if(gscreen == nil)
return;
if(swback){
freememimage(swback);
freememimage(swmask);
freememimage(swmask1);
freememimage(swimg);
freememimage(swimg1);
}
swback = allocmemimage(Rect(0,0,32,32), gscreen->chan);
swmask = allocmemimage(Rect(0,0,16,16), GREY8);
swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
swimg = allocmemimage(Rect(0,0,16,16), GREY8);
swimg1 = allocmemimage(Rect(0,0,16,16), GREY1);
if(swback == nil || swmask == nil || swmask1 == nil || swimg == nil || swimg1 == nil){
print("software cursor: allocmemimage fails\n");
return;
}
memfillcolor(swback, DTransparent);
memfillcolor(swmask, DOpaque);
memfillcolor(swmask1, DOpaque);
memfillcolor(swimg, DBlack);
memfillcolor(swimg1, DBlack);
}