xref: /freebsd/lib/libvgl/mouse.c (revision 41059135ce931c0f1014a999ffabc6bc470ce856)
1 /*-
2  * Copyright (c) 1991-1997 Søren Schmidt
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer
10  *    in this position and unchanged.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include <stdio.h>
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
35 #include <sys/signal.h>
36 #include <sys/consio.h>
37 #include <sys/fbio.h>
38 #include "vgl.h"
39 
40 #define X 0xff
41 static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
42 	X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
43 	X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
44 	X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
45 	X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
46 	X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
47 	X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
48 	X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
49 	X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
50 	X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
51 	0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,0,
52 	0,0,0,X,X,X,X,X,0,0,0,0,0,0,0,0,
53 	0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
54 	0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
55 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
56 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
57 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
58 };
59 static byte StdOrMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
60 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
61 	0,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
62 	0,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
63 	0,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
64 	0,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
65 	0,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
66 	0,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
67 	0,X,X,0,X,0,0,0,0,0,0,0,0,0,0,0,
68 	0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0,
69 	0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,0,
70 	0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,
71 	0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,0,
72 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
73 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
74 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
75 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
76 };
77 #undef X
78 static VGLBitmap VGLMouseStdAndMask =
79     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdAndMask);
80 static VGLBitmap VGLMouseStdOrMask =
81     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdOrMask);
82 static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask;
83 static byte map[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE];
84 static VGLBitmap VGLMouseSave =
85     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, map);
86 static int VGLMouseVisible = 0;
87 static int VGLMouseFrozen = 0;
88 static int VGLMouseShown = 0;
89 static int VGLMouseXpos = 0;
90 static int VGLMouseYpos = 0;
91 static int VGLMouseButtons = 0;
92 
93 void
94 VGLMousePointerShow()
95 {
96   byte buf[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE];
97   VGLBitmap buffer =
98     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, buf);
99   byte crtcidx, crtcval, gdcidx, gdcval;
100   int pos;
101 
102   if (!VGLMouseVisible) {
103     VGLMouseVisible = 1;
104     crtcidx = inb(0x3c4);
105     crtcval = inb(0x3c5);
106     gdcidx = inb(0x3ce);
107     gdcval = inb(0x3cf);
108     __VGLBitmapCopy(VGLDisplay, VGLMouseXpos, VGLMouseYpos,
109 		  &VGLMouseSave, 0, 0, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
110     bcopy(VGLMouseSave.Bitmap, buffer.Bitmap, MOUSE_IMG_SIZE*MOUSE_IMG_SIZE);
111     for (pos = 0; pos <  MOUSE_IMG_SIZE*MOUSE_IMG_SIZE; pos++)
112       buffer.Bitmap[pos]=(buffer.Bitmap[pos]&~(VGLMouseAndMask->Bitmap[pos])) |
113 			   VGLMouseOrMask->Bitmap[pos];
114     __VGLBitmapCopy(&buffer, 0, 0, VGLDisplay,
115 		  VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
116     outb(0x3c4, crtcidx);
117     outb(0x3c5, crtcval);
118     outb(0x3ce, gdcidx);
119     outb(0x3cf, gdcval);
120   }
121 }
122 
123 void
124 VGLMousePointerHide()
125 {
126   byte crtcidx, crtcval, gdcidx, gdcval;
127 
128   if (VGLMouseVisible) {
129     VGLMouseVisible = 0;
130     crtcidx = inb(0x3c4);
131     crtcval = inb(0x3c5);
132     gdcidx = inb(0x3ce);
133     gdcval = inb(0x3cf);
134     __VGLBitmapCopy(&VGLMouseSave, 0, 0, VGLDisplay,
135 		  VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
136     outb(0x3c4, crtcidx);
137     outb(0x3c5, crtcval);
138     outb(0x3ce, gdcidx);
139     outb(0x3cf, gdcval);
140   }
141 }
142 
143 void
144 VGLMouseMode(int mode)
145 {
146   if (mode == VGL_MOUSESHOW) {
147     if (VGLMouseShown == VGL_MOUSEHIDE) {
148       VGLMousePointerShow();
149       VGLMouseShown = VGL_MOUSESHOW;
150     }
151   }
152   else {
153     if (VGLMouseShown == VGL_MOUSESHOW) {
154       VGLMousePointerHide();
155       VGLMouseShown = VGL_MOUSEHIDE;
156     }
157   }
158 }
159 
160 void
161 VGLMouseAction(int dummy)
162 {
163   struct mouse_info mouseinfo;
164 
165   if (VGLMouseFrozen) {
166     VGLMouseFrozen++;
167     return;
168   }
169   mouseinfo.operation = MOUSE_GETINFO;
170   ioctl(0, CONS_MOUSECTL, &mouseinfo);
171   if (VGLMouseShown == VGL_MOUSESHOW)
172     VGLMousePointerHide();
173   VGLMouseXpos = mouseinfo.u.data.x;
174   VGLMouseYpos = mouseinfo.u.data.y;
175   VGLMouseButtons = mouseinfo.u.data.buttons;
176   if (VGLMouseShown == VGL_MOUSESHOW)
177     VGLMousePointerShow();
178 }
179 
180 void
181 VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask)
182 {
183   if (VGLMouseShown == VGL_MOUSESHOW)
184     VGLMousePointerHide();
185   VGLMouseAndMask = AndMask;
186   VGLMouseOrMask = OrMask;
187   if (VGLMouseShown == VGL_MOUSESHOW)
188     VGLMousePointerShow();
189 }
190 
191 void
192 VGLMouseSetStdImage()
193 {
194   if (VGLMouseShown == VGL_MOUSESHOW)
195     VGLMousePointerHide();
196   VGLMouseAndMask = &VGLMouseStdAndMask;
197   VGLMouseOrMask = &VGLMouseStdOrMask;
198   if (VGLMouseShown == VGL_MOUSESHOW)
199     VGLMousePointerShow();
200 }
201 
202 int
203 VGLMouseInit(int mode)
204 {
205   struct mouse_info mouseinfo;
206   int error;
207 
208   VGLMouseSetStdImage();
209   mouseinfo.operation = MOUSE_MODE;
210   mouseinfo.u.mode.signal = SIGUSR2;
211   if ((error = ioctl(0, CONS_MOUSECTL, &mouseinfo)))
212     return error;
213   signal(SIGUSR2, VGLMouseAction);
214   mouseinfo.operation = MOUSE_GETINFO;
215   ioctl(0, CONS_MOUSECTL, &mouseinfo);
216   VGLMouseXpos = mouseinfo.u.data.x;
217   VGLMouseYpos = mouseinfo.u.data.y;
218   VGLMouseButtons = mouseinfo.u.data.buttons;
219   VGLMouseMode(mode);
220   return 0;
221 }
222 
223 int
224 VGLMouseStatus(int *x, int *y, char *buttons)
225 {
226   signal(SIGUSR2, SIG_IGN);
227   *x =  VGLMouseXpos;
228   *y =  VGLMouseYpos;
229   *buttons =  VGLMouseButtons;
230   signal(SIGUSR2, VGLMouseAction);
231   return VGLMouseShown;
232 }
233 
234 int
235 VGLMouseFreeze(int x, int y, int width, int hight, byte color)
236 {
237   if (!VGLMouseFrozen) {
238     VGLMouseFrozen = 1;
239     if (width > 1 || hight > 1) {		/* bitmap */
240       if (VGLMouseShown == 1) {
241         int overlap;
242 
243         if (x > VGLMouseXpos)
244           overlap = (VGLMouseXpos + MOUSE_IMG_SIZE) - x;
245         else
246           overlap = (x + width) - VGLMouseXpos;
247         if (overlap > 0) {
248           if (y > VGLMouseYpos)
249             overlap = (VGLMouseYpos + MOUSE_IMG_SIZE) - y;
250           else
251             overlap = (y + hight) - VGLMouseYpos;
252           if (overlap > 0)
253             VGLMousePointerHide();
254         }
255       }
256     }
257     else {				/* bit */
258       if (VGLMouseShown &&
259           x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE &&
260           y >= VGLMouseYpos && y < VGLMouseYpos + MOUSE_IMG_SIZE) {
261         VGLMouseSave.Bitmap[(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)] =
262           (color);
263         if (VGLMouseAndMask->Bitmap
264           [(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)]) {
265           return 1;
266         }
267       }
268     }
269   }
270   return 0;
271 }
272 
273 void
274 VGLMouseUnFreeze()
275 {
276   if (VGLMouseFrozen > 1) {
277     VGLMouseFrozen = 0;
278     VGLMouseAction(0);
279   }
280   else {
281     VGLMouseFrozen = 0;
282     if (VGLMouseShown == VGL_MOUSESHOW && !VGLMouseVisible)
283       VGLMousePointerShow();
284   }
285 }
286