x68kMouse.c revision d8389a6e
1/* $NetBSD: x68kMouse.c,v 1.13 2025/06/17 15:55:03 tsutsui Exp $ */
2/*-------------------------------------------------------------------------
3 * Copyright (c) 1996 Yasushi Yamasaki
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *-----------------------------------------------------------------------*/
26
27/*-
28 * Copyright (c) 1987 by the Regents of the University of California
29 *
30 * Permission to use, copy, modify, and distribute this
31 * software and its documentation for any purpose and without
32 * fee is hereby granted, provided that the above copyright
33 * notice appear in all copies.  The University of California
34 * makes no representations about the suitability of this
35 * software for any purpose.  It is provided "as is" without
36 * express or implied warranty.
37 */
38
39/************************************************************
40Copyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
41
42                    All Rights Reserved
43
44Permission  to  use,  copy,  modify,  and  distribute   this
45software  and  its documentation for any purpose and without
46fee is hereby granted, provided that the above copyright no-
47tice  appear  in all copies and that both that copyright no-
48tice and this permission notice appear in  supporting  docu-
49mentation,  and  that the names of Sun or X Consortium
50not be used in advertising or publicity pertaining to
51distribution  of  the software  without specific prior
52written permission. Sun and X Consortium make no
53representations about the suitability of this software for
54any purpose. It is provided "as is" without any express or
55implied warranty.
56
57SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
58INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
59NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
60ABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
61ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
62PROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
63OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
64THE USE OR PERFORMANCE OF THIS SOFTWARE.
65
66********************************************************/
67/*
68 * Copyright 1991, 1992, 1993 Kaleb S. Keithley
69 *
70 * Permission to use, copy, modify, and distribute this
71 * software and its documentation for any purpose and without
72 * fee is hereby granted, provided that the above copyright
73 * notice appear in all copies.  Kaleb S. Keithley makes no
74 * representations about the suitability of this software for
75 * any purpose.  It is provided "as is" without express or
76 * implied warranty.
77 */
78
79#include "x68k.h"
80#include "mi.h"
81#include "input.h"
82#include "inpututils.h"
83
84#include "exevents.h"
85#include "events.h"
86#include "eventstr.h"
87#include <X11/Xatom.h>
88#include "xserver-properties.h"
89
90static void x68kMouseHandlerNotify(int, int, void *);
91static Bool x68kCursorOffScreen(ScreenPtr *, int *, int *);
92static void x68kCrossScreen(ScreenPtr, int);
93static void x68kWarpCursor(DeviceIntPtr, ScreenPtr, int, int);
94static void x68kMouseCtrl(DeviceIntPtr, PtrCtrl*);
95
96miPointerScreenFuncRec x68kPointerScreenFuncs = {
97    x68kCursorOffScreen,
98    x68kCrossScreen,
99    x68kWarpCursor,
100};
101
102DeviceIntPtr x68kPointerDevice = NULL;
103
104static X68kMousePriv x68kMousePriv;
105
106static void
107x68kMouseHandlerNotify(int fd __unused, int ready __unused, void *data __unused)
108{
109}
110
111/*-
112 *-----------------------------------------------------------------------
113 * x68kMouseProc --
114 *	Handle the initialization, etc. of a mouse
115 *
116 * Results:
117 *	none.
118 *
119 * Side Effects:
120 *-----------------------------------------------------------------------
121 */
122int
123x68kMouseProc(DeviceIntPtr device, int what)
124{
125    DevicePtr   pMouse = &device->public;
126    int		format;
127    static int	oformat;
128    BYTE	map[4];
129    Atom btn_labels[3] = {0};
130    Atom axes_labels[2] = { 0, 0 };
131    MouseEmu3btnPtr pEmu3btn;
132    Bool emu3enable;
133    int emu3timeout;
134
135    switch (what) {
136	case DEVICE_INIT:
137            pMouse->devicePrivate = (void *) &x68kMousePriv;
138            if( (x68kMousePriv.fd = open("/dev/mouse", O_RDONLY)) == -1 ) {
139                ErrorF("Can't open mouse device\n");
140                return !Success;
141            }
142	    pMouse->on = FALSE;
143	    map[1] = 1;
144	    map[2] = 2;
145	    map[3] = 3;
146	    btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
147	    btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
148	    btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
149	    axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
150	    axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
151
152	    InitPointerDeviceStruct(pMouse, map, 3, btn_labels,
153		x68kMouseCtrl, GetMotionHistorySize(),
154		2, axes_labels);
155
156	    /* X valuator */
157	    InitValuatorAxisStruct(device, 0, axes_labels[0],
158		NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative);
159	    device->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
160	    device->last.valuators[0] = device->valuator->axisVal[0];
161
162	    /* Y valuator */
163	    InitValuatorAxisStruct(device, 1, axes_labels[1],
164		NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative);
165	    device->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
166	    device->last.valuators[1] = device->valuator->axisVal[1];
167
168	    /* Initialize emulation 3 buttons settings */
169	    emu3enable = TRUE;			/* XXX should be configurable */
170	    emu3timeout = EMU3B_DEF_TIMEOUT;	/* XXX should be configurable */
171	    if (emu3enable) {
172		pEmu3btn = &x68kMousePriv.emu3btn;
173		Emulate3ButtonsEnable(pEmu3btn, device, emu3timeout);
174	    }
175
176	    break;
177
178	case DEVICE_ON:
179	    if (ioctl (x68kMousePriv.fd, VUIDGFORMAT, &oformat) == -1) {
180		ErrorF("x68kMouseProc ioctl VUIDGFORMAT\n");
181		return !Success;
182	    }
183	    format = VUID_FIRM_EVENT;
184	    if (ioctl (x68kMousePriv.fd, VUIDSFORMAT, &format) == -1) {
185		ErrorF("x68kMouseProc ioctl VUIDSFORMAT\n");
186		return !Success;
187	    }
188            if ( fcntl(x68kMousePriv.fd, F_SETOWN, getpid()) == -1 ||
189                 fcntl(x68kMousePriv.fd, F_SETFL, O_NONBLOCK | O_ASYNC) == -1
190                 ) {
191                ErrorF("Async mouse I/O failed\n");
192                return !Success;
193            }
194	    x68kMousePriv.bmask = 0;
195	    SetNotifyFd(x68kMousePriv.fd, x68kMouseHandlerNotify,
196		X_NOTIFY_READ, NULL);
197	    pMouse->on = TRUE;
198	    break;
199
200	case DEVICE_OFF:
201	    pMouse->on = FALSE;
202	    RemoveNotifyFd(x68kMousePriv.fd);
203	    break;
204
205	case DEVICE_CLOSE:
206	    if (ioctl (x68kMousePriv.fd, VUIDSFORMAT, &oformat) == -1)
207		ErrorF("x68kMouseProc ioctl VUIDSFORMAT\n");
208	    break;
209
210	case DEVICE_ABORT:
211	    break;
212    }
213    return Success;
214}
215
216/*-
217 *-----------------------------------------------------------------------
218 * x68kMouseCtrl --
219 *	Alter the control parameters for the mouse. Since acceleration
220 *	etc. is done from the PtrCtrl record in the mouse's device record,
221 *	there's nothing to do here.
222 *
223 * Results:
224 *	None.
225 *
226 * Side Effects:
227 *	None.
228 *
229 *-----------------------------------------------------------------------
230 */
231/*ARGSUSED*/
232static void
233x68kMouseCtrl(DeviceIntPtr device, PtrCtrl* ctrl)
234{
235}
236
237/*-
238 *-----------------------------------------------------------------------
239 * x68kMouseGetEvents --
240 *	Return the events waiting in the wings for the given mouse.
241 *
242 * Results:
243 *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
244 *	The number of events contained in the array.
245 *	A boolean as to whether more events might be available.
246 *
247 * Side Effects:
248 *	None.
249 *-----------------------------------------------------------------------
250 */
251
252Firm_event *
253x68kMouseGetEvents(int fd, int *pNumEvents, Bool *pAgain)
254{
255    int nBytes;               /* number of bytes of events available. */
256    static Firm_event evBuf[X68K_MAXEVENTS];     /* Buffer for Firm_events */
257
258    if ((nBytes = read (fd, (char *)evBuf, sizeof(evBuf))) == -1) {
259	if (errno == EWOULDBLOCK) {
260	    *pNumEvents = 0;
261	    *pAgain = FALSE;
262	} else {
263	    ErrorF("x68kMouseGetEvents read\n");
264	    FatalError ("Could not read from mouse");
265	}
266    } else {
267	*pNumEvents = nBytes / sizeof (Firm_event);
268	*pAgain = (nBytes == sizeof (evBuf));
269    }
270    return evBuf;
271}
272
273/*-
274 *-----------------------------------------------------------------------
275 * x68kMouseEnqueueEvent --
276 *	Given a Firm_event for a mouse, pass it off the the dix layer
277 *	properly converted...
278 *
279 * Results:
280 *	None.
281 *
282 * Side Effects:
283 *	The cursor may be redrawn...? devPrivate/x/y will be altered.
284 *
285 *-----------------------------------------------------------------------
286 */
287
288void
289x68kMouseEnqueueEvent(DeviceIntPtr device, Firm_event *fe)
290{
291    X68kMousePrivPtr	pPriv;	/* Private data for pointer */
292    int			bmask;	/* Temporary button mask */
293    int			type, buttons, flag;
294    int			valuators[2];
295    ValuatorMask	mask;
296
297    pPriv = (X68kMousePrivPtr)device->public.devicePrivate;
298
299    switch (fe->id) {
300    case MS_LEFT:
301    case MS_MIDDLE:
302    case MS_RIGHT:
303	/*
304	 * A button changed state. Sometimes we will get two events
305	 * for a single state change. Should we get a button event which
306	 * reflects the current state of affairs, that event is discarded.
307	 *
308	 * Mouse buttons start at 1 as defined in <X11/X.h>.
309	 *
310	 * The bmask stores which buttons are currently pressed.
311	 * This bmask is also used for Emulate3Buttons functions that
312	 * assume the left button is LSB as defined in mouseEmu3btn.c.
313	 */
314	buttons = (fe->id - MS_LEFT) + 1;
315	bmask = 1 << (buttons - 1);
316	if (fe->value == VKEY_UP) {
317	    if (pPriv->bmask & bmask) {
318		type = ButtonRelease;
319		pPriv->bmask &= ~bmask;
320	    } else {
321		return;
322	    }
323	} else {
324	    if ((pPriv->bmask & bmask) == 0) {
325		type = ButtonPress;
326		pPriv->bmask |= bmask;
327	    } else {
328		return;
329	    }
330	}
331	if (buttons == Button1 || buttons == Button3) {
332	    /* Handle middle button emulation */
333	    Emulate3ButtonsQueueEvent(&pPriv->emu3btn, type, buttons, pPriv->bmask);
334	} else {
335	    flag = POINTER_RELATIVE;
336	    valuator_mask_zero(&mask);
337	    QueuePointerEvents(device, type, buttons, flag, &mask);
338	}
339	break;
340    case LOC_X_DELTA:
341	valuators[0] = fe->value;
342	valuators[1] = 0;
343	valuator_mask_set_range(&mask, 0, 2, valuators);
344        flag = POINTER_RELATIVE | POINTER_ACCELERATE;
345	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
346	break;
347    case LOC_Y_DELTA:
348	/*
349	 * For some reason, motion up generates a positive y delta
350	 * and motion down a negative delta, so we must subtract
351	 * here instead of add...
352	 */
353	valuators[0] = 0;
354	valuators[1] = -fe->value;
355	valuator_mask_set_range(&mask, 0, 2, valuators);
356        flag = POINTER_RELATIVE | POINTER_ACCELERATE;
357	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
358	break;
359    case LOC_X_ABSOLUTE:
360    case LOC_Y_ABSOLUTE:
361	/* XXX not sure how to get current X and Y position */
362    default:
363	FatalError ("%s: unrecognized id\n", __func__);
364	break;
365    }
366}
367
368/*ARGSUSED*/
369static Bool
370x68kCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
371{
372    return FALSE;
373}
374
375static void
376x68kCrossScreen(ScreenPtr pScreen, int entering)
377{
378}
379
380static void
381x68kWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
382{
383    input_lock();
384    miPointerWarpCursor (pDev, pScreen, x, y);
385    input_unlock();
386}
387
388/* EOF x68kMouse.c */
389