Don't drop non-repeating keyboard input

Keyboard input is not dropped, unless the input was received due to a
key being automatically repeated (as a consequence of the key being held
down).  This way characters are never dropped while typing, but it also
avoids situations where the screen doesn't stop scrolling immediately
when "j" is released after being held.
This commit is contained in:
Bjorn Winckler
2008-09-28 23:50:39 +02:00
parent e378d7332b
commit 2d1fc65b0e
2 changed files with 81 additions and 36 deletions
+53 -30
View File
@@ -91,7 +91,7 @@ static NSString *MMSymlinkWarningString =
- (void)processInputQueue;
- (void)handleInputEvent:(int)msgid data:(NSData *)data;
+ (NSDictionary *)specialKeys;
- (void)handleInsertText:(NSData *)data;
- (void)handleInsertText:(NSString *)text;
- (void)handleKeyDown:(NSString *)key modifiers:(int)mods;
- (void)queueMessage:(int)msgid data:(NSData *)data;
- (void)connectionDidDie:(NSNotification *)notification;
@@ -1048,11 +1048,16 @@ static NSString *MMSymlinkWarningString =
BOOL interrupt = NO;
if (msgid == InterruptMsgID) {
interrupt = YES;
} else if (InsertTextMsgID == msgid && data != nil && [data length] == 1) {
char_u *str = (char_u*)[data bytes];
if ((str[0] == Ctrl_C && ctrl_c_interrupts) ||
(str[0] == intr_char && intr_char != Ctrl_C))
interrupt = YES;
} else if (InsertTextMsgID == msgid && data != nil) {
const void *bytes = [data bytes];
bytes += sizeof(int);
int len = *((int*)bytes); bytes += sizeof(int);
if (1 == len) {
char_u *str = (char_u*)bytes;
if ((str[0] == Ctrl_C && ctrl_c_interrupts) ||
(str[0] == intr_char && intr_char != Ctrl_C))
interrupt = YES;
}
}
if (interrupt) {
@@ -1063,18 +1068,36 @@ static NSString *MMSymlinkWarningString =
// Remove all previous instances of this message from the input queue, else
// the input queue may fill up as a result of Vim not being able to keep up
// with the speed at which new messages are received. This avoids annoying
// situations such as when the keyboard repeat rate is higher than what Vim
// can cope with (which would cause a 'stutter' when scrolling by holding
// down 'j' and then when 'j' was released the screen kept scrolling for a
// little while).
// with the speed at which new messages are received.
// Keyboard input is never dropped, unless the input represents and
// auto-repeated key.
int i, count = [inputQueue count];
for (i = 1; i < count; i+=2) {
if ([[inputQueue objectAtIndex:i-1] intValue] == msgid) {
[inputQueue removeObjectAtIndex:i];
[inputQueue removeObjectAtIndex:i-1];
break;
BOOL isKeyRepeat = NO;
BOOL isKeyboardInput = NO;
if (data && (InsertTextMsgID == msgid || KeyDownMsgID == msgid ||
CmdKeyMsgID == msgid)) {
isKeyboardInput = YES;
// The lowest bit of the first int is set if this key is a repeat.
int flags = *((int*)[data bytes]);
if (flags & 1)
isKeyRepeat = YES;
}
// Keyboard input is not removed from the queue; repeats are ignored if
// there already is keyboard input on the input queue.
if (isKeyRepeat || !isKeyboardInput) {
int i, count = [inputQueue count];
for (i = 1; i < count; i+=2) {
if ([[inputQueue objectAtIndex:i-1] intValue] == msgid) {
if (isKeyRepeat)
return;
[inputQueue removeObjectAtIndex:i];
[inputQueue removeObjectAtIndex:i-1];
break;
}
}
}
@@ -1539,18 +1562,21 @@ static NSString *MMSymlinkWarningString =
- (void)handleInputEvent:(int)msgid data:(NSData *)data
{
if (InsertTextMsgID == msgid) {
[self handleInsertText:data];
} else if (KeyDownMsgID == msgid || CmdKeyMsgID == msgid) {
if (InsertTextMsgID == msgid || KeyDownMsgID == msgid ||
CmdKeyMsgID == msgid) {
if (!data) return;
const void *bytes = [data bytes];
int mods = *((int*)bytes); bytes += sizeof(int);
int len = *((int*)bytes); bytes += sizeof(int);
NSString *key = [[NSString alloc] initWithBytes:bytes length:len
encoding:NSUTF8StringEncoding];
NSString *key = [[NSString alloc] initWithBytes:bytes
length:len
encoding:NSUTF8StringEncoding];
mods = eventModifierFlagsToVimModMask(mods);
[self handleKeyDown:key modifiers:mods];
if (InsertTextMsgID == msgid)
[self handleInsertText:key];
else
[self handleKeyDown:key modifiers:mods];
[key release];
} else if (ScrollWheelMsgID == msgid) {
@@ -1732,14 +1758,12 @@ static NSString *MMSymlinkWarningString =
return specialKeys;
}
- (void)handleInsertText:(NSData *)data
- (void)handleInsertText:(NSString *)text
{
if (!data) return;
if (!text) return;
NSString *key = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
char_u *str = (char_u*)[key UTF8String];
int i, len = [key lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
char_u *str = (char_u*)[text UTF8String];
int i, len = [text lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
#ifdef FEAT_MBYTE
char_u *conv_str = NULL;
@@ -1765,7 +1789,6 @@ static NSString *MMSymlinkWarningString =
if (conv_str)
vim_free(conv_str);
#endif
[key release];
}
- (void)handleKeyDown:(NSString *)key modifiers:(int)mods
+28 -6
View File
@@ -38,7 +38,8 @@ static float MMDragAreaSize = 73.0f;
- (MMWindowController *)windowController;
- (MMVimController *)vimController;
- (void)dispatchKeyEvent:(NSEvent *)event;
- (void)sendKeyDown:(const char *)chars length:(int)len modifiers:(int)flags;
- (void)sendKeyDown:(const char *)chars length:(int)len modifiers:(int)flags
isARepeat:(BOOL)isARepeat;
- (void)hideMouseCursor;
- (void)startDragTimerWithInterval:(NSTimeInterval)t;
- (void)dragTimerFired:(NSTimer *)timer;
@@ -157,8 +158,17 @@ static float MMDragAreaSize = 73.0f;
//NSLog(@"send InsertTextMsgID: %@", string);
[[self vimController] sendMessage:InsertTextMsgID
data:[string dataUsingEncoding:NSUTF8StringEncoding]];
NSMutableData *data = [NSMutableData data];
int len = [string lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
int flags = [event modifierFlags] & 0xffff0000U;
if ([event isARepeat])
flags |= 1;
[data appendBytes:&flags length:sizeof(int)];
[data appendBytes:&len length:sizeof(int)];
[data appendBytes:[string UTF8String] length:len];
[[self vimController] sendMessage:InsertTextMsgID data:data];
}
- (void)doCommandBySelector:(SEL)selector
@@ -193,7 +203,8 @@ static float MMDragAreaSize = 73.0f;
chars = MMKeypadEnter;
}
[self sendKeyDown:chars length:len modifiers:[event modifierFlags]];
[self sendKeyDown:chars length:len modifiers:[event modifierFlags]
isARepeat:[event isARepeat]];
} else {
[self dispatchKeyEvent:event];
}
@@ -214,7 +225,7 @@ static float MMDragAreaSize = 73.0f;
// stroke (some input methods use e.g. arrow keys). The function key down
// event will still reach Vim though (via keyDown:). The exceptions to
// this rule are: PageUp/PageDown (keycode 116/121).
int flags = [event modifierFlags];
int flags = [event modifierFlags] & 0xffff0000U;
if ([event type] != NSKeyDown || flags & NSFunctionKeyMask
&& !(116 == [event keyCode] || 121 == [event keyCode]))
return NO;
@@ -272,6 +283,9 @@ static float MMDragAreaSize = 73.0f;
len = [unmodchars lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
}
if ([event isARepeat])
flags |= 1;
[data appendBytes:&flags length:sizeof(int)];
[data appendBytes:&len length:sizeof(int)];
[data appendBytes:[unmodchars UTF8String] length:len];
@@ -748,14 +762,22 @@ static float MMDragAreaSize = 73.0f;
bytes = [chars UTF8String];
}
[self sendKeyDown:bytes length:len modifiers:mods];
[self sendKeyDown:bytes length:len modifiers:mods
isARepeat:[event isARepeat]];
}
- (void)sendKeyDown:(const char *)chars length:(int)len modifiers:(int)flags
isARepeat:(BOOL)isARepeat
{
if (chars && len > 0) {
NSMutableData *data = [NSMutableData data];
// The low 16 bits are not used for modifier flags by NSEvent. Use
// these bits for custom flags.
flags &= 0xffff0000;
if (isARepeat)
flags |= 1;
[data appendBytes:&flags length:sizeof(int)];
[data appendBytes:&len length:sizeof(int)];
[data appendBytes:chars length:len];