From c5394cea63ef184f59da26ae4feb4f55c9d9bf01 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Sat, 25 Jul 2020 19:19:57 +0200 Subject: [PATCH 1/8] Fix handling of standard edit commands in context menu under Mac Feed back standard commands like copy, paste into wxMenItem if possible. This way commands that don't exist in the global menubar can still be fed back eg when originating from a context menu. See #18738. --- src/osx/cocoa/nonownedwnd.mm | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/osx/cocoa/nonownedwnd.mm b/src/osx/cocoa/nonownedwnd.mm index d9702e6682..35c86fcf3b 100644 --- a/src/osx/cocoa/nonownedwnd.mm +++ b/src/osx/cocoa/nonownedwnd.mm @@ -335,8 +335,20 @@ extern int wxOSXGetIdFromSelector(SEL action ); return self; } -- (BOOL) triggerMenu:(SEL) action +- (BOOL) triggerMenu:(SEL) action sender:(id)sender { + // feed back into menu item, if it is ours + if ( [sender isKindOfClass:wxNSMenuItem.class] ) + { + wxNSMenuItem* nsMenuItem = (wxNSMenuItem*) sender; + wxMenuItemImpl* impl = [nsMenuItem implementation]; + if ( impl ) + { + wxMenuItem* menuitem = impl->GetWXPeer(); + return menuitem->GetMenu()->HandleCommandProcess(menuitem); + } + } + // otherwise feed back command into common menubar wxMenuBar* mbar = wxMenuBar::MacGetInstalledMenuBar(); if ( mbar ) { @@ -369,43 +381,43 @@ extern int wxOSXGetIdFromSelector(SEL action ); - (void)undo:(id)sender { wxUnusedVar(sender); - [self triggerMenu:_cmd]; + [self triggerMenu:_cmd sender:sender]; } - (void)redo:(id)sender { wxUnusedVar(sender); - [self triggerMenu:_cmd]; + [self triggerMenu:_cmd sender:sender]; } - (void)cut:(id)sender { wxUnusedVar(sender); - [self triggerMenu:_cmd]; + [self triggerMenu:_cmd sender:sender]; } - (void)copy:(id)sender { wxUnusedVar(sender); - [self triggerMenu:_cmd]; + [self triggerMenu:_cmd sender:sender]; } - (void)paste:(id)sender { wxUnusedVar(sender); - [self triggerMenu:_cmd]; + [self triggerMenu:_cmd sender:sender]; } - (void)delete:(id)sender { wxUnusedVar(sender); - [self triggerMenu:_cmd]; + [self triggerMenu:_cmd sender:sender]; } - (void)selectAll:(id)sender { wxUnusedVar(sender); - [self triggerMenu:_cmd]; + [self triggerMenu:_cmd sender:sender]; } - (void)windowDidMiniaturize:(NSNotification *)notification From 8e26b8d54e7444b44d0b849f5127e3b982285a7c Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Sun, 24 Jan 2021 19:09:31 +0100 Subject: [PATCH 2/8] Fix wxSYS_COLOUR_BTNFACE value under macOS < 10.14 Use fallback value which isn't just RGB(0,0,0) when building under 10.15 but running under 10.13. Closes #18977. --- src/osx/cocoa/settings.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osx/cocoa/settings.mm b/src/osx/cocoa/settings.mm index de5f52860c..dd691a39bc 100644 --- a/src/osx/cocoa/settings.mm +++ b/src/osx/cocoa/settings.mm @@ -116,7 +116,7 @@ wxColour wxSystemSettingsNative::GetColour(wxSystemColour index) if ( WX_IS_MACOS_AVAILABLE(10, 14 ) ) sysColor = [NSColor windowBackgroundColor]; else - sysColor = [NSColor controlColor]; + return wxColour(wxMacCreateCGColorFromHITheme(3 /* kThemeBrushDialogBackgroundActive */)); break; case wxSYS_COLOUR_LISTBOX: sysColor = [NSColor controlBackgroundColor]; From 5f30f79bc88bc8b2aa8f8aa7988e64a49c51a825 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 24 Jan 2021 20:53:30 +0100 Subject: [PATCH 3/8] Remove unnecessary checks of wxEvent::GetSkipped() HandleWindowEvent() already returns false if the event handler skipped the event, there is no need to test for it explicitly. No real changes. --- src/osx/cocoa/window.mm | 2 +- src/osx/window_osx.cpp | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 338588c07b..7ffe20a338 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -3712,7 +3712,7 @@ bool wxWidgetCocoaImpl::DoHandleKeyNavigation(const wxKeyEvent &event) /* CTRL-TAB changes the (parent) window, i.e. switch notebook page */ new_event.SetWindowChange( event.ControlDown() ); new_event.SetCurrentFocus( focus ); - handled = iter->HandleWindowEvent( new_event ) && !new_event.GetSkipped(); + handled = iter->HandleWindowEvent( new_event ); } iter = iter->GetParent() ; diff --git a/src/osx/window_osx.cpp b/src/osx/window_osx.cpp index 6ab7dc8152..1b429d8f05 100644 --- a/src/osx/window_osx.cpp +++ b/src/osx/window_osx.cpp @@ -2605,11 +2605,7 @@ bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event ) #endif // wxUSE_ACCEL if ( !handled ) - { handled = HandleWindowEvent( event ) ; - if ( handled && event.GetSkipped() ) - handled = false ; - } return handled ; } From f8d4bba9e7d8e60e396dac2276d6c88ed3db117f Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 24 Jan 2021 20:57:20 +0100 Subject: [PATCH 4/8] Fix handling of accelerators in wxOSX Check accelerator tables when handling wxEVT_CHAR_HOOK, not wxEVT_KEY_DOWN, as we don't get the latter at all for some events, e.g. Cmd-Alt-1 doesn't generate wxEVT_KEY_DOWN (which looks like another bug) but does generate wxEVT_CHAR_HOOK. Closes #13937. --- src/osx/window_osx.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osx/window_osx.cpp b/src/osx/window_osx.cpp index 1b429d8f05..b3609f8026 100644 --- a/src/osx/window_osx.cpp +++ b/src/osx/window_osx.cpp @@ -2573,7 +2573,7 @@ bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event ) // moved the ordinary key event sending AFTER the accel evaluation #if wxUSE_ACCEL - if (event.GetEventType() == wxEVT_KEY_DOWN) + if (event.GetEventType() == wxEVT_CHAR_HOOK) { wxWindow *ancestor = this; while (ancestor) From c714e75555cae40ff5014b6fa61f18483c19bac3 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 24 Jan 2021 21:01:09 +0100 Subject: [PATCH 5/8] Generate wxEVT_CHAR_HOOK events before accelerators This is more consistent with the other ports and allows to use wxEVT_CHAR_HOOK handler to preempt processing of the accelerators (but notice that under macOS this only works for accelerators that are part of wxAcceleratorTable and not those associated with the menu items, as the latter ones are not handled by this code at all). Also simplify the code structure a little by getting rid of an unnecessary and more confusing than helpful "handled" variable. --- src/osx/window_osx.cpp | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/osx/window_osx.cpp b/src/osx/window_osx.cpp index b3609f8026..ef60bef9da 100644 --- a/src/osx/window_osx.cpp +++ b/src/osx/window_osx.cpp @@ -2568,9 +2568,8 @@ bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event ) : "unknown", wxDumpWindow(this)); - bool handled = false; - - // moved the ordinary key event sending AFTER the accel evaluation + if ( HandleWindowEvent(event) ) + return true; #if wxUSE_ACCEL if (event.GetEventType() == wxEVT_CHAR_HOOK) @@ -2584,16 +2583,16 @@ bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event ) wxEvtHandler * const handler = ancestor->GetEventHandler(); wxCommandEvent command_event( wxEVT_MENU, command ); - handled = handler->ProcessEvent( command_event ); - - if ( !handled ) + if ( !handler->ProcessEvent( command_event ) ) { // accelerators can also be used with buttons, try them too command_event.SetEventType(wxEVT_BUTTON); - handled = handler->ProcessEvent( command_event ); + handler->ProcessEvent( command_event ); } - break; + // In any case, the event was handled as it triggered an + // accelerator. + return true; } if (ancestor->IsTopNavigationDomain(wxWindow::Navigation_Accel)) @@ -2604,10 +2603,7 @@ bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event ) } #endif // wxUSE_ACCEL - if ( !handled ) - handled = HandleWindowEvent( event ) ; - - return handled ; + return false; } /* static */ From b2675d6a60a398d8681d0bc47655a2d9c2411239 Mon Sep 17 00:00:00 2001 From: Andreas Falkenhahn Date: Sun, 24 Jan 2021 21:16:23 +0100 Subject: [PATCH 6/8] Fix sending event when cancelling editing in wxDVC under Mac Move existing code for sending wxEVT_DATAVIEW_ITEM_EDITING_DONE to a new sendEditingDoneEvent:isCancelled function and also call it, with true argument, from cancelOperation: to generate the expected event. Closes #17835. --- src/osx/cocoa/dataview.mm | 81 +++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 29 deletions(-) diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm index 6935f463ed..f11717f000 100644 --- a/src/osx/cocoa/dataview.mm +++ b/src/osx/cocoa/dataview.mm @@ -1937,6 +1937,57 @@ outlineView:(NSOutlineView*)outlineView dvc->GetEventHandler()->ProcessEvent(event); } +-(void) sendEditingDoneEvent:(BOOL)isCancelled +{ + // under OSX an event indicating the end of an editing session can be sent + // even if no event indicating a start of an editing session has been sent + // (see Documentation for NSControl controlTextDidEndEditing:); this is + // not expected by a user of the wxWidgets library and therefore an + // wxEVT_DATAVIEW_ITEM_EDITING_DONE event is only sent if a + // corresponding wxEVT_DATAVIEW_ITEM_EDITING_STARTED has been sent + // before; to check if a wxEVT_DATAVIEW_ITEM_EDITING_STARTED has + // been sent the last edited column/row are valid: + if ( currentlyEditedColumn != -1 && currentlyEditedRow != -1 ) + { + NSTableColumn* + tableColumn = [[self tableColumns] objectAtIndex:currentlyEditedColumn]; + wxDataViewColumn* const + col([static_cast(tableColumn) getColumnPointer]); + + wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl(); + + const wxDataViewItem + item = wxDataViewItemFromItem([self itemAtRow:currentlyEditedRow]); + + // send event to wxWidgets: + wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_EDITING_DONE, dvc, col, item); + if ( isCancelled ) + event.SetEditCancelled(); + + dvc->GetEventHandler()->ProcessEvent(event); + + // we're not editing any more + currentlyEditedColumn = + currentlyEditedRow = -1; + } +} + +-(void) editColumn:(NSInteger)column row:(NSInteger)row withEvent:(NSEvent*)event select:(BOOL)select +{ + [super editColumn:column row:row withEvent:event select:select]; + + currentlyEditedColumn = column; + currentlyEditedRow = row; +} + +-(void) cancelOperation:(id)sender +{ + [self abortEditing]; + [[self window] makeFirstResponder:self]; + + [self sendEditingDoneEvent:YES]; +} + -(BOOL) textShouldBeginEditing:(NSText*)textEditor { wxUnusedVar(textEditor); @@ -2007,35 +2058,7 @@ outlineView:(NSOutlineView*)outlineView // have the checks for IsDeleting() in several other methods of this class. [super textDidEndEditing:notification]; - // under OSX an event indicating the end of an editing session can be sent - // even if no event indicating a start of an editing session has been sent - // (see Documentation for NSControl controlTextDidEndEditing:); this is - // not expected by a user of the wxWidgets library and therefore an - // wxEVT_DATAVIEW_ITEM_EDITING_DONE event is only sent if a - // corresponding wxEVT_DATAVIEW_ITEM_EDITING_STARTED has been sent - // before; to check if a wxEVT_DATAVIEW_ITEM_EDITING_STARTED has - // been sent the last edited column/row are valid: - if ( currentlyEditedColumn != -1 && currentlyEditedRow != -1 ) - { - NSTableColumn* - tableColumn = [[self tableColumns] objectAtIndex:currentlyEditedColumn]; - wxDataViewColumn* const - col([static_cast(tableColumn) getColumnPointer]); - - wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl(); - - const wxDataViewItem - item = wxDataViewItemFromItem([self itemAtRow:currentlyEditedRow]); - - // send event to wxWidgets: - wxDataViewEvent event(wxEVT_DATAVIEW_ITEM_EDITING_DONE, dvc, col, item); - dvc->GetEventHandler()->ProcessEvent(event); - - - // we're not editing any more - currentlyEditedColumn = - currentlyEditedRow = -1; - } + [self sendEditingDoneEvent:NO]; } -(BOOL) becomeFirstResponder From 678b641950cbf1ad35da1edbdd351bc6ef979f68 Mon Sep 17 00:00:00 2001 From: Julian Smart Date: Sun, 24 Jan 2021 23:45:24 +0100 Subject: [PATCH 7/8] Fix initial focus problem for hidden windows under Mac Assume that hidden windows do accept focus because, even if this is still wrong, in general, it is less harmful than wrongly returning false from CanFocus() for them. Closes #18987. --- src/osx/cocoa/window.mm | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index 7ffe20a338..3336fa0fca 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -3094,12 +3094,11 @@ bool wxWidgetCocoaImpl::CanFocus() const { if ( !IsVisible() ) { - // It's useless to call canBecomeKeyView in this case, it will always - // return false. Try to return something reasonable ourselves, knowing - // that most controls are not focusable when full keyboard access if - // off and wxNSTextViewControl overrides CanFocus() to always return - // true anyhow. - return [NSApp isFullKeyboardAccessEnabled]; + // canBecomeKeyView always returns false for hidden windows, but this + // could be wrong because the window could still accept focus once it + // becomes visible, so we have no choice but to return true here to + // avoid situations in which the expected window doesn't get the focus. + return true; } NSView* targetView = m_osxView; From 78e7a966cc8597f86a9db54038d2ef8320cd28ce Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 27 Jan 2021 17:53:42 +0100 Subject: [PATCH 8/8] Revert "Fix wxSYS_COLOUR_BTNFACE value under macOS < 10.14" This reverts commit 8e26b8d54e7444b44d0b849f5127e3b982285a7c because it has been superseded by 17239d5c3d (macOS add fallback for retrieving color channels from dynamic system colors on pre 10.14 systems, 2021-01-26) in master. See #18977. --- src/osx/cocoa/settings.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/osx/cocoa/settings.mm b/src/osx/cocoa/settings.mm index dd691a39bc..de5f52860c 100644 --- a/src/osx/cocoa/settings.mm +++ b/src/osx/cocoa/settings.mm @@ -116,7 +116,7 @@ wxColour wxSystemSettingsNative::GetColour(wxSystemColour index) if ( WX_IS_MACOS_AVAILABLE(10, 14 ) ) sysColor = [NSColor windowBackgroundColor]; else - return wxColour(wxMacCreateCGColorFromHITheme(3 /* kThemeBrushDialogBackgroundActive */)); + sysColor = [NSColor controlColor]; break; case wxSYS_COLOUR_LISTBOX: sysColor = [NSColor controlBackgroundColor];