2 * SPDX-License-Identifier: BSD-3-Clause
4 * Copyright (c) 1991-1997 Søren Schmidt
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
35 #include <sys/types.h>
36 #include <sys/ioctl.h>
37 #include <sys/signal.h>
38 #include <sys/consio.h>
42 static void VGLMouseAction(int dummy);
44 #define BORDER 0xff /* default border -- light white in rgb 3:3:2 */
45 #define INTERIOR 0xa0 /* default interior -- red in rgb 3:3:2 */
46 #define LARGE_MOUSE_IMG_XSIZE 19
47 #define LARGE_MOUSE_IMG_YSIZE 32
48 #define SMALL_MOUSE_IMG_XSIZE 10
49 #define SMALL_MOUSE_IMG_YSIZE 16
50 #define X 0xff /* any nonzero in And mask means part of cursor */
53 static byte LargeAndMask[] = {
54 X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
55 X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
56 X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
57 X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
58 X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
59 X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
60 X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
61 X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
62 X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
63 X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
64 X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
65 X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
66 X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,
67 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,
68 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,
69 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,
70 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,
71 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
72 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
73 X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
74 X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
75 X,X,X,X,X,X,0,X,X,X,X,X,X,0,0,0,0,0,0,
76 X,X,X,X,X,0,0,X,X,X,X,X,X,0,0,0,0,0,0,
77 X,X,X,X,0,0,0,0,X,X,X,X,X,X,0,0,0,0,0,
78 X,X,X,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0,0,
79 X,X,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0,
80 0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0,
81 0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,
82 0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,
83 0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,
84 0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,
85 0,0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,0,0,0,
87 static byte LargeOrMask[] = {
88 B,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
89 B,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
90 B,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
91 B,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
92 B,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,
93 B,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,
94 B,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,
95 B,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,
96 B,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,
97 B,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,
98 B,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,
99 B,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,
100 B,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,
101 B,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,
102 B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,
103 B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,
104 B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,
105 B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,
106 B,I,I,I,I,I,I,I,I,I,I,B,B,B,B,B,B,B,B,
107 B,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,
108 B,I,I,I,I,I,B,I,I,I,I,B,0,0,0,0,0,0,0,
109 B,I,I,I,I,B,0,B,I,I,I,I,B,0,0,0,0,0,0,
110 B,I,I,I,B,0,0,B,I,I,I,I,B,0,0,0,0,0,0,
111 B,I,I,B,0,0,0,0,B,I,I,I,I,B,0,0,0,0,0,
112 B,I,B,0,0,0,0,0,B,I,I,I,I,B,0,0,0,0,0,
113 B,B,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0,0,
114 0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0,0,
115 0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0,
116 0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0,
117 0,0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,
118 0,0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,
119 0,0,0,0,0,0,0,0,0,0,0,0,B,B,B,B,0,0,0,
121 static byte SmallAndMask[] = {
122 X,X,0,0,0,0,0,0,0,0,
123 X,X,X,0,0,0,0,0,0,0,
124 X,X,X,X,0,0,0,0,0,0,
125 X,X,X,X,X,0,0,0,0,0,
126 X,X,X,X,X,X,0,0,0,0,
127 X,X,X,X,X,X,X,0,0,0,
128 X,X,X,X,X,X,X,X,0,0,
129 X,X,X,X,X,X,X,X,X,0,
130 X,X,X,X,X,X,X,X,X,X,
131 X,X,X,X,X,X,X,X,X,X,
132 X,X,X,X,X,X,X,0,0,0,
133 X,X,X,0,X,X,X,X,0,0,
134 X,X,0,0,X,X,X,X,0,0,
135 0,0,0,0,0,X,X,X,X,0,
136 0,0,0,0,0,X,X,X,X,0,
137 0,0,0,0,0,0,X,X,0,0,
139 static byte SmallOrMask[] = {
140 B,B,0,0,0,0,0,0,0,0,
141 B,I,B,0,0,0,0,0,0,0,
142 B,I,I,B,0,0,0,0,0,0,
143 B,I,I,I,B,0,0,0,0,0,
144 B,I,I,I,I,B,0,0,0,0,
145 B,I,I,I,I,I,B,0,0,0,
146 B,I,I,I,I,I,I,B,0,0,
147 B,I,I,I,I,I,I,I,B,0,
148 B,I,I,I,I,I,I,I,I,B,
149 B,I,I,I,I,I,B,B,B,B,
150 B,I,I,B,I,I,B,0,0,0,
151 B,I,B,0,B,I,I,B,0,0,
152 B,B,0,0,B,I,I,B,0,0,
153 0,0,0,0,0,B,I,I,B,0,
154 0,0,0,0,0,B,I,I,B,0,
155 0,0,0,0,0,0,B,B,0,0,
160 static VGLBitmap VGLMouseLargeAndMask =
161 VGLBITMAP_INITIALIZER(MEMBUF, LARGE_MOUSE_IMG_XSIZE, LARGE_MOUSE_IMG_YSIZE,
163 static VGLBitmap VGLMouseLargeOrMask =
164 VGLBITMAP_INITIALIZER(MEMBUF, LARGE_MOUSE_IMG_XSIZE, LARGE_MOUSE_IMG_YSIZE,
166 static VGLBitmap VGLMouseSmallAndMask =
167 VGLBITMAP_INITIALIZER(MEMBUF, SMALL_MOUSE_IMG_XSIZE, SMALL_MOUSE_IMG_YSIZE,
169 static VGLBitmap VGLMouseSmallOrMask =
170 VGLBITMAP_INITIALIZER(MEMBUF, SMALL_MOUSE_IMG_XSIZE, SMALL_MOUSE_IMG_YSIZE,
172 static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask;
173 static int VGLMouseShown = VGL_MOUSEHIDE;
174 static int VGLMouseXpos = 0;
175 static int VGLMouseYpos = 0;
176 static int VGLMouseButtons = 0;
177 static volatile sig_atomic_t VGLMintpending;
178 static volatile sig_atomic_t VGLMsuppressint;
180 #define INTOFF() (VGLMsuppressint++)
181 #define INTON() do { \
182 if (--VGLMsuppressint == 0 && VGLMintpending) \
187 __VGLMouseMode(int mode)
192 oldmode = VGLMouseShown;
193 if (mode == VGL_MOUSESHOW) {
194 if (VGLMouseShown == VGL_MOUSEHIDE) {
195 VGLMouseShown = VGL_MOUSESHOW;
196 __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos,
197 VGLDisplay, VGLMouseXpos, VGLMouseYpos,
198 VGLMouseAndMask->VXsize, -VGLMouseAndMask->VYsize);
202 if (VGLMouseShown == VGL_MOUSESHOW) {
203 VGLMouseShown = VGL_MOUSEHIDE;
204 __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos,
205 VGLDisplay, VGLMouseXpos, VGLMouseYpos,
206 VGLMouseAndMask->VXsize, VGLMouseAndMask->VYsize);
214 VGLMouseMode(int mode)
216 __VGLMouseMode(mode);
220 VGLMouseAction(int dummy)
222 struct mouse_info mouseinfo;
225 if (VGLMsuppressint) {
232 mouseinfo.operation = MOUSE_GETINFO;
233 ioctl(0, CONS_MOUSECTL, &mouseinfo);
234 if (VGLMouseXpos != mouseinfo.u.data.x ||
235 VGLMouseYpos != mouseinfo.u.data.y) {
236 mousemode = __VGLMouseMode(VGL_MOUSEHIDE);
237 VGLMouseXpos = mouseinfo.u.data.x;
238 VGLMouseYpos = mouseinfo.u.data.y;
239 __VGLMouseMode(mousemode);
241 VGLMouseButtons = mouseinfo.u.data.buttons;
244 * Loop to handle any new (suppressed) signals. This is INTON() without
245 * recursion. !SA_RESTART prevents recursion in signal handling. So the
246 * maximum recursion is 2 levels.
254 VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask)
258 mousemode = __VGLMouseMode(VGL_MOUSEHIDE);
260 VGLMouseAndMask = AndMask;
262 if (VGLMouseOrMask != NULL) {
263 free(VGLMouseOrMask->Bitmap);
264 free(VGLMouseOrMask);
266 VGLMouseOrMask = VGLBitmapCreate(MEMBUF, OrMask->VXsize, OrMask->VYsize, 0);
267 VGLBitmapAllocateBits(VGLMouseOrMask);
268 VGLBitmapCvt(OrMask, VGLMouseOrMask);
270 __VGLMouseMode(mousemode);
274 VGLMouseSetStdImage()
276 if (VGLDisplay->VXsize > 800)
277 VGLMouseSetImage(&VGLMouseLargeAndMask, &VGLMouseLargeOrMask);
279 VGLMouseSetImage(&VGLMouseSmallAndMask, &VGLMouseSmallOrMask);
283 VGLMouseInit(int mode)
285 struct mouse_info mouseinfo;
287 int andmask, border, error, i, interior;
289 switch (VGLModeInfo.vi_mem_model) {
290 case V_INFO_MM_PACKED:
291 case V_INFO_MM_PLANAR:
307 if (VGLModeInfo.vi_mode == M_BG640x480)
308 border = 0; /* XXX (palette makes 0x04 look like 0x0f) */
309 if (getenv("VGLMOUSEBORDERCOLOR") != NULL)
310 border = strtoul(getenv("VGLMOUSEBORDERCOLOR"), NULL, 0);
311 if (getenv("VGLMOUSEINTERIORCOLOR") != NULL)
312 interior = strtoul(getenv("VGLMOUSEINTERIORCOLOR"), NULL, 0);
313 ormask = &VGLMouseLargeOrMask;
314 for (i = 0; i < ormask->VXsize * ormask->VYsize; i++)
315 ormask->Bitmap[i] = ormask->Bitmap[i] == BORDER ? border :
316 ormask->Bitmap[i] == INTERIOR ? interior : 0;
317 ormask = &VGLMouseSmallOrMask;
318 for (i = 0; i < ormask->VXsize * ormask->VYsize; i++)
319 ormask->Bitmap[i] = ormask->Bitmap[i] == BORDER ? border :
320 ormask->Bitmap[i] == INTERIOR ? interior : 0;
321 VGLMouseSetStdImage();
322 mouseinfo.operation = MOUSE_MODE;
323 mouseinfo.u.mode.signal = SIGUSR2;
324 if ((error = ioctl(0, CONS_MOUSECTL, &mouseinfo)))
326 signal(SIGUSR2, VGLMouseAction);
327 mouseinfo.operation = MOUSE_GETINFO;
328 ioctl(0, CONS_MOUSECTL, &mouseinfo);
329 VGLMouseXpos = mouseinfo.u.data.x;
330 VGLMouseYpos = mouseinfo.u.data.y;
331 VGLMouseButtons = mouseinfo.u.data.buttons;
337 VGLMouseRestore(void)
339 struct mouse_info mouseinfo;
342 mouseinfo.operation = MOUSE_GETINFO;
343 if (ioctl(0, CONS_MOUSECTL, &mouseinfo) == 0) {
344 mouseinfo.operation = MOUSE_MOVEABS;
345 mouseinfo.u.data.x = VGLMouseXpos;
346 mouseinfo.u.data.y = VGLMouseYpos;
347 ioctl(0, CONS_MOUSECTL, &mouseinfo);
353 VGLMouseStatus(int *x, int *y, char *buttons)
358 *buttons = VGLMouseButtons;
360 return VGLMouseShown;
370 VGLMouseFreezeXY(int x, int y)
373 if (VGLMouseShown != VGL_MOUSESHOW)
375 if (x >= VGLMouseXpos && x < VGLMouseXpos + VGLMouseAndMask->VXsize &&
376 y >= VGLMouseYpos && y < VGLMouseYpos + VGLMouseAndMask->VYsize &&
377 VGLMouseAndMask->Bitmap[(y-VGLMouseYpos)*VGLMouseAndMask->VXsize+
384 VGLMouseOverlap(int x, int y, int width, int hight)
388 if (VGLMouseShown != VGL_MOUSESHOW)
390 if (x > VGLMouseXpos)
391 overlap = (VGLMouseXpos + VGLMouseAndMask->VXsize) - x;
393 overlap = (x + width) - VGLMouseXpos;
396 if (y > VGLMouseYpos)
397 overlap = (VGLMouseYpos + VGLMouseAndMask->VYsize) - y;
399 overlap = (y + hight) - VGLMouseYpos;
404 VGLMouseMerge(int x, int y, int width, byte *line)
406 int pos, x1, xend, xstart;
409 if (xstart < VGLMouseXpos)
410 xstart = VGLMouseXpos;
412 if (xend > VGLMouseXpos + VGLMouseAndMask->VXsize)
413 xend = VGLMouseXpos + VGLMouseAndMask->VXsize;
414 for (x1 = xstart; x1 < xend; x1++) {
415 pos = (y - VGLMouseYpos) * VGLMouseAndMask->VXsize + x1 - VGLMouseXpos;
416 if (VGLMouseAndMask->Bitmap[pos])
417 bcopy(&VGLMouseOrMask->Bitmap[pos * VGLDisplay->PixelBytes],
418 &line[(x1 - x) * VGLDisplay->PixelBytes], VGLDisplay->PixelBytes);