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