merge the formfield patch from ooo-build
[ooovba.git] / vcl / source / window / floatwin.cxx
blobc47d5f296e2f7a09f255a92a63da33d61deb9269
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: floatwin.cxx,v $
10 * $Revision: 1.40 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #ifndef _SV_SVSYS_HXX
35 #include <svsys.h>
36 #endif
37 #include <vcl/svdata.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <vcl/brdwin.hxx>
41 #include <vcl/event.hxx>
42 #include <vcl/toolbox.hxx>
43 #include <vcl/floatwin.hxx>
44 #include <vcl/window.h>
45 #ifndef _SV_RC_H
46 #include <tools/rc.h>
47 #endif
48 #include <vcl/salframe.hxx>
49 #include <tools/debug.hxx>
52 // =======================================================================
54 class FloatingWindow::ImplData
56 public:
57 ImplData();
58 ~ImplData();
60 ToolBox* mpBox;
61 Rectangle maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
64 FloatingWindow::ImplData::ImplData()
66 mpBox = NULL;
69 FloatingWindow::ImplData::~ImplData()
73 Rectangle& FloatingWindow::ImplGetItemEdgeClipRect()
75 return mpImplData->maItemEdgeClipRect;
78 // =======================================================================
80 void FloatingWindow::ImplInit( Window* pParent, WinBits nStyle )
82 mpImplData = new ImplData;
84 mpWindowImpl->mbFloatWin = TRUE;
85 mbInCleanUp = FALSE;
86 mbGrabFocus = FALSE;
88 DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL!" );
90 if ( !pParent )
91 pParent = ImplGetSVData()->maWinData.mpAppWin;
93 DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists" );
95 // no Border, then we dont need a border window
96 if ( !nStyle )
98 mpWindowImpl->mbOverlapWin = TRUE;
99 nStyle |= WB_DIALOGCONTROL;
100 SystemWindow::ImplInit( pParent, nStyle, NULL );
102 else
104 if ( !(nStyle & WB_NODIALOGCONTROL) )
105 nStyle |= WB_DIALOGCONTROL;
107 if( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)
108 && !(nStyle & WB_OWNERDRAWDECORATION) )
110 WinBits nFloatWinStyle = nStyle;
111 // #99154# floaters are not closeable by default anymore, eg fullscreen floater
112 // nFloatWinStyle |= WB_CLOSEABLE;
113 mpWindowImpl->mbFrame = TRUE;
114 mpWindowImpl->mbOverlapWin = TRUE;
115 SystemWindow::ImplInit( pParent, nFloatWinStyle & ~WB_BORDER, NULL );
117 else
119 ImplBorderWindow* pBorderWin;
120 USHORT nBorderStyle = BORDERWINDOW_STYLE_BORDER | BORDERWINDOW_STYLE_FLOAT;
122 if( nStyle & WB_OWNERDRAWDECORATION ) nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
123 else nBorderStyle |= BORDERWINDOW_STYLE_OVERLAP;
125 if ( (nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE)) )
127 nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
128 nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable
130 pBorderWin = new ImplBorderWindow( pParent, nStyle, nBorderStyle );
131 SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
132 pBorderWin->mpWindowImpl->mpClientWindow = this;
133 pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
134 pBorderWin->SetDisplayActive( TRUE );
135 mpWindowImpl->mpBorderWindow = pBorderWin;
136 mpWindowImpl->mpRealParent = pParent;
139 SetActivateMode( 0 );
141 mpNextFloat = NULL;
142 mpFirstPopupModeWin = NULL;
143 mnPostId = 0;
144 mnTitle = (nStyle & WB_MOVEABLE) ? FLOATWIN_TITLE_NORMAL : FLOATWIN_TITLE_NONE;
145 mnOldTitle = mnTitle;
146 mnPopupModeFlags = 0;
147 mbInPopupMode = FALSE;
148 mbPopupMode = FALSE;
149 mbPopupModeCanceled = FALSE;
150 mbPopupModeTearOff = FALSE;
151 mbMouseDown = FALSE;
153 ImplInitSettings();
156 // -----------------------------------------------------------------------
158 void FloatingWindow::ImplInitSettings()
160 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
162 Color aColor;
163 if ( IsControlBackground() )
164 aColor = GetControlBackground();
165 else if ( Window::GetStyle() & WB_3DLOOK )
166 aColor = rStyleSettings.GetFaceColor();
167 else
168 aColor = rStyleSettings.GetWindowColor();
169 SetBackground( aColor );
172 // =======================================================================
174 FloatingWindow::FloatingWindow( Window* pParent, WinBits nStyle ) :
175 SystemWindow( WINDOW_FLOATINGWINDOW )
177 ImplInit( pParent, nStyle );
180 // -----------------------------------------------------------------------
182 FloatingWindow::FloatingWindow( Window* pParent, const ResId& rResId ) :
183 SystemWindow( WINDOW_FLOATINGWINDOW )
185 rResId.SetRT( RSC_FLOATINGWINDOW );
186 WinBits nStyle = ImplInitRes( rResId );
187 ImplInit( pParent, nStyle );
188 ImplLoadRes( rResId );
190 if ( !(nStyle & WB_HIDE) )
191 Show();
194 // -----------------------------------------------------------------------
196 void FloatingWindow::ImplLoadRes( const ResId& rResId )
198 SystemWindow::ImplLoadRes( rResId );
200 ULONG nObjMask = ReadLongRes();
202 if ( (RSC_FLOATINGWINDOW_WHMAPMODE | RSC_FLOATINGWINDOW_WIDTH |
203 RSC_FLOATINGWINDOW_HEIGHT) & nObjMask )
205 // Groessenangabe aus der Resource verwenden
206 Size aSize;
207 MapUnit eSizeMap = MAP_PIXEL;
209 if ( RSC_FLOATINGWINDOW_WHMAPMODE & nObjMask )
210 eSizeMap = (MapUnit) ReadShortRes();
211 if ( RSC_FLOATINGWINDOW_WIDTH & nObjMask )
212 aSize.Width() = ReadShortRes();
213 if ( RSC_FLOATINGWINDOW_HEIGHT & nObjMask )
214 aSize.Height() = ReadShortRes();
216 SetRollUpOutputSizePixel( LogicToPixel( aSize, eSizeMap ) );
219 if (nObjMask & RSC_FLOATINGWINDOW_ZOOMIN )
221 if ( ReadShortRes() )
222 RollUp();
226 // -----------------------------------------------------------------------
228 FloatingWindow::~FloatingWindow()
230 if( mbPopupModeCanceled )
231 // indicates that ESC key was pressed
232 // will be handled in Window::ImplGrabFocus()
233 SetDialogControlFlags( GetDialogControlFlags() | WINDOW_DLGCTRL_FLOATWIN_POPUPMODEEND_CANCEL );
235 if ( IsInPopupMode() )
236 EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL | FLOATWIN_POPUPMODEEND_DONTCALLHDL );
238 if ( mnPostId )
239 Application::RemoveUserEvent( mnPostId );
241 delete mpImplData;
244 // -----------------------------------------------------------------------
246 Point FloatingWindow::CalcFloatingPosition( Window* pWindow, const Rectangle& rRect, ULONG nFlags, USHORT& rArrangeIndex )
248 return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
251 // -----------------------------------------------------------------------
253 Point FloatingWindow::ImplCalcPos( Window* pWindow,
254 const Rectangle& rRect, ULONG nFlags,
255 USHORT& rArrangeIndex )
257 // Fenster-Position ermitteln
258 Point aPos;
259 Size aSize = pWindow->GetSizePixel();
260 Rectangle aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
261 FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow );
263 // convert....
264 Window* pW = pWindow;
265 if ( pW->mpWindowImpl->mpRealParent )
266 pW = pW->mpWindowImpl->mpRealParent;
268 Rectangle normRect( rRect ); // rRect is already relative to top-level window
269 normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) );
271 BOOL bRTL = Application::GetSettings().GetLayoutRTL();
273 Rectangle devRect( pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ),
274 pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) );
276 Rectangle devRectRTL( devRect );
277 if( bRTL )
278 // create a rect that can be compared to desktop coordinates
279 devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect );
280 if( Application::GetScreenCount() > 1 && ! Application::IsMultiDisplay() )
281 aScreenRect = Application::GetScreenPosSizePixel(
282 Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );
285 USHORT nArrangeAry[5];
286 USHORT nArrangeIndex;
287 BOOL bBreak;
288 Point e1,e2; // the common edge between the item rect and the floating window
290 if ( nFlags & FLOATWIN_POPUPMODE_LEFT )
292 nArrangeAry[0] = FLOATWIN_POPUPMODE_LEFT;
293 nArrangeAry[1] = FLOATWIN_POPUPMODE_RIGHT;
294 nArrangeAry[2] = FLOATWIN_POPUPMODE_UP;
295 nArrangeAry[3] = FLOATWIN_POPUPMODE_DOWN;
296 nArrangeAry[4] = FLOATWIN_POPUPMODE_LEFT;
298 else if ( nFlags & FLOATWIN_POPUPMODE_RIGHT )
300 nArrangeAry[0] = FLOATWIN_POPUPMODE_RIGHT;
301 nArrangeAry[1] = FLOATWIN_POPUPMODE_LEFT;
302 nArrangeAry[2] = FLOATWIN_POPUPMODE_UP;
303 nArrangeAry[3] = FLOATWIN_POPUPMODE_DOWN;
304 nArrangeAry[4] = FLOATWIN_POPUPMODE_RIGHT;
306 else if ( nFlags & FLOATWIN_POPUPMODE_UP )
308 nArrangeAry[0] = FLOATWIN_POPUPMODE_UP;
309 nArrangeAry[1] = FLOATWIN_POPUPMODE_DOWN;
310 nArrangeAry[2] = FLOATWIN_POPUPMODE_RIGHT;
311 nArrangeAry[3] = FLOATWIN_POPUPMODE_LEFT;
312 nArrangeAry[4] = FLOATWIN_POPUPMODE_UP;
314 else
316 nArrangeAry[0] = FLOATWIN_POPUPMODE_DOWN;
317 nArrangeAry[1] = FLOATWIN_POPUPMODE_UP;
318 nArrangeAry[2] = FLOATWIN_POPUPMODE_RIGHT;
319 nArrangeAry[3] = FLOATWIN_POPUPMODE_LEFT;
320 nArrangeAry[4] = FLOATWIN_POPUPMODE_DOWN;
322 if ( nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE )
323 nArrangeIndex = 4;
324 else
325 nArrangeIndex = 0;
327 for ( ; nArrangeIndex < 5; nArrangeIndex++ )
329 bBreak = TRUE;
330 switch ( nArrangeAry[nArrangeIndex] )
333 case FLOATWIN_POPUPMODE_LEFT:
334 aPos.X() = devRect.Left()-aSize.Width()+1;
335 aPos.Y() = devRect.Top();
336 aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
337 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
339 if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() )
340 bBreak = FALSE;
342 else
344 if ( aPos.X() < aScreenRect.Left() )
345 bBreak = FALSE;
347 if( bBreak )
349 e1 = devRect.TopLeft();
350 e2 = devRect.BottomLeft();
351 // set non-zero width
352 e2.X()++;
353 // don't clip corners
354 e1.Y()++;
355 e2.Y()--;
357 break;
358 case FLOATWIN_POPUPMODE_RIGHT:
359 aPos = devRect.TopRight();
360 aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
361 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
363 if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() )
364 bBreak = FALSE;
366 else
368 if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
369 bBreak = FALSE;
371 if( bBreak )
373 e1 = devRect.TopRight();
374 e2 = devRect.BottomRight();
375 // set non-zero width
376 e2.X()++;
377 // don't clip corners
378 e1.Y()++;
379 e2.Y()--;
381 break;
382 case FLOATWIN_POPUPMODE_UP:
383 aPos.X() = devRect.Left();
384 aPos.Y() = devRect.Top()-aSize.Height()+1;
385 if ( aPos.Y() < aScreenRect.Top() )
386 bBreak = FALSE;
387 if( bBreak )
389 e1 = devRect.TopLeft();
390 e2 = devRect.TopRight();
391 // set non-zero height
392 e2.Y()++;
393 // don't clip corners
394 e1.X()++;
395 e2.X()--;
397 break;
398 case FLOATWIN_POPUPMODE_DOWN:
399 aPos = devRect.BottomLeft();
400 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
401 bBreak = FALSE;
402 if( bBreak )
404 e1 = devRect.BottomLeft();
405 e2 = devRect.BottomRight();
406 // set non-zero height
407 e2.Y()++;
408 // don't clip corners
409 e1.X()++;
410 e2.X()--;
412 break;
415 // Evt. noch anpassen
416 if ( bBreak && !(nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE) )
418 if ( (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_LEFT) ||
419 (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_RIGHT) )
421 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
423 aPos.Y() = devRect.Bottom()-aSize.Height()+1;
424 if ( aPos.Y() < aScreenRect.Top() )
425 aPos.Y() = aScreenRect.Top();
428 else
430 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
432 if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
433 aPos.X() -= aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1;
434 else if( aPos.X() + aSize.Width() > aScreenRect.Right() )
436 aPos.X() -= aSize.Width()-2; // popup to left instead
437 aPos.Y() -= 2;
440 else if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
442 aPos.X() = devRect.Right()-aSize.Width()+1;
443 if ( aPos.X() < aScreenRect.Left() )
444 aPos.X() = aScreenRect.Left();
449 if ( bBreak )
450 break;
452 if ( nArrangeIndex > 4 )
453 nArrangeIndex = 4;
455 rArrangeIndex = nArrangeIndex;
457 aPos = pW->AbsoluteScreenToOutputPixel( aPos );
459 // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
460 if( pFloatingWindow )
462 pFloatingWindow->mpImplData->maItemEdgeClipRect =
463 Rectangle( e1, e2 );
466 // caller expects cordinates relative to top-level win
467 return pW->OutputToScreenPixel( aPos );
470 // -----------------------------------------------------------------------
472 FloatingWindow* FloatingWindow::ImplFloatHitTest( Window* pReference, const Point& rPos, USHORT& rHitTest )
474 FloatingWindow* pWin = this;
476 Point aAbsolute( rPos );
478 // compare coordinates in absolute screen coordinates
479 if( pReference->ImplHasMirroredGraphics() )
481 if(!pReference->IsRTLEnabled() )
482 // --- RTL --- re-mirror back to get device coordiantes
483 pReference->ImplReMirror( aAbsolute );
485 Rectangle aRect( pReference->ScreenToOutputPixel(aAbsolute), Size(1,1) ) ;
486 aRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect );
487 aAbsolute = aRect.TopLeft();
489 else
490 aAbsolute = Point( pReference->OutputToAbsoluteScreenPixel(
491 pReference->ScreenToOutputPixel(rPos) ) );
495 // compute the floating window's size in absolute screen coordinates
497 // use the border window to have the exact position
498 Window *pBorderWin = pWin->GetWindow( WINDOW_BORDER );
500 Point aPt; // the top-left corner in output coordinates ie (0,0)
501 Rectangle devRect( pBorderWin->ImplOutputToUnmirroredAbsoluteScreenPixel( Rectangle( aPt, pBorderWin->GetSizePixel()) ) ) ;
502 if ( devRect.IsInside( aAbsolute ) )
504 rHitTest = IMPL_FLOATWIN_HITTEST_WINDOW;
505 return pWin;
508 // test, if mouse is in rectangle, (this is typically the rect of the active
509 // toolbox item or similar)
510 // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
511 // is already in absolute device coordinates
512 if ( pWin->maFloatRect.IsInside( aAbsolute ) )
514 rHitTest = IMPL_FLOATWIN_HITTEST_RECT;
515 return pWin;
518 pWin = pWin->mpNextFloat;
520 while ( pWin );
522 rHitTest = IMPL_FLOATWIN_HITTEST_OUTSIDE;
523 return NULL;
526 // -----------------------------------------------------------------------
528 FloatingWindow* FloatingWindow::ImplFindLastLevelFloat()
530 FloatingWindow* pWin = this;
531 FloatingWindow* pLastFoundWin = pWin;
535 if ( pWin->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NEWLEVEL )
536 pLastFoundWin = pWin;
538 pWin = pWin->mpNextFloat;
540 while ( pWin );
542 return pLastFoundWin;
545 // -----------------------------------------------------------------------
547 BOOL FloatingWindow::ImplIsFloatPopupModeWindow( const Window* pWindow )
549 FloatingWindow* pWin = this;
553 if ( pWin->mpFirstPopupModeWin == pWindow )
554 return TRUE;
556 pWin = pWin->mpNextFloat;
558 while ( pWin );
560 return FALSE;
563 // -----------------------------------------------------------------------
565 IMPL_LINK( FloatingWindow, ImplEndPopupModeHdl, void*, EMPTYARG )
567 mnPostId = 0;
568 mnPopupModeFlags = 0;
569 mbPopupMode = FALSE;
570 PopupModeEnd();
571 return 0;
574 // -----------------------------------------------------------------------
576 long FloatingWindow::Notify( NotifyEvent& rNEvt )
578 // Zuerst Basisklasse rufen wegen TabSteuerung
579 long nRet = SystemWindow::Notify( rNEvt );
580 if ( !nRet )
582 if ( rNEvt.GetType() == EVENT_KEYINPUT )
584 const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
585 KeyCode aKeyCode = pKEvt->GetKeyCode();
586 USHORT nKeyCode = aKeyCode.GetCode();
588 if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
590 Close();
591 return TRUE;
596 return nRet;
599 // -----------------------------------------------------------------------
601 void FloatingWindow::StateChanged( StateChangedType nType )
603 SystemWindow::StateChanged( nType );
605 if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
607 ImplInitSettings();
608 Invalidate();
612 // -----------------------------------------------------------------------
614 void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
616 SystemWindow::DataChanged( rDCEvt );
618 if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
619 (rDCEvt.GetFlags() & SETTINGS_STYLE) )
621 ImplInitSettings();
622 Invalidate();
626 // -----------------------------------------------------------------------
628 void FloatingWindow::ImplCallPopupModeEnd()
630 // PopupMode wurde beendet
631 mbInPopupMode = FALSE;
633 // Handler asyncron rufen
634 if ( !mnPostId )
635 Application::PostUserEvent( mnPostId, LINK( this, FloatingWindow, ImplEndPopupModeHdl ) );
638 // -----------------------------------------------------------------------
640 void FloatingWindow::PopupModeEnd()
642 maPopupModeEndHdl.Call( this );
645 // -----------------------------------------------------------------------
647 void FloatingWindow::SetTitleType( USHORT nTitle )
649 if ( (mnTitle != nTitle) && mpWindowImpl->mpBorderWindow )
651 mnTitle = nTitle;
652 Size aOutSize = GetOutputSizePixel();
653 USHORT nTitleStyle;
654 if ( nTitle == FLOATWIN_TITLE_NORMAL )
655 nTitleStyle = BORDERWINDOW_TITLE_SMALL;
656 else if ( nTitle == FLOATWIN_TITLE_TEAROFF )
657 nTitleStyle = BORDERWINDOW_TITLE_TEAROFF;
658 else // nTitle == FLOATWIN_TITLE_NONE
659 nTitleStyle = BORDERWINDOW_TITLE_NONE;
660 ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetTitleType( nTitleStyle, aOutSize );
661 ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
665 // -----------------------------------------------------------------------
667 void FloatingWindow::StartPopupMode( const Rectangle& rRect, ULONG nFlags )
669 // avoid flickering
670 if ( IsVisible() )
671 Show( FALSE, SHOW_NOFOCUSCHANGE );
673 if ( IsRollUp() )
674 RollDown();
676 // remove title
677 mnOldTitle = mnTitle;
678 if ( nFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF )
679 SetTitleType( FLOATWIN_TITLE_TEAROFF );
680 else
681 SetTitleType( FLOATWIN_TITLE_NONE );
683 // avoid close on focus change for decorated floating windows only
684 if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
685 nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
687 // #102010# For debugging Accessibility
688 static const char* pEnv = getenv("SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
689 if( pEnv && *pEnv )
690 nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
692 // compute window position according to flags and arrangement
693 USHORT nArrangeIndex;
694 SetPosPixel( ImplCalcPos( this, rRect, nFlags, nArrangeIndex ) );
696 // set data and display window
697 // convert maFloatRect to absolute device coordinates
698 // so they can be compared across different frames
699 // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
700 maFloatRect = rRect;
701 if( GetParent()->ImplHasMirroredGraphics() )
703 maFloatRect.SetPos( GetParent()->ScreenToOutputPixel( rRect.TopLeft() ) );
704 maFloatRect = GetParent()->ImplOutputToUnmirroredAbsoluteScreenPixel( maFloatRect );
706 else
707 maFloatRect.SetPos( GetParent()->OutputToAbsoluteScreenPixel( GetParent()->ScreenToOutputPixel( rRect.TopLeft() ) ) );
709 maFloatRect.Left() -= 2;
710 maFloatRect.Top() -= 2;
711 maFloatRect.Right() += 2;
712 maFloatRect.Bottom() += 2;
713 mnPopupModeFlags = nFlags;
714 mbInPopupMode = TRUE;
715 mbPopupMode = TRUE;
716 mbPopupModeCanceled = FALSE;
717 mbPopupModeTearOff = FALSE;
718 mbMouseDown = FALSE;
720 mbOldSaveBackMode = IsSaveBackgroundEnabled();
721 EnableSaveBackground();
723 // add FloatingWindow to list of windows that are in popup mode
724 ImplSVData* pSVData = ImplGetSVData();
725 mpNextFloat = pSVData->maWinData.mpFirstFloat;
726 pSVData->maWinData.mpFirstFloat = this;
727 if( nFlags & FLOATWIN_POPUPMODE_GRABFOCUS )
729 // force key input even without focus (useful for menues)
730 mbGrabFocus = TRUE;
732 Show( TRUE, SHOW_NOACTIVATE );
735 // -----------------------------------------------------------------------
737 void FloatingWindow::StartPopupMode( ToolBox* pBox, ULONG nFlags )
739 // get selected button
740 USHORT nItemId = pBox->GetDownItemId();
741 if ( !nItemId )
742 return;
744 mpImplData->mpBox = pBox;
745 pBox->ImplFloatControl( TRUE, this );
747 // retrieve some data from the ToolBox
748 Rectangle aRect = pBox->GetItemRect( nItemId );
749 Point aPos;
750 // convert to parent's screen coordinates
751 aPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
752 aRect.SetPos( aPos );
754 nFlags |=
755 FLOATWIN_POPUPMODE_NOFOCUSCLOSE |
756 // FLOATWIN_POPUPMODE_NOMOUSECLOSE |
757 FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |
758 // FLOATWIN_POPUPMODE_NOMOUSERECTCLOSE | // #105968# floating toolboxes should close when clicked in (parent's) float rect
759 FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE;
760 // | FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
763 * FLOATWIN_POPUPMODE_NOKEYCLOSE |
764 * don't set since it disables closing floaters with escape
767 // Flags fuer Positionierung bestimmen
768 if ( !(nFlags & (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_UP |
769 FLOATWIN_POPUPMODE_LEFT | FLOATWIN_POPUPMODE_RIGHT |
770 FLOATWIN_POPUPMODE_NOAUTOARRANGE)) )
772 if ( pBox->IsHorizontal() )
773 nFlags |= FLOATWIN_POPUPMODE_DOWN;
774 else
775 nFlags |= FLOATWIN_POPUPMODE_RIGHT;
778 // FloatingModus starten
779 StartPopupMode( aRect, nFlags );
782 // -----------------------------------------------------------------------
784 void FloatingWindow::ImplEndPopupMode( USHORT nFlags, ULONG nFocusId )
786 if ( !mbInPopupMode )
787 return;
789 ImplSVData* pSVData = ImplGetSVData();
791 mbInCleanUp = TRUE; // prevent killing this window due to focus change while working with it
793 // Bei allen nachfolgenden PopupMode-Fenster den Modus auch beenden
794 while ( pSVData->maWinData.mpFirstFloat && pSVData->maWinData.mpFirstFloat != this )
795 pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
798 // Fenster aus der Liste austragen
799 pSVData->maWinData.mpFirstFloat = mpNextFloat;
800 mpNextFloat = NULL;
802 ULONG nPopupModeFlags = mnPopupModeFlags;
804 // Wenn nicht abgerissen wurde, dann Fenster wieder Hiden
805 if ( !(nFlags & FLOATWIN_POPUPMODEEND_TEAROFF) ||
806 !(nPopupModeFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF) )
808 Show( FALSE, SHOW_NOFOCUSCHANGE );
810 // Focus evt. auf ein entsprechendes FloatingWindow weiterschalten
811 if ( nFocusId )
812 Window::EndSaveFocus( nFocusId );
813 else if ( pSVData->maWinData.mpFocusWin && pSVData->maWinData.mpFirstFloat &&
814 ImplIsWindowOrChild( pSVData->maWinData.mpFocusWin ) )
815 pSVData->maWinData.mpFirstFloat->GrabFocus();
816 mbPopupModeTearOff = FALSE;
818 else
820 mbPopupModeTearOff = TRUE;
821 if ( nFocusId )
822 Window::EndSaveFocus( nFocusId, FALSE );
824 EnableSaveBackground( mbOldSaveBackMode );
826 mbPopupModeCanceled = (nFlags & FLOATWIN_POPUPMODEEND_CANCEL) != 0;
828 // Gegebenenfalls den Title wieder herstellen
829 SetTitleType( mnOldTitle );
831 // ToolBox wieder auf normal schalten
832 if ( mpImplData->mpBox )
834 mpImplData->mpBox->ImplFloatControl( FALSE, this );
835 mpImplData->mpBox = NULL;
838 // Je nach Parameter den PopupModeEnd-Handler rufen
839 if ( !(nFlags & FLOATWIN_POPUPMODEEND_DONTCALLHDL) )
840 ImplCallPopupModeEnd();
842 // Je nach Parameter die restlichen Fenster auch noch schliessen
843 if ( nFlags & FLOATWIN_POPUPMODEEND_CLOSEALL )
845 if ( !(nPopupModeFlags & FLOATWIN_POPUPMODE_NEWLEVEL) )
847 if ( pSVData->maWinData.mpFirstFloat )
849 FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
850 pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
855 mbInCleanUp = FALSE;
858 // -----------------------------------------------------------------------
860 void FloatingWindow::EndPopupMode( USHORT nFlags )
862 ImplEndPopupMode( nFlags );
865 // -----------------------------------------------------------------------
867 void FloatingWindow::AddPopupModeWindow( Window* pWindow )
869 // !!! bisher erst 1 Fenster und noch keine Liste
870 mpFirstPopupModeWin = pWindow;
873 // -----------------------------------------------------------------------
875 void FloatingWindow::RemovePopupModeWindow( Window* pWindow )
877 // !!! bisher erst 1 Fenster und noch keine Liste
878 if ( mpFirstPopupModeWin == pWindow )
879 mpFirstPopupModeWin = NULL;