From 26d6f82a81f6150d43c75db5a6bb5198d86fe798 Mon Sep 17 00:00:00 2001 From: Stefan Csomor Date: Tue, 13 Apr 2021 17:35:20 +0200 Subject: [PATCH] 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