diff options
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/osx/salnsmenu.h | 6 | ||||
-rw-r--r-- | vcl/osx/salframeview.mm | 32 | ||||
-rw-r--r-- | vcl/osx/salmenu.cxx | 12 | ||||
-rw-r--r-- | vcl/osx/salnsmenu.mm | 84 |
4 files changed, 116 insertions, 18 deletions
diff --git a/vcl/inc/osx/salnsmenu.h b/vcl/inc/osx/salnsmenu.h index 9e0f9acf68ed..d6b065a7706e 100644 --- a/vcl/inc/osx/salnsmenu.h +++ b/vcl/inc/osx/salnsmenu.h @@ -44,15 +44,21 @@ class AquaSalMenuItem; @interface SalNSMenuItem : NSMenuItem <NSMenuItemValidation> { AquaSalMenuItem* mpMenuItem; + BOOL mbReallyEnabled; } - (id)initWithMenuItem:(AquaSalMenuItem*)pMenuItem; +- (BOOL)isReallyEnabled; - (void)menuItemTriggered:(id)aSender; - (BOOL)validateMenuItem:(NSMenuItem*)pMenuItem; +- (void)setReallyEnabled:(BOOL)bEnabled; @end @interface SalNSMainMenu : NSMenu { + NSEvent* mpLastPerformKeyEquivalentEvent; } +- (id)initWithTitle:(NSString*)pTitle; +- (void)dealloc; - (BOOL)performKeyEquivalent:(NSEvent*)pEvent; @end diff --git a/vcl/osx/salframeview.mm b/vcl/osx/salframeview.mm index eb8ed68add34..a8432aba31b9 100644 --- a/vcl/osx/salframeview.mm +++ b/vcl/osx/salframeview.mm @@ -1748,9 +1748,37 @@ static void updateWinDataInLiveResize(bool bInLiveResize) -(void)noop: (id)aSender { (void)aSender; - if( ! mbKeyHandled ) + if( ! mbKeyHandled && mpLastEvent ) { - if( ! [self sendSingleCharacter:mpLastEvent] ) + // Related tdf#162843: replace the event's string parameter + // When using the Dvorak - QWERTY keyboard and the Command key + // is pressed, any key events that match a disabled menu item + // are handled here. However, the Dvorak - QWERTY event's + // charactersIgnoringModifiers string can cause cutting and + // copying to fail in the Find toolbar and the Find and Replace + // dialog so replace the event's charactersIgnoringModifiers + // string with the event's character string. + NSEvent* pEvent = mpLastEvent; + NSEventModifierFlags nModMask = [mpLastEvent modifierFlags]; + if( nModMask & NSEventModifierFlagCommand ) + { + switch( [mpLastEvent type] ) + { + case NSEventTypeKeyDown: + case NSEventTypeKeyUp: + case NSEventTypeFlagsChanged: + { + NSString* pCharacters = [mpLastEvent characters]; + NSString* pCharactersIgnoringModifiers = ( nModMask & NSEventModifierFlagShift ) ? [pCharacters uppercaseString] : pCharacters; + pEvent = [NSEvent keyEventWithType: [pEvent type] location: [pEvent locationInWindow] modifierFlags: nModMask timestamp: [pEvent timestamp] windowNumber: [pEvent windowNumber] context: nil characters: pCharacters charactersIgnoringModifiers: pCharactersIgnoringModifiers isARepeat: [pEvent isARepeat] keyCode: [pEvent keyCode]]; + break; + } + default: + break; + } + } + + if( ! [self sendSingleCharacter:pEvent] ) { /* prevent recursion */ if( mpLastEvent != mpLastSuperEvent && [NSApp respondsToSelector: @selector(sendSuperEvent:)] ) diff --git a/vcl/osx/salmenu.cxx b/vcl/osx/salmenu.cxx index dcac168f7e53..0410da4e99fd 100644 --- a/vcl/osx/salmenu.cxx +++ b/vcl/osx/salmenu.cxx @@ -412,7 +412,10 @@ void AquaSalMenu::enableMainMenu( bool bEnable ) for( int n = 1; n < nItems; n++ ) { NSMenuItem* pItem = [pMainMenu itemAtIndex: n]; - [pItem setEnabled: bEnable ? YES : NO]; + if( [pItem isKindOfClass: [SalNSMenuItem class]]) + [static_cast<SalNSMenuItem*>(pItem) setReallyEnabled: bEnable]; + else + [pItem setEnabled: bEnable]; } } } @@ -581,7 +584,10 @@ void AquaSalMenu::EnableItem( unsigned nPos, bool bEnable ) if( nPos < maItems.size() ) { NSMenuItem* pItem = maItems[nPos]->mpMenuItem; - [pItem setEnabled: bEnable ? YES : NO]; + if( [pItem isKindOfClass: [SalNSMenuItem class]]) + [static_cast<SalNSMenuItem*>(pItem) setReallyEnabled: bEnable]; + else + [pItem setEnabled: bEnable]; } } @@ -874,7 +880,7 @@ AquaSalMenuItem::AquaSalMenuItem( const SalItemParams* pItemData ) : else { mpMenuItem = [[SalNSMenuItem alloc] initWithMenuItem: this]; - [mpMenuItem setEnabled: YES]; + [static_cast<SalNSMenuItem*>(mpMenuItem) setReallyEnabled: YES]; // peel mnemonics because on mac there are no such things for menu items // Delete CJK-style mnemonics for the dropdown menu of the 'New button' and lower menu of 'File > New' diff --git a/vcl/osx/salnsmenu.mm b/vcl/osx/salnsmenu.mm index 31a2ace83f07..383e0b574a54 100644 --- a/vcl/osx/salnsmenu.mm +++ b/vcl/osx/salnsmenu.mm @@ -142,8 +142,15 @@ action: @selector(menuItemTriggered:) keyEquivalent: [NSString string]]; [ret setTarget: self]; + mbReallyEnabled = [ret isEnabled]; return ret; } + +-(BOOL)isReallyEnabled +{ + return mbReallyEnabled; +} + -(void)menuItemTriggered: (id)aSender { (void)aSender; @@ -187,8 +194,8 @@ [pCharacters isEqualToString: @"a"] || [pCharacters isEqualToString: @"z"] ) ) { - NSEvent* pEvent = [NSApp currentEvent]; NSEvent* pKeyEvent = nil; + NSEvent* pEvent = [NSApp currentEvent]; if( pEvent ) { switch( [pEvent type] ) @@ -196,23 +203,29 @@ case NSEventTypeKeyDown: case NSEventTypeKeyUp: case NSEventTypeFlagsChanged: - pKeyEvent = pEvent; + // tdf#162843 replace the event's string parameters + // When using the Dvorak - QWERTY keyboard, the + // event's charactersIgnoringModifiers string causes + // pasting to fail so replace both the event's + // characters and charactersIgnoringModifiers strings + // with this menu item's key equivalent. + pKeyEvent = [NSEvent keyEventWithType: [pEvent type] location: [pEvent locationInWindow] modifierFlags: nModMask timestamp: [pEvent timestamp] windowNumber: [pEvent windowNumber] context: nil characters: pCharacters charactersIgnoringModifiers: pCharacters isARepeat: [pEvent isARepeat] keyCode: [pEvent keyCode]]; break; default: break; } + } - if( !pKeyEvent ) - { - // Native key events appear to set the location to the - // top left corner of the key window - NSPoint aPoint = NSMakePoint(0, [pKeyWin frame].size.height); - pKeyEvent = [NSEvent keyEventWithType: NSEventTypeKeyDown location: aPoint modifierFlags: nModMask timestamp: [[NSProcessInfo processInfo] systemUptime] windowNumber: [pKeyWin windowNumber] context: nil characters: pCharacters charactersIgnoringModifiers: pCharacters isARepeat: NO keyCode: 0]; - } - - [[pKeyWin contentView] keyDown: pKeyEvent]; - return; + if( !pKeyEvent ) + { + // Native key events appear to set the location to the + // top left corner of the key window + NSPoint aPoint = NSMakePoint(0, [pKeyWin frame].size.height); + pKeyEvent = [NSEvent keyEventWithType: NSEventTypeKeyDown location: aPoint modifierFlags: nModMask timestamp: [[NSProcessInfo processInfo] systemUptime] windowNumber: [pKeyWin windowNumber] context: nil characters: pCharacters charactersIgnoringModifiers: pCharacters isARepeat: NO keyCode: 0]; } + + [[pKeyWin contentView] keyDown: pKeyEvent]; + return; } } @@ -255,6 +268,12 @@ } } +-(void)setReallyEnabled: (BOOL)bEnabled +{ + mbReallyEnabled = bEnabled; + [self setEnabled: mbReallyEnabled]; +} + -(BOOL)validateMenuItem: (NSMenuItem *)pMenuItem { // Related: tdf#126638 disable all menu items when displaying modal windows @@ -265,7 +284,18 @@ if (!pMenuItem || [NSApp modalWindow]) return NO; - return [pMenuItem isEnabled]; + // Related: tdf#126638 return the last enabled state set by the LibreOffice code + // Apparently whatever is returned will be passed to + // -[NSMenuItem setEnabled:] which can cause the enabled state + // to be different than the enabled state that the LibreOffice + // code expoects. This results in menu items failing to be + // reenabled after being temporarily disabled such as when a + // native modal dialog is closed. So, return the last enabled + // state set by the LibreOffice code. + if ([pMenuItem isKindOfClass: [SalNSMenuItem class]]) + return [static_cast<SalNSMenuItem*>(pMenuItem) isReallyEnabled]; + else + return [pMenuItem isEnabled]; } @end @@ -359,8 +389,36 @@ SAL_WNODEPRECATED_DECLARATIONS_POP @implementation SalNSMainMenu +- (id)initWithTitle:(NSString*)pTitle +{ + mpLastPerformKeyEquivalentEvent = nil; + return [super initWithTitle:pTitle]; +} + +- (void)dealloc +{ + if (mpLastPerformKeyEquivalentEvent) + [mpLastPerformKeyEquivalentEvent release]; + + [super dealloc]; +} + - (BOOL)performKeyEquivalent:(NSEvent*)pEvent { + // Related: tdf#162843 prevent dispatch of the same event more than once + // When pressing Command-V with a Dvorak - QWERTY keyboard, + // that single event passes through this selector twice which + // causes content to be pasted twice in any text fields in the + // Find and Replace dialog. + if (pEvent == mpLastPerformKeyEquivalentEvent) + return false; + + if (mpLastPerformKeyEquivalentEvent) + [mpLastPerformKeyEquivalentEvent release]; + mpLastPerformKeyEquivalentEvent = pEvent; + if (mpLastPerformKeyEquivalentEvent) + [mpLastPerformKeyEquivalentEvent retain]; + bool bRet = [super performKeyEquivalent: pEvent]; // tdf#126638 dispatch key shortcut events to modal windows |