offapi/UnoApi_offapi.mk                                 |    1 
 offapi/com/sun/star/text/XTextViewTextRangeSupplier.idl |   46 ++++++++++++++++
 sw/qa/uibase/uno/uno.cxx                                |   43 ++++++++++++++
 sw/source/uibase/inc/unotxvw.hxx                        |    6 ++
 sw/source/uibase/uno/unotxvw.cxx                        |   27 +++++++++
 5 files changed, 123 insertions(+)

New commits:
commit 8e7dc248f2787df0e658c4ece33220944fca7f16
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Mar 9 11:49:06 2021 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Mar 9 20:12:24 2021 +0100

    sw: add UNO API to find the closest doc model position based on pixel 
position
    
    The use-case is drag&drop: if an UNO API client registers its drag&drop
    listener, then it gets a DropTargetDropEvent and has to decide if it
    wants to handle that event or allow Writer to handle it. In case it
    decides to handle the event, it would be good to able to e.g. insert a
    string at the point where the Writer UI indicates it to the user. But
    DropTargetDropEvent only exposes a pixel position and Writer requires
    you to have an XTextRange when inserting content.
    
    Fix the problem by introducing a new createTextRangeByPixelPosition()
    which first does a pixel -> logic coordinate conversion (this is
    window-specific, in case you have multiple windows), then picks the doc
    model position which is the closest to a logic coordinate.
    
    Change-Id: I6a8e69e3c39b9d99209342469653c0e0bd99bf53
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112201
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/offapi/UnoApi_offapi.mk b/offapi/UnoApi_offapi.mk
index 020149df1311..21adff7c48f1 100644
--- a/offapi/UnoApi_offapi.mk
+++ b/offapi/UnoApi_offapi.mk
@@ -3841,6 +3841,7 @@ $(eval $(call 
gb_UnoApi_add_idlfiles,offapi,com/sun/star/text,\
        XTextViewCursor \
        XTextViewCursorSupplier \
        XWordCursor \
+       XTextViewTextRangeSupplier \
 ))
 $(eval $(call gb_UnoApi_add_idlfiles,offapi,com/sun/star/ucb,\
        AlreadyInitializedException \
diff --git a/offapi/com/sun/star/text/XTextViewTextRangeSupplier.idl 
b/offapi/com/sun/star/text/XTextViewTextRangeSupplier.idl
new file mode 100644
index 000000000000..57adf359f756
--- /dev/null
+++ b/offapi/com/sun/star/text/XTextViewTextRangeSupplier.idl
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+#ifndef __com_sun_star_text_XTextViewTextRangeSupplier_idl__
+#define __com_sun_star_text_XTextViewTextRangeSupplier_idl__
+
+#include <com/sun/star/uno/XInterface.idl>
+
+#include <com/sun/star/text/awt/Point.idl>
+#include <com/sun/star/text/XTextRange.idl>
+
+module com {  module sun {  module star {  module text {
+
+/** supplies access to a document model position at a view-dependent pixel 
position.
+
+    @since LibreOffice 7.2
+ */
+interface XTextViewTextRangeSupplier: com::sun::star::uno::XInterface
+{
+    /** @returns
+                the text range of the document position.
+     */
+    com::sun::star::text::XTextRange createTextRangeByPixelPosition([in] 
com::sun::star::awt::Point PixelPosition);
+
+};
+
+}; }; }; };
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/qa/uibase/uno/uno.cxx b/sw/qa/uibase/uno/uno.cxx
index 01dadbc80fee..f4b337d8f9d2 100644
--- a/sw/qa/uibase/uno/uno.cxx
+++ b/sw/qa/uibase/uno/uno.cxx
@@ -9,10 +9,18 @@
 
 #include <swmodeltestbase.hxx>
 
+#include <com/sun/star/frame/XModel2.hpp>
+#include <com/sun/star/text/XTextViewTextRangeSupplier.hpp>
 #include <com/sun/star/util/XCloseable.hpp>
 
 #include <vcl/scheduler.hxx>
 
+#include <docsh.hxx>
+#include <edtwin.hxx>
+#include <unotextrange.hxx>
+#include <view.hxx>
+#include <wrtsh.hxx>
+
 constexpr OUStringLiteral DATA_DIRECTORY = u"/sw/qa/uibase/uno/data/";
 
 /// Covers sw/source/uibase/uno/ fixes.
@@ -47,6 +55,41 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, 
testCondFieldCachedValue)
     getParagraph(2, "1");
 }
 
+CPPUNIT_TEST_FIXTURE(SwUibaseUnoTest, testCreateTextRangeByPixelPosition)
+{
+    // Given a document with 2 characters, and the pixel position of the point 
between them:
+    SwDoc* pDoc = createSwDoc();
+    SwDocShell* pDocShell = pDoc->GetDocShell();
+    SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+    pWrtShell->Insert2("AZ");
+    pWrtShell->Left(CRSR_SKIP_CHARS, /*bSelect=*/false, 1, 
/*bBasicCall=*/false);
+    Point aLogic = pWrtShell->GetCharRect().Center();
+    SwView* pView = pDocShell->GetView();
+    SwEditWin& rEditWin = pView->GetEditWin();
+    Point aPixel = rEditWin.LogicToPixel(aLogic);
+
+    // When converting that pixel position to a document model position (text 
range):
+    uno::Reference<frame::XModel2> xModel(mxComponent, uno::UNO_QUERY);
+    uno::Reference<container::XEnumeration> xControllers = 
xModel->getControllers();
+    uno::Reference<text::XTextViewTextRangeSupplier> 
xController(xControllers->nextElement(),
+                                                                 
uno::UNO_QUERY);
+    awt::Point aPoint(aPixel.getX(), aPixel.getY());
+    uno::Reference<text::XTextRange> xTextRange
+        = xController->createTextRangeByPixelPosition(aPoint);
+
+    // Then make sure that text range points after the first character:
+    auto pTextRange = dynamic_cast<SwXTextRange*>(xTextRange.get());
+    SwPaM aPaM(pDoc->GetNodes());
+    pTextRange->GetPositions(aPaM);
+    sal_Int32 nActual = aPaM.GetPoint()->nContent.GetIndex();
+    // Without the needed PixelToLogic() call in place, this test would have 
failed with:
+    // - Expected: 1
+    // - Actual  : 0
+    // i.e. the returned text range pointed before the first character, not 
between the first and
+    // the second character.
+    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), nActual);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/inc/unotxvw.hxx b/sw/source/uibase/inc/unotxvw.hxx
index 473633defd9e..1f52f7ea6230 100644
--- a/sw/source/uibase/inc/unotxvw.hxx
+++ b/sw/source/uibase/inc/unotxvw.hxx
@@ -23,6 +23,7 @@
 #include <comphelper/interfacecontainer2.hxx>
 #include <com/sun/star/text/XTextViewCursor.hpp>
 #include <com/sun/star/text/XTextViewCursorSupplier.hpp>
+#include <com/sun/star/text/XTextViewTextRangeSupplier.hpp>
 #include <com/sun/star/text/XRubySelection.hpp>
 #include <com/sun/star/view/XFormLayerAccess.hpp>
 #include <com/sun/star/view/XScreenCursor.hpp>
@@ -52,6 +53,7 @@ class SwXTextView final :
     public css::lang::XServiceInfo,
     public css::view::XFormLayerAccess,
     public css::text::XTextViewCursorSupplier,
+    public css::text::XTextViewTextRangeSupplier,
     public css::text::XRubySelection,
     public css::view::XViewSettingsSupplier,
     public css::beans::XPropertySet,
@@ -101,6 +103,10 @@ public:
     //XTextViewCursorSupplier
     virtual css::uno::Reference< css::text::XTextViewCursor >  SAL_CALL 
getViewCursor() override;
 
+    // XTextViewTextRangeSupplier
+    virtual css::uno::Reference<css::text::XTextRange>
+        SAL_CALL createTextRangeByPixelPosition(const css::awt::Point& 
rPixelPosition) override;
+
     //XViewSettings
     virtual css::uno::Reference< css::beans::XPropertySet >  SAL_CALL 
getViewSettings() override;
 
diff --git a/sw/source/uibase/uno/unotxvw.cxx b/sw/source/uibase/uno/unotxvw.cxx
index e6621293391d..1b805102c6d7 100644
--- a/sw/source/uibase/uno/unotxvw.cxx
+++ b/sw/source/uibase/uno/unotxvw.cxx
@@ -64,6 +64,8 @@
 #include <unotextrange.hxx>
 #include <sfx2/docfile.hxx>
 #include <swdtflvr.hxx>
+#include <rootfrm.hxx>
+#include <edtwin.hxx>
 #include <vcl/svapp.hxx>
 #include <comphelper/processfactory.hxx>
 #include <comphelper/profilezone.hxx>
@@ -133,6 +135,7 @@ Sequence< uno::Type > SAL_CALL SwXTextView::getTypes(  )
             cppu::UnoType<XServiceInfo>::get(),
             cppu::UnoType<XFormLayerAccess>::get(),
             cppu::UnoType<XTextViewCursorSupplier>::get(),
+            cppu::UnoType<XTextViewTextRangeSupplier>::get(),
             cppu::UnoType<XViewSettingsSupplier>::get(),
             cppu::UnoType<XRubySelection>::get(),
             cppu::UnoType<XPropertySet>::get(),
@@ -185,6 +188,11 @@ uno::Any SAL_CALL SwXTextView::queryInterface( const 
uno::Type& aType )
         uno::Reference<text::XTextViewCursorSupplier> xRet = this;
         aRet <<= xRet;
     }
+    else if (aType == cppu::UnoType<text::XTextViewTextRangeSupplier>::get())
+    {
+        uno::Reference<text::XTextViewTextRangeSupplier> xRet = this;
+        aRet <<= xRet;
+    }
     else if(aType == cppu::UnoType<view::XViewSettingsSupplier>::get())
     {
         uno::Reference<view::XViewSettingsSupplier> xRet = this;
@@ -514,6 +522,25 @@ uno::Reference< text::XTextViewCursor >  
SwXTextView::getViewCursor()
     return mxTextViewCursor;
 }
 
+uno::Reference<text::XTextRange>
+SwXTextView::createTextRangeByPixelPosition(const awt::Point& rPixelPosition)
+{
+    SolarMutexGuard aGuard;
+
+    Point aPixelPoint(rPixelPosition.X, rPixelPosition.Y);
+    if (!m_pView)
+        throw RuntimeException();
+
+    Point aLogicPoint = m_pView->GetEditWin().PixelToLogic(aPixelPoint);
+    SwWrtShell& rSh = m_pView->GetWrtShell();
+    SwPosition aPosition(*rSh.GetCurrentShellCursor().GetPoint());
+    rSh.GetLayout()->GetModelPositionForViewPoint(&aPosition, aLogicPoint);
+    uno::Reference<text::XTextRange> xRet
+        = SwXTextRange::CreateXTextRange(*rSh.GetDoc(), aPosition, 
/*pMark=*/nullptr);
+
+    return xRet;
+}
+
 uno::Reference< beans::XPropertySet >  SwXTextView::getViewSettings()
 {
     SolarMutexGuard aGuard;
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to