x68kMouse.c revision 3ec86d60
1/* $NetBSD: x68kMouse.c,v 1.17 2025/06/22 22:31:22 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 x68kMouseEvents(int, int, void *);
91static Firm_event *x68kMouseGetEvents(int, int *, Bool *);
92static void x68kMouseEnqueueEvent(DeviceIntPtr, Firm_event *);
93static Bool x68kCursorOffScreen(ScreenPtr *, int *, int *);
94static void x68kCrossScreen(ScreenPtr, int);
95static void x68kWarpCursor(DeviceIntPtr, ScreenPtr, int, int);
96static void x68kMouseCtrl(DeviceIntPtr, PtrCtrl*);
97
98typedef struct _X68kMousePriv {
99    int fd;
100    int bmask;
101    int oformat;
102    MouseEmu3btn emu3btn;
103} X68kMousePriv, *X68kMousePrivPtr;
104
105miPointerScreenFuncRec x68kPointerScreenFuncs = {
106    x68kCursorOffScreen,
107    x68kCrossScreen,
108    x68kWarpCursor,
109};
110
111DeviceIntPtr x68kPointerDevice = NULL;
112
113/*------------------------------------------------------------------------
114 * x68kMouseEvents --
115 *	When registered polled mouse input event handler is invoked,
116 *	read device events and enqueue them using the mi event queue.
117 * Results:
118 *	None.
119 *
120 *----------------------------------------------------------------------*/
121static void
122x68kMouseEvents(int fd, int ready, void *data)
123{
124    int i, numEvents = 0;
125    Bool again = FALSE;
126    Firm_event *events;
127    DeviceIntPtr device = (DeviceIntPtr)data;
128
129    input_lock();
130
131    do {
132	events = x68kMouseGetEvents(fd, &numEvents, &again);
133	for (i = 0; i < numEvents; i++) {
134	    x68kMouseEnqueueEvent(device, &events[i]);
135	}
136    } while (again);
137
138    input_unlock();
139}
140
141/*-
142 *-----------------------------------------------------------------------
143 * x68kMouseProc --
144 *	Handle the initialization, etc. of a mouse
145 *
146 * Results:
147 *	none.
148 *
149 * Side Effects:
150 *-----------------------------------------------------------------------
151 */
152int
153x68kMouseProc(DeviceIntPtr device, int what)
154{
155    DevicePtr   pMouse = &device->public;
156    X68kMousePrivPtr pPriv;
157    int		format;
158    BYTE	map[4];
159    Atom btn_labels[3] = {0};
160    Atom axes_labels[2] = { 0, 0 };
161    MouseEmu3btnPtr pEmu3btn;
162    Bool emu3enable;
163    int emu3timeout;
164
165    switch (what) {
166	case DEVICE_INIT:
167            pPriv = malloc(sizeof(*pPriv));
168            if (pPriv == NULL) {
169                LogMessage(X_ERROR, "Cannot allocate private data for mouse\n");
170                return !Success;
171            }
172            pPriv->fd = open("/dev/mouse", O_RDONLY | O_NONBLOCK);
173            if (pPriv->fd == -1) {
174                LogMessage(X_ERROR, "Can't open mouse device\n");
175                return !Success;
176            }
177            pPriv->bmask = 0;
178            pPriv->oformat = 0;
179            memset(&pPriv->emu3btn, 0, sizeof(pPriv->emu3btn));
180            pMouse->devicePrivate = pPriv;
181	    pMouse->on = FALSE;
182
183	    map[1] = 1;
184	    map[2] = 2;
185	    map[3] = 3;
186	    btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
187	    btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
188	    btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
189	    axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
190	    axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
191
192	    InitPointerDeviceStruct(pMouse, map, 3, btn_labels,
193		x68kMouseCtrl, GetMotionHistorySize(),
194		2, axes_labels);
195
196	    /* X valuator */
197	    InitValuatorAxisStruct(device, 0, axes_labels[0],
198		NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative);
199	    device->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
200	    device->last.valuators[0] = device->valuator->axisVal[0];
201
202	    /* Y valuator */
203	    InitValuatorAxisStruct(device, 1, axes_labels[1],
204		NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative);
205	    device->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
206	    device->last.valuators[1] = device->valuator->axisVal[1];
207
208	    /* Initialize emulation 3 buttons settings */
209	    emu3enable = TRUE;			/* XXX should be configurable */
210	    emu3timeout = EMU3B_DEF_TIMEOUT;	/* XXX should be configurable */
211	    if (emu3enable) {
212		pEmu3btn = &pPriv->emu3btn;
213		Emulate3ButtonsEnable(pEmu3btn, device, emu3timeout);
214	    }
215
216	    break;
217
218	case DEVICE_ON:
219	    pPriv = (X68kMousePrivPtr)pMouse->devicePrivate;
220	    if (ioctl(pPriv->fd, VUIDGFORMAT, &pPriv->oformat) == -1) {
221		LogMessage(X_ERROR, "x68kMouseProc ioctl VUIDGFORMAT\n");
222		return !Success;
223	    }
224	    format = VUID_FIRM_EVENT;
225	    if (ioctl(pPriv->fd, VUIDSFORMAT, &format) == -1) {
226		LogMessage(X_ERROR, "x68kMouseProc ioctl VUIDSFORMAT\n");
227		return !Success;
228	    }
229
230	    SetNotifyFd(pPriv->fd, x68kMouseEvents, X_NOTIFY_READ, device);
231
232	    pPriv->bmask = 0;
233	    pMouse->on = TRUE;
234	    break;
235
236	case DEVICE_OFF:
237	    pPriv = (X68kMousePrivPtr)pMouse->devicePrivate;
238	    RemoveNotifyFd(pPriv->fd);
239	    if (ioctl(pPriv->fd, VUIDSFORMAT, &pPriv->oformat) == -1)
240		LogMessage(X_ERROR, "x68kMouseProc ioctl VUIDSFORMAT\n");
241	    pMouse->on = FALSE;
242	    break;
243
244	case DEVICE_CLOSE:
245	    pPriv = (X68kMousePrivPtr)pMouse->devicePrivate;
246	    close(pPriv->fd);
247	    free(pPriv);
248	    break;
249
250	case DEVICE_ABORT:
251	    break;
252    }
253    return Success;
254}
255
256/*-
257 *-----------------------------------------------------------------------
258 * x68kMouseCtrl --
259 *	Alter the control parameters for the mouse. Since acceleration
260 *	etc. is done from the PtrCtrl record in the mouse's device record,
261 *	there's nothing to do here.
262 *
263 * Results:
264 *	None.
265 *
266 * Side Effects:
267 *	None.
268 *
269 *-----------------------------------------------------------------------
270 */
271/*ARGSUSED*/
272static void
273x68kMouseCtrl(DeviceIntPtr device, PtrCtrl* ctrl)
274{
275}
276
277/*-
278 *-----------------------------------------------------------------------
279 * x68kMouseGetEvents --
280 *	Return the events waiting in the wings for the given mouse.
281 *
282 * Results:
283 *	A pointer to an array of Firm_events or (Firm_event *)0 if no events
284 *	The number of events contained in the array.
285 *	A boolean as to whether more events might be available.
286 *
287 * Side Effects:
288 *	None.
289 *-----------------------------------------------------------------------
290 */
291
292static Firm_event *
293x68kMouseGetEvents(int fd, int *pNumEvents, Bool *pAgain)
294{
295    int nBytes;               /* number of bytes of events available. */
296    static Firm_event evBuf[X68K_MAXEVENTS];     /* Buffer for Firm_events */
297
298    if ((nBytes = read (fd, (char *)evBuf, sizeof(evBuf))) == -1) {
299	if (errno == EWOULDBLOCK) {
300	    *pNumEvents = 0;
301	    *pAgain = FALSE;
302	} else {
303	    ErrorF("x68kMouseGetEvents read\n");
304	    FatalError ("Could not read from mouse");
305	}
306    } else {
307	*pNumEvents = nBytes / sizeof (Firm_event);
308	*pAgain = (nBytes == sizeof (evBuf));
309    }
310    return evBuf;
311}
312
313/*-
314 *-----------------------------------------------------------------------
315 * x68kMouseEnqueueEvent --
316 *	Given a Firm_event for a mouse, pass it off the the dix layer
317 *	properly converted...
318 *
319 * Results:
320 *	None.
321 *
322 * Side Effects:
323 *	The cursor may be redrawn...? devPrivate/x/y will be altered.
324 *
325 *-----------------------------------------------------------------------
326 */
327
328static void
329x68kMouseEnqueueEvent(DeviceIntPtr device, Firm_event *fe)
330{
331    X68kMousePrivPtr	pPriv;	/* Private data for pointer */
332    int			bmask;	/* Temporary button mask */
333    int			type, buttons, flag;
334    int			valuators[2];
335    ValuatorMask	mask;
336
337    pPriv = (X68kMousePrivPtr)device->public.devicePrivate;
338
339    switch (fe->id) {
340    case MS_LEFT:
341    case MS_MIDDLE:
342    case MS_RIGHT:
343	/*
344	 * A button changed state. Sometimes we will get two events
345	 * for a single state change. Should we get a button event which
346	 * reflects the current state of affairs, that event is discarded.
347	 *
348	 * Mouse buttons start at 1 as defined in <X11/X.h>.
349	 *
350	 * The bmask stores which buttons are currently pressed.
351	 * This bmask is also used for Emulate3Buttons functions that
352	 * assume the left button is LSB as defined in mouseEmu3btn.c.
353	 */
354	buttons = (fe->id - MS_LEFT) + 1;
355	bmask = 1 << (buttons - 1);
356	if (fe->value == VKEY_UP) {
357	    if (pPriv->bmask & bmask) {
358		type = ButtonRelease;
359		pPriv->bmask &= ~bmask;
360	    } else {
361		return;
362	    }
363	} else {
364	    if ((pPriv->bmask & bmask) == 0) {
365		type = ButtonPress;
366		pPriv->bmask |= bmask;
367	    } else {
368		return;
369	    }
370	}
371	if (buttons == Button1 || buttons == Button3) {
372	    /* Handle middle button emulation */
373	    Emulate3ButtonsQueueEvent(&pPriv->emu3btn, type, buttons, pPriv->bmask);
374	} else {
375	    flag = POINTER_RELATIVE;
376	    valuator_mask_zero(&mask);
377	    QueuePointerEvents(device, type, buttons, flag, &mask);
378	}
379	break;
380    case LOC_X_DELTA:
381	valuators[0] = fe->value;
382	valuators[1] = 0;
383	valuator_mask_set_range(&mask, 0, 2, valuators);
384        flag = POINTER_RELATIVE | POINTER_ACCELERATE;
385	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
386	break;
387    case LOC_Y_DELTA:
388	/*
389	 * For some reason, motion up generates a positive y delta
390	 * and motion down a negative delta, so we must subtract
391	 * here instead of add...
392	 */
393	valuators[0] = 0;
394	valuators[1] = -fe->value;
395	valuator_mask_set_range(&mask, 0, 2, valuators);
396        flag = POINTER_RELATIVE | POINTER_ACCELERATE;
397	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
398	break;
399    case LOC_X_ABSOLUTE:
400    case LOC_Y_ABSOLUTE:
401	/* XXX not sure how to get current X and Y position */
402    default:
403	FatalError ("%s: unrecognized id\n", __func__);
404	break;
405    }
406}
407
408/*ARGSUSED*/
409static Bool
410x68kCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
411{
412    return FALSE;
413}
414
415static void
416x68kCrossScreen(ScreenPtr pScreen, int entering)
417{
418}
419
420static void
421x68kWarpCursor(DeviceIntPtr device, ScreenPtr pScreen, int x, int y)
422{
423    input_lock();
424    miPointerWarpCursor(device, pScreen, x, y);
425    input_unlock();
426}
427
428/* EOF x68kMouse.c */
429