Modifier key sends Esc

Adds possibility to make the left Ctrl, Alt, or Cmd key function as a
second Esc key.  The key will still function as a modifier if held down
in conjunction with another key.  Enable by setting the user default
"MMFakeEscModifier" to:
    1 = Left Ctrl
    2 = Left Alt
    3 = Left Cmd
    any other number disables this functionality

By remapping Caps-Lock to one of the above modifier keys this enables
the use of Caps-Lock as a second (and easy to reach) Esc key.  Caps-Lock
can be remapped inside "System Preferences -> Keyboard & Mouse ->
Modifier Keys...".

The Esc event is sent when the modifier key is released.  If the key is
not released within a predefined timeout, then no Esc event is
generated.  The timeout can be changed by setting the user default
MMFakeEscTimeout (a float, specifying the timeout in seconds).

The fact that the Esc event is sent on release makes it feel somewhat
sluggish.  It is possible to have the event sent when the modifier key
is pressed by setting the user default "MMFakeEscOnKeyDown" but then the
left modifier key can only be used as an Esc key.
This commit is contained in:
Bjorn Winckler
2008-09-30 22:06:30 +02:00
parent 6fb7a6f38b
commit 3d2d6a810e
5 changed files with 126 additions and 1 deletions
+4
View File
@@ -185,6 +185,10 @@ fsEventCallback(ConstFSEventStreamRef streamRef,
[NSNumber numberWithBool:NO], MMVerticalSplitKey,
[NSNumber numberWithInt:0], MMPreloadCacheSizeKey,
[NSNumber numberWithInt:0], MMLastWindowClosedBehaviorKey,
[NSNumber numberWithInt:MMDisableFakeEsc],
MMFakeEscModifierKey,
[NSNumber numberWithFloat:0.3], MMFakeEscTimeoutKey,
[NSNumber numberWithBool:NO], MMFakeEscOnKeyDownKey,
nil];
[[NSUserDefaults standardUserDefaults] registerDefaults:dict];
+7
View File
@@ -12,6 +12,13 @@
@interface MMApplication : NSApplication {
CFAbsoluteTime fakeEscTimeDown;
CFAbsoluteTime fakeEscTimeout;
int fakeEscKeyCode;
unsigned fakeEscModifierMask;
BOOL blockFakeEscEvent;
BOOL blockKeyDown;
BOOL fakeEscOnKeyDown;
}
@end
+101 -1
View File
@@ -14,6 +14,7 @@
*/
#import "MMApplication.h"
#import "Miscellaneous.h"
// Ctrl-Tab is broken on pre 10.5, so we add a hack to make it work.
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4
@@ -26,11 +27,107 @@
@implementation MMApplication
- (void)awakeFromNib
{
NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
switch ([ud integerForKey:MMFakeEscModifierKey]) {
case MMCtrlFakeEsc:
fakeEscKeyCode = 59;
fakeEscModifierMask = NSControlKeyMask;
break;
case MMAltFakeEsc:
fakeEscKeyCode = 58;
fakeEscModifierMask = NSAlternateKeyMask;
break;
case MMCmdFakeEsc:
fakeEscKeyCode = 55;
fakeEscModifierMask = NSCommandKeyMask;
break;
default:
fakeEscKeyCode = fakeEscModifierMask = 0;
}
fakeEscTimeout = [ud floatForKey:MMFakeEscTimeoutKey];
fakeEscOnKeyDown = [ud boolForKey:MMFakeEscOnKeyDownKey];
}
- (void)sendEvent:(NSEvent *)event
{
NSEventType type = [event type];
unsigned flags = [event modifierFlags];
// The following hack allows the user to set one modifier key of choice
// (Ctrl, Alt, or Cmd) to generate an Esc key press event. In order for
// the key to still be used as a modifier we only send the "faked" Esc
// event if the modifier was pressed and released without any other keys
// being pressed in between. The user may elect to have the chosen
// modifier sending Esc on key down, since sending it on key up makes it
// appear a bit sluggish. However, this effectively disables the modifier
// key (but only the left key and not the right one, in case there are two
// on the keyboard).
//
// This hack is particularly useful in conjunction with Mac OS X's ability
// to turn Caps-Lock into a modifier key of choice because it enables us to
// turn Caps-Lock into a quasi-Esc key! (This remapping be done inside
// "System Preferences -> Keyboard & Mouse -> Modifier Keys...".)
//
if (fakeEscKeyCode != 0) {
if (NSFlagsChanged == type && [event keyCode] == fakeEscKeyCode) {
BOOL sendEsc = NO;
CFAbsoluteTime timeNow = CFAbsoluteTimeGetCurrent();
if ((flags & fakeEscModifierMask) == 0) {
// The chosen modifier was released. If the modifier was
// recently pressed then convert this event to a "fake" Esc key
// press event.
if (!blockFakeEscEvent && !fakeEscOnKeyDown &&
timeNow - fakeEscTimeDown < fakeEscTimeout)
sendEsc = YES;
blockFakeEscEvent = YES;
blockKeyDown = NO;
} else {
// The chosen modifier was pressed.
blockFakeEscEvent = NO;
fakeEscTimeDown = timeNow;
if (fakeEscOnKeyDown) {
sendEsc = YES;
// Block key down while the fake Esc modifier key is held,
// otherwise "marked text" may pop up if a key is pressed
// while the fake Esc modifier is held (which looks ugly,
// but is harmless).
blockKeyDown = YES;
}
}
if (sendEsc) {
NSEvent *e = [NSEvent keyEventWithType:NSKeyDown
location:[event locationInWindow]
modifierFlags:flags & 0x0000ffffU
timestamp:[event timestamp]
windowNumber:[event windowNumber]
context:[event context]
characters:@"\x1b" // Esc
charactersIgnoringModifiers:@"\x1b"
isARepeat:NO
keyCode:53];
[self postEvent:e atStart:YES];
return;
}
} else if (type != NSKeyUp) {
// Another event occurred, so don't send any fake Esc events now
// (else the modifier would not function as a modifier key any
// more).
blockFakeEscEvent = YES;
}
if (blockKeyDown && type == NSKeyDown)
return;
}
#ifdef MM_CTRL_TAB_HACK
NSResponder *firstResponder = [[self keyWindow] firstResponder];
@@ -51,7 +148,7 @@
// key event.
if ((NSKeyDown == type || NSKeyUp == type) && (flags & NSHelpKeyMask)) {
flags &= ~NSHelpKeyMask;
event = [NSEvent keyEventWithType:[event type]
NSEvent *e = [NSEvent keyEventWithType:[event type]
location:[event locationInWindow]
modifierFlags:flags
timestamp:[event timestamp]
@@ -61,6 +158,9 @@
charactersIgnoringModifiers:[event charactersIgnoringModifiers]
isARepeat:[event isARepeat]
keyCode:[event keyCode]];
[self postEvent:e atStart:YES];
return;
}
[super sendEvent:event];
+11
View File
@@ -53,6 +53,9 @@ extern NSString *MMOpenLayoutKey;
extern NSString *MMVerticalSplitKey;
extern NSString *MMPreloadCacheSizeKey;
extern NSString *MMLastWindowClosedBehaviorKey;
extern NSString *MMFakeEscModifierKey;
extern NSString *MMFakeEscTimeoutKey;
extern NSString *MMFakeEscOnKeyDownKey;
// Enum for MMUntitledWindowKey
@@ -79,6 +82,14 @@ enum {
MMTerminateWhenLastWindowClosed = 2,
};
// Enum for MMFakeEscModifierKey
enum {
MMDisableFakeEsc = 0,
MMCtrlFakeEsc = 1,
MMAltFakeEsc = 2,
MMCmdFakeEsc = 3
};
+3
View File
@@ -44,6 +44,9 @@ NSString *MMOpenLayoutKey = @"MMOpenLayout";
NSString *MMVerticalSplitKey = @"MMVerticalSplit";
NSString *MMPreloadCacheSizeKey = @"MMPreloadCacheSize";
NSString *MMLastWindowClosedBehaviorKey = @"MMLastWindowClosedBehavior";
NSString *MMFakeEscModifierKey = @"MMFakeEscModifier";
NSString *MMFakeEscTimeoutKey = @"MMFakeEscTimeout";
NSString *MMFakeEscOnKeyDownKey = @"MMFakeEscOnKeyDown";