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