diff --git a/forms/source/component/FormComponent.cxx b/forms/source/component/FormComponent.cxx index 97ac1280bd91..0492afa4817f 100644 --- a/forms/source/component/FormComponent.cxx +++ b/forms/source/component/FormComponent.cxx @@ -53,7 +53,8 @@ #include #include - +#include +#include namespace frm { using namespace ::com::sun::star::uno; @@ -270,6 +271,9 @@ void SAL_CALL OControl::createPeer(const Reference& _rxToolkit, const { m_xControl->createPeer( _rxToolkit, _rxParent ); impl_resetStateGuard_nothrow(); + + VclPtr pVclPeer = VCLUnoHelper::GetWindow(getPeer()); + pVclPeer->SetFormControl(true); } } diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index b32f775db14b..bee8f3178ae7 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -187,6 +187,8 @@ public: static void notifyDocumentSizeChangedAllViews(vcl::ITiledRenderable* pDoc, bool bInvalidateAll = true); /// Emits a LOK_CALLBACK_DOCUMENT_SIZE_CHANGED for all views of the same document with the same part static void notifyPartSizeChangedAllViews(vcl::ITiledRenderable* pDoc, int nPart); + /// Emits a LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR + static void notifyCursorInvalidation(SfxViewShell const* pThisView, tools::Rectangle const * pRect, bool bControlEvent); /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed. static void notifyInvalidation(SfxViewShell const* pThisView, int nPart, tools::Rectangle const *); /// Emits a LOK_CALLBACK_INVALIDATE_TILES, but tweaks it according to setOptionalFeatures() if needed diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index ee35c7195278..1748644dff75 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -434,6 +434,9 @@ public: /// ILibreOfficeKitNotifier. Emits a LOK_CALLBACK_INVALIDATE_TILES. virtual void notifyInvalidation(tools::Rectangle const *) const override; + /// ILibreOfficeKitNotifier. + virtual void notifyCursorInvalidation(tools::Rectangle const *, bool bControlEvent) const override; + /// See OutlinerViewShell::NotifyOtherViews(). void NotifyOtherViews(int nType, const OString& rKey, const OString& rPayload) override; /// See OutlinerViewShell::NotifyOtherView(). diff --git a/include/vcl/IDialogRenderable.hxx b/include/vcl/IDialogRenderable.hxx index 79ed78765212..aaa17cd7991c 100644 --- a/include/vcl/IDialogRenderable.hxx +++ b/include/vcl/IDialogRenderable.hxx @@ -40,6 +40,9 @@ public: /// Emits a LOK_CALLBACK_INVALIDATE_TILES. virtual void notifyInvalidation(tools::Rectangle const *) const = 0; + /// Emits a LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR. + virtual void notifyCursorInvalidation(tools::Rectangle const *, bool bControlEvent) const = 0; + /// Debugging virtual OString dumpNotifyState() const = 0; }; diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx index 058402d4b5e1..ef908f61931b 100644 --- a/include/vcl/svapp.hxx +++ b/include/vcl/svapp.hxx @@ -1325,7 +1325,8 @@ public: const OUString& rAction, const std::vector& rPayload = std::vector()) const override; virtual void libreOfficeKitViewCallback(int nType, const OString& pPayload) const override; - virtual void notifyInvalidation(tools::Rectangle const *) const override; + virtual void notifyInvalidation(tools::Rectangle const* pRect) const override; + virtual void notifyCursorInvalidation(tools::Rectangle const* pRect, bool bControlEvent) const override; virtual OString dumpNotifyState() const override; private: diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx index 2176d4e7b992..8369693dd05f 100644 --- a/include/vcl/window.hxx +++ b/include/vcl/window.hxx @@ -768,6 +768,8 @@ public: void SetType( WindowType eType ); WindowType GetType() const; std::string_view GetTypeName() const; + bool IsFormControl() const; + void SetFormControl(bool bFormControl); bool IsSystemWindow() const; SAL_DLLPRIVATE bool IsDockingWindow() const; bool IsDialog() const; diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index d27e0cbca0d9..495eefd13029 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -679,6 +679,16 @@ void SfxLokHelper::notifyWindow(const SfxViewShell* pThisView, pThisView->libreOfficeKitViewCallback(LOK_CALLBACK_WINDOW, s); } +void SfxLokHelper::notifyCursorInvalidation(SfxViewShell const* pThisView, tools::Rectangle const* pRect, bool bControlEvent) +{ + int nViewId = SfxLokHelper::getView(*pThisView); + OString sPayload = OString::Concat("{ \"viewId\": \"") + OString::number(nViewId) + "\", \"rectangle\": \"" + pRect->toString(); + if (bControlEvent) + sPayload += "\", \"controlEvent\": true"; + sPayload += " }"; + pThisView->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, sPayload); +} + void SfxLokHelper::notifyInvalidation(SfxViewShell const* pThisView, tools::Rectangle const* pRect) { // -1 means all parts diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx index 98d3ee3a237d..a8e1e6237579 100644 --- a/sfx2/source/view/viewsh.cxx +++ b/sfx2/source/view/viewsh.cxx @@ -3565,6 +3565,11 @@ void SfxViewShell::notifyInvalidation(tools::Rectangle const* pRect) const SfxLokHelper::notifyInvalidation(this, pRect); } +void SfxViewShell::notifyCursorInvalidation(tools::Rectangle const* pRect, bool bControlEvent) const +{ + SfxLokHelper::notifyCursorInvalidation(this, pRect, bControlEvent); +} + void SfxViewShell::NotifyOtherViews(int nType, const OString& rKey, const OString& rPayload) { SfxLokHelper::notifyOtherViews(this, nType, rKey, rPayload); diff --git a/vcl/inc/window.h b/vcl/inc/window.h index 36ccb9341457..1fd18186ac71 100644 --- a/vcl/inc/window.h +++ b/vcl/inc/window.h @@ -393,6 +393,7 @@ public: mbSecondary:1, mbNonHomogeneous:1, mbDoubleBufferingRequested:1; + bool mbIsFormControl : 1 = false; rtl::Reference< DNDListenerContainer > mxDNDListenerContainer; diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 124dc4289f29..d60d5fa59aea 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -341,6 +341,10 @@ void Application::notifyInvalidation(tools::Rectangle const* /*pRect*/) const { } +void Application::notifyCursorInvalidation(tools::Rectangle const* /*pRect*/, bool /*bControlEvent*/) const +{ +} + void Application::Execute() { ImplSVData* pSVData = ImplGetSVData(); diff --git a/vcl/source/window/cursor.cxx b/vcl/source/window/cursor.cxx index 6c9d7577aa41..2437fc321348 100644 --- a/vcl/source/window/cursor.cxx +++ b/vcl/source/window/cursor.cxx @@ -241,7 +241,38 @@ void vcl::Cursor::ImplDoShow( bool bDrawDirect, bool bRestore ) } } -void vcl::Cursor::LOKNotify( vcl::Window* pWindow, const OUString& rAction ) +namespace +{ + +tools::Rectangle calcualteCursorRect(Point const& rPosition, Size const rSize, vcl::Window* pWindow, vcl::Window* pParent) +{ + Point aPositionPixel = pWindow->LogicToPixel(rPosition); + const tools::Long nX = pWindow->GetOutOffXPixel() + aPositionPixel.X() - pParent->GetOutOffXPixel(); + const tools::Long nY = pWindow->GetOutOffYPixel() + aPositionPixel.Y() - pParent->GetOutOffYPixel(); + + Size aSizePixel = pWindow->LogicToPixel(rSize); + if (!aSizePixel.Width()) + aSizePixel.setWidth( pWindow->GetSettings().GetStyleSettings().GetCursorSize() ); + + Point aPosition(nX, nY); + + if (pWindow->IsRTLEnabled() && pWindow->GetOutDev() && pParent->GetOutDev() + && !pWindow->GetOutDev()->ImplIsAntiparallel()) + pParent->GetOutDev()->ReMirror(aPosition); + + if (!pWindow->IsRTLEnabled() && pWindow->GetOutDev() && pParent->GetOutDev() + && pWindow->GetOutDev()->ImplIsAntiparallel()) + { + pWindow->GetOutDev()->ReMirror(aPosition); + pParent->GetOutDev()->ReMirror(aPosition); + } + + return tools::Rectangle(aPosition, aSizePixel); +} + +} // end anonymous namespace + +void vcl::Cursor::LOKNotify(vcl::Window* pWindow, const OUString& rAction) { VclPtr pParent = pWindow->GetParentWithLOKNotifier(); if (!pParent) @@ -251,39 +282,40 @@ void vcl::Cursor::LOKNotify( vcl::Window* pWindow, const OUString& rAction ) assert(mpData && "Require ImplCursorData"); assert(comphelper::LibreOfficeKit::isActive()); - if (comphelper::LibreOfficeKit::isDialogPainting()) - return; - const vcl::ILibreOfficeKitNotifier* pNotifier = pParent->GetLOKNotifier(); - std::vector aItems; - if (rAction == "cursor_visible") - aItems.emplace_back("visible", mpData->mbCurVisible ? "true" : "false"); - else if (rAction == "cursor_invalidate") + + if (pWindow->IsFormControl() || (pWindow->GetParent() && pWindow->GetParent()->IsFormControl())) { - const tools::Long nX = pWindow->GetOutOffXPixel() + pWindow->LogicToPixel(GetPos()).X() - pParent->GetOutOffXPixel(); - const tools::Long nY = pWindow->GetOutOffYPixel() + pWindow->LogicToPixel(GetPos()).Y() - pParent->GetOutOffYPixel(); - Size aSize = pWindow->LogicToPixel(GetSize()); - if (!aSize.Width()) - aSize.setWidth( pWindow->GetSettings().GetStyleSettings().GetCursorSize() ); - - Point aPos(nX, nY); - - if (pWindow->IsRTLEnabled() && pWindow->GetOutDev() && pParent->GetOutDev() - && !pWindow->GetOutDev()->ImplIsAntiparallel()) - pParent->GetOutDev()->ReMirror(aPos); - - if (!pWindow->IsRTLEnabled() && pWindow->GetOutDev() && pParent->GetOutDev() - && pWindow->GetOutDev()->ImplIsAntiparallel()) + if (rAction == "cursor_invalidate") { - pWindow->GetOutDev()->ReMirror(aPos); - pParent->GetOutDev()->ReMirror(aPos); + tools::Rectangle aRect; + if (pWindow->IsFormControl()) + aRect = calcualteCursorRect(GetPos(), GetSize(), pWindow, pWindow->GetParent()); + else + aRect = calcualteCursorRect(GetPos(), GetSize(), pWindow, pWindow->GetParent()->GetParent()); + + OutputDevice* pDevice = mpData->mpWindow->GetOutDev(); + const tools::Rectangle aRectTwip = pDevice->PixelToLogic(aRect, MapMode(MapUnit::MapTwip)); + pNotifier->notifyCursorInvalidation(&aRectTwip, true); } - - const tools::Rectangle aRect(aPos, aSize); - aItems.emplace_back("rectangle", aRect.toString()); } + else + { + if (comphelper::LibreOfficeKit::isDialogPainting()) + return; - pNotifier->notifyWindow(pParent->GetLOKWindowId(), rAction, aItems); + std::vector aItems; + if (rAction == "cursor_visible") + { + aItems.emplace_back("visible", mpData->mbCurVisible ? "true" : "false"); + } + else if (rAction == "cursor_invalidate") + { + const tools::Rectangle aRect = calcualteCursorRect(GetPos(), GetSize(), pWindow, pParent); + aItems.emplace_back("rectangle", aRect.toString()); + } + pNotifier->notifyWindow(pParent->GetLOKWindowId(), rAction, aItems); + } } bool vcl::Cursor::ImplDoHide( bool bSuspend ) diff --git a/vcl/source/window/window2.cxx b/vcl/source/window/window2.cxx index 7b1946360a47..93a81bb259a6 100644 --- a/vcl/source/window/window2.cxx +++ b/vcl/source/window/window2.cxx @@ -1045,6 +1045,17 @@ WindowType Window::GetType() const return WindowType::NONE; } +bool Window::IsFormControl() const +{ + return mpWindowImpl ? mpWindowImpl->mbIsFormControl : false; +} + +void Window::SetFormControl(bool bFormControl) +{ + if (mpWindowImpl) + mpWindowImpl->mbIsFormControl = bFormControl; +} + Dialog* Window::GetParentDialog() const { const vcl::Window *pWindow = this;