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*4]; 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*4]; 99 VGLBitmap buffer = 100 VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, buf); 101 byte crtcidx, crtcval, gdcidx, gdcval; 102 int i, pos, pos1; 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, 113 MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*VGLDisplay->PixelBytes); 114 for (pos = 0; pos < MOUSE_IMG_SIZE*MOUSE_IMG_SIZE; pos++) 115 for (i = 0; i < VGLDisplay->PixelBytes; i++) { 116 pos1 = pos * VGLDisplay->PixelBytes + i; 117 buffer.Bitmap[pos1] = (buffer.Bitmap[pos1] & 118 ~VGLMouseAndMask->Bitmap[pos]) | 119 VGLMouseOrMask->Bitmap[pos]; 120 } 121 __VGLBitmapCopy(&buffer, 0, 0, VGLDisplay, 122 VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE); 123 outb(0x3c4, crtcidx); 124 outb(0x3c5, crtcval); 125 outb(0x3ce, gdcidx); 126 outb(0x3cf, gdcval); 127 } 128 } 129 130 void 131 VGLMousePointerHide() 132 { 133 byte crtcidx, crtcval, gdcidx, gdcval; 134 135 if (VGLMouseVisible) { 136 VGLMouseVisible = 0; 137 crtcidx = inb(0x3c4); 138 crtcval = inb(0x3c5); 139 gdcidx = inb(0x3ce); 140 gdcval = inb(0x3cf); 141 __VGLBitmapCopy(&VGLMouseSave, 0, 0, VGLDisplay, 142 VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE); 143 outb(0x3c4, crtcidx); 144 outb(0x3c5, crtcval); 145 outb(0x3ce, gdcidx); 146 outb(0x3cf, gdcval); 147 } 148 } 149 150 void 151 VGLMouseMode(int mode) 152 { 153 if (mode == VGL_MOUSESHOW) { 154 if (VGLMouseShown == VGL_MOUSEHIDE) { 155 VGLMousePointerShow(); 156 VGLMouseShown = VGL_MOUSESHOW; 157 } 158 } 159 else { 160 if (VGLMouseShown == VGL_MOUSESHOW) { 161 VGLMousePointerHide(); 162 VGLMouseShown = VGL_MOUSEHIDE; 163 } 164 } 165 } 166 167 void 168 VGLMouseAction(int dummy) 169 { 170 struct mouse_info mouseinfo; 171 172 if (VGLMouseFrozen) { 173 VGLMouseFrozen++; 174 return; 175 } 176 mouseinfo.operation = MOUSE_GETINFO; 177 ioctl(0, CONS_MOUSECTL, &mouseinfo); 178 if (VGLMouseShown == VGL_MOUSESHOW) 179 VGLMousePointerHide(); 180 VGLMouseXpos = mouseinfo.u.data.x; 181 VGLMouseYpos = mouseinfo.u.data.y; 182 VGLMouseButtons = mouseinfo.u.data.buttons; 183 if (VGLMouseShown == VGL_MOUSESHOW) 184 VGLMousePointerShow(); 185 } 186 187 void 188 VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask) 189 { 190 if (VGLMouseShown == VGL_MOUSESHOW) 191 VGLMousePointerHide(); 192 VGLMouseAndMask = AndMask; 193 VGLMouseOrMask = OrMask; 194 if (VGLMouseShown == VGL_MOUSESHOW) 195 VGLMousePointerShow(); 196 } 197 198 void 199 VGLMouseSetStdImage() 200 { 201 if (VGLMouseShown == VGL_MOUSESHOW) 202 VGLMousePointerHide(); 203 VGLMouseAndMask = &VGLMouseStdAndMask; 204 VGLMouseOrMask = &VGLMouseStdOrMask; 205 if (VGLMouseShown == VGL_MOUSESHOW) 206 VGLMousePointerShow(); 207 } 208 209 int 210 VGLMouseInit(int mode) 211 { 212 struct mouse_info mouseinfo; 213 int error, i, mask; 214 215 switch (VGLModeInfo.vi_mem_model) { 216 case V_INFO_MM_PACKED: 217 case V_INFO_MM_PLANAR: 218 mask = 0x0f; 219 break; 220 case V_INFO_MM_VGAX: 221 mask = 0x3f; 222 break; 223 default: 224 mask = 0xff; 225 break; 226 } 227 for (i = 0; i < 256; i++) 228 VGLMouseStdOrMask.Bitmap[i] &= mask; 229 VGLMouseSetStdImage(); 230 mouseinfo.operation = MOUSE_MODE; 231 mouseinfo.u.mode.signal = SIGUSR2; 232 if ((error = ioctl(0, CONS_MOUSECTL, &mouseinfo))) 233 return error; 234 signal(SIGUSR2, VGLMouseAction); 235 mouseinfo.operation = MOUSE_GETINFO; 236 ioctl(0, CONS_MOUSECTL, &mouseinfo); 237 VGLMouseXpos = mouseinfo.u.data.x; 238 VGLMouseYpos = mouseinfo.u.data.y; 239 VGLMouseButtons = mouseinfo.u.data.buttons; 240 VGLMouseMode(mode); 241 return 0; 242 } 243 244 int 245 VGLMouseStatus(int *x, int *y, char *buttons) 246 { 247 signal(SIGUSR2, SIG_IGN); 248 *x = VGLMouseXpos; 249 *y = VGLMouseYpos; 250 *buttons = VGLMouseButtons; 251 signal(SIGUSR2, VGLMouseAction); 252 return VGLMouseShown; 253 } 254 255 int 256 VGLMouseFreeze(int x, int y, int width, int hight, u_long color) 257 { 258 int i, xstride, ystride; 259 260 if (!VGLMouseFrozen) { 261 VGLMouseFrozen = 1; 262 if (width > 1 || hight > 1) { /* bitmap */ 263 if (VGLMouseShown == 1) { 264 int overlap; 265 266 if (x > VGLMouseXpos) 267 overlap = (VGLMouseXpos + MOUSE_IMG_SIZE) - x; 268 else 269 overlap = (x + width) - VGLMouseXpos; 270 if (overlap > 0) { 271 if (y > VGLMouseYpos) 272 overlap = (VGLMouseYpos + MOUSE_IMG_SIZE) - y; 273 else 274 overlap = (y + hight) - VGLMouseYpos; 275 if (overlap > 0) 276 VGLMousePointerHide(); 277 } 278 } 279 } 280 else { /* bit */ 281 if (VGLMouseShown && 282 x >= VGLMouseXpos && x < VGLMouseXpos + MOUSE_IMG_SIZE && 283 y >= VGLMouseYpos && y < VGLMouseYpos + MOUSE_IMG_SIZE) { 284 xstride = VGLDisplay->PixelBytes; 285 ystride = MOUSE_IMG_SIZE * xstride; 286 for (i = 0; i < xstride; i++, color >>= 8) 287 VGLMouseSave.Bitmap[(y-VGLMouseYpos)*ystride+ 288 (x-VGLMouseXpos)*xstride+i] = color; 289 if (VGLMouseAndMask->Bitmap 290 [(y-VGLMouseYpos)*MOUSE_IMG_SIZE+(x-VGLMouseXpos)]) { 291 return 1; 292 } 293 } 294 } 295 } 296 return 0; 297 } 298 299 void 300 VGLMouseUnFreeze() 301 { 302 if (VGLMouseFrozen > 1) { 303 VGLMouseFrozen = 0; 304 VGLMouseAction(0); 305 } 306 else { 307 VGLMouseFrozen = 0; 308 if (VGLMouseShown == VGL_MOUSESHOW && !VGLMouseVisible) 309 VGLMousePointerShow(); 310 } 311 } 312