From a02b930596c98353bbc73fbbe898e99fe9133242 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Mon, 26 Jul 2021 11:06:51 +0300 Subject: [PATCH 01/12] Fix HitTestSingleLine(Beyond) --- src/univ/textctrl.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index d9fc2e365e..24f190a1a7 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -2884,16 +2884,7 @@ wxTextCtrlHitTestResult wxTextCtrl::HitTestLine(const wxString& line, dc.GetTextExtent(line, &width, NULL); if ( x >= width ) { - // clicking beyond the end of line is equivalent to clicking at - // the end of it, so return the last line column col = line.length(); - if ( col ) - { - // unless the line is empty and so doesn't have any column at all - - // in this case return 0, what else can we do? - col--; - } - res = wxTE_HT_BEYOND; } else if ( x < 0 ) From 3e675fa75e2aa7805ad8b9924f407fa8af94ba27 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Mon, 26 Jul 2021 11:10:20 +0300 Subject: [PATCH 02/12] Fix HitTestSingleLine(Scrolled) --- src/univ/textctrl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index 24f190a1a7..c8f6884599 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -2459,7 +2459,7 @@ void wxTextCtrl::UpdateLastVisible() return; // use (efficient) HitTestLine to find the last visible character - wxString text = m_value.Mid((size_t)SData().m_colStart /* to the end */); + wxString text = m_value;//m_value.Mid((size_t)SData().m_colStart /* to the end */); wxTextCoord col; switch ( HitTestLine(text, m_rectText.width, &col) ) { @@ -3379,7 +3379,7 @@ void wxTextCtrl::ScrollText(wxTextCoord col) SData().m_colStart = col; // after changing m_colStart, recalc the last visible position: we need - // to recalc the last visible position beore scrolling in order to make + // to recalc the last visible position before scrolling in order to make // it appear exactly at the right edge of the text area after scrolling UpdateLastVisible(); From 5bc725f505fb34069792af7e2a48540f022c921a Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Tue, 27 Jul 2021 10:50:24 +0300 Subject: [PATCH 03/12] Set insertion point to 0 in SetValue for multiline --- src/univ/textctrl.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index c8f6884599..ac69ed1e4a 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -790,10 +790,7 @@ void wxTextCtrl::DoSetValue(const wxString& value, int flags) Replace(0, GetLastPosition(), value); - if ( IsSingleLine() ) - { - SetInsertionPoint(0); - } + SetInsertionPoint(0); } else // nothing changed { From 335d0bec0c0e14b79acf4faeff80d0cf6c3d98a5 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Tue, 27 Jul 2021 14:43:30 +0300 Subject: [PATCH 04/12] Skip or disable unsupported tests --- tests/controls/textctrltest.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/controls/textctrltest.cpp b/tests/controls/textctrltest.cpp index 9d17f13892..7d13969d61 100644 --- a/tests/controls/textctrltest.cpp +++ b/tests/controls/textctrltest.cpp @@ -437,7 +437,7 @@ void TextCtrlTestCase::ProcessEnter() void TextCtrlTestCase::Url() { -#if wxUSE_UIACTIONSIMULATOR && defined(__WXMSW__) +#if wxUSE_UIACTIONSIMULATOR && defined(__WXMSW__) && !defined(__WXUNIVERSAL__) // For some unfathomable reason, this test consistently fails when run in // AppVeyor CI environment, even though it passes locally, so skip it // there. @@ -543,7 +543,11 @@ void TextCtrlTestCase::FontStyle() m_text->AppendText("Default font size 14"); wxTextAttr attrOut; - m_text->GetStyle(5, attrOut); + if ( !m_text->GetStyle(5, attrOut) ) + { + WARN("Retrieving text style not supported, skipping test."); + return; + } CPPUNIT_ASSERT( attrOut.HasFont() ); @@ -686,7 +690,7 @@ void TextCtrlTestCase::DoPositionToCoordsTestWithStyle(long style) const wxPoint pos0 = m_text->PositionToCoords(0); if ( pos0 == wxDefaultPosition ) { -#if defined(__WXMSW__) || defined(__WXGTK20__) +#if ( defined(__WXMSW__) && !defined(__WXUNIVERSAL__) ) || defined(__WXGTK20__) CPPUNIT_FAIL( "PositionToCoords() unexpectedly failed." ); #endif return; From f7f6575bfbbcc1aa7156314398ce4e9ced2eb090 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Sun, 1 Aug 2021 11:33:03 +0300 Subject: [PATCH 05/12] Fix positions tests --- src/univ/textctrl.cpp | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index ac69ed1e4a..8cf17e9825 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -1192,6 +1192,13 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text) // update the (cached) last position first as refresh functions use it m_posLast += text.length() - to + from; +#if defined(__WXMSW__) + // Take into account that every new line mark occupies + // two characters, not one. + if ( !HasFlag(wxTE_RICH | wxTE_RICH2) ) + m_posLast += nReplaceCount - 1; +#endif // WXMSW + // we may optimize refresh if the number of rows didn't change - but if // it did we have to refresh everything below the part we chanegd as // well as it might have moved @@ -1721,11 +1728,10 @@ wxTextPos wxTextCtrl::XYToPosition(wxTextCoord x, wxTextCoord y) const } else // multiline { - if ( (size_t)y >= GetLineCount() ) - { - // this position is below the text - return GetLastPosition(); - } + size_t nLineCount = GetLineCount(); + + if ((size_t)y >= nLineCount) + return -1; wxTextPos pos = 0; for ( size_t nLine = 0; nLine < (size_t)y; nLine++ ) @@ -1733,14 +1739,16 @@ wxTextPos wxTextCtrl::XYToPosition(wxTextCoord x, wxTextCoord y) const // +1 is because the positions at the end of this line and of the // start of the next one are different pos += GetLines()[nLine].length() + 1; + +#if defined(__WXMSW__) + if( !HasFlag(wxTE_RICH | wxTE_RICH2) && nLine + 1 != nLineCount) + pos += 1; +#endif // WXMSW } - // take into account also the position in line + // out of the line if ( (size_t)x > GetLines()[y].length() ) - { - // don't return position in the next line - x = GetLines()[y].length(); - } + return -1; return pos + x; } @@ -1767,15 +1775,24 @@ bool wxTextCtrl::PositionToXY(wxTextPos pos, size_t nLineCount = GetLineCount(); for ( size_t nLine = 0; nLine < nLineCount; nLine++ ) { - // +1 is because the start the start of the next line is one + // +1 is because the start of the next line is one // position after the end of this one wxTextPos posNew = posCur + GetLines()[nLine].length() + 1; +#if defined(__WXMSW__) + if( !HasFlag(wxTE_RICH | wxTE_RICH2) && nLine + 1 != nLineCount) + posNew += 1; +#endif // WXMSW if ( posNew > pos ) { // we've found the line, now just calc the column if ( x ) *x = pos - posCur; +#if defined(__WXMSW__) + if ( !HasFlag(wxTE_RICH | wxTE_RICH2) && x && nLine + 1 != nLineCount && posNew - 1 == pos) + *x = pos - posCur - 1; +#endif // WXMSW + if ( y ) *y = nLine; From af8b662868caaea6705e1d728ad5a793313cc732 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Mon, 2 Aug 2021 10:03:42 +0300 Subject: [PATCH 06/12] Handle WM_GETDLGCODE in wxTextCtrl for wxUniv too --- include/wx/univ/textctrl.h | 6 +++ src/msw/window.cpp | 105 ++++++++++++++++++++++++++++++++++++- src/univ/dialog.cpp | 8 ++- src/univ/textctrl.cpp | 22 ++++++++ 4 files changed, 138 insertions(+), 3 deletions(-) diff --git a/include/wx/univ/textctrl.h b/include/wx/univ/textctrl.h index 3a15244a8b..d5cea66484 100644 --- a/include/wx/univ/textctrl.h +++ b/include/wx/univ/textctrl.h @@ -451,6 +451,12 @@ protected: bool DoCut(); bool DoPaste(); +#ifdef __WXMSW__ +public: + // override MSWHandleMessage to process WM_GETDLGCODE + bool MSWHandleMessage(WXLRESULT *result, WXUINT message, WXWPARAM wParam, WXLPARAM lParam); +#endif // __WXMSW__ + private: // all these methods are for multiline text controls only diff --git a/src/msw/window.cpp b/src/msw/window.cpp index cba433d6be..417e86e62a 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -2676,7 +2676,104 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } } #else // __WXUNIVERSAL__ - wxUnusedVar(pMsg); + // But it also handles clicks on default button + if ( m_hWnd && + HasFlag(wxTAB_TRAVERSAL) && + wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) ) + { + MSG *msg = (MSG *)pMsg; + + if ( msg->message == WM_KEYDOWN ) + { + bool bCtrlDown = wxIsCtrlDown(); + + // WM_GETDLGCODE: ask the control if it wants the key for itself, + // don't process it if it's the case (except for Ctrl-Tab/Enter + // combinations which are always processed) + LONG lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0); + + // surprisingly, DLGC_WANTALLKEYS bit mask doesn't contain the + // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, + // it, of course, implies them + if ( lDlgCode & DLGC_WANTALLKEYS ) + { + lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS; + } + + switch ( msg->wParam ) + { + case VK_RETURN: + { +#if wxUSE_BUTTON + // currently active button should get enter press even + // if there is a default button elsewhere so check if + // this window is a button first + wxButton *btn = NULL; + if ( lDlgCode & DLGC_DEFPUSHBUTTON ) + { + // let IsDialogMessage() handle this for all + // buttons except the owner-drawn ones which it + // just seems to ignore + long style = ::GetWindowLong(msg->hwnd, GWL_STYLE); + if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW ) + { + btn = wxDynamicCast + ( + wxFindWinFromHandle(msg->hwnd), + wxButton + ); + } + } + else // not a button itself, do we have default button? + { + // check if this window or any of its ancestors + // wants the message for itself (we always reserve + // Ctrl-Enter for dialog navigation though) + wxWindow *win = wxDynamicCast(this, wxWindow); + if ( !bCtrlDown ) + { + // this will contain the dialog code of this + // window and all of its parent windows in turn + LONG lDlgCode2 = lDlgCode; + + while ( win ) + { + if ( lDlgCode2 & DLGC_WANTMESSAGE ) + { + // as it wants to process Enter itself, + // don't call IsDialogMessage() which + // would consume it + return false; + } + + // don't propagate keyboard messages beyond + // the first top level window parent + if ( win->IsTopLevel() ) + break; + + win = win->GetParent(); + + lDlgCode2 = ::SendMessage + ( + GetHwndOf(win), + WM_GETDLGCODE, + 0, + 0 + ); + } + } + + btn = MSWGetDefaultButtonFor(win); + } + + if ( MSWClickButtonIfPossible(btn) ) + return true; +#endif // wxUSE_BUTTON + } + break; + } + } + } #endif // !__WXUNIVERSAL__/__WXUNIVERSAL__ #if wxUSE_TOOLTIPS @@ -2812,8 +2909,14 @@ bool wxWindowMSW::MSWClickButtonIfPossible(wxButton* btn) #if wxUSE_BUTTON if ( btn && btn->IsEnabled() && btn->IsShownOnScreen() ) { +#ifndef __WXUNIVERSAL__ btn->MSWCommand(BN_CLICKED, 0 /* unused */); return true; +#endif // !__WXUNIVERSAL + + wxCommandEvent event(wxEVT_BUTTON, btn->GetId()); + event.SetEventObject(btn); + return btn->HandleWindowEvent(event); } #endif // wxUSE_BUTTON diff --git a/src/univ/dialog.cpp b/src/univ/dialog.cpp index 8de1a92a5d..fae198adbb 100644 --- a/src/univ/dialog.cpp +++ b/src/univ/dialog.cpp @@ -96,8 +96,12 @@ void wxDialog::OnOK(wxCommandEvent &WXUNUSED(event)) } else { - SetReturnCode(wxID_OK); - Show(false); + // don't change return code from event char if it was set earlier + if (GetReturnCode() == 0) + { + SetReturnCode(wxID_OK); + Show(false); + } } } } diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index 8cf17e9825..53ca0ae95f 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -4805,6 +4805,28 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) event.Skip(); } +#ifdef __WXMSW__ +bool wxTextCtrl::MSWHandleMessage(WXLRESULT* result, WXUINT message, WXWPARAM wParam, WXLPARAM lParam) +{ + bool processed = wxTextCtrlBase::MSWHandleMessage(result, message, wParam, lParam); + switch ( message ) + { + case WM_GETDLGCODE: + { + long lDlgCode = 0; + + // multiline controls should always get ENTER for themselves + if ( HasFlag(wxTE_PROCESS_ENTER) || HasFlag(wxTE_MULTILINE) ) + lDlgCode |= DLGC_WANTMESSAGE; + + *result |= lDlgCode; + return true; + } + } + return processed; +} +#endif // __WXMSW__ + /* static */ wxInputHandler *wxTextCtrl::GetStdInputHandler(wxInputHandler *handlerDef) { From 5d1a936f732b27a1b801492502e6ce499738d2c3 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Sat, 7 Aug 2021 09:40:26 +0300 Subject: [PATCH 07/12] Revert "Handle WM_GETDLGCODE in wxTextCtrl for wxUniv too" This reverts commit af8b662868caaea6705e1d728ad5a793313cc732. --- include/wx/univ/textctrl.h | 6 --- src/msw/window.cpp | 105 +------------------------------------ src/univ/dialog.cpp | 8 +-- src/univ/textctrl.cpp | 22 -------- 4 files changed, 3 insertions(+), 138 deletions(-) diff --git a/include/wx/univ/textctrl.h b/include/wx/univ/textctrl.h index d5cea66484..3a15244a8b 100644 --- a/include/wx/univ/textctrl.h +++ b/include/wx/univ/textctrl.h @@ -451,12 +451,6 @@ protected: bool DoCut(); bool DoPaste(); -#ifdef __WXMSW__ -public: - // override MSWHandleMessage to process WM_GETDLGCODE - bool MSWHandleMessage(WXLRESULT *result, WXUINT message, WXWPARAM wParam, WXLPARAM lParam); -#endif // __WXMSW__ - private: // all these methods are for multiline text controls only diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 417e86e62a..cba433d6be 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -2676,104 +2676,7 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg) } } #else // __WXUNIVERSAL__ - // But it also handles clicks on default button - if ( m_hWnd && - HasFlag(wxTAB_TRAVERSAL) && - wxHasWindowExStyle(this, WS_EX_CONTROLPARENT) ) - { - MSG *msg = (MSG *)pMsg; - - if ( msg->message == WM_KEYDOWN ) - { - bool bCtrlDown = wxIsCtrlDown(); - - // WM_GETDLGCODE: ask the control if it wants the key for itself, - // don't process it if it's the case (except for Ctrl-Tab/Enter - // combinations which are always processed) - LONG lDlgCode = ::SendMessage(msg->hwnd, WM_GETDLGCODE, 0, 0); - - // surprisingly, DLGC_WANTALLKEYS bit mask doesn't contain the - // DLGC_WANTTAB nor DLGC_WANTARROWS bits although, logically, - // it, of course, implies them - if ( lDlgCode & DLGC_WANTALLKEYS ) - { - lDlgCode |= DLGC_WANTTAB | DLGC_WANTARROWS; - } - - switch ( msg->wParam ) - { - case VK_RETURN: - { -#if wxUSE_BUTTON - // currently active button should get enter press even - // if there is a default button elsewhere so check if - // this window is a button first - wxButton *btn = NULL; - if ( lDlgCode & DLGC_DEFPUSHBUTTON ) - { - // let IsDialogMessage() handle this for all - // buttons except the owner-drawn ones which it - // just seems to ignore - long style = ::GetWindowLong(msg->hwnd, GWL_STYLE); - if ( (style & BS_OWNERDRAW) == BS_OWNERDRAW ) - { - btn = wxDynamicCast - ( - wxFindWinFromHandle(msg->hwnd), - wxButton - ); - } - } - else // not a button itself, do we have default button? - { - // check if this window or any of its ancestors - // wants the message for itself (we always reserve - // Ctrl-Enter for dialog navigation though) - wxWindow *win = wxDynamicCast(this, wxWindow); - if ( !bCtrlDown ) - { - // this will contain the dialog code of this - // window and all of its parent windows in turn - LONG lDlgCode2 = lDlgCode; - - while ( win ) - { - if ( lDlgCode2 & DLGC_WANTMESSAGE ) - { - // as it wants to process Enter itself, - // don't call IsDialogMessage() which - // would consume it - return false; - } - - // don't propagate keyboard messages beyond - // the first top level window parent - if ( win->IsTopLevel() ) - break; - - win = win->GetParent(); - - lDlgCode2 = ::SendMessage - ( - GetHwndOf(win), - WM_GETDLGCODE, - 0, - 0 - ); - } - } - - btn = MSWGetDefaultButtonFor(win); - } - - if ( MSWClickButtonIfPossible(btn) ) - return true; -#endif // wxUSE_BUTTON - } - break; - } - } - } + wxUnusedVar(pMsg); #endif // !__WXUNIVERSAL__/__WXUNIVERSAL__ #if wxUSE_TOOLTIPS @@ -2909,14 +2812,8 @@ bool wxWindowMSW::MSWClickButtonIfPossible(wxButton* btn) #if wxUSE_BUTTON if ( btn && btn->IsEnabled() && btn->IsShownOnScreen() ) { -#ifndef __WXUNIVERSAL__ btn->MSWCommand(BN_CLICKED, 0 /* unused */); return true; -#endif // !__WXUNIVERSAL - - wxCommandEvent event(wxEVT_BUTTON, btn->GetId()); - event.SetEventObject(btn); - return btn->HandleWindowEvent(event); } #endif // wxUSE_BUTTON diff --git a/src/univ/dialog.cpp b/src/univ/dialog.cpp index fae198adbb..8de1a92a5d 100644 --- a/src/univ/dialog.cpp +++ b/src/univ/dialog.cpp @@ -96,12 +96,8 @@ void wxDialog::OnOK(wxCommandEvent &WXUNUSED(event)) } else { - // don't change return code from event char if it was set earlier - if (GetReturnCode() == 0) - { - SetReturnCode(wxID_OK); - Show(false); - } + SetReturnCode(wxID_OK); + Show(false); } } } diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index 53ca0ae95f..8cf17e9825 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -4805,28 +4805,6 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) event.Skip(); } -#ifdef __WXMSW__ -bool wxTextCtrl::MSWHandleMessage(WXLRESULT* result, WXUINT message, WXWPARAM wParam, WXLPARAM lParam) -{ - bool processed = wxTextCtrlBase::MSWHandleMessage(result, message, wParam, lParam); - switch ( message ) - { - case WM_GETDLGCODE: - { - long lDlgCode = 0; - - // multiline controls should always get ENTER for themselves - if ( HasFlag(wxTE_PROCESS_ENTER) || HasFlag(wxTE_MULTILINE) ) - lDlgCode |= DLGC_WANTMESSAGE; - - *result |= lDlgCode; - return true; - } - } - return processed; -} -#endif // __WXMSW__ - /* static */ wxInputHandler *wxTextCtrl::GetStdInputHandler(wxInputHandler *handlerDef) { From e3acc50fbcb1ed390b75046099769fa7243016d8 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Sat, 7 Aug 2021 09:56:02 +0300 Subject: [PATCH 08/12] Improve wxTE_PROCESS_ENTER handling in wxUniv --- include/wx/univ/textctrl.h | 3 +++ src/univ/dialog.cpp | 8 ++++++-- src/univ/textctrl.cpp | 42 ++++++++++++++++++++++++++++++++++++-- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/include/wx/univ/textctrl.h b/include/wx/univ/textctrl.h index 3a15244a8b..7b59237332 100644 --- a/include/wx/univ/textctrl.h +++ b/include/wx/univ/textctrl.h @@ -36,6 +36,7 @@ class WXDLLIMPEXP_FWD_CORE wxTextCtrlCommandProcessor; #define wxACTION_TEXT_WORD_RIGHT wxT("wordright") #define wxACTION_TEXT_PAGE_UP wxT("pageup") #define wxACTION_TEXT_PAGE_DOWN wxT("pagedown") +#define wxACTION_TEXT_RETURN wxT("return") // clipboard operations #define wxACTION_TEXT_COPY wxT("copy") @@ -451,6 +452,8 @@ protected: bool DoCut(); bool DoPaste(); + bool ClickDefaultButtonIfPossible(); + private: // all these methods are for multiline text controls only diff --git a/src/univ/dialog.cpp b/src/univ/dialog.cpp index 8de1a92a5d..fae198adbb 100644 --- a/src/univ/dialog.cpp +++ b/src/univ/dialog.cpp @@ -96,8 +96,12 @@ void wxDialog::OnOK(wxCommandEvent &WXUNUSED(event)) } else { - SetReturnCode(wxID_OK); - Show(false); + // don't change return code from event char if it was set earlier + if (GetReturnCode() == 0) + { + SetReturnCode(wxID_OK); + Show(false); + } } } } diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index 8cf17e9825..75a3831abf 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -4676,6 +4676,15 @@ bool wxTextCtrl::PerformAction(const wxControlAction& actionOrig, if ( CanRedo() ) Redo(); } + else if ( action == wxACTION_TEXT_RETURN ) + { + // activate default button + if ( !HasFlag(wxTE_PROCESS_ENTER) && !HasFlag(wxTE_MULTILINE) ) + { + return ClickDefaultButtonIfPossible(); + } + return false; + } else { return wxControl::PerformAction(action, numArg, strArg); @@ -4768,13 +4777,18 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) #endif if ( keycode == WXK_RETURN ) { - if ( IsSingleLine() || (GetWindowStyle() & wxTE_PROCESS_ENTER) ) + if ( (GetWindowStyle() & wxTE_PROCESS_ENTER) ) { wxCommandEvent event(wxEVT_TEXT_ENTER, GetId()); InitCommandEvent(event); event.SetString(GetValue()); GetEventHandler()->ProcessEvent(event); } + + if ( IsSingleLine() ) + { + ClickDefaultButtonIfPossible(); + } else // interpret normally: insert new line { PerformAction(wxACTION_TEXT_INSERT, -1, wxT('\n')); @@ -4805,6 +4819,23 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) event.Skip(); } +bool wxTextCtrl::ClickDefaultButtonIfPossible() +{ + wxTopLevelWindow* tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow); + if ( tlw ) + { + wxButton* btn = wxDynamicCast(tlw->GetDefaultItem(), wxButton); + if ( btn ) + { + wxCommandEvent evt(wxEVT_BUTTON, btn->GetId()); + evt.SetEventObject(btn); + btn->Command(evt); + return true; + } + } + return false; +} + /* static */ wxInputHandler *wxTextCtrl::GetStdInputHandler(wxInputHandler *handlerDef) { @@ -4922,6 +4953,9 @@ bool wxStdTextCtrlInputHandler::HandleKey(wxInputConsumer *consumer, action << wxACTION_TEXT_PREFIX_DEL << wxACTION_TEXT_LEFT; break; + case WXK_RETURN: + action << wxACTION_TEXT_RETURN; + break; // something else default: // reset the action as it could be already set to one of the @@ -4957,7 +4991,11 @@ bool wxStdTextCtrlInputHandler::HandleKey(wxInputConsumer *consumer, if ( (action != wxACTION_NONE) && (action != wxACTION_TEXT_PREFIX_SEL) ) { - consumer->PerformAction(action, -1, str); + bool result = consumer->PerformAction(action, -1, str); + if ( !result && action == wxACTION_TEXT_RETURN ) + { + return wxStdInputHandler::HandleKey(consumer, event, pressed); + } // the key down of WXK_UP/DOWN and WXK_PAGEUP/DOWN // must generate a wxEVT_TEXT event. For the controls From b8d9ac9a32e1fb8d24d240195b597b69a2c8f5bd Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Sat, 7 Aug 2021 11:03:03 +0300 Subject: [PATCH 09/12] Revert MSW-specific changes for wxTextCtrl tests in wxUniv --- src/univ/textctrl.cpp | 21 +------------------- tests/controls/textctrltest.cpp | 34 ++++++++++++++++----------------- 2 files changed, 18 insertions(+), 37 deletions(-) diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index 75a3831abf..11f1613340 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -1192,13 +1192,6 @@ void wxTextCtrl::Replace(wxTextPos from, wxTextPos to, const wxString& text) // update the (cached) last position first as refresh functions use it m_posLast += text.length() - to + from; -#if defined(__WXMSW__) - // Take into account that every new line mark occupies - // two characters, not one. - if ( !HasFlag(wxTE_RICH | wxTE_RICH2) ) - m_posLast += nReplaceCount - 1; -#endif // WXMSW - // we may optimize refresh if the number of rows didn't change - but if // it did we have to refresh everything below the part we chanegd as // well as it might have moved @@ -1740,10 +1733,6 @@ wxTextPos wxTextCtrl::XYToPosition(wxTextCoord x, wxTextCoord y) const // start of the next one are different pos += GetLines()[nLine].length() + 1; -#if defined(__WXMSW__) - if( !HasFlag(wxTE_RICH | wxTE_RICH2) && nLine + 1 != nLineCount) - pos += 1; -#endif // WXMSW } // out of the line @@ -1778,21 +1767,13 @@ bool wxTextCtrl::PositionToXY(wxTextPos pos, // +1 is because the start of the next line is one // position after the end of this one wxTextPos posNew = posCur + GetLines()[nLine].length() + 1; -#if defined(__WXMSW__) - if( !HasFlag(wxTE_RICH | wxTE_RICH2) && nLine + 1 != nLineCount) - posNew += 1; -#endif // WXMSW + if ( posNew > pos ) { // we've found the line, now just calc the column if ( x ) *x = pos - posCur; -#if defined(__WXMSW__) - if ( !HasFlag(wxTE_RICH | wxTE_RICH2) && x && nLine + 1 != nLineCount && posNew - 1 == pos) - *x = pos - posCur - 1; -#endif // WXMSW - if ( y ) *y = nLine; diff --git a/tests/controls/textctrltest.cpp b/tests/controls/textctrltest.cpp index 7d13969d61..5196b6d08d 100644 --- a/tests/controls/textctrltest.cpp +++ b/tests/controls/textctrltest.cpp @@ -793,7 +793,7 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) delete m_text; CreateText(style|wxTE_MULTILINE|wxTE_DONTWRAP); -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) const bool isRichEdit = (style & (wxTE_RICH | wxTE_RICH2)) != 0; #endif @@ -844,7 +844,7 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) text = wxS("123\nab\nX"); m_text->SetValue(text); -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) // Take into account that every new line mark occupies // two characters, not one. const long numChars_msw_2 = 8 + 2; @@ -863,14 +863,14 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) { 0, 2 }, { 1, 2 } }; const long &ref_numChars_2 = -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) isRichEdit ? numChars_2 : numChars_msw_2; #else numChars_2; #endif XYPos *ref_coords_2 = -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) isRichEdit ? coords_2 : coords_2_msw; #else coords_2; @@ -892,7 +892,7 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) text = wxS("\n\n\n"); m_text->SetValue(text); -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) // Take into account that every new line mark occupies // two characters, not one. const long numChars_msw_3 = 3 + 3; @@ -913,14 +913,14 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) { 0, 3 } }; const long &ref_numChars_3 = -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) isRichEdit ? numChars_3 : numChars_msw_3; #else numChars_3; #endif XYPos *ref_coords_3 = -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) isRichEdit ? coords_3 : coords_3_msw; #else coords_3; @@ -942,7 +942,7 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) text = wxS("123\na\n\nX\n\n"); m_text->SetValue(text); -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) // Take into account that every new line mark occupies // two characters, not one. const long numChars_msw_4 = 10 + 5; @@ -967,14 +967,14 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) { 0, 5 } }; const long &ref_numChars_4 = -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) isRichEdit ? numChars_4 : numChars_msw_4; #else numChars_4; #endif XYPos *ref_coords_4 = -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) isRichEdit ? coords_4 : coords_4_msw; #else coords_4; @@ -1015,7 +1015,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) delete m_text; CreateText(style|wxTE_MULTILINE|wxTE_DONTWRAP); -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) const bool isRichEdit = (style & (wxTE_RICH | wxTE_RICH2)) != 0; #endif @@ -1059,7 +1059,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) const long maxLineLength_2 = 4; const long numLines_2 = 3; CPPUNIT_ASSERT_EQUAL( numLines_2, m_text->GetNumberOfLines() ); -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) // Note: New lines are occupied by two characters. long pos_2_msw[numLines_2 + 1][maxLineLength_2 + 1] = { { 0, 1, 2, 3, -1 }, // New line occupies positions 3, 4 @@ -1074,7 +1074,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) { -1, -1, -1, -1, -1 } }; long (&ref_pos_2)[numLines_2 + 1][maxLineLength_2 + 1] = -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) isRichEdit ? pos_2 : pos_2_msw; #else pos_2; @@ -1094,7 +1094,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) const long maxLineLength_3 = 1; const long numLines_3 = 4; CPPUNIT_ASSERT_EQUAL( numLines_3, m_text->GetNumberOfLines() ); -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) // Note: New lines are occupied by two characters. long pos_3_msw[numLines_3 + 1][maxLineLength_3 + 1] = { { 0, -1 }, // New line occupies positions 0, 1 @@ -1111,7 +1111,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) { -1, -1 } }; long (&ref_pos_3)[numLines_3 + 1][maxLineLength_3 + 1] = -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) isRichEdit ? pos_3 : pos_3_msw; #else pos_3; @@ -1131,7 +1131,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) const long maxLineLength_4 = 4; const long numLines_4 = 6; CPPUNIT_ASSERT_EQUAL( numLines_4, m_text->GetNumberOfLines() ); -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) // Note: New lines are occupied by two characters. long pos_4_msw[numLines_4 + 1][maxLineLength_4 + 1] = { { 0, 1, 2, 3, -1 }, // New line occupies positions 3, 4 @@ -1152,7 +1152,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) { -1, -1, -1, -1, -1 } }; long (&ref_pos_4)[numLines_4 + 1][maxLineLength_4 + 1] = -#if defined(__WXMSW__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) isRichEdit ? pos_4 : pos_4_msw; #else pos_4; From 15c51255726be518218c5a9acdd762260ee6db8c Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Sat, 7 Aug 2021 22:34:56 +0300 Subject: [PATCH 10/12] Refactoring --- src/univ/textctrl.cpp | 2 +- tests/controls/textctrltest.cpp | 40 +++++++++++++++++---------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index 11f1613340..da1e5bce82 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -2454,7 +2454,7 @@ void wxTextCtrl::UpdateLastVisible() return; // use (efficient) HitTestLine to find the last visible character - wxString text = m_value;//m_value.Mid((size_t)SData().m_colStart /* to the end */); + wxString text = m_value; wxTextCoord col; switch ( HitTestLine(text, m_rectText.width, &col) ) { diff --git a/tests/controls/textctrltest.cpp b/tests/controls/textctrltest.cpp index 5196b6d08d..57856491e4 100644 --- a/tests/controls/textctrltest.cpp +++ b/tests/controls/textctrltest.cpp @@ -38,6 +38,8 @@ static const int TEXT_HEIGHT = 200; +#define wxHAS_2CHAR_NEWLINES defined(__WXMSW__) && !defined(__WXUNIVERSAL__) + // ---------------------------------------------------------------------------- // test class // ---------------------------------------------------------------------------- @@ -437,7 +439,7 @@ void TextCtrlTestCase::ProcessEnter() void TextCtrlTestCase::Url() { -#if wxUSE_UIACTIONSIMULATOR && defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxUSE_UIACTIONSIMULATOR && wxHAS_2CHAR_NEWLINES // For some unfathomable reason, this test consistently fails when run in // AppVeyor CI environment, even though it passes locally, so skip it // there. @@ -690,7 +692,7 @@ void TextCtrlTestCase::DoPositionToCoordsTestWithStyle(long style) const wxPoint pos0 = m_text->PositionToCoords(0); if ( pos0 == wxDefaultPosition ) { -#if ( defined(__WXMSW__) && !defined(__WXUNIVERSAL__) ) || defined(__WXGTK20__) +#if ( wxHAS_2CHAR_NEWLINES ) || defined(__WXGTK20__) CPPUNIT_FAIL( "PositionToCoords() unexpectedly failed." ); #endif return; @@ -793,7 +795,7 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) delete m_text; CreateText(style|wxTE_MULTILINE|wxTE_DONTWRAP); -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES const bool isRichEdit = (style & (wxTE_RICH | wxTE_RICH2)) != 0; #endif @@ -844,7 +846,7 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) text = wxS("123\nab\nX"); m_text->SetValue(text); -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES // Take into account that every new line mark occupies // two characters, not one. const long numChars_msw_2 = 8 + 2; @@ -863,14 +865,14 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) { 0, 2 }, { 1, 2 } }; const long &ref_numChars_2 = -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES isRichEdit ? numChars_2 : numChars_msw_2; #else numChars_2; #endif XYPos *ref_coords_2 = -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES isRichEdit ? coords_2 : coords_2_msw; #else coords_2; @@ -892,7 +894,7 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) text = wxS("\n\n\n"); m_text->SetValue(text); -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES // Take into account that every new line mark occupies // two characters, not one. const long numChars_msw_3 = 3 + 3; @@ -913,14 +915,14 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) { 0, 3 } }; const long &ref_numChars_3 = -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES isRichEdit ? numChars_3 : numChars_msw_3; #else numChars_3; #endif XYPos *ref_coords_3 = -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES isRichEdit ? coords_3 : coords_3_msw; #else coords_3; @@ -942,7 +944,7 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) text = wxS("123\na\n\nX\n\n"); m_text->SetValue(text); -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES // Take into account that every new line mark occupies // two characters, not one. const long numChars_msw_4 = 10 + 5; @@ -967,14 +969,14 @@ void TextCtrlTestCase::DoPositionToXYMultiLine(long style) { 0, 5 } }; const long &ref_numChars_4 = -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES isRichEdit ? numChars_4 : numChars_msw_4; #else numChars_4; #endif XYPos *ref_coords_4 = -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES isRichEdit ? coords_4 : coords_4_msw; #else coords_4; @@ -1015,7 +1017,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) delete m_text; CreateText(style|wxTE_MULTILINE|wxTE_DONTWRAP); -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES const bool isRichEdit = (style & (wxTE_RICH | wxTE_RICH2)) != 0; #endif @@ -1059,7 +1061,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) const long maxLineLength_2 = 4; const long numLines_2 = 3; CPPUNIT_ASSERT_EQUAL( numLines_2, m_text->GetNumberOfLines() ); -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES // Note: New lines are occupied by two characters. long pos_2_msw[numLines_2 + 1][maxLineLength_2 + 1] = { { 0, 1, 2, 3, -1 }, // New line occupies positions 3, 4 @@ -1074,7 +1076,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) { -1, -1, -1, -1, -1 } }; long (&ref_pos_2)[numLines_2 + 1][maxLineLength_2 + 1] = -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES isRichEdit ? pos_2 : pos_2_msw; #else pos_2; @@ -1094,7 +1096,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) const long maxLineLength_3 = 1; const long numLines_3 = 4; CPPUNIT_ASSERT_EQUAL( numLines_3, m_text->GetNumberOfLines() ); -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES // Note: New lines are occupied by two characters. long pos_3_msw[numLines_3 + 1][maxLineLength_3 + 1] = { { 0, -1 }, // New line occupies positions 0, 1 @@ -1111,7 +1113,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) { -1, -1 } }; long (&ref_pos_3)[numLines_3 + 1][maxLineLength_3 + 1] = -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES isRichEdit ? pos_3 : pos_3_msw; #else pos_3; @@ -1131,7 +1133,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) const long maxLineLength_4 = 4; const long numLines_4 = 6; CPPUNIT_ASSERT_EQUAL( numLines_4, m_text->GetNumberOfLines() ); -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES // Note: New lines are occupied by two characters. long pos_4_msw[numLines_4 + 1][maxLineLength_4 + 1] = { { 0, 1, 2, 3, -1 }, // New line occupies positions 3, 4 @@ -1152,7 +1154,7 @@ void TextCtrlTestCase::DoXYToPositionMultiLine(long style) { -1, -1, -1, -1, -1 } }; long (&ref_pos_4)[numLines_4 + 1][maxLineLength_4 + 1] = -#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if wxHAS_2CHAR_NEWLINES isRichEdit ? pos_4 : pos_4_msw; #else pos_4; From 51bc8ede7f863d1c7ad2e9ba7f98e51bf86f8806 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Sat, 7 Aug 2021 23:58:14 +0300 Subject: [PATCH 11/12] Fix Wexpansion-to-defined --- tests/controls/textctrltest.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/controls/textctrltest.cpp b/tests/controls/textctrltest.cpp index 57856491e4..7098df48f8 100644 --- a/tests/controls/textctrltest.cpp +++ b/tests/controls/textctrltest.cpp @@ -38,7 +38,11 @@ static const int TEXT_HEIGHT = 200; -#define wxHAS_2CHAR_NEWLINES defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#if defined(__WXMSW__) && !defined(__WXUNIVERSAL__) +#define wxHAS_2CHAR_NEWLINES 1 +#else +#define wxHAS_2CHAR_NEWLINES 0 +#endif // ---------------------------------------------------------------------------- // test class From 656b0b85c6d10fd880bb4bcca146368a69b0eb84 Mon Sep 17 00:00:00 2001 From: Kvaz1r Date: Sun, 8 Aug 2021 00:23:04 +0300 Subject: [PATCH 12/12] Fix With wxTE_PROCESS_ENTER and wxTE_MULTILINE without skipping --- src/univ/textctrl.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/univ/textctrl.cpp b/src/univ/textctrl.cpp index da1e5bce82..0d66222326 100644 --- a/src/univ/textctrl.cpp +++ b/src/univ/textctrl.cpp @@ -4763,7 +4763,8 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) wxCommandEvent event(wxEVT_TEXT_ENTER, GetId()); InitCommandEvent(event); event.SetString(GetValue()); - GetEventHandler()->ProcessEvent(event); + if( GetEventHandler()->ProcessEvent(event) ) + return; } if ( IsSingleLine() )