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