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 #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 X 0xff /* any nonzero in And mask means part of cursor */
47 static byte StdAndMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
48 X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
49 X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,
50 X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,
51 X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,
52 X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,
53 X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
54 X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,
55 X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,
56 X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
57 X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,
58 X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,
59 X,X,X,0,X,X,X,X,0,0,0,0,0,0,0,0,
60 X,X,0,0,X,X,X,X,0,0,0,0,0,0,0,0,
61 0,0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,
62 0,0,0,0,0,X,X,X,X,0,0,0,0,0,0,0,
63 0,0,0,0,0,0,X,X,0,0,0,0,0,0,0,0,
65 static byte StdOrMask[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE] = {
66 B,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
67 B,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,
68 B,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,
69 B,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,
70 B,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,
71 B,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,
72 B,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,
73 B,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,
74 B,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,
75 B,I,I,I,I,I,B,B,B,B,0,0,0,0,0,0,
76 B,I,I,B,I,I,B,0,0,0,0,0,0,0,0,0,
77 B,I,B,0,B,I,I,B,0,0,0,0,0,0,0,0,
78 B,B,0,0,B,I,I,B,0,0,0,0,0,0,0,0,
79 0,0,0,0,0,B,I,I,B,0,0,0,0,0,0,0,
80 0,0,0,0,0,B,I,I,B,0,0,0,0,0,0,0,
81 0,0,0,0,0,0,B,B,0,0,0,0,0,0,0,0,
86 static VGLBitmap VGLMouseStdAndMask =
87 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdAndMask);
88 static VGLBitmap VGLMouseStdOrMask =
89 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, StdOrMask);
90 static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask;
91 static int VGLMouseVisible = 0;
92 static int VGLMouseShown = VGL_MOUSEHIDE;
93 static int VGLMouseXpos = 0;
94 static int VGLMouseYpos = 0;
95 static int VGLMouseButtons = 0;
96 static volatile sig_atomic_t VGLMintpending;
97 static volatile sig_atomic_t VGLMsuppressint;
99 #define INTOFF() (VGLMsuppressint++)
100 #define INTON() do { \
101 if (--VGLMsuppressint == 0 && VGLMintpending) \
106 VGLMousePointerShow()
108 byte buf[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*4];
110 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, buf);
113 if (!VGLMouseVisible) {
116 buffer.PixelBytes = VGLDisplay->PixelBytes;
117 __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos,
118 &buffer, 0, 0, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
119 for (pos = 0; pos < MOUSE_IMG_SIZE*MOUSE_IMG_SIZE; pos++)
120 if (VGLMouseAndMask->Bitmap[pos])
121 bcopy(&VGLMouseOrMask->Bitmap[pos*VGLDisplay->PixelBytes],
122 &buffer.Bitmap[pos*VGLDisplay->PixelBytes],
123 VGLDisplay->PixelBytes);
124 __VGLBitmapCopy(&buffer, 0, 0, VGLDisplay,
125 VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
131 VGLMousePointerHide()
133 if (VGLMouseVisible) {
136 __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos, VGLDisplay,
137 VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
143 VGLMouseMode(int mode)
145 if (mode == VGL_MOUSESHOW) {
146 if (VGLMouseShown == VGL_MOUSEHIDE) {
147 VGLMousePointerShow();
148 VGLMouseShown = VGL_MOUSESHOW;
152 if (VGLMouseShown == VGL_MOUSESHOW) {
153 VGLMousePointerHide();
154 VGLMouseShown = VGL_MOUSEHIDE;
160 VGLMouseAction(int dummy)
162 struct mouse_info mouseinfo;
164 if (VGLMsuppressint) {
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();
182 * Loop to handle any new (suppressed) signals. This is INTON() without
183 * recursion. !SA_RESTART prevents recursion in signal handling. So the
184 * maximum recursion is 2 levels.
192 VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask)
194 if (VGLMouseShown == VGL_MOUSESHOW)
195 VGLMousePointerHide();
197 VGLMouseAndMask = AndMask;
199 if (VGLMouseOrMask != NULL) {
200 free(VGLMouseOrMask->Bitmap);
201 free(VGLMouseOrMask);
203 VGLMouseOrMask = VGLBitmapCreate(MEMBUF, OrMask->VXsize, OrMask->VYsize, 0);
204 VGLBitmapAllocateBits(VGLMouseOrMask);
205 VGLBitmapCvt(OrMask, VGLMouseOrMask);
207 if (VGLMouseShown == VGL_MOUSESHOW)
208 VGLMousePointerShow();
212 VGLMouseSetStdImage()
214 VGLMouseSetImage(&VGLMouseStdAndMask, &VGLMouseStdOrMask);
218 VGLMouseInit(int mode)
220 struct mouse_info mouseinfo;
221 int andmask, border, error, i, interior;
223 switch (VGLModeInfo.vi_mem_model) {
224 case V_INFO_MM_PACKED:
225 case V_INFO_MM_PLANAR:
241 if (VGLModeInfo.vi_mode == M_BG640x480)
242 border = 0; /* XXX (palette makes 0x04 look like 0x0f) */
243 if (getenv("VGLMOUSEBORDERCOLOR") != NULL)
244 border = strtoul(getenv("VGLMOUSEBORDERCOLOR"), NULL, 0);
245 if (getenv("VGLMOUSEINTERIORCOLOR") != NULL)
246 interior = strtoul(getenv("VGLMOUSEINTERIORCOLOR"), NULL, 0);
247 for (i = 0; i < MOUSE_IMG_SIZE*MOUSE_IMG_SIZE; i++)
248 VGLMouseStdOrMask.Bitmap[i] = VGLMouseStdOrMask.Bitmap[i] == BORDER ?
249 border : VGLMouseStdOrMask.Bitmap[i] == INTERIOR ? interior : 0;
250 VGLMouseSetStdImage();
251 mouseinfo.operation = MOUSE_MODE;
252 mouseinfo.u.mode.signal = SIGUSR2;
253 if ((error = ioctl(0, CONS_MOUSECTL, &mouseinfo)))
255 signal(SIGUSR2, VGLMouseAction);
256 mouseinfo.operation = MOUSE_GETINFO;
257 ioctl(0, CONS_MOUSECTL, &mouseinfo);
258 VGLMouseXpos = mouseinfo.u.data.x;
259 VGLMouseYpos = mouseinfo.u.data.y;
260 VGLMouseButtons = mouseinfo.u.data.buttons;
266 VGLMouseRestore(void)
268 struct mouse_info mouseinfo;
271 mouseinfo.operation = MOUSE_GETINFO;
272 if (ioctl(0, CONS_MOUSECTL, &mouseinfo) == 0) {
273 mouseinfo.operation = MOUSE_MOVEABS;
274 mouseinfo.u.data.x = VGLMouseXpos;
275 mouseinfo.u.data.y = VGLMouseYpos;
276 ioctl(0, CONS_MOUSECTL, &mouseinfo);
282 VGLMouseStatus(int *x, int *y, char *buttons)
287 *buttons = VGLMouseButtons;
289 return VGLMouseShown;
299 VGLMouseFreezeXY(int x, int y)
302 if (VGLMouseShown != VGL_MOUSESHOW)
304 if (x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE &&
305 y >= VGLMouseYpos && y < VGLMouseYpos + MOUSE_IMG_SIZE &&
306 VGLMouseAndMask->Bitmap[(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)])
312 VGLMouseOverlap(int x, int y, int width, int hight)
316 if (VGLMouseShown != VGL_MOUSESHOW)
318 if (x > VGLMouseXpos)
319 overlap = (VGLMouseXpos + MOUSE_IMG_SIZE) - x;
321 overlap = (x + width) - VGLMouseXpos;
324 if (y > VGLMouseYpos)
325 overlap = (VGLMouseYpos + MOUSE_IMG_SIZE) - y;
327 overlap = (y + hight) - VGLMouseYpos;
332 VGLMouseMerge(int x, int y, int width, byte *line)
334 int pos, x1, xend, xstart;
337 if (xstart < VGLMouseXpos)
338 xstart = VGLMouseXpos;
340 if (xend > VGLMouseXpos + MOUSE_IMG_SIZE)
341 xend = VGLMouseXpos + MOUSE_IMG_SIZE;
342 for (x1 = xstart; x1 < xend; x1++) {
343 pos = (y - VGLMouseYpos) * MOUSE_IMG_SIZE + x1 - VGLMouseXpos;
344 if (VGLMouseAndMask->Bitmap[pos])
345 bcopy(&VGLMouseOrMask->Bitmap[pos * VGLDisplay->PixelBytes],
346 &line[(x1 - x) * VGLDisplay->PixelBytes], VGLDisplay->PixelBytes);