162918564Stsutsui/* $NetBSD: x68kMouse.c,v 1.18 2025/06/22 22:33:03 tsutsui Exp $ */
2ba64b02eStsutsui/*-------------------------------------------------------------------------
3ba64b02eStsutsui * Copyright (c) 1996 Yasushi Yamasaki
4ba64b02eStsutsui * All rights reserved.
5ba64b02eStsutsui *
6ba64b02eStsutsui * Redistribution and use in source and binary forms, with or without
7ba64b02eStsutsui * modification, are permitted provided that the following conditions
8ba64b02eStsutsui * are met:
9ba64b02eStsutsui * 1. Redistributions of source code must retain the above copyright
10ba64b02eStsutsui *    notice, this list of conditions and the following disclaimer.
11ba64b02eStsutsui * 2. Redistributions in binary form must reproduce the above copyright
12ba64b02eStsutsui *    notice, this list of conditions and the following disclaimer in the
13ba64b02eStsutsui *    documentation and/or other materials provided with the distribution.
14ba64b02eStsutsui *
15ba64b02eStsutsui * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16ba64b02eStsutsui * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17ba64b02eStsutsui * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18ba64b02eStsutsui * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19ba64b02eStsutsui * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20ba64b02eStsutsui * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21ba64b02eStsutsui * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22ba64b02eStsutsui * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23ba64b02eStsutsui * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24ba64b02eStsutsui * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25ba64b02eStsutsui *-----------------------------------------------------------------------*/
26ba64b02eStsutsui
27ba64b02eStsutsui/*-
28ba64b02eStsutsui * Copyright (c) 1987 by the Regents of the University of California
29ba64b02eStsutsui *
30ba64b02eStsutsui * Permission to use, copy, modify, and distribute this
31ba64b02eStsutsui * software and its documentation for any purpose and without
32ba64b02eStsutsui * fee is hereby granted, provided that the above copyright
33ba64b02eStsutsui * notice appear in all copies.  The University of California
34ba64b02eStsutsui * makes no representations about the suitability of this
35ba64b02eStsutsui * software for any purpose.  It is provided "as is" without
36ba64b02eStsutsui * express or implied warranty.
37ba64b02eStsutsui */
38ba64b02eStsutsui
39ba64b02eStsutsui/************************************************************
40ba64b02eStsutsuiCopyright 1987 by Sun Microsystems, Inc. Mountain View, CA.
41ba64b02eStsutsui
42ba64b02eStsutsui                    All Rights Reserved
43ba64b02eStsutsui
44ba64b02eStsutsuiPermission  to  use,  copy,  modify,  and  distribute   this
45ba64b02eStsutsuisoftware  and  its documentation for any purpose and without
46ba64b02eStsutsuifee is hereby granted, provided that the above copyright no-
47ba64b02eStsutsuitice  appear  in all copies and that both that copyright no-
48ba64b02eStsutsuitice and this permission notice appear in  supporting  docu-
49ba64b02eStsutsuimentation,  and  that the names of Sun or X Consortium
50ab290810Stsutsuinot be used in advertising or publicity pertaining to
51ab290810Stsutsuidistribution  of  the software  without specific prior
52ab290810Stsutsuiwritten permission. Sun and X Consortium make no
53ab290810Stsutsuirepresentations about the suitability of this software for
54ab290810Stsutsuiany purpose. It is provided "as is" without any express or
55ba64b02eStsutsuiimplied warranty.
56ba64b02eStsutsui
57ba64b02eStsutsuiSUN DISCLAIMS ALL WARRANTIES WITH REGARD TO  THIS  SOFTWARE,
58ba64b02eStsutsuiINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
59ba64b02eStsutsuiNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE  LI-
60ba64b02eStsutsuiABLE  FOR  ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
61ba64b02eStsutsuiANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,  DATA  OR
62ba64b02eStsutsuiPROFITS,  WHETHER  IN  AN  ACTION OF CONTRACT, NEGLIGENCE OR
63ba64b02eStsutsuiOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
64ba64b02eStsutsuiTHE USE OR PERFORMANCE OF THIS SOFTWARE.
65ba64b02eStsutsui
66ba64b02eStsutsui********************************************************/
67ba64b02eStsutsui/*
68ba64b02eStsutsui * Copyright 1991, 1992, 1993 Kaleb S. Keithley
69ba64b02eStsutsui *
70ba64b02eStsutsui * Permission to use, copy, modify, and distribute this
71ba64b02eStsutsui * software and its documentation for any purpose and without
72ba64b02eStsutsui * fee is hereby granted, provided that the above copyright
73ab290810Stsutsui * notice appear in all copies.  Kaleb S. Keithley makes no
74ab290810Stsutsui * representations about the suitability of this software for
75ab290810Stsutsui * any purpose.  It is provided "as is" without express or
76ba64b02eStsutsui * implied warranty.
77ba64b02eStsutsui */
78ba64b02eStsutsui
79ba64b02eStsutsui#include "x68k.h"
80ba64b02eStsutsui#include "mi.h"
81ba64b02eStsutsui#include "input.h"
82ba64b02eStsutsui#include "inpututils.h"
83ba64b02eStsutsui
84ba64b02eStsutsui#include "exevents.h"
85909daefdSmrg#include "events.h"
86909daefdSmrg#include "eventstr.h"
87ba64b02eStsutsui#include <X11/Xatom.h>
88ba64b02eStsutsui#include "xserver-properties.h"
89ba64b02eStsutsui
9045f60b5bStsutsuistatic void x68kMouseEvents(int, int, void *);
9162918564Stsutsuistatic int x68kMouseGetEvents(DeviceIntPtr);
9245f60b5bStsutsuistatic void x68kMouseEnqueueEvent(DeviceIntPtr, Firm_event *);
93ba64b02eStsutsuistatic Bool x68kCursorOffScreen(ScreenPtr *, int *, int *);
94ba64b02eStsutsuistatic void x68kCrossScreen(ScreenPtr, int);
95ba64b02eStsutsuistatic void x68kWarpCursor(DeviceIntPtr, ScreenPtr, int, int);
96ba64b02eStsutsuistatic void x68kMouseCtrl(DeviceIntPtr, PtrCtrl*);
97ba64b02eStsutsui
983ec86d60Stsutsuitypedef struct _X68kMousePriv {
993ec86d60Stsutsui    int fd;
1003ec86d60Stsutsui    int bmask;
1013ec86d60Stsutsui    int oformat;
1023ec86d60Stsutsui    MouseEmu3btn emu3btn;
10362918564Stsutsui    Firm_event evbuf[X68K_MAXEVENTS];
1043ec86d60Stsutsui} X68kMousePriv, *X68kMousePrivPtr;
1053ec86d60Stsutsui
106ba64b02eStsutsuimiPointerScreenFuncRec x68kPointerScreenFuncs = {
107ba64b02eStsutsui    x68kCursorOffScreen,
108ba64b02eStsutsui    x68kCrossScreen,
109ba64b02eStsutsui    x68kWarpCursor,
110ba64b02eStsutsui};
111ba64b02eStsutsui
112ba64b02eStsutsuiDeviceIntPtr x68kPointerDevice = NULL;
113ba64b02eStsutsui
11445f60b5bStsutsui/*------------------------------------------------------------------------
11545f60b5bStsutsui * x68kMouseEvents --
11645f60b5bStsutsui *	When registered polled mouse input event handler is invoked,
11745f60b5bStsutsui *	read device events and enqueue them using the mi event queue.
11845f60b5bStsutsui * Results:
11945f60b5bStsutsui *	None.
12045f60b5bStsutsui *
12145f60b5bStsutsui *----------------------------------------------------------------------*/
12272502d70Stsutsuistatic void
12345f60b5bStsutsuix68kMouseEvents(int fd, int ready, void *data)
12472502d70Stsutsui{
12562918564Stsutsui    int i, numEvents;
12645f60b5bStsutsui    DeviceIntPtr device = (DeviceIntPtr)data;
12762918564Stsutsui    DevicePtr pMouse = &device->public;
12862918564Stsutsui    X68kMousePrivPtr pPriv = pMouse->devicePrivate;
12945f60b5bStsutsui
13045f60b5bStsutsui    input_lock();
13145f60b5bStsutsui
13245f60b5bStsutsui    do {
13362918564Stsutsui	numEvents = x68kMouseGetEvents(device);
13445f60b5bStsutsui	for (i = 0; i < numEvents; i++) {
13562918564Stsutsui	    x68kMouseEnqueueEvent(device, &pPriv->evbuf[i]);
13645f60b5bStsutsui	}
13762918564Stsutsui    } while (numEvents == X68K_MAXEVENTS);
13845f60b5bStsutsui
13945f60b5bStsutsui    input_unlock();
14072502d70Stsutsui}
14172502d70Stsutsui
142ba64b02eStsutsui/*-
143ba64b02eStsutsui *-----------------------------------------------------------------------
144ba64b02eStsutsui * x68kMouseProc --
145ba64b02eStsutsui *	Handle the initialization, etc. of a mouse
146ba64b02eStsutsui *
147ba64b02eStsutsui * Results:
148ba64b02eStsutsui *	none.
149ba64b02eStsutsui *
150ba64b02eStsutsui * Side Effects:
151ba64b02eStsutsui *-----------------------------------------------------------------------
152ba64b02eStsutsui */
153ba64b02eStsutsuiint
154ba64b02eStsutsuix68kMouseProc(DeviceIntPtr device, int what)
155ba64b02eStsutsui{
156ba64b02eStsutsui    DevicePtr   pMouse = &device->public;
1574ff7d041Stsutsui    X68kMousePrivPtr pPriv;
158ab290810Stsutsui    int		format;
159ab290810Stsutsui    BYTE	map[4];
160ba64b02eStsutsui    Atom btn_labels[3] = {0};
161ba64b02eStsutsui    Atom axes_labels[2] = { 0, 0 };
162e8a9312aStsutsui    MouseEmu3btnPtr pEmu3btn;
163e8a9312aStsutsui    Bool emu3enable;
164e8a9312aStsutsui    int emu3timeout;
165ba64b02eStsutsui
166ba64b02eStsutsui    switch (what) {
167ba64b02eStsutsui	case DEVICE_INIT:
1683ec86d60Stsutsui            pPriv = malloc(sizeof(*pPriv));
1693ec86d60Stsutsui            if (pPriv == NULL) {
1703ec86d60Stsutsui                LogMessage(X_ERROR, "Cannot allocate private data for mouse\n");
171ba64b02eStsutsui                return !Success;
172ba64b02eStsutsui            }
1733ec86d60Stsutsui            pPriv->fd = open("/dev/mouse", O_RDONLY | O_NONBLOCK);
1743ec86d60Stsutsui            if (pPriv->fd == -1) {
1753ec86d60Stsutsui                LogMessage(X_ERROR, "Can't open mouse device\n");
1763ec86d60Stsutsui                return !Success;
1773ec86d60Stsutsui            }
1783ec86d60Stsutsui            pPriv->bmask = 0;
1793ec86d60Stsutsui            pPriv->oformat = 0;
1803ec86d60Stsutsui            memset(&pPriv->emu3btn, 0, sizeof(pPriv->emu3btn));
1814ff7d041Stsutsui            pMouse->devicePrivate = pPriv;
182ba64b02eStsutsui	    pMouse->on = FALSE;
1833ec86d60Stsutsui
184ba64b02eStsutsui	    map[1] = 1;
185ba64b02eStsutsui	    map[2] = 2;
186ba64b02eStsutsui	    map[3] = 3;
187ba64b02eStsutsui	    btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
188ba64b02eStsutsui	    btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
189ba64b02eStsutsui	    btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
190ba64b02eStsutsui	    axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
191ba64b02eStsutsui	    axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
192ba64b02eStsutsui
193ba64b02eStsutsui	    InitPointerDeviceStruct(pMouse, map, 3, btn_labels,
194ab290810Stsutsui		x68kMouseCtrl, GetMotionHistorySize(),
195ba64b02eStsutsui		2, axes_labels);
196e8a9312aStsutsui
197d8389a6eStsutsui	    /* X valuator */
198d8389a6eStsutsui	    InitValuatorAxisStruct(device, 0, axes_labels[0],
199d8389a6eStsutsui		NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative);
200d8389a6eStsutsui	    device->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
201d8389a6eStsutsui	    device->last.valuators[0] = device->valuator->axisVal[0];
202d8389a6eStsutsui
203d8389a6eStsutsui	    /* Y valuator */
204d8389a6eStsutsui	    InitValuatorAxisStruct(device, 1, axes_labels[1],
205d8389a6eStsutsui		NO_AXIS_LIMITS, NO_AXIS_LIMITS, 1, 0, 1, Relative);
206d8389a6eStsutsui	    device->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
207d8389a6eStsutsui	    device->last.valuators[1] = device->valuator->axisVal[1];
208d8389a6eStsutsui
209e8a9312aStsutsui	    /* Initialize emulation 3 buttons settings */
210e8a9312aStsutsui	    emu3enable = TRUE;			/* XXX should be configurable */
211e8a9312aStsutsui	    emu3timeout = EMU3B_DEF_TIMEOUT;	/* XXX should be configurable */
212e8a9312aStsutsui	    if (emu3enable) {
2134ff7d041Stsutsui		pEmu3btn = &pPriv->emu3btn;
214e8a9312aStsutsui		Emulate3ButtonsEnable(pEmu3btn, device, emu3timeout);
215e8a9312aStsutsui	    }
216e8a9312aStsutsui
217ba64b02eStsutsui	    break;
218ba64b02eStsutsui
219ba64b02eStsutsui	case DEVICE_ON:
2204ff7d041Stsutsui	    pPriv = (X68kMousePrivPtr)pMouse->devicePrivate;
2213ec86d60Stsutsui	    if (ioctl(pPriv->fd, VUIDGFORMAT, &pPriv->oformat) == -1) {
2223ec86d60Stsutsui		LogMessage(X_ERROR, "x68kMouseProc ioctl VUIDGFORMAT\n");
223ba64b02eStsutsui		return !Success;
224ba64b02eStsutsui	    }
225ba64b02eStsutsui	    format = VUID_FIRM_EVENT;
2264ff7d041Stsutsui	    if (ioctl(pPriv->fd, VUIDSFORMAT, &format) == -1) {
2273ec86d60Stsutsui		LogMessage(X_ERROR, "x68kMouseProc ioctl VUIDSFORMAT\n");
228ba64b02eStsutsui		return !Success;
229ba64b02eStsutsui	    }
2303ec86d60Stsutsui
2314ff7d041Stsutsui	    SetNotifyFd(pPriv->fd, x68kMouseEvents, X_NOTIFY_READ, device);
2323ec86d60Stsutsui
2334ff7d041Stsutsui	    pPriv->bmask = 0;
234ba64b02eStsutsui	    pMouse->on = TRUE;
235ba64b02eStsutsui	    break;
236ba64b02eStsutsui
237ba64b02eStsutsui	case DEVICE_OFF:
2384ff7d041Stsutsui	    pPriv = (X68kMousePrivPtr)pMouse->devicePrivate;
2394ff7d041Stsutsui	    RemoveNotifyFd(pPriv->fd);
2403ec86d60Stsutsui	    if (ioctl(pPriv->fd, VUIDSFORMAT, &pPriv->oformat) == -1)
2413ec86d60Stsutsui		LogMessage(X_ERROR, "x68kMouseProc ioctl VUIDSFORMAT\n");
2423ec86d60Stsutsui	    pMouse->on = FALSE;
243ba64b02eStsutsui	    break;
244ba64b02eStsutsui
245ba64b02eStsutsui	case DEVICE_CLOSE:
2464ff7d041Stsutsui	    pPriv = (X68kMousePrivPtr)pMouse->devicePrivate;
2473ec86d60Stsutsui	    close(pPriv->fd);
2483ec86d60Stsutsui	    free(pPriv);
249ba64b02eStsutsui	    break;
250ba64b02eStsutsui
2512aa2a51fStsutsui	case DEVICE_ABORT:
2522aa2a51fStsutsui	    break;
253ba64b02eStsutsui    }
254ba64b02eStsutsui    return Success;
255ba64b02eStsutsui}
256ab290810Stsutsui
257ba64b02eStsutsui/*-
258ba64b02eStsutsui *-----------------------------------------------------------------------
259ba64b02eStsutsui * x68kMouseCtrl --
260ba64b02eStsutsui *	Alter the control parameters for the mouse. Since acceleration
261ba64b02eStsutsui *	etc. is done from the PtrCtrl record in the mouse's device record,
262ba64b02eStsutsui *	there's nothing to do here.
263ba64b02eStsutsui *
264ba64b02eStsutsui * Results:
265ba64b02eStsutsui *	None.
266ba64b02eStsutsui *
267ba64b02eStsutsui * Side Effects:
268ba64b02eStsutsui *	None.
269ba64b02eStsutsui *
270ba64b02eStsutsui *-----------------------------------------------------------------------
271ba64b02eStsutsui */
272ba64b02eStsutsui/*ARGSUSED*/
273ba64b02eStsutsuistatic void
274ba64b02eStsutsuix68kMouseCtrl(DeviceIntPtr device, PtrCtrl* ctrl)
275ba64b02eStsutsui{
276ba64b02eStsutsui}
277ba64b02eStsutsui
278ba64b02eStsutsui/*-
279ba64b02eStsutsui *-----------------------------------------------------------------------
280ba64b02eStsutsui * x68kMouseGetEvents --
281ba64b02eStsutsui *	Return the events waiting in the wings for the given mouse.
282ba64b02eStsutsui *
283ba64b02eStsutsui * Results:
28462918564Stsutsui *      Update Firm_event buffer in DeviceIntPtr if events are received.
28562918564Stsutsui *      Return the number of received Firm_events in the buffer.
286ba64b02eStsutsui *
287ba64b02eStsutsui * Side Effects:
288ba64b02eStsutsui *	None.
289ba64b02eStsutsui *-----------------------------------------------------------------------
290ba64b02eStsutsui */
291ba64b02eStsutsui
29262918564Stsutsuistatic int
29362918564Stsutsuix68kMouseGetEvents(DeviceIntPtr device)
294ba64b02eStsutsui{
29562918564Stsutsui    DevicePtr pMouse = &device->public;
29662918564Stsutsui    X68kMousePrivPtr pPriv = pMouse->devicePrivate;
297ba64b02eStsutsui    int nBytes;               /* number of bytes of events available. */
29862918564Stsutsui    int NumEvents = 0;
29962918564Stsutsui
30062918564Stsutsui    nBytes = read(pPriv->fd, (char *)pPriv->evbuf, sizeof(pPriv->evbuf));
30162918564Stsutsui    if (nBytes == -1) {
30262918564Stsutsui	if (errno != EWOULDBLOCK) {
30362918564Stsutsui	    LogMessage(X_ERROR, "Unexpected error on reading mouse\n");
30462918564Stsutsui	    FatalError("Could not read from mouse");
305ba64b02eStsutsui	}
306ba64b02eStsutsui    } else {
30762918564Stsutsui	NumEvents = nBytes / sizeof(pPriv->evbuf[0]);
308ba64b02eStsutsui    }
30962918564Stsutsui    return NumEvents;
310ba64b02eStsutsui}
311ba64b02eStsutsui
312ba64b02eStsutsui/*-
313ba64b02eStsutsui *-----------------------------------------------------------------------
314ba64b02eStsutsui * x68kMouseEnqueueEvent --
315ba64b02eStsutsui *	Given a Firm_event for a mouse, pass it off the the dix layer
316ba64b02eStsutsui *	properly converted...
317ba64b02eStsutsui *
318ba64b02eStsutsui * Results:
319ba64b02eStsutsui *	None.
320ba64b02eStsutsui *
321ba64b02eStsutsui * Side Effects:
322ba64b02eStsutsui *	The cursor may be redrawn...? devPrivate/x/y will be altered.
323ba64b02eStsutsui *
324ba64b02eStsutsui *-----------------------------------------------------------------------
325ba64b02eStsutsui */
326ba64b02eStsutsui
32745f60b5bStsutsuistatic void
328ba64b02eStsutsuix68kMouseEnqueueEvent(DeviceIntPtr device, Firm_event *fe)
329ba64b02eStsutsui{
330ba64b02eStsutsui    X68kMousePrivPtr	pPriv;	/* Private data for pointer */
331ba64b02eStsutsui    int			bmask;	/* Temporary button mask */
332ba64b02eStsutsui    int			type, buttons, flag;
333bddeb3e5Stsutsui    int			valuators[2];
334ba64b02eStsutsui    ValuatorMask	mask;
335ba64b02eStsutsui
336ba64b02eStsutsui    pPriv = (X68kMousePrivPtr)device->public.devicePrivate;
337ba64b02eStsutsui
338ba64b02eStsutsui    switch (fe->id) {
339ba64b02eStsutsui    case MS_LEFT:
340ba64b02eStsutsui    case MS_MIDDLE:
341ba64b02eStsutsui    case MS_RIGHT:
342ba64b02eStsutsui	/*
343ba64b02eStsutsui	 * A button changed state. Sometimes we will get two events
344ba64b02eStsutsui	 * for a single state change. Should we get a button event which
345ba64b02eStsutsui	 * reflects the current state of affairs, that event is discarded.
346ba64b02eStsutsui	 *
347e8a9312aStsutsui	 * Mouse buttons start at 1 as defined in <X11/X.h>.
348e8a9312aStsutsui	 *
349e8a9312aStsutsui	 * The bmask stores which buttons are currently pressed.
350e8a9312aStsutsui	 * This bmask is also used for Emulate3Buttons functions that
351e8a9312aStsutsui	 * assume the left button is LSB as defined in mouseEmu3btn.c.
352ba64b02eStsutsui	 */
353ba64b02eStsutsui	buttons = (fe->id - MS_LEFT) + 1;
354e8a9312aStsutsui	bmask = 1 << (buttons - 1);
355ba64b02eStsutsui	if (fe->value == VKEY_UP) {
356ba64b02eStsutsui	    if (pPriv->bmask & bmask) {
357ba64b02eStsutsui		type = ButtonRelease;
358ba64b02eStsutsui		pPriv->bmask &= ~bmask;
359ba64b02eStsutsui	    } else {
360ba64b02eStsutsui		return;
361ba64b02eStsutsui	    }
362ba64b02eStsutsui	} else {
363ba64b02eStsutsui	    if ((pPriv->bmask & bmask) == 0) {
364ba64b02eStsutsui		type = ButtonPress;
365ba64b02eStsutsui		pPriv->bmask |= bmask;
366ba64b02eStsutsui	    } else {
367ba64b02eStsutsui		return;
368ba64b02eStsutsui	    }
369ba64b02eStsutsui	}
370e8a9312aStsutsui	if (buttons == Button1 || buttons == Button3) {
371e8a9312aStsutsui	    /* Handle middle button emulation */
372e8a9312aStsutsui	    Emulate3ButtonsQueueEvent(&pPriv->emu3btn, type, buttons, pPriv->bmask);
373e8a9312aStsutsui	} else {
374e8a9312aStsutsui	    flag = POINTER_RELATIVE;
375e8a9312aStsutsui	    valuator_mask_zero(&mask);
376e8a9312aStsutsui	    QueuePointerEvents(device, type, buttons, flag, &mask);
377e8a9312aStsutsui	}
378ba64b02eStsutsui	break;
379ba64b02eStsutsui    case LOC_X_DELTA:
380ba64b02eStsutsui	valuators[0] = fe->value;
381ba64b02eStsutsui	valuators[1] = 0;
382ba64b02eStsutsui	valuator_mask_set_range(&mask, 0, 2, valuators);
383ba64b02eStsutsui        flag = POINTER_RELATIVE | POINTER_ACCELERATE;
384bddeb3e5Stsutsui	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
385ba64b02eStsutsui	break;
386ba64b02eStsutsui    case LOC_Y_DELTA:
387ba64b02eStsutsui	/*
388ba64b02eStsutsui	 * For some reason, motion up generates a positive y delta
389ba64b02eStsutsui	 * and motion down a negative delta, so we must subtract
390ba64b02eStsutsui	 * here instead of add...
391ba64b02eStsutsui	 */
392ba64b02eStsutsui	valuators[0] = 0;
393ba64b02eStsutsui	valuators[1] = -fe->value;
394ba64b02eStsutsui	valuator_mask_set_range(&mask, 0, 2, valuators);
395ba64b02eStsutsui        flag = POINTER_RELATIVE | POINTER_ACCELERATE;
396bddeb3e5Stsutsui	QueuePointerEvents(device, MotionNotify, 0, flag, &mask);
397ba64b02eStsutsui	break;
398ba64b02eStsutsui    case LOC_X_ABSOLUTE:
399ba64b02eStsutsui    case LOC_Y_ABSOLUTE:
400ba64b02eStsutsui	/* XXX not sure how to get current X and Y position */
401ba64b02eStsutsui    default:
402ba64b02eStsutsui	FatalError ("%s: unrecognized id\n", __func__);
403ba64b02eStsutsui	break;
404ba64b02eStsutsui    }
405ba64b02eStsutsui}
406ba64b02eStsutsui
407ba64b02eStsutsui/*ARGSUSED*/
408ba64b02eStsutsuistatic Bool
409ba64b02eStsutsuix68kCursorOffScreen(ScreenPtr *pScreen, int *x, int *y)
410ba64b02eStsutsui{
411ba64b02eStsutsui    return FALSE;
412ba64b02eStsutsui}
413ba64b02eStsutsui
414ba64b02eStsutsuistatic void
415ba64b02eStsutsuix68kCrossScreen(ScreenPtr pScreen, int entering)
416ba64b02eStsutsui{
417ba64b02eStsutsui}
418ba64b02eStsutsui
419ba64b02eStsutsuistatic void
420b0c54374Stsutsuix68kWarpCursor(DeviceIntPtr device, ScreenPtr pScreen, int x, int y)
421ba64b02eStsutsui{
4221406604bStsutsui    input_lock();
423b0c54374Stsutsui    miPointerWarpCursor(device, pScreen, x, y);
4241406604bStsutsui    input_unlock();
425ba64b02eStsutsui}
426ba64b02eStsutsui
427ba64b02eStsutsui/* EOF x68kMouse.c */
428