Line data Source code
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 :
25 : #include <vcl/layout.hxx>
26 : #include <vcl/svapp.hxx>
27 : #include <vcl/wrkwin.hxx>
28 : #include <vcl/event.hxx>
29 : #include <vcl/toolbox.hxx>
30 : #include <vcl/floatwin.hxx>
31 : #include <vcl/settings.hxx>
32 :
33 : #include <tools/rc.h>
34 : #include <tools/debug.hxx>
35 :
36 : class FloatingWindow::ImplData
37 : {
38 : public:
39 : ImplData();
40 : ~ImplData();
41 :
42 : VclPtr<ToolBox> mpBox;
43 : Rectangle maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
44 : };
45 :
46 3290 : FloatingWindow::ImplData::ImplData()
47 : {
48 3290 : mpBox = NULL;
49 3290 : }
50 :
51 3288 : FloatingWindow::ImplData::~ImplData()
52 : {
53 3288 : }
54 :
55 0 : Rectangle& FloatingWindow::ImplGetItemEdgeClipRect()
56 : {
57 0 : return mpImplData->maItemEdgeClipRect;
58 : }
59 :
60 3290 : void FloatingWindow::ImplInit( vcl::Window* pParent, WinBits nStyle )
61 : {
62 3290 : mpImplData = new ImplData;
63 :
64 3290 : mpWindowImpl->mbFloatWin = true;
65 3290 : mbInCleanUp = false;
66 3290 : mbGrabFocus = false;
67 :
68 : DBG_ASSERT(pParent, "FloatWindow::FloatingWindow(): - pParent == NULL!");
69 :
70 3290 : if (!pParent)
71 0 : pParent = ImplGetSVData()->maWinData.mpAppWin;
72 :
73 : DBG_ASSERT(pParent, "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists");
74 :
75 : // no Border, then we dont need a border window
76 3290 : if (!nStyle)
77 : {
78 0 : mpWindowImpl->mbOverlapWin = true;
79 0 : nStyle |= WB_DIALOGCONTROL;
80 0 : SystemWindow::ImplInit(pParent, nStyle, NULL);
81 : }
82 : else
83 : {
84 3290 : if (!(nStyle & WB_NODIALOGCONTROL))
85 3290 : nStyle |= WB_DIALOGCONTROL;
86 :
87 3290 : if (nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)
88 0 : && !(nStyle & WB_OWNERDRAWDECORATION))
89 : {
90 0 : WinBits nFloatWinStyle = nStyle;
91 : // #99154# floaters are not closeable by default anymore, eg fullscreen floater
92 : // nFloatWinStyle |= WB_CLOSEABLE;
93 0 : mpWindowImpl->mbFrame = true;
94 0 : mpWindowImpl->mbOverlapWin = true;
95 0 : SystemWindow::ImplInit(pParent, nFloatWinStyle & ~WB_BORDER, NULL);
96 : }
97 : else
98 : {
99 : ImplBorderWindow* pBorderWin;
100 3290 : sal_uInt16 nBorderStyle = BORDERWINDOW_STYLE_BORDER | BORDERWINDOW_STYLE_FLOAT;
101 :
102 3290 : if (nStyle & WB_OWNERDRAWDECORATION)
103 0 : nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
104 : else
105 3290 : nBorderStyle |= BORDERWINDOW_STYLE_OVERLAP;
106 :
107 3290 : if ((nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE)))
108 : {
109 3290 : nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
110 3290 : nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable
111 : }
112 3290 : pBorderWin = VclPtr<ImplBorderWindow>::Create(pParent, nStyle, nBorderStyle);
113 3290 : SystemWindow::ImplInit(pBorderWin, nStyle & ~WB_BORDER, NULL);
114 3290 : pBorderWin->mpWindowImpl->mpClientWindow = this;
115 : pBorderWin->GetBorder(mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder,
116 3290 : mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder);
117 3290 : pBorderWin->SetDisplayActive(true);
118 3290 : mpWindowImpl->mpBorderWindow = pBorderWin;
119 3290 : mpWindowImpl->mpRealParent = pParent;
120 : }
121 : }
122 3290 : SetActivateMode( ActivateModeFlags::NONE );
123 :
124 3290 : mpNextFloat = NULL;
125 3290 : mpFirstPopupModeWin = NULL;
126 3290 : mnPostId = 0;
127 3290 : mnTitle = (nStyle & (WB_MOVEABLE | WB_POPUP)) ? FloatWinTitleType::Normal : FloatWinTitleType::NONE;
128 3290 : mnOldTitle = mnTitle;
129 3290 : mnPopupModeFlags = FloatWinPopupFlags::NONE;
130 3290 : mbInPopupMode = false;
131 3290 : mbPopupMode = false;
132 3290 : mbPopupModeCanceled = false;
133 3290 : mbPopupModeTearOff = false;
134 3290 : mbMouseDown = false;
135 :
136 3290 : ImplInitSettings();
137 3290 : }
138 :
139 3290 : void FloatingWindow::ImplInitSettings()
140 : {
141 3290 : const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
142 :
143 3290 : Color aColor;
144 3290 : if (IsControlBackground())
145 0 : aColor = GetControlBackground();
146 3290 : else if (Window::GetStyle() & WB_3DLOOK)
147 0 : aColor = rStyleSettings.GetFaceColor();
148 : else
149 3290 : aColor = rStyleSettings.GetWindowColor();
150 3290 : SetBackground(aColor);
151 3290 : }
152 :
153 3290 : FloatingWindow::FloatingWindow(vcl::Window* pParent, WinBits nStyle) :
154 3290 : SystemWindow(WINDOW_FLOATINGWINDOW)
155 : {
156 3290 : ImplInit(pParent, nStyle);
157 3290 : }
158 :
159 0 : FloatingWindow::FloatingWindow(vcl::Window* pParent, const OString& rID, const OUString& rUIXMLDescription, const css::uno::Reference<css::frame::XFrame> &rFrame)
160 : : SystemWindow(WINDOW_FLOATINGWINDOW)
161 : , mpNextFloat(0)
162 : , mpFirstPopupModeWin(0)
163 : , mpImplData(0)
164 : , mnPostId(0)
165 : , mnPopupModeFlags(FloatWinPopupFlags::NONE)
166 : , mnTitle(FloatWinTitleType::Unknown)
167 : , mnOldTitle(FloatWinTitleType::Unknown)
168 : , mbInPopupMode(false)
169 : , mbPopupMode(false)
170 : , mbPopupModeCanceled(false)
171 : , mbPopupModeTearOff(false)
172 : , mbMouseDown(false)
173 : , mbOldSaveBackMode(false)
174 : , mbGrabFocus(false)
175 0 : , mbInCleanUp(false)
176 : {
177 0 : loadUI(pParent, rID, rUIXMLDescription, rFrame);
178 0 : }
179 :
180 : //Find the real parent stashed in mpDialogParent.
181 0 : void FloatingWindow::doDeferredInit(WinBits nBits)
182 : {
183 0 : vcl::Window *pParent = mpDialogParent;
184 0 : mpDialogParent = NULL;
185 0 : ImplInit(pParent, nBits);
186 0 : mbIsDefferedInit = false;
187 0 : }
188 :
189 20 : void FloatingWindow::ApplySettings(vcl::RenderContext& rRenderContext)
190 : {
191 20 : const StyleSettings& rStyleSettings = rRenderContext.GetSettings().GetStyleSettings();
192 :
193 20 : Color aColor;
194 20 : if (Window::GetStyle() & WB_3DLOOK)
195 0 : aColor = rStyleSettings.GetFaceColor();
196 : else
197 20 : aColor = rStyleSettings.GetWindowColor();
198 :
199 20 : ApplyControlBackground(rRenderContext, aColor);
200 20 : }
201 :
202 6576 : FloatingWindow::~FloatingWindow()
203 : {
204 3288 : disposeOnce();
205 :
206 : // Unfortunately the vclwidgets clang plug-in says: "OutputDevice
207 : // subclass should have nothing in its destructor but a call to
208 : // disposeOnce()."
209 : // assert (!mnPostId);
210 3288 : }
211 :
212 3288 : void FloatingWindow::dispose()
213 : {
214 3288 : if (mpImplData)
215 : {
216 3288 : if( mbPopupModeCanceled )
217 : // indicates that ESC key was pressed
218 : // will be handled in Window::ImplGrabFocus()
219 0 : SetDialogControlFlags( GetDialogControlFlags() | DialogControlFlags::FloatWinPopupModeEndCancel );
220 :
221 3288 : if ( IsInPopupMode() )
222 10 : EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll | FloatWinPopupEndFlags::DontCallHdl );
223 :
224 3288 : if ( mnPostId )
225 8 : Application::RemoveUserEvent( mnPostId );
226 3288 : mnPostId = 0;
227 : }
228 :
229 3288 : delete mpImplData;
230 3288 : mpImplData = NULL;
231 :
232 3288 : mpNextFloat.clear();
233 3288 : mpFirstPopupModeWin.clear();
234 3288 : SystemWindow::dispose();
235 3288 : }
236 :
237 0 : Point FloatingWindow::CalcFloatingPosition( vcl::Window* pWindow, const Rectangle& rRect, FloatWinPopupFlags nFlags, sal_uInt16& rArrangeIndex )
238 : {
239 0 : return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
240 : }
241 :
242 12 : Point FloatingWindow::ImplCalcPos( vcl::Window* pWindow,
243 : const Rectangle& rRect, FloatWinPopupFlags nFlags,
244 : sal_uInt16& rArrangeIndex )
245 : {
246 : // get window position
247 12 : Point aPos;
248 12 : Size aSize = pWindow->GetSizePixel();
249 12 : Rectangle aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
250 12 : FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow );
251 :
252 : // convert....
253 12 : vcl::Window* pW = pWindow;
254 12 : if ( pW->mpWindowImpl->mpRealParent )
255 12 : pW = pW->mpWindowImpl->mpRealParent;
256 :
257 12 : Rectangle normRect( rRect ); // rRect is already relative to top-level window
258 12 : normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) );
259 :
260 12 : bool bRTL = AllSettings::GetLayoutRTL();
261 :
262 24 : Rectangle devRect( pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ),
263 36 : pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) );
264 :
265 12 : Rectangle devRectRTL( devRect );
266 12 : if( bRTL )
267 : // create a rect that can be compared to desktop coordinates
268 0 : devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect );
269 12 : if( Application::GetScreenCount() > 1 && Application::IsUnifiedDisplay() )
270 : aScreenRect = Application::GetScreenPosSizePixel(
271 0 : Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );
272 :
273 : FloatWinPopupFlags nArrangeAry[5];
274 : sal_uInt16 nArrangeIndex;
275 12 : Point e1,e2; // the common edge between the item rect and the floating window
276 :
277 12 : if ( nFlags & FloatWinPopupFlags::Left )
278 : {
279 0 : nArrangeAry[0] = FloatWinPopupFlags::Left;
280 0 : nArrangeAry[1] = FloatWinPopupFlags::Right;
281 0 : nArrangeAry[2] = FloatWinPopupFlags::Up;
282 0 : nArrangeAry[3] = FloatWinPopupFlags::Down;
283 0 : nArrangeAry[4] = FloatWinPopupFlags::Left;
284 : }
285 12 : else if ( nFlags & FloatWinPopupFlags::Right )
286 : {
287 0 : nArrangeAry[0] = FloatWinPopupFlags::Right;
288 0 : nArrangeAry[1] = FloatWinPopupFlags::Left;
289 0 : nArrangeAry[2] = FloatWinPopupFlags::Up;
290 0 : nArrangeAry[3] = FloatWinPopupFlags::Down;
291 0 : nArrangeAry[4] = FloatWinPopupFlags::Right;
292 : }
293 12 : else if ( nFlags & FloatWinPopupFlags::Up )
294 : {
295 0 : nArrangeAry[0] = FloatWinPopupFlags::Up;
296 0 : nArrangeAry[1] = FloatWinPopupFlags::Down;
297 0 : nArrangeAry[2] = FloatWinPopupFlags::Right;
298 0 : nArrangeAry[3] = FloatWinPopupFlags::Left;
299 0 : nArrangeAry[4] = FloatWinPopupFlags::Up;
300 : }
301 : else
302 : {
303 12 : nArrangeAry[0] = FloatWinPopupFlags::Down;
304 12 : nArrangeAry[1] = FloatWinPopupFlags::Up;
305 12 : nArrangeAry[2] = FloatWinPopupFlags::Right;
306 12 : nArrangeAry[3] = FloatWinPopupFlags::Left;
307 12 : nArrangeAry[4] = FloatWinPopupFlags::Down;
308 : }
309 12 : if ( nFlags & FloatWinPopupFlags::NoAutoArrange )
310 0 : nArrangeIndex = 4;
311 : else
312 12 : nArrangeIndex = 0;
313 :
314 12 : for ( ; nArrangeIndex < 5; nArrangeIndex++ )
315 : {
316 12 : bool bBreak = true;
317 12 : switch ( nArrangeAry[nArrangeIndex] )
318 : {
319 :
320 : case FloatWinPopupFlags::Left:
321 0 : aPos.X() = devRect.Left()-aSize.Width()+1;
322 0 : aPos.Y() = devRect.Top();
323 0 : aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
324 0 : if( bRTL ) // --- RTL --- we're comparing screen coordinates here
325 : {
326 0 : if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() )
327 0 : bBreak = false;
328 : }
329 : else
330 : {
331 0 : if ( aPos.X() < aScreenRect.Left() )
332 0 : bBreak = false;
333 : }
334 0 : if( bBreak )
335 : {
336 0 : e1 = devRect.TopLeft();
337 0 : e2 = devRect.BottomLeft();
338 : // set non-zero width
339 0 : e2.X()++;
340 : // don't clip corners
341 0 : e1.Y()++;
342 0 : e2.Y()--;
343 : }
344 0 : break;
345 : case FloatWinPopupFlags::Right:
346 0 : aPos = devRect.TopRight();
347 0 : aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
348 0 : if( bRTL ) // --- RTL --- we're comparing screen coordinates here
349 : {
350 0 : if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() )
351 0 : bBreak = false;
352 : }
353 : else
354 : {
355 0 : if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
356 0 : bBreak = false;
357 : }
358 0 : if( bBreak )
359 : {
360 0 : e1 = devRect.TopRight();
361 0 : e2 = devRect.BottomRight();
362 : // set non-zero width
363 0 : e2.X()++;
364 : // don't clip corners
365 0 : e1.Y()++;
366 0 : e2.Y()--;
367 : }
368 0 : break;
369 : case FloatWinPopupFlags::Up:
370 0 : aPos.X() = devRect.Left();
371 0 : aPos.Y() = devRect.Top()-aSize.Height()+1;
372 0 : if ( aPos.Y() < aScreenRect.Top() )
373 0 : bBreak = false;
374 0 : if( bBreak )
375 : {
376 0 : e1 = devRect.TopLeft();
377 0 : e2 = devRect.TopRight();
378 : // set non-zero height
379 0 : e2.Y()++;
380 : // don't clip corners
381 0 : e1.X()++;
382 0 : e2.X()--;
383 : }
384 0 : break;
385 : case FloatWinPopupFlags::Down:
386 12 : aPos = devRect.BottomLeft();
387 12 : if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
388 0 : bBreak = false;
389 12 : if( bBreak )
390 : {
391 12 : e1 = devRect.BottomLeft();
392 12 : e2 = devRect.BottomRight();
393 : // set non-zero height
394 12 : e2.Y()++;
395 : // don't clip corners
396 12 : e1.X()++;
397 12 : e2.X()--;
398 : }
399 12 : break;
400 0 : default: break;
401 : }
402 :
403 : // adjust if necessary
404 12 : if ( bBreak && !(nFlags & FloatWinPopupFlags::NoAutoArrange) )
405 : {
406 24 : if ( (nArrangeAry[nArrangeIndex] == FloatWinPopupFlags::Left) ||
407 12 : (nArrangeAry[nArrangeIndex] == FloatWinPopupFlags::Right) )
408 : {
409 0 : if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
410 : {
411 0 : aPos.Y() = devRect.Bottom()-aSize.Height()+1;
412 0 : if ( aPos.Y() < aScreenRect.Top() )
413 0 : aPos.Y() = aScreenRect.Top();
414 : }
415 : }
416 : else
417 : {
418 12 : if( bRTL ) // --- RTL --- we're comparing screen coordinates here
419 : {
420 0 : if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
421 0 : aPos.X() -= aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1;
422 : }
423 12 : else if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
424 : {
425 0 : aPos.X() = devRect.Right()-aSize.Width()+1;
426 0 : if ( aPos.X() < aScreenRect.Left() )
427 0 : aPos.X() = aScreenRect.Left();
428 : }
429 : }
430 : }
431 :
432 12 : if ( bBreak )
433 12 : break;
434 : }
435 12 : if ( nArrangeIndex > 4 )
436 0 : nArrangeIndex = 4;
437 :
438 12 : rArrangeIndex = nArrangeIndex;
439 :
440 12 : aPos = pW->AbsoluteScreenToOutputPixel( aPos );
441 :
442 : // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
443 12 : if( pFloatingWindow )
444 : {
445 : pFloatingWindow->mpImplData->maItemEdgeClipRect =
446 12 : Rectangle( e1, e2 );
447 : }
448 :
449 : // caller expects cordinates relative to top-level win
450 12 : return pW->OutputToScreenPixel( aPos );
451 : }
452 :
453 0 : FloatingWindow* FloatingWindow::ImplFloatHitTest( vcl::Window* pReference, const Point& rPos, HitTest& rHitTest )
454 : {
455 0 : FloatingWindow* pWin = this;
456 :
457 0 : Point aAbsolute( rPos );
458 :
459 0 : const OutputDevice *pWindowOutDev = pReference->GetOutDev();
460 :
461 : // compare coordinates in absolute screen coordinates
462 0 : if( pReference->HasMirroredGraphics() )
463 : {
464 0 : if(!pReference->IsRTLEnabled() )
465 : // --- RTL --- re-mirror back to get device coordiantes
466 0 : pWindowOutDev->ReMirror( aAbsolute );
467 :
468 0 : Rectangle aRect( pReference->ScreenToOutputPixel(aAbsolute), Size(1,1) ) ;
469 0 : aRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect );
470 0 : aAbsolute = aRect.TopLeft();
471 : }
472 : else
473 : aAbsolute = Point( pReference->OutputToAbsoluteScreenPixel(
474 0 : pReference->ScreenToOutputPixel(rPos) ) );
475 :
476 0 : do
477 : {
478 : // compute the floating window's size in absolute screen coordinates
479 :
480 : // use the border window to have the exact position
481 0 : vcl::Window *pBorderWin = pWin->GetWindow( GetWindowType::Border );
482 :
483 0 : Point aPt; // the top-left corner in output coordinates ie (0,0)
484 0 : Rectangle devRect( pBorderWin->ImplOutputToUnmirroredAbsoluteScreenPixel( Rectangle( aPt, pBorderWin->GetSizePixel()) ) ) ;
485 0 : if ( devRect.IsInside( aAbsolute ) )
486 : {
487 0 : rHitTest = HITTEST_WINDOW;
488 0 : return pWin;
489 : }
490 :
491 : // test, if mouse is in rectangle, (this is typically the rect of the active
492 : // toolbox item or similar)
493 : // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
494 : // is already in absolute device coordinates
495 0 : if ( pWin->maFloatRect.IsInside( aAbsolute ) )
496 : {
497 0 : rHitTest = HITTEST_RECT;
498 0 : return pWin;
499 : }
500 :
501 0 : pWin = pWin->mpNextFloat;
502 : }
503 : while ( pWin );
504 :
505 0 : rHitTest = HITTEST_OUTSIDE;
506 0 : return NULL;
507 : }
508 :
509 0 : FloatingWindow* FloatingWindow::ImplFindLastLevelFloat()
510 : {
511 0 : FloatingWindow* pWin = this;
512 0 : FloatingWindow* pLastFoundWin = pWin;
513 :
514 0 : do
515 : {
516 0 : if ( pWin->GetPopupModeFlags() & FloatWinPopupFlags::NewLevel )
517 0 : pLastFoundWin = pWin;
518 :
519 0 : pWin = pWin->mpNextFloat;
520 : }
521 : while ( pWin );
522 :
523 0 : return pLastFoundWin;
524 : }
525 :
526 0 : bool FloatingWindow::ImplIsFloatPopupModeWindow( const vcl::Window* pWindow )
527 : {
528 0 : FloatingWindow* pWin = this;
529 :
530 0 : do
531 : {
532 0 : if ( pWin->mpFirstPopupModeWin == pWindow )
533 0 : return true;
534 :
535 0 : pWin = pWin->mpNextFloat;
536 : }
537 : while ( pWin );
538 :
539 0 : return false;
540 : }
541 :
542 4 : IMPL_LINK_NOARG(FloatingWindow, ImplEndPopupModeHdl)
543 : {
544 2 : VclPtr<FloatingWindow> pThis(this);
545 2 : mnPostId = 0;
546 2 : mnPopupModeFlags = FloatWinPopupFlags::NONE;
547 2 : mbPopupMode = false;
548 2 : PopupModeEnd();
549 2 : return 0;
550 : }
551 :
552 16401 : bool FloatingWindow::Notify( NotifyEvent& rNEvt )
553 : {
554 : // call Base Class first for tab control
555 16401 : bool nRet = SystemWindow::Notify( rNEvt );
556 16401 : if ( !nRet )
557 : {
558 16401 : if ( rNEvt.GetType() == MouseNotifyEvent::KEYINPUT )
559 : {
560 0 : const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
561 0 : vcl::KeyCode aKeyCode = pKEvt->GetKeyCode();
562 0 : sal_uInt16 nKeyCode = aKeyCode.GetCode();
563 :
564 0 : if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
565 : {
566 0 : Close();
567 0 : return true;
568 : }
569 : }
570 : }
571 :
572 16401 : return nRet;
573 : }
574 :
575 36 : void FloatingWindow::StateChanged( StateChangedType nType )
576 : {
577 36 : if (nType == StateChangedType::InitShow)
578 : {
579 12 : DoInitialLayout();
580 : }
581 :
582 36 : SystemWindow::StateChanged( nType );
583 :
584 36 : if ( nType == StateChangedType::ControlBackground )
585 : {
586 0 : ImplInitSettings();
587 0 : Invalidate();
588 : }
589 36 : }
590 :
591 0 : void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
592 : {
593 0 : SystemWindow::DataChanged( rDCEvt );
594 :
595 0 : if ( (rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
596 0 : (rDCEvt.GetFlags() & AllSettingsFlags::STYLE) )
597 : {
598 0 : ImplInitSettings();
599 0 : Invalidate();
600 : }
601 0 : }
602 :
603 10 : void FloatingWindow::ImplCallPopupModeEnd()
604 : {
605 : // PopupMode is finished
606 10 : mbInPopupMode = false;
607 :
608 : // call Handler asynchronously.
609 10 : if ( mpImplData && !mnPostId )
610 10 : mnPostId = Application::PostUserEvent( LINK( this, FloatingWindow, ImplEndPopupModeHdl ), NULL, true );
611 10 : }
612 :
613 2 : void FloatingWindow::PopupModeEnd()
614 : {
615 2 : maPopupModeEndHdl.Call( this );
616 2 : }
617 :
618 24 : void FloatingWindow::SetTitleType( FloatWinTitleType nTitle )
619 : {
620 24 : if ( (mnTitle != nTitle) && mpWindowImpl->mpBorderWindow )
621 : {
622 0 : mnTitle = nTitle;
623 0 : Size aOutSize = GetOutputSizePixel();
624 : sal_uInt16 nTitleStyle;
625 0 : if ( nTitle == FloatWinTitleType::Normal )
626 0 : nTitleStyle = BORDERWINDOW_TITLE_SMALL;
627 0 : else if ( nTitle == FloatWinTitleType::TearOff )
628 0 : nTitleStyle = BORDERWINDOW_TITLE_TEAROFF;
629 0 : else if ( nTitle == FloatWinTitleType::Popup )
630 0 : nTitleStyle = BORDERWINDOW_TITLE_POPUP;
631 : else // nTitle == FloatWinTitleType::NONE
632 0 : nTitleStyle = BORDERWINDOW_TITLE_NONE;
633 0 : static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->SetTitleType( nTitleStyle, aOutSize );
634 0 : static_cast<ImplBorderWindow*>(mpWindowImpl->mpBorderWindow.get())->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
635 : }
636 24 : }
637 :
638 12 : void FloatingWindow::StartPopupMode( const Rectangle& rRect, FloatWinPopupFlags nFlags )
639 : {
640 12 : if ( IsRollUp() )
641 0 : RollDown();
642 :
643 : // remove title
644 12 : mnOldTitle = mnTitle;
645 12 : if ( ( mpWindowImpl->mnStyle & WB_POPUP ) && !GetText().isEmpty() )
646 0 : SetTitleType( FloatWinTitleType::Popup );
647 12 : else if ( nFlags & FloatWinPopupFlags::AllowTearOff )
648 0 : SetTitleType( FloatWinTitleType::TearOff );
649 : else
650 12 : SetTitleType( FloatWinTitleType::NONE );
651 :
652 : // avoid close on focus change for decorated floating windows only
653 12 : if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
654 0 : nFlags |= FloatWinPopupFlags::NoAppFocusClose;
655 :
656 : // #102010# For debugging Accessibility
657 12 : static const char* pEnv = getenv("SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
658 12 : if( pEnv && *pEnv )
659 0 : nFlags |= FloatWinPopupFlags::NoAppFocusClose;
660 :
661 : // compute window position according to flags and arrangement
662 : sal_uInt16 nArrangeIndex;
663 12 : Point aPos = ImplCalcPos( this, rRect, nFlags, nArrangeIndex );
664 12 : SetPosPixel( aPos );
665 :
666 : // set data and display window
667 : // convert maFloatRect to absolute device coordinates
668 : // so they can be compared across different frames
669 : // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
670 12 : maFloatRect = rRect;
671 :
672 12 : vcl::Window *pReference = GetParent();
673 12 : const OutputDevice *pParentWinOutDev = pReference->GetOutDev();
674 :
675 : // compare coordinates in absolute screen coordinates
676 : // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509
677 12 : if( pReference->HasMirroredGraphics() )
678 : {
679 0 : if(!pReference->IsRTLEnabled() )
680 : // --- RTL --- re-mirror back to get device coordiantes
681 0 : pParentWinOutDev->ReMirror(maFloatRect);
682 :
683 0 : maFloatRect.SetPos(pReference->ScreenToOutputPixel(maFloatRect.TopLeft()));
684 0 : maFloatRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel(maFloatRect);
685 : }
686 : else
687 12 : maFloatRect.SetPos(pReference->OutputToAbsoluteScreenPixel(pReference->ScreenToOutputPixel(rRect.TopLeft())));
688 :
689 12 : maFloatRect.Left() -= 2;
690 12 : maFloatRect.Top() -= 2;
691 12 : maFloatRect.Right() += 2;
692 12 : maFloatRect.Bottom() += 2;
693 12 : mnPopupModeFlags = nFlags;
694 12 : mbInPopupMode = true;
695 12 : mbPopupMode = true;
696 12 : mbPopupModeCanceled = false;
697 12 : mbPopupModeTearOff = false;
698 12 : mbMouseDown = false;
699 :
700 12 : mbOldSaveBackMode = IsSaveBackgroundEnabled();
701 12 : EnableSaveBackground();
702 :
703 : // add FloatingWindow to list of windows that are in popup mode
704 12 : ImplSVData* pSVData = ImplGetSVData();
705 12 : mpNextFloat = pSVData->maWinData.mpFirstFloat;
706 12 : pSVData->maWinData.mpFirstFloat = this;
707 12 : if( nFlags & FloatWinPopupFlags::GrabFocus )
708 : {
709 : // force key input even without focus (useful for menus)
710 8 : mbGrabFocus = true;
711 : }
712 12 : Show( true, ShowFlags::NoActivate );
713 12 : }
714 :
715 0 : void FloatingWindow::StartPopupMode( ToolBox* pBox, FloatWinPopupFlags nFlags )
716 : {
717 : // get selected button
718 0 : sal_uInt16 nItemId = pBox->GetDownItemId();
719 0 : if ( !nItemId )
720 0 : return;
721 :
722 0 : mpImplData->mpBox = pBox;
723 0 : pBox->ImplFloatControl( true, this );
724 :
725 : // retrieve some data from the ToolBox
726 0 : Rectangle aRect = pBox->GetItemRect( nItemId );
727 0 : Point aPos;
728 : // convert to parent's screen coordinates
729 0 : aPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
730 0 : aRect.SetPos( aPos );
731 :
732 0 : nFlags |=
733 : FloatWinPopupFlags::NoFocusClose |
734 : // FloatWinPopupFlags::NoMouseClose |
735 : FloatWinPopupFlags::AllMouseButtonClose |
736 : // FloatWinPopupFlags::NoMouseRectClose | // #105968# floating toolboxes should close when clicked in (parent's) float rect
737 0 : FloatWinPopupFlags::NoMouseUpClose;
738 : // | FloatWinPopupFlags::NoAppFocusClose;
739 :
740 : /*
741 : * FloatWinPopupFlags::NoKeyClose |
742 : * don't set since it disables closing floaters with escape
743 : */
744 :
745 : // set Flags for positioning
746 0 : if ( !(nFlags & (FloatWinPopupFlags::Down | FloatWinPopupFlags::Up |
747 : FloatWinPopupFlags::Left | FloatWinPopupFlags::Right |
748 0 : FloatWinPopupFlags::NoAutoArrange)) )
749 : {
750 0 : if ( pBox->IsHorizontal() )
751 0 : nFlags |= FloatWinPopupFlags::Down;
752 : else
753 0 : nFlags |= FloatWinPopupFlags::Right;
754 : }
755 :
756 : // start FloatingMode
757 0 : StartPopupMode( aRect, nFlags );
758 : }
759 :
760 20 : void FloatingWindow::ImplEndPopupMode( FloatWinPopupEndFlags nFlags, sal_uLong nFocusId )
761 : {
762 20 : if ( !mbInPopupMode )
763 28 : return;
764 :
765 12 : ImplSVData* pSVData = ImplGetSVData();
766 :
767 12 : mbInCleanUp = true; // prevent killing this window due to focus change while working with it
768 :
769 : // stop the PopupMode also for all following PopupMode windows
770 24 : while ( pSVData->maWinData.mpFirstFloat && pSVData->maWinData.mpFirstFloat.get() != this )
771 0 : pSVData->maWinData.mpFirstFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel );
772 :
773 : // delete window from the list
774 12 : pSVData->maWinData.mpFirstFloat = mpNextFloat;
775 12 : mpNextFloat = NULL;
776 :
777 12 : FloatWinPopupFlags nPopupModeFlags = mnPopupModeFlags;
778 :
779 : // hide window again if it was not deleted
780 24 : if ( !(nFlags & FloatWinPopupEndFlags::TearOff) ||
781 12 : !(nPopupModeFlags & FloatWinPopupFlags::AllowTearOff) )
782 : {
783 12 : Show( false, ShowFlags::NoFocusChange );
784 :
785 : // maybe pass focus on to a suitable FloatingWindow
786 12 : if ( nFocusId )
787 0 : Window::EndSaveFocus( nFocusId );
788 12 : else if ( pSVData->maWinData.mpFocusWin && pSVData->maWinData.mpFirstFloat &&
789 0 : ImplIsWindowOrChild( pSVData->maWinData.mpFocusWin ) )
790 0 : pSVData->maWinData.mpFirstFloat->GrabFocus();
791 12 : mbPopupModeTearOff = false;
792 : }
793 : else
794 : {
795 0 : mbPopupModeTearOff = true;
796 0 : if ( nFocusId )
797 0 : Window::EndSaveFocus( nFocusId, false );
798 : }
799 12 : EnableSaveBackground( mbOldSaveBackMode );
800 :
801 12 : mbPopupModeCanceled = bool(nFlags & FloatWinPopupEndFlags::Cancel);
802 :
803 : // redo title
804 12 : SetTitleType( mnOldTitle );
805 :
806 : // set ToolBox again to normal
807 12 : if ( mpImplData->mpBox )
808 : {
809 0 : mpImplData->mpBox->ImplFloatControl( false, this );
810 0 : mpImplData->mpBox = NULL;
811 : }
812 :
813 : // call PopupModeEnd-Handler depending on parameter
814 12 : if ( !(nFlags & FloatWinPopupEndFlags::DontCallHdl) )
815 10 : ImplCallPopupModeEnd();
816 :
817 : // close all other windows depending on parameter
818 12 : if ( nFlags & FloatWinPopupEndFlags::CloseAll )
819 : {
820 2 : if ( !(nPopupModeFlags & FloatWinPopupFlags::NewLevel) )
821 : {
822 2 : if ( pSVData->maWinData.mpFirstFloat )
823 : {
824 0 : FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
825 0 : pLastLevelFloat->EndPopupMode( FloatWinPopupEndFlags::Cancel | FloatWinPopupEndFlags::CloseAll );
826 : }
827 : }
828 : }
829 :
830 12 : mbInCleanUp = false;
831 : }
832 :
833 12 : void FloatingWindow::EndPopupMode( FloatWinPopupEndFlags nFlags )
834 : {
835 12 : ImplEndPopupMode( nFlags );
836 12 : }
837 :
838 8 : void FloatingWindow::AddPopupModeWindow( vcl::Window* pWindow )
839 : {
840 : // !!! up-to-now only 1 window and not yet a list
841 8 : mpFirstPopupModeWin = pWindow;
842 8 : }
843 :
844 0 : void FloatingWindow::setPosSizeOnContainee(Size aSize, Window &rBox)
845 : {
846 0 : sal_Int32 nBorderWidth = get_border_width();
847 :
848 0 : aSize.Width() -= mpWindowImpl->mnLeftBorder + mpWindowImpl->mnRightBorder + 2 * nBorderWidth;
849 0 : aSize.Height() -= nBorderWidth + mpWindowImpl->mnTopBorder + mpWindowImpl->mnBottomBorder + 2 * nBorderWidth;
850 :
851 0 : Point aPos(nBorderWidth, nBorderWidth);
852 0 : VclContainer::setLayoutAllocation(rBox, aPos, aSize);
853 801 : }
854 :
855 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|