]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/port/swcursor.c
devdraw: fix topnwindows() panic when images are not windows (thanks aiju)
[plan9front.git] / sys / src / 9 / port / swcursor.c
1 #include        "u.h"
2 #include        "../port/lib.h"
3 #include        "mem.h"
4 #include        "dat.h"
5 #include        "fns.h"
6 #include        "../port/error.h"
7
8 #define Image   IMAGE
9 #include        <draw.h>
10 #include        <memdraw.h>
11 #include        <cursor.h>
12 #include        "screen.h"
13
14 extern Memimage* gscreen;
15
16 /*
17  * Software cursor. 
18  */
19 static Memimage*        swback;         /* screen under cursor */
20 static Memimage*        swimg;          /* cursor image */
21 static Memimage*        swmask;         /* cursor mask */
22 static Memimage*        swimg1;
23 static Memimage*        swmask1;
24
25 static Point            swoffset;
26 static Rectangle        swrect;         /* screen rectangle in swback */
27 static Point            swvispt;        /* actual cursor location */
28 static int              swvisible;      /* is the cursor visible? */
29
30 /*
31  * called with drawlock locked for us, most of the time.
32  * kernel prints at inopportune times might mean we don't
33  * hold the lock, but memimagedraw is now reentrant so
34  * that should be okay: worst case we get cursor droppings.
35  */
36 void
37 swcursorhide(void)
38 {
39         if(swvisible == 0)
40                 return;
41         if(swback == nil || gscreen == nil)
42                 return;
43         swvisible = 0;
44         memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
45 }
46
47 void
48 swcursoravoid(Rectangle r)
49 {
50         if(swvisible && rectXrect(r, swrect)){
51                 swcursorhide();
52                 mouseredraw();  /* schedule cursor redraw after we release drawlock */
53         }
54 }
55
56 void
57 swcursordraw(Point p)
58 {
59         Rectangle flushr;
60
61         if(swvisible)
62                 return;
63         if(swback == nil || swimg1 == nil || swmask1 == nil || gscreen == nil)
64                 return;
65         assert(!canqlock(&drawlock));
66         swvispt = addpt(swoffset, p);
67         flushr = swrect; 
68         swrect = rectaddpt(Rect(0,0,16,16), swvispt);
69         combinerect(&flushr, swrect);
70         memimagedraw(swback, swback->r, gscreen, swvispt, memopaque, ZP, S);
71         memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
72         flushmemscreen(flushr);
73         swvisible = 1;
74 }
75
76 void
77 swcursorload(Cursor *curs)
78 {
79         uchar *ip, *mp;
80         int i, j, set, clr;
81
82         if(swimg == nil || swmask == nil || swimg1 == nil || swmask1 == nil)
83                 return;
84         /*
85          * Build cursor image and mask.
86          * Image is just the usual cursor image
87          * but mask is a transparent alpha mask.
88          * 
89          * The 16x16x8 memimages do not have
90          * padding at the end of their scan lines.
91          */
92         ip = byteaddr(swimg, ZP);
93         mp = byteaddr(swmask, ZP);
94         for(i=0; i<32; i++){
95                 set = curs->set[i];
96                 clr = curs->clr[i];
97                 for(j=0x80; j; j>>=1){
98                         *ip++ = set&j ? 0x00 : 0xFF;
99                         *mp++ = (clr|set)&j ? 0xFF : 0x00;
100                 }
101         }
102         swoffset = curs->offset;
103         memimagedraw(swimg1, swimg1->r, swimg, ZP, memopaque, ZP, S);
104         memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
105
106         mouseredraw();
107 }
108
109 void
110 swcursorinit(void)
111 {
112         if(gscreen == nil)
113                 return;
114
115         if(swback){
116                 freememimage(swback);
117                 freememimage(swmask);
118                 freememimage(swmask1);
119                 freememimage(swimg);
120                 freememimage(swimg1); 
121         }
122         swback = allocmemimage(Rect(0,0,32,32), gscreen->chan);
123         swmask = allocmemimage(Rect(0,0,16,16), GREY8);
124         swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
125         swimg = allocmemimage(Rect(0,0,16,16), GREY8);
126         swimg1 = allocmemimage(Rect(0,0,16,16), GREY1);
127         if(swback == nil || swmask == nil || swmask1 == nil || swimg == nil || swimg1 == nil){
128                 print("software cursor: allocmemimage fails\n");
129                 return;
130         }
131         memfillcolor(swback, DTransparent);
132         memfillcolor(swmask, DOpaque);
133         memfillcolor(swmask1, DOpaque);
134         memfillcolor(swimg, DBlack);
135         memfillcolor(swimg1, DBlack);
136 }