/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * 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/. */ #include #include #include #include #include #include #include #include #include #include #include css::uno::Reference& LokStarMathHelper::GetXController() { if (!mxController && mpViewShell) { if (const SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient()) { if (const auto& xEmbObj = pIPClient->GetObject()) { css::uno::Reference xComp(xEmbObj->getComponent(), css::uno::UNO_QUERY); if (xComp && xComp->supportsService("com.sun.star.formula.FormulaProperties")) if (css::uno::Reference xModel{ xComp, css::uno::UNO_QUERY }) mxController = xModel->getCurrentController(); } } } return mxController; } namespace { // Find a child SmGraphicWindow* vcl::Window* FindSmGraphicWindow(vcl::Window* pWin) { if (!pWin) return nullptr; if (pWin->IsStarMath()) return pWin; pWin = pWin->GetWindow(GetWindowType::FirstChild); while (pWin) { if (vcl::Window* pSmGraphicWindow = FindSmGraphicWindow(pWin)) return pSmGraphicWindow; pWin = pWin->GetWindow(GetWindowType::Next); } return nullptr; } // Find a child window that corresponds to SmGraphicWidget vcl::Window* FindChildSmGraphicWidgetWindow(vcl::Window* pWin) { if (!pWin) return nullptr; // The needed window is a VclDrawingArea if (dynamic_cast(pWin)) return pWin; pWin = pWin->GetWindow(GetWindowType::FirstChild); while (pWin) { if (vcl::Window* pSmGraphicWidgetWindow = FindChildSmGraphicWidgetWindow(pWin)) return pSmGraphicWidgetWindow; pWin = pWin->GetWindow(GetWindowType::Next); } return nullptr; } } vcl::Window* LokStarMathHelper::GetGraphicWindow() { if (!mpGraphicWindow) { if (const css::uno::Reference& xController = GetXController()) { if (const css::uno::Reference xFrame = xController->getFrame()) { css::uno::Reference xDockerWin = xFrame->getContainerWindow(); mpGraphicWindow.set(FindSmGraphicWindow(VCLUnoHelper::GetWindow(xDockerWin))); } } } return mpGraphicWindow.get(); } vcl::Window* LokStarMathHelper::GetWidgetWindow() { if (!mpWidgetWindow) mpWidgetWindow.set(FindChildSmGraphicWidgetWindow(GetGraphicWindow())); return mpWidgetWindow.get(); } tools::Rectangle LokStarMathHelper::GetBoundingBox() { if (mpViewShell) { if (SfxInPlaceClient* pIPClient = mpViewShell->GetIPClient()) { if (vcl::Window* pRootWin = pIPClient->GetEditWin()) { if (vcl::Window* pWindow = GetWidgetWindow()) { // In all cases, the following code fragment // returns the bounding box in twips. // Note: the correct mapmode (representing document zoom) is provided by // GraphicWindow, not WidgetWindow const MapMode& aMapMode = GetGraphicWindow()->GetMapMode(); const auto & [ m, d ] = o3tl::getConversionMulDiv(o3tl::Length::px, o3tl::Length::twip); const Fraction& scaleX = aMapMode.GetScaleX(); const Fraction& scaleY = aMapMode.GetScaleY(); const auto nXNum = m * scaleX.GetDenominator(); const auto nXDen = d * scaleX.GetNumerator(); const auto nYNum = m * scaleY.GetDenominator(); const auto nYDen = d * scaleY.GetNumerator(); Point aOffset = pWindow->GetOffsetPixelFrom(*pRootWin).scale(nXNum, nXDen, nYNum, nYDen); Size aSize = pWindow->GetSizePixel().scale(nXNum, nXDen, nYNum, nYDen); return { aOffset, aSize }; } } } } return {}; } bool LokStarMathHelper::postMouseEvent(int nType, int nX, int nY, int nCount, int nButtons, int nModifier, double fScaleX, double fScaleY) { if (vcl::Window* pWindow = GetWidgetWindow()) { Point aMousePos(nX, nY); tools::Rectangle rBBox = GetBoundingBox(); if (rBBox.Contains(aMousePos)) { int nWinX = nX - rBBox.Left(); int nWinY = nY - rBBox.Top(); // window expects pixels, but the conversion factor // can depend on the client zoom Point aPos(nWinX * fScaleX, nWinY * fScaleY); LokMouseEventData aMouseEventData(nType, aPos, nCount, MouseEventModifiers::SIMPLECLICK, nButtons, nModifier); SfxLokHelper::postMouseEventAsync(pWindow, aMouseEventData); return true; } } return false; } /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */