kinput.c revision 6747b715
1/* 2 * Copyright � 1999 Keith Packard 3 * Copyright � 2006 Nokia Corporation 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of the authors not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. The authors make no 12 * representations about the suitability of this software for any purpose. It 13 * is provided "as is" without express or implied warranty. 14 * 15 * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include <kdrive-config.h> 26#endif 27#include "kdrive.h" 28#include "inputstr.h" 29 30#define XK_PUBLISHING 31#include <X11/keysym.h> 32#if HAVE_X11_XF86KEYSYM_H 33#include <X11/XF86keysym.h> 34#endif 35#include <signal.h> 36#include <stdio.h> 37#ifdef sun 38#include <sys/file.h> /* needed for FNONBLOCK & FASYNC */ 39#endif 40 41#include "xkbsrv.h" 42 43#include <X11/extensions/XI.h> 44#include <X11/extensions/XIproto.h> 45#include "XIstubs.h" /* even though we don't use stubs. cute, no? */ 46#include "exevents.h" 47#include "extinit.h" 48#include "exglobals.h" 49#include "eventstr.h" 50#include "xserver-properties.h" 51 52#define AtomFromName(x) MakeAtom(x, strlen(x), 1) 53 54struct KdConfigDevice { 55 char *line; 56 struct KdConfigDevice *next; 57}; 58 59/* kdKeyboards and kdPointers hold all the real devices. */ 60static KdKeyboardInfo *kdKeyboards = NULL; 61static KdPointerInfo *kdPointers = NULL; 62static struct KdConfigDevice *kdConfigKeyboards = NULL; 63static struct KdConfigDevice *kdConfigPointers = NULL; 64 65static KdKeyboardDriver *kdKeyboardDrivers = NULL; 66static KdPointerDriver *kdPointerDrivers = NULL; 67 68static EventListPtr kdEvents = NULL; 69 70static Bool kdInputEnabled; 71static Bool kdOffScreen; 72static unsigned long kdOffScreenTime; 73static KdPointerMatrix kdPointerMatrix = { 74 { { 1, 0, 0 }, 75 { 0, 1, 0 } } 76}; 77 78void KdResetInputMachine (void); 79 80#define KD_MAX_INPUT_FDS 8 81 82typedef struct _kdInputFd { 83 int fd; 84 void (*read) (int fd, void *closure); 85 int (*enable) (int fd, void *closure); 86 void (*disable) (int fd, void *closure); 87 void *closure; 88} KdInputFd; 89 90static KdInputFd kdInputFds[KD_MAX_INPUT_FDS]; 91static int kdNumInputFds; 92 93extern Bool kdRawPointerCoordinates; 94 95static void 96KdSigio (int sig) 97{ 98 int i; 99 100 for (i = 0; i < kdNumInputFds; i++) 101 (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure); 102} 103 104static void 105KdBlockSigio (void) 106{ 107 sigset_t set; 108 109 sigemptyset (&set); 110 sigaddset (&set, SIGIO); 111 sigprocmask (SIG_BLOCK, &set, 0); 112} 113 114static void 115KdUnblockSigio (void) 116{ 117 sigset_t set; 118 119 sigemptyset (&set); 120 sigaddset (&set, SIGIO); 121 sigprocmask (SIG_UNBLOCK, &set, 0); 122} 123 124#ifdef DEBUG_SIGIO 125 126void 127KdAssertSigioBlocked (char *where) 128{ 129 sigset_t set, old; 130 131 sigemptyset (&set); 132 sigprocmask (SIG_BLOCK, &set, &old); 133 if (!sigismember (&old, SIGIO)) { 134 ErrorF ("SIGIO not blocked at %s\n", where); 135 KdBacktrace(0); 136 } 137} 138 139#else 140 141#define KdAssertSigioBlocked(s) 142 143#endif 144 145static int kdnFds; 146 147#ifdef FNONBLOCK 148#define NOBLOCK FNONBLOCK 149#else 150#define NOBLOCK FNDELAY 151#endif 152 153void 154KdResetInputMachine (void) 155{ 156 KdPointerInfo *pi; 157 158 for (pi = kdPointers; pi; pi = pi->next) { 159 pi->mouseState = start; 160 pi->eventHeld = FALSE; 161 } 162} 163 164static void 165KdNonBlockFd (int fd) 166{ 167 int flags; 168 flags = fcntl (fd, F_GETFL); 169 flags |= FASYNC|NOBLOCK; 170 fcntl (fd, F_SETFL, flags); 171} 172 173static void 174KdAddFd (int fd) 175{ 176 struct sigaction act; 177 sigset_t set; 178 179 kdnFds++; 180 fcntl (fd, F_SETOWN, getpid()); 181 KdNonBlockFd (fd); 182 AddEnabledDevice (fd); 183 memset (&act, '\0', sizeof act); 184 act.sa_handler = KdSigio; 185 sigemptyset (&act.sa_mask); 186 sigaddset (&act.sa_mask, SIGIO); 187 sigaddset (&act.sa_mask, SIGALRM); 188 sigaddset (&act.sa_mask, SIGVTALRM); 189 sigaction (SIGIO, &act, 0); 190 sigemptyset (&set); 191 sigprocmask (SIG_SETMASK, &set, 0); 192} 193 194static void 195KdRemoveFd (int fd) 196{ 197 struct sigaction act; 198 int flags; 199 200 kdnFds--; 201 RemoveEnabledDevice (fd); 202 flags = fcntl (fd, F_GETFL); 203 flags &= ~(FASYNC|NOBLOCK); 204 fcntl (fd, F_SETFL, flags); 205 if (kdnFds == 0) 206 { 207 memset (&act, '\0', sizeof act); 208 act.sa_handler = SIG_IGN; 209 sigemptyset (&act.sa_mask); 210 sigaction (SIGIO, &act, 0); 211 } 212} 213 214Bool 215KdRegisterFd (int fd, void (*read) (int fd, void *closure), void *closure) 216{ 217 if (kdNumInputFds == KD_MAX_INPUT_FDS) 218 return FALSE; 219 kdInputFds[kdNumInputFds].fd = fd; 220 kdInputFds[kdNumInputFds].read = read; 221 kdInputFds[kdNumInputFds].enable = 0; 222 kdInputFds[kdNumInputFds].disable = 0; 223 kdInputFds[kdNumInputFds].closure = closure; 224 kdNumInputFds++; 225 if (kdInputEnabled) 226 KdAddFd (fd); 227 return TRUE; 228} 229 230void 231KdUnregisterFd (void *closure, int fd, Bool do_close) 232{ 233 int i, j; 234 235 for (i = 0; i < kdNumInputFds; i++) { 236 if (kdInputFds[i].closure == closure && 237 (fd == -1 || kdInputFds[i].fd == fd)) { 238 if (kdInputEnabled) 239 KdRemoveFd (kdInputFds[i].fd); 240 if (do_close) 241 close (kdInputFds[i].fd); 242 kdNumInputFds--; 243 for (j = i; j < kdNumInputFds; j++) 244 kdInputFds[j] = kdInputFds[j+1]; 245 break; 246 } 247 } 248} 249 250void 251KdUnregisterFds (void *closure, Bool do_close) 252{ 253 KdUnregisterFd(closure, -1, do_close); 254} 255 256void 257KdDisableInput (void) 258{ 259 KdKeyboardInfo *ki; 260 KdPointerInfo *pi; 261 int found = 0, i = 0; 262 263 KdBlockSigio(); 264 265 for (ki = kdKeyboards; ki; ki = ki->next) { 266 if (ki->driver && ki->driver->Disable) 267 (*ki->driver->Disable) (ki); 268 } 269 270 for (pi = kdPointers; pi; pi = pi->next) { 271 if (pi->driver && pi->driver->Disable) 272 (*pi->driver->Disable) (pi); 273 } 274 275 if (kdNumInputFds) { 276 ErrorF("[KdDisableInput] Buggy drivers: still %d input fds left!", 277 kdNumInputFds); 278 i = 0; 279 while (i < kdNumInputFds) { 280 found = 0; 281 for (ki = kdKeyboards; ki; ki = ki->next) { 282 if (ki == kdInputFds[i].closure) { 283 ErrorF(" fd %d belongs to keybd driver %s\n", 284 kdInputFds[i].fd, 285 ki->driver && ki->driver->name ? 286 ki->driver->name : "(unnamed!)"); 287 found = 1; 288 break; 289 } 290 } 291 292 if (found) { 293 i++; 294 continue; 295 } 296 297 for (pi = kdPointers; pi; pi = pi->next) { 298 if (pi == kdInputFds[i].closure) { 299 ErrorF(" fd %d belongs to pointer driver %s\n", 300 kdInputFds[i].fd, 301 pi->driver && pi->driver->name ? 302 pi->driver->name : "(unnamed!)"); 303 break; 304 } 305 } 306 307 if (found) { 308 i++; 309 continue; 310 } 311 312 ErrorF(" fd %d not claimed by any active device!\n", 313 kdInputFds[i].fd); 314 KdUnregisterFd(kdInputFds[i].closure, kdInputFds[i].fd, TRUE); 315 } 316 } 317 318 kdInputEnabled = FALSE; 319} 320 321void 322KdEnableInput (void) 323{ 324 InternalEvent ev; 325 KdKeyboardInfo *ki; 326 KdPointerInfo *pi; 327 328 kdInputEnabled = TRUE; 329 330 for (ki = kdKeyboards; ki; ki = ki->next) { 331 if (ki->driver && ki->driver->Enable) 332 (*ki->driver->Enable) (ki); 333 } 334 335 for (pi = kdPointers; pi; pi = pi->next) { 336 if (pi->driver && pi->driver->Enable) 337 (*pi->driver->Enable) (pi); 338 } 339 340 /* reset screen saver */ 341 ev.any.time = GetTimeInMillis (); 342 NoticeEventTime (&ev); 343 344 KdUnblockSigio (); 345} 346 347static KdKeyboardDriver * 348KdFindKeyboardDriver (char *name) 349{ 350 KdKeyboardDriver *ret; 351 352 /* ask a stupid question ... */ 353 if (!name) 354 return NULL; 355 356 for (ret = kdKeyboardDrivers; ret; ret = ret->next) { 357 if (strcmp(ret->name, name) == 0) 358 return ret; 359 } 360 361 return NULL; 362} 363 364static KdPointerDriver * 365KdFindPointerDriver (char *name) 366{ 367 KdPointerDriver *ret; 368 369 /* ask a stupid question ... */ 370 if (!name) 371 return NULL; 372 373 for (ret = kdPointerDrivers; ret; ret = ret->next) { 374 if (strcmp(ret->name, name) == 0) 375 return ret; 376 } 377 378 return NULL; 379} 380 381static int 382KdPointerProc(DeviceIntPtr pDevice, int onoff) 383{ 384 DevicePtr pDev = (DevicePtr)pDevice; 385 KdPointerInfo *pi; 386 Atom xiclass; 387 Atom *btn_labels; 388 Atom *axes_labels; 389 390 if (!pDev) 391 return BadImplementation; 392 393 for (pi = kdPointers; pi; pi = pi->next) { 394 if (pi->dixdev && pi->dixdev->id == pDevice->id) 395 break; 396 } 397 398 if (!pi || !pi->dixdev || pi->dixdev->id != pDevice->id) { 399 ErrorF("[KdPointerProc] Failed to find pointer for device %d!\n", 400 pDevice->id); 401 return BadImplementation; 402 } 403 404 switch (onoff) 405 { 406 case DEVICE_INIT: 407#ifdef DEBUG 408 ErrorF("initialising pointer %s ...\n", pi->name); 409#endif 410 if (!pi->driver) { 411 if (!pi->driverPrivate) { 412 ErrorF("no driver specified for %s\n", pi->name); 413 return BadImplementation; 414 } 415 416 pi->driver = KdFindPointerDriver(pi->driverPrivate); 417 if (!pi->driver) { 418 ErrorF("Couldn't find pointer driver %s\n", 419 pi->driverPrivate ? (char *) pi->driverPrivate : 420 "(unnamed)"); 421 return !Success; 422 } 423 free(pi->driverPrivate); 424 pi->driverPrivate = NULL; 425 } 426 427 if (!pi->driver->Init) { 428 ErrorF("no init function\n"); 429 return BadImplementation; 430 } 431 432 if ((*pi->driver->Init) (pi) != Success) { 433 return !Success; 434 } 435 436 btn_labels = calloc(pi->nButtons, sizeof(Atom)); 437 if (!btn_labels) 438 return BadAlloc; 439 axes_labels = calloc(pi->nAxes, sizeof(Atom)); 440 if (!axes_labels) { 441 free(btn_labels); 442 return BadAlloc; 443 } 444 445 switch(pi->nAxes) 446 { 447 default: 448 case 7: 449 btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT); 450 case 6: 451 btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT); 452 case 5: 453 btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN); 454 case 4: 455 btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP); 456 case 3: 457 btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT); 458 case 2: 459 btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE); 460 case 1: 461 btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT); 462 case 0: 463 break; 464 } 465 466 if (pi->nAxes >= 2) { 467 axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X); 468 axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y); 469 } 470 471 InitPointerDeviceStruct(pDev, pi->map, pi->nButtons, btn_labels, 472 (PtrCtrlProcPtr)NoopDDA, 473 GetMotionHistorySize(), pi->nAxes, axes_labels); 474 475 free(btn_labels); 476 free(axes_labels); 477 478 if (pi->inputClass == KD_TOUCHSCREEN) { 479 InitAbsoluteClassDeviceStruct(pDevice); 480 xiclass = AtomFromName(XI_TOUCHSCREEN); 481 } 482 else { 483 xiclass = AtomFromName(XI_MOUSE); 484 } 485 486 AssignTypeAndName(pi->dixdev, xiclass, 487 pi->name ? pi->name : "Generic KDrive Pointer"); 488 489 return Success; 490 491 case DEVICE_ON: 492 if (pDev->on == TRUE) 493 return Success; 494 495 if (!pi->driver->Enable) { 496 ErrorF("no enable function\n"); 497 return BadImplementation; 498 } 499 500 if ((*pi->driver->Enable) (pi) == Success) { 501 pDev->on = TRUE; 502 return Success; 503 } 504 else { 505 return BadImplementation; 506 } 507 508 return Success; 509 510 case DEVICE_OFF: 511 if (pDev->on == FALSE) { 512 return Success; 513 } 514 515 if (!pi->driver->Disable) { 516 return BadImplementation; 517 } 518 else { 519 (*pi->driver->Disable) (pi); 520 pDev->on = FALSE; 521 return Success; 522 } 523 524 return Success; 525 526 case DEVICE_CLOSE: 527 if (pDev->on) { 528 if (!pi->driver->Disable) { 529 return BadImplementation; 530 } 531 (*pi->driver->Disable) (pi); 532 pDev->on = FALSE; 533 } 534 535 if (!pi->driver->Fini) 536 return BadImplementation; 537 538 (*pi->driver->Fini) (pi); 539 540 KdRemovePointer(pi); 541 542 return Success; 543 } 544 545 /* NOTREACHED */ 546 return BadImplementation; 547} 548 549Bool 550LegalModifier(unsigned int key, DeviceIntPtr pDev) 551{ 552 return TRUE; 553} 554 555static void 556KdBell (int volume, DeviceIntPtr pDev, pointer arg, int something) 557{ 558 KeybdCtrl *ctrl = arg; 559 KdKeyboardInfo *ki = NULL; 560 561 for (ki = kdKeyboards; ki; ki = ki->next) { 562 if (ki->dixdev && ki->dixdev->id == pDev->id) 563 break; 564 } 565 566 if (!ki || !ki->dixdev || ki->dixdev->id != pDev->id || !ki->driver) 567 return; 568 569 KdRingBell(ki, volume, ctrl->bell_pitch, ctrl->bell_duration); 570} 571 572void 573DDXRingBell(int volume, int pitch, int duration) 574{ 575 KdKeyboardInfo *ki = NULL; 576 577 if (kdOsFuncs->Bell) { 578 (*kdOsFuncs->Bell)(volume, pitch, duration); 579 } 580 else { 581 for (ki = kdKeyboards; ki; ki = ki->next) { 582 if (ki->dixdev->coreEvents) 583 KdRingBell(ki, volume, pitch, duration); 584 } 585 } 586} 587 588void 589KdRingBell(KdKeyboardInfo *ki, int volume, int pitch, int duration) 590{ 591 if (!ki || !ki->driver || !ki->driver->Bell) 592 return; 593 594 if (kdInputEnabled) 595 (*ki->driver->Bell) (ki, volume, pitch, duration); 596} 597 598 599static void 600KdSetLeds (KdKeyboardInfo *ki, int leds) 601{ 602 if (!ki || !ki->driver) 603 return; 604 605 if (kdInputEnabled) { 606 if (ki->driver->Leds) 607 (*ki->driver->Leds) (ki, leds); 608 } 609} 610 611void 612KdSetLed (KdKeyboardInfo *ki, int led, Bool on) 613{ 614 if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed) 615 return; 616 617 NoteLedState (ki->dixdev, led, on); 618 KdSetLeds (ki, ki->dixdev->kbdfeed->ctrl.leds); 619} 620 621void 622KdSetPointerMatrix (KdPointerMatrix *matrix) 623{ 624 kdPointerMatrix = *matrix; 625} 626 627void 628KdComputePointerMatrix (KdPointerMatrix *m, Rotation randr, int width, 629 int height) 630{ 631 int x_dir = 1, y_dir = 1; 632 int i, j; 633 int size[2]; 634 635 size[0] = width; size[1] = height; 636 if (randr & RR_Reflect_X) 637 x_dir = -1; 638 if (randr & RR_Reflect_Y) 639 y_dir = -1; 640 switch (randr & (RR_Rotate_All)) { 641 case RR_Rotate_0: 642 m->matrix[0][0] = x_dir; m->matrix[0][1] = 0; 643 m->matrix[1][0] = 0; m->matrix[1][1] = y_dir; 644 break; 645 case RR_Rotate_90: 646 m->matrix[0][0] = 0; m->matrix[0][1] = -x_dir; 647 m->matrix[1][0] = y_dir; m->matrix[1][1] = 0; 648 break; 649 case RR_Rotate_180: 650 m->matrix[0][0] = -x_dir; m->matrix[0][1] = 0; 651 m->matrix[1][0] = 0; m->matrix[1][1] = -y_dir; 652 break; 653 case RR_Rotate_270: 654 m->matrix[0][0] = 0; m->matrix[0][1] = x_dir; 655 m->matrix[1][0] = -y_dir; m->matrix[1][1] = 0; 656 break; 657 } 658 for (i = 0; i < 2; i++) 659 { 660 m->matrix[i][2] = 0; 661 for (j = 0 ; j < 2; j++) 662 if (m->matrix[i][j] < 0) 663 m->matrix[i][2] = size[j] - 1; 664 } 665} 666 667void 668KdScreenToPointerCoords (int *x, int *y) 669{ 670 int (*m)[3] = kdPointerMatrix.matrix; 671 int div = m[0][1] * m[1][0] - m[1][1] * m[0][0]; 672 int sx = *x; 673 int sy = *y; 674 675 *x = (m[0][1] * sy - m[0][1] * m[1][2] + m[1][1] * m[0][2] - m[1][1] * sx) / div; 676 *y = (m[1][0] * sx + m[0][0] * m[1][2] - m[1][0] * m[0][2] - m[0][0] * sy) / div; 677} 678 679static void 680KdKbdCtrl (DeviceIntPtr pDevice, KeybdCtrl *ctrl) 681{ 682 KdKeyboardInfo *ki; 683 684 for (ki = kdKeyboards; ki; ki = ki->next) { 685 if (ki->dixdev && ki->dixdev->id == pDevice->id) 686 break; 687 } 688 689 if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id || !ki->driver) 690 return; 691 692 KdSetLeds(ki, ctrl->leds); 693 ki->bellPitch = ctrl->bell_pitch; 694 ki->bellDuration = ctrl->bell_duration; 695} 696 697extern KeybdCtrl defaultKeyboardControl; 698 699static int 700KdKeyboardProc(DeviceIntPtr pDevice, int onoff) 701{ 702 Bool ret; 703 DevicePtr pDev = (DevicePtr)pDevice; 704 KdKeyboardInfo *ki; 705 Atom xiclass; 706 XkbRMLVOSet rmlvo; 707 708 if (!pDev) 709 return BadImplementation; 710 711 for (ki = kdKeyboards; ki; ki = ki->next) { 712 if (ki->dixdev && ki->dixdev->id == pDevice->id) 713 break; 714 } 715 716 if (!ki || !ki->dixdev || ki->dixdev->id != pDevice->id) { 717 return BadImplementation; 718 } 719 720 switch (onoff) 721 { 722 case DEVICE_INIT: 723#ifdef DEBUG 724 ErrorF("initialising keyboard %s\n", ki->name); 725#endif 726 if (!ki->driver) { 727 if (!ki->driverPrivate) { 728 ErrorF("no driver specified!\n"); 729 return BadImplementation; 730 } 731 732 ki->driver = KdFindKeyboardDriver(ki->driverPrivate); 733 if (!ki->driver) { 734 ErrorF("Couldn't find keyboard driver %s\n", 735 ki->driverPrivate ? (char *) ki->driverPrivate : 736 "(unnamed)"); 737 return !Success; 738 } 739 free(ki->driverPrivate); 740 ki->driverPrivate = NULL; 741 } 742 743 if (!ki->driver->Init) { 744 ErrorF("Keyboard %s: no init function\n", ki->name); 745 return BadImplementation; 746 } 747 748 if ((*ki->driver->Init) (ki) != Success) { 749 return !Success; 750 } 751 752 memset(&rmlvo, 0, sizeof(rmlvo)); 753 rmlvo.rules = ki->xkbRules; 754 rmlvo.model = ki->xkbModel; 755 rmlvo.layout = ki->xkbLayout; 756 rmlvo.variant = ki->xkbVariant; 757 rmlvo.options = ki->xkbOptions; 758 ret = InitKeyboardDeviceStruct (pDevice, &rmlvo, KdBell, KdKbdCtrl); 759 if (!ret) { 760 ErrorF("Couldn't initialise keyboard %s\n", ki->name); 761 return BadImplementation; 762 } 763 764 xiclass = AtomFromName(XI_KEYBOARD); 765 AssignTypeAndName(pDevice, xiclass, 766 ki->name ? ki->name : "Generic KDrive Keyboard"); 767 768 KdResetInputMachine(); 769 770 return Success; 771 772 case DEVICE_ON: 773 if (pDev->on == TRUE) 774 return Success; 775 776 if (!ki->driver->Enable) 777 return BadImplementation; 778 779 if ((*ki->driver->Enable) (ki) != Success) { 780 return BadMatch; 781 } 782 783 pDev->on = TRUE; 784 return Success; 785 786 case DEVICE_OFF: 787 if (pDev->on == FALSE) 788 return Success; 789 790 if (!ki->driver->Disable) 791 return BadImplementation; 792 793 (*ki->driver->Disable) (ki); 794 pDev->on = FALSE; 795 796 return Success; 797 798 break; 799 800 case DEVICE_CLOSE: 801 if (pDev->on) { 802 if (!ki->driver->Disable) 803 return BadImplementation; 804 805 (*ki->driver->Disable) (ki); 806 pDev->on = FALSE; 807 } 808 809 if (!ki->driver->Fini) 810 return BadImplementation; 811 812 (*ki->driver->Fini) (ki); 813 814 KdRemoveKeyboard(ki); 815 816 return Success; 817 } 818 819 /* NOTREACHED */ 820 return BadImplementation; 821} 822 823void 824KdAddPointerDriver (KdPointerDriver *driver) 825{ 826 KdPointerDriver **prev; 827 828 if (!driver) 829 return; 830 831 for (prev = &kdPointerDrivers; *prev; prev = &(*prev)->next) { 832 if (*prev == driver) 833 return; 834 } 835 *prev = driver; 836} 837 838void 839KdRemovePointerDriver (KdPointerDriver *driver) 840{ 841 KdPointerDriver *tmp; 842 843 if (!driver) 844 return; 845 846 /* FIXME remove all pointers using this driver */ 847 for (tmp = kdPointerDrivers; tmp; tmp = tmp->next) { 848 if (tmp->next == driver) 849 tmp->next = driver->next; 850 } 851 if (tmp == driver) 852 tmp = NULL; 853} 854 855void 856KdAddKeyboardDriver (KdKeyboardDriver *driver) 857{ 858 KdKeyboardDriver **prev; 859 860 if (!driver) 861 return; 862 863 for (prev = &kdKeyboardDrivers; *prev; prev = &(*prev)->next) { 864 if (*prev == driver) 865 return; 866 } 867 *prev = driver; 868} 869 870void 871KdRemoveKeyboardDriver (KdKeyboardDriver *driver) 872{ 873 KdKeyboardDriver *tmp; 874 875 if (!driver) 876 return; 877 878 /* FIXME remove all keyboards using this driver */ 879 for (tmp = kdKeyboardDrivers; tmp; tmp = tmp->next) { 880 if (tmp->next == driver) 881 tmp->next = driver->next; 882 } 883 if (tmp == driver) 884 tmp = NULL; 885} 886 887KdKeyboardInfo * 888KdNewKeyboard (void) 889{ 890 KdKeyboardInfo *ki = calloc(sizeof(KdKeyboardInfo), 1); 891 if (!ki) 892 return NULL; 893 894 ki->minScanCode = 0; 895 ki->maxScanCode = 0; 896 ki->leds = 0; 897 ki->bellPitch = 1000; 898 ki->bellDuration = 200; 899 ki->next = NULL; 900 ki->options = NULL; 901 ki->xkbRules = strdup(XKB_DFLT_RULES); 902 ki->xkbModel = strdup(XKB_DFLT_MODEL); 903 ki->xkbLayout = strdup(XKB_DFLT_LAYOUT); 904 ki->xkbVariant = strdup(XKB_DFLT_VARIANT); 905 ki->xkbOptions = strdup(XKB_DFLT_OPTIONS); 906 907 return ki; 908} 909 910int 911KdAddConfigKeyboard (char *keyboard) 912{ 913 struct KdConfigDevice **prev, *new; 914 915 if (!keyboard) 916 return Success; 917 918 new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); 919 if (!new) 920 return BadAlloc; 921 922 new->line = strdup(keyboard); 923 new->next = NULL; 924 925 for (prev = &kdConfigKeyboards; *prev; prev = &(*prev)->next); 926 *prev = new; 927 928 return Success; 929} 930 931int 932KdAddKeyboard (KdKeyboardInfo *ki) 933{ 934 KdKeyboardInfo **prev; 935 936 if (!ki) 937 return !Success; 938 939 ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE); 940 if (!ki->dixdev) { 941 ErrorF("Couldn't register keyboard device %s\n", 942 ki->name ? ki->name : "(unnamed)"); 943 return !Success; 944 } 945 946 ki->dixdev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; 947 ki->dixdev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; 948 RegisterOtherDevice(ki->dixdev); 949 950#ifdef DEBUG 951 ErrorF("added keyboard %s with dix id %d\n", ki->name, ki->dixdev->id); 952#endif 953 954 for (prev = &kdKeyboards; *prev; prev = &(*prev)->next); 955 *prev = ki; 956 957 return Success; 958} 959 960void 961KdRemoveKeyboard (KdKeyboardInfo *ki) 962{ 963 KdKeyboardInfo **prev; 964 965 if (!ki) 966 return; 967 968 for (prev = &kdKeyboards; *prev; prev = &(*prev)->next) { 969 if (*prev == ki) { 970 *prev = ki->next; 971 break; 972 } 973 } 974 975 KdFreeKeyboard(ki); 976} 977 978int 979KdAddConfigPointer (char *pointer) 980{ 981 struct KdConfigDevice **prev, *new; 982 983 if (!pointer) 984 return Success; 985 986 new = (struct KdConfigDevice *) calloc(sizeof(struct KdConfigDevice), 1); 987 if (!new) 988 return BadAlloc; 989 990 new->line = strdup(pointer); 991 new->next = NULL; 992 993 for (prev = &kdConfigPointers; *prev; prev = &(*prev)->next); 994 *prev = new; 995 996 return Success; 997} 998 999int 1000KdAddPointer (KdPointerInfo *pi) 1001{ 1002 KdPointerInfo **prev; 1003 1004 if (!pi) 1005 return Success; 1006 1007 pi->mouseState = start; 1008 pi->eventHeld = FALSE; 1009 1010 pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE); 1011 if (!pi->dixdev) { 1012 ErrorF("Couldn't add pointer device %s\n", 1013 pi->name ? pi->name : "(unnamed)"); 1014 return BadDevice; 1015 } 1016 1017 pi->dixdev->deviceGrab.ActivateGrab = ActivatePointerGrab; 1018 pi->dixdev->deviceGrab.DeactivateGrab = DeactivatePointerGrab; 1019 RegisterOtherDevice(pi->dixdev); 1020 1021 for (prev = &kdPointers; *prev; prev = &(*prev)->next); 1022 *prev = pi; 1023 1024 return Success; 1025} 1026 1027void 1028KdRemovePointer (KdPointerInfo *pi) 1029{ 1030 KdPointerInfo **prev; 1031 1032 if (!pi) 1033 return; 1034 1035 for (prev = &kdPointers; *prev; prev = &(*prev)->next) { 1036 if (*prev == pi) { 1037 *prev = pi->next; 1038 break; 1039 } 1040 } 1041 1042 KdFreePointer(pi); 1043} 1044 1045/* 1046 * You can call your kdriver server with something like: 1047 * $ ./hw/kdrive/yourserver/X :1 -mouse evdev,,device=/dev/input/event4 -keybd 1048 * evdev,,device=/dev/input/event1,xkbmodel=abnt2,xkblayout=br 1049 */ 1050static Bool 1051KdGetOptions (InputOption **options, char *string) 1052{ 1053 InputOption *newopt = NULL, **tmpo = NULL; 1054 int tam_key = 0; 1055 1056 newopt = calloc(1, sizeof (InputOption)); 1057 if (!newopt) 1058 return FALSE; 1059 1060 for (tmpo = options; *tmpo; tmpo = &(*tmpo)->next) 1061 ; /* Hello, I'm here */ 1062 *tmpo = newopt; 1063 1064 if (strchr(string, '=')) 1065 { 1066 tam_key = (strchr(string, '=') - string); 1067 newopt->key = (char *)malloc(tam_key); 1068 strncpy(newopt->key, string, tam_key); 1069 newopt->key[tam_key] = '\0'; 1070 newopt->value = strdup(strchr(string, '=') + 1); 1071 } 1072 else 1073 { 1074 newopt->key = strdup(string); 1075 newopt->value = NULL; 1076 } 1077 newopt->next = NULL; 1078 1079 return TRUE; 1080} 1081 1082static void 1083KdParseKbdOptions (KdKeyboardInfo *ki) 1084{ 1085 InputOption *option = NULL; 1086 1087 for (option = ki->options; option; option = option->next) 1088 { 1089 if (strcasecmp(option->key, "XkbRules") == 0) 1090 ki->xkbRules = option->value; 1091 else if (strcasecmp(option->key, "XkbModel") == 0) 1092 ki->xkbModel = option->value; 1093 else if (strcasecmp(option->key, "XkbLayout") == 0) 1094 ki->xkbLayout = option->value; 1095 else if (strcasecmp(option->key, "XkbVariant") == 0) 1096 ki->xkbVariant = option->value; 1097 else if (strcasecmp(option->key, "XkbOptions") == 0) 1098 ki->xkbOptions = option->value; 1099 else if (!strcasecmp (option->key, "device")) 1100 ki->path = strdup(option->value); 1101 else 1102 ErrorF("Kbd option key (%s) of value (%s) not assigned!\n", 1103 option->key, option->value); 1104 } 1105} 1106 1107KdKeyboardInfo * 1108KdParseKeyboard (char *arg) 1109{ 1110 char save[1024]; 1111 char delim; 1112 InputOption *options = NULL; 1113 KdKeyboardInfo *ki = NULL; 1114 1115 ki = KdNewKeyboard(); 1116 if (!ki) 1117 return NULL; 1118 1119 ki->name = strdup("Unknown KDrive Keyboard"); 1120 ki->path = NULL; 1121 ki->driver = NULL; 1122 ki->driverPrivate = NULL; 1123 ki->next = NULL; 1124 1125 if (!arg) 1126 { 1127 ErrorF("keybd: no arg\n"); 1128 KdFreeKeyboard (ki); 1129 return NULL; 1130 } 1131 1132 if (strlen (arg) >= sizeof (save)) 1133 { 1134 ErrorF("keybd: arg too long\n"); 1135 KdFreeKeyboard (ki); 1136 return NULL; 1137 } 1138 1139 arg = KdParseFindNext (arg, ",", save, &delim); 1140 if (!save[0]) 1141 { 1142 ErrorF("keybd: failed on save[0]\n"); 1143 KdFreeKeyboard (ki); 1144 return NULL; 1145 } 1146 1147 if (strcmp (save, "auto") == 0) 1148 ki->driverPrivate = NULL; 1149 else 1150 ki->driverPrivate = strdup(save); 1151 1152 if (delim != ',') 1153 { 1154 return ki; 1155 } 1156 1157 arg = KdParseFindNext (arg, ",", save, &delim); 1158 1159 while (delim == ',') 1160 { 1161 arg = KdParseFindNext (arg, ",", save, &delim); 1162 1163 if (!KdGetOptions(&options, save)) 1164 { 1165 KdFreeKeyboard(ki); 1166 return NULL; 1167 } 1168 } 1169 1170 if (options) 1171 { 1172 ki->options = options; 1173 KdParseKbdOptions(ki); 1174 } 1175 1176 return ki; 1177} 1178 1179static void 1180KdParsePointerOptions (KdPointerInfo *pi) 1181{ 1182 InputOption *option = NULL; 1183 1184 for (option = pi->options; option; option = option->next) 1185 { 1186 if (!strcmp (option->key, "emulatemiddle")) 1187 pi->emulateMiddleButton = TRUE; 1188 else if (!strcmp (option->key, "noemulatemiddle")) 1189 pi->emulateMiddleButton = FALSE; 1190 else if (!strcmp (option->key, "transformcoord")) 1191 pi->transformCoordinates = TRUE; 1192 else if (!strcmp (option->key, "rawcoord")) 1193 pi->transformCoordinates = FALSE; 1194 else if (!strcasecmp (option->key, "device")) 1195 pi->path = strdup(option->value); 1196 else if (!strcasecmp (option->key, "protocol")) 1197 pi->protocol = strdup(option->value); 1198 else 1199 ErrorF("Pointer option key (%s) of value (%s) not assigned!\n", 1200 option->key, option->value); 1201 } 1202} 1203 1204KdPointerInfo * 1205KdParsePointer (char *arg) 1206{ 1207 char save[1024]; 1208 char delim; 1209 KdPointerInfo *pi = NULL; 1210 InputOption *options = NULL; 1211 int i = 0; 1212 1213 pi = KdNewPointer(); 1214 if (!pi) 1215 return NULL; 1216 pi->emulateMiddleButton = kdEmulateMiddleButton; 1217 pi->transformCoordinates = !kdRawPointerCoordinates; 1218 pi->protocol = NULL; 1219 pi->nButtons = 5; /* XXX should not be hardcoded */ 1220 pi->inputClass = KD_MOUSE; 1221 1222 if (!arg) 1223 { 1224 ErrorF("mouse: no arg\n"); 1225 KdFreePointer (pi); 1226 return NULL; 1227 } 1228 1229 if (strlen (arg) >= sizeof (save)) 1230 { 1231 ErrorF("mouse: arg too long\n"); 1232 KdFreePointer (pi); 1233 return NULL; 1234 } 1235 arg = KdParseFindNext (arg, ",", save, &delim); 1236 if (!save[0]) 1237 { 1238 ErrorF("failed on save[0]\n"); 1239 KdFreePointer (pi); 1240 return NULL; 1241 } 1242 1243 if (strcmp(save, "auto") == 0) 1244 pi->driverPrivate = NULL; 1245 else 1246 pi->driverPrivate = strdup(save); 1247 1248 if (delim != ',') 1249 { 1250 return pi; 1251 } 1252 1253 arg = KdParseFindNext (arg, ",", save, &delim); 1254 1255 while (delim == ',') 1256 { 1257 arg = KdParseFindNext (arg, ",", save, &delim); 1258 if (save[0] == '{') 1259 { 1260 char *s = save + 1; 1261 i = 0; 1262 while (*s && *s != '}') 1263 { 1264 if ('1' <= *s && *s <= '0' + pi->nButtons) 1265 pi->map[i] = *s - '0'; 1266 else 1267 UseMsg (); 1268 s++; 1269 } 1270 } 1271 else 1272 { 1273 if (!KdGetOptions(&options, save)) 1274 { 1275 KdFreePointer(pi); 1276 return NULL; 1277 } 1278 } 1279 } 1280 1281 if (options) 1282 { 1283 pi->options = options; 1284 KdParsePointerOptions(pi); 1285 } 1286 1287 return pi; 1288} 1289 1290 1291void 1292KdInitInput (void) 1293{ 1294 KdPointerInfo *pi; 1295 KdKeyboardInfo *ki; 1296 struct KdConfigDevice *dev; 1297 1298 kdInputEnabled = TRUE; 1299 1300 for (dev = kdConfigPointers; dev; dev = dev->next) { 1301 pi = KdParsePointer(dev->line); 1302 if (!pi) 1303 ErrorF("Failed to parse pointer\n"); 1304 if (KdAddPointer(pi) != Success) 1305 ErrorF("Failed to add pointer!\n"); 1306 } 1307 for (dev = kdConfigKeyboards; dev; dev = dev->next) { 1308 ki = KdParseKeyboard(dev->line); 1309 if (!ki) 1310 ErrorF("Failed to parse keyboard\n"); 1311 if (KdAddKeyboard(ki) != Success) 1312 ErrorF("Failed to add keyboard!\n"); 1313 } 1314 1315 mieqInit(); 1316} 1317 1318/* 1319 * Middle button emulation state machine 1320 * 1321 * Possible transitions: 1322 * Button 1 press v1 1323 * Button 1 release ^1 1324 * Button 2 press v2 1325 * Button 2 release ^2 1326 * Button 3 press v3 1327 * Button 3 release ^3 1328 * Button other press vo 1329 * Button other release ^o 1330 * Mouse motion <> 1331 * Keyboard event k 1332 * timeout ... 1333 * outside box <-> 1334 * 1335 * States: 1336 * start 1337 * button_1_pend 1338 * button_1_down 1339 * button_2_down 1340 * button_3_pend 1341 * button_3_down 1342 * synthetic_2_down_13 1343 * synthetic_2_down_3 1344 * synthetic_2_down_1 1345 * 1346 * Transition diagram 1347 * 1348 * start 1349 * v1 -> (hold) (settimeout) button_1_pend 1350 * ^1 -> (deliver) start 1351 * v2 -> (deliver) button_2_down 1352 * ^2 -> (deliever) start 1353 * v3 -> (hold) (settimeout) button_3_pend 1354 * ^3 -> (deliver) start 1355 * vo -> (deliver) start 1356 * ^o -> (deliver) start 1357 * <> -> (deliver) start 1358 * k -> (deliver) start 1359 * 1360 * button_1_pend (button 1 is down, timeout pending) 1361 * ^1 -> (release) (deliver) start 1362 * v2 -> (release) (deliver) button_1_down 1363 * ^2 -> (release) (deliver) button_1_down 1364 * v3 -> (cleartimeout) (generate v2) synthetic_2_down_13 1365 * ^3 -> (release) (deliver) button_1_down 1366 * vo -> (release) (deliver) button_1_down 1367 * ^o -> (release) (deliver) button_1_down 1368 * <-> -> (release) (deliver) button_1_down 1369 * <> -> (deliver) button_1_pend 1370 * k -> (release) (deliver) button_1_down 1371 * ... -> (release) button_1_down 1372 * 1373 * button_1_down (button 1 is down) 1374 * ^1 -> (deliver) start 1375 * v2 -> (deliver) button_1_down 1376 * ^2 -> (deliver) button_1_down 1377 * v3 -> (deliver) button_1_down 1378 * ^3 -> (deliver) button_1_down 1379 * vo -> (deliver) button_1_down 1380 * ^o -> (deliver) button_1_down 1381 * <> -> (deliver) button_1_down 1382 * k -> (deliver) button_1_down 1383 * 1384 * button_2_down (button 2 is down) 1385 * v1 -> (deliver) button_2_down 1386 * ^1 -> (deliver) button_2_down 1387 * ^2 -> (deliver) start 1388 * v3 -> (deliver) button_2_down 1389 * ^3 -> (deliver) button_2_down 1390 * vo -> (deliver) button_2_down 1391 * ^o -> (deliver) button_2_down 1392 * <> -> (deliver) button_2_down 1393 * k -> (deliver) button_2_down 1394 * 1395 * button_3_pend (button 3 is down, timeout pending) 1396 * v1 -> (generate v2) synthetic_2_down 1397 * ^1 -> (release) (deliver) button_3_down 1398 * v2 -> (release) (deliver) button_3_down 1399 * ^2 -> (release) (deliver) button_3_down 1400 * ^3 -> (release) (deliver) start 1401 * vo -> (release) (deliver) button_3_down 1402 * ^o -> (release) (deliver) button_3_down 1403 * <-> -> (release) (deliver) button_3_down 1404 * <> -> (deliver) button_3_pend 1405 * k -> (release) (deliver) button_3_down 1406 * ... -> (release) button_3_down 1407 * 1408 * button_3_down (button 3 is down) 1409 * v1 -> (deliver) button_3_down 1410 * ^1 -> (deliver) button_3_down 1411 * v2 -> (deliver) button_3_down 1412 * ^2 -> (deliver) button_3_down 1413 * ^3 -> (deliver) start 1414 * vo -> (deliver) button_3_down 1415 * ^o -> (deliver) button_3_down 1416 * <> -> (deliver) button_3_down 1417 * k -> (deliver) button_3_down 1418 * 1419 * synthetic_2_down_13 (button 1 and 3 are down) 1420 * ^1 -> (generate ^2) synthetic_2_down_3 1421 * v2 -> synthetic_2_down_13 1422 * ^2 -> synthetic_2_down_13 1423 * ^3 -> (generate ^2) synthetic_2_down_1 1424 * vo -> (deliver) synthetic_2_down_13 1425 * ^o -> (deliver) synthetic_2_down_13 1426 * <> -> (deliver) synthetic_2_down_13 1427 * k -> (deliver) synthetic_2_down_13 1428 * 1429 * synthetic_2_down_3 (button 3 is down) 1430 * v1 -> (deliver) synthetic_2_down_3 1431 * ^1 -> (deliver) synthetic_2_down_3 1432 * v2 -> synthetic_2_down_3 1433 * ^2 -> synthetic_2_down_3 1434 * ^3 -> start 1435 * vo -> (deliver) synthetic_2_down_3 1436 * ^o -> (deliver) synthetic_2_down_3 1437 * <> -> (deliver) synthetic_2_down_3 1438 * k -> (deliver) synthetic_2_down_3 1439 * 1440 * synthetic_2_down_1 (button 1 is down) 1441 * ^1 -> start 1442 * v2 -> synthetic_2_down_1 1443 * ^2 -> synthetic_2_down_1 1444 * v3 -> (deliver) synthetic_2_down_1 1445 * ^3 -> (deliver) synthetic_2_down_1 1446 * vo -> (deliver) synthetic_2_down_1 1447 * ^o -> (deliver) synthetic_2_down_1 1448 * <> -> (deliver) synthetic_2_down_1 1449 * k -> (deliver) synthetic_2_down_1 1450 */ 1451 1452typedef enum _inputClass { 1453 down_1, up_1, 1454 down_2, up_2, 1455 down_3, up_3, 1456 down_o, up_o, 1457 motion, outside_box, 1458 keyboard, timeout, 1459 num_input_class 1460} KdInputClass; 1461 1462typedef enum _inputAction { 1463 noop, 1464 hold, 1465 setto, 1466 deliver, 1467 release, 1468 clearto, 1469 gen_down_2, 1470 gen_up_2 1471} KdInputAction; 1472 1473#define MAX_ACTIONS 2 1474 1475typedef struct _inputTransition { 1476 KdInputAction actions[MAX_ACTIONS]; 1477 KdPointerState nextState; 1478} KdInputTransition; 1479 1480static const 1481KdInputTransition kdInputMachine[num_input_states][num_input_class] = { 1482 /* start */ 1483 { 1484 { { hold, setto }, button_1_pend }, /* v1 */ 1485 { { deliver, noop }, start }, /* ^1 */ 1486 { { deliver, noop }, button_2_down }, /* v2 */ 1487 { { deliver, noop }, start }, /* ^2 */ 1488 { { hold, setto }, button_3_pend }, /* v3 */ 1489 { { deliver, noop }, start }, /* ^3 */ 1490 { { deliver, noop }, start }, /* vo */ 1491 { { deliver, noop }, start }, /* ^o */ 1492 { { deliver, noop }, start }, /* <> */ 1493 { { deliver, noop }, start }, /* <-> */ 1494 { { noop, noop }, start }, /* k */ 1495 { { noop, noop }, start }, /* ... */ 1496 }, 1497 /* button_1_pend */ 1498 { 1499 { { noop, noop }, button_1_pend }, /* v1 */ 1500 { { release, deliver }, start }, /* ^1 */ 1501 { { release, deliver }, button_1_down }, /* v2 */ 1502 { { release, deliver }, button_1_down }, /* ^2 */ 1503 { { clearto, gen_down_2 }, synth_2_down_13 }, /* v3 */ 1504 { { release, deliver }, button_1_down }, /* ^3 */ 1505 { { release, deliver }, button_1_down }, /* vo */ 1506 { { release, deliver }, button_1_down }, /* ^o */ 1507 { { deliver, noop }, button_1_pend }, /* <> */ 1508 { { release, deliver }, button_1_down }, /* <-> */ 1509 { { noop, noop }, button_1_down }, /* k */ 1510 { { release, noop }, button_1_down }, /* ... */ 1511 }, 1512 /* button_1_down */ 1513 { 1514 { { noop, noop }, button_1_down }, /* v1 */ 1515 { { deliver, noop }, start }, /* ^1 */ 1516 { { deliver, noop }, button_1_down }, /* v2 */ 1517 { { deliver, noop }, button_1_down }, /* ^2 */ 1518 { { deliver, noop }, button_1_down }, /* v3 */ 1519 { { deliver, noop }, button_1_down }, /* ^3 */ 1520 { { deliver, noop }, button_1_down }, /* vo */ 1521 { { deliver, noop }, button_1_down }, /* ^o */ 1522 { { deliver, noop }, button_1_down }, /* <> */ 1523 { { deliver, noop }, button_1_down }, /* <-> */ 1524 { { noop, noop }, button_1_down }, /* k */ 1525 { { noop, noop }, button_1_down }, /* ... */ 1526 }, 1527 /* button_2_down */ 1528 { 1529 { { deliver, noop }, button_2_down }, /* v1 */ 1530 { { deliver, noop }, button_2_down }, /* ^1 */ 1531 { { noop, noop }, button_2_down }, /* v2 */ 1532 { { deliver, noop }, start }, /* ^2 */ 1533 { { deliver, noop }, button_2_down }, /* v3 */ 1534 { { deliver, noop }, button_2_down }, /* ^3 */ 1535 { { deliver, noop }, button_2_down }, /* vo */ 1536 { { deliver, noop }, button_2_down }, /* ^o */ 1537 { { deliver, noop }, button_2_down }, /* <> */ 1538 { { deliver, noop }, button_2_down }, /* <-> */ 1539 { { noop, noop }, button_2_down }, /* k */ 1540 { { noop, noop }, button_2_down }, /* ... */ 1541 }, 1542 /* button_3_pend */ 1543 { 1544 { { clearto, gen_down_2 }, synth_2_down_13 }, /* v1 */ 1545 { { release, deliver }, button_3_down }, /* ^1 */ 1546 { { release, deliver }, button_3_down }, /* v2 */ 1547 { { release, deliver }, button_3_down }, /* ^2 */ 1548 { { release, deliver }, button_3_down }, /* v3 */ 1549 { { release, deliver }, start }, /* ^3 */ 1550 { { release, deliver }, button_3_down }, /* vo */ 1551 { { release, deliver }, button_3_down }, /* ^o */ 1552 { { deliver, noop }, button_3_pend }, /* <> */ 1553 { { release, deliver }, button_3_down }, /* <-> */ 1554 { { release, noop }, button_3_down }, /* k */ 1555 { { release, noop }, button_3_down }, /* ... */ 1556 }, 1557 /* button_3_down */ 1558 { 1559 { { deliver, noop }, button_3_down }, /* v1 */ 1560 { { deliver, noop }, button_3_down }, /* ^1 */ 1561 { { deliver, noop }, button_3_down }, /* v2 */ 1562 { { deliver, noop }, button_3_down }, /* ^2 */ 1563 { { noop, noop }, button_3_down }, /* v3 */ 1564 { { deliver, noop }, start }, /* ^3 */ 1565 { { deliver, noop }, button_3_down }, /* vo */ 1566 { { deliver, noop }, button_3_down }, /* ^o */ 1567 { { deliver, noop }, button_3_down }, /* <> */ 1568 { { deliver, noop }, button_3_down }, /* <-> */ 1569 { { noop, noop }, button_3_down }, /* k */ 1570 { { noop, noop }, button_3_down }, /* ... */ 1571 }, 1572 /* synthetic_2_down_13 */ 1573 { 1574 { { noop, noop }, synth_2_down_13 }, /* v1 */ 1575 { { gen_up_2, noop }, synth_2_down_3 }, /* ^1 */ 1576 { { noop, noop }, synth_2_down_13 }, /* v2 */ 1577 { { noop, noop }, synth_2_down_13 }, /* ^2 */ 1578 { { noop, noop }, synth_2_down_13 }, /* v3 */ 1579 { { gen_up_2, noop }, synth_2_down_1 }, /* ^3 */ 1580 { { deliver, noop }, synth_2_down_13 }, /* vo */ 1581 { { deliver, noop }, synth_2_down_13 }, /* ^o */ 1582 { { deliver, noop }, synth_2_down_13 }, /* <> */ 1583 { { deliver, noop }, synth_2_down_13 }, /* <-> */ 1584 { { noop, noop }, synth_2_down_13 }, /* k */ 1585 { { noop, noop }, synth_2_down_13 }, /* ... */ 1586 }, 1587 /* synthetic_2_down_3 */ 1588 { 1589 { { deliver, noop }, synth_2_down_3 }, /* v1 */ 1590 { { deliver, noop }, synth_2_down_3 }, /* ^1 */ 1591 { { deliver, noop }, synth_2_down_3 }, /* v2 */ 1592 { { deliver, noop }, synth_2_down_3 }, /* ^2 */ 1593 { { noop, noop }, synth_2_down_3 }, /* v3 */ 1594 { { noop, noop }, start }, /* ^3 */ 1595 { { deliver, noop }, synth_2_down_3 }, /* vo */ 1596 { { deliver, noop }, synth_2_down_3 }, /* ^o */ 1597 { { deliver, noop }, synth_2_down_3 }, /* <> */ 1598 { { deliver, noop }, synth_2_down_3 }, /* <-> */ 1599 { { noop, noop }, synth_2_down_3 }, /* k */ 1600 { { noop, noop }, synth_2_down_3 }, /* ... */ 1601 }, 1602 /* synthetic_2_down_1 */ 1603 { 1604 { { noop, noop }, synth_2_down_1 }, /* v1 */ 1605 { { noop, noop }, start }, /* ^1 */ 1606 { { deliver, noop }, synth_2_down_1 }, /* v2 */ 1607 { { deliver, noop }, synth_2_down_1 }, /* ^2 */ 1608 { { deliver, noop }, synth_2_down_1 }, /* v3 */ 1609 { { deliver, noop }, synth_2_down_1 }, /* ^3 */ 1610 { { deliver, noop }, synth_2_down_1 }, /* vo */ 1611 { { deliver, noop }, synth_2_down_1 }, /* ^o */ 1612 { { deliver, noop }, synth_2_down_1 }, /* <> */ 1613 { { deliver, noop }, synth_2_down_1 }, /* <-> */ 1614 { { noop, noop }, synth_2_down_1 }, /* k */ 1615 { { noop, noop }, synth_2_down_1 }, /* ... */ 1616 }, 1617}; 1618 1619#define EMULATION_WINDOW 10 1620#define EMULATION_TIMEOUT 100 1621 1622static int 1623KdInsideEmulationWindow (KdPointerInfo *pi, int x, int y, int z) 1624{ 1625 pi->emulationDx = pi->heldEvent.x - x; 1626 pi->emulationDy = pi->heldEvent.y - y; 1627 1628 return (abs (pi->emulationDx) < EMULATION_WINDOW && 1629 abs (pi->emulationDy) < EMULATION_WINDOW); 1630} 1631 1632static KdInputClass 1633KdClassifyInput (KdPointerInfo *pi, int type, int x, int y, int z, int b) 1634{ 1635 switch (type) { 1636 case ButtonPress: 1637 switch (b) { 1638 case 1: return down_1; 1639 case 2: return down_2; 1640 case 3: return down_3; 1641 default: return down_o; 1642 } 1643 break; 1644 case ButtonRelease: 1645 switch (b) { 1646 case 1: return up_1; 1647 case 2: return up_2; 1648 case 3: return up_3; 1649 default: return up_o; 1650 } 1651 break; 1652 case MotionNotify: 1653 if (pi->eventHeld && !KdInsideEmulationWindow(pi, x, y, z)) 1654 return outside_box; 1655 else 1656 return motion; 1657 default: 1658 return keyboard; 1659 } 1660 return keyboard; 1661} 1662 1663#ifdef DEBUG 1664char *kdStateNames[] = { 1665 "start", 1666 "button_1_pend", 1667 "button_1_down", 1668 "button_2_down", 1669 "button_3_pend", 1670 "button_3_down", 1671 "synth_2_down_13", 1672 "synth_2_down_3", 1673 "synthetic_2_down_1", 1674 "num_input_states" 1675}; 1676 1677char *kdClassNames[] = { 1678 "down_1", "up_1", 1679 "down_2", "up_2", 1680 "down_3", "up_3", 1681 "motion", "ouside_box", 1682 "keyboard", "timeout", 1683 "num_input_class" 1684}; 1685 1686char *kdActionNames[] = { 1687 "noop", 1688 "hold", 1689 "setto", 1690 "deliver", 1691 "release", 1692 "clearto", 1693 "gen_down_2", 1694 "gen_up_2", 1695}; 1696#endif /* DEBUG */ 1697 1698static void 1699KdQueueEvent (DeviceIntPtr pDev, InternalEvent *ev) 1700{ 1701 KdAssertSigioBlocked ("KdQueueEvent"); 1702 mieqEnqueue (pDev, ev); 1703} 1704 1705/* We return true if we're stealing the event. */ 1706static Bool 1707KdRunMouseMachine (KdPointerInfo *pi, KdInputClass c, int type, int x, int y, 1708 int z, int b, int absrel) 1709{ 1710 const KdInputTransition *t; 1711 int a; 1712 1713 c = KdClassifyInput(pi, type, x, y, z, b); 1714 t = &kdInputMachine[pi->mouseState][c]; 1715 for (a = 0; a < MAX_ACTIONS; a++) 1716 { 1717 switch (t->actions[a]) { 1718 case noop: 1719 break; 1720 case hold: 1721 pi->eventHeld = TRUE; 1722 pi->emulationDx = 0; 1723 pi->emulationDy = 0; 1724 pi->heldEvent.type = type; 1725 pi->heldEvent.x = x; 1726 pi->heldEvent.y = y; 1727 pi->heldEvent.z = z; 1728 pi->heldEvent.flags = b; 1729 pi->heldEvent.absrel = absrel; 1730 return TRUE; 1731 break; 1732 case setto: 1733 pi->emulationTimeout = GetTimeInMillis () + EMULATION_TIMEOUT; 1734 pi->timeoutPending = TRUE; 1735 break; 1736 case deliver: 1737 _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x, 1738 pi->heldEvent.y, pi->heldEvent.z, 1739 pi->heldEvent.flags, pi->heldEvent.absrel, 1740 TRUE); 1741 break; 1742 case release: 1743 pi->eventHeld = FALSE; 1744 pi->timeoutPending = FALSE; 1745 _KdEnqueuePointerEvent (pi, pi->heldEvent.type, pi->heldEvent.x, 1746 pi->heldEvent.y, pi->heldEvent.z, 1747 pi->heldEvent.flags, pi->heldEvent.absrel, 1748 TRUE); 1749 return TRUE; 1750 break; 1751 case clearto: 1752 pi->timeoutPending = FALSE; 1753 break; 1754 case gen_down_2: 1755 _KdEnqueuePointerEvent (pi, ButtonPress, x, y, z, 2, absrel, 1756 TRUE); 1757 pi->eventHeld = FALSE; 1758 return TRUE; 1759 break; 1760 case gen_up_2: 1761 _KdEnqueuePointerEvent (pi, ButtonRelease, x, y, z, 2, absrel, 1762 TRUE); 1763 return TRUE; 1764 break; 1765 } 1766 } 1767 pi->mouseState = t->nextState; 1768 return FALSE; 1769} 1770 1771static int 1772KdHandlePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z, int b, 1773 int absrel) 1774{ 1775 if (pi->emulateMiddleButton) 1776 return KdRunMouseMachine (pi, KdClassifyInput(pi, type, x, y, z, b), 1777 type, x, y, z, b, absrel); 1778 return FALSE; 1779} 1780 1781static void 1782KdReceiveTimeout (KdPointerInfo *pi) 1783{ 1784 KdRunMouseMachine (pi, timeout, 0, 0, 0, 0, 0, 0); 1785} 1786 1787/* 1788 * kdCheckTermination 1789 * 1790 * This function checks for the key sequence that terminates the server. When 1791 * detected, it sets the dispatchException flag and returns. The key sequence 1792 * is: 1793 * Control-Alt 1794 * It's assumed that the server will be waken up by the caller when this 1795 * function returns. 1796 */ 1797 1798extern int nClients; 1799 1800void 1801KdReleaseAllKeys (void) 1802{ 1803#if 0 1804 int key, nEvents, i; 1805 KdKeyboardInfo *ki; 1806 1807 KdBlockSigio (); 1808 1809 for (ki = kdKeyboards; ki; ki = ki->next) { 1810 for (key = ki->keySyms.minKeyCode; key < ki->keySyms.maxKeyCode; 1811 key++) { 1812 if (key_is_down(ki->dixdev, key, KEY_POSTED | KEY_PROCESSED)) { 1813 KdHandleKeyboardEvent(ki, KeyRelease, key); 1814 GetEventList(&kdEvents); 1815 nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key); 1816 for (i = 0; i < nEvents; i++) 1817 KdQueueEvent (ki->dixdev, (kdEvents + i)->event); 1818 } 1819 } 1820 } 1821 1822 KdUnblockSigio (); 1823#endif 1824} 1825 1826static void 1827KdCheckLock (void) 1828{ 1829 KeyClassPtr keyc = NULL; 1830 Bool isSet = FALSE, shouldBeSet = FALSE; 1831 KdKeyboardInfo *tmp = NULL; 1832 1833 for (tmp = kdKeyboards; tmp; tmp = tmp->next) { 1834 if (tmp->LockLed && tmp->dixdev && tmp->dixdev->key) { 1835 keyc = tmp->dixdev->key; 1836 isSet = (tmp->leds & (1 << (tmp->LockLed-1))) != 0; 1837 /* FIXME: Just use XKB indicators! */ 1838 shouldBeSet = !!(XkbStateFieldFromRec(&keyc->xkbInfo->state) & LockMask); 1839 if (isSet != shouldBeSet) 1840 KdSetLed (tmp, tmp->LockLed, shouldBeSet); 1841 } 1842 } 1843} 1844 1845void 1846KdEnqueueKeyboardEvent(KdKeyboardInfo *ki, 1847 unsigned char scan_code, 1848 unsigned char is_up) 1849{ 1850 unsigned char key_code; 1851 KeyClassPtr keyc = NULL; 1852 KeybdCtrl *ctrl = NULL; 1853 int type, nEvents, i; 1854 1855 if (!ki || !ki->dixdev || !ki->dixdev->kbdfeed || !ki->dixdev->key) 1856 return; 1857 1858 keyc = ki->dixdev->key; 1859 ctrl = &ki->dixdev->kbdfeed->ctrl; 1860 1861 if (scan_code >= ki->minScanCode && scan_code <= ki->maxScanCode) 1862 { 1863 key_code = scan_code + KD_MIN_KEYCODE - ki->minScanCode; 1864 1865 /* 1866 * Set up this event -- the type may be modified below 1867 */ 1868 if (is_up) 1869 type = KeyRelease; 1870 else 1871 type = KeyPress; 1872 1873 GetEventList(&kdEvents); 1874 1875 nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code); 1876 for (i = 0; i < nEvents; i++) 1877 KdQueueEvent(ki->dixdev, (InternalEvent *)((kdEvents + i)->event)); 1878 } 1879 else { 1880 ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n", 1881 ki->name, scan_code, ki->minScanCode, ki->maxScanCode); 1882 } 1883} 1884 1885/* 1886 * kdEnqueuePointerEvent 1887 * 1888 * This function converts hardware mouse event information into X event 1889 * information. A mouse movement event is passed off to MI to generate 1890 * a MotionNotify event, if appropriate. Button events are created and 1891 * passed off to MI for enqueueing. 1892 */ 1893 1894/* FIXME do something a little more clever to deal with multiple axes here */ 1895void 1896KdEnqueuePointerEvent(KdPointerInfo *pi, unsigned long flags, int rx, int ry, 1897 int rz) 1898{ 1899 CARD32 ms; 1900 unsigned char buttons; 1901 int x, y, z; 1902 int (*matrix)[3] = kdPointerMatrix.matrix; 1903 unsigned long button; 1904 int n; 1905 int dixflags = 0; 1906 1907 if (!pi) 1908 return; 1909 1910 ms = GetTimeInMillis(); 1911 1912 /* we don't need to transform z, so we don't. */ 1913 if (flags & KD_MOUSE_DELTA) { 1914 if (pi->transformCoordinates) { 1915 x = matrix[0][0] * rx + matrix[0][1] * ry; 1916 y = matrix[1][0] * rx + matrix[1][1] * ry; 1917 } 1918 else { 1919 x = rx; 1920 y = ry; 1921 } 1922 } 1923 else { 1924 if (pi->transformCoordinates) { 1925 x = matrix[0][0] * rx + matrix[0][1] * ry + matrix[0][2]; 1926 y = matrix[1][0] * rx + matrix[1][1] * ry + matrix[1][2]; 1927 } 1928 else { 1929 x = rx; 1930 y = ry; 1931 } 1932 } 1933 z = rz; 1934 1935 if (flags & KD_MOUSE_DELTA) 1936 { 1937 if (x || y || z) 1938 { 1939 dixflags = POINTER_RELATIVE | POINTER_ACCELERATE; 1940 _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE); 1941 } 1942 } else 1943 { 1944 dixflags = POINTER_ABSOLUTE; 1945 if (x != pi->dixdev->last.valuators[0] || 1946 y != pi->dixdev->last.valuators[1]) 1947 _KdEnqueuePointerEvent(pi, MotionNotify, x, y, z, 0, dixflags, FALSE); 1948 } 1949 1950 buttons = flags; 1951 1952 for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons; 1953 button <<= 1, n++) { 1954 if (((pi->buttonState & button) ^ (buttons & button)) && 1955 !(buttons & button)) { 1956 _KdEnqueuePointerEvent(pi, ButtonRelease, x, y, z, n, 1957 dixflags, FALSE); 1958 } 1959 } 1960 for (button = KD_BUTTON_1, n = 1; n <= pi->nButtons; 1961 button <<= 1, n++) { 1962 if (((pi->buttonState & button) ^ (buttons & button)) && 1963 (buttons & button)) { 1964 _KdEnqueuePointerEvent(pi, ButtonPress, x, y, z, n, 1965 dixflags, FALSE); 1966 } 1967 } 1968 1969 pi->buttonState = buttons; 1970} 1971 1972void 1973_KdEnqueuePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z, 1974 int b, int absrel, Bool force) 1975{ 1976 int nEvents = 0, i = 0; 1977 int valuators[3] = { x, y, z }; 1978 1979 /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */ 1980 if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel)) 1981 return; 1982 1983 GetEventList(&kdEvents); 1984 nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel, 1985 0, 3, valuators); 1986 for (i = 0; i < nEvents; i++) 1987 KdQueueEvent(pi->dixdev, (InternalEvent *)((kdEvents + i)->event)); 1988} 1989 1990void 1991KdBlockHandler (int screen, 1992 pointer blockData, 1993 pointer timeout, 1994 pointer readmask) 1995{ 1996 KdPointerInfo *pi; 1997 int myTimeout=0; 1998 1999 for (pi = kdPointers; pi; pi = pi->next) 2000 { 2001 if (pi->timeoutPending) 2002 { 2003 int ms; 2004 2005 ms = pi->emulationTimeout - GetTimeInMillis (); 2006 if (ms < 1) 2007 ms = 1; 2008 if(ms<myTimeout || myTimeout==0) 2009 myTimeout=ms; 2010 } 2011 } 2012 /* if we need to poll for events, do that */ 2013 if(kdOsFuncs->pollEvents) 2014 { 2015 (*kdOsFuncs->pollEvents)(); 2016 myTimeout=20; 2017 } 2018 if(myTimeout>0) 2019 AdjustWaitForDelay (timeout, myTimeout); 2020} 2021 2022void 2023KdWakeupHandler (int screen, 2024 pointer data, 2025 unsigned long lresult, 2026 pointer readmask) 2027{ 2028 int result = (int) lresult; 2029 fd_set *pReadmask = (fd_set *) readmask; 2030 int i; 2031 KdPointerInfo *pi; 2032 2033 if (kdInputEnabled && result > 0) 2034 { 2035 for (i = 0; i < kdNumInputFds; i++) 2036 if (FD_ISSET (kdInputFds[i].fd, pReadmask)) 2037 { 2038 KdBlockSigio (); 2039 (*kdInputFds[i].read) (kdInputFds[i].fd, kdInputFds[i].closure); 2040 KdUnblockSigio (); 2041 } 2042 } 2043 for (pi = kdPointers; pi; pi = pi->next) 2044 { 2045 if (pi->timeoutPending) 2046 { 2047 if ((long) (GetTimeInMillis () - pi->emulationTimeout) >= 0) 2048 { 2049 pi->timeoutPending = FALSE; 2050 KdBlockSigio (); 2051 KdReceiveTimeout (pi); 2052 KdUnblockSigio (); 2053 } 2054 } 2055 } 2056 if (kdSwitchPending) 2057 KdProcessSwitch (); 2058} 2059 2060#define KdScreenOrigin(pScreen) (&(KdGetScreenPriv(pScreen)->screen->origin)) 2061 2062static Bool 2063KdCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y) 2064{ 2065 ScreenPtr pScreen = *ppScreen; 2066 ScreenPtr pNewScreen; 2067 int n; 2068 int dx, dy; 2069 int best_x, best_y; 2070 int n_best_x, n_best_y; 2071 CARD32 ms; 2072 2073 if (kdDisableZaphod || screenInfo.numScreens <= 1) 2074 return FALSE; 2075 2076 if (0 <= *x && *x < pScreen->width && 0 <= *y && *y < pScreen->height) 2077 return FALSE; 2078 2079 ms = GetTimeInMillis (); 2080 if (kdOffScreen && (int) (ms - kdOffScreenTime) < 1000) 2081 return FALSE; 2082 kdOffScreen = TRUE; 2083 kdOffScreenTime = ms; 2084 n_best_x = -1; 2085 best_x = 32767; 2086 n_best_y = -1; 2087 best_y = 32767; 2088 for (n = 0; n < screenInfo.numScreens; n++) 2089 { 2090 pNewScreen = screenInfo.screens[n]; 2091 if (pNewScreen == pScreen) 2092 continue; 2093 dx = KdScreenOrigin(pNewScreen)->x - KdScreenOrigin(pScreen)->x; 2094 dy = KdScreenOrigin(pNewScreen)->y - KdScreenOrigin(pScreen)->y; 2095 if (*x < 0) 2096 { 2097 if (dx <= 0 && -dx < best_x) 2098 { 2099 best_x = -dx; 2100 n_best_x = n; 2101 } 2102 } 2103 else if (*x >= pScreen->width) 2104 { 2105 if (dx >= 0 && dx < best_x) 2106 { 2107 best_x = dx; 2108 n_best_x = n; 2109 } 2110 } 2111 if (*y < 0) 2112 { 2113 if (dy <= 0 && -dy < best_y) 2114 { 2115 best_y = -dy; 2116 n_best_y = n; 2117 } 2118 } 2119 else if (*y >= pScreen->height) 2120 { 2121 if (dy >= 0 && dy < best_y) 2122 { 2123 best_y = dy; 2124 n_best_y = n; 2125 } 2126 } 2127 } 2128 if (best_y < best_x) 2129 n_best_x = n_best_y; 2130 if (n_best_x == -1) 2131 return FALSE; 2132 pNewScreen = screenInfo.screens[n_best_x]; 2133 2134 if (*x < 0) 2135 *x += pNewScreen->width; 2136 if (*y < 0) 2137 *y += pNewScreen->height; 2138 2139 if (*x >= pScreen->width) 2140 *x -= pScreen->width; 2141 if (*y >= pScreen->height) 2142 *y -= pScreen->height; 2143 2144 *ppScreen = pNewScreen; 2145 return TRUE; 2146} 2147 2148static void 2149KdCrossScreen(ScreenPtr pScreen, Bool entering) 2150{ 2151#ifndef XIPAQ 2152 if (entering) 2153 KdEnableScreen (pScreen); 2154 else 2155 KdDisableScreen (pScreen); 2156#endif 2157} 2158 2159int KdCurScreen; /* current event screen */ 2160 2161static void 2162KdWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) 2163{ 2164 KdBlockSigio (); 2165 KdCurScreen = pScreen->myNum; 2166 miPointerWarpCursor(pDev, pScreen, x, y); 2167 KdUnblockSigio (); 2168} 2169 2170miPointerScreenFuncRec kdPointerScreenFuncs = 2171{ 2172 KdCursorOffScreen, 2173 KdCrossScreen, 2174 KdWarpCursor 2175}; 2176 2177void 2178ProcessInputEvents (void) 2179{ 2180 mieqProcessInputEvents(); 2181 miPointerUpdateSprite(inputInfo.pointer); 2182 if (kdSwitchPending) 2183 KdProcessSwitch (); 2184 KdCheckLock (); 2185} 2186 2187/* FIXME use XSECURITY to work out whether the client should be allowed to 2188 * open and close. */ 2189void 2190OpenInputDevice(DeviceIntPtr pDev, ClientPtr client, int *status) 2191{ 2192 if (!pDev) 2193 *status = BadDevice; 2194 else 2195 *status = Success; 2196} 2197 2198void 2199CloseInputDevice(DeviceIntPtr pDev, ClientPtr client) 2200{ 2201 return; 2202} 2203 2204/* We initialise all input devices at startup. */ 2205void 2206AddOtherInputDevices(void) 2207{ 2208 return; 2209} 2210 2211/* At the moment, absolute/relative is up to the client. */ 2212int 2213SetDeviceMode(register ClientPtr client, DeviceIntPtr pDev, int mode) 2214{ 2215 return BadMatch; 2216} 2217 2218int 2219SetDeviceValuators(register ClientPtr client, DeviceIntPtr pDev, 2220 int *valuators, int first_valuator, int num_valuators) 2221{ 2222 return BadMatch; 2223} 2224 2225int 2226ChangeDeviceControl(register ClientPtr client, DeviceIntPtr pDev, 2227 xDeviceCtl *control) 2228{ 2229 switch (control->control) { 2230 case DEVICE_RESOLUTION: 2231 /* FIXME do something more intelligent here */ 2232 return BadMatch; 2233 2234 case DEVICE_ABS_CALIB: 2235 case DEVICE_ABS_AREA: 2236 return Success; 2237 2238 case DEVICE_CORE: 2239 return BadMatch; 2240 case DEVICE_ENABLE: 2241 return Success; 2242 2243 default: 2244 return BadMatch; 2245 } 2246 2247 /* NOTREACHED */ 2248 return BadImplementation; 2249} 2250 2251int 2252NewInputDeviceRequest(InputOption *options, InputAttributes *attrs, 2253 DeviceIntPtr *pdev) 2254{ 2255 InputOption *option = NULL; 2256 KdPointerInfo *pi = NULL; 2257 KdKeyboardInfo *ki = NULL; 2258 2259 for (option = options; option; option = option->next) { 2260 if (strcmp(option->key, "type") == 0) { 2261 if (strcmp(option->value, "pointer") == 0) { 2262 pi = KdNewPointer(); 2263 if (!pi) 2264 return BadAlloc; 2265 } 2266 else if (strcmp(option->value, "keyboard") == 0) { 2267 ki = KdNewKeyboard(); 2268 if (!ki) 2269 return BadAlloc; 2270 } 2271 else { 2272 ErrorF("unrecognised device type!\n"); 2273 return BadValue; 2274 } 2275 } 2276#ifdef CONFIG_HAL 2277 else if (strcmp(option->key, "_source") == 0 && 2278 strcmp(option->value, "server/hal") == 0) 2279 { 2280 ErrorF("Ignoring device from HAL.\n"); 2281 return BadValue; 2282 } 2283#endif 2284#ifdef CONFIG_UDEV 2285 else if (strcmp(option->key, "_source") == 0 && 2286 strcmp(option->value, "server/udev") == 0) 2287 { 2288 ErrorF("Ignoring device from udev.\n"); 2289 return BadValue; 2290 } 2291#endif 2292 } 2293 2294 if (!ki && !pi) { 2295 ErrorF("unrecognised device identifier!\n"); 2296 return BadValue; 2297 } 2298 2299 /* FIXME: change this code below to use KdParseKbdOptions and 2300 * KdParsePointerOptions */ 2301 for (option = options; option; option = option->next) { 2302 if (strcmp(option->key, "device") == 0) { 2303 if (pi && option->value) 2304 pi->path = strdup(option->value); 2305 else if (ki && option->value) 2306 ki->path = strdup(option->value); 2307 } 2308 else if (strcmp(option->key, "driver") == 0) { 2309 if (pi) { 2310 pi->driver = KdFindPointerDriver(option->value); 2311 if (!pi->driver) { 2312 ErrorF("couldn't find driver!\n"); 2313 KdFreePointer(pi); 2314 return BadValue; 2315 } 2316 pi->options = options; 2317 } 2318 else if (ki) { 2319 ki->driver = KdFindKeyboardDriver(option->value); 2320 if (!ki->driver) { 2321 ErrorF("couldn't find driver!\n"); 2322 KdFreeKeyboard(ki); 2323 return BadValue; 2324 } 2325 ki->options = options; 2326 } 2327 } 2328 } 2329 2330 if (pi) { 2331 if (KdAddPointer(pi) != Success || 2332 ActivateDevice(pi->dixdev, TRUE) != Success || 2333 EnableDevice(pi->dixdev, TRUE) != TRUE) { 2334 ErrorF("couldn't add or enable pointer\n"); 2335 return BadImplementation; 2336 } 2337 } 2338 else if (ki) { 2339 if (KdAddKeyboard(ki) != Success || 2340 ActivateDevice(ki->dixdev, TRUE) != Success || 2341 EnableDevice(ki->dixdev, TRUE) != TRUE) { 2342 ErrorF("couldn't add or enable keyboard\n"); 2343 return BadImplementation; 2344 } 2345 } 2346 2347 if (pi) { 2348 *pdev = pi->dixdev; 2349 } else if(ki) { 2350 *pdev = ki->dixdev; 2351 } 2352 2353 return Success; 2354} 2355 2356void 2357DeleteInputDeviceRequest(DeviceIntPtr pDev) 2358{ 2359 RemoveDevice(pDev, TRUE); 2360} 2361