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
VGLMousePointerShow()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
VGLMousePointerHide()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
VGLMouseMode(int mode)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
VGLMouseAction(int dummy)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
VGLMouseSetImage(VGLBitmap * AndMask,VGLBitmap * OrMask)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
VGLMouseSetStdImage()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
VGLMouseInit(int mode)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
VGLMouseStatus(int * x,int * y,char * buttons)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
VGLMouseFreeze(int x,int y,int width,int hight,byte color)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
VGLMouseUnFreeze()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