Annotation of driverkit/libDriver/Kernel/EventInput.m, revision 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.