/* -*- 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 .
*/
class FloatingWindow::ImplData
{ public:
ImplData();
VclPtr<ToolBox> mpBox;
AbsoluteScreenPixelRectangle maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
Point maPos; // position of the floating window wrt. parent
Point maLOKTwipsPos; ///< absolute position of the floating window in the document - in twips (for toplevel floating windows).
};
if (!pParent)
pParent = ImplGetSVData()->maFrameData.mpAppWin;
SAL_WARN_IF(!pParent, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists");
// no Border, then we don't need a border window if (!nStyle)
{
mpWindowImpl->mbOverlapWin = true;
nStyle |= WB_DIALOGCONTROL;
ImplInit(pParent, nStyle, nullptr);
} else
{ if (!(nStyle & WB_NODIALOGCONTROL))
nStyle |= WB_DIALOGCONTROL;
if (mpImplData)
{ if( mbPopupModeCanceled ) // indicates that ESC key was pressed // will be handled in Window::ImplGrabFocus()
SetDialogControlFlags( GetDialogControlFlags() | DialogControlFlags::FloatWinPopupModeEndCancel );
AbsoluteScreenPixelRectangle devRectRTL( devRect ); if( bRTL ) // create a rect that can be compared to desktop coordinates
devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect ); if( Application::GetScreenCount() > 1 )
aScreenRect = Application::GetScreenPosSizePixel(
Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );
FloatWinPopupFlags nArrangeAry[5];
sal_uInt16 nArrangeAttempts = 5;
AbsoluteScreenPixelPoint e1,e2; // the common edge between the item rect and the floating window
// no further adjustment for LibreOfficeKit if (bLOKActive) break;
// set bBreak true on last attempt if (nArrangeIndex + 1 == nArrangeAttempts)
bBreak = true;
// adjust if necessary if (bBreak)
{ if (aPos.Y() + aSize.Height() > aScreenRect.Bottom())
{
aPos.setY(devRect.Bottom() - aSize.Height() + 1); if (aPos.Y() < aScreenRect.Top())
aPos.setY(aScreenRect.Top()); // move to the right or left of the parent if possible if (devRect.Right() + 4 + aSize.Width() < aScreenRect.Right())
aPos.setX(devRect.Right() + 4); elseif (devRect.Left() - 4 - aSize.Width() > aScreenRect.Left())
aPos.setX(devRect.Left() - 4 - aSize.Width());
} else
{ if( bRTL )
{ if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
aPos.AdjustX( -(aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1) );
} elseif ( aPos.X()+aSize.Width() > aScreenRect.Right() )
{
aPos.setX( devRect.Right()-aSize.Width()+1 ); if ( aPos.X() < aScreenRect.Left() )
aPos.setX( aScreenRect.Left() );
}
}
}
if ( bBreak ) break;
}
rArrangeIndex = nArrangeIndex;
Point aPosOut = pW->AbsoluteScreenToOutputPixel( aPos );
// store a cliprect that can be used to clip the common edge of the itemrect and the floating window if( pFloatingWindow && pFloatingWindow->mpImplData->mpBox )
{
pFloatingWindow->mpImplData->maItemEdgeClipRect =
AbsoluteScreenPixelRectangle( e1, e2 );
}
if (bLOKActive && pLOKTwipsPos)
{ if (pW->IsMapModeEnabled() || pW->GetMapMode().GetMapUnit() == MapUnit::MapPixel)
{ // if we use pW->LogicToLogic(aPos, pW->GetMapMode(), MapMode(MapUnit::MapTwip)), // for pixel conversions when map mode is not enabled, we get // a 20 twips per pixel conversion since LogicToLogic uses // a fixed 72 dpi value, instead of a correctly computed output // device dpi or at least the most commonly used 96 dpi value; // and anyway the following is what we already do in // ScGridWindow::LogicInvalidate when map mode is not enabled.
do
{ // compute the floating window's size in absolute screen coordinates
// use the border window to have the exact position
vcl::Window *pBorderWin = pWin->GetWindow( GetWindowType::Border ); if (!pBorderWin) break;
// the top-left corner in output coordinates ie (0,0)
AbsoluteScreenPixelRectangle devRect( pBorderWin->ImplOutputToUnmirroredAbsoluteScreenPixel( tools::Rectangle( Point(), pBorderWin->GetSizePixel()) ) ) ; if ( devRect.Contains( aAbsolute ) )
{ // inside the window return pWin;
}
// test, if mouse is in rectangle, (this is typically the rect of the active // toolbox item or similar) // note: maFloatRect is set in FloatingWindow::StartPopupMode() and // is already in absolute device coordinates if ( pWin->maFloatRect.Contains( aAbsolute ) )
{
rbHitTestInsideRect = true; return pWin;
}
VclPtr<vcl::Window> pParent = GetParentWithLOKNotifier(); if (pParent)
{ if (nType == StateChangedType::InitShow)
{
std::vector<vcl::LOKPayloadItem> aItems; if (pParent == this)
{ // we are a toplevel window, let's so far pretend to be a // dialog - but maybe we'll need a separate type for this // later if (mbInPopupMode)
aItems.emplace_back("type", "dropdown"); else
aItems.emplace_back("type", "dialog");
aItems.emplace_back("position", mpImplData->maLOKTwipsPos.toString()); // twips
} else
{
SetLOKNotifier(pParent->GetLOKNotifier()); if (dynamic_cast<HelpTextWindow*>(this))
aItems.emplace_back("type", "tooltip"); else
aItems.emplace_back("type", "child");
aItems.emplace_back("parentId", OString::number(pParent->GetLOKWindowId())); if (mbInPopupMode)
aItems.emplace_back("position", mpImplData->maPos.toString()); // pixels else// mpImplData->maPos is not set
aItems.emplace_back("position", GetPosPixel().toString());
// avoid close on focus change for decorated floating windows only if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
nFlags |= FloatWinPopupFlags::NoAppFocusClose;
// compute window position according to flags and arrangement
sal_uInt16 nArrangeIndex;
DoInitialLayout();
mpImplData->maPos = ImplCalcPos(this, rRect, nFlags, nArrangeIndex, &mpImplData->maLOKTwipsPos);
SetPosPixel( mpImplData->maPos );
ImplGetFrame()->PositionByToolkit(rRect, nFlags);
// set data and display window // convert maFloatRect to absolute device coordinates // so they can be compared across different frames // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
maFloatRect = FloatingWindow::ImplConvertToAbsPos(GetParent(), rRect);
// add FloatingWindow to list of windows that are in popup mode
ImplSVData* pSVData = ImplGetSVData();
mpNextFloat = pSVData->mpWinData->mpFirstFloat;
pSVData->mpWinData->mpFirstFloat = this; bool bGrabFocus(nFlags & FloatWinPopupFlags::GrabFocus); if (bGrabFocus)
{ // force key input even without focus (useful for menus)
mbGrabFocus = true;
mxPrevFocusWin = Window::SaveFocus();
mpWindowImpl->mpFrameData->mbHasFocus = true;
}
Show( true, ShowFlags::NoActivate ); if (bGrabFocus)
GrabFocus();
}
mbInCleanUp = true; // prevent killing this window due to focus change while working with it
if (!(nFlags & FloatWinPopupEndFlags::NoCloseChildren))
{ // stop the PopupMode also for all PopupMode windows created after us
std::vector<VclPtr<FloatingWindow>> aCancelFloats; // stop the PopupMode also for all following PopupMode windows for (auto pFloat = pSVData->mpWinData->mpFirstFloat;
pFloat != nullptr && pFloat != this;
pFloat = pFloat->mpNextFloat)
aCancelFloats.push_back(pFloat); for (auto & it : aCancelFloats)
it->EndPopupMode(FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::NoCloseChildren);
}
// delete window from the list
pSVData->mpWinData->mpFirstFloat = mpNextFloat;
mpNextFloat = nullptr;
// hide window again if it was not deleted if (!mbPopupModeTearOff)
Show( false, ShowFlags::NoFocusChange );
if (HasChildPathFocus() && xFocusId != nullptr)
{ // restore focus to previous focus window if we still have the focus
Window::EndSaveFocus(xFocusId);
} elseif ( pSVData->mpWinData->mpFocusWin && pSVData->mpWinData->mpFirstFloat &&
ImplIsWindowOrChild( pSVData->mpWinData->mpFocusWin ) )
{ // maybe pass focus on to a suitable FloatingWindow
pSVData->mpWinData->mpFirstFloat->GrabFocus();
}
// set ToolBox again to normal if (mpImplData && mpImplData->mpBox)
{
mpImplData->mpBox->ImplFloatControl( false, this ); // if the parent ToolBox is in popup mode, it should be closed too. if ( GetDockingManager()->IsInPopupMode( mpImplData->mpBox ) )
nFlags |= FloatWinPopupEndFlags::CloseAll;
mpImplData->mpBox = nullptr;
}
// call PopupModeEnd-Handler depending on parameter if ( !(nFlags & FloatWinPopupEndFlags::DontCallHdl) )
ImplCallPopupModeEnd();
// close all other windows depending on parameter if ( nFlags & FloatWinPopupEndFlags::CloseAll )
{ if ( !(nPopupModeFlags & FloatWinPopupFlags::NewLevel) )
{ if (pSVData->mpWinData->mpFirstFloat)
{
FloatingWindow* pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat();
pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
}
}
}
void FloatingWindow::AddPopupModeWindow(vcl::Window* pWindow)
{ // !!! up-to-now only 1 window and not yet a list
mpFirstPopupModeWin = pWindow;
}
bool SystemWindow::UpdatePositionData()
{ // tdf#164337 don't update position data when waiting for a system resize // When entering and exiting LibreOffice's internal full screen mode, // updating position data causes the "exit full screen" floating // toolbar to migrate after cycle. if (mpWindowImpl->mbWaitSystemResize) returnfalse;
auto pWin = ImplGetParent(); if (pWin)
{ // Simulate Move, so the relative position of the floating window will be recalculated
pWin->ImplCallMove(); returntrue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.