diff options
author | Caolán McNamara <caolanm@redhat.com> | 2020-10-25 15:27:58 +0000 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2020-10-27 17:00:59 +0100 |
commit | b9405fbc4e19901c78d136895c5ab0437d8450ac (patch) | |
tree | f42d180c9f6b4450959ff94d6f40a2ae881d8984 /vcl | |
parent | 23c30c073495201acb82e6e2e83bb0840f25acce (diff) |
Resolves: tdf#137620 add DeleteSurroundingText at vcl::Window level
a) give it a default implementation based on the current one
b) re-use code introduced for WeldEditView::DeleteSurroundingText
for the EditView containing vcl::Window in impress/draw and
various similar Annotation windows
Change-Id: I55547c70e90ee394795b5545450cf8131538fad8
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104781
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/salvtables.hxx | 1 | ||||
-rw-r--r-- | vcl/inc/salwtype.hxx | 1 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 7 | ||||
-rw-r--r-- | vcl/source/control/edit.cxx | 10 | ||||
-rw-r--r-- | vcl/source/window/layout.cxx | 20 | ||||
-rw-r--r-- | vcl/source/window/window.cxx | 60 | ||||
-rw-r--r-- | vcl/source/window/winproc.cxx | 20 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkframe.cxx | 78 | ||||
-rw-r--r-- | vcl/unx/gtk3/gtk3gtkinst.cxx | 2 |
9 files changed, 141 insertions, 58 deletions
diff --git a/vcl/inc/salvtables.hxx b/vcl/inc/salvtables.hxx index 5a715b128f87..7717502833e8 100644 --- a/vcl/inc/salvtables.hxx +++ b/vcl/inc/salvtables.hxx @@ -1100,6 +1100,7 @@ private: DECL_LINK(CommandHdl, const CommandEvent&, bool); DECL_LINK(QueryTooltipHdl, tools::Rectangle&, OUString); DECL_LINK(GetSurroundingHdl, OUString&, int); + DECL_LINK(DeleteSurroundingHdl, const Selection&, bool); DECL_LINK(StartDragHdl, VclDrawingArea*, bool); // SalInstanceWidget has a generic listener for all these diff --git a/vcl/inc/salwtype.hxx b/vcl/inc/salwtype.hxx index ea2ee46af04f..2b07854271ef 100644 --- a/vcl/inc/salwtype.hxx +++ b/vcl/inc/salwtype.hxx @@ -80,6 +80,7 @@ enum class SalEvent { ShowDialog, MenuButtonCommand, SurroundingTextRequest, + DeleteSurroundingTextRequest, SurroundingTextSelectionChange, StartReconversion, QueryCharPosition, diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 26e382af0536..303907501e96 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -5848,6 +5848,7 @@ SalInstanceDrawingArea::SalInstanceDrawingArea(VclDrawingArea* pDrawingArea, Sal m_xDrawingArea->SetCommandHdl(LINK(this, SalInstanceDrawingArea, CommandHdl)); m_xDrawingArea->SetQueryTooltipHdl(LINK(this, SalInstanceDrawingArea, QueryTooltipHdl)); m_xDrawingArea->SetGetSurroundingHdl(LINK(this, SalInstanceDrawingArea, GetSurroundingHdl)); + m_xDrawingArea->SetDeleteSurroundingHdl(LINK(this, SalInstanceDrawingArea, DeleteSurroundingHdl)); m_xDrawingArea->SetStartDragHdl(LINK(this, SalInstanceDrawingArea, StartDragHdl)); } @@ -5941,6 +5942,7 @@ void SalInstanceDrawingArea::enable_drag_source(rtl::Reference<TransferDataConta SalInstanceDrawingArea::~SalInstanceDrawingArea() { + m_xDrawingArea->SetDeleteSurroundingHdl(Link<const Selection&, bool>()); m_xDrawingArea->SetGetSurroundingHdl(Link<OUString&, int>()); m_xDrawingArea->SetQueryTooltipHdl(Link<tools::Rectangle&, OUString>()); m_xDrawingArea->SetCommandHdl(Link<const CommandEvent&, bool>()); @@ -6017,6 +6019,11 @@ IMPL_LINK(SalInstanceDrawingArea, GetSurroundingHdl, OUString&, rSurrounding, in return m_aGetSurroundingHdl.Call(rSurrounding); } +IMPL_LINK(SalInstanceDrawingArea, DeleteSurroundingHdl, const Selection&, rSelection, bool) +{ + return m_aDeleteSurroundingHdl.Call(rSelection); +} + IMPL_LINK(SalInstanceDrawingArea, QueryTooltipHdl, tools::Rectangle&, rHelpArea, OUString) { return m_aQueryTooltipHdl.Call(rHelpArea); diff --git a/vcl/source/control/edit.cxx b/vcl/source/control/edit.cxx index 18f4fb70ee66..27eaddaf1949 100644 --- a/vcl/source/control/edit.cxx +++ b/vcl/source/control/edit.cxx @@ -2908,7 +2908,15 @@ OUString Edit::GetSurroundingText() const Selection Edit::GetSurroundingTextSelection() const { - return GetSelection(); + return GetSelection(); +} + +bool Edit::DeleteSurroundingText(const Selection& rSelection) +{ + SetSelection(rSelection); + DeleteSelected(); + // maybe we should update mpIMEInfos here + return true; } FactoryFunction Edit::GetUITestFactory() const diff --git a/vcl/source/window/layout.cxx b/vcl/source/window/layout.cxx index 36ebf51a74ff..4c98d7a88ad5 100644 --- a/vcl/source/window/layout.cxx +++ b/vcl/source/window/layout.cxx @@ -2859,19 +2859,27 @@ void VclDrawingArea::StartDrag(sal_Int8, const Point&) OUString VclDrawingArea::GetSurroundingText() const { + if (!m_aGetSurroundingHdl.IsSet()) + return Control::GetSurroundingText(); OUString sSurroundingText; - if (m_aGetSurroundingHdl.Call(sSurroundingText) != -1) - return sSurroundingText; - return Control::GetSurroundingText(); + m_aGetSurroundingHdl.Call(sSurroundingText); + return sSurroundingText; } Selection VclDrawingArea::GetSurroundingTextSelection() const { + if (!m_aGetSurroundingHdl.IsSet()) + return Control::GetSurroundingTextSelection(); OUString sSurroundingText; int nCursor = m_aGetSurroundingHdl.Call(sSurroundingText); - if (nCursor != -1) - return Selection(nCursor, nCursor); - return Control::GetSurroundingTextSelection(); + return Selection(nCursor, nCursor); +} + +bool VclDrawingArea::DeleteSurroundingText(const Selection& rSelection) +{ + if (!m_aDeleteSurroundingHdl.IsSet()) + return Control::DeleteSurroundingText(rSelection); + return m_aDeleteSurroundingHdl.Call(rSelection); } VclHPaned::~VclHPaned() diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx index 447cd0112cca..2d9cfd5966cd 100644 --- a/vcl/source/window/window.cxx +++ b/vcl/source/window/window.cxx @@ -21,6 +21,7 @@ #include <sal/log.hxx> #include <sal/types.h> +#include <tools/diagnose_ex.h> #include <vcl/salgtype.hxx> #include <vcl/event.hxx> #include <vcl/help.hxx> @@ -57,6 +58,7 @@ #include <com/sun/star/accessibility/AccessibleRelation.hpp> #include <com/sun/star/accessibility/XAccessible.hpp> +#include <com/sun/star/accessibility/XAccessibleEditableText.hpp> #include <com/sun/star/awt/XWindowPeer.hpp> #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp> #include <com/sun/star/datatransfer/dnd/XDragGestureRecognizer.hpp> @@ -3771,6 +3773,64 @@ Selection Window::GetSurroundingTextSelection() const return Selection( 0, 0 ); } +namespace +{ + using namespace com::sun::star; + + uno::Reference<accessibility::XAccessibleEditableText> lcl_GetxText(vcl::Window *pFocusWin) + { + uno::Reference<accessibility::XAccessibleEditableText> xText; + try + { + uno::Reference< accessibility::XAccessible > xAccessible( pFocusWin->GetAccessible() ); + if (xAccessible.is()) + xText = FindFocusedEditableText(xAccessible->getAccessibleContext()); + } + catch(const uno::Exception&) + { + TOOLS_WARN_EXCEPTION( "vcl.gtk3", "Exception in getting input method surrounding text"); + } + return xText; + } +} + +// this is a rubbish implementation using a11y, ideally all subclasses implementing +// GetSurroundingText/GetSurroundingTextSelection should implement this and then this +// should be removed in favor of a stub that returns false +bool Window::DeleteSurroundingText(const Selection& rSelection) +{ + uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText(this); + if (xText.is()) + { + sal_Int32 nPosition = xText->getCaretPosition(); + // #i111768# range checking + sal_Int32 nDeletePos = rSelection.Min(); + sal_Int32 nDeleteEnd = rSelection.Max(); + if (nDeletePos < 0) + nDeletePos = 0; + if (nDeleteEnd < 0) + nDeleteEnd = 0; + if (nDeleteEnd > xText->getCharacterCount()) + nDeleteEnd = xText->getCharacterCount(); + + xText->deleteText(nDeletePos, nDeleteEnd); + //tdf91641 adjust cursor if deleted chars shift it forward (normal case) + if (nDeletePos < nPosition) + { + if (nDeleteEnd <= nPosition) + nPosition = nPosition - (nDeleteEnd - nDeletePos); + else + nPosition = nDeletePos; + + if (xText->getCharacterCount() >= nPosition) + xText->setCaretPosition( nPosition ); + } + return true; + } + + return false; +} + bool Window::UsePolyPolygonForComplexGradient() { return meRasterOp != RasterOp::OverPaint; diff --git a/vcl/source/window/winproc.cxx b/vcl/source/window/winproc.cxx index 39b76a85b100..aab2cb21bb21 100644 --- a/vcl/source/window/winproc.cxx +++ b/vcl/source/window/winproc.cxx @@ -2274,6 +2274,23 @@ static void ImplHandleSalSurroundingTextRequest( vcl::Window *pWindow, pEvt->mnEnd = aSelRange.Max(); } +static void ImplHandleSalDeleteSurroundingTextRequest( vcl::Window *pWindow, + SalSurroundingTextSelectionChangeEvent *pEvt ) +{ + vcl::Window* pChild = ImplGetKeyInputWindow( pWindow ); + + Selection aSelection(pEvt->mnStart, pEvt->mnEnd); + if (pChild && pChild->DeleteSurroundingText(aSelection)) + { + pEvt->mnStart = aSelection.Min(); + pEvt->mnEnd = aSelection.Max(); + } + else + { + pEvt->mnStart = pEvt->mnEnd = SAL_MAX_UINT32; + } +} + static void ImplHandleSurroundingTextSelectionChange( vcl::Window *pWindow, sal_uLong nStart, sal_uLong nEnd ) @@ -2569,6 +2586,9 @@ bool ImplWindowFrameProc( vcl::Window* _pWindow, SalEvent nEvent, const void* pE case SalEvent::SurroundingTextRequest: ImplHandleSalSurroundingTextRequest( pWindow, const_cast<SalSurroundingTextRequestEvent *>(static_cast<SalSurroundingTextRequestEvent const *>(pEvent)) ); break; + case SalEvent::DeleteSurroundingTextRequest: + ImplHandleSalDeleteSurroundingTextRequest( pWindow, const_cast<SalSurroundingTextSelectionChangeEvent *>(static_cast<SalSurroundingTextSelectionChangeEvent const *>(pEvent)) ); + break; case SalEvent::SurroundingTextSelectionChange: { SalSurroundingTextSelectionChangeEvent const * pEvt diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx index 1bccc46f2131..8c62814bc183 100644 --- a/vcl/unx/gtk3/gtk3gtkframe.cxx +++ b/vcl/unx/gtk3/gtk3gtkframe.cxx @@ -58,7 +58,6 @@ #include <cstdlib> #include <cmath> -#include <com/sun/star/accessibility/XAccessibleEditableText.hpp> #include <com/sun/star/awt/MouseButton.hpp> #include <com/sun/star/datatransfer/dnd/DNDConstants.hpp> @@ -4360,22 +4359,6 @@ void GtkSalFrame::IMHandler::signalIMPreeditEnd( GtkIMContext*, gpointer im_hand pThis->updateIMSpotLocation(); } -static uno::Reference<accessibility::XAccessibleEditableText> lcl_GetxText(vcl::Window *pFocusWin) -{ - uno::Reference<accessibility::XAccessibleEditableText> xText; - try - { - uno::Reference< accessibility::XAccessible > xAccessible( pFocusWin->GetAccessible() ); - if (xAccessible.is()) - xText = FindFocusedEditableText(xAccessible->getAccessibleContext()); - } - catch(const uno::Exception&) - { - TOOLS_WARN_EXCEPTION( "vcl.gtk3", "Exception in getting input method surrounding text"); - } - return xText; -} - gboolean GtkSalFrame::IMHandler::signalIMRetrieveSurrounding( GtkIMContext* pContext, gpointer im_handler ) { GtkSalFrame::IMHandler* pThis = static_cast<GtkSalFrame::IMHandler*>(im_handler); @@ -4396,7 +4379,7 @@ gboolean GtkSalFrame::IMHandler::signalIMRetrieveSurrounding( GtkIMContext* pCon Selection GtkSalFrame::CalcDeleteSurroundingSelection(const OUString& rSurroundingText, int nCursorIndex, int nOffset, int nChars) { - Selection aInvalid(-1, -1); + Selection aInvalid(SAL_MAX_UINT32, SAL_MAX_UINT32); if (nCursorIndex == -1) return aInvalid; @@ -4445,42 +4428,37 @@ Selection GtkSalFrame::CalcDeleteSurroundingSelection(const OUString& rSurroundi } gboolean GtkSalFrame::IMHandler::signalIMDeleteSurrounding( GtkIMContext*, gint offset, gint nchars, - gpointer /*im_handler*/ ) + gpointer im_handler ) { - vcl::Window *pFocusWin = Application::GetFocusWindow(); - if (!pFocusWin) - return true; + GtkSalFrame::IMHandler* pThis = static_cast<GtkSalFrame::IMHandler*>(im_handler); - uno::Reference<accessibility::XAccessibleEditableText> xText = lcl_GetxText(pFocusWin); - if (xText.is()) - { - sal_Int32 nPosition = xText->getCaretPosition(); - // #i111768# range checking - sal_Int32 nDeletePos = nPosition + offset; - sal_Int32 nDeleteEnd = nDeletePos + nchars; - if (nDeletePos < 0) - nDeletePos = 0; - if (nDeleteEnd < 0) - nDeleteEnd = 0; - if (nDeleteEnd > xText->getCharacterCount()) - nDeleteEnd = xText->getCharacterCount(); - - xText->deleteText(nDeletePos, nDeleteEnd); - //tdf91641 adjust cursor if deleted chars shift it forward (normal case) - if (nDeletePos < nPosition) - { - if (nDeleteEnd <= nPosition) - nPosition = nPosition - (nDeleteEnd - nDeletePos); - else - nPosition = nDeletePos; + // First get the surrounding text + SalSurroundingTextRequestEvent aSurroundingTextEvt; + aSurroundingTextEvt.maText.clear(); + aSurroundingTextEvt.mnStart = aSurroundingTextEvt.mnEnd = 0; - if (xText->getCharacterCount() >= nPosition) - xText->setCaretPosition( nPosition ); - } - return true; - } + SolarMutexGuard aGuard; + pThis->m_pFrame->CallCallback(SalEvent::SurroundingTextRequest, &aSurroundingTextEvt); + + // Turn offset, nchars into a utf-16 selection + Selection aSelection = GtkSalFrame::CalcDeleteSurroundingSelection(aSurroundingTextEvt.maText, + aSurroundingTextEvt.mnStart, + offset, nchars); + Selection aInvalid(SAL_MAX_UINT32, SAL_MAX_UINT32); + if (aSelection == aInvalid) + return false; - return false; + SalSurroundingTextSelectionChangeEvent aEvt; + aEvt.mnStart = aSelection.Min(); + aEvt.mnEnd = aSelection.Max(); + + pThis->m_pFrame->CallCallback(SalEvent::DeleteSurroundingTextRequest, &aEvt); + + aSelection = Selection(aEvt.mnStart, aEvt.mnEnd); + if (aSelection == aInvalid) + return false; + + return true; } Size GtkSalDisplay::GetScreenSize( int nDisplayScreen ) diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 6ee16f782503..e9a7070de4d0 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -13849,7 +13849,7 @@ public: sal_Int32 nCursorIndex = pThis->m_pArea->im_context_get_surrounding(sSurroundingText); Selection aSelection = GtkSalFrame::CalcDeleteSurroundingSelection(sSurroundingText, nCursorIndex, nOffset, nChars); - if (aSelection != Selection(-1, -1)) + if (aSelection != Selection(SAL_MAX_UINT32, SAL_MAX_UINT32)) bRet = pThis->m_pArea->im_context_delete_surrounding(aSelection); return bRet; } |