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