/src/libreoffice/vcl/source/window/floatwin.cxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #include <svdata.hxx> |
21 | | #include <brdwin.hxx> |
22 | | #include <window.h> |
23 | | #include <salframe.hxx> |
24 | | #include <helpwin.hxx> |
25 | | |
26 | | #include <comphelper/lok.hxx> |
27 | | #include <sal/log.hxx> |
28 | | #include <tools/mapunit.hxx> |
29 | | #include <vcl/layout.hxx> |
30 | | #include <vcl/svapp.hxx> |
31 | | #include <vcl/wrkwin.hxx> |
32 | | #include <vcl/event.hxx> |
33 | | #include <vcl/toolbox.hxx> |
34 | | #include <vcl/toolkit/floatwin.hxx> |
35 | | #include <vcl/settings.hxx> |
36 | | #include <vcl/IDialogRenderable.hxx> |
37 | | |
38 | | class FloatingWindow::ImplData |
39 | | { |
40 | | public: |
41 | | ImplData(); |
42 | | |
43 | | VclPtr<ToolBox> mpBox; |
44 | | AbsoluteScreenPixelRectangle maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window |
45 | | Point maPos; // position of the floating window wrt. parent |
46 | | Point maLOKTwipsPos; ///< absolute position of the floating window in the document - in twips (for toplevel floating windows). |
47 | | }; |
48 | | |
49 | | FloatingWindow::ImplData::ImplData() |
50 | 0 | { |
51 | 0 | mpBox = nullptr; |
52 | 0 | } |
53 | | |
54 | | const AbsoluteScreenPixelRectangle & FloatingWindow::ImplGetItemEdgeClipRect() |
55 | 0 | { |
56 | 0 | return mpImplData->maItemEdgeClipRect; |
57 | 0 | } |
58 | | |
59 | | void FloatingWindow::ImplInitFloating( vcl::Window* pParent, WinBits nStyle ) |
60 | 0 | { |
61 | 0 | mpImplData.reset(new ImplData); |
62 | |
|
63 | 0 | mpWindowImpl->mbFloatWin = true; |
64 | 0 | mbInCleanUp = false; |
65 | 0 | mbGrabFocus = false; |
66 | |
|
67 | 0 | SAL_WARN_IF(!pParent, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL!"); |
68 | | |
69 | 0 | if (!pParent) |
70 | 0 | pParent = ImplGetSVData()->maFrameData.mpAppWin; |
71 | |
|
72 | 0 | SAL_WARN_IF(!pParent, "vcl", "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists"); |
73 | | |
74 | | // no Border, then we don't need a border window |
75 | 0 | if (!nStyle) |
76 | 0 | { |
77 | 0 | mpWindowImpl->mbOverlapWin = true; |
78 | 0 | nStyle |= WB_DIALOGCONTROL; |
79 | 0 | ImplInit(pParent, nStyle, nullptr); |
80 | 0 | } |
81 | 0 | else |
82 | 0 | { |
83 | 0 | if (!(nStyle & WB_NODIALOGCONTROL)) |
84 | 0 | nStyle |= WB_DIALOGCONTROL; |
85 | |
|
86 | 0 | if (nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_CLOSEABLE | WB_STANDALONE) |
87 | 0 | && !(nStyle & WB_OWNERDRAWDECORATION)) |
88 | 0 | { |
89 | 0 | WinBits nFloatWinStyle = nStyle; |
90 | | // #99154# floaters are not closeable by default anymore, eg fullscreen floater |
91 | | // nFloatWinStyle |= WB_CLOSEABLE; |
92 | 0 | mpWindowImpl->mbFrame = true; |
93 | 0 | mpWindowImpl->mbOverlapWin = true; |
94 | 0 | ImplInit(pParent, nFloatWinStyle & ~WB_BORDER, nullptr); |
95 | 0 | } |
96 | 0 | else |
97 | 0 | { |
98 | 0 | VclPtr<ImplBorderWindow> pBorderWin; |
99 | 0 | BorderWindowStyle nBorderStyle = BorderWindowStyle::Float; |
100 | |
|
101 | 0 | if (nStyle & WB_OWNERDRAWDECORATION) |
102 | 0 | nBorderStyle |= BorderWindowStyle::Frame; |
103 | 0 | else |
104 | 0 | nBorderStyle |= BorderWindowStyle::Overlap; |
105 | |
|
106 | 0 | if ((nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE))) |
107 | 0 | { |
108 | 0 | nBorderStyle |= BorderWindowStyle::Frame; |
109 | 0 | nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable |
110 | 0 | } |
111 | 0 | pBorderWin = VclPtr<ImplBorderWindow>::Create(pParent, nStyle, nBorderStyle); |
112 | 0 | ImplInit(pBorderWin, nStyle & ~WB_BORDER, nullptr); |
113 | 0 | pBorderWin->mpWindowImpl->mpClientWindow = this; |
114 | 0 | pBorderWin->GetBorder(mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, |
115 | 0 | mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder); |
116 | 0 | pBorderWin->SetDisplayActive(true); |
117 | 0 | mpWindowImpl->mpBorderWindow = pBorderWin; |
118 | 0 | mpWindowImpl->mpRealParent = pParent; |
119 | 0 | } |
120 | 0 | } |
121 | 0 | SetActivateMode( ActivateModeFlags::NONE ); |
122 | |
|
123 | 0 | mpNextFloat = nullptr; |
124 | 0 | mpFirstPopupModeWin = nullptr; |
125 | 0 | mnPostId = nullptr; |
126 | 0 | mnTitle = (nStyle & (WB_MOVEABLE | WB_POPUP)) ? FloatWinTitleType::Normal : FloatWinTitleType::NONE; |
127 | 0 | mnOldTitle = mnTitle; |
128 | 0 | mnPopupModeFlags = FloatWinPopupFlags::NONE; |
129 | 0 | mbInPopupMode = false; |
130 | 0 | mbPopupMode = false; |
131 | 0 | mbPopupModeCanceled = false; |
132 | 0 | mbPopupModeTearOff = false; |
133 | 0 | mbMouseDown = false; |
134 | |
|
135 | 0 | ImplInitSettings(); |
136 | 0 | } |
137 | | |
138 | | void FloatingWindow::ImplInitSettings() |
139 | 0 | { |
140 | 0 | const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); |
141 | |
|
142 | 0 | Color aColor; |
143 | 0 | if (IsControlBackground()) |
144 | 0 | aColor = GetControlBackground(); |
145 | 0 | else if (Window::GetStyle() & WB_3DLOOK) |
146 | 0 | aColor = rStyleSettings.GetFaceColor(); |
147 | 0 | else |
148 | 0 | aColor = rStyleSettings.GetWindowColor(); |
149 | 0 | SetBackground(aColor); |
150 | 0 | } |
151 | | |
152 | | FloatingWindow::FloatingWindow(vcl::Window* pParent, WinBits nStyle) : |
153 | 0 | SystemWindow(WindowType::FLOATINGWINDOW, "vcl::FloatingWindow maLayoutIdle") |
154 | 0 | { |
155 | 0 | ImplInitFloating(pParent, nStyle); |
156 | 0 | } Unexecuted instantiation: FloatingWindow::FloatingWindow(vcl::Window*, long) Unexecuted instantiation: FloatingWindow::FloatingWindow(vcl::Window*, long) |
157 | | |
158 | | FloatingWindow::FloatingWindow(vcl::Window* pParent, const OUString& rID, const OUString& rUIXMLDescription, const css::uno::Reference<css::frame::XFrame> &rFrame) |
159 | 0 | : SystemWindow(WindowType::FLOATINGWINDOW, "vcl::FloatingWindow maLayoutIdle") |
160 | 0 | , mpNextFloat(nullptr) |
161 | 0 | , mpFirstPopupModeWin(nullptr) |
162 | 0 | , mnPostId(nullptr) |
163 | 0 | , mnPopupModeFlags(FloatWinPopupFlags::NONE) |
164 | 0 | , mnTitle(FloatWinTitleType::Unknown) |
165 | 0 | , mnOldTitle(FloatWinTitleType::Unknown) |
166 | 0 | , mbInPopupMode(false) |
167 | 0 | , mbPopupMode(false) |
168 | 0 | , mbPopupModeCanceled(false) |
169 | 0 | , mbPopupModeTearOff(false) |
170 | 0 | , mbMouseDown(false) |
171 | 0 | , mbGrabFocus(false) |
172 | 0 | , mbInCleanUp(false) |
173 | 0 | { |
174 | 0 | loadUI(pParent, rID, rUIXMLDescription, rFrame); |
175 | 0 | } Unexecuted instantiation: FloatingWindow::FloatingWindow(vcl::Window*, rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const&) Unexecuted instantiation: FloatingWindow::FloatingWindow(vcl::Window*, rtl::OUString const&, rtl::OUString const&, com::sun::star::uno::Reference<com::sun::star::frame::XFrame> const&) |
176 | | |
177 | | void FloatingWindow::ImplDeferredInit(vcl::Window* pParent, WinBits nBits) |
178 | 0 | { |
179 | 0 | ImplInitFloating(pParent, nBits); |
180 | 0 | } |
181 | | |
182 | | void FloatingWindow::ApplySettings(vcl::RenderContext& rRenderContext) |
183 | 0 | { |
184 | 0 | const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings(); |
185 | |
|
186 | 0 | Color aColor; |
187 | 0 | if (Window::GetStyle() & WB_3DLOOK) |
188 | 0 | aColor = rStyleSettings.GetFaceColor(); |
189 | 0 | else |
190 | 0 | aColor = rStyleSettings.GetWindowColor(); |
191 | |
|
192 | 0 | ApplyControlBackground(rRenderContext, aColor); |
193 | 0 | } |
194 | | |
195 | | FloatingWindow::~FloatingWindow() |
196 | 0 | { |
197 | 0 | disposeOnce(); |
198 | 0 | assert (!mnPostId); |
199 | 0 | } |
200 | | |
201 | | void FloatingWindow::dispose() |
202 | 0 | { |
203 | 0 | ReleaseLOKNotifier(); |
204 | |
|
205 | 0 | if (mpImplData) |
206 | 0 | { |
207 | 0 | if( mbPopupModeCanceled ) |
208 | | // indicates that ESC key was pressed |
209 | | // will be handled in Window::ImplGrabFocus() |
210 | 0 | SetDialogControlFlags( GetDialogControlFlags() | DialogControlFlags::FloatWinPopupModeEndCancel ); |
211 | |
|
212 | 0 | if ( IsInPopupMode() ) |
213 | 0 | EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll | FloatWinPopupEndFlags::DontCallHdl ); |
214 | |
|
215 | 0 | if ( mnPostId ) |
216 | 0 | Application::RemoveUserEvent( mnPostId ); |
217 | 0 | mnPostId = nullptr; |
218 | 0 | } |
219 | |
|
220 | 0 | mpImplData.reset(); |
221 | |
|
222 | 0 | mpNextFloat.reset(); |
223 | 0 | mpFirstPopupModeWin.reset(); |
224 | 0 | mxPrevFocusWin.reset(); |
225 | 0 | SystemWindow::dispose(); |
226 | 0 | } |
227 | | |
228 | | Point FloatingWindow::ImplCalcPos(vcl::Window* pWindow, |
229 | | const tools::Rectangle& rRect, FloatWinPopupFlags nFlags, |
230 | | sal_uInt16& rArrangeIndex, Point* pLOKTwipsPos) |
231 | 0 | { |
232 | | // get window position |
233 | 0 | AbsoluteScreenPixelPoint aPos; |
234 | 0 | Size aSize = ::isLayoutEnabled(pWindow) ? pWindow->get_preferred_size() : pWindow->GetSizePixel(); |
235 | 0 | AbsoluteScreenPixelRectangle aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel(); |
236 | 0 | FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow ); |
237 | | |
238 | | // convert... |
239 | 0 | vcl::Window* pW = pWindow; |
240 | 0 | if ( pW->mpWindowImpl->mpRealParent ) |
241 | 0 | pW = pW->mpWindowImpl->mpRealParent; |
242 | |
|
243 | 0 | tools::Rectangle normRect( rRect ); // rRect is already relative to top-level window |
244 | 0 | normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) ); |
245 | |
|
246 | 0 | bool bRTL = AllSettings::GetLayoutRTL(); |
247 | |
|
248 | 0 | AbsoluteScreenPixelRectangle devRect( pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ), |
249 | 0 | pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) ); |
250 | |
|
251 | 0 | AbsoluteScreenPixelRectangle devRectRTL( devRect ); |
252 | 0 | if( bRTL ) |
253 | | // create a rect that can be compared to desktop coordinates |
254 | 0 | devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect ); |
255 | 0 | if( Application::GetScreenCount() > 1 ) |
256 | 0 | aScreenRect = Application::GetScreenPosSizePixel( |
257 | 0 | Application::GetBestScreen( bRTL ? devRectRTL : devRect ) ); |
258 | |
|
259 | 0 | FloatWinPopupFlags nArrangeAry[5]; |
260 | 0 | sal_uInt16 nArrangeAttempts = 5; |
261 | 0 | AbsoluteScreenPixelPoint e1,e2; // the common edge between the item rect and the floating window |
262 | |
|
263 | 0 | if ( nFlags & FloatWinPopupFlags::Left ) |
264 | 0 | { |
265 | 0 | nArrangeAry[0] = FloatWinPopupFlags::Left; |
266 | 0 | nArrangeAry[1] = FloatWinPopupFlags::Right; |
267 | 0 | nArrangeAry[2] = FloatWinPopupFlags::Up; |
268 | 0 | nArrangeAry[3] = FloatWinPopupFlags::Down; |
269 | 0 | nArrangeAry[4] = FloatWinPopupFlags::Left; |
270 | 0 | } |
271 | 0 | else if ( nFlags & FloatWinPopupFlags::Right ) |
272 | 0 | { |
273 | 0 | nArrangeAry[0] = FloatWinPopupFlags::Right; |
274 | 0 | nArrangeAry[1] = FloatWinPopupFlags::Left; |
275 | 0 | nArrangeAry[2] = FloatWinPopupFlags::Up; |
276 | 0 | nArrangeAry[3] = FloatWinPopupFlags::Down; |
277 | 0 | nArrangeAry[4] = FloatWinPopupFlags::Right; |
278 | 0 | } |
279 | 0 | else if ( nFlags & FloatWinPopupFlags::Up ) |
280 | 0 | { |
281 | 0 | nArrangeAry[0] = FloatWinPopupFlags::Up; |
282 | 0 | nArrangeAry[1] = FloatWinPopupFlags::Down; |
283 | 0 | if (nFlags & FloatWinPopupFlags::NoHorzPlacement) |
284 | 0 | { |
285 | 0 | nArrangeAry[2] = FloatWinPopupFlags::Up; |
286 | 0 | nArrangeAttempts = 3; |
287 | 0 | } |
288 | 0 | else |
289 | 0 | { |
290 | 0 | nArrangeAry[2] = FloatWinPopupFlags::Right; |
291 | 0 | nArrangeAry[3] = FloatWinPopupFlags::Left; |
292 | 0 | nArrangeAry[4] = FloatWinPopupFlags::Up; |
293 | 0 | } |
294 | 0 | } |
295 | 0 | else |
296 | 0 | { |
297 | 0 | nArrangeAry[0] = FloatWinPopupFlags::Down; |
298 | 0 | nArrangeAry[1] = FloatWinPopupFlags::Up; |
299 | 0 | if (nFlags & FloatWinPopupFlags::NoHorzPlacement) |
300 | 0 | { |
301 | 0 | nArrangeAry[2] = FloatWinPopupFlags::Down; |
302 | 0 | nArrangeAttempts = 3; |
303 | 0 | } |
304 | 0 | else |
305 | 0 | { |
306 | 0 | nArrangeAry[2] = FloatWinPopupFlags::Right; |
307 | 0 | nArrangeAry[3] = FloatWinPopupFlags::Left; |
308 | 0 | nArrangeAry[4] = FloatWinPopupFlags::Down; |
309 | 0 | } |
310 | 0 | } |
311 | |
|
312 | 0 | sal_uInt16 nArrangeIndex = 0; |
313 | 0 | const bool bLOKActive = comphelper::LibreOfficeKit::isActive(); |
314 | |
|
315 | 0 | for ( ; nArrangeIndex < nArrangeAttempts; nArrangeIndex++ ) |
316 | 0 | { |
317 | 0 | bool bBreak = true; |
318 | 0 | switch ( nArrangeAry[nArrangeIndex] ) |
319 | 0 | { |
320 | | |
321 | 0 | case FloatWinPopupFlags::Left: |
322 | 0 | aPos.setX( devRect.Left()-aSize.Width()+1 ); |
323 | 0 | aPos.setY( devRect.Top() ); |
324 | 0 | aPos.AdjustY( -(pWindow->mpWindowImpl->mnTopBorder) ); |
325 | 0 | if( bRTL ) |
326 | 0 | { |
327 | 0 | if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() ) |
328 | 0 | bBreak = false; |
329 | 0 | } |
330 | 0 | else |
331 | 0 | { |
332 | 0 | if ( aPos.X() < aScreenRect.Left() ) |
333 | 0 | bBreak = false; |
334 | 0 | } |
335 | 0 | if (bBreak || bLOKActive) |
336 | 0 | { |
337 | 0 | e1 = devRect.TopLeft(); |
338 | 0 | e2 = devRect.BottomLeft(); |
339 | | // set non-zero width |
340 | 0 | e2.AdjustX( 1 ); |
341 | | // don't clip corners |
342 | 0 | e1.AdjustY( 1 ); |
343 | 0 | e2.AdjustY( -1 ); |
344 | 0 | } |
345 | 0 | break; |
346 | 0 | case FloatWinPopupFlags::Right: |
347 | 0 | aPos = devRect.TopRight(); |
348 | 0 | aPos.AdjustY( -(pWindow->mpWindowImpl->mnTopBorder) ); |
349 | 0 | if( bRTL ) |
350 | 0 | { |
351 | 0 | if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() ) |
352 | 0 | bBreak = false; |
353 | 0 | } |
354 | 0 | else |
355 | 0 | { |
356 | 0 | if ( aPos.X()+aSize.Width() > aScreenRect.Right() ) |
357 | 0 | bBreak = false; |
358 | 0 | } |
359 | 0 | if (bBreak || bLOKActive) |
360 | 0 | { |
361 | 0 | e1 = devRect.TopRight(); |
362 | 0 | e2 = devRect.BottomRight(); |
363 | | // set non-zero width |
364 | 0 | e2.AdjustX( 1 ); |
365 | | // don't clip corners |
366 | 0 | e1.AdjustY( 1 ); |
367 | 0 | e2.AdjustY( -1 ); |
368 | 0 | } |
369 | 0 | break; |
370 | 0 | case FloatWinPopupFlags::Up: |
371 | 0 | aPos.setX( devRect.Left() ); |
372 | 0 | aPos.setY( devRect.Top()-aSize.Height()+1 ); |
373 | 0 | if ( aPos.Y() < aScreenRect.Top() ) |
374 | 0 | bBreak = false; |
375 | 0 | if (bBreak || bLOKActive) |
376 | 0 | { |
377 | 0 | e1 = devRect.TopLeft(); |
378 | 0 | e2 = devRect.TopRight(); |
379 | | // set non-zero height |
380 | 0 | e2.AdjustY( 1 ); |
381 | | // don't clip corners |
382 | 0 | e1.AdjustX( 1 ); |
383 | 0 | e2.AdjustX( -1 ); |
384 | 0 | } |
385 | 0 | break; |
386 | 0 | case FloatWinPopupFlags::Down: |
387 | 0 | aPos = devRect.BottomLeft(); |
388 | 0 | if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() ) |
389 | 0 | bBreak = false; |
390 | 0 | if (bBreak || bLOKActive) |
391 | 0 | { |
392 | 0 | e1 = devRect.BottomLeft(); |
393 | 0 | e2 = devRect.BottomRight(); |
394 | | // set non-zero height |
395 | 0 | e2.AdjustY( 1 ); |
396 | | // don't clip corners |
397 | 0 | e1.AdjustX( 1 ); |
398 | 0 | e2.AdjustX( -1 ); |
399 | 0 | } |
400 | 0 | break; |
401 | 0 | default: break; |
402 | 0 | } |
403 | | |
404 | | // no further adjustment for LibreOfficeKit |
405 | 0 | if (bLOKActive) |
406 | 0 | break; |
407 | | |
408 | | // set bBreak true on last attempt |
409 | 0 | if (nArrangeIndex + 1 == nArrangeAttempts) |
410 | 0 | bBreak = true; |
411 | | |
412 | | // adjust if necessary |
413 | 0 | if (bBreak) |
414 | 0 | { |
415 | 0 | if (aPos.Y() + aSize.Height() > aScreenRect.Bottom()) |
416 | 0 | { |
417 | 0 | aPos.setY(devRect.Bottom() - aSize.Height() + 1); |
418 | 0 | if (aPos.Y() < aScreenRect.Top()) |
419 | 0 | aPos.setY(aScreenRect.Top()); |
420 | | // move to the right or left of the parent if possible |
421 | 0 | if (devRect.Right() + 4 + aSize.Width() < aScreenRect.Right()) |
422 | 0 | aPos.setX(devRect.Right() + 4); |
423 | 0 | else if (devRect.Left() - 4 - aSize.Width() > aScreenRect.Left()) |
424 | 0 | aPos.setX(devRect.Left() - 4 - aSize.Width()); |
425 | 0 | } |
426 | 0 | else |
427 | 0 | { |
428 | 0 | if( bRTL ) |
429 | 0 | { |
430 | 0 | if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() ) |
431 | 0 | aPos.AdjustX( -(aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1) ); |
432 | 0 | } |
433 | 0 | else if ( aPos.X()+aSize.Width() > aScreenRect.Right() ) |
434 | 0 | { |
435 | 0 | aPos.setX( devRect.Right()-aSize.Width()+1 ); |
436 | 0 | if ( aPos.X() < aScreenRect.Left() ) |
437 | 0 | aPos.setX( aScreenRect.Left() ); |
438 | 0 | } |
439 | 0 | } |
440 | 0 | } |
441 | |
|
442 | 0 | if ( bBreak ) |
443 | 0 | break; |
444 | 0 | } |
445 | | |
446 | 0 | rArrangeIndex = nArrangeIndex; |
447 | |
|
448 | 0 | Point aPosOut = pW->AbsoluteScreenToOutputPixel( aPos ); |
449 | | |
450 | | // store a cliprect that can be used to clip the common edge of the itemrect and the floating window |
451 | 0 | if( pFloatingWindow && pFloatingWindow->mpImplData->mpBox ) |
452 | 0 | { |
453 | 0 | pFloatingWindow->mpImplData->maItemEdgeClipRect = |
454 | 0 | AbsoluteScreenPixelRectangle( e1, e2 ); |
455 | 0 | } |
456 | |
|
457 | 0 | if (bLOKActive && pLOKTwipsPos) |
458 | 0 | { |
459 | 0 | if (pW->IsMapModeEnabled() || pW->GetMapMode().GetMapUnit() == MapUnit::MapPixel) |
460 | 0 | { |
461 | | // if we use pW->LogicToLogic(aPos, pW->GetMapMode(), MapMode(MapUnit::MapTwip)), |
462 | | // for pixel conversions when map mode is not enabled, we get |
463 | | // a 20 twips per pixel conversion since LogicToLogic uses |
464 | | // a fixed 72 dpi value, instead of a correctly computed output |
465 | | // device dpi or at least the most commonly used 96 dpi value; |
466 | | // and anyway the following is what we already do in |
467 | | // ScGridWindow::LogicInvalidate when map mode is not enabled. |
468 | |
|
469 | 0 | *pLOKTwipsPos = pW->PixelToLogic(aPosOut, MapMode(MapUnit::MapTwip)); |
470 | 0 | } |
471 | 0 | else |
472 | 0 | { |
473 | 0 | *pLOKTwipsPos = OutputDevice::LogicToLogic(aPosOut, pW->GetMapMode(), MapMode(MapUnit::MapTwip)); |
474 | 0 | } |
475 | 0 | } |
476 | | |
477 | | // caller expects coordinates relative to top-level win |
478 | 0 | return pW->OutputToScreenPixel( aPosOut ); |
479 | 0 | } |
480 | | |
481 | | AbsoluteScreenPixelPoint FloatingWindow::ImplConvertToAbsPos(vcl::Window* pReference, const Point& rPos) |
482 | 0 | { |
483 | 0 | const OutputDevice *pWindowOutDev = pReference->GetOutDev(); |
484 | | |
485 | | // compare coordinates in absolute screen coordinates |
486 | 0 | if ( pWindowOutDev->HasMirroredGraphics() && !comphelper::LibreOfficeKit::isActive() ) |
487 | 0 | { |
488 | 0 | Point aTmp(rPos); |
489 | 0 | if(!pReference->IsRTLEnabled() ) |
490 | 0 | pWindowOutDev->ReMirror( aTmp ); |
491 | |
|
492 | 0 | tools::Rectangle aRect( pReference->ScreenToOutputPixel(aTmp), Size(1,1) ) ; |
493 | 0 | aRect = tools::Rectangle(pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect )); |
494 | 0 | return AbsoluteScreenPixelPoint(aRect.TopLeft()); |
495 | 0 | } |
496 | 0 | else |
497 | 0 | return pReference->OutputToAbsoluteScreenPixel( |
498 | 0 | pReference->ScreenToOutputPixel(rPos) ); |
499 | 0 | } |
500 | | |
501 | | AbsoluteScreenPixelRectangle FloatingWindow::ImplConvertToAbsPos(vcl::Window* pReference, const tools::Rectangle& rRect) |
502 | 0 | { |
503 | 0 | AbsoluteScreenPixelRectangle aFloatRect; |
504 | |
|
505 | 0 | const OutputDevice *pParentWinOutDev = pReference->GetOutDev(); |
506 | | |
507 | | // compare coordinates in absolute screen coordinates |
508 | | // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509 |
509 | 0 | if( pParentWinOutDev->HasMirroredGraphics() && !comphelper::LibreOfficeKit::isActive() ) |
510 | 0 | { |
511 | 0 | tools::Rectangle aScreenRect(rRect); |
512 | 0 | if(!pReference->IsRTLEnabled() ) |
513 | 0 | pParentWinOutDev->ReMirror(aScreenRect); |
514 | |
|
515 | 0 | tools::Rectangle aOutRect(pReference->ScreenToOutputPixel(aScreenRect.TopLeft()), aScreenRect.GetSize()); |
516 | 0 | aFloatRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel(aOutRect); |
517 | 0 | } |
518 | 0 | else |
519 | 0 | aFloatRect = AbsoluteScreenPixelRectangle( |
520 | 0 | pReference->OutputToAbsoluteScreenPixel(pReference->ScreenToOutputPixel(rRect.TopLeft())), |
521 | 0 | rRect.GetSize()); |
522 | |
|
523 | 0 | return aFloatRect; |
524 | 0 | } |
525 | | |
526 | | tools::Rectangle FloatingWindow::ImplConvertToRelPos(vcl::Window* pReference, const AbsoluteScreenPixelRectangle& rRect) |
527 | 0 | { |
528 | 0 | tools::Rectangle aFloatRect; |
529 | |
|
530 | 0 | const OutputDevice *pParentWinOutDev = pReference->GetOutDev(); |
531 | | |
532 | | // compare coordinates in absolute screen coordinates |
533 | | // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509 |
534 | 0 | if( pParentWinOutDev->HasMirroredGraphics() ) |
535 | 0 | { |
536 | 0 | aFloatRect = pReference->ImplUnmirroredAbsoluteScreenToOutputPixel(rRect); |
537 | 0 | aFloatRect.SetPos(pReference->OutputToScreenPixel(aFloatRect.TopLeft())); |
538 | |
|
539 | 0 | if(!pReference->IsRTLEnabled() ) |
540 | 0 | pParentWinOutDev->ReMirror(aFloatRect); |
541 | 0 | } |
542 | 0 | else |
543 | 0 | aFloatRect = tools::Rectangle(pReference->OutputToScreenPixel(pReference->AbsoluteScreenToOutputPixel(rRect.TopLeft())), |
544 | 0 | rRect.GetSize()); |
545 | |
|
546 | 0 | return aFloatRect; |
547 | 0 | } |
548 | | |
549 | | FloatingWindow* FloatingWindow::ImplFloatHitTest( vcl::Window* pReference, const Point& rPos, bool& rbHitTestInsideRect ) |
550 | 0 | { |
551 | 0 | FloatingWindow* pWin = this; |
552 | 0 | rbHitTestInsideRect = false; |
553 | |
|
554 | 0 | AbsoluteScreenPixelPoint aAbsolute(FloatingWindow::ImplConvertToAbsPos(pReference, rPos)); |
555 | |
|
556 | 0 | do |
557 | 0 | { |
558 | | // compute the floating window's size in absolute screen coordinates |
559 | | |
560 | | // use the border window to have the exact position |
561 | 0 | vcl::Window *pBorderWin = pWin->GetWindow( GetWindowType::Border ); |
562 | 0 | if (!pBorderWin) |
563 | 0 | break; |
564 | | |
565 | | // the top-left corner in output coordinates ie (0,0) |
566 | 0 | AbsoluteScreenPixelRectangle devRect( pBorderWin->ImplOutputToUnmirroredAbsoluteScreenPixel( tools::Rectangle( Point(), pBorderWin->GetSizePixel()) ) ) ; |
567 | 0 | if ( devRect.Contains( aAbsolute ) ) |
568 | 0 | { |
569 | | // inside the window |
570 | 0 | return pWin; |
571 | 0 | } |
572 | | |
573 | | // test, if mouse is in rectangle, (this is typically the rect of the active |
574 | | // toolbox item or similar) |
575 | | // note: maFloatRect is set in FloatingWindow::StartPopupMode() and |
576 | | // is already in absolute device coordinates |
577 | 0 | if ( pWin->maFloatRect.Contains( aAbsolute ) ) |
578 | 0 | { |
579 | 0 | rbHitTestInsideRect = true; |
580 | 0 | return pWin; |
581 | 0 | } |
582 | | |
583 | 0 | pWin = pWin->mpNextFloat; |
584 | 0 | } |
585 | 0 | while ( pWin ); |
586 | | |
587 | 0 | return nullptr; |
588 | 0 | } |
589 | | |
590 | | FloatingWindow* FloatingWindow::ImplFindLastLevelFloat() |
591 | 0 | { |
592 | 0 | FloatingWindow* pWin = this; |
593 | 0 | FloatingWindow* pLastFoundWin = pWin; |
594 | |
|
595 | 0 | do |
596 | 0 | { |
597 | 0 | if ( pWin->GetPopupModeFlags() & FloatWinPopupFlags::NewLevel ) |
598 | 0 | pLastFoundWin = pWin; |
599 | |
|
600 | 0 | pWin = pWin->mpNextFloat; |
601 | 0 | } |
602 | 0 | while ( pWin ); |
603 | |
|
604 | 0 | return pLastFoundWin; |
605 | 0 | } |
606 | | |
607 | | bool FloatingWindow::ImplIsFloatPopupModeWindow( const vcl::Window* pWindow ) |
608 | 0 | { |
609 | 0 | FloatingWindow* pWin = this; |
610 | |
|
611 | 0 | do |
612 | 0 | { |
613 | 0 | if ( pWin->mpFirstPopupModeWin == pWindow ) |
614 | 0 | return true; |
615 | | |
616 | 0 | pWin = pWin->mpNextFloat; |
617 | 0 | } |
618 | 0 | while ( pWin ); |
619 | | |
620 | 0 | return false; |
621 | 0 | } |
622 | | |
623 | | IMPL_LINK_NOARG(FloatingWindow, ImplEndPopupModeHdl, void*, void) |
624 | 0 | { |
625 | 0 | VclPtr<FloatingWindow> pThis(this); |
626 | 0 | mnPostId = nullptr; |
627 | 0 | mnPopupModeFlags = FloatWinPopupFlags::NONE; |
628 | 0 | mbPopupMode = false; |
629 | 0 | PopupModeEnd(); |
630 | 0 | } |
631 | | |
632 | | bool FloatingWindow::EventNotify( NotifyEvent& rNEvt ) |
633 | 0 | { |
634 | | // call Base Class first for tab control |
635 | 0 | bool bRet = SystemWindow::EventNotify( rNEvt ); |
636 | 0 | if ( !bRet ) |
637 | 0 | { |
638 | 0 | if ( rNEvt.GetType() == NotifyEventType::KEYINPUT ) |
639 | 0 | { |
640 | 0 | const KeyEvent* pKEvt = rNEvt.GetKeyEvent(); |
641 | 0 | vcl::KeyCode aKeyCode = pKEvt->GetKeyCode(); |
642 | 0 | sal_uInt16 nKeyCode = aKeyCode.GetCode(); |
643 | |
|
644 | 0 | if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) ) |
645 | 0 | { |
646 | 0 | Close(); |
647 | 0 | return true; |
648 | 0 | } |
649 | 0 | } |
650 | 0 | } |
651 | | |
652 | 0 | return bRet; |
653 | 0 | } |
654 | | |
655 | | void FloatingWindow::PixelInvalidate(const tools::Rectangle* /*pRectangle*/) |
656 | 0 | { |
657 | 0 | if (VclPtr<vcl::Window> pParent = GetParentWithLOKNotifier()) |
658 | 0 | { |
659 | 0 | const tools::Rectangle aRect(Point(0,0), Size(GetSizePixel().Width()+1, GetSizePixel().Height()+1)); |
660 | 0 | std::vector<vcl::LOKPayloadItem> aPayload |
661 | 0 | { |
662 | 0 | std::make_pair("rectangle"_ostr, aRect.toString()) |
663 | 0 | }; |
664 | 0 | const vcl::ILibreOfficeKitNotifier* pNotifier = pParent->GetLOKNotifier(); |
665 | 0 | pNotifier->notifyWindow(GetLOKWindowId(), u"invalidate"_ustr, aPayload); |
666 | 0 | } |
667 | 0 | } |
668 | | |
669 | | void FloatingWindow::StateChanged( StateChangedType nType ) |
670 | 0 | { |
671 | 0 | if (nType == StateChangedType::InitShow) |
672 | 0 | { |
673 | 0 | DoInitialLayout(); |
674 | 0 | } |
675 | |
|
676 | 0 | SystemWindow::StateChanged( nType ); |
677 | |
|
678 | 0 | VclPtr<vcl::Window> pParent = GetParentWithLOKNotifier(); |
679 | 0 | if (pParent) |
680 | 0 | { |
681 | 0 | if (nType == StateChangedType::InitShow) |
682 | 0 | { |
683 | 0 | std::vector<vcl::LOKPayloadItem> aItems; |
684 | 0 | if (pParent == this) |
685 | 0 | { |
686 | | // we are a toplevel window, let's so far pretend to be a |
687 | | // dialog - but maybe we'll need a separate type for this |
688 | | // later |
689 | 0 | if (mbInPopupMode) |
690 | 0 | aItems.emplace_back("type", "dropdown"); |
691 | 0 | else |
692 | 0 | aItems.emplace_back("type", "dialog"); |
693 | 0 | aItems.emplace_back("position", mpImplData->maLOKTwipsPos.toString()); // twips |
694 | 0 | } |
695 | 0 | else |
696 | 0 | { |
697 | 0 | SetLOKNotifier(pParent->GetLOKNotifier()); |
698 | 0 | if (dynamic_cast<HelpTextWindow*>(this)) |
699 | 0 | aItems.emplace_back("type", "tooltip"); |
700 | 0 | else |
701 | 0 | aItems.emplace_back("type", "child"); |
702 | |
|
703 | 0 | aItems.emplace_back("parentId", OString::number(pParent->GetLOKWindowId())); |
704 | 0 | if (mbInPopupMode) |
705 | 0 | aItems.emplace_back("position", mpImplData->maPos.toString()); // pixels |
706 | 0 | else // mpImplData->maPos is not set |
707 | 0 | aItems.emplace_back("position", GetPosPixel().toString()); |
708 | |
|
709 | 0 | } |
710 | 0 | aItems.emplace_back("size", GetSizePixel().toString()); |
711 | 0 | GetLOKNotifier()->notifyWindow(GetLOKWindowId(), u"created"_ustr, aItems); |
712 | 0 | } |
713 | 0 | else if (!IsVisible() && nType == StateChangedType::Visible) |
714 | 0 | { |
715 | 0 | if (const vcl::ILibreOfficeKitNotifier* pNotifier = GetLOKNotifier()) |
716 | 0 | { |
717 | 0 | pNotifier->notifyWindow(GetLOKWindowId(), u"close"_ustr); |
718 | 0 | ReleaseLOKNotifier(); |
719 | 0 | } |
720 | 0 | } |
721 | 0 | } |
722 | |
|
723 | 0 | if ( nType == StateChangedType::ControlBackground ) |
724 | 0 | { |
725 | 0 | ImplInitSettings(); |
726 | 0 | Invalidate(); |
727 | 0 | } |
728 | 0 | } |
729 | | |
730 | | void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt ) |
731 | 0 | { |
732 | 0 | SystemWindow::DataChanged( rDCEvt ); |
733 | |
|
734 | 0 | if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) && |
735 | 0 | (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) ) |
736 | 0 | { |
737 | 0 | ImplInitSettings(); |
738 | 0 | Invalidate(); |
739 | 0 | } |
740 | 0 | } |
741 | | |
742 | | void FloatingWindow::ImplCallPopupModeEnd() |
743 | 0 | { |
744 | | // PopupMode is finished |
745 | 0 | mbInPopupMode = false; |
746 | | |
747 | | // call Handler asynchronously. |
748 | 0 | if ( mpImplData && !mnPostId ) |
749 | 0 | mnPostId = Application::PostUserEvent(LINK(this, FloatingWindow, ImplEndPopupModeHdl)); |
750 | 0 | } |
751 | | |
752 | | void FloatingWindow::PopupModeEnd() |
753 | 0 | { |
754 | 0 | maPopupModeEndHdl.Call( this ); |
755 | 0 | } |
756 | | |
757 | | void FloatingWindow::SetTitleType( FloatWinTitleType nTitle ) |
758 | 0 | { |
759 | 0 | if ( (mnTitle == nTitle) || !mpWindowImpl->mpBorderWindow ) |
760 | 0 | return; |
761 | | |
762 | 0 | mnTitle = nTitle; |
763 | 0 | Size aOutSize = GetOutputSizePixel(); |
764 | 0 | BorderWindowTitleType nTitleStyle; |
765 | 0 | if ( nTitle == FloatWinTitleType::Normal ) |
766 | 0 | nTitleStyle = BorderWindowTitleType::Small; |
767 | 0 | else if ( nTitle == FloatWinTitleType::TearOff ) |
768 | 0 | nTitleStyle = BorderWindowTitleType::Tearoff; |
769 | 0 | else if ( nTitle == FloatWinTitleType::Popup ) |
770 | 0 | nTitleStyle = BorderWindowTitleType::Popup; |
771 | 0 | else // nTitle == FloatWinTitleType::NONE |
772 | 0 | nTitleStyle = BorderWindowTitleType::NONE; |
773 | 0 | static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetTitleType( nTitleStyle, aOutSize ); |
774 | 0 | static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder ); |
775 | 0 | } |
776 | | |
777 | | void FloatingWindow::StartPopupMode( const tools::Rectangle& rRect, FloatWinPopupFlags nFlags ) |
778 | 0 | { |
779 | | // remove title |
780 | 0 | mnOldTitle = mnTitle; |
781 | 0 | if ( ( mpWindowImpl->mnStyle & WB_POPUP ) && !GetText().isEmpty() ) |
782 | 0 | SetTitleType( FloatWinTitleType::Popup ); |
783 | 0 | else if ( nFlags & FloatWinPopupFlags::AllowTearOff ) |
784 | 0 | SetTitleType( FloatWinTitleType::TearOff ); |
785 | 0 | else |
786 | 0 | SetTitleType( FloatWinTitleType::NONE ); |
787 | | |
788 | | // avoid close on focus change for decorated floating windows only |
789 | 0 | if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) ) |
790 | 0 | nFlags |= FloatWinPopupFlags::NoAppFocusClose; |
791 | | |
792 | | // compute window position according to flags and arrangement |
793 | 0 | sal_uInt16 nArrangeIndex; |
794 | 0 | DoInitialLayout(); |
795 | 0 | mpImplData->maPos = ImplCalcPos(this, rRect, nFlags, nArrangeIndex, &mpImplData->maLOKTwipsPos); |
796 | 0 | SetPosPixel( mpImplData->maPos ); |
797 | 0 | ImplGetFrame()->PositionByToolkit(rRect, nFlags); |
798 | | |
799 | | // set data and display window |
800 | | // convert maFloatRect to absolute device coordinates |
801 | | // so they can be compared across different frames |
802 | | // !!! rRect is expected to be in screen coordinates of the parent frame window !!! |
803 | 0 | maFloatRect = FloatingWindow::ImplConvertToAbsPos(GetParent(), rRect); |
804 | |
|
805 | 0 | maFloatRect.AdjustLeft( -2 ); |
806 | 0 | maFloatRect.AdjustTop( -2 ); |
807 | 0 | maFloatRect.AdjustRight(2 ); |
808 | 0 | maFloatRect.AdjustBottom(2 ); |
809 | 0 | mnPopupModeFlags = nFlags; |
810 | 0 | mbInPopupMode = true; |
811 | 0 | mbPopupMode = true; |
812 | 0 | mbPopupModeCanceled = false; |
813 | 0 | mbPopupModeTearOff = false; |
814 | 0 | mbMouseDown = false; |
815 | | |
816 | | // add FloatingWindow to list of windows that are in popup mode |
817 | 0 | ImplSVData* pSVData = ImplGetSVData(); |
818 | 0 | mpNextFloat = pSVData->mpWinData->mpFirstFloat; |
819 | 0 | pSVData->mpWinData->mpFirstFloat = this; |
820 | 0 | bool bGrabFocus(nFlags & FloatWinPopupFlags::GrabFocus); |
821 | 0 | if (bGrabFocus) |
822 | 0 | { |
823 | | // force key input even without focus (useful for menus) |
824 | 0 | mbGrabFocus = true; |
825 | 0 | mxPrevFocusWin = Window::SaveFocus(); |
826 | 0 | mpWindowImpl->mpFrameData->mbHasFocus = true; |
827 | 0 | } |
828 | 0 | Show( true, ShowFlags::NoActivate ); |
829 | 0 | if (bGrabFocus) |
830 | 0 | GrabFocus(); |
831 | 0 | } |
832 | | |
833 | | void FloatingWindow::StartPopupMode( ToolBox* pBox, FloatWinPopupFlags nFlags ) |
834 | 0 | { |
835 | 0 | mpImplData->mpBox = pBox; |
836 | | |
837 | | // get selected button |
838 | 0 | ToolBoxItemId nItemId = pBox->GetDownItemId(); |
839 | |
|
840 | 0 | if ( nItemId ) |
841 | 0 | pBox->ImplFloatControl( true, this ); |
842 | | |
843 | | // retrieve some data from the ToolBox |
844 | 0 | tools::Rectangle aRect = nItemId ? pBox->GetItemRect( nItemId ) : pBox->GetOverflowRect(); |
845 | | |
846 | | // convert to parent's screen coordinates |
847 | 0 | mpImplData->maPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) ); |
848 | 0 | aRect.SetPos( mpImplData->maPos ); |
849 | |
|
850 | 0 | nFlags |= |
851 | 0 | FloatWinPopupFlags::AllMouseButtonClose | |
852 | 0 | FloatWinPopupFlags::NoMouseUpClose; |
853 | | |
854 | | // set Flags for positioning |
855 | 0 | if ( !(nFlags & (FloatWinPopupFlags::Down | FloatWinPopupFlags::Up | |
856 | 0 | FloatWinPopupFlags::Left | FloatWinPopupFlags::Right)) ) |
857 | 0 | { |
858 | 0 | if ( pBox->IsHorizontal() ) |
859 | 0 | nFlags |= FloatWinPopupFlags::Down; |
860 | 0 | else |
861 | 0 | nFlags |= FloatWinPopupFlags::Right; |
862 | 0 | } |
863 | | |
864 | | // start FloatingMode |
865 | 0 | StartPopupMode( aRect, nFlags ); |
866 | 0 | } |
867 | | |
868 | | void FloatingWindow::ImplEndPopupMode( FloatWinPopupEndFlags nFlags, const VclPtr<vcl::Window>& xFocusId ) |
869 | 0 | { |
870 | 0 | if ( !mbInPopupMode ) |
871 | 0 | return; |
872 | | |
873 | 0 | ImplSVData* pSVData = ImplGetSVData(); |
874 | |
|
875 | 0 | mbInCleanUp = true; // prevent killing this window due to focus change while working with it |
876 | |
|
877 | 0 | if (!(nFlags & FloatWinPopupEndFlags::NoCloseChildren)) |
878 | 0 | { |
879 | | // stop the PopupMode also for all PopupMode windows created after us |
880 | 0 | std::vector<VclPtr<FloatingWindow>> aCancelFloats; |
881 | | // stop the PopupMode also for all following PopupMode windows |
882 | 0 | for (auto pFloat = pSVData->mpWinData->mpFirstFloat; |
883 | 0 | pFloat != nullptr && pFloat != this; |
884 | 0 | pFloat = pFloat->mpNextFloat) |
885 | 0 | aCancelFloats.push_back(pFloat); |
886 | 0 | for (auto & it : aCancelFloats) |
887 | 0 | it->EndPopupMode(FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::NoCloseChildren); |
888 | 0 | } |
889 | | |
890 | | // delete window from the list |
891 | 0 | pSVData->mpWinData->mpFirstFloat = mpNextFloat; |
892 | 0 | mpNextFloat = nullptr; |
893 | |
|
894 | 0 | FloatWinPopupFlags nPopupModeFlags = mnPopupModeFlags; |
895 | 0 | mbPopupModeTearOff = nFlags & FloatWinPopupEndFlags::TearOff && |
896 | 0 | nPopupModeFlags & FloatWinPopupFlags::AllowTearOff; |
897 | | |
898 | | // hide window again if it was not deleted |
899 | 0 | if (!mbPopupModeTearOff) |
900 | 0 | Show( false, ShowFlags::NoFocusChange ); |
901 | |
|
902 | 0 | if (HasChildPathFocus() && xFocusId != nullptr) |
903 | 0 | { |
904 | | // restore focus to previous focus window if we still have the focus |
905 | 0 | Window::EndSaveFocus(xFocusId); |
906 | 0 | } |
907 | 0 | else if ( pSVData->mpWinData->mpFocusWin && pSVData->mpWinData->mpFirstFloat && |
908 | 0 | ImplIsWindowOrChild( pSVData->mpWinData->mpFocusWin ) ) |
909 | 0 | { |
910 | | // maybe pass focus on to a suitable FloatingWindow |
911 | 0 | pSVData->mpWinData->mpFirstFloat->GrabFocus(); |
912 | 0 | } |
913 | |
|
914 | 0 | mbPopupModeCanceled = bool(nFlags & FloatWinPopupEndFlags::Cancel); |
915 | | |
916 | | // redo title |
917 | 0 | SetTitleType( mnOldTitle ); |
918 | | |
919 | | // set ToolBox again to normal |
920 | 0 | if (mpImplData && mpImplData->mpBox) |
921 | 0 | { |
922 | 0 | mpImplData->mpBox->ImplFloatControl( false, this ); |
923 | | // if the parent ToolBox is in popup mode, it should be closed too. |
924 | 0 | if ( GetDockingManager()->IsInPopupMode( mpImplData->mpBox ) ) |
925 | 0 | nFlags |= FloatWinPopupEndFlags::CloseAll; |
926 | |
|
927 | 0 | mpImplData->mpBox = nullptr; |
928 | 0 | } |
929 | | |
930 | | // call PopupModeEnd-Handler depending on parameter |
931 | 0 | if ( !(nFlags & FloatWinPopupEndFlags::DontCallHdl) ) |
932 | 0 | ImplCallPopupModeEnd(); |
933 | | |
934 | | // close all other windows depending on parameter |
935 | 0 | if ( nFlags & FloatWinPopupEndFlags::CloseAll ) |
936 | 0 | { |
937 | 0 | if ( !(nPopupModeFlags & FloatWinPopupFlags::NewLevel) ) |
938 | 0 | { |
939 | 0 | if (pSVData->mpWinData->mpFirstFloat) |
940 | 0 | { |
941 | 0 | FloatingWindow* pLastLevelFloat = pSVData->mpWinData->mpFirstFloat->ImplFindLastLevelFloat(); |
942 | 0 | pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll ); |
943 | 0 | } |
944 | 0 | } |
945 | 0 | } |
946 | |
|
947 | 0 | mbInCleanUp = false; |
948 | 0 | } |
949 | | |
950 | | void FloatingWindow::EndPopupMode( FloatWinPopupEndFlags nFlags ) |
951 | 0 | { |
952 | 0 | ImplEndPopupMode(nFlags, mxPrevFocusWin); |
953 | 0 | } |
954 | | |
955 | | void FloatingWindow::AddPopupModeWindow(vcl::Window* pWindow) |
956 | 0 | { |
957 | | // !!! up-to-now only 1 window and not yet a list |
958 | 0 | mpFirstPopupModeWin = pWindow; |
959 | 0 | } |
960 | | |
961 | | bool SystemWindow::UpdatePositionData() |
962 | 0 | { |
963 | | // tdf#164337 don't update position data when waiting for a system resize |
964 | | // When entering and exiting LibreOffice's internal full screen mode, |
965 | | // updating position data causes the "exit full screen" floating |
966 | | // toolbar to migrate after cycle. |
967 | 0 | if (mpWindowImpl->mbWaitSystemResize) |
968 | 0 | return false; |
969 | | |
970 | 0 | auto pWin = ImplGetParent(); |
971 | 0 | if (pWin) |
972 | 0 | { |
973 | | // Simulate Move, so the relative position of the floating window will be recalculated |
974 | 0 | pWin->ImplCallMove(); |
975 | 0 | return true; |
976 | 0 | } |
977 | | |
978 | 0 | return false; |
979 | 0 | } |
980 | | |
981 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |