mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-07 15:37:14 +02:00
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:
+53
-30
@@ -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
|
||||
|
||||
@@ -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];
|
||||
|
||||
Reference in New Issue
Block a user