diff -Naur cotvnc/Source/EventFilter.h cotvncmod/Source/EventFilter.h --- cotvnc/Source/EventFilter.h 2005-07-12 22:54:53.000000000 +0200 +++ cotvncmod/Source/EventFilter.h 2008-01-05 15:22:46.000000000 +0100 @@ -153,6 +153,9 @@ - (void)keyUp: (NSEvent *)theEvent; - (void)flagsChanged:(NSEvent *)theEvent; +// Misc? +- (void)setModifierFlags:(unsigned int)modifierFlags timestamp: (NSTimeInterval)timestamp; + // Synthesized Events - (void)clearAllEmulationStates; - (void)queueMouseDownEventFromEvent: (NSEvent *)theEvent buttonNumber: (unsigned int)button; diff -Naur cotvnc/Source/EventFilter.m cotvncmod/Source/EventFilter.m --- cotvnc/Source/EventFilter.m 2006-01-18 20:20:38.000000000 +0100 +++ cotvncmod/Source/EventFilter.m 2008-01-05 16:31:03.000000000 +0100 @@ -12,7 +12,7 @@ #import "QueuedEvent.h" #import "RFBConnection.h" #import "RFBView.h" - +#include static inline unsigned int ButtonNumberToArrayIndex( unsigned int buttonNumber ) @@ -303,12 +303,11 @@ } } -- (void)flagsChanged:(NSEvent *)theEvent +- (void)setModifierFlags:(unsigned int)modifierFlags timestamp: (NSTimeInterval)timestamp; { - unsigned int newState = [theEvent modifierFlags]; + unsigned int newState = modifierFlags; newState = ~(~newState | 0xFFFF); unsigned int changedState = newState ^ _queuedModifiers; - NSTimeInterval timestamp = [theEvent timestamp]; _queuedModifiers = newState; if ( NSShiftKeyMask & changedState ) @@ -363,6 +362,12 @@ } +- (void)flagsChanged:(NSEvent *)theEvent +{ + [self setModifierFlags: [theEvent modifierFlags] timestamp: [theEvent timestamp]]; +} + + #pragma mark - #pragma mark Synthesized Events @@ -453,33 +458,42 @@ - (void)pasteString: (NSString *)string { [self _updateCapsLockStateIfNecessary]; - int index, strLength = [string length]; + int index, index2, strLength = [string length]; NSTimeInterval now = [[NSDate date] timeIntervalSince1970]; [self clearAllEmulationStates]; - BOOL capsLockWasPressed = (_pressedModifiers & NSAlphaShiftKeyMask) ? YES : NO; - + unsigned int queuedModifiersSave = _queuedModifiers; + [self setModifierFlags: 0 timestamp: now]; + for ( index = 0; index < strLength; ++index ) { unichar character = [string characterAtIndex: index]; // hack - lets' be polite to the server - if ( '\n' == character ) - character = '\r'; +// if ( '\n' == character ) +// character = '\r'; + unsigned int numRepeat = 1; +// if ( '\t' == character ) +// { +// numRepeat = 4; +// character = ' '; +// } - QueuedEvent *event = [QueuedEvent keyDownEventWithCharacter: character - characterIgnoringModifiers: character - timestamp: now]; - [_pendingEvents addObject: event]; - event = [QueuedEvent keyUpEventWithCharacter: character - characterIgnoringModifiers: character - timestamp: now]; - [_pendingEvents addObject: event]; + for (index2 = 0; index2 < numRepeat; ++index2) + { + QueuedEvent *event = [QueuedEvent keyDownEventWithCharacter: character + characterIgnoringModifiers: character + timestamp: now]; + [_pendingEvents addObject: event]; + event = [QueuedEvent keyUpEventWithCharacter: character + characterIgnoringModifiers: character + timestamp: now]; + [_pendingEvents addObject: event]; + } } - [self sendAllPendingQueueEntriesNow]; - if ( capsLockWasPressed ) - _pressedModifiers |= NSAlphaShiftKeyMask; + [self setModifierFlags: queuedModifiersSave timestamp: now]; + [self sendAnyValidEventsToServerNow]; } @@ -588,16 +602,38 @@ // I'll maintain state of the unmodified character because, for example, if you set // caps lock and then keyrepeat something and unset caps lock while you're doing it, // the key up character will be for the lowercase letter. - if ( NSAlphaShiftKeyMask & _pressedModifiers ) - character = toupper(characterIgnoringModifiers); - else - character = characterIgnoringModifiers; +// if ( NSAlphaShiftKeyMask & _pressedModifiers ) +// character = toupper(characterIgnoringModifiers); +// else +// character = characterIgnoringModifiers; sendKey = character; + if ( kQueuedKeyDownEvent == [event type] ) { - [_pressedKeys addObject: encodedChar]; - [_connection sendKey: sendKey pressed: YES]; +// printf("character %c, characterIgnoringModifiers %c\n", character, characterIgnoringModifiers); + if (character != characterIgnoringModifiers && (_pressedModifiers & NSAlternateKeyMask | _pressedModifiers & NSControlKeyMask | _pressedModifiers & NSCommandKeyMask)) + { + if (_pressedModifiers & NSAlternateKeyMask) + [_connection sendModifier: NSAlternateKeyMask pressed: NO]; + if (_pressedModifiers & NSControlKeyMask) + [_connection sendModifier: NSControlKeyMask pressed: NO]; + if (_pressedModifiers & NSCommandKeyMask) + [_connection sendModifier: NSCommandKeyMask pressed: NO]; + [_connection sendKey: sendKey pressed: YES]; + [_connection sendKey: sendKey pressed: NO]; + if (_pressedModifiers & NSAlternateKeyMask) + [_connection sendModifier: NSAlternateKeyMask pressed: YES]; + if (_pressedModifiers & NSControlKeyMask) + [_connection sendModifier: NSControlKeyMask pressed: YES]; + if (_pressedModifiers & NSCommandKeyMask) + [_connection sendModifier: NSCommandKeyMask pressed: YES]; + } + else + { + [_pressedKeys addObject: encodedChar]; + [_connection sendKey: sendKey pressed: YES]; + } } else if ( [_pressedKeys containsObject: encodedChar] ) { @@ -645,9 +681,27 @@ NSEnumerator *eventEnumerator = [_pendingEvents objectEnumerator]; QueuedEvent *event; - while ( event = [eventEnumerator nextObject] ) - [self _sendEvent: event]; // this sets stuff like _pressedKeyes, _pressedButtons, etc. - [self discardAllPendingQueueEntries]; + size_t nObjects = [_pendingEvents count]; + + if (nObjects > 2) + { + // Ratelimit so keypresses can be sorted by time + unsigned int SendRate = 500; // Max key presses per second. Some timer somewhere probably reorders keypresses at millisecond time resolution. + unsigned int SleepTime = 1000000 / SendRate; + + while ( event = [eventEnumerator nextObject] ) + { + [self _sendEvent: event]; // this sets stuff like _pressedKeyes, _pressedButtons, etc. + usleep(SleepTime); + } + [self discardAllPendingQueueEntries]; + } + else + { + while ( event = [eventEnumerator nextObject] ) + [self _sendEvent: event]; // this sets stuff like _pressedKeyes, _pressedButtons, etc. + [self discardAllPendingQueueEntries]; + } } diff -Naur cotvnc/Source/RFBConnection.m cotvncmod/Source/RFBConnection.m --- cotvnc/Source/RFBConnection.m 2005-08-14 20:11:44.000000000 +0200 +++ cotvncmod/Source/RFBConnection.m 2008-01-05 16:08:36.000000000 +0100 @@ -626,7 +626,8 @@ - (void)sendModifier:(unsigned int)m pressed: (BOOL)pressed { -/* NSString *modifierStr =nil; + /* + NSString *modifierStr =nil; switch (m) { case NSShiftKeyMask: @@ -640,8 +641,8 @@ case NSAlphaShiftKeyMask: modifierStr = @"NSAlphaShiftKeyMask"; break; } - NSLog(@"modifier %@ %s", modifierStr, pressed ? "pressed" : "released"); */ - + NSLog(@"modifier %@ %s", modifierStr, pressed ? "pressed" : "released"); +*/ rfbKeyEventMsg msg; memset(&msg, 0, sizeof(msg)); @@ -683,9 +684,11 @@ kc = c; } -/* unichar _kc = (unichar)kc; + /* + unichar _kc = (unichar)kc; NSString *keyStr = [NSString stringWithCharacters: &_kc length: 1]; - NSLog(@"key '%@' %s", keyStr, pressed ? "pressed" : "released"); */ + NSLog(@"c %d key '%@' %s", c, keyStr, pressed ? "pressed" : "released"); + */ msg.key = htonl(kc); [self writeBytes:(unsigned char*)&msg length:sizeof(msg)];