Skip to content

Instantly share code, notes, and snippets.

@atr000
Created May 3, 2010 00:33
Show Gist options
  • Save atr000/387590 to your computer and use it in GitHub Desktop.
Save atr000/387590 to your computer and use it in GitHub Desktop.
/* keyremap.c
*
* features:
* 1. map lower enter to forward delete key - useful for macbooks
* (works only when secure event input is not activated,
* which happens very rarely, e.g. when password fields are focused)
* 2. send enter key event when right command key is released
* without any other key pressed while it was down
*
* by Bert Mu"nnich, January 2009
* Based on http://www.osxbook.com/book/bonus/chapter2/alterkeys/
* so the credits go to Amit Singh
*
* Compile it using the following cmdline:
* gcc -framework ApplicationServices -O3 -o keyremap keyremap.c
*
* Tested on Mac OS X 10.6.1
*/
#define debug(...) if (debugMsgsEnabled) printf(__VA_ARGS__)
#define RIGHT_CMD_DOWN 1048848
#define MODIFIER_UP 256
#include <ApplicationServices/ApplicationServices.h>
const CGKeyCode ENTER = (CGKeyCode) 76;
const CGKeyCode FWDDEL = (CGKeyCode) 117;
const CGKeyCode RIGHT_CMD = (CGKeyCode) 54;
static bool sendEnter = false;
static bool debugMsgsEnabled = false;
const char *progname = "";
CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
CGKeyCode keycode = (CGKeyCode) CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
CGEventFlags modifiers = CGEventGetFlags(event);
debug("Type: %i Modifiers: %i Keycode: %i\n", type, (int) modifiers, keycode);
if (keycode == RIGHT_CMD) {
if (modifiers == RIGHT_CMD_DOWN) {
sendEnter = true;
} else if (modifiers == MODIFIER_UP && sendEnter) {
debug("right cmd released with no other key pressed -> send enter key event\n");
sendEnter = false;
// we had to get a new CGEventRef every time because creating a
// global one causes a bus error inside CGEventCreateKeyboardEvent
CGEventRef enterKey = CGEventCreateKeyboardEvent(NULL, ENTER, true);
CGEventSetFlags(enterKey, (CGEventFlags) 256);
// press the enter key...
CGEventSetType(enterKey, kCGEventKeyDown);
CGEventTapPostEvent(proxy, enterKey);
// ... and release it
CGEventSetType(enterKey, kCGEventKeyUp);
CGEventTapPostEvent(proxy, enterKey);
CFRelease(enterKey);
}
} else if (sendEnter) {
debug("another key pressed while right cmd down -> don't send enter key event\n");
sendEnter = false;
}
if (keycode == ENTER) {
debug("change enter to fwd delete\n");
CGEventSetIntegerValueField(event, kCGKeyboardEventKeycode, FWDDEL);
}
return event;
}
int main(int argc, char **argv) {
if (argc > 1) {
debugMsgsEnabled = true;
}
progname = argv[0];
CFMachPortRef eventTap;
CFRunLoopSourceRef runLoopSource;
CGEventMask eventMask = CGEventMaskBit(kCGEventFlagsChanged) | CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp);
eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0, eventMask, myCGEventCallback, NULL);
if (!eventTap) {
fprintf(stderr, "Failed to create event tap!\n");
exit(1);
}
runLoopSource = CFMachPortCreateRunLoopSource(NULL, eventTap, 0);
CFRelease(eventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
CFRelease(runLoopSource);
CFRunLoopRun();
exit(0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment