Version 4.2.0.1, tag libreoffice-4.2.0.1
[LibreOffice.git] / vcl / source / window / floatwin.cxx
blob10f1e974b08b7fae6dd6de3261615c3e01ce92ec
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <svdata.hxx>
22 #include <brdwin.hxx>
23 #include <window.h>
24 #include <salframe.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>
32 #include <tools/rc.h>
33 #include <tools/debug.hxx>
36 // =======================================================================
38 class FloatingWindow::ImplData
40 public:
41 ImplData();
42 ~ImplData();
44 ToolBox* mpBox;
45 Rectangle maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
48 FloatingWindow::ImplData::ImplData()
50 mpBox = NULL;
53 FloatingWindow::ImplData::~ImplData()
57 Rectangle& FloatingWindow::ImplGetItemEdgeClipRect()
59 return mpImplData->maItemEdgeClipRect;
62 // =======================================================================
64 void FloatingWindow::ImplInit( Window* pParent, WinBits nStyle )
66 mpImplData = new ImplData;
68 mpWindowImpl->mbFloatWin = sal_True;
69 mbInCleanUp = sal_False;
70 mbGrabFocus = sal_False;
72 DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL!" );
74 if ( !pParent )
75 pParent = ImplGetSVData()->maWinData.mpAppWin;
77 DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists" );
79 // no Border, then we dont need a border window
80 if ( !nStyle )
82 mpWindowImpl->mbOverlapWin = sal_True;
83 nStyle |= WB_DIALOGCONTROL;
84 SystemWindow::ImplInit( pParent, nStyle, NULL );
86 else
88 if ( !(nStyle & WB_NODIALOGCONTROL) )
89 nStyle |= WB_DIALOGCONTROL;
91 if( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)
92 && !(nStyle & WB_OWNERDRAWDECORATION) )
94 WinBits nFloatWinStyle = nStyle;
95 // #99154# floaters are not closeable by default anymore, eg fullscreen floater
96 // nFloatWinStyle |= WB_CLOSEABLE;
97 mpWindowImpl->mbFrame = sal_True;
98 mpWindowImpl->mbOverlapWin = sal_True;
99 SystemWindow::ImplInit( pParent, nFloatWinStyle & ~WB_BORDER, NULL );
101 else
103 ImplBorderWindow* pBorderWin;
104 sal_uInt16 nBorderStyle = BORDERWINDOW_STYLE_BORDER | BORDERWINDOW_STYLE_FLOAT;
106 if( nStyle & WB_OWNERDRAWDECORATION ) nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
107 else nBorderStyle |= BORDERWINDOW_STYLE_OVERLAP;
109 if ( (nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE)) )
111 nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
112 nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable
114 pBorderWin = new ImplBorderWindow( pParent, nStyle, nBorderStyle );
115 SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
116 pBorderWin->mpWindowImpl->mpClientWindow = this;
117 pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
118 pBorderWin->SetDisplayActive( sal_True );
119 mpWindowImpl->mpBorderWindow = pBorderWin;
120 mpWindowImpl->mpRealParent = pParent;
123 SetActivateMode( 0 );
125 mpNextFloat = NULL;
126 mpFirstPopupModeWin = NULL;
127 mnPostId = 0;
128 mnTitle = (nStyle & (WB_MOVEABLE | WB_POPUP)) ? FLOATWIN_TITLE_NORMAL : FLOATWIN_TITLE_NONE;
129 mnOldTitle = mnTitle;
130 mnPopupModeFlags = 0;
131 mbInPopupMode = sal_False;
132 mbPopupMode = sal_False;
133 mbPopupModeCanceled = sal_False;
134 mbPopupModeTearOff = sal_False;
135 mbMouseDown = sal_False;
137 ImplInitSettings();
140 // -----------------------------------------------------------------------
142 void FloatingWindow::ImplInitSettings()
144 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
146 Color aColor;
147 if ( IsControlBackground() )
148 aColor = GetControlBackground();
149 else if ( Window::GetStyle() & WB_3DLOOK )
150 aColor = rStyleSettings.GetFaceColor();
151 else
152 aColor = rStyleSettings.GetWindowColor();
153 SetBackground( aColor );
156 // =======================================================================
158 FloatingWindow::FloatingWindow( Window* pParent, WinBits nStyle ) :
159 SystemWindow( WINDOW_FLOATINGWINDOW )
161 ImplInit( pParent, nStyle );
164 // -----------------------------------------------------------------------
166 FloatingWindow::FloatingWindow( Window* pParent, const ResId& rResId ) :
167 SystemWindow( WINDOW_FLOATINGWINDOW )
169 rResId.SetRT( RSC_FLOATINGWINDOW );
170 WinBits nStyle = ImplInitRes( rResId );
171 ImplInit( pParent, nStyle );
172 ImplLoadRes( rResId );
174 if ( !(nStyle & WB_HIDE) )
175 Show();
178 // -----------------------------------------------------------------------
180 void FloatingWindow::ImplLoadRes( const ResId& rResId )
182 SystemWindow::ImplLoadRes( rResId );
184 sal_uLong nObjMask = ReadLongRes();
186 if ( (RSC_FLOATINGWINDOW_WHMAPMODE | RSC_FLOATINGWINDOW_WIDTH |
187 RSC_FLOATINGWINDOW_HEIGHT) & nObjMask )
189 // Groessenangabe aus der Resource verwenden
190 Size aSize;
191 MapUnit eSizeMap = MAP_PIXEL;
193 if ( RSC_FLOATINGWINDOW_WHMAPMODE & nObjMask )
194 eSizeMap = (MapUnit) ReadShortRes();
195 if ( RSC_FLOATINGWINDOW_WIDTH & nObjMask )
196 aSize.Width() = ReadShortRes();
197 if ( RSC_FLOATINGWINDOW_HEIGHT & nObjMask )
198 aSize.Height() = ReadShortRes();
200 SetRollUpOutputSizePixel( LogicToPixel( aSize, eSizeMap ) );
203 if (nObjMask & RSC_FLOATINGWINDOW_ZOOMIN )
205 if ( ReadShortRes() )
206 RollUp();
210 // -----------------------------------------------------------------------
212 FloatingWindow::~FloatingWindow()
214 if( mbPopupModeCanceled )
215 // indicates that ESC key was pressed
216 // will be handled in Window::ImplGrabFocus()
217 SetDialogControlFlags( GetDialogControlFlags() | WINDOW_DLGCTRL_FLOATWIN_POPUPMODEEND_CANCEL );
219 if ( IsInPopupMode() )
220 EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL | FLOATWIN_POPUPMODEEND_DONTCALLHDL );
222 if ( mnPostId )
223 Application::RemoveUserEvent( mnPostId );
225 delete mpImplData;
228 // -----------------------------------------------------------------------
230 Point FloatingWindow::CalcFloatingPosition( Window* pWindow, const Rectangle& rRect, sal_uLong nFlags, sal_uInt16& rArrangeIndex )
232 return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
235 // -----------------------------------------------------------------------
237 Point FloatingWindow::ImplCalcPos( Window* pWindow,
238 const Rectangle& rRect, sal_uLong nFlags,
239 sal_uInt16& rArrangeIndex )
241 // Fenster-Position ermitteln
242 Point aPos;
243 Size aSize = pWindow->GetSizePixel();
244 Rectangle aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
245 FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow );
247 // convert....
248 Window* pW = pWindow;
249 if ( pW->mpWindowImpl->mpRealParent )
250 pW = pW->mpWindowImpl->mpRealParent;
252 Rectangle normRect( rRect ); // rRect is already relative to top-level window
253 normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) );
255 sal_Bool bRTL = Application::GetSettings().GetLayoutRTL();
257 Rectangle devRect( pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ),
258 pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) );
260 Rectangle devRectRTL( devRect );
261 if( bRTL )
262 // create a rect that can be compared to desktop coordinates
263 devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect );
264 if( Application::GetScreenCount() > 1 && Application::IsUnifiedDisplay() )
265 aScreenRect = Application::GetScreenPosSizePixel(
266 Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );
269 sal_uInt16 nArrangeAry[5];
270 sal_uInt16 nArrangeIndex;
271 bool bBreak;
272 Point e1,e2; // the common edge between the item rect and the floating window
274 if ( nFlags & FLOATWIN_POPUPMODE_LEFT )
276 nArrangeAry[0] = FLOATWIN_POPUPMODE_LEFT;
277 nArrangeAry[1] = FLOATWIN_POPUPMODE_RIGHT;
278 nArrangeAry[2] = FLOATWIN_POPUPMODE_UP;
279 nArrangeAry[3] = FLOATWIN_POPUPMODE_DOWN;
280 nArrangeAry[4] = FLOATWIN_POPUPMODE_LEFT;
282 else if ( nFlags & FLOATWIN_POPUPMODE_RIGHT )
284 nArrangeAry[0] = FLOATWIN_POPUPMODE_RIGHT;
285 nArrangeAry[1] = FLOATWIN_POPUPMODE_LEFT;
286 nArrangeAry[2] = FLOATWIN_POPUPMODE_UP;
287 nArrangeAry[3] = FLOATWIN_POPUPMODE_DOWN;
288 nArrangeAry[4] = FLOATWIN_POPUPMODE_RIGHT;
290 else if ( nFlags & FLOATWIN_POPUPMODE_UP )
292 nArrangeAry[0] = FLOATWIN_POPUPMODE_UP;
293 nArrangeAry[1] = FLOATWIN_POPUPMODE_DOWN;
294 nArrangeAry[2] = FLOATWIN_POPUPMODE_RIGHT;
295 nArrangeAry[3] = FLOATWIN_POPUPMODE_LEFT;
296 nArrangeAry[4] = FLOATWIN_POPUPMODE_UP;
298 else
300 nArrangeAry[0] = FLOATWIN_POPUPMODE_DOWN;
301 nArrangeAry[1] = FLOATWIN_POPUPMODE_UP;
302 nArrangeAry[2] = FLOATWIN_POPUPMODE_RIGHT;
303 nArrangeAry[3] = FLOATWIN_POPUPMODE_LEFT;
304 nArrangeAry[4] = FLOATWIN_POPUPMODE_DOWN;
306 if ( nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE )
307 nArrangeIndex = 4;
308 else
309 nArrangeIndex = 0;
311 for ( ; nArrangeIndex < 5; nArrangeIndex++ )
313 bBreak = true;
314 switch ( nArrangeAry[nArrangeIndex] )
317 case FLOATWIN_POPUPMODE_LEFT:
318 aPos.X() = devRect.Left()-aSize.Width()+1;
319 aPos.Y() = devRect.Top();
320 aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
321 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
323 if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() )
324 bBreak = false;
326 else
328 if ( aPos.X() < aScreenRect.Left() )
329 bBreak = false;
331 if( bBreak )
333 e1 = devRect.TopLeft();
334 e2 = devRect.BottomLeft();
335 // set non-zero width
336 e2.X()++;
337 // don't clip corners
338 e1.Y()++;
339 e2.Y()--;
341 break;
342 case FLOATWIN_POPUPMODE_RIGHT:
343 aPos = devRect.TopRight();
344 aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
345 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
347 if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() )
348 bBreak = false;
350 else
352 if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
353 bBreak = false;
355 if( bBreak )
357 e1 = devRect.TopRight();
358 e2 = devRect.BottomRight();
359 // set non-zero width
360 e2.X()++;
361 // don't clip corners
362 e1.Y()++;
363 e2.Y()--;
365 break;
366 case FLOATWIN_POPUPMODE_UP:
367 aPos.X() = devRect.Left();
368 aPos.Y() = devRect.Top()-aSize.Height()+1;
369 if ( aPos.Y() < aScreenRect.Top() )
370 bBreak = false;
371 if( bBreak )
373 e1 = devRect.TopLeft();
374 e2 = devRect.TopRight();
375 // set non-zero height
376 e2.Y()++;
377 // don't clip corners
378 e1.X()++;
379 e2.X()--;
381 break;
382 case FLOATWIN_POPUPMODE_DOWN:
383 aPos = devRect.BottomLeft();
384 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
385 bBreak = false;
386 if( bBreak )
388 e1 = devRect.BottomLeft();
389 e2 = devRect.BottomRight();
390 // set non-zero height
391 e2.Y()++;
392 // don't clip corners
393 e1.X()++;
394 e2.X()--;
396 break;
399 // Evt. noch anpassen
400 if ( bBreak && !(nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE) )
402 if ( (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_LEFT) ||
403 (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_RIGHT) )
405 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
407 aPos.Y() = devRect.Bottom()-aSize.Height()+1;
408 if ( aPos.Y() < aScreenRect.Top() )
409 aPos.Y() = aScreenRect.Top();
412 else
414 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
416 if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
417 aPos.X() -= aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1;
419 else if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
421 aPos.X() = devRect.Right()-aSize.Width()+1;
422 if ( aPos.X() < aScreenRect.Left() )
423 aPos.X() = aScreenRect.Left();
428 if ( bBreak )
429 break;
431 if ( nArrangeIndex > 4 )
432 nArrangeIndex = 4;
434 rArrangeIndex = nArrangeIndex;
436 aPos = pW->AbsoluteScreenToOutputPixel( aPos );
438 // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
439 if( pFloatingWindow )
441 pFloatingWindow->mpImplData->maItemEdgeClipRect =
442 Rectangle( e1, e2 );
445 // caller expects cordinates relative to top-level win
446 return pW->OutputToScreenPixel( aPos );
449 // -----------------------------------------------------------------------
451 FloatingWindow* FloatingWindow::ImplFloatHitTest( Window* pReference, const Point& rPos, sal_uInt16& rHitTest )
453 FloatingWindow* pWin = this;
455 Point aAbsolute( rPos );
457 // compare coordinates in absolute screen coordinates
458 if( pReference->ImplHasMirroredGraphics() )
460 if(!pReference->IsRTLEnabled() )
461 // --- RTL --- re-mirror back to get device coordiantes
462 pReference->ImplReMirror( aAbsolute );
464 Rectangle aRect( pReference->ScreenToOutputPixel(aAbsolute), Size(1,1) ) ;
465 aRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect );
466 aAbsolute = aRect.TopLeft();
468 else
469 aAbsolute = Point( pReference->OutputToAbsoluteScreenPixel(
470 pReference->ScreenToOutputPixel(rPos) ) );
474 // compute the floating window's size in absolute screen coordinates
476 // use the border window to have the exact position
477 Window *pBorderWin = pWin->GetWindow( WINDOW_BORDER );
479 Point aPt; // the top-left corner in output coordinates ie (0,0)
480 Rectangle devRect( pBorderWin->ImplOutputToUnmirroredAbsoluteScreenPixel( Rectangle( aPt, pBorderWin->GetSizePixel()) ) ) ;
481 if ( devRect.IsInside( aAbsolute ) )
483 rHitTest = IMPL_FLOATWIN_HITTEST_WINDOW;
484 return pWin;
487 // test, if mouse is in rectangle, (this is typically the rect of the active
488 // toolbox item or similar)
489 // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
490 // is already in absolute device coordinates
491 if ( pWin->maFloatRect.IsInside( aAbsolute ) )
493 rHitTest = IMPL_FLOATWIN_HITTEST_RECT;
494 return pWin;
497 pWin = pWin->mpNextFloat;
499 while ( pWin );
501 rHitTest = IMPL_FLOATWIN_HITTEST_OUTSIDE;
502 return NULL;
505 // -----------------------------------------------------------------------
507 FloatingWindow* FloatingWindow::ImplFindLastLevelFloat()
509 FloatingWindow* pWin = this;
510 FloatingWindow* pLastFoundWin = pWin;
514 if ( pWin->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NEWLEVEL )
515 pLastFoundWin = pWin;
517 pWin = pWin->mpNextFloat;
519 while ( pWin );
521 return pLastFoundWin;
524 // -----------------------------------------------------------------------
526 sal_Bool FloatingWindow::ImplIsFloatPopupModeWindow( const Window* pWindow )
528 FloatingWindow* pWin = this;
532 if ( pWin->mpFirstPopupModeWin == pWindow )
533 return sal_True;
535 pWin = pWin->mpNextFloat;
537 while ( pWin );
539 return sal_False;
542 // -----------------------------------------------------------------------
544 IMPL_LINK_NOARG(FloatingWindow, ImplEndPopupModeHdl)
546 mnPostId = 0;
547 mnPopupModeFlags = 0;
548 mbPopupMode = sal_False;
549 PopupModeEnd();
550 return 0;
553 // -----------------------------------------------------------------------
555 long FloatingWindow::Notify( NotifyEvent& rNEvt )
557 // Zuerst Basisklasse rufen wegen TabSteuerung
558 long nRet = SystemWindow::Notify( rNEvt );
559 if ( !nRet )
561 if ( rNEvt.GetType() == EVENT_KEYINPUT )
563 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
564 KeyCode aKeyCode = pKEvt->GetKeyCode();
565 sal_uInt16 nKeyCode = aKeyCode.GetCode();
567 if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
569 Close();
570 return sal_True;
575 return nRet;
578 // -----------------------------------------------------------------------
580 void FloatingWindow::StateChanged( StateChangedType nType )
582 SystemWindow::StateChanged( nType );
584 if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
586 ImplInitSettings();
587 Invalidate();
591 // -----------------------------------------------------------------------
593 void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
595 SystemWindow::DataChanged( rDCEvt );
597 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
598 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
600 ImplInitSettings();
601 Invalidate();
605 // -----------------------------------------------------------------------
607 void FloatingWindow::ImplCallPopupModeEnd()
609 // PopupMode wurde beendet
610 mbInPopupMode = sal_False;
612 // Handler asyncron rufen
613 if ( !mnPostId )
614 Application::PostUserEvent( mnPostId, LINK( this, FloatingWindow, ImplEndPopupModeHdl ) );
617 // -----------------------------------------------------------------------
619 void FloatingWindow::PopupModeEnd()
621 maPopupModeEndHdl.Call( this );
624 // -----------------------------------------------------------------------
626 void FloatingWindow::SetTitleType( sal_uInt16 nTitle )
628 if ( (mnTitle != nTitle) && mpWindowImpl->mpBorderWindow )
630 mnTitle = nTitle;
631 Size aOutSize = GetOutputSizePixel();
632 sal_uInt16 nTitleStyle;
633 if ( nTitle == FLOATWIN_TITLE_NORMAL )
634 nTitleStyle = BORDERWINDOW_TITLE_SMALL;
635 else if ( nTitle == FLOATWIN_TITLE_TEAROFF )
636 nTitleStyle = BORDERWINDOW_TITLE_TEAROFF;
637 else if ( nTitle == FLOATWIN_TITLE_POPUP )
638 nTitleStyle = BORDERWINDOW_TITLE_POPUP;
639 else // nTitle == FLOATWIN_TITLE_NONE
640 nTitleStyle = BORDERWINDOW_TITLE_NONE;
641 ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetTitleType( nTitleStyle, aOutSize );
642 ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
646 // -----------------------------------------------------------------------
648 void FloatingWindow::StartPopupMode( const Rectangle& rRect, sal_uLong nFlags )
650 // avoid flickering
651 if ( IsVisible() )
652 Show( sal_False, SHOW_NOFOCUSCHANGE );
654 if ( IsRollUp() )
655 RollDown();
657 // remove title
658 mnOldTitle = mnTitle;
659 if ( ( mpWindowImpl->mnStyle & WB_POPUP ) && !GetText().isEmpty() )
660 SetTitleType( FLOATWIN_TITLE_POPUP );
661 else if ( nFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF )
662 SetTitleType( FLOATWIN_TITLE_TEAROFF );
663 else
664 SetTitleType( FLOATWIN_TITLE_NONE );
666 // avoid close on focus change for decorated floating windows only
667 if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
668 nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
670 // #102010# For debugging Accessibility
671 static const char* pEnv = getenv("SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
672 if( pEnv && *pEnv )
673 nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
675 // compute window position according to flags and arrangement
676 sal_uInt16 nArrangeIndex;
677 Point aPos = ImplCalcPos( this, rRect, nFlags, nArrangeIndex );
678 SetPosPixel( aPos );
680 // set data and display window
681 // convert maFloatRect to absolute device coordinates
682 // so they can be compared across different frames
683 // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
684 maFloatRect = rRect;
686 Window *pReference = GetParent();
688 // compare coordinates in absolute screen coordinates
689 // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509
690 if( pReference->ImplHasMirroredGraphics() )
692 if(!pReference->IsRTLEnabled() )
693 // --- RTL --- re-mirror back to get device coordiantes
694 pReference->ImplReMirror(maFloatRect);
696 maFloatRect.SetPos(pReference->ScreenToOutputPixel(maFloatRect.TopLeft()));
697 maFloatRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel(maFloatRect);
699 else
700 maFloatRect.SetPos(pReference->OutputToAbsoluteScreenPixel(pReference->ScreenToOutputPixel(rRect.TopLeft())));
702 maFloatRect.Left() -= 2;
703 maFloatRect.Top() -= 2;
704 maFloatRect.Right() += 2;
705 maFloatRect.Bottom() += 2;
706 mnPopupModeFlags = nFlags;
707 mbInPopupMode = sal_True;
708 mbPopupMode = sal_True;
709 mbPopupModeCanceled = sal_False;
710 mbPopupModeTearOff = sal_False;
711 mbMouseDown = sal_False;
713 mbOldSaveBackMode = IsSaveBackgroundEnabled();
714 EnableSaveBackground();
716 // add FloatingWindow to list of windows that are in popup mode
717 ImplSVData* pSVData = ImplGetSVData();
718 mpNextFloat = pSVData->maWinData.mpFirstFloat;
719 pSVData->maWinData.mpFirstFloat = this;
720 if( nFlags & FLOATWIN_POPUPMODE_GRABFOCUS )
722 // force key input even without focus (useful for menus)
723 mbGrabFocus = sal_True;
725 Show( sal_True, SHOW_NOACTIVATE );
728 // -----------------------------------------------------------------------
730 void FloatingWindow::StartPopupMode( ToolBox* pBox, sal_uLong nFlags )
732 // get selected button
733 sal_uInt16 nItemId = pBox->GetDownItemId();
734 if ( !nItemId )
735 return;
737 mpImplData->mpBox = pBox;
738 pBox->ImplFloatControl( sal_True, this );
740 // retrieve some data from the ToolBox
741 Rectangle aRect = pBox->GetItemRect( nItemId );
742 Point aPos;
743 // convert to parent's screen coordinates
744 aPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
745 aRect.SetPos( aPos );
747 nFlags |=
748 FLOATWIN_POPUPMODE_NOFOCUSCLOSE |
749 // FLOATWIN_POPUPMODE_NOMOUSECLOSE |
750 FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |
751 // FLOATWIN_POPUPMODE_NOMOUSERECTCLOSE | // #105968# floating toolboxes should close when clicked in (parent's) float rect
752 FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE;
753 // | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
756 * FLOATWIN_POPUPMODE_NOKEYCLOSE |
757 * don't set since it disables closing floaters with escape
760 // Flags fuer Positionierung bestimmen
761 if ( !(nFlags & (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_UP |
762 FLOATWIN_POPUPMODE_LEFT | FLOATWIN_POPUPMODE_RIGHT |
763 FLOATWIN_POPUPMODE_NOAUTOARRANGE)) )
765 if ( pBox->IsHorizontal() )
766 nFlags |= FLOATWIN_POPUPMODE_DOWN;
767 else
768 nFlags |= FLOATWIN_POPUPMODE_RIGHT;
771 // FloatingModus starten
772 StartPopupMode( aRect, nFlags );
775 // -----------------------------------------------------------------------
777 void FloatingWindow::ImplEndPopupMode( sal_uInt16 nFlags, sal_uLong nFocusId )
779 if ( !mbInPopupMode )
780 return;
782 ImplSVData* pSVData = ImplGetSVData();
784 mbInCleanUp = sal_True; // prevent killing this window due to focus change while working with it
786 // Bei allen nachfolgenden PopupMode-Fenster den Modus auch beenden
787 while ( pSVData->maWinData.mpFirstFloat && pSVData->maWinData.mpFirstFloat != this )
788 pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
791 // Fenster aus der Liste austragen
792 pSVData->maWinData.mpFirstFloat = mpNextFloat;
793 mpNextFloat = NULL;
795 sal_uLong nPopupModeFlags = mnPopupModeFlags;
797 // Wenn nicht abgerissen wurde, dann Fenster wieder Hiden
798 if ( !(nFlags & FLOATWIN_POPUPMODEEND_TEAROFF) ||
799 !(nPopupModeFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF) )
801 Show( sal_False, SHOW_NOFOCUSCHANGE );
803 // Focus evt. auf ein entsprechendes FloatingWindow weiterschalten
804 if ( nFocusId )
805 Window::EndSaveFocus( nFocusId );
806 else if ( pSVData->maWinData.mpFocusWin && pSVData->maWinData.mpFirstFloat &&
807 ImplIsWindowOrChild( pSVData->maWinData.mpFocusWin ) )
808 pSVData->maWinData.mpFirstFloat->GrabFocus();
809 mbPopupModeTearOff = sal_False;
811 else
813 mbPopupModeTearOff = sal_True;
814 if ( nFocusId )
815 Window::EndSaveFocus( nFocusId, sal_False );
817 EnableSaveBackground( mbOldSaveBackMode );
819 mbPopupModeCanceled = (nFlags & FLOATWIN_POPUPMODEEND_CANCEL) != 0;
821 // Gegebenenfalls den Title wieder herstellen
822 SetTitleType( mnOldTitle );
824 // ToolBox wieder auf normal schalten
825 if ( mpImplData->mpBox )
827 mpImplData->mpBox->ImplFloatControl( sal_False, this );
828 mpImplData->mpBox = NULL;
831 // Je nach Parameter den PopupModeEnd-Handler rufen
832 if ( !(nFlags & FLOATWIN_POPUPMODEEND_DONTCALLHDL) )
833 ImplCallPopupModeEnd();
835 // Je nach Parameter die restlichen Fenster auch noch schliessen
836 if ( nFlags & FLOATWIN_POPUPMODEEND_CLOSEALL )
838 if ( !(nPopupModeFlags & FLOATWIN_POPUPMODE_NEWLEVEL) )
840 if ( pSVData->maWinData.mpFirstFloat )
842 FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
843 pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
848 mbInCleanUp = sal_False;
851 // -----------------------------------------------------------------------
853 void FloatingWindow::EndPopupMode( sal_uInt16 nFlags )
855 ImplEndPopupMode( nFlags );
858 // -----------------------------------------------------------------------
860 void FloatingWindow::AddPopupModeWindow( Window* pWindow )
862 // !!! bisher erst 1 Fenster und noch keine Liste
863 mpFirstPopupModeWin = pWindow;
866 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */