Annotation of driverkit/libDriver/Kernel/EventInput.m, revision 1.1.1.1

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(&current_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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.