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