vcl: cursor invalidation for form controls

Form controls need to send cursor invalidation when, to make it
possible to show the cursor in online, when we are editing an edit
box in the document.

Change-Id: I17c74b8183ba8caf06898019908bf0c2879d49d0
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189178
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190804
Tested-by: Jenkins
Reviewed-by: Gökay ŞATIR <gokaysatir@collabora.com>
This commit is contained in:
Tomaž Vajngerl
2025-09-11 15:43:17 +02:00
committed by Gökay ŞATIR
parent 7a036a6458
commit 0b18630a51
12 changed files with 108 additions and 30 deletions
+5 -1
View File
@@ -53,7 +53,8 @@
#include <sal/log.hxx>
#include <algorithm>
#include <vcl/window.hxx>
#include <toolkit/helper/vclunohelper.hxx>
namespace frm
{
using namespace ::com::sun::star::uno;
@@ -270,6 +271,9 @@ void SAL_CALL OControl::createPeer(const Reference<XToolkit>& _rxToolkit, const
{
m_xControl->createPeer( _rxToolkit, _rxParent );
impl_resetStateGuard_nothrow();
VclPtr<vcl::Window> pVclPeer = VCLUnoHelper::GetWindow(getPeer());
pVclPeer->SetFormControl(true);
}
}
+2
View File
@@ -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
+3
View File
@@ -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().
+3
View File
@@ -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;
};
+2 -1
View File
@@ -1325,7 +1325,8 @@ public:
const OUString& rAction,
const std::vector<vcl::LOKPayloadItem>& rPayload = std::vector<vcl::LOKPayloadItem>()) 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:
+2
View File
@@ -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;
+10
View File
@@ -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
+5
View File
@@ -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);
+1
View File
@@ -393,6 +393,7 @@ public:
mbSecondary:1,
mbNonHomogeneous:1,
mbDoubleBufferingRequested:1;
bool mbIsFormControl : 1 = false;
rtl::Reference< DNDListenerContainer > mxDNDListenerContainer;
+4
View File
@@ -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();
+60 -28
View File
@@ -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<vcl::Window> 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<vcl::LOKPayloadItem> 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<vcl::LOKPayloadItem> 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 )
+11
View File
@@ -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;