/** NSEvent The event class Copyright (C) 1996 Free Software Foundation, Inc. Author: Scott Christley Author: Ovidiu Predescu Date: 1996 Author: Felipe A. Rodriguez Date: Sept 1998 Updated: Richard Frith-Macdonald Date: June 1999 This file is part of the GNUstep GUI Library. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; see the file COPYING.LIB. If not, see or write to the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "config.h" #import #import #import #import #import #import #import #import #import "AppKit/NSEvent.h" #import "AppKit/NSApplication.h" #import "AppKit/NSWindow.h" #import "AppKit/NSGraphicsContext.h" #import "AppKit/NSGraphics.h" #import "AppKit/PSOperators.h" #import "GNUstepGUI/GSDisplayServer.h" /* * gstep-base has a faster mechanism to get the current thread. */ #ifndef GNUSTEP_BASE_LIBRARY #define GSCurrentThread() [NSThread currentThread] #define GSCurrentThreadDictionary() [[NSThread currentThread] threadDictionary] #endif @implementation NSEvent /* * Class variables */ static NSString *timerKey = @"NSEventTimersKey"; static Class dateClass; static Class eventClass; /* * Class methods */ + (void) initialize { if (self == [NSEvent class]) { [self setVersion: 3]; dateClass = [NSDate class]; eventClass = [NSEvent class]; } } /* * Creating NSEvent objects */ + (NSEvent*) enterExitEventWithType: (NSEventType)type location: (NSPoint)location modifierFlags: (NSUInteger)flags timestamp: (NSTimeInterval)time windowNumber: (NSInteger)windowNum context: (NSGraphicsContext*)context eventNumber: (NSInteger)eventNum trackingNumber: (NSInteger)trackingNum userData: (void *)userData { NSEvent *e; if (type == NSCursorUpdate) RETAIN((id)userData); else if ((type != NSMouseEntered) && (type != NSMouseExited)) [NSException raise: NSInvalidArgumentException format: @"enterExitEvent with wrong type"]; e = (NSEvent*)NSAllocateObject(self, 0, NSDefaultMallocZone()); if (self != eventClass) e = [e init]; AUTORELEASE(e); e->event_type = type; e->location_point = location; e->modifier_flags = flags; e->event_time = time; e->window_num = windowNum; e->event_context = context; e->event_data.tracking.event_num = eventNum; e->event_data.tracking.tracking_num = trackingNum; e->event_data.tracking.user_data = userData; return e; } + (NSEvent*) keyEventWithType: (NSEventType)type location: (NSPoint)location modifierFlags: (NSUInteger)flags timestamp: (NSTimeInterval)time windowNumber: (NSInteger)windowNum context: (NSGraphicsContext *)context characters: (NSString *)keys charactersIgnoringModifiers: (NSString *)ukeys isARepeat: (BOOL)repeatKey keyCode: (unsigned short)code { NSEvent *e; if (!(NSEventMaskFromType(type) & GSKeyEventMask)) [NSException raise: NSInvalidArgumentException format: @"keyEvent with wrong type"]; e = (NSEvent*)NSAllocateObject(self, 0, NSDefaultMallocZone()); if (self != eventClass) e = [e init]; AUTORELEASE(e); e->event_type = type; e->location_point = location; e->modifier_flags = flags; e->event_time = time; e->window_num = windowNum; e->event_context = context; RETAIN(keys); e->event_data.key.char_keys = keys; RETAIN(ukeys); e->event_data.key.unmodified_keys = ukeys; e->event_data.key.repeat = repeatKey; e->event_data.key.key_code = code; return e; } + (NSEvent*) mouseEventWithType: (NSEventType)type location: (NSPoint)location modifierFlags: (NSUInteger)flags timestamp: (NSTimeInterval)time windowNumber: (NSInteger)windowNum context: (NSGraphicsContext*)context eventNumber: (NSInteger)eventNum clickCount: (NSInteger)clickNum pressure: (float)pressureValue { NSEvent *e; if (!(NSEventMaskFromType(type) & GSMouseEventMask)) [NSException raise: NSInvalidArgumentException format: @"mouseEvent with wrong type"]; e = (NSEvent*)NSAllocateObject(self, 0, NSDefaultMallocZone()); if (self != eventClass) e = [e init]; AUTORELEASE(e); e->event_type = type; e->location_point = location; e->modifier_flags = flags; e->event_time = time; e->window_num = windowNum; e->event_context = context; e->event_data.mouse.event_num = eventNum; e->event_data.mouse.click = clickNum; e->event_data.mouse.pressure = pressureValue; return e; } + (NSEvent*) mouseEventWithType: (NSEventType)type location: (NSPoint)location modifierFlags: (NSUInteger)flags timestamp: (NSTimeInterval)time windowNumber: (NSInteger)windowNum context: (NSGraphicsContext*)context eventNumber: (NSInteger)eventNum clickCount: (NSInteger)clickNum pressure: (float)pressureValue buttonNumber: (NSInteger)buttonNum deltaX: (CGFloat)deltaX deltaY: (CGFloat)deltaY deltaZ: (CGFloat)deltaZ { NSEvent *e; if (!(NSEventMaskFromType(type) & GSMouseEventMask)) [NSException raise: NSInvalidArgumentException format: @"mouseEvent with wrong type"]; e = (NSEvent*)NSAllocateObject(self, 0, NSDefaultMallocZone()); if (self != eventClass) e = [e init]; AUTORELEASE(e); e->event_type = type; e->location_point = location; e->modifier_flags = flags; e->event_time = time; e->window_num = windowNum; e->event_context = context; e->event_data.mouse.event_num = eventNum; e->event_data.mouse.click = clickNum; e->event_data.mouse.button = buttonNum; e->event_data.mouse.pressure = pressureValue; e->event_data.mouse.deltaX = deltaX; e->event_data.mouse.deltaY = deltaY; e->event_data.mouse.deltaZ = deltaZ; return e; } /** * Returns the current mouse location. */ + (NSPoint) mouseLocation { return [GSCurrentServer() mouselocation]; } + (NSEvent*) otherEventWithType: (NSEventType)type location: (NSPoint)location modifierFlags: (NSUInteger)flags timestamp: (NSTimeInterval)time windowNumber: (NSInteger)windowNum context: (NSGraphicsContext*)context subtype: (short)subType data1: (NSInteger)data1 data2: (NSInteger)data2 { NSEvent *e; if (!(NSEventMaskFromType(type) & GSOtherEventMask)) [NSException raise: NSInvalidArgumentException format: @"otherEvent with wrong type"]; e = (NSEvent*)NSAllocateObject(self, 0, NSDefaultMallocZone()); if (self != eventClass) e = [e init]; AUTORELEASE(e); e->event_type = type; e->location_point = location; e->modifier_flags = flags; e->event_time = time; e->window_num = windowNum; e->event_context = context; e->event_data.misc.sub_type = subType; e->event_data.misc.data1 = data1; e->event_data.misc.data2 = data2; return e; } /* * Requesting Periodic Events */ + (void) startPeriodicEventsAfterDelay: (NSTimeInterval)delaySeconds withPeriod: (NSTimeInterval)periodSeconds { NSTimer *timer; NSMutableDictionary *dict = GSCurrentThreadDictionary(); NSDebugLLog (@"NSEvent", @"startPeriodicEventsAfterDelay: withPeriod: "); if ([dict objectForKey: timerKey]) [NSException raise: NSInternalInconsistencyException format: @"Periodic events are already being generated for " @"this thread %p", GSCurrentThread()]; /* * Register a timer that will fire in delaySeconds. * This timer will fire the first event and register * a repeat timer that will send the following events */ timer = [NSTimer timerWithTimeInterval: delaySeconds target: self selector: @selector(_registerRealTimer:) userInfo: [NSNumber numberWithDouble: periodSeconds] repeats: NO]; [[NSRunLoop currentRunLoop] addTimer: timer forMode: NSEventTrackingRunLoopMode]; [dict setObject: timer forKey: timerKey]; } + (void) _timerFired: (NSTimer*)timer { NSTimeInterval timeInterval; NSEvent *periodicEvent; timeInterval = [dateClass timeIntervalSinceReferenceDate]; periodicEvent = [self otherEventWithType: NSPeriodic location: NSZeroPoint modifierFlags: 0 timestamp: timeInterval windowNumber: 0 context: [NSApp context] subtype: 0 data1: 0 data2: 0]; NSDebugLLog (@"NSEvent", @"_timerFired: "); [NSApp postEvent: periodicEvent atStart: NO]; } /* * This method provides a means of delaying the start of periodic events */ + (void) _registerRealTimer: (NSTimer*)timer { NSTimer *realTimer; NSMutableDictionary *dict = GSCurrentThreadDictionary(); NSDebugLLog (@"NSEvent", @"_registerRealTimer: "); { NSTimeInterval timeInterval; NSEvent *periodicEvent; timeInterval = [dateClass timeIntervalSinceReferenceDate]; periodicEvent = [self otherEventWithType: NSPeriodic location: NSZeroPoint modifierFlags: 0 timestamp: timeInterval windowNumber: 0 context: [NSApp context] subtype: 0 data1: 0 data2: 0]; [NSApp postEvent: periodicEvent atStart: NO]; } realTimer = [NSTimer timerWithTimeInterval: [[timer userInfo] doubleValue] target: self selector: @selector(_timerFired:) userInfo: nil repeats: YES]; [dict setObject: realTimer forKey: timerKey]; [[NSRunLoop currentRunLoop] addTimer: realTimer forMode: NSEventTrackingRunLoopMode]; } + (void) stopPeriodicEvents { NSTimer *timer; NSMutableDictionary *dict = GSCurrentThreadDictionary(); NSDebugLLog (@"NSEvent", @"stopPeriodicEvents"); timer = [dict objectForKey: timerKey]; [timer invalidate]; [dict removeObjectForKey: timerKey]; } /** * Returns the button number for the mouse button pressed in a mouse * event. Intended primarily for the case where a mouse has three or * more buttons, and you want to know which button an 'other' mouse * event refers to. */ - (NSInteger) buttonNumber { if (!(NSEventMaskFromType(event_type) & GSMouseEventMask)) { [NSException raise: NSInternalInconsistencyException format: @"buttonNumber requested for non-mouse event"]; } return event_data.mouse.button; } /** * Returns the string of characters for a keyboard event. *
Raises an NSInternalInconsistencyException if applied to any * other type of event. */ - (NSString *) characters { if ((event_type != NSKeyUp) && (event_type != NSKeyDown)) { [NSException raise: NSInternalInconsistencyException format: @"characters requested for non-keyboard event"]; } return event_data.key.char_keys; } /** * Returns the string of characters for a keyboard event, as if no modifier * keys had been pressed when the keyboard event occirred. *
Raises an NSInternalInconsistencyException if applied to any * other type of event. */ - (NSString *) charactersIgnoringModifiers { if ((event_type != NSKeyUp) && (event_type != NSKeyDown)) { [NSException raise: NSInternalInconsistencyException format: @"charactersIgnoringModifiers requested for " @"non-keyboard event"]; } return event_data.key.unmodified_keys; } /** * Return the number of clicks associated with the mouse down or up * event. This method is not applicable for any event type other * than a mouse down or mouse up. *
Raises an NSInternalInconsistencyException if applied to any * other type of event. */ - (NSInteger) clickCount { /* Make sure it is one of the right event types */ if (!(NSEventMaskFromType(event_type) & GSMouseEventMask)) { [NSException raise: NSInternalInconsistencyException format: @"clickCount requested for non-mouse event"]; } return event_data.mouse.click; } /** * Returns the graphics context for which this event was generated. */ - (NSGraphicsContext*) context { return event_context; } - (id) copyWithZone: (NSZone*)zone { NSEvent *e = (NSEvent*)NSCopyObject (self, 0, zone); if ((NSEventMaskFromType(event_type) & GSKeyEventMask)) { event_data.key.char_keys = [event_data.key.char_keys copyWithZone: zone]; event_data.key.unmodified_keys = [event_data.key.unmodified_keys copyWithZone: zone]; } else if (event_type == NSCursorUpdate) { event_data.tracking.user_data = (void *)[(id)event_data.tracking.user_data copyWithZone: zone]; } return e; } /** * Returns the 'data1' item associated with the event. *
Raises NSInternalInconsistencyException if the event is not * of type NSAppKitDefined, NSSystemDefined, NSApplicationDefined, * or NSPeriodic */ - (NSInteger) data1 { if (event_type < NSAppKitDefined || event_type > NSPeriodic) { [NSException raise: NSInternalInconsistencyException format: @"data1 requested for invalid event type"]; } return event_data.misc.data1; } /** * Returns the 'data2' item associated with the event. *
Raises NSInternalInconsistencyException if the event is not * of type NSAppKitDefined, NSSystemDefined, NSApplicationDefined, * or NSPeriodic */ - (NSInteger) data2 { if (event_type < NSAppKitDefined || event_type > NSPeriodic) { [NSException raise: NSInternalInconsistencyException format: @"data2 requested for invalid event type"]; } return event_data.misc.data2; } - (void) dealloc { if ((NSEventMaskFromType(event_type) & GSKeyEventMask)) { RELEASE(event_data.key.char_keys); RELEASE(event_data.key.unmodified_keys); } else if (event_type == NSCursorUpdate) { RELEASE((id)event_data.tracking.user_data); } [super dealloc]; } /**

Returns the movement of the mouse on the X axis.

This method is only valid for NSMouseMoved, NS*MouseDragged and NSScrollWheel events, otherwise it will return 0.

*/ - (CGFloat) deltaX { if (!(NSEventMaskFromType(event_type) & GSMouseMovedEventMask)) { return 0.0; } return event_data.mouse.deltaX; } /**

Returns the movement of the mouse on the Y axis.

This method is only valid for NSMouseMoved, NS*MouseDragged and NSScrollWheel events, otherwise it will return 0.

*/ - (CGFloat) deltaY { if (!(NSEventMaskFromType(event_type) & GSMouseMovedEventMask)) { return 0.0; } return event_data.mouse.deltaY; } /**

Returns the movement of the mouse on the Z axis.

This method is only valid for NSMouseMoved, NS*MouseDragged and NSScrollWheel events, otherwise it will return 0.

The value returned is 0.0 in most cases.

*/ - (CGFloat) deltaZ { if (!(NSEventMaskFromType(event_type) & GSMouseMovedEventMask)) { return 0.0; } return event_data.mouse.deltaZ; } - (NSString*) description { static const char *eventTypes[] = { "nullEvent", "leftMouseDown", "leftMouseUp", "rightMouseDown", "rightMouseUp", "mouseMoved", "leftMouseDragged", "rightMouseDragged", "mouseEntered", "mouseExited", "keyDown", "keyUp", "flagsChanged", "appKitDefined", "systemDefined", "applicationDefined", "periodic", "cursorUpdate", "", "", "", "", "scrollWheel", "tabletPoint", "tabletProximity", "otherMouseDown", "otherMouseUp", "otherMouseDragged" }; switch (event_type) { case NSLeftMouseDown: case NSLeftMouseUp: case NSOtherMouseDown: case NSOtherMouseUp: case NSRightMouseDown: case NSRightMouseUp: return [NSString stringWithFormat: @"NSEvent: eventType = %s, point = { %f, %f }, modifiers = %lu," @" time = %f, window = %ld, dpsContext = %p," @" event number = %ld, click = %ld, pressure = %f", eventTypes[event_type], location_point.x, location_point.y, (unsigned long) modifier_flags, event_time, (long) window_num, event_context, (long int) event_data.mouse.event_num, (long int) event_data.mouse.click, event_data.mouse.pressure]; break; case NSMouseEntered: case NSMouseExited: return [NSString stringWithFormat: @"NSEvent: eventType = %s, point = { %f, %f }, modifiers = %lu," @" time = %f, window = %ld, dpsContext = %p, " @" event number = %ld, tracking number = %ld, user data = %p", eventTypes[event_type], location_point.x, location_point.y, (unsigned long) modifier_flags, event_time, (long) window_num, event_context, (long) event_data.tracking.event_num, (long) event_data.tracking.tracking_num, event_data.tracking.user_data]; break; case NSKeyDown: case NSKeyUp: case NSFlagsChanged: return [NSString stringWithFormat: @"NSEvent: eventType = %s, point = { %f, %f }, modifiers = %lu," @" time = %f, window = %ld, dpsContext = %p, " @" repeat = %s, keys = %@, ukeys = %@, keyCode = 0x%x", eventTypes[event_type], location_point.x, location_point.y, (unsigned long) modifier_flags, event_time, (long) window_num, event_context, (event_data.key.repeat ? "YES" : "NO"), event_data.key.char_keys, event_data.key.unmodified_keys, event_data.key.key_code]; break; case NSPeriodic: case NSCursorUpdate: case NSAppKitDefined: case NSSystemDefined: case NSApplicationDefined: return [NSString stringWithFormat: @"NSEvent: eventType = %s, point = { %f, %f }, modifiers = %lu," @" time = %f, window = %ld, dpsContext = %p, " @" subtype = %d, data1 = %lx, data2 = %lx", eventTypes[event_type], location_point.x, location_point.y, (unsigned long) modifier_flags, event_time, (long) window_num, event_context, event_data.misc.sub_type, (long) event_data.misc.data1, (long) event_data.misc.data2]; break; case NSScrollWheel: case NSMouseMoved: case NSLeftMouseDragged: case NSOtherMouseDragged: case NSRightMouseDragged: return [NSString stringWithFormat: @"NSEvent: eventType = %s, point = { %f, %f }, modifiers = %lu," @" time = %f, window = %ld, dpsContext = %p," @" event number = %ld, click = %ld, pressure = %f" @" button = %ld, deltaX = %f, deltaY = %f, deltaZ = %f", eventTypes[event_type], location_point.x, location_point.y, (unsigned long) modifier_flags, event_time, (long) window_num, event_context, (long ) event_data.mouse.event_num, (long) event_data.mouse.click, event_data.mouse.pressure, (long) event_data.mouse.button, event_data.mouse.deltaX, event_data.mouse.deltaY, event_data.mouse.deltaZ]; break; // FIXME: Tablet events case NSTabletPoint: case NSTabletProximity: break; default: return [NSString stringWithFormat: @"NSEvent: eventType = UNKNOWN!, point = { %f, %f }, modifiers = %lu," @" time = %f, window = %ld", location_point.x, location_point.y, (unsigned long) modifier_flags, event_time, (long) window_num]; break; } return [super description]; } - (void) encodeWithCoder: (NSCoder*)aCoder { if ([aCoder allowsKeyedCoding]) { // FIXME } else { [aCoder encodeValueOfObjCType: @encode(NSInteger) at: &event_type]; [aCoder encodePoint: location_point]; [aCoder encodeValueOfObjCType: @encode(NSUInteger) at: &modifier_flags]; [aCoder encodeValueOfObjCType: @encode(NSTimeInterval) at: &event_time]; [aCoder encodeValueOfObjCType: @encode(NSInteger) at: &window_num]; switch (event_type) { case NSLeftMouseDown: case NSLeftMouseUp: case NSOtherMouseDown: case NSOtherMouseUp: case NSRightMouseDown: case NSRightMouseUp: case NSScrollWheel: case NSMouseMoved: case NSLeftMouseDragged: case NSOtherMouseDragged: case NSRightMouseDragged: [aCoder encodeValuesOfObjCTypes: "iififff", &event_data.mouse.event_num, &event_data.mouse.click, &event_data.mouse.pressure, &event_data.mouse.button, &event_data.mouse.deltaX, &event_data.mouse.deltaY, &event_data.mouse.deltaZ]; break; case NSMouseEntered: case NSMouseExited: case NSCursorUpdate: // Can't do anything with the user_data!? [aCoder encodeValuesOfObjCTypes: "ii", &event_data.tracking.event_num, &event_data.tracking.tracking_num]; break; case NSKeyDown: case NSKeyUp: case NSFlagsChanged: [aCoder encodeValueOfObjCType: @encode(BOOL) at: &event_data.key.repeat]; [aCoder encodeObject: event_data.key.char_keys]; [aCoder encodeObject: event_data.key.unmodified_keys]; [aCoder encodeValueOfObjCType: "S" at: &event_data.key.key_code]; break; case NSPeriodic: case NSAppKitDefined: case NSSystemDefined: case NSApplicationDefined: [aCoder encodeValuesOfObjCTypes: "sii", &event_data.misc.sub_type, &event_data.misc.data1, &event_data.misc.data2]; break; case NSTabletPoint: case NSTabletProximity: // FIXME: Tablet events break; } } } /** * Returns the event number associated with any mouse event or tracking * event. Event numbers are allocated sequentially when the system * creates these events. *
Raises an NSInternalInconsistencyException if applied to any * other type of event. */ - (NSInteger) eventNumber { /* Make sure it is one of the right event types */ if (!(NSEventMaskFromType(event_type) & GSMouseEventMask) && !(NSEventMaskFromType(event_type) & GSEnterExitEventMask)) [NSException raise: NSInternalInconsistencyException format: @"eventNumber requested for non-tracking event"]; if ((event_type == NSMouseEntered) || (event_type == NSMouseExited)) return event_data.tracking.event_num; else return event_data.mouse.event_num; } - (id) initWithCoder: (NSCoder*)aDecoder { if ([aDecoder allowsKeyedCoding]) { // FIXME } else { int version = [aDecoder versionForClassName: @"NSEvent"]; [aDecoder decodeValueOfObjCType: @encode(NSInteger) at: &event_type]; location_point = [aDecoder decodePoint]; [aDecoder decodeValueOfObjCType: @encode(NSUInteger) at: &modifier_flags]; [aDecoder decodeValueOfObjCType: @encode(NSTimeInterval) at: &event_time]; [aDecoder decodeValueOfObjCType: @encode(NSInteger) at: &window_num]; if (version == 1) { // For the unlikely case that old events have been stored, convert them. switch ((int)event_type) { case 0: event_type = NSLeftMouseDown; break; case 1: event_type = NSLeftMouseUp; break; case 2: event_type = NSOtherMouseDown; break; case 3: event_type = NSOtherMouseUp; break; case 4: event_type = NSRightMouseDown; break; case 5: event_type = NSRightMouseUp; break; case 6: event_type = NSMouseMoved; break; case 7: event_type = NSLeftMouseDragged; break; case 8: event_type = NSOtherMouseDragged; break; case 9: event_type = NSRightMouseDragged; break; case 10: event_type = NSMouseEntered; break; case 11: event_type = NSMouseExited; break; case 12: event_type = NSKeyDown; break; case 13: event_type = NSKeyUp; break; case 14: event_type = NSFlagsChanged; break; case 15: event_type = NSAppKitDefined; break; case 16: event_type = NSSystemDefined; break; case 17: event_type = NSApplicationDefined; break; case 18: event_type = NSPeriodic; break; case 19: event_type = NSCursorUpdate; break; case 20: event_type = NSScrollWheel; break; default: break; } } // Previously flag change events where encoded wrongly if ((version == 2) && (event_type == NSFlagsChanged)) { [aDecoder decodeValuesOfObjCTypes: "sii", &event_data.misc.sub_type, &event_data.misc.data1, &event_data.misc.data2]; return self; } // Decode the event date based upon the event type switch (event_type) { case NSLeftMouseDown: case NSLeftMouseUp: case NSOtherMouseDown: case NSOtherMouseUp: case NSRightMouseDown: case NSRightMouseUp: case NSScrollWheel: case NSMouseMoved: case NSLeftMouseDragged: case NSOtherMouseDragged: case NSRightMouseDragged: [aDecoder decodeValuesOfObjCTypes: "iififff", &event_data.mouse.event_num, &event_data.mouse.click, &event_data.mouse.pressure, &event_data.mouse.button, &event_data.mouse.deltaX, &event_data.mouse.deltaY, &event_data.mouse.deltaZ]; break; case NSMouseEntered: case NSMouseExited: case NSCursorUpdate: // Can't do anything with the user_data!? [aDecoder decodeValuesOfObjCTypes: "ii", &event_data.tracking.event_num, &event_data.tracking.tracking_num]; break; case NSKeyDown: case NSKeyUp: case NSFlagsChanged: [aDecoder decodeValueOfObjCType: @encode(BOOL) at: &event_data.key.repeat]; event_data.key.char_keys = [aDecoder decodeObject]; event_data.key.unmodified_keys = [aDecoder decodeObject]; [aDecoder decodeValueOfObjCType: "S" at: &event_data.key.key_code]; break; case NSPeriodic: case NSAppKitDefined: case NSSystemDefined: case NSApplicationDefined: [aDecoder decodeValuesOfObjCTypes: "sii", &event_data.misc.sub_type, &event_data.misc.data1, &event_data.misc.data2]; break; case NSTabletPoint: case NSTabletProximity: // FIXME: Tablet events break; } } return self; } /** * Returns a flag to say if this is a keyboard repeat event. *
Raises an NSInternalInconsistencyException if applied to any * other type of event than an NSKeyUp or NSKeyDown. */ - (BOOL) isARepeat { if ((event_type != NSKeyUp) && (event_type != NSKeyDown)) [NSException raise: NSInternalInconsistencyException format: @"isARepeat requested for non-keyboard event"]; return event_data.key.repeat; } /** * Returns the numeric key code of a keyboard event. *
Raises an NSInternalInconsistencyException if applied to any * other type of event than an NSKeyUp or NSKeyDown. */ - (unsigned short) keyCode { if (!(NSEventMaskFromType(event_type) & GSKeyEventMask)) { [NSException raise: NSInternalInconsistencyException format: @"keyCode requested for non-keyboard event"]; } return event_data.key.key_code; } /** * Returns the window location for which this event was generated (in the * base coordinate system of the window). */ - (NSPoint) locationInWindow { return location_point; } /** * Returns the modifier flag bits associated with the event. */ - (NSUInteger) modifierFlags { return modifier_flags; } /** * Returns the pressure associated with a mouse event. This is a value * in the range 0.0 to 1.0 and for mormal mouse events should be set to * one of those extremes. This is used by pressure sensitive input devices. *
Raises an NSInternalInconsistencyException if applied to any * other type of event than a mouse event. */ - (float) pressure { /* Make sure it is one of the right event types */ if (!(NSEventMaskFromType(event_type) & GSMouseEventMask)) { [NSException raise: NSInternalInconsistencyException format: @"pressure requested for non-mouse event"]; } return event_data.mouse.pressure; } /** * Returns the 'subtype' item associated with the event. *
Raises NSInternalInconsistencyException if the event is not * of type NSAppKitDefined, NSSystemDefined, NSApplicationDefined, * NSPeriodic or a mouve event. */ - (short) subtype { if (!(NSEventMaskFromType(event_type) & GSOtherEventMask) && !(NSEventMaskFromType(event_type) & GSMouseEventMask)) { [NSException raise: NSInternalInconsistencyException format: @"subtype requested for invalid event type"]; } if (NSEventMaskFromType(event_type) & GSOtherEventMask) return event_data.misc.sub_type; else { if (event_type == NSTabletPoint) return NSTabletPointEventSubtype; else if (event_type == NSTabletProximity) return NSTabletProximityEventSubtype; else return NSMouseEventSubtype; } } /** * Returns the time interval since system startup at which this * event was generated. */ - (NSTimeInterval) timestamp { return event_time; } /** * Returns a number identifying the tracking rectangle entered or exited. *
Raises an NSInternalInconsistencyException if applied to any * other type of event than a mouse entered or exited event. */ - (NSInteger) trackingNumber { if (event_type != NSMouseEntered && event_type != NSMouseExited && event_type != NSCursorUpdate) { [NSException raise: NSInternalInconsistencyException format: @"trackingNumber requested for non-tracking event"]; } return event_data.tracking.tracking_num; } /** * returns the type of this event. */ - (NSEventType) type { return event_type; } /** * Returns usder data associated with a tracking event... the data assigned to * the tracking rectangle concerned when it was created.. *
Raises an NSInternalInconsistencyException if applied to any * other type of event than a mouse entered or exited event. */ - (void *) userData { if (event_type != NSMouseEntered && event_type != NSMouseExited && event_type != NSCursorUpdate) { [NSException raise: NSInternalInconsistencyException format: @"userData requested for non-tracking event"]; } return event_data.tracking.user_data; } /** * Returns the window for which this event was generated.
* Periodic events have no associated window, and you should not call * this method for those events. */ - (NSWindow *) window { return GSWindowWithNumber(window_num); } /** * Returns the window number of the window for which this event was generated. *
Periodic events have no associated window, and you should not call * this method for those events. */ - (NSInteger) windowNumber { return window_num; } /* * Methods for tablet events */ - (NSInteger) absoluteX { // FIXME return 0; } - (NSInteger) absoluteY { // FIXME return 0; } - (NSInteger) absoluteZ { // FIXME return 0; } - (NSUInteger) buttonMask { // FIXME return 0; } - (NSUInteger) capabilityMask { // FIXME return 0; } - (NSUInteger) deviceID { // FIXME return 0; } - (BOOL) isEnteringProximity { // FIXME return NO; } - (NSUInteger) pointingDeviceID { // FIXME return 0; } - (NSUInteger) pointingDeviceSerialNumber { // FIXME return 0; } - (NSPointingDeviceType) pointingDeviceType { // FIXME return NSUnknownPointingDevice; } - (float) rotation { // FIXME return 0.0; } - (NSUInteger) systemTabletID { // FIXME return 0; } - (NSUInteger) tabletID { // FIXME return 0; } - (float) tangentialPressure { // FIXME return 0.0; } - (NSPoint) tilt { // FIXME return NSMakePoint(0.0, 0.0); } - (unsigned long long) uniqueID { // FIXME return 0; } - (id) vendorDefined { // FIXME return nil; } - (NSUInteger) vendorID { // FIXME return 0; } - (NSUInteger) vendorPointingDeviceType { // FIXME return 0; } @end