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