From 18c45321f4550d1dfbc88d7134684a93f74f7a67 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Tue, 13 Apr 2021 17:34:34 +0200 Subject: [PATCH 1/4] Return bool from wxWidgetCocoaImpl::doCommandBySelector() This allows to determine whether the event was handled by wx code and perform further processing by feeding things back to native code if not. --- include/wx/osx/cocoa/private.h | 3 ++- src/osx/cocoa/window.mm | 14 +++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/include/wx/osx/cocoa/private.h b/include/wx/osx/cocoa/private.h index eafd4ab3a3..bf2c243a4a 100644 --- a/include/wx/osx/cocoa/private.h +++ b/include/wx/osx/cocoa/private.h @@ -199,7 +199,8 @@ public : virtual void cursorUpdate(WX_NSEvent event, WXWidget slf, void* _cmd); virtual void keyEvent(WX_NSEvent event, WXWidget slf, void* _cmd); virtual void insertText(NSString* text, WXWidget slf, void* _cmd); - virtual void doCommandBySelector(void* sel, WXWidget slf, void* _cmd); + // Returns true if the event was processed by a user-defined event handler. + virtual bool doCommandBySelector(void* sel, WXWidget slf, void* _cmd); virtual bool acceptsFirstResponder(WXWidget slf, void* _cmd); virtual bool becomeFirstResponder(WXWidget slf, void* _cmd); virtual bool resignFirstResponder(WXWidget slf, void* _cmd); diff --git a/src/osx/cocoa/window.mm b/src/osx/cocoa/window.mm index b322e582c5..d5bfe85661 100644 --- a/src/osx/cocoa/window.mm +++ b/src/osx/cocoa/window.mm @@ -2129,7 +2129,7 @@ void wxWidgetCocoaImpl::insertText(NSString* text, WXWidget slf, void *_cmd) } } -void wxWidgetCocoaImpl::doCommandBySelector(void* sel, WXWidget slf, void* WXUNUSED(_cmd)) +bool wxWidgetCocoaImpl::doCommandBySelector(void* sel, WXWidget slf, void* WXUNUSED(_cmd)) { wxLogTrace(TRACE_KEYS, "Selector %s for %s", wxDumpSelector((SEL)sel), wxDumpNSView(slf)); @@ -2139,23 +2139,25 @@ void wxWidgetCocoaImpl::doCommandBySelector(void* sel, WXWidget slf, void* WXUNU // it is also possible to map 1 keystroke to multiple commands, eg Ctrl-O on mac is translated to the bash-equivalent of // execute and move back in history, since this results in two commands, Ctrl-O was sent twice as a wx key down event. // we now track the sending of the events to avoid duplicates. - + + bool handled = false; + if ( IsInNativeKeyDown() && !WasKeyDownSent()) { // If we have a corresponding key event, send wxEVT_KEY_DOWN now. // (see also: wxWidgetCocoaImpl::DoHandleKeyEvent) wxKeyEvent wxevent(wxEVT_KEY_DOWN); SetupKeyEvent( wxevent, GetLastNativeKeyDownEvent() ); - bool result = GetWXPeer()->OSXHandleKeyEvent(wxevent); + handled = GetWXPeer()->OSXHandleKeyEvent(wxevent); - if (!result) + if (!handled) { // Generate wxEVT_CHAR if wxEVT_KEY_DOWN is not handled. wxKeyEvent wxevent2(wxevent) ; wxevent2.SetEventType(wxEVT_CHAR); SetupKeyEvent( wxevent2, GetLastNativeKeyDownEvent() ); - GetWXPeer()->OSXHandleKeyEvent(wxevent2); + handled = GetWXPeer()->OSXHandleKeyEvent(wxevent2); } SetKeyDownSent(); } @@ -2163,6 +2165,8 @@ void wxWidgetCocoaImpl::doCommandBySelector(void* sel, WXWidget slf, void* WXUNU { wxLogTrace(TRACE_KEYS, "Doing nothing in doCommandBySelector:"); } + + return handled; } bool wxWidgetCocoaImpl::acceptsFirstResponder(WXWidget slf, void *_cmd) From 26d6f82a81f6150d43c75db5a6bb5198d86fe798 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Tue, 13 Apr 2021 17:35:20 +0200 Subject: [PATCH 2/4] Implement EVT_CHAR generation for wxDataViewCtrl under Mac This requires manually sending the original key event back to the native control because NSOutlineView doesn't implement the NSTextInputClient protocol and so doesn't allow handling the keys in the usual way. --- include/wx/osx/cocoa/dataview.h | 3 ++ include/wx/osx/dataview.h | 1 + src/osx/cocoa/dataview.mm | 63 ++++++++++++++++++++++++++------- src/osx/dataview_osx.cpp | 7 ++++ 4 files changed, 61 insertions(+), 13 deletions(-) diff --git a/include/wx/osx/cocoa/dataview.h b/include/wx/osx/cocoa/dataview.h index a41c26d209..0694257cba 100644 --- a/include/wx/osx/cocoa/dataview.h +++ b/include/wx/osx/cocoa/dataview.h @@ -573,6 +573,9 @@ public: virtual void SetFont(const wxFont& font); + virtual void keyEvent(WX_NSEvent event, WXWidget slf, void* _cmd) wxOVERRIDE; + virtual bool doCommandBySelector(void* sel, WXWidget slf, void* _cmd) wxOVERRIDE; + private: void InitOutlineView(long style); int GetDefaultRowHeight() const; diff --git a/include/wx/osx/dataview.h b/include/wx/osx/dataview.h index 7e759472b1..bc0741f353 100644 --- a/include/wx/osx/dataview.h +++ b/include/wx/osx/dataview.h @@ -285,6 +285,7 @@ protected: // event handling void OnSize(wxSizeEvent &event); void OnMouse(wxMouseEvent &event); + void OnChar(wxKeyEvent &event); private: // initializing of local variables: diff --git a/src/osx/cocoa/dataview.mm b/src/osx/cocoa/dataview.mm index 6ff0cc3088..ae6fb345bb 100644 --- a/src/osx/cocoa/dataview.mm +++ b/src/osx/cocoa/dataview.mm @@ -1632,6 +1632,16 @@ outlineView:(NSOutlineView*)outlineView // ============================================================================ @implementation wxCocoaOutlineView ++ (void)initialize +{ + static BOOL initialized = NO; + if (!initialized) + { + initialized = YES; + wxOSXCocoaClassAddWXMethods( self ); + } +} + // // initializers / destructor // @@ -1723,20 +1733,15 @@ outlineView:(NSOutlineView*)outlineView // Default enter key behaviour is to begin cell editing. Subclass keyDown to // provide a keyboard wxEVT_DATAVIEW_ITEM_ACTIVATED event and allow the NSEvent // to pass if the wxEvent is not processed. -- (void)keyDown:(NSEvent *)event + +// catch events routed here and feed them back before things get routed up the responder chain +// otherwise we lose functionality like arrow keys etc. +- (void)doCommandBySelector:(SEL)aSelector { - if( [[event charactersIgnoringModifiers] - characterAtIndex: 0] == NSCarriageReturnCharacter ) + wxWidgetCocoaImpl* impl = (wxWidgetCocoaImpl* ) wxWidgetImpl::FindFromWXWidget( self ); + if (impl) { - wxDataViewCtrl* const dvc = implementation->GetDataViewCtrl(); - const wxDataViewItem item = wxDataViewItem( [[self itemAtRow:[self selectedRow]] pointer]); - wxDataViewEvent eventDV(wxEVT_DATAVIEW_ITEM_ACTIVATED, dvc, item); - if ( !dvc->GetEventHandler()->ProcessEvent(eventDV) ) - [super keyDown:event]; - } - else - { - [super keyDown:event]; // all other keys + impl->doCommandBySelector(aSelector, self, _cmd); } } @@ -2082,7 +2087,8 @@ wxCocoaDataViewControl::wxCocoaDataViewControl(wxWindow* peer, : wxWidgetCocoaImpl ( peer, - [[NSScrollView alloc] initWithFrame:wxOSXGetFrameForControl(peer,pos,size)] + [[NSScrollView alloc] initWithFrame:wxOSXGetFrameForControl(peer,pos,size)], + wxWidgetImpl::Widget_UserKeyEvents ), m_DataSource(NULL), m_OutlineView([[wxCocoaOutlineView alloc] init]), @@ -2130,6 +2136,37 @@ wxCocoaDataViewControl::~wxCocoaDataViewControl() [m_OutlineView release]; } +void wxCocoaDataViewControl::keyEvent(WX_NSEvent event, WXWidget slf, void *_cmd) +{ + if( [event type] == NSKeyDown && [[event charactersIgnoringModifiers] + characterAtIndex: 0] == NSCarriageReturnCharacter ) + { + wxDataViewCtrl* const dvc = GetDataViewCtrl(); + const wxDataViewItem item = wxDataViewItem( [[m_OutlineView itemAtRow:[m_OutlineView selectedRow]] pointer]); + wxDataViewEvent eventDV(wxEVT_DATAVIEW_ITEM_ACTIVATED, dvc, item); + if ( !dvc->GetEventHandler()->ProcessEvent(eventDV) ) + wxWidgetCocoaImpl::keyEvent(event, slf, _cmd); + } + else + { + wxWidgetCocoaImpl::keyEvent(event, slf, _cmd); // all other keys + } +} + +bool wxCocoaDataViewControl::doCommandBySelector(void* sel, WXWidget slf, void* _cmd) +{ + bool handled = wxWidgetCocoaImpl::doCommandBySelector(sel, slf, _cmd); + // if this special key has not been handled + if ( !handled && IsInNativeKeyDown() ) + { + // send the original key event back to the native implementation to get proper default handling like eg for arrow keys + wxOSX_EventHandlerPtr superimpl = (wxOSX_EventHandlerPtr) [[slf superclass] instanceMethodForSelector:@selector(keyDown:)]; + superimpl(slf, @selector(keyDown:), GetLastNativeKeyDownEvent()); + } + return handled; +} + + // // column related methods (inherited from wxDataViewWidgetImpl) // diff --git a/src/osx/dataview_osx.cpp b/src/osx/dataview_osx.cpp index c79d04f3c1..5db0a17b5a 100644 --- a/src/osx/dataview_osx.cpp +++ b/src/osx/dataview_osx.cpp @@ -770,11 +770,18 @@ void wxDataViewCtrl::OnMouse(wxMouseEvent& event) event.Skip(); } +void wxDataViewCtrl::OnChar(wxKeyEvent& event) +{ + // generic key handling can moved here + event.Skip(); +} + wxIMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl,wxDataViewCtrlBase); wxBEGIN_EVENT_TABLE(wxDataViewCtrl,wxDataViewCtrlBase) EVT_SIZE(wxDataViewCtrl::OnSize) EVT_MOTION(wxDataViewCtrl::OnMouse) + EVT_CHAR(wxDataViewCtrl::OnChar) wxEND_EVENT_TABLE() #endif // !wxHAS_GENERIC_DATAVIEWCTRL From ccdfd28b482d4a42d68842624f9b429e71a9656c Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 24 Apr 2021 00:31:17 +0200 Subject: [PATCH 3/4] Remove empty wxDataViewCtrl::OnChar() added in the parent commit This is not really useful to have, so just remove it. --- include/wx/osx/dataview.h | 1 - src/osx/dataview_osx.cpp | 7 ------- 2 files changed, 8 deletions(-) diff --git a/include/wx/osx/dataview.h b/include/wx/osx/dataview.h index bc0741f353..7e759472b1 100644 --- a/include/wx/osx/dataview.h +++ b/include/wx/osx/dataview.h @@ -285,7 +285,6 @@ protected: // event handling void OnSize(wxSizeEvent &event); void OnMouse(wxMouseEvent &event); - void OnChar(wxKeyEvent &event); private: // initializing of local variables: diff --git a/src/osx/dataview_osx.cpp b/src/osx/dataview_osx.cpp index 5db0a17b5a..c79d04f3c1 100644 --- a/src/osx/dataview_osx.cpp +++ b/src/osx/dataview_osx.cpp @@ -770,18 +770,11 @@ void wxDataViewCtrl::OnMouse(wxMouseEvent& event) event.Skip(); } -void wxDataViewCtrl::OnChar(wxKeyEvent& event) -{ - // generic key handling can moved here - event.Skip(); -} - wxIMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl,wxDataViewCtrlBase); wxBEGIN_EVENT_TABLE(wxDataViewCtrl,wxDataViewCtrlBase) EVT_SIZE(wxDataViewCtrl::OnSize) EVT_MOTION(wxDataViewCtrl::OnMouse) - EVT_CHAR(wxDataViewCtrl::OnChar) wxEND_EVENT_TABLE() #endif // !wxHAS_GENERIC_DATAVIEWCTRL From e46b6d77583c1607f3d1c1a348d35b1c57866611 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 24 Apr 2021 00:32:14 +0200 Subject: [PATCH 4/4] Also remove useless wxDataViewCtrl::OnMouse() from Mac version This empty event handler doesn't do anything useful. --- include/wx/osx/dataview.h | 1 - src/osx/dataview_osx.cpp | 6 ------ 2 files changed, 7 deletions(-) diff --git a/include/wx/osx/dataview.h b/include/wx/osx/dataview.h index 7e759472b1..457eddbebd 100644 --- a/include/wx/osx/dataview.h +++ b/include/wx/osx/dataview.h @@ -284,7 +284,6 @@ protected: // event handling void OnSize(wxSizeEvent &event); - void OnMouse(wxMouseEvent &event); private: // initializing of local variables: diff --git a/src/osx/dataview_osx.cpp b/src/osx/dataview_osx.cpp index c79d04f3c1..7ac200d45b 100644 --- a/src/osx/dataview_osx.cpp +++ b/src/osx/dataview_osx.cpp @@ -765,16 +765,10 @@ wxSize wxDataViewCtrl::DoGetBestSize() const return best; } -void wxDataViewCtrl::OnMouse(wxMouseEvent& event) -{ - event.Skip(); -} - wxIMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl,wxDataViewCtrlBase); wxBEGIN_EVENT_TABLE(wxDataViewCtrl,wxDataViewCtrlBase) EVT_SIZE(wxDataViewCtrl::OnSize) - EVT_MOTION(wxDataViewCtrl::OnMouse) wxEND_EVENT_TABLE() #endif // !wxHAS_GENERIC_DATAVIEWCTRL