Created
January 11, 2012 03:19
-
-
Save nacho4d/1592813 to your computer and use it in GitHub Desktop.
Trying to catch keyboard events
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Created by Guillermo Enriquez on 09/10/2012. | |
// Copyright 2012 nacho4d. All rights reserved. | |
int main(int argc, char *argv[]) { | |
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
int retVal = UIApplicationMain(argc, argv, @"Application", @"AppDelegate"); | |
[pool drain]; | |
return retVal; | |
} | |
@interface Application : UIApplication | |
@end | |
@implementation Application | |
// Calculation of offsets for traversing GSEventRef: | |
// Count the size of types inside CGEventRecord struct | |
// https://github.com/kennytm/iphone-private-frameworks/blob/master/GraphicsServices/GSEvent.h | |
// typedef struct GSEventRecord { | |
// GSEventType type; // 0x8 //2 | |
// GSEventSubType subtype; // 0xC //3 | |
// CGPoint location; // 0x10 //4 | |
// CGPoint windowLocation; // 0x18 //6 | |
// int windowContextId; // 0x20 //8 | |
// uint64_t timestamp; // 0x24, from mach_absolute_time //9 | |
// GSWindowRef window; // 0x2C // | |
// GSEventFlags flags; // 0x30 //12 | |
// unsigned senderPID; // 0x34 //13 | |
// CFIndex infoSize; // 0x38 //14 | |
// } GSEventRecord; | |
// typedef struct GSEventKey { | |
// GSEvent _super; | |
// UniChar keycode, characterIgnoringModifier, character; // 0x38, 0x3A, 0x3C // 15 and start of 16 | |
// short characterSet; // 0x3E // end of 16 | |
// Boolean isKeyRepeating; // 0x40 // start of 17 | |
// } GSEventKey; | |
#define GSEVENT_TYPE 2 | |
//#define GSEVENT_SUBTYPE 3 | |
//#define GSEVENT_LOCATION 4 | |
//#define GSEVENT_WINLOCATION 6 | |
//#define GSEVENT_WINCONTEXTID 8 | |
//#define GSEVENT_TIMESTAMP 9 | |
//#define GSEVENT_WINREF 11 | |
#define GSEVENT_FLAGS 12 | |
//#define GSEVENT_SENDERPID 13 | |
//#define GSEVENT_INFOSIZE 14 | |
#define GSEVENTKEY_KEYCODE_CHARIGNORINGMOD 15 | |
//#define GSEVENTKEY_CHARSET_CHARSET 16 | |
//#define GSEVENTKEY_ISKEYREPEATING 17 // ?? | |
#define GSEVENT_TYPE_KEYDOWN 10 | |
#define GSEVENT_TYPE_KEYUP 11 | |
NSString *const UIEventGSEventKeyUpNotification = @"UIEventGSEventKeyUpNotification"; | |
- (void)sendEvent:(UIEvent *)event | |
{ | |
[super sendEvent:event]; | |
if ([event respondsToSelector:@selector(_gsEvent)]) { | |
// Hardware Key events are of kind UIInternalEvent which are a wrapper of GSEventRef which is wrapper of GSEventRecord | |
int *eventMemory = (int *)[event performSelector:@selector(_gsEvent)]; | |
if (eventMemory) { | |
int eventType = eventMemory[GSEVENT_TYPE]; | |
NSLog(@"event type = %d", eventType); | |
if (eventType == GSEVENT_TYPE_KEYUP) { | |
// Since the event type is key up we can assume is a GSEventKey struct | |
// Get flags from GSEvent | |
int eventFlags = eventMemory[GSEVENT_FLAGS]; | |
if (eventFlags) { | |
NSLog(@"flags %8X", eventFlags); | |
// Only post notifications when Shift, Ctrl, Cmd or Alt key were pressed. | |
// Get keycode from GSEventKey | |
int tmp = eventMemory[15]; | |
UniChar *keycode = (UniChar *)&tmp; // Cast to silent warning | |
//tmp = (tmp & 0xFF00); | |
//tmp = tmp >> 16; | |
//UniChar keycode = tmp; | |
//tmp = eventMemory[16]; | |
//tmp = (tmp & 0x00FF); | |
//tmp = tmp << 16; | |
//UniChar keycode = tmp; | |
NSLog(@"keycode %d", keycode[0]); | |
//printf("Shift Ctrl Alt Cmd %d %d %d %d\n ", (eventFlags&(1<<17))?1:0, (eventFlags&(1<<18))?1:0, (eventFlags&(1<<19))?1:0, (eventFlags&(1<<20))?1:0 ); | |
NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:[NSNumber numberWithShort:keycode[0]], @"keycode", [NSNumber numberWithInt:eventFlags], @"eventFlags", nil]; | |
[[NSNotificationCenter defaultCenter] postNotificationName:UIEventGSEventKeyUpNotification object:nil userInfo:userInfo]; | |
/* | |
Some Keycodes found | |
=================== | |
Alphabet | |
a = 4 | |
b = 5 | |
c = ... | |
z = 29 | |
Numbers | |
1 = 30 | |
2 = 31 | |
3 = ... | |
9 = 38 | |
Arrows | |
Right = 79 | |
Left = 80 | |
Down = 81 | |
Up = 82 | |
Flags found (Differ from Kenny's header) | |
======================================== | |
Cmd = 1 << 17 | |
Shift = 1 << 18 | |
Ctrl = 1 << 19 | |
Alt = 1 << 20 | |
*/ | |
} | |
} | |
} | |
} | |
} | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int main(int argc, char *argv[]) { | |
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; | |
int retVal = UIApplicationMain(argc, argv, @"Application", @"AppDelegate"); | |
[pool drain]; | |
return retVal; | |
} | |
@interface Application : UIApplication | |
@end | |
@implementation Application | |
// Calculation of offsets for traversing GSEventRef: | |
// Count the size of types inside CGEventRecord struct. Just for Reference: | |
// https://github.com/kennytm/iphone-private-frameworks/blob/master/GraphicsServices/GSEvent.h | |
// typedef struct GSEventRecord { | |
// GSEventType type; // 0x8 | |
// GSEventSubType subtype; // 0xC | |
// CGPoint location; // 0x10 | |
// CGPoint windowLocation; // 0x18 | |
// int windowContextId; // 0x20 | |
// uint64_t timestamp; // 0x24, from mach_absolute_time | |
// GSWindowRef window; // 0x2C | |
// GSEventFlags flags; // 0x30 | |
// unsigned senderPID; // 0x34 | |
// CFIndex infoSize; // 0x38 | |
//} GSEventRecord; | |
#define GS_EVENT_TYPE_OFFSET 2 | |
// fields length (1 : 4 bytes) | |
#define GS_EVENT_TYPE_LEN 1 | |
#define GS_EVENT_SUBTYPE_LEN 1 | |
#define GS_EVENT_LOCATION_LEN 2 | |
#define GS_EVENT_WINLOCATION_LEN 2 | |
#define GS_EVENT_WINCONTEXTID_LEN 1 | |
#define GS_EVENT_TIMESTAMP_LEN 4 | |
#define GS_EVENT_WINREF_LEN 1 | |
//#define GS_EVENT_FLAGS_LEN 1 | |
//#define GS_EVENT_SENDERPID_LEN 1 | |
//#define GS_EVENT_INFOSIZE_LEN 1 | |
- (void)sendEvent:(UIEvent *)anEvent | |
{ | |
[super sendEvent:anEvent]; | |
return;// Disable below code because so far I couldn't find key event flags (Shift, Cmd, Alt, Ctrl) | |
// Send notification if is a keyboard event | |
if ([anEvent respondsToSelector:@selector(_gsEvent)]) { | |
// Hardware Key events are of kind UIInternalEvent which are a wrapper of GSEventRef which is wrapper of GSEventRecord | |
int *eventMemory = (int *)[anEvent performSelector:@selector(_gsEvent)]; | |
if (eventMemory) { | |
int eventType = eventMemory[GS_EVENT_TYPE_OFFSET]; | |
NSLog(@"event type = %d", eventType); // keydown:11, keyup:12 | |
int flagsOffset = GS_EVENT_TYPE_OFFSET + GS_EVENT_TYPE_LEN + GS_EVENT_SUBTYPE_LEN + GS_EVENT_LOCATION_LEN + GS_EVENT_WINLOCATION_LEN + GS_EVENT_WINCONTEXTID_LEN + GS_EVENT_TIMESTAMP_LEN + GS_EVENT_WINREF_LEN; | |
// Apparently above offset calculation is only for iOS4, in iOS5 GSEvent.h is somehow changed and below code does not work | |
int eventFlags = eventMemory[flagsOffset]; | |
printf("%8X ", eventFlags); | |
printf("Shift Ctrl Alt Cmd %d %d %d %d\n ", (eventFlags&(1<<17))?1:0, (eventFlags&(1<<18))?1:0, (eventFlags&(1<<19))?1:0, (eventFlags&(1<<20))?1:0 ); | |
// Now do something with the flags :) | |
} | |
} | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Experimenting with this, on my iPad (3rd gen, iOS 6.1.3) + Apple BT keyboard, the modifier flags are like so. Wonder if this differs per version of iOS and/or hardware: