|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: /* Copyright (c) 1992 NeXT Computer, Inc. All rights reserved. ! 25: * ! 26: * EventInput.m - Event System periodic operations module, ! 27: * ObjC implementation. ! 28: * ! 29: * This module is the kernel version. It will need ! 30: * to be re-implemented to run in user space. ! 31: * ! 32: * Periodic services driven out ot this module are almost ! 33: * entirely cursor related. ! 34: * ! 35: * HISTORY ! 36: * 31-Mar-92 Mike Paquette at NeXT ! 37: * Created. ! 38: * 5 Aug 1993 Erik Kay at NeXT ! 39: * minor API cleanup ! 40: */ ! 41: ! 42: #import <driverkit/generalFuncs.h> ! 43: #import <machkit/NXLock.h> ! 44: #import <driverkit/kernelDriver.h> ! 45: #import <mach/notify.h> ! 46: #if __nrw__ ! 47: #import <bsd/sys/reboot.h> // For disgusting hard poweroff hack... ! 48: #endif ! 49: #import <bsd/dev/ev_keymap.h> ! 50: #import <bsd/dev/evio.h> ! 51: #import <kern/queue.h> ! 52: #import <bsd/dev/machine/ev_private.h> /* Per-machine configuration info */ ! 53: #import <driverkit/EventInput.h> ! 54: #if m88k ! 55: #import <machdep/m88k/xpr.h> ! 56: #else ! 57: #define xpr_ev_cursor(x, a, b, c, d, e) ! 58: #endif ! 59: ! 60: #if DEBUG && __nrw__ ! 61: /* ! 62: * Avoid compiler headbutts with mon/types.h.. ! 63: * ! 64: * Is this machine dependent? If so, wrap it and put the ! 65: * cover function in machine/ev.c ! 66: */ ! 67: #define _MON_TYPES_BOOLEAN_ ! 68: #define _MON_TYPES_CPUTYPES_ ! 69: #define _MON_TYPES_SIZE_ ! 70: #define _MON_BIT_MACROS_ ! 71: #import <mon/mon_service.h> ! 72: ! 73: static void ! 74: break_to_parent() ! 75: { ! 76: mon_command_mode(); ! 77: } ! 78: #endif /* DEBUG && __nrw__ */ ! 79: ! 80: ! 81: #define PtInRect(ptp,rp) \ ! 82: ((ptp)->x >= (rp)->minx && (ptp)->x < (rp)->maxx && \ ! 83: (ptp)->y >= (rp)->miny && (ptp)->y < (rp)->maxy) ! 84: ! 85: @implementation EventDriver(Input) ! 86: ! 87: // ! 88: // Kernel versions of nanosecond callouts. ! 89: // ! 90: static void EvPeriodicCallout( void *data ) ! 91: { ! 92: EventDriver *inst = (EventDriver *)data; ! 93: inst->periodicRunPending = NO; ! 94: [inst periodicEvents]; ! 95: } ! 96: ! 97: // ! 98: // Schedule periodicEvents to be run nst nanoseconds. ! 99: // ! 100: - runPeriodicEvent:(ns_time_t)nst ! 101: { ! 102: ! 103: if ( periodicRunPending == YES ) ! 104: ns_untimeout((func)EvPeriodicCallout,(void *)self); ! 105: ns_abstimeout( (func)EvPeriodicCallout, ! 106: (void *)self, ! 107: nst, ! 108: CALLOUT_PRI_THREAD ); ! 109: periodicRunPending = YES; ! 110: return self; ! 111: } ! 112: ! 113: // ! 114: // Schedule the next periodic event to be run, based on the current state of ! 115: // the event system. We have to consider things here such as when the last ! 116: // periodic event pass ran, if there is currently any mouse delta accumulated, ! 117: // and how long it has been since the last event was consumed by an app (for ! 118: // driving the wait cursor). ! 119: // ! 120: // This code should only be run from the periodicEvents method or ! 121: // _setCursorPosition. ! 122: // ! 123: - scheduleNextPeriodicEvent ! 124: { ! 125: ns_time_t time_for_next_run; ! 126: ns_time_t current_time; ! 127: ! 128: IOGetTimestamp(¤t_time); ! 129: time_for_next_run = current_time + EV_TICK_TO_NS(10); ! 130: ! 131: // figure in wait cursor delay periods here ! 132: if (waitFrameTime > current_time && waitFrameTime < time_for_next_run) ! 133: time_for_next_run = waitFrameTime; ! 134: ! 135: if ( periodicRunPending == NO // need to schedule ! 136: || nextPeriodicRun > time_for_next_run // need to reschedule ! 137: || nextPeriodicRun <= thisPeriodicRun ) // clock wrapped around ! 138: { ! 139: nextPeriodicRun = time_for_next_run; ! 140: [self runPeriodicEvent:time_for_next_run]; ! 141: } ! 142: ! 143: return self; ! 144: } ! 145: ! 146: // Periodic events are driven from this method. ! 147: // After taking care of all pending work, the method ! 148: // calls scheduleNextPeriodicEvent to compute and set the ! 149: // next callout. ! 150: // ! 151: - (void)periodicEvents ! 152: { ! 153: unsigned int tick; ! 154: EvGlobals *glob; ! 155: ! 156: // If eventsOpen is false, then the driver shmem is ! 157: // no longer valid, and it is in the process of shutting down. ! 158: // We should give up without rescheduling. ! 159: [driverLock lock]; ! 160: if ( eventsOpen == NO ) ! 161: { ! 162: [driverLock unlock]; ! 163: return; ! 164: } ! 165: glob = (EvGlobals *)evg; ! 166: // Increment event time stamp last ! 167: IOGetTimestamp(&thisPeriodicRun); ! 168: ! 169: // Temporary hack til we wean PS off of VertRetraceClock ! 170: tick = EV_NS_TO_TICK(thisPeriodicRun); ! 171: if ( tick == 0 ) ! 172: tick = 1; ! 173: glob->VertRetraceClock = tick; ! 174: ! 175: // Update cursor position if needed ! 176: if ( needSetCursorPosition == YES ) ! 177: [self _setCursorPosition:&pointerLoc atTime:tick]; ! 178: ! 179: // WAITCURSOR ACTION ! 180: if ( ev_try_lock(&glob->waitCursorSema) ) ! 181: { ! 182: if ( ev_try_lock(&glob->cursorSema) ) ! 183: { ! 184: // See if the current context has timed out ! 185: if ( (glob->AALastEventSent != glob->AALastEventConsumed) ! 186: && ((glob->VertRetraceClock - glob->AALastEventSent > ! 187: glob->waitThreshold))) ! 188: glob->ctxtTimedOut = TRUE; ! 189: // If wait cursor enabled and context timed out, do waitcursor ! 190: if (glob->waitCursorEnabled && glob->globalWaitCursorEnabled && ! 191: glob->ctxtTimedOut) ! 192: { ! 193: /* WAIT CURSOR SHOULD BE ON */ ! 194: if (!glob->waitCursorUp) ! 195: [self showWaitCursor]; ! 196: } else ! 197: { ! 198: /* WAIT CURSOR SHOULD BE OFF */ ! 199: if (glob->waitCursorUp && waitSusTime <= thisPeriodicRun) ! 200: [self hideWaitCursor]; ! 201: } ! 202: /* Animate cursor */ ! 203: if (glob->waitCursorUp && waitFrameTime <= thisPeriodicRun) ! 204: [self animateWaitCursor]; ! 205: ev_unlock(&glob->cursorSema); ! 206: if ((glob->VertRetraceClock > autoDimTime) && (!autoDimmed)) ! 207: [self doAutoDim]; ! 208: } ! 209: ev_unlock(&glob->waitCursorSema); ! 210: } ! 211: [self scheduleNextPeriodicEvent]; ! 212: [driverLock unlock]; ! 213: ! 214: return; ! 215: } ! 216: ! 217: // ! 218: // Start the cursor system running. Invoked via setParameterInt:EVIOST from ! 219: // the Window Server. ! 220: // ! 221: // At this point, the WindowServer is up, running, and ready to process events. ! 222: // We will attach the keyboard and mouse, if none are available yet. ! 223: // ! 224: - (void)startCursor ! 225: { ! 226: Point p; ! 227: ! 228: if (screens) // Should be at least 1! ! 229: { ! 230: [driverLock lock]; ! 231: if ( eventsOpen == NO ) ! 232: { ! 233: [driverLock unlock]; ! 234: return; ! 235: } ! 236: p = ((EvGlobals*)evg)->cursorLoc; ! 237: if ( (currentScreen = [self pointToScreen:&p]) < 0 ) ! 238: { ! 239: [driverLock unlock]; ! 240: return; ! 241: } ! 242: cursorPin = ((EvScreen*)evScreen)[currentScreen].bounds; ! 243: cursorPin.maxx--; // Set the range the cursor is pinned ! 244: cursorPin.maxy--; // to for this display [closed range] ! 245: [self setBrightness]; ! 246: [self showCursor]; ! 247: [driverLock unlock]; // We may get events in the attach process ! 248: [self attachDefaultEventSources]; ! 249: } ! 250: } ! 251: ! 252: // ! 253: // Wait Cursor machinery. The driverLock should be held on entry to ! 254: // these methods, and the shared memory area must be set up. ! 255: // ! 256: - (void)showWaitCursor ! 257: { ! 258: xpr_ev_cursor("showWaitCursor\n",1,2,3,4,5); ! 259: ((EvGlobals*)evg)->waitCursorUp = YES; ! 260: [self changeCursor:EV_WAITCURSOR]; ! 261: // Set animation and sustain absolute times. ! 262: waitFrameTime = waitFrameRate + thisPeriodicRun; ! 263: waitSusTime = waitSustain + thisPeriodicRun; ! 264: } ! 265: ! 266: - (void)hideWaitCursor ! 267: { ! 268: xpr_ev_cursor("hideWaitCursor\n",1,2,3,4,5); ! 269: ((EvGlobals*)evg)->waitCursorUp = NO; ! 270: [self changeCursor:EV_STD_CURSOR]; ! 271: waitFrameTime = 0ULL; ! 272: waitSusTime = 0ULL; ! 273: } ! 274: ! 275: - (void)animateWaitCursor ! 276: { ! 277: xpr_ev_cursor("animateWaitCursor\n",1,2,3,4,5); ! 278: [self changeCursor:((EvGlobals*)evg)->frame + 1]; ! 279: // Set the next animation time. ! 280: waitFrameTime = waitFrameRate + thisPeriodicRun; ! 281: } ! 282: ! 283: - (void)changeCursor:(int)frame ! 284: { ! 285: ((EvGlobals*)evg)->frame = (frame > EV_MAXCURSOR) ? EV_WAITCURSOR : frame; ! 286: xpr_ev_cursor("changeCursor %d\n",((EvGlobals*)evg)->frame,2,3,4,5); ! 287: [self moveCursor]; ! 288: } ! 289: ! 290: // ! 291: // Return the screen number in which point p lies. Return -1 if the point ! 292: // lies outside of all registered screens. ! 293: // ! 294: - (int) pointToScreen:(Point *) p ! 295: { ! 296: int i; ! 297: EvScreen *screen = (EvScreen *)evScreen; ! 298: for (i=screens; --i != -1; ) { ! 299: if (screen[i].instance != nil ! 300: && (p->x >= screen[i].bounds.minx) ! 301: && (p->x < screen[i].bounds.maxx) ! 302: && (p->y >= screen[i].bounds.miny) ! 303: && (p->y < screen[i].bounds.maxy)) ! 304: return i; ! 305: } ! 306: return(-1); /* Cursor outside of known screen boundary */ ! 307: } ! 308: ! 309: // ! 310: // API used to manipulate screen brightness ! 311: // ! 312: // On entry to each of these, the driverLock should be set. ! 313: // ! 314: // Set the current brightness ! 315: - setBrightness:(int)b ! 316: { ! 317: if ( b < EV_SCREEN_MIN_BRIGHTNESS ) ! 318: b = EV_SCREEN_MIN_BRIGHTNESS; ! 319: else if ( b > EV_SCREEN_MAX_BRIGHTNESS ) ! 320: b = EV_SCREEN_MAX_BRIGHTNESS; ! 321: if ( b != curBright ) ! 322: { ! 323: curBright = b; ! 324: if ( autoDimmed == NO ) ! 325: return [self setBrightness]; ! 326: } ! 327: return self; ! 328: } ! 329: ! 330: - (int)brightness ! 331: { ! 332: return curBright; ! 333: } ! 334: ! 335: // Set the current brightness ! 336: - setAutoDimBrightness:(int)b ! 337: { ! 338: if ( b < EV_SCREEN_MIN_BRIGHTNESS ) ! 339: b = EV_SCREEN_MIN_BRIGHTNESS; ! 340: else if ( b > EV_SCREEN_MAX_BRIGHTNESS ) ! 341: b = EV_SCREEN_MAX_BRIGHTNESS; ! 342: if ( b != dimmedBrightness ) ! 343: { ! 344: dimmedBrightness = b; ! 345: if ( autoDimmed == YES ) ! 346: return [self setBrightness]; ! 347: } ! 348: return self; ! 349: } ! 350: ! 351: - (int)autoDimBrightness ! 352: { ! 353: return dimmedBrightness; ! 354: } ! 355: ! 356: ! 357: - (int)currentBrightness; // Return the current brightness ! 358: { ! 359: if ( autoDimmed == YES && dimmedBrightness < curBright ) ! 360: return dimmedBrightness; ! 361: else ! 362: return curBright; ! 363: } ! 364: ! 365: - doAutoDim ! 366: { ! 367: autoDimmed = YES; ! 368: [self setBrightness]; ! 369: return self; ! 370: } ! 371: ! 372: // Return display brightness to normal ! 373: - undoAutoDim ! 374: { ! 375: autoDimmed = NO; ! 376: [self setBrightness]; ! 377: return self; ! 378: } ! 379: ! 380: - forceAutoDimState:(BOOL)dim ! 381: { ! 382: if ( dim == YES ) ! 383: { ! 384: if ( autoDimmed == NO ) ! 385: { ! 386: if ( eventsOpen == YES ) ! 387: autoDimTime = ((EvGlobals*)evg)->VertRetraceClock; ! 388: [self doAutoDim]; ! 389: } ! 390: } ! 391: else ! 392: { ! 393: if ( autoDimmed == YES ) ! 394: { ! 395: if ( eventsOpen == YES ) ! 396: autoDimTime = ((EvGlobals*)evg)->VertRetraceClock ! 397: + autoDimPeriod; ! 398: [self undoAutoDim]; ! 399: } ! 400: } ! 401: return self; ! 402: } ! 403: ! 404: // ! 405: // API used to manipulate sound volume/attenuation ! 406: // ! 407: // Set the current brightness. ! 408: - setAudioVolume:(int)v ! 409: { ! 410: if ( v < EV_AUDIO_MIN_VOLUME ) ! 411: v = EV_AUDIO_MIN_VOLUME; ! 412: else if ( v > EV_AUDIO_MAX_VOLUME ) ! 413: v = EV_AUDIO_MAX_VOLUME; ! 414: curVolume = v; ! 415: return self; ! 416: } ! 417: ! 418: // ! 419: // Volume set programatically, rather than from keyboard ! 420: // ! 421: - setUserAudioVolume:(int)v ! 422: { ! 423: [self setAudioVolume:v]; ! 424: // Let sound driver know about the change ! 425: [self evSpecialKeyMsg: NX_KEYTYPE_SOUND_UP ! 426: direction:NX_KEYDOWN ! 427: flags:0 ! 428: level:curVolume]; ! 429: ! 430: } ! 431: ! 432: - (int)audioVolume ! 433: { ! 434: return curVolume; ! 435: } ! 436: ! 437: // ! 438: // API used to drive event state out to attached screens ! 439: // ! 440: // On entry to each of these, the driverLock should be set. ! 441: // ! 442: - setBrightness // Propagate state out to screens ! 443: { ! 444: int i; ! 445: for ( i = 0; i < screens; ++i ) ! 446: [self evDispatch:i command:EVLEVEL]; ! 447: ! 448: return self; ! 449: } ! 450: - showCursor ! 451: { ! 452: return [self evDispatch:currentScreen command:EVSHOW]; ! 453: } ! 454: - hideCursor ! 455: { ! 456: return [self evDispatch:currentScreen command:EVHIDE]; ! 457: } ! 458: - moveCursor ! 459: { ! 460: return [self evDispatch:currentScreen command:EVMOVE]; ! 461: } ! 462: ! 463: // ! 464: // - attachDefaultEventSources ! 465: // Attach the default event sources. ! 466: // The default sources are machine dependent. ! 467: // ! 468: - attachDefaultEventSources ! 469: { ! 470: id driver; ! 471: id class; ! 472: IOReturn r; ! 473: const char **devClass; ! 474: ! 475: for ( devClass = defaultEventSources(); *devClass != NULL; ++devClass ) ! 476: [self attachEventSource: *devClass]; ! 477: ! 478: return self; ! 479: } ! 480: ! 481: - attachEventSource:(const char *)classname ! 482: { ! 483: id driver; ! 484: id class; ! 485: if ( (class = objc_getClass(classname)) == nil ) ! 486: { ! 487: IOLog( "%s: %s: no such class.\n", ! 488: [self name], classname); ! 489: return nil; ! 490: } ! 491: if ( [class respondsTo:@selector(probe)] == NO ) ! 492: { ! 493: IOLog( "%s: %s does not respond to probe.\n", ! 494: [self name], classname); ! 495: return nil; ! 496: } ! 497: if ( (driver = [class probe]) == nil ) ! 498: { ! 499: IOLog("%s: probe of %s failed\n", ! 500: [self name], classname ); ! 501: return nil; ! 502: } ! 503: if ( [self registerEventSource: driver] == nil ) ! 504: { ! 505: IOLog("%s: becomeOwner of %s failed\n", ! 506: [self name], classname ); ! 507: return nil; ! 508: } ! 509: return driver; ! 510: } ! 511: ! 512: // ! 513: // - detachEventSources ! 514: // Detach all event sources ! 515: // ! 516: - detachEventSources ! 517: { ! 518: attachedEventSrc *device; ! 519: ! 520: [eventSrcListLock lock]; ! 521: while(!queue_empty(&eventSrcList)) { ! 522: device = (attachedEventSrc *)queue_first(&eventSrcList); ! 523: queue_remove(&eventSrcList, ! 524: device, ! 525: attachedEventSrc *, ! 526: link); ! 527: // Release lock while we tear down dequeued item. ! 528: [eventSrcListLock unlock]; ! 529: ! 530: if ( device->info.eventSrc != nil ) ! 531: [device->info.eventSrc relinquishOwnership:self]; ! 532: IOFree(device, sizeof (attachedEventSrc)); ! 533: [eventSrcListLock lock]; ! 534: } ! 535: [eventSrcListLock unlock]; ! 536: return self; ! 537: } ! 538: ! 539: // ! 540: // EventSrcClient implementation ! 541: // ! 542: ! 543: // ! 544: // A new device instance desires to be added to our list. ! 545: // Try to get ownership of the device. If we get it, add it to ! 546: // the list. ! 547: // ! 548: - registerEventSource:source ! 549: { ! 550: attachedEventSrc *device; ! 551: ! 552: if ( [source becomeOwner:self] != IO_R_SUCCESS ) ! 553: return nil; ! 554: device = IOMalloc( sizeof (attachedEventSrc) ); ! 555: bzero( device, sizeof (attachedEventSrc) ); ! 556: device->info.eventSrc = source; ! 557: // Enter the device on our list. ! 558: [eventSrcListLock lock]; ! 559: queue_enter(&eventSrcList, ! 560: device, ! 561: attachedEventSrc *, ! 562: link); ! 563: [eventSrcListLock unlock]; ! 564: return self; ! 565: } ! 566: ! 567: // ! 568: // Called when another client wishes to assume ownership of calling adbDevice. ! 569: // This happens when a client attempts a becomeOwner: on a device which is ! 570: // owned by the callee of this method. ! 571: // ! 572: // Returns: ! 573: // IO_R_SUCCESS ==> It's OK to give ownership of the device to other client. ! 574: // In this case, callee no longer owns the device. ! 575: // IO_R_BUSY ==> Don't transfer ownership. ! 576: // ! 577: // Note that this call occurs during (i.e., before the return of) a ! 578: // attachDevice: call to the caller of this method. ! 579: // ! 580: - (IOReturn)relinquishOwnershipRequest : device; ! 581: { ! 582: return (eventsOpen == NO) ? IO_R_SUCCESS : IO_R_BUSY; ! 583: } ! 584: ! 585: // ! 586: // Method by which a client, who has registered "intent to own" via ! 587: // desireOwnership:client, is notified that the calling device is available. ! 588: // Client will typically call becomeOwner: during this call. ! 589: // ! 590: - (void)canBecomeOwner : device; ! 591: { ! 592: IOReturn drtn; ! 593: drtn = [device becomeOwner: self]; ! 594: if(drtn) ! 595: { ! 596: IOLog("%s: becomeOwner of %s failed (%s)\n", ! 597: [self name], ! 598: [device name], ! 599: [self stringFromReturn:drtn]); ! 600: } ! 601: } ! 602: ! 603: // ! 604: // Process a mouse status change. The driver should sign extend ! 605: // it's deltas and perform any bit flipping needed there. ! 606: // ! 607: // We take the state as presented and turn it into events. ! 608: // ! 609: - relativePointerEvent:(int)buttons deltaX:(int)dx deltaY:(int)dy ! 610: { ! 611: ns_time_t ts; ! 612: IOGetTimestamp( &ts ); ! 613: return [self relativePointerEvent:buttons ! 614: deltaX:dx ! 615: deltaY:dy ! 616: atTime:ts]; ! 617: } ! 618: ! 619: - relativePointerEvent:(int)buttons ! 620: deltaX:(int)dx ! 621: deltaY:(int)dy ! 622: atTime:(ns_time_t)ts ! 623: { ! 624: unsigned tick; ! 625: ! 626: tick = EV_NS_TO_TICK(ts); ! 627: [driverLock lock]; ! 628: if ( eventsOpen == NO ) ! 629: { ! 630: [driverLock unlock]; ! 631: return self; ! 632: } ! 633: // Fake up pressure changes from button state changes ! 634: if ( (buttons & EV_LB) != (((EvGlobals*)evg)->buttons & EV_LB) ) ! 635: { ! 636: if ( buttons & EV_LB ) ! 637: lastPressure = MAXPRESSURE; ! 638: else ! 639: lastPressure = MINPRESSURE; ! 640: } ! 641: [self _setButtonState:buttons atTime:tick]; ! 642: ! 643: // figure cursor movement ! 644: if ( dx || dy ) ! 645: { ! 646: pointerLoc.x += dx; ! 647: pointerLoc.y += dy; ! 648: if ( needSetCursorPosition == NO ) ! 649: [self _setCursorPosition:&pointerLoc atTime:tick]; ! 650: } ! 651: [driverLock unlock]; ! 652: return self; ! 653: } ! 654: ! 655: - absolutePointerEvent:(int)buttons ! 656: at:(Point *)newLoc ! 657: inProximity:(BOOL)proximity ! 658: { ! 659: unsigned int pressure; ! 660: ns_time_t ts; ! 661: IOGetTimestamp( &ts ); ! 662: // Fake up pressure changes from button state changes ! 663: [driverLock lock]; ! 664: pressure = lastPressure; ! 665: if ( eventsOpen == NO ) ! 666: { ! 667: [driverLock unlock]; ! 668: return self; ! 669: } ! 670: if ( (buttons & EV_LB) != (((EvGlobals*)evg)->buttons & EV_LB) ) ! 671: { ! 672: if ( buttons & EV_LB ) ! 673: pressure = MAXPRESSURE; ! 674: else ! 675: pressure = MINPRESSURE; ! 676: } ! 677: [driverLock unlock]; ! 678: [self absolutePointerEvent:buttons ! 679: at:newLoc ! 680: inProximity:proximity ! 681: withPressure:pressure ! 682: withAngle:90 ! 683: atTime:ts]; ! 684: return self; ! 685: } ! 686: ! 687: - absolutePointerEvent:(int)buttons ! 688: at:(Point *)newLoc ! 689: inProximity:(BOOL)proximity ! 690: withPressure:(int)pressure ! 691: { ! 692: ns_time_t ts; ! 693: IOGetTimestamp( &ts ); ! 694: [self absolutePointerEvent:buttons ! 695: at:newLoc ! 696: inProximity:proximity ! 697: withPressure:pressure ! 698: withAngle:90 ! 699: atTime:ts]; ! 700: return self; ! 701: } ! 702: ! 703: - absolutePointerEvent:(int)buttons ! 704: at:(Point *)newLoc ! 705: inProximity:(BOOL)proximity ! 706: withPressure:(int)pressure ! 707: withAngle:(int)stylusAngle ! 708: atTime:(ns_time_t)ts ! 709: ! 710: { ! 711: NXEventData outData; /* dummy data */ ! 712: unsigned tick; ! 713: ! 714: tick = EV_NS_TO_TICK(ts); ! 715: [driverLock lock]; ! 716: if ( eventsOpen == NO ) ! 717: { ! 718: [driverLock unlock]; ! 719: return self; ! 720: } ! 721: ! 722: lastPressure = pressure; ! 723: if ( newLoc->x != pointerLoc.x || newLoc->y != pointerLoc.y ) ! 724: { ! 725: pointerLoc = *newLoc; ! 726: if ( needSetCursorPosition == NO ) ! 727: [self _setCursorPosition:&pointerLoc atTime:tick]; ! 728: } ! 729: if ( lastProximity != proximity && proximity == YES ) ! 730: { ! 731: ((EvGlobals*)evg)->eventFlags |= NX_STYLUSPROXIMITYMASK; ! 732: bzero( (char *)&outData, sizeof outData ); ! 733: [self postEvent:NX_FLAGSCHANGED ! 734: at:(Point *)&pointerLoc ! 735: atTime:tick ! 736: withData:&outData]; ! 737: } ! 738: if ( proximity == YES ) ! 739: [self _setButtonState:buttons atTime:tick]; ! 740: if ( lastProximity != proximity && proximity == NO ) ! 741: { ! 742: ((EvGlobals*)evg)->eventFlags &= ~NX_STYLUSPROXIMITYMASK; ! 743: bzero( (char *)&outData, sizeof outData ); ! 744: [self postEvent:NX_FLAGSCHANGED ! 745: at:(Point *)&pointerLoc ! 746: atTime:tick ! 747: withData:&outData]; ! 748: } ! 749: lastProximity = proximity; ! 750: [driverLock unlock]; ! 751: return self; ! 752: } ! 753: ! 754: // ! 755: // Process a keyboard state change. ! 756: // ! 757: - keyboardEvent:(unsigned)eventType ! 758: flags:(unsigned)flags ! 759: keyCode:(unsigned)key ! 760: charCode:(unsigned)charCode ! 761: charSet:(unsigned)charSet ! 762: originalCharCode:(unsigned)origCharCode ! 763: originalCharSet:(unsigned)origCharSet ! 764: repeat:(BOOL)repeat ! 765: atTime:(ns_time_t)ts ! 766: { ! 767: NXEventData outData; ! 768: unsigned tick; ! 769: ! 770: tick = EV_NS_TO_TICK(ts); ! 771: outData.key.repeat = repeat; ! 772: outData.key.keyCode = key; ! 773: outData.key.charSet = charSet; ! 774: outData.key.charCode = charCode; ! 775: outData.key.origCharSet = origCharSet; ! 776: outData.key.origCharCode = origCharCode; ! 777: ! 778: [driverLock lock]; ! 779: if ( eventsOpen == NO ) ! 780: { ! 781: [driverLock unlock]; ! 782: return self; ! 783: } ! 784: ((EvGlobals*)evg)->eventFlags = (((EvGlobals*)evg)->eventFlags & ~KEYBOARD_FLAGSMASK) ! 785: | (flags & KEYBOARD_FLAGSMASK); ! 786: ! 787: [self postEvent:eventType ! 788: at:(Point *)&pointerLoc ! 789: atTime:tick ! 790: withData:&outData]; ! 791: ! 792: [driverLock unlock]; ! 793: return self; ! 794: } ! 795: ! 796: ! 797: - keyboardSpecialEvent:(unsigned)eventType ! 798: flags:(unsigned)flags ! 799: keyCode:(unsigned)key ! 800: specialty:(unsigned)flavor ! 801: atTime:(ns_time_t)ts ! 802: { ! 803: NXEventData outData; ! 804: unsigned tick; ! 805: int level = -1; ! 806: ! 807: bzero( (void *)&outData, sizeof outData ); ! 808: tick = EV_NS_TO_TICK(ts); ! 809: ! 810: [driverLock lock]; ! 811: if ( eventsOpen == NO ) ! 812: { ! 813: [driverLock unlock]; ! 814: return self; ! 815: } ! 816: // Update flags. ! 817: ((EvGlobals*)evg)->eventFlags = (((EvGlobals*)evg)->eventFlags & ~KEYBOARD_FLAGSMASK) ! 818: | (flags & KEYBOARD_FLAGSMASK); ! 819: // Most of these keys don't generate events. Forcibly undo autodim. ! 820: if ( autoDimmed == YES ) ! 821: [self forceAutoDimState:NO]; ! 822: if ( eventType == NX_KEYDOWN ) ! 823: { ! 824: switch ( flavor ) ! 825: { ! 826: case NX_KEYTYPE_SOUND_UP: ! 827: if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 ) ! 828: [self setAudioVolume:[self audioVolume] + 1]; ! 829: level = [self audioVolume]; ! 830: break; ! 831: case NX_KEYTYPE_SOUND_DOWN: ! 832: if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 ) ! 833: [self setAudioVolume:[self audioVolume] - 1]; ! 834: level = [self audioVolume]; ! 835: break; ! 836: case NX_KEYTYPE_BRIGHTNESS_UP: ! 837: #if DEBUG && __nrw__ ! 838: if ( (flags & BRIGHT_BREAK_TO_DEBUGGER_MASK) ! 839: == BRIGHT_BREAK_TO_DEBUGGER_MASK ) ! 840: { ! 841: [driverLock unlock]; ! 842: break_to_parent(); ! 843: return self; ! 844: } ! 845: #endif DEBUG && __nrw__ ! 846: if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 ) ! 847: [self setBrightness:[self brightness] + 1]; ! 848: level = [self brightness]; ! 849: break; ! 850: case NX_KEYTYPE_BRIGHTNESS_DOWN: ! 851: if ( (flags & SPECIALKEYS_MODIFIER_MASK) == 0 ) ! 852: [self setBrightness:[self brightness] - 1]; ! 853: level = [self brightness]; ! 854: break; ! 855: case NX_POWER_KEY: ! 856: #if DEBUG && __nrw__ ! 857: if ( (flags & PWR_BREAK_TO_DEBUGGER_MASK) ! 858: == PWR_BREAK_TO_DEBUGGER_MASK ) ! 859: { ! 860: [driverLock unlock]; ! 861: break_to_parent(); ! 862: return self; ! 863: } ! 864: #endif DEBUG && __nrw__ ! 865: #if __nrw__ ! 866: // ICK! Do we really need this "feature"? ! 867: if ( (flags & HARD_POWEROFF_MASK) ! 868: == HARD_POWEROFF_MASK ) ! 869: { ! 870: [driverLock unlock]; ! 871: boot(0,RB_NOSYNC|RB_POWERDOWN,NULL); ! 872: return self; // not reached... ! 873: } ! 874: #endif ! 875: outData.compound.subType = 1; ! 876: [self postEvent:NX_SYSDEFINED ! 877: at:(Point *)&pointerLoc ! 878: atTime:tick ! 879: withData:&outData]; ! 880: break; ! 881: } ! 882: } ! 883: #if 0 /* So far, nothing to do on keyup */ ! 884: else if ( eventType == NX_KEYUP ) ! 885: { ! 886: switch ( flavor ) ! 887: { ! 888: case NX_KEYTYPE_SOUND_UP: ! 889: break; ! 890: case NX_KEYTYPE_SOUND_DOWN: ! 891: break; ! 892: case NX_KEYTYPE_BRIGHTNESS_UP: ! 893: break; ! 894: case NX_KEYTYPE_BRIGHTNESS_DOWN: ! 895: break; ! 896: case NX_POWER_KEY: ! 897: break; ! 898: } ! 899: } ! 900: #endif ! 901: [driverLock unlock]; ! 902: if ( level != -1 ) // An interesting special key event occurred ! 903: { ! 904: [self evSpecialKeyMsg: flavor ! 905: direction:eventType ! 906: flags:flags ! 907: level:level]; ! 908: } ! 909: return self; ! 910: } ! 911: ! 912: /* ! 913: * Update current event flags. Restricted to keyboard flags only, this ! 914: * method is used to silently update the flags state for keys which both ! 915: * generate characters and flag changes. The specs say we don't generate ! 916: * a flags-changed event for such keys. This method is also used to clear ! 917: * the keyboard flags on a keyboard subsystem reset. ! 918: */ ! 919: - updateEventFlags:(unsigned)flags ! 920: { ! 921: [driverLock lock]; ! 922: if ( eventsOpen ) ! 923: ((EvGlobals*)evg)->eventFlags = (((EvGlobals*)evg)->eventFlags & ~KEYBOARD_FLAGSMASK) ! 924: | (flags & KEYBOARD_FLAGSMASK); ! 925: [driverLock unlock]; ! 926: return self; ! 927: } ! 928: ! 929: /* ! 930: * Return current event flags ! 931: */ ! 932: - (int)eventFlags ! 933: { ! 934: int flags = 0; ! 935: [driverLock lock]; ! 936: if ( eventsOpen ) ! 937: flags = ((EvGlobals*)evg)->eventFlags; ! 938: [driverLock unlock]; ! 939: return flags; ! 940: } ! 941: ! 942: // ! 943: // - _setButtonState:(int)buttons atTime:(int)t ! 944: // Update the button state. Generate button events as needed ! 945: // ! 946: - _setButtonState:(int)buttons atTime:(unsigned)t ! 947: { ! 948: EvGlobals *glob = (EvGlobals *)evg; ! 949: if ((glob->buttons & EV_LB) != (buttons & EV_LB)) ! 950: { ! 951: if (buttons & EV_LB) ! 952: { ! 953: [self postEvent:NX_LMOUSEDOWN ! 954: at:(Point *)&glob->cursorLoc ! 955: atTime:t ! 956: withData:NULL]; ! 957: glob->buttons |= EV_LB; ! 958: } ! 959: else ! 960: { ! 961: [self postEvent:NX_LMOUSEUP ! 962: at:(Point *)&glob->cursorLoc ! 963: atTime:t ! 964: withData:NULL]; ! 965: glob->buttons &= ~EV_LB; ! 966: } ! 967: // After entering initial up/down event, set up ! 968: // coalescing state so drags will behave correctly ! 969: glob->dontCoalesce = glob->dontWantCoalesce; ! 970: if (glob->dontCoalesce) ! 971: glob->eventFlags |= NX_NONCOALSESCEDMASK; ! 972: else ! 973: glob->eventFlags &= ~NX_NONCOALSESCEDMASK; ! 974: } ! 975: ! 976: if ((glob->buttons & EV_RB) != (buttons & EV_RB)) { ! 977: if (buttons & EV_RB) { ! 978: [self postEvent:NX_RMOUSEDOWN ! 979: at:(Point *)&glob->cursorLoc ! 980: atTime:t ! 981: withData:NULL]; ! 982: glob->buttons |= EV_RB; ! 983: } else { ! 984: [self postEvent:NX_RMOUSEUP ! 985: at:(Point *)&glob->cursorLoc ! 986: atTime:t ! 987: withData:NULL]; ! 988: glob->buttons &= ~EV_RB; ! 989: } ! 990: } ! 991: return self; ! 992: } ! 993: // ! 994: // Sets the cursor position (((EvGlobals*)evg)->cursorLoc) to the new ! 995: // location. The location is clipped against the cursor pin rectangle, ! 996: // mouse moved/dragged events are generated using the given event mask, ! 997: // and a mouse-exited event may be generated. The cursor image is ! 998: // moved. ! 999: // On entry, the driverLock should be set. ! 1000: // ! 1001: - setCursorPosition:(Point *)newLoc ! 1002: { ! 1003: if ( eventsOpen == YES ) ! 1004: { ! 1005: pointerLoc = *newLoc; ! 1006: if ( needSetCursorPosition == NO ) ! 1007: [self _setCursorPosition:newLoc atTime:EvTickTimeValue()]; ! 1008: } ! 1009: } ! 1010: ! 1011: // ! 1012: // This mechanism is used to update the cursor position, possibly generating ! 1013: // messages to registered frame buffer devices and posting drag, tracking, and ! 1014: // mouse motion events. ! 1015: // ! 1016: // On entry, the driverLock should be set. ! 1017: // This can be called from setCursorPosition:(Point *)newLoc to set the ! 1018: // position by a _IOSetParameterFromIntArray() call, directly from the absolute or ! 1019: // relative pointer device routines, or on a timed event callback. ! 1020: // ! 1021: - _setCursorPosition:(Point *)newLoc atTime:(unsigned)t ! 1022: { ! 1023: int newScreen = -1; ! 1024: EvGlobals *glob = (EvGlobals *)evg; ! 1025: ! 1026: if (!screens) ! 1027: return self; ! 1028: ! 1029: if ( ev_try_lock(&glob->cursorSema) == 0 ) // host using shmem ! 1030: { ! 1031: needSetCursorPosition = YES; // try again later ! 1032: [self scheduleNextPeriodicEvent]; ! 1033: return self; ! 1034: } ! 1035: // Past here we hold the cursorSema lock. Make sure the lock is ! 1036: // cleared before returning or the system will be wedged. ! 1037: ! 1038: needSetCursorPosition = NO; // We WILL succeed ! 1039: ! 1040: /* Check to see if cursor ventured outside of current screen bounds ! 1041: before worrying about which screen it may have gone to. */ ! 1042: ! 1043: if (!PtInRect(newLoc, &((EvScreen*)evScreen)[currentScreen].bounds)) { ! 1044: /* At this point cursor has gone off screen. Check to see if moved ! 1045: to another screen. If not, just clip it to current screen. */ ! 1046: ! 1047: if ((newScreen = [self pointToScreen:newLoc]) < 0) { ! 1048: /* Pin new cursor position to cursorPin rect */ ! 1049: newLoc->x = (newLoc->x < cursorPin.minx) ? ! 1050: cursorPin.minx : ((newLoc->x > cursorPin.maxx) ? ! 1051: cursorPin.maxx : newLoc->x); ! 1052: newLoc->y = (newLoc->y < cursorPin.miny) ? ! 1053: cursorPin.miny : ((newLoc->y > cursorPin.maxy) ? ! 1054: cursorPin.maxy : newLoc->y); ! 1055: } ! 1056: } ! 1057: ! 1058: pointerLoc = *newLoc; // Sync up pointer with clipped cursor ! 1059: /* Catch the no-move case */ ! 1060: if (glob->cursorLoc.x == newLoc->x && glob->cursorLoc.y == newLoc->y) ! 1061: { ! 1062: ev_unlock(&glob->cursorSema); ! 1063: return self; ! 1064: } ! 1065: glob->cursorLoc = *newLoc; ! 1066: /* If newScreen is zero or positive, then cursor crossed screens */ ! 1067: if (newScreen >= 0) { ! 1068: /* cursor changed screens */ ! 1069: [self hideCursor]; /* hide cursor on old screen */ ! 1070: currentScreen = newScreen; ! 1071: cursorPin = ((EvScreen*)evScreen)[currentScreen].bounds; ! 1072: cursorPin.maxx--; /* Make half-open rectangle */ ! 1073: cursorPin.maxy--; ! 1074: [self showCursor]; ! 1075: } else { ! 1076: /* cursor moved on same screen */ ! 1077: [self moveCursor]; ! 1078: } ! 1079: ! 1080: /* See if anybody wants the mouse moved or dragged events */ ! 1081: if (glob->movedMask) { ! 1082: if ((glob->movedMask&NX_LMOUSEDRAGGEDMASK)&&(glob->buttons& EV_LB)) ! 1083: [self postEvent:NX_LMOUSEDRAGGED ! 1084: at:newLoc ! 1085: atTime:t ! 1086: withData:NULL]; ! 1087: else ! 1088: if ((glob->movedMask&NX_RMOUSEDRAGGEDMASK) && ! 1089: (glob->buttons & EV_RB)) ! 1090: [self postEvent:NX_RMOUSEDRAGGED ! 1091: at:newLoc ! 1092: atTime:t ! 1093: withData:NULL]; ! 1094: else ! 1095: if (glob->movedMask & NX_MOUSEMOVEDMASK) ! 1096: [self postEvent:NX_MOUSEMOVED ! 1097: at:newLoc ! 1098: atTime:t ! 1099: withData:NULL]; ! 1100: } ! 1101: ! 1102: /* check new cursor position for leaving glob->mouseRect */ ! 1103: if (glob->mouseRectValid && (!PtInRect(newLoc, &glob->mouseRect))) ! 1104: { ! 1105: if (glob->mouseRectValid) ! 1106: { ! 1107: [self postEvent:NX_MOUSEEXITED ! 1108: at:newLoc ! 1109: atTime:t ! 1110: withData:NULL]; ! 1111: glob->mouseRectValid = 0; ! 1112: } ! 1113: } ! 1114: ev_unlock(&glob->cursorSema); ! 1115: return self; ! 1116: } ! 1117: ! 1118: @end ! 1119:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.