Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save nacho4d/1592813 to your computer and use it in GitHub Desktop.
Save nacho4d/1592813 to your computer and use it in GitHub Desktop.
Trying to catch keyboard events
// 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
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
@swilliams
Copy link

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:

1 << 16 // cmd
1 << 17 // shift
1 << 19 // option
1 << 20 // ctrl

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment