]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libvgl/mouse.c
Add a manpage for elf_aux_info(3)
[FreeBSD/FreeBSD.git] / lib / libvgl / mouse.c
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 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 */
45 #define B       BORDER
46 #define I       INTERIOR
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,
64 };
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,
82 };
83 #undef X
84 #undef B
85 #undef I
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;
98
99 #define INTOFF()        (VGLMsuppressint++)
100 #define INTON()         do {                                            \
101                                 if (--VGLMsuppressint == 0 && VGLMintpending) \
102                                         VGLMouseAction(0);              \
103                         } while (0)
104
105 void
106 VGLMousePointerShow()
107 {
108   byte buf[MOUSE_IMG_SIZE*MOUSE_IMG_SIZE*4];
109   VGLBitmap buffer =
110     VGLBITMAP_INITIALIZER(MEMBUF, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE, buf);
111   int pos;
112
113   if (!VGLMouseVisible) {
114     INTOFF();
115     VGLMouseVisible = 1;
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);
126     INTON();
127   }
128 }
129
130 void
131 VGLMousePointerHide()
132 {
133   if (VGLMouseVisible) {
134     INTOFF();
135     VGLMouseVisible = 0;
136     __VGLBitmapCopy(&VGLVDisplay, VGLMouseXpos, VGLMouseYpos, VGLDisplay, 
137                     VGLMouseXpos, VGLMouseYpos, MOUSE_IMG_SIZE, MOUSE_IMG_SIZE);
138     INTON();
139   }
140 }
141
142 void
143 VGLMouseMode(int mode)
144 {
145   if (mode == VGL_MOUSESHOW) {
146     if (VGLMouseShown == VGL_MOUSEHIDE) {
147       VGLMousePointerShow();
148       VGLMouseShown = VGL_MOUSESHOW;
149     }
150   }
151   else {
152     if (VGLMouseShown == VGL_MOUSESHOW) {
153       VGLMousePointerHide();
154       VGLMouseShown = VGL_MOUSEHIDE;
155     }
156   }
157 }
158
159 void
160 VGLMouseAction(int dummy)       
161 {
162   struct mouse_info mouseinfo;
163
164   if (VGLMsuppressint) {
165     VGLMintpending = 1;
166     return;
167   }
168 again:
169   INTOFF();
170   VGLMintpending = 0;
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();
180
181   /* 
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.
185    */
186   VGLMsuppressint = 0;
187   if (VGLMintpending)
188     goto again;
189 }
190
191 void
192 VGLMouseSetImage(VGLBitmap *AndMask, VGLBitmap *OrMask)
193 {
194   if (VGLMouseShown == VGL_MOUSESHOW)
195     VGLMousePointerHide();
196
197   VGLMouseAndMask = AndMask;
198
199   if (VGLMouseOrMask != NULL) {
200     free(VGLMouseOrMask->Bitmap);
201     free(VGLMouseOrMask);
202   }
203   VGLMouseOrMask = VGLBitmapCreate(MEMBUF, OrMask->VXsize, OrMask->VYsize, 0);
204   VGLBitmapAllocateBits(VGLMouseOrMask);
205   VGLBitmapCvt(OrMask, VGLMouseOrMask);
206
207   if (VGLMouseShown == VGL_MOUSESHOW)
208     VGLMousePointerShow();
209 }
210
211 void
212 VGLMouseSetStdImage()
213 {
214   VGLMouseSetImage(&VGLMouseStdAndMask, &VGLMouseStdOrMask);
215 }
216
217 int
218 VGLMouseInit(int mode)
219 {
220   struct mouse_info mouseinfo;
221   int andmask, border, error, i, interior;
222
223   switch (VGLModeInfo.vi_mem_model) {
224   case V_INFO_MM_PACKED:
225   case V_INFO_MM_PLANAR:
226     andmask = 0x0f;
227     border = 0x0f;
228     interior = 0x04;
229     break;
230   case V_INFO_MM_VGAX:
231     andmask = 0x3f;
232     border = 0x3f;
233     interior = 0x24;
234     break;
235   default:
236     andmask = 0xff;
237     border = BORDER;
238     interior = INTERIOR;
239     break;
240   }
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)))
254     return error;
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;
261   VGLMouseMode(mode);
262   return 0;
263 }
264
265 void
266 VGLMouseRestore(void)
267 {
268   struct mouse_info mouseinfo;
269
270   INTOFF();
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);
277   }
278   INTON();
279 }
280
281 int
282 VGLMouseStatus(int *x, int *y, char *buttons)
283 {
284   INTOFF();
285   *x =  VGLMouseXpos;
286   *y =  VGLMouseYpos;
287   *buttons =  VGLMouseButtons;
288   INTON();
289   return VGLMouseShown;
290 }
291
292 void
293 VGLMouseFreeze(void)
294 {
295   INTOFF();
296 }
297
298 int
299 VGLMouseFreezeXY(int x, int y)
300 {
301   INTOFF();
302   if (VGLMouseShown != VGL_MOUSESHOW)
303     return 0;
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)])
307     return 1;
308   return 0;
309 }
310
311 int
312 VGLMouseOverlap(int x, int y, int width, int hight)
313 {
314   int overlap;
315
316   if (VGLMouseShown != VGL_MOUSESHOW)
317     return 0;
318   if (x > VGLMouseXpos)
319     overlap = (VGLMouseXpos + MOUSE_IMG_SIZE) - x;
320   else
321     overlap = (x + width) - VGLMouseXpos;
322   if (overlap <= 0)
323     return 0;
324   if (y > VGLMouseYpos)
325     overlap = (VGLMouseYpos + MOUSE_IMG_SIZE) - y;
326   else
327     overlap = (y + hight) - VGLMouseYpos;
328   return overlap > 0;
329 }
330
331 void
332 VGLMouseMerge(int x, int y, int width, byte *line)
333 {
334   int pos, x1, xend, xstart;
335
336   xstart = x;
337   if (xstart < VGLMouseXpos)
338     xstart = VGLMouseXpos;
339   xend = x + width;
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);
347   }
348 }
349
350 void
351 VGLMouseUnFreeze()
352 {
353   INTON();
354 }