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