diff options
Diffstat (limited to 'lib/libvgl/mouse.c')
-rw-r--r-- | lib/libvgl/mouse.c | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/lib/libvgl/mouse.c b/lib/libvgl/mouse.c new file mode 100644 index 000000000000..c4019fd7606f --- /dev/null +++ b/lib/libvgl/mouse.c @@ -0,0 +1,421 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1991-1997 Søren Schmidt + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/signal.h> +#include <sys/consio.h> +#include <sys/fbio.h> +#include "vgl.h" + +static void VGLMouseAction(int dummy); + +#define BORDER 0xff /* default border -- light white in rgb 3:3:2 */ +#define INTERIOR 0xa0 /* default interior -- red in rgb 3:3:2 */ +#define LARGE_MOUSE_IMG_XSIZE 19 +#define LARGE_MOUSE_IMG_YSIZE 32 +#define SMALL_MOUSE_IMG_XSIZE 10 +#define SMALL_MOUSE_IMG_YSIZE 16 +#define X 0xff /* any nonzero in And mask means part of cursor */ +#define B BORDER +#define I INTERIOR +static byte LargeAndMask[] = { + X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0,0, + X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0,0, + X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0,0, + X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0,0, + X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0,0, + X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0,0, + X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0, + X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0, + X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0, + X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0, + X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0,0, + X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0,0, + X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,0, + X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, + X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X, + X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0, + X,X,X,X,X,X,X,X,X,X,X,X,0,0,0,0,0,0,0, + X,X,X,X,X,X,0,X,X,X,X,X,X,0,0,0,0,0,0, + X,X,X,X,X,0,0,X,X,X,X,X,X,0,0,0,0,0,0, + X,X,X,X,0,0,0,0,X,X,X,X,X,X,0,0,0,0,0, + X,X,X,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0,0, + X,X,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0, + 0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0, + 0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0, + 0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,X,X,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,X,X,X,X,0,0,0, +}; +static byte LargeOrMask[] = { + B,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + B,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + B,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + B,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + B,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0,0, + B,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0,0, + B,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0,0, + B,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0,0, + B,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0,0, + B,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0,0, + B,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0, + B,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0, + B,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0, + B,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0, + B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0,0, + B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0,0, + B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B,0, + B,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,I,B, + B,I,I,I,I,I,I,I,I,I,I,B,B,B,B,B,B,B,B, + B,I,I,I,I,I,I,I,I,I,I,B,0,0,0,0,0,0,0, + B,I,I,I,I,I,B,I,I,I,I,B,0,0,0,0,0,0,0, + B,I,I,I,I,B,0,B,I,I,I,I,B,0,0,0,0,0,0, + B,I,I,I,B,0,0,B,I,I,I,I,B,0,0,0,0,0,0, + B,I,I,B,0,0,0,0,B,I,I,I,I,B,0,0,0,0,0, + B,I,B,0,0,0,0,0,B,I,I,I,I,B,0,0,0,0,0, + B,B,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0,0, + 0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0, + 0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0, + 0,0,0,0,0,0,0,0,0,0,0,B,I,I,I,I,B,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,B,B,B,B,0,0,0, +}; +static byte SmallAndMask[] = { + X,X,0,0,0,0,0,0,0,0, + X,X,X,0,0,0,0,0,0,0, + X,X,X,X,0,0,0,0,0,0, + X,X,X,X,X,0,0,0,0,0, + X,X,X,X,X,X,0,0,0,0, + X,X,X,X,X,X,X,0,0,0, + X,X,X,X,X,X,X,X,0,0, + X,X,X,X,X,X,X,X,X,0, + X,X,X,X,X,X,X,X,X,X, + X,X,X,X,X,X,X,X,X,X, + X,X,X,X,X,X,X,0,0,0, + X,X,X,0,X,X,X,X,0,0, + X,X,0,0,X,X,X,X,0,0, + 0,0,0,0,0,X,X,X,X,0, + 0,0,0,0,0,X,X,X,X,0, + 0,0,0,0,0,0,X,X,0,0, +}; +static byte SmallOrMask[] = { + B,B,0,0,0,0,0,0,0,0, + B,I,B,0,0,0,0,0,0,0, + B,I,I,B,0,0,0,0,0,0, + B,I,I,I,B,0,0,0,0,0, + B,I,I,I,I,B,0,0,0,0, + B,I,I,I,I,I,B,0,0,0, + B,I,I,I,I,I,I,B,0,0, + B,I,I,I,I,I,I,I,B,0, + B,I,I,I,I,I,I,I,I,B, + B,I,I,I,I,I,B,B,B,B, + B,I,I,B,I,I,B,0,0,0, + B,I,B,0,B,I,I,B,0,0, + B,B,0,0,B,I,I,B,0,0, + 0,0,0,0,0,B,I,I,B,0, + 0,0,0,0,0,B,I,I,B,0, + 0,0,0,0,0,0,B,B,0,0, +}; +#undef X +#undef B +#undef I +static VGLBitmap VGLMouseLargeAndMask = + VGLBITMAP_INITIALIZER(MEMBUF, LARGE_MOUSE_IMG_XSIZE, LARGE_MOUSE_IMG_YSIZE, + LargeAndMask); +static VGLBitmap VGLMouseLargeOrMask = + VGLBITMAP_INITIALIZER(MEMBUF, LARGE_MOUSE_IMG_XSIZE, LARGE_MOUSE_IMG_YSIZE, + LargeOrMask); +static VGLBitmap VGLMouseSmallAndMask = + VGLBITMAP_INITIALIZER(MEMBUF, SMALL_MOUSE_IMG_XSIZE, SMALL_MOUSE_IMG_YSIZE, + SmallAndMask); +static VGLBitmap VGLMouseSmallOrMask = + VGLBITMAP_INITIALIZER(MEMBUF, SMALL_MOUSE_IMG_XSIZE, SMALL_MOUSE_IMG_YSIZE, + SmallOrMask); +static VGLBitmap *VGLMouseAndMask, *VGLMouseOrMask; +static int VGLMouseShown = VGL_MOUSEHIDE; +static int VGLMouseXpos = 0; +static int VGLMouseYpos = 0; +static int VGLMouseButtons = 0; +static volatile sig_atomic_t VGLMintpending; +static volatile sig_atomic_t VGLMsuppressint; + +#define INTOFF() (VGLMsuppressint++) +#define INTON() do { \ + if (--VGLMsuppressint == 0 && VGLMintpending) \ + VGLMouseAction(0); \ + } while (0) + +int +__VGLMouseMode(int mode) +{ + int oldmode; + + INTOFF(); + oldmode = VGLMouseShown; + if (mode == VGL_MOUSESHOW) { + if (VGLMouseShown == VGL_MOUSEHIDE) { + VGLMouseShown = VGL_MOUSESHOW; + __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos, + VGLDisplay, VGLMouseXpos, VGLMouseYpos, + VGLMouseAndMask->VXsize, -VGLMouseAndMask->VYsize); + } + } + else { + if (VGLMouseShown == VGL_MOUSESHOW) { + VGLMouseShown = VGL_MOUSEHIDE; + __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos, + VGLDisplay, VGLMouseXpos, VGLMouseYpos, + VGLMouseAndMask->VXsize, VGLMouseAndMask->VYsize); + } + } + INTON(); + return oldmode; +} + +void +VGLMouseMode(int mode) +{ + __VGLMouseMode(mode); +} + +static void +VGLMouseAction(int dummy) +{ + struct mouse_info mouseinfo; + int mousemode; + + if (VGLMsuppressint) { + VGLMintpending = 1; + return; + } +again: + INTOFF(); + VGLMintpending = 0; + mouseinfo.operation = MOUSE_GETINFO; + ioctl(0, CONS_MOUSECTL, &mouseinfo); + if (VGLMouseXpos != mouseinfo.u.data.x || + VGLMouseYpos != mouseinfo.u.data.y) { + mousemode = __VGLMouseMode(VGL_MOUSEHIDE); + VGLMouseXpos = mouseinfo.u.data.x; + VGLMouseYpos = mouseinfo.u.data.y; + __VGLMouseMode(mousemode); + } + VGLMouseButtons = mouseinfo.u.data.buttons; + + /* + * Loop to handle any new (suppressed) signals. This is INTON() without + * recursion. !SA_RESTART prevents recursion in signal handling. So the + * maximum recursion is 2 levels. + */ + VGLMsuppressint = 0; + if (VGLMintpending) + goto again; +} + +void +VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask) +{ + int mousemode; + + mousemode = __VGLMouseMode(VGL_MOUSEHIDE); + + VGLMouseAndMask = AndMask; + + if (VGLMouseOrMask != NULL) { + free(VGLMouseOrMask->Bitmap); + free(VGLMouseOrMask); + } + VGLMouseOrMask = VGLBitmapCreate(MEMBUF, OrMask->VXsize, OrMask->VYsize, 0); + VGLBitmapAllocateBits(VGLMouseOrMask); + VGLBitmapCvt(OrMask, VGLMouseOrMask); + + __VGLMouseMode(mousemode); +} + +void +VGLMouseSetStdImage() +{ + if (VGLDisplay->VXsize > 800) + VGLMouseSetImage(&VGLMouseLargeAndMask, &VGLMouseLargeOrMask); + else + VGLMouseSetImage(&VGLMouseSmallAndMask, &VGLMouseSmallOrMask); +} + +int +VGLMouseInit(int mode) +{ + struct mouse_info mouseinfo; + VGLBitmap *ormask; + int border, error, i, interior; + + switch (VGLModeInfo.vi_mem_model) { + case V_INFO_MM_PACKED: + case V_INFO_MM_PLANAR: + border = 0x0f; + interior = 0x04; + break; + case V_INFO_MM_VGAX: + border = 0x3f; + interior = 0x24; + break; + default: + border = BORDER; + interior = INTERIOR; + break; + } + if (VGLModeInfo.vi_mode == M_BG640x480) + border = 0; /* XXX (palette makes 0x04 look like 0x0f) */ + if (getenv("VGLMOUSEBORDERCOLOR") != NULL) + border = strtoul(getenv("VGLMOUSEBORDERCOLOR"), NULL, 0); + if (getenv("VGLMOUSEINTERIORCOLOR") != NULL) + interior = strtoul(getenv("VGLMOUSEINTERIORCOLOR"), NULL, 0); + ormask = &VGLMouseLargeOrMask; + for (i = 0; i < ormask->VXsize * ormask->VYsize; i++) + ormask->Bitmap[i] = ormask->Bitmap[i] == BORDER ? border : + ormask->Bitmap[i] == INTERIOR ? interior : 0; + ormask = &VGLMouseSmallOrMask; + for (i = 0; i < ormask->VXsize * ormask->VYsize; i++) + ormask->Bitmap[i] = ormask->Bitmap[i] == BORDER ? border : + ormask->Bitmap[i] == INTERIOR ? interior : 0; + VGLMouseSetStdImage(); + mouseinfo.operation = MOUSE_MODE; + mouseinfo.u.mode.signal = SIGUSR2; + if ((error = ioctl(0, CONS_MOUSECTL, &mouseinfo))) + return error; + signal(SIGUSR2, VGLMouseAction); + mouseinfo.operation = MOUSE_GETINFO; + ioctl(0, CONS_MOUSECTL, &mouseinfo); + VGLMouseXpos = mouseinfo.u.data.x; + VGLMouseYpos = mouseinfo.u.data.y; + VGLMouseButtons = mouseinfo.u.data.buttons; + VGLMouseMode(mode); + return 0; +} + +void +VGLMouseRestore(void) +{ + struct mouse_info mouseinfo; + + INTOFF(); + mouseinfo.operation = MOUSE_GETINFO; + if (ioctl(0, CONS_MOUSECTL, &mouseinfo) == 0) { + mouseinfo.operation = MOUSE_MOVEABS; + mouseinfo.u.data.x = VGLMouseXpos; + mouseinfo.u.data.y = VGLMouseYpos; + ioctl(0, CONS_MOUSECTL, &mouseinfo); + } + INTON(); +} + +int +VGLMouseStatus(int *x, int *y, char *buttons) +{ + INTOFF(); + *x = VGLMouseXpos; + *y = VGLMouseYpos; + *buttons = VGLMouseButtons; + INTON(); + return VGLMouseShown; +} + +void +VGLMouseFreeze(void) +{ + INTOFF(); +} + +int +VGLMouseFreezeXY(int x, int y) +{ + INTOFF(); + if (VGLMouseShown != VGL_MOUSESHOW) + return 0; + if (x >= VGLMouseXpos && x < VGLMouseXpos + VGLMouseAndMask->VXsize && + y >= VGLMouseYpos && y < VGLMouseYpos + VGLMouseAndMask->VYsize && + VGLMouseAndMask->Bitmap[(y-VGLMouseYpos)*VGLMouseAndMask->VXsize+ + (x-VGLMouseXpos)]) + return 1; + return 0; +} + +int +VGLMouseOverlap(int x, int y, int width, int hight) +{ + int overlap; + + if (VGLMouseShown != VGL_MOUSESHOW) + return 0; + if (x > VGLMouseXpos) + overlap = (VGLMouseXpos + VGLMouseAndMask->VXsize) - x; + else + overlap = (x + width) - VGLMouseXpos; + if (overlap <= 0) + return 0; + if (y > VGLMouseYpos) + overlap = (VGLMouseYpos + VGLMouseAndMask->VYsize) - y; + else + overlap = (y + hight) - VGLMouseYpos; + return overlap > 0; +} + +void +VGLMouseMerge(int x, int y, int width, byte *line) +{ + int pos, x1, xend, xstart; + + xstart = x; + if (xstart < VGLMouseXpos) + xstart = VGLMouseXpos; + xend = x + width; + if (xend > VGLMouseXpos + VGLMouseAndMask->VXsize) + xend = VGLMouseXpos + VGLMouseAndMask->VXsize; + for (x1 = xstart; x1 < xend; x1++) { + pos = (y - VGLMouseYpos) * VGLMouseAndMask->VXsize + x1 - VGLMouseXpos; + if (VGLMouseAndMask->Bitmap[pos]) + bcopy(&VGLMouseOrMask->Bitmap[pos * VGLDisplay->PixelBytes], + &line[(x1 - x) * VGLDisplay->PixelBytes], VGLDisplay->PixelBytes); + } +} + +void +VGLMouseUnFreeze() +{ + INTON(); +} |