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