Version 3.6.0.2, tag libreoffice-3.6.0.2
[LibreOffice.git] / vcl / source / window / floatwin.cxx
blob44f172f262590551b9c5f194720b80623374f753
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include <svdata.hxx>
31 #include <brdwin.hxx>
32 #include <window.h>
33 #include <salframe.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/wrkwin.hxx>
37 #include <vcl/event.hxx>
38 #include <vcl/toolbox.hxx>
39 #include <vcl/floatwin.hxx>
41 #include <tools/rc.h>
42 #include <tools/debug.hxx>
45 // =======================================================================
47 class FloatingWindow::ImplData
49 public:
50 ImplData();
51 ~ImplData();
53 ToolBox* mpBox;
54 Rectangle maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
57 FloatingWindow::ImplData::ImplData()
59 mpBox = NULL;
62 FloatingWindow::ImplData::~ImplData()
66 Rectangle& FloatingWindow::ImplGetItemEdgeClipRect()
68 return mpImplData->maItemEdgeClipRect;
71 // =======================================================================
73 void FloatingWindow::ImplInit( Window* pParent, WinBits nStyle )
75 mpImplData = new ImplData;
77 mpWindowImpl->mbFloatWin = sal_True;
78 mbInCleanUp = sal_False;
79 mbGrabFocus = sal_False;
81 DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL!" );
83 if ( !pParent )
84 pParent = ImplGetSVData()->maWinData.mpAppWin;
86 DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists" );
88 // no Border, then we dont need a border window
89 if ( !nStyle )
91 mpWindowImpl->mbOverlapWin = sal_True;
92 nStyle |= WB_DIALOGCONTROL;
93 SystemWindow::ImplInit( pParent, nStyle, NULL );
95 else
97 if ( !(nStyle & WB_NODIALOGCONTROL) )
98 nStyle |= WB_DIALOGCONTROL;
100 if( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)
101 && !(nStyle & WB_OWNERDRAWDECORATION) )
103 WinBits nFloatWinStyle = nStyle;
104 // #99154# floaters are not closeable by default anymore, eg fullscreen floater
105 // nFloatWinStyle |= WB_CLOSEABLE;
106 mpWindowImpl->mbFrame = sal_True;
107 mpWindowImpl->mbOverlapWin = sal_True;
108 SystemWindow::ImplInit( pParent, nFloatWinStyle & ~WB_BORDER, NULL );
110 else
112 ImplBorderWindow* pBorderWin;
113 sal_uInt16 nBorderStyle = BORDERWINDOW_STYLE_BORDER | BORDERWINDOW_STYLE_FLOAT;
115 if( nStyle & WB_OWNERDRAWDECORATION ) nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
116 else nBorderStyle |= BORDERWINDOW_STYLE_OVERLAP;
118 if ( (nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE)) )
120 nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
121 nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable
123 pBorderWin = new ImplBorderWindow( pParent, nStyle, nBorderStyle );
124 SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
125 pBorderWin->mpWindowImpl->mpClientWindow = this;
126 pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
127 pBorderWin->SetDisplayActive( sal_True );
128 mpWindowImpl->mpBorderWindow = pBorderWin;
129 mpWindowImpl->mpRealParent = pParent;
132 SetActivateMode( 0 );
134 mpNextFloat = NULL;
135 mpFirstPopupModeWin = NULL;
136 mnPostId = 0;
137 mnTitle = (nStyle & (WB_MOVEABLE | WB_POPUP)) ? FLOATWIN_TITLE_NORMAL : FLOATWIN_TITLE_NONE;
138 mnOldTitle = mnTitle;
139 mnPopupModeFlags = 0;
140 mbInPopupMode = sal_False;
141 mbPopupMode = sal_False;
142 mbPopupModeCanceled = sal_False;
143 mbPopupModeTearOff = sal_False;
144 mbMouseDown = sal_False;
146 ImplInitSettings();
149 // -----------------------------------------------------------------------
151 void FloatingWindow::ImplInitSettings()
153 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
155 Color aColor;
156 if ( IsControlBackground() )
157 aColor = GetControlBackground();
158 else if ( Window::GetStyle() & WB_3DLOOK )
159 aColor = rStyleSettings.GetFaceColor();
160 else
161 aColor = rStyleSettings.GetWindowColor();
162 SetBackground( aColor );
165 // =======================================================================
167 FloatingWindow::FloatingWindow( Window* pParent, WinBits nStyle ) :
168 SystemWindow( WINDOW_FLOATINGWINDOW )
170 ImplInit( pParent, nStyle );
173 // -----------------------------------------------------------------------
175 FloatingWindow::FloatingWindow( Window* pParent, const ResId& rResId ) :
176 SystemWindow( WINDOW_FLOATINGWINDOW )
178 rResId.SetRT( RSC_FLOATINGWINDOW );
179 WinBits nStyle = ImplInitRes( rResId );
180 ImplInit( pParent, nStyle );
181 ImplLoadRes( rResId );
183 if ( !(nStyle & WB_HIDE) )
184 Show();
187 // -----------------------------------------------------------------------
189 void FloatingWindow::ImplLoadRes( const ResId& rResId )
191 SystemWindow::ImplLoadRes( rResId );
193 sal_uLong nObjMask = ReadLongRes();
195 if ( (RSC_FLOATINGWINDOW_WHMAPMODE | RSC_FLOATINGWINDOW_WIDTH |
196 RSC_FLOATINGWINDOW_HEIGHT) & nObjMask )
198 // Groessenangabe aus der Resource verwenden
199 Size aSize;
200 MapUnit eSizeMap = MAP_PIXEL;
202 if ( RSC_FLOATINGWINDOW_WHMAPMODE & nObjMask )
203 eSizeMap = (MapUnit) ReadShortRes();
204 if ( RSC_FLOATINGWINDOW_WIDTH & nObjMask )
205 aSize.Width() = ReadShortRes();
206 if ( RSC_FLOATINGWINDOW_HEIGHT & nObjMask )
207 aSize.Height() = ReadShortRes();
209 SetRollUpOutputSizePixel( LogicToPixel( aSize, eSizeMap ) );
212 if (nObjMask & RSC_FLOATINGWINDOW_ZOOMIN )
214 if ( ReadShortRes() )
215 RollUp();
219 // -----------------------------------------------------------------------
221 FloatingWindow::~FloatingWindow()
223 if( mbPopupModeCanceled )
224 // indicates that ESC key was pressed
225 // will be handled in Window::ImplGrabFocus()
226 SetDialogControlFlags( GetDialogControlFlags() | WINDOW_DLGCTRL_FLOATWIN_POPUPMODEEND_CANCEL );
228 if ( IsInPopupMode() )
229 EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL | FLOATWIN_POPUPMODEEND_DONTCALLHDL );
231 if ( mnPostId )
232 Application::RemoveUserEvent( mnPostId );
234 delete mpImplData;
237 // -----------------------------------------------------------------------
239 Point FloatingWindow::CalcFloatingPosition( Window* pWindow, const Rectangle& rRect, sal_uLong nFlags, sal_uInt16& rArrangeIndex )
241 return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
244 // -----------------------------------------------------------------------
246 Point FloatingWindow::ImplCalcPos( Window* pWindow,
247 const Rectangle& rRect, sal_uLong nFlags,
248 sal_uInt16& rArrangeIndex )
250 // Fenster-Position ermitteln
251 Point aPos;
252 Size aSize = pWindow->GetSizePixel();
253 Rectangle aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
254 FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow );
256 // convert....
257 Window* pW = pWindow;
258 if ( pW->mpWindowImpl->mpRealParent )
259 pW = pW->mpWindowImpl->mpRealParent;
261 Rectangle normRect( rRect ); // rRect is already relative to top-level window
262 normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) );
264 sal_Bool bRTL = Application::GetSettings().GetLayoutRTL();
266 Rectangle devRect( pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ),
267 pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) );
269 Rectangle devRectRTL( devRect );
270 if( bRTL )
271 // create a rect that can be compared to desktop coordinates
272 devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect );
273 if( Application::GetScreenCount() > 1 && Application::IsUnifiedDisplay() )
274 aScreenRect = Application::GetScreenPosSizePixel(
275 Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );
278 sal_uInt16 nArrangeAry[5];
279 sal_uInt16 nArrangeIndex;
280 sal_Bool bBreak;
281 Point e1,e2; // the common edge between the item rect and the floating window
283 if ( nFlags & FLOATWIN_POPUPMODE_LEFT )
285 nArrangeAry[0] = FLOATWIN_POPUPMODE_LEFT;
286 nArrangeAry[1] = FLOATWIN_POPUPMODE_RIGHT;
287 nArrangeAry[2] = FLOATWIN_POPUPMODE_UP;
288 nArrangeAry[3] = FLOATWIN_POPUPMODE_DOWN;
289 nArrangeAry[4] = FLOATWIN_POPUPMODE_LEFT;
291 else if ( nFlags & FLOATWIN_POPUPMODE_RIGHT )
293 nArrangeAry[0] = FLOATWIN_POPUPMODE_RIGHT;
294 nArrangeAry[1] = FLOATWIN_POPUPMODE_LEFT;
295 nArrangeAry[2] = FLOATWIN_POPUPMODE_UP;
296 nArrangeAry[3] = FLOATWIN_POPUPMODE_DOWN;
297 nArrangeAry[4] = FLOATWIN_POPUPMODE_RIGHT;
299 else if ( nFlags & FLOATWIN_POPUPMODE_UP )
301 nArrangeAry[0] = FLOATWIN_POPUPMODE_UP;
302 nArrangeAry[1] = FLOATWIN_POPUPMODE_DOWN;
303 nArrangeAry[2] = FLOATWIN_POPUPMODE_RIGHT;
304 nArrangeAry[3] = FLOATWIN_POPUPMODE_LEFT;
305 nArrangeAry[4] = FLOATWIN_POPUPMODE_UP;
307 else
309 nArrangeAry[0] = FLOATWIN_POPUPMODE_DOWN;
310 nArrangeAry[1] = FLOATWIN_POPUPMODE_UP;
311 nArrangeAry[2] = FLOATWIN_POPUPMODE_RIGHT;
312 nArrangeAry[3] = FLOATWIN_POPUPMODE_LEFT;
313 nArrangeAry[4] = FLOATWIN_POPUPMODE_DOWN;
315 if ( nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE )
316 nArrangeIndex = 4;
317 else
318 nArrangeIndex = 0;
320 for ( ; nArrangeIndex < 5; nArrangeIndex++ )
322 bBreak = sal_True;
323 switch ( nArrangeAry[nArrangeIndex] )
326 case FLOATWIN_POPUPMODE_LEFT:
327 aPos.X() = devRect.Left()-aSize.Width()+1;
328 aPos.Y() = devRect.Top();
329 aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
330 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
332 if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() )
333 bBreak = sal_False;
335 else
337 if ( aPos.X() < aScreenRect.Left() )
338 bBreak = sal_False;
340 if( bBreak )
342 e1 = devRect.TopLeft();
343 e2 = devRect.BottomLeft();
344 // set non-zero width
345 e2.X()++;
346 // don't clip corners
347 e1.Y()++;
348 e2.Y()--;
350 break;
351 case FLOATWIN_POPUPMODE_RIGHT:
352 aPos = devRect.TopRight();
353 aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
354 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
356 if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() )
357 bBreak = sal_False;
359 else
361 if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
362 bBreak = sal_False;
364 if( bBreak )
366 e1 = devRect.TopRight();
367 e2 = devRect.BottomRight();
368 // set non-zero width
369 e2.X()++;
370 // don't clip corners
371 e1.Y()++;
372 e2.Y()--;
374 break;
375 case FLOATWIN_POPUPMODE_UP:
376 aPos.X() = devRect.Left();
377 aPos.Y() = devRect.Top()-aSize.Height()+1;
378 if ( aPos.Y() < aScreenRect.Top() )
379 bBreak = sal_False;
380 if( bBreak )
382 e1 = devRect.TopLeft();
383 e2 = devRect.TopRight();
384 // set non-zero height
385 e2.Y()++;
386 // don't clip corners
387 e1.X()++;
388 e2.X()--;
390 break;
391 case FLOATWIN_POPUPMODE_DOWN:
392 aPos = devRect.BottomLeft();
393 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
394 bBreak = sal_False;
395 if( bBreak )
397 e1 = devRect.BottomLeft();
398 e2 = devRect.BottomRight();
399 // set non-zero height
400 e2.Y()++;
401 // don't clip corners
402 e1.X()++;
403 e2.X()--;
405 break;
408 // Evt. noch anpassen
409 if ( bBreak && !(nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE) )
411 if ( (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_LEFT) ||
412 (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_RIGHT) )
414 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
416 aPos.Y() = devRect.Bottom()-aSize.Height()+1;
417 if ( aPos.Y() < aScreenRect.Top() )
418 aPos.Y() = aScreenRect.Top();
421 else
423 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
425 if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
426 aPos.X() -= aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1;
428 else if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
430 aPos.X() = devRect.Right()-aSize.Width()+1;
431 if ( aPos.X() < aScreenRect.Left() )
432 aPos.X() = aScreenRect.Left();
437 if ( bBreak )
438 break;
440 if ( nArrangeIndex > 4 )
441 nArrangeIndex = 4;
443 rArrangeIndex = nArrangeIndex;
445 aPos = pW->AbsoluteScreenToOutputPixel( aPos );
447 // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
448 if( pFloatingWindow )
450 pFloatingWindow->mpImplData->maItemEdgeClipRect =
451 Rectangle( e1, e2 );
454 // caller expects cordinates relative to top-level win
455 return pW->OutputToScreenPixel( aPos );
458 // -----------------------------------------------------------------------
460 FloatingWindow* FloatingWindow::ImplFloatHitTest( Window* pReference, const Point& rPos, sal_uInt16& rHitTest )
462 FloatingWindow* pWin = this;
464 Point aAbsolute( rPos );
466 // compare coordinates in absolute screen coordinates
467 if( pReference->ImplHasMirroredGraphics() )
469 if(!pReference->IsRTLEnabled() )
470 // --- RTL --- re-mirror back to get device coordiantes
471 pReference->ImplReMirror( aAbsolute );
473 Rectangle aRect( pReference->ScreenToOutputPixel(aAbsolute), Size(1,1) ) ;
474 aRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect );
475 aAbsolute = aRect.TopLeft();
477 else
478 aAbsolute = Point( pReference->OutputToAbsoluteScreenPixel(
479 pReference->ScreenToOutputPixel(rPos) ) );
483 // compute the floating window's size in absolute screen coordinates
485 // use the border window to have the exact position
486 Window *pBorderWin = pWin->GetWindow( WINDOW_BORDER );
488 Point aPt; // the top-left corner in output coordinates ie (0,0)
489 Rectangle devRect( pBorderWin->ImplOutputToUnmirroredAbsoluteScreenPixel( Rectangle( aPt, pBorderWin->GetSizePixel()) ) ) ;
490 if ( devRect.IsInside( aAbsolute ) )
492 rHitTest = IMPL_FLOATWIN_HITTEST_WINDOW;
493 return pWin;
496 // test, if mouse is in rectangle, (this is typically the rect of the active
497 // toolbox item or similar)
498 // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
499 // is already in absolute device coordinates
500 if ( pWin->maFloatRect.IsInside( aAbsolute ) )
502 rHitTest = IMPL_FLOATWIN_HITTEST_RECT;
503 return pWin;
506 pWin = pWin->mpNextFloat;
508 while ( pWin );
510 rHitTest = IMPL_FLOATWIN_HITTEST_OUTSIDE;
511 return NULL;
514 // -----------------------------------------------------------------------
516 FloatingWindow* FloatingWindow::ImplFindLastLevelFloat()
518 FloatingWindow* pWin = this;
519 FloatingWindow* pLastFoundWin = pWin;
523 if ( pWin->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NEWLEVEL )
524 pLastFoundWin = pWin;
526 pWin = pWin->mpNextFloat;
528 while ( pWin );
530 return pLastFoundWin;
533 // -----------------------------------------------------------------------
535 sal_Bool FloatingWindow::ImplIsFloatPopupModeWindow( const Window* pWindow )
537 FloatingWindow* pWin = this;
541 if ( pWin->mpFirstPopupModeWin == pWindow )
542 return sal_True;
544 pWin = pWin->mpNextFloat;
546 while ( pWin );
548 return sal_False;
551 // -----------------------------------------------------------------------
553 IMPL_LINK_NOARG(FloatingWindow, ImplEndPopupModeHdl)
555 mnPostId = 0;
556 mnPopupModeFlags = 0;
557 mbPopupMode = sal_False;
558 PopupModeEnd();
559 return 0;
562 // -----------------------------------------------------------------------
564 long FloatingWindow::Notify( NotifyEvent& rNEvt )
566 // Zuerst Basisklasse rufen wegen TabSteuerung
567 long nRet = SystemWindow::Notify( rNEvt );
568 if ( !nRet )
570 if ( rNEvt.GetType() == EVENT_KEYINPUT )
572 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
573 KeyCode aKeyCode = pKEvt->GetKeyCode();
574 sal_uInt16 nKeyCode = aKeyCode.GetCode();
576 if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
578 Close();
579 return sal_True;
584 return nRet;
587 // -----------------------------------------------------------------------
589 void FloatingWindow::StateChanged( StateChangedType nType )
591 SystemWindow::StateChanged( nType );
593 if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
595 ImplInitSettings();
596 Invalidate();
600 // -----------------------------------------------------------------------
602 void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
604 SystemWindow::DataChanged( rDCEvt );
606 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
607 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
609 ImplInitSettings();
610 Invalidate();
614 // -----------------------------------------------------------------------
616 void FloatingWindow::ImplCallPopupModeEnd()
618 // PopupMode wurde beendet
619 mbInPopupMode = sal_False;
621 // Handler asyncron rufen
622 if ( !mnPostId )
623 Application::PostUserEvent( mnPostId, LINK( this, FloatingWindow, ImplEndPopupModeHdl ) );
626 // -----------------------------------------------------------------------
628 void FloatingWindow::PopupModeEnd()
630 maPopupModeEndHdl.Call( this );
633 // -----------------------------------------------------------------------
635 void FloatingWindow::SetTitleType( sal_uInt16 nTitle )
637 if ( (mnTitle != nTitle) && mpWindowImpl->mpBorderWindow )
639 mnTitle = nTitle;
640 Size aOutSize = GetOutputSizePixel();
641 sal_uInt16 nTitleStyle;
642 if ( nTitle == FLOATWIN_TITLE_NORMAL )
643 nTitleStyle = BORDERWINDOW_TITLE_SMALL;
644 else if ( nTitle == FLOATWIN_TITLE_TEAROFF )
645 nTitleStyle = BORDERWINDOW_TITLE_TEAROFF;
646 else if ( nTitle == FLOATWIN_TITLE_POPUP )
647 nTitleStyle = BORDERWINDOW_TITLE_POPUP;
648 else // nTitle == FLOATWIN_TITLE_NONE
649 nTitleStyle = BORDERWINDOW_TITLE_NONE;
650 ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetTitleType( nTitleStyle, aOutSize );
651 ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
655 // -----------------------------------------------------------------------
657 void FloatingWindow::StartPopupMode( const Rectangle& rRect, sal_uLong nFlags )
659 // avoid flickering
660 if ( IsVisible() )
661 Show( sal_False, SHOW_NOFOCUSCHANGE );
663 if ( IsRollUp() )
664 RollDown();
666 // remove title
667 mnOldTitle = mnTitle;
668 if ( ( mpWindowImpl->mnStyle & WB_POPUP ) && GetText().Len() )
669 SetTitleType( FLOATWIN_TITLE_POPUP );
670 else if ( nFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF )
671 SetTitleType( FLOATWIN_TITLE_TEAROFF );
672 else
673 SetTitleType( FLOATWIN_TITLE_NONE );
675 // avoid close on focus change for decorated floating windows only
676 if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
677 nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
679 // #102010# For debugging Accessibility
680 static const char* pEnv = getenv("SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
681 if( pEnv && *pEnv )
682 nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
684 // compute window position according to flags and arrangement
685 sal_uInt16 nArrangeIndex;
686 Point aPos = ImplCalcPos( this, rRect, nFlags, nArrangeIndex );
687 SetPosPixel( aPos );
689 // set data and display window
690 // convert maFloatRect to absolute device coordinates
691 // so they can be compared across different frames
692 // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
693 maFloatRect = rRect;
695 Window *pReference = GetParent();
697 // compare coordinates in absolute screen coordinates
698 // Keep in sync with FloatingWindow::ImplFloatHitTest, e.g. fdo#33509
699 if( pReference->ImplHasMirroredGraphics() )
701 if(!pReference->IsRTLEnabled() )
702 // --- RTL --- re-mirror back to get device coordiantes
703 pReference->ImplReMirror(maFloatRect);
705 maFloatRect.SetPos(pReference->ScreenToOutputPixel(maFloatRect.TopLeft()));
706 maFloatRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel(maFloatRect);
708 else
709 maFloatRect.SetPos(pReference->OutputToAbsoluteScreenPixel(pReference->ScreenToOutputPixel(rRect.TopLeft())));
711 maFloatRect.Left() -= 2;
712 maFloatRect.Top() -= 2;
713 maFloatRect.Right() += 2;
714 maFloatRect.Bottom() += 2;
715 mnPopupModeFlags = nFlags;
716 mbInPopupMode = sal_True;
717 mbPopupMode = sal_True;
718 mbPopupModeCanceled = sal_False;
719 mbPopupModeTearOff = sal_False;
720 mbMouseDown = sal_False;
722 mbOldSaveBackMode = IsSaveBackgroundEnabled();
723 EnableSaveBackground();
725 // add FloatingWindow to list of windows that are in popup mode
726 ImplSVData* pSVData = ImplGetSVData();
727 mpNextFloat = pSVData->maWinData.mpFirstFloat;
728 pSVData->maWinData.mpFirstFloat = this;
729 if( nFlags & FLOATWIN_POPUPMODE_GRABFOCUS )
731 // force key input even without focus (useful for menus)
732 mbGrabFocus = sal_True;
734 Show( sal_True, SHOW_NOACTIVATE );
737 // -----------------------------------------------------------------------
739 void FloatingWindow::StartPopupMode( ToolBox* pBox, sal_uLong nFlags )
741 // get selected button
742 sal_uInt16 nItemId = pBox->GetDownItemId();
743 if ( !nItemId )
744 return;
746 mpImplData->mpBox = pBox;
747 pBox->ImplFloatControl( sal_True, this );
749 // retrieve some data from the ToolBox
750 Rectangle aRect = pBox->GetItemRect( nItemId );
751 Point aPos;
752 // convert to parent's screen coordinates
753 aPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
754 aRect.SetPos( aPos );
756 nFlags |=
757 FLOATWIN_POPUPMODE_NOFOCUSCLOSE |
758 // FLOATWIN_POPUPMODE_NOMOUSECLOSE |
759 FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |
760 // FLOATWIN_POPUPMODE_NOMOUSERECTCLOSE | // #105968# floating toolboxes should close when clicked in (parent's) float rect
761 FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE;
762 // | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
765 * FLOATWIN_POPUPMODE_NOKEYCLOSE |
766 * don't set since it disables closing floaters with escape
769 // Flags fuer Positionierung bestimmen
770 if ( !(nFlags & (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_UP |
771 FLOATWIN_POPUPMODE_LEFT | FLOATWIN_POPUPMODE_RIGHT |
772 FLOATWIN_POPUPMODE_NOAUTOARRANGE)) )
774 if ( pBox->IsHorizontal() )
775 nFlags |= FLOATWIN_POPUPMODE_DOWN;
776 else
777 nFlags |= FLOATWIN_POPUPMODE_RIGHT;
780 // FloatingModus starten
781 StartPopupMode( aRect, nFlags );
784 // -----------------------------------------------------------------------
786 void FloatingWindow::ImplEndPopupMode( sal_uInt16 nFlags, sal_uLong nFocusId )
788 if ( !mbInPopupMode )
789 return;
791 ImplSVData* pSVData = ImplGetSVData();
793 mbInCleanUp = sal_True; // prevent killing this window due to focus change while working with it
795 // Bei allen nachfolgenden PopupMode-Fenster den Modus auch beenden
796 while ( pSVData->maWinData.mpFirstFloat && pSVData->maWinData.mpFirstFloat != this )
797 pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
800 // Fenster aus der Liste austragen
801 pSVData->maWinData.mpFirstFloat = mpNextFloat;
802 mpNextFloat = NULL;
804 sal_uLong nPopupModeFlags = mnPopupModeFlags;
806 // Wenn nicht abgerissen wurde, dann Fenster wieder Hiden
807 if ( !(nFlags & FLOATWIN_POPUPMODEEND_TEAROFF) ||
808 !(nPopupModeFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF) )
810 Show( sal_False, SHOW_NOFOCUSCHANGE );
812 // Focus evt. auf ein entsprechendes FloatingWindow weiterschalten
813 if ( nFocusId )
814 Window::EndSaveFocus( nFocusId );
815 else if ( pSVData->maWinData.mpFocusWin && pSVData->maWinData.mpFirstFloat &&
816 ImplIsWindowOrChild( pSVData->maWinData.mpFocusWin ) )
817 pSVData->maWinData.mpFirstFloat->GrabFocus();
818 mbPopupModeTearOff = sal_False;
820 else
822 mbPopupModeTearOff = sal_True;
823 if ( nFocusId )
824 Window::EndSaveFocus( nFocusId, sal_False );
826 EnableSaveBackground( mbOldSaveBackMode );
828 mbPopupModeCanceled = (nFlags & FLOATWIN_POPUPMODEEND_CANCEL) != 0;
830 // Gegebenenfalls den Title wieder herstellen
831 SetTitleType( mnOldTitle );
833 // ToolBox wieder auf normal schalten
834 if ( mpImplData->mpBox )
836 mpImplData->mpBox->ImplFloatControl( sal_False, this );
837 mpImplData->mpBox = NULL;
840 // Je nach Parameter den PopupModeEnd-Handler rufen
841 if ( !(nFlags & FLOATWIN_POPUPMODEEND_DONTCALLHDL) )
842 ImplCallPopupModeEnd();
844 // Je nach Parameter die restlichen Fenster auch noch schliessen
845 if ( nFlags & FLOATWIN_POPUPMODEEND_CLOSEALL )
847 if ( !(nPopupModeFlags & FLOATWIN_POPUPMODE_NEWLEVEL) )
849 if ( pSVData->maWinData.mpFirstFloat )
851 FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
852 pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
857 mbInCleanUp = sal_False;
860 // -----------------------------------------------------------------------
862 void FloatingWindow::EndPopupMode( sal_uInt16 nFlags )
864 ImplEndPopupMode( nFlags );
867 // -----------------------------------------------------------------------
869 void FloatingWindow::AddPopupModeWindow( Window* pWindow )
871 // !!! bisher erst 1 Fenster und noch keine Liste
872 mpFirstPopupModeWin = pWindow;
875 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */