summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vcl/inc/osx/salnsmenu.h14
-rw-r--r--vcl/osx/salmenu.cxx14
-rw-r--r--vcl/osx/salnsmenu.mm84
-rw-r--r--vcl/osx/vclnsapp.mm49
4 files changed, 121 insertions, 40 deletions
diff --git a/vcl/inc/osx/salnsmenu.h b/vcl/inc/osx/salnsmenu.h
index 696abca2fc0b..64b65e2c95bd 100644
--- a/vcl/inc/osx/salnsmenu.h
+++ b/vcl/inc/osx/salnsmenu.h
@@ -35,17 +35,29 @@ class AquaSalMenuItem;
{
AquaSalMenu* mpMenu;
}
++ (BOOL)dispatchSpecialKeyEquivalents:(NSEvent*)pEvent;
- (id)initWithMenu:(AquaSalMenu*)pMenu;
- (void)menuNeedsUpdate:(NSMenu*)pMenu;
- (void)setSalMenu:(AquaSalMenu*)pMenu;
@end
-@interface SalNSMenuItem : NSMenuItem
+@interface SalNSMenuItem : NSMenuItem <NSMenuItemValidation>
{
AquaSalMenuItem* mpMenuItem;
}
- (id)initWithMenuItem:(AquaSalMenuItem*)pMenuItem;
- (void)menuItemTriggered:(id)aSender;
+- (BOOL)validateMenuItem:(NSMenuItem*)pMenuItem;
+@end
+
+@interface SalNSMainMenuDelegate : NSObject
+{
+}
+- (id)init;
+- (BOOL)menuHasKeyEquivalent:(NSMenu*)pMenu
+ forEvent:(NSEvent*)pEvent
+ target:(id*)pTarget
+ action:(SEL*)pAction;
@end
#endif // INCLUDED_VCL_INC_OSX_SALNSMENU_H
diff --git a/vcl/osx/salmenu.cxx b/vcl/osx/salmenu.cxx
index b3d02587f46b..7685a1b9e1bc 100644
--- a/vcl/osx/salmenu.cxx
+++ b/vcl/osx/salmenu.cxx
@@ -113,6 +113,7 @@ const AquaSalMenu* AquaSalMenu::pCurrentMenuBar = nullptr;
// FIXME: currently this is leaked
static MainMenuSelector* pMainMenuSelector = nil;
+static SalNSMainMenuDelegate* pMainMenuDelegate = nil;
static void initAppMenu()
{
@@ -134,6 +135,10 @@ static void initAppMenu()
[NSApp setMainMenu: pMainMenu];
pMainMenuSelector = [[MainMenuSelector alloc] init];
+ pMainMenuDelegate = [[SalNSMainMenuDelegate alloc] init];
+
+ // tdf#126638 set a special delegate for the main menu
+ [pMainMenu setDelegate: reinterpret_cast< id<NSMenuDelegate> >(pMainMenuDelegate)];
// about
NSString* pString = CreateNSString(VclResId(SV_STDTEXT_ABOUT));
@@ -230,12 +235,19 @@ AquaSalMenu::AquaSalMenu( bool bMenuBar ) :
{
mpMenu = [[SalNSMenu alloc] initWithMenu: this];
[mpMenu setDelegate: reinterpret_cast< id<NSMenuDelegate> >(mpMenu)];
+
+ // Related: tdf#126638 enable the menu's "autoenabledItems" property
+ // Enable the menu's "autoenabledItems" property so that
+ // -[SalNSMenuItem validateMenuItem:] will be called before handling
+ // a key shortcut and the menu item can be temporarily disabled if a
+ // modal window is displayed.
+ [mpMenu setAutoenablesItems: YES];
}
else
{
mpMenu = [NSApp mainMenu];
+ [mpMenu setAutoenablesItems: NO];
}
- [mpMenu setAutoenablesItems: NO];
}
AquaSalMenu::~AquaSalMenu()
diff --git a/vcl/osx/salnsmenu.mm b/vcl/osx/salnsmenu.mm
index b2df2da7e5f5..0659e412db1a 100644
--- a/vcl/osx/salnsmenu.mm
+++ b/vcl/osx/salnsmenu.mm
@@ -30,6 +30,53 @@
#include <osx/salnsmenu.h>
@implementation SalNSMenu
+
++(BOOL)dispatchSpecialKeyEquivalents: (NSEvent*)pEvent
+{
+ if( pEvent && [pEvent type] == NSEventTypeKeyDown )
+ {
+ unsigned int nModMask = ([pEvent modifierFlags] & (NSEventModifierFlagShift|NSEventModifierFlagControl|NSEventModifierFlagOption|NSEventModifierFlagCommand));
+ if( nModMask == NSEventModifierFlagCommand )
+ {
+ if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"v"] )
+ {
+ if( [NSApp sendAction: @selector(paste:) to: nil from: nil] )
+ return YES;
+ }
+ else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"c"] )
+ {
+ if( [NSApp sendAction: @selector(copy:) to: nil from: nil] )
+ return YES;
+ }
+ else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"x"] )
+ {
+ if( [NSApp sendAction: @selector(cut:) to: nil from: nil] )
+ return YES;
+ }
+ else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"a"] )
+ {
+ if( [NSApp sendAction: @selector(selectAll:) to: nil from: nil] )
+ return YES;
+ }
+ else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"z"] )
+ {
+ if( [NSApp sendAction: @selector(undo:) to: nil from: nil] )
+ return YES;
+ }
+ }
+ else if( nModMask == (NSEventModifierFlagCommand|NSEventModifierFlagShift) )
+ {
+ if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"Z"] )
+ {
+ if( [NSApp sendAction: @selector(redo:) to: nil from: nil] )
+ return YES;
+ }
+ }
+ }
+
+ return NO;
+}
+
-(id)initWithMenu: (AquaSalMenu*)pMenu
{
mpMenu = pMenu;
@@ -167,6 +214,19 @@
OSL_FAIL( "menubar item without frame !" );
}
}
+
+-(BOOL)validateMenuItem: (NSMenuItem *)pMenuItem
+{
+ // Related: tdf#126638 disable all menu items when displaying modal windows
+ // For some unknown reason, key shortcuts are dispatched to the LibreOffice
+ // menu items instead of the modal window so disable all LibreOffice menu
+ // items while a native modal dialog such as the native Open, Save, or
+ // Print dialog is displayed.
+ if (!pMenuItem || [NSApp modalWindow])
+ return NO;
+
+ return [pMenuItem isEnabled];
+}
@end
@implementation OOStatusItemView
@@ -257,5 +317,29 @@ SAL_WNODEPRECATED_DECLARATIONS_POP
}
@end
+@implementation SalNSMainMenuDelegate
+
+-(id)init
+{
+ return [super init];
+}
+
+-(BOOL)menuHasKeyEquivalent: (NSMenu*)pMenu forEvent: (NSEvent*)pEvent target: (id*)pTarget action: (SEL*)pAction
+{
+ assert( pMenu == [NSApp mainMenu] );
+
+ // tdf#126638 dispatch key shortcut events to modal windows
+ // Some modal windows, such as the native Open and Save dialogs,
+ // ignore any key shortcut events so use the same existing special
+ // dispatching code that -[VCL_NSApplication sendEvent:] uses to
+ // dispatch key shortcuts to non-modal, non-LibreOffice windows.
+ if( [NSApp modalWindow] )
+ [SalNSMenu dispatchSpecialKeyEquivalents: pEvent];
+
+ // Always return NO since the target and action are not set
+ return NO;
+}
+
+@end
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/osx/vclnsapp.mm b/vcl/osx/vclnsapp.mm
index 5daf923ce105..cd60cb0b0cec 100644
--- a/vcl/osx/vclnsapp.mm
+++ b/vcl/osx/vclnsapp.mm
@@ -34,6 +34,7 @@
#include <osx/salframe.h>
#include <osx/salframeview.h>
#include <osx/salinst.h>
+#include <osx/salnsmenu.h>
#include <osx/vclnsapp.h>
#include <quartz/utils.h>
@@ -170,44 +171,8 @@
// precondition: this ONLY works because CMD-V (paste), CMD-C (copy) and CMD-X (cut) are
// NOT localized, that is the same in all locales. Should this be
// different in any locale, this hack will fail.
- unsigned int nModMask = ([pEvent modifierFlags] & (NSEventModifierFlagShift|NSEventModifierFlagControl|NSEventModifierFlagOption|NSEventModifierFlagCommand));
- if( nModMask == NSEventModifierFlagCommand )
- {
-
- if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"v"] )
- {
- if( [NSApp sendAction: @selector(paste:) to: nil from: nil] )
- return;
- }
- else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"c"] )
- {
- if( [NSApp sendAction: @selector(copy:) to: nil from: nil] )
- return;
- }
- else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"x"] )
- {
- if( [NSApp sendAction: @selector(cut:) to: nil from: nil] )
- return;
- }
- else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"a"] )
- {
- if( [NSApp sendAction: @selector(selectAll:) to: nil from: nil] )
- return;
- }
- else if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"z"] )
- {
- if( [NSApp sendAction: @selector(undo:) to: nil from: nil] )
- return;
- }
- }
- else if( nModMask == (NSEventModifierFlagCommand|NSEventModifierFlagShift) )
- {
- if( [[pEvent charactersIgnoringModifiers] isEqualToString: @"Z"] )
- {
- if( [NSApp sendAction: @selector(redo:) to: nil from: nil] )
- return;
- }
- }
+ if( [SalNSMenu dispatchSpecialKeyEquivalents:pEvent] )
+ return;
}
}
[super sendEvent: pEvent];
@@ -315,6 +280,14 @@
-(NSApplicationTerminateReply)applicationShouldTerminate: (NSApplication *) app
{
(void)app;
+
+ // Related: tdf#126638 disable all menu items when displaying modal windows
+ // Although -[SalNSMenuItem validateMenuItem:] disables almost all menu
+ // items when a modal window is displayed, the standard Quit menu item
+ // does not get disabled so disable it here.
+ if ([NSApp modalWindow])
+ return NSTerminateCancel;
+
NSApplicationTerminateReply aReply = NSTerminateNow;
{
SolarMutexGuard aGuard;