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>
33 #include <sys/types.h>
34 #include <sys/ioctl.h>
35 #include <sys/signal.h>
36 #include <sys/consio.h>
40 static void VGLMouseAction(int dummy);
42 #define BORDER 0xff /* default border -- light white in rgb 3:3:2 */
43 #define INTERIOR 0xa0 /* default interior -- red in rgb 3:3:2 */
44 #define LARGE_MOUSE_IMG_XSIZE 19
45 #define LARGE_MOUSE_IMG_YSIZE 32
46 #define SMALL_MOUSE_IMG_XSIZE 10
47 #define SMALL_MOUSE_IMG_YSIZE 16
48 #define X 0xff /* any nonzero in And mask means part of cursor */
51 static byte LargeAndMask[] = {
52 X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
53 X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
54 X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
55 X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
56 X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
57 X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
58 X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
59 X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
60 X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
61 X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
62 X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
63 X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
64 X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,
65 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,
66 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,
67 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,
68 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,
69 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
70 X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,
71 X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
72 X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
73 X,X,X,X,X,X,0,X,X,X,X,X,X,0,0,0,0,0,0,
74 X,X,X,X,X,0,0,X,X,X,X,X,X,0,0,0,0,0,0,
75 X,X,X,X,0,0,0,0,X,X,X,X,X,X,0,0,0,0,0,
76 X,X,X,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0,0,
77 X,X,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0,
78 0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0,
79 0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,
80 0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,
81 0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,
82 0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,
83 0,0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,0,0,0,
85 static byte LargeOrMask[] = {
86 B,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
87 B,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
88 B,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
89 B,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
90 B,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,
91 B,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,
92 B,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,
93 B,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,
94 B,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,
95 B,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,
96 B,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,
97 B,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,
98 B,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,
99 B,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,
100 B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,
101 B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,
102 B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,
103 B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,
104 B,I,I,I,I,I,I,I,I,I,I,B,B,B,B,B,B,B,B,
105 B,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,
106 B,I,I,I,I,I,B,I,I,I,I,B,0,0,0,0,0,0,0,
107 B,I,I,I,I,B,0,B,I,I,I,I,B,0,0,0,0,0,0,
108 B,I,I,I,B,0,0,B,I,I,I,I,B,0,0,0,0,0,0,
109 B,I,I,B,0,0,0,0,B,I,I,I,I,B,0,0,0,0,0,
110 B,I,B,0,0,0,0,0,B,I,I,I,I,B,0,0,0,0,0,
111 B,B,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0,0,
112 0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0,0,
113 0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0,
114 0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0,
115 0,0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,
116 0,0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,
117 0,0,0,0,0,0,0,0,0,0,0,0,B,B,B,B,0,0,0,
119 static byte SmallAndMask[] = {
120 X,X,0,0,0,0,0,0,0,0,
121 X,X,X,0,0,0,0,0,0,0,
122 X,X,X,X,0,0,0,0,0,0,
123 X,X,X,X,X,0,0,0,0,0,
124 X,X,X,X,X,X,0,0,0,0,
125 X,X,X,X,X,X,X,0,0,0,
126 X,X,X,X,X,X,X,X,0,0,
127 X,X,X,X,X,X,X,X,X,0,
128 X,X,X,X,X,X,X,X,X,X,
129 X,X,X,X,X,X,X,X,X,X,
130 X,X,X,X,X,X,X,0,0,0,
131 X,X,X,0,X,X,X,X,0,0,
132 X,X,0,0,X,X,X,X,0,0,
133 0,0,0,0,0,X,X,X,X,0,
134 0,0,0,0,0,X,X,X,X,0,
135 0,0,0,0,0,0,X,X,0,0,
137 static byte SmallOrMask[] = {
138 B,B,0,0,0,0,0,0,0,0,
139 B,I,B,0,0,0,0,0,0,0,
140 B,I,I,B,0,0,0,0,0,0,
141 B,I,I,I,B,0,0,0,0,0,
142 B,I,I,I,I,B,0,0,0,0,
143 B,I,I,I,I,I,B,0,0,0,
144 B,I,I,I,I,I,I,B,0,0,
145 B,I,I,I,I,I,I,I,B,0,
146 B,I,I,I,I,I,I,I,I,B,
147 B,I,I,I,I,I,B,B,B,B,
148 B,I,I,B,I,I,B,0,0,0,
149 B,I,B,0,B,I,I,B,0,0,
150 B,B,0,0,B,I,I,B,0,0,
151 0,0,0,0,0,B,I,I,B,0,
152 0,0,0,0,0,B,I,I,B,0,
153 0,0,0,0,0,0,B,B,0,0,
158 static VGLBitmap VGLMouseLargeAndMask =
159 VGLBITMAP_INITIALIZER(MEMBUF, LARGE_MOUSE_IMG_XSIZE, LARGE_MOUSE_IMG_YSIZE,
161 static VGLBitmap VGLMouseLargeOrMask =
162 VGLBITMAP_INITIALIZER(MEMBUF, LARGE_MOUSE_IMG_XSIZE, LARGE_MOUSE_IMG_YSIZE,
164 static VGLBitmap VGLMouseSmallAndMask =
165 VGLBITMAP_INITIALIZER(MEMBUF, SMALL_MOUSE_IMG_XSIZE, SMALL_MOUSE_IMG_YSIZE,
167 static VGLBitmap VGLMouseSmallOrMask =
168 VGLBITMAP_INITIALIZER(MEMBUF, SMALL_MOUSE_IMG_XSIZE, SMALL_MOUSE_IMG_YSIZE,
170 static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask;
171 static int VGLMouseShown = VGL_MOUSEHIDE;
172 static int VGLMouseXpos = 0;
173 static int VGLMouseYpos = 0;
174 static int VGLMouseButtons = 0;
175 static volatile sig_atomic_t VGLMintpending;
176 static volatile sig_atomic_t VGLMsuppressint;
178 #define INTOFF() (VGLMsuppressint++)
179 #define INTON() do { \
180 if (--VGLMsuppressint == 0 && VGLMintpending) \
185 __VGLMouseMode(int mode)
190 oldmode = VGLMouseShown;
191 if (mode == VGL_MOUSESHOW) {
192 if (VGLMouseShown == VGL_MOUSEHIDE) {
193 VGLMouseShown = VGL_MOUSESHOW;
194 __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos,
195 VGLDisplay, VGLMouseXpos, VGLMouseYpos,
196 VGLMouseAndMask->VXsize, -VGLMouseAndMask->VYsize);
200 if (VGLMouseShown == VGL_MOUSESHOW) {
201 VGLMouseShown = VGL_MOUSEHIDE;
202 __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos,
203 VGLDisplay, VGLMouseXpos, VGLMouseYpos,
204 VGLMouseAndMask->VXsize, VGLMouseAndMask->VYsize);
212 VGLMouseMode(int mode)
214 __VGLMouseMode(mode);
218 VGLMouseAction(int dummy)
220 struct mouse_info mouseinfo;
223 if (VGLMsuppressint) {
230 mouseinfo.operation = MOUSE_GETINFO;
231 ioctl(0, CONS_MOUSECTL, &mouseinfo);
232 if (VGLMouseXpos != mouseinfo.u.data.x ||
233 VGLMouseYpos != mouseinfo.u.data.y) {
234 mousemode = __VGLMouseMode(VGL_MOUSEHIDE);
235 VGLMouseXpos = mouseinfo.u.data.x;
236 VGLMouseYpos = mouseinfo.u.data.y;
237 __VGLMouseMode(mousemode);
239 VGLMouseButtons = mouseinfo.u.data.buttons;
242 * Loop to handle any new (suppressed) signals. This is INTON() without
243 * recursion. !SA_RESTART prevents recursion in signal handling. So the
244 * maximum recursion is 2 levels.
252 VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask)
256 mousemode = __VGLMouseMode(VGL_MOUSEHIDE);
258 VGLMouseAndMask = AndMask;
260 if (VGLMouseOrMask != NULL) {
261 free(VGLMouseOrMask->Bitmap);
262 free(VGLMouseOrMask);
264 VGLMouseOrMask = VGLBitmapCreate(MEMBUF, OrMask->VXsize, OrMask->VYsize, 0);
265 VGLBitmapAllocateBits(VGLMouseOrMask);
266 VGLBitmapCvt(OrMask, VGLMouseOrMask);
268 __VGLMouseMode(mousemode);
272 VGLMouseSetStdImage()
274 if (VGLDisplay->VXsize > 800)
275 VGLMouseSetImage(&VGLMouseLargeAndMask, &VGLMouseLargeOrMask);
277 VGLMouseSetImage(&VGLMouseSmallAndMask, &VGLMouseSmallOrMask);
281 VGLMouseInit(int mode)
283 struct mouse_info mouseinfo;
285 int border, error, i, interior;
287 switch (VGLModeInfo.vi_mem_model) {
288 case V_INFO_MM_PACKED:
289 case V_INFO_MM_PLANAR:
302 if (VGLModeInfo.vi_mode == M_BG640x480)
303 border = 0; /* XXX (palette makes 0x04 look like 0x0f) */
304 if (getenv("VGLMOUSEBORDERCOLOR") != NULL)
305 border = strtoul(getenv("VGLMOUSEBORDERCOLOR"), NULL, 0);
306 if (getenv("VGLMOUSEINTERIORCOLOR") != NULL)
307 interior = strtoul(getenv("VGLMOUSEINTERIORCOLOR"), NULL, 0);
308 ormask = &VGLMouseLargeOrMask;
309 for (i = 0; i < ormask->VXsize * ormask->VYsize; i++)
310 ormask->Bitmap[i] = ormask->Bitmap[i] == BORDER ? border :
311 ormask->Bitmap[i] == INTERIOR ? interior : 0;
312 ormask = &VGLMouseSmallOrMask;
313 for (i = 0; i < ormask->VXsize * ormask->VYsize; i++)
314 ormask->Bitmap[i] = ormask->Bitmap[i] == BORDER ? border :
315 ormask->Bitmap[i] == INTERIOR ? interior : 0;
316 VGLMouseSetStdImage();
317 mouseinfo.operation = MOUSE_MODE;
318 mouseinfo.u.mode.signal = SIGUSR2;
319 if ((error = ioctl(0, CONS_MOUSECTL, &mouseinfo)))
321 signal(SIGUSR2, VGLMouseAction);
322 mouseinfo.operation = MOUSE_GETINFO;
323 ioctl(0, CONS_MOUSECTL, &mouseinfo);
324 VGLMouseXpos = mouseinfo.u.data.x;
325 VGLMouseYpos = mouseinfo.u.data.y;
326 VGLMouseButtons = mouseinfo.u.data.buttons;
332 VGLMouseRestore(void)
334 struct mouse_info mouseinfo;
337 mouseinfo.operation = MOUSE_GETINFO;
338 if (ioctl(0, CONS_MOUSECTL, &mouseinfo) == 0) {
339 mouseinfo.operation = MOUSE_MOVEABS;
340 mouseinfo.u.data.x = VGLMouseXpos;
341 mouseinfo.u.data.y = VGLMouseYpos;
342 ioctl(0, CONS_MOUSECTL, &mouseinfo);
348 VGLMouseStatus(int *x, int *y, char *buttons)
353 *buttons = VGLMouseButtons;
355 return VGLMouseShown;
365 VGLMouseFreezeXY(int x, int y)
368 if (VGLMouseShown != VGL_MOUSESHOW)
370 if (x >= VGLMouseXpos && x < VGLMouseXpos + VGLMouseAndMask->VXsize &&
371 y >= VGLMouseYpos && y < VGLMouseYpos + VGLMouseAndMask->VYsize &&
372 VGLMouseAndMask->Bitmap[(y-VGLMouseYpos)*VGLMouseAndMask->VXsize+
379 VGLMouseOverlap(int x, int y, int width, int hight)
383 if (VGLMouseShown != VGL_MOUSESHOW)
385 if (x > VGLMouseXpos)
386 overlap = (VGLMouseXpos + VGLMouseAndMask->VXsize) - x;
388 overlap = (x + width) - VGLMouseXpos;
391 if (y > VGLMouseYpos)
392 overlap = (VGLMouseYpos + VGLMouseAndMask->VYsize) - y;
394 overlap = (y + hight) - VGLMouseYpos;
399 VGLMouseMerge(int x, int y, int width, byte *line)
401 int pos, x1, xend, xstart;
404 if (xstart < VGLMouseXpos)
405 xstart = VGLMouseXpos;
407 if (xend > VGLMouseXpos + VGLMouseAndMask->VXsize)
408 xend = VGLMouseXpos + VGLMouseAndMask->VXsize;
409 for (x1 = xstart; x1 < xend; x1++) {
410 pos = (y - VGLMouseYpos) * VGLMouseAndMask->VXsize + x1 - VGLMouseXpos;
411 if (VGLMouseAndMask->Bitmap[pos])
412 bcopy(&VGLMouseOrMask->Bitmap[pos * VGLDisplay->PixelBytes],
413 &line[(x1 - x) * VGLDisplay->PixelBytes], VGLDisplay->PixelBytes);