xref: /AOO41X/main/vcl/source/window/floatwin.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
30 
31 #include <svdata.hxx>
32 #include <brdwin.hxx>
33 #include <window.h>
34 #include <salframe.hxx>
35 
36 #include <vcl/svapp.hxx>
37 #include <vcl/wrkwin.hxx>
38 #include <vcl/event.hxx>
39 #include <vcl/toolbox.hxx>
40 #include <vcl/floatwin.hxx>
41 
42 #include <tools/rc.h>
43 #include <tools/debug.hxx>
44 
45 
46 // =======================================================================
47 
48 class FloatingWindow::ImplData
49 {
50 public:
51     ImplData();
52     ~ImplData();
53 
54 	ToolBox* 		mpBox;
55 	Rectangle		maItemEdgeClipRect; // used to clip the common edge between a toolbar item and the border of this window
56 };
57 
58 FloatingWindow::ImplData::ImplData()
59 {
60     mpBox = NULL;
61 }
62 
63 FloatingWindow::ImplData::~ImplData()
64 {
65 }
66 
67 Rectangle& FloatingWindow::ImplGetItemEdgeClipRect()
68 {
69     return mpImplData->maItemEdgeClipRect;
70 }
71 
72 // =======================================================================
73 
74 void FloatingWindow::ImplInit( Window* pParent, WinBits nStyle )
75 {
76     mpImplData = new ImplData;
77 
78     mpWindowImpl->mbFloatWin = sal_True;
79     mbInCleanUp = sal_False;
80     mbGrabFocus = sal_False;
81 
82     DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL!" );
83 
84     if ( !pParent )
85         pParent = ImplGetSVData()->maWinData.mpAppWin;
86 
87     DBG_ASSERT( pParent, "FloatWindow::FloatingWindow(): - pParent == NULL and no AppWindow exists" );
88 
89     // no Border, then we dont need a border window
90     if ( !nStyle )
91     {
92         mpWindowImpl->mbOverlapWin = sal_True;
93         nStyle |= WB_DIALOGCONTROL;
94         SystemWindow::ImplInit( pParent, nStyle, NULL );
95     }
96     else
97     {
98         if ( !(nStyle & WB_NODIALOGCONTROL) )
99             nStyle |= WB_DIALOGCONTROL;
100 
101         if( nStyle & (WB_MOVEABLE | WB_SIZEABLE | WB_ROLLABLE | WB_CLOSEABLE | WB_STANDALONE)
102             && !(nStyle & WB_OWNERDRAWDECORATION) )
103         {
104             WinBits nFloatWinStyle = nStyle;
105             // #99154# floaters are not closeable by default anymore, eg fullscreen floater
106             // nFloatWinStyle |= WB_CLOSEABLE;
107             mpWindowImpl->mbFrame = sal_True;
108             mpWindowImpl->mbOverlapWin = sal_True;
109             SystemWindow::ImplInit( pParent, nFloatWinStyle & ~WB_BORDER, NULL );
110         }
111         else
112         {
113             ImplBorderWindow*   pBorderWin;
114             sal_uInt16              nBorderStyle = BORDERWINDOW_STYLE_BORDER | BORDERWINDOW_STYLE_FLOAT;
115 
116             if( nStyle & WB_OWNERDRAWDECORATION ) nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
117             else                                  nBorderStyle |= BORDERWINDOW_STYLE_OVERLAP;
118 
119             if ( (nStyle & WB_SYSTEMWINDOW) && !(nStyle & (WB_MOVEABLE | WB_SIZEABLE)) )
120             {
121                 nBorderStyle |= BORDERWINDOW_STYLE_FRAME;
122                 nStyle |= WB_CLOSEABLE; // make undecorated floaters closeable
123             }
124             pBorderWin  = new ImplBorderWindow( pParent, nStyle, nBorderStyle );
125             SystemWindow::ImplInit( pBorderWin, nStyle & ~WB_BORDER, NULL );
126             pBorderWin->mpWindowImpl->mpClientWindow = this;
127             pBorderWin->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
128             pBorderWin->SetDisplayActive( sal_True );
129             mpWindowImpl->mpBorderWindow  = pBorderWin;
130             mpWindowImpl->mpRealParent    = pParent;
131         }
132     }
133     SetActivateMode( 0 );
134 
135     mpNextFloat             = NULL;
136     mpFirstPopupModeWin     = NULL;
137     mnPostId                = 0;
138     mnTitle                 = (nStyle & WB_MOVEABLE) ? FLOATWIN_TITLE_NORMAL : FLOATWIN_TITLE_NONE;
139     mnOldTitle              = mnTitle;
140     mnPopupModeFlags        = 0;
141     mbInPopupMode           = sal_False;
142     mbPopupMode             = sal_False;
143     mbPopupModeCanceled     = sal_False;
144     mbPopupModeTearOff      = sal_False;
145     mbMouseDown             = sal_False;
146 
147     ImplInitSettings();
148 }
149 
150 // -----------------------------------------------------------------------
151 
152 void FloatingWindow::ImplInitSettings()
153 {
154     const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
155 
156     Color aColor;
157     if ( IsControlBackground() )
158         aColor = GetControlBackground();
159     else if ( Window::GetStyle() & WB_3DLOOK )
160         aColor = rStyleSettings.GetFaceColor();
161     else
162         aColor = rStyleSettings.GetWindowColor();
163     SetBackground( aColor );
164 }
165 
166 // =======================================================================
167 
168 FloatingWindow::FloatingWindow( Window* pParent, WinBits nStyle ) :
169     SystemWindow( WINDOW_FLOATINGWINDOW )
170 {
171     ImplInit( pParent, nStyle );
172 }
173 
174 // -----------------------------------------------------------------------
175 
176 FloatingWindow::FloatingWindow( Window* pParent, const ResId& rResId ) :
177     SystemWindow( WINDOW_FLOATINGWINDOW )
178 {
179     rResId.SetRT( RSC_FLOATINGWINDOW );
180     WinBits nStyle = ImplInitRes( rResId );
181     ImplInit( pParent, nStyle );
182     ImplLoadRes( rResId );
183 
184     if ( !(nStyle & WB_HIDE) )
185         Show();
186 }
187 
188 // -----------------------------------------------------------------------
189 
190 void FloatingWindow::ImplLoadRes( const ResId& rResId )
191 {
192     SystemWindow::ImplLoadRes( rResId );
193 
194     sal_uLong nObjMask = ReadLongRes();
195 
196     if ( (RSC_FLOATINGWINDOW_WHMAPMODE | RSC_FLOATINGWINDOW_WIDTH |
197           RSC_FLOATINGWINDOW_HEIGHT) & nObjMask )
198     {
199         // Groessenangabe aus der Resource verwenden
200         Size    aSize;
201         MapUnit eSizeMap = MAP_PIXEL;
202 
203         if ( RSC_FLOATINGWINDOW_WHMAPMODE & nObjMask )
204             eSizeMap = (MapUnit) ReadShortRes();
205         if ( RSC_FLOATINGWINDOW_WIDTH & nObjMask )
206             aSize.Width() = ReadShortRes();
207         if ( RSC_FLOATINGWINDOW_HEIGHT & nObjMask )
208             aSize.Height() = ReadShortRes();
209 
210         SetRollUpOutputSizePixel( LogicToPixel( aSize, eSizeMap ) );
211     }
212 
213     if (nObjMask & RSC_FLOATINGWINDOW_ZOOMIN )
214     {
215         if ( ReadShortRes() )
216             RollUp();
217     }
218 }
219 
220 // -----------------------------------------------------------------------
221 
222 FloatingWindow::~FloatingWindow()
223 {
224     if( mbPopupModeCanceled )
225         // indicates that ESC key was pressed
226         // will be handled in Window::ImplGrabFocus()
227         SetDialogControlFlags( GetDialogControlFlags() | WINDOW_DLGCTRL_FLOATWIN_POPUPMODEEND_CANCEL );
228 
229     if ( IsInPopupMode() )
230         EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL | FLOATWIN_POPUPMODEEND_DONTCALLHDL );
231 
232     if ( mnPostId )
233         Application::RemoveUserEvent( mnPostId );
234 
235     delete mpImplData;
236 }
237 
238 // -----------------------------------------------------------------------
239 
240 Point FloatingWindow::CalcFloatingPosition( Window* pWindow, const Rectangle& rRect, sal_uLong nFlags, sal_uInt16& rArrangeIndex )
241 {
242     return ImplCalcPos( pWindow, rRect, nFlags, rArrangeIndex );
243 }
244 
245 // -----------------------------------------------------------------------
246 
247 Point FloatingWindow::ImplCalcPos( Window* pWindow,
248                                    const Rectangle& rRect, sal_uLong nFlags,
249                                    sal_uInt16& rArrangeIndex )
250 {
251     // Fenster-Position ermitteln
252     Point       aPos;
253     Size        aSize = pWindow->GetSizePixel();
254     Rectangle   aScreenRect = pWindow->ImplGetFrameWindow()->GetDesktopRectPixel();
255     FloatingWindow *pFloatingWindow = dynamic_cast<FloatingWindow*>( pWindow );
256 
257     // convert....
258     Window* pW = pWindow;
259     if ( pW->mpWindowImpl->mpRealParent )
260         pW = pW->mpWindowImpl->mpRealParent;
261 
262     Rectangle normRect( rRect );  // rRect is already relative to top-level window
263     normRect.SetPos( pW->ScreenToOutputPixel( normRect.TopLeft() ) );
264 
265     sal_Bool bRTL = Application::GetSettings().GetLayoutRTL();
266 
267     Rectangle devRect(  pW->OutputToAbsoluteScreenPixel( normRect.TopLeft() ),
268                         pW->OutputToAbsoluteScreenPixel( normRect.BottomRight() ) );
269 
270     Rectangle devRectRTL( devRect );
271     if( bRTL )
272         // create a rect that can be compared to desktop coordinates
273         devRectRTL = pW->ImplOutputToUnmirroredAbsoluteScreenPixel( normRect );
274     if( Application::GetScreenCount() > 1 && ! Application::IsMultiDisplay() )
275         aScreenRect = Application::GetScreenPosSizePixel(
276             Application::GetBestScreen( bRTL ? devRectRTL : devRect ) );
277 
278 
279     sal_uInt16      nArrangeAry[5];
280     sal_uInt16      nArrangeIndex;
281     sal_Bool        bBreak;
282     Point       e1,e2;  // the common edge between the item rect and the floating window
283 
284     if ( nFlags & FLOATWIN_POPUPMODE_LEFT )
285     {
286         nArrangeAry[0]  = FLOATWIN_POPUPMODE_LEFT;
287         nArrangeAry[1]  = FLOATWIN_POPUPMODE_RIGHT;
288         nArrangeAry[2]  = FLOATWIN_POPUPMODE_UP;
289         nArrangeAry[3]  = FLOATWIN_POPUPMODE_DOWN;
290         nArrangeAry[4]  = FLOATWIN_POPUPMODE_LEFT;
291     }
292     else if ( nFlags & FLOATWIN_POPUPMODE_RIGHT )
293     {
294         nArrangeAry[0]  = FLOATWIN_POPUPMODE_RIGHT;
295         nArrangeAry[1]  = FLOATWIN_POPUPMODE_LEFT;
296         nArrangeAry[2]  = FLOATWIN_POPUPMODE_UP;
297         nArrangeAry[3]  = FLOATWIN_POPUPMODE_DOWN;
298         nArrangeAry[4]  = FLOATWIN_POPUPMODE_RIGHT;
299     }
300     else if ( nFlags & FLOATWIN_POPUPMODE_UP )
301     {
302         nArrangeAry[0]  = FLOATWIN_POPUPMODE_UP;
303         nArrangeAry[1]  = FLOATWIN_POPUPMODE_DOWN;
304         nArrangeAry[2]  = FLOATWIN_POPUPMODE_RIGHT;
305         nArrangeAry[3]  = FLOATWIN_POPUPMODE_LEFT;
306         nArrangeAry[4]  = FLOATWIN_POPUPMODE_UP;
307     }
308     else
309     {
310         nArrangeAry[0]  = FLOATWIN_POPUPMODE_DOWN;
311         nArrangeAry[1]  = FLOATWIN_POPUPMODE_UP;
312         nArrangeAry[2]  = FLOATWIN_POPUPMODE_RIGHT;
313         nArrangeAry[3]  = FLOATWIN_POPUPMODE_LEFT;
314         nArrangeAry[4]  = FLOATWIN_POPUPMODE_DOWN;
315     }
316     if ( nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE )
317         nArrangeIndex = 4;
318     else
319         nArrangeIndex = 0;
320 
321     for ( ; nArrangeIndex < 5; nArrangeIndex++ )
322     {
323         bBreak = sal_True;
324         switch ( nArrangeAry[nArrangeIndex] )
325         {
326 
327             case FLOATWIN_POPUPMODE_LEFT:
328                 aPos.X() = devRect.Left()-aSize.Width()+1;
329                 aPos.Y() = devRect.Top();
330                 aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
331                 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
332                 {
333                     if( (devRectRTL.Right()+aSize.Width()) > aScreenRect.Right() )
334                         bBreak = sal_False;
335                 }
336                 else
337                 {
338                     if ( aPos.X() < aScreenRect.Left() )
339                         bBreak = sal_False;
340                 }
341                 if( bBreak )
342                 {
343                     e1 = devRect.TopLeft();
344                     e2 = devRect.BottomLeft();
345                     // set non-zero width
346                     e2.X()++;
347                     // don't clip corners
348                     e1.Y()++;
349                     e2.Y()--;
350                 }
351                 break;
352             case FLOATWIN_POPUPMODE_RIGHT:
353                 aPos     = devRect.TopRight();
354                 aPos.Y() -= pWindow->mpWindowImpl->mnTopBorder;
355                 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
356                 {
357                     if( (devRectRTL.Left() - aSize.Width()) < aScreenRect.Left() )
358                         bBreak = sal_False;
359                 }
360                 else
361                 {
362                     if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
363                         bBreak = sal_False;
364                 }
365                 if( bBreak )
366                 {
367                     e1 = devRect.TopRight();
368                     e2 = devRect.BottomRight();
369                     // set non-zero width
370                     e2.X()++;
371                     // don't clip corners
372                     e1.Y()++;
373                     e2.Y()--;
374                 }
375                 break;
376             case FLOATWIN_POPUPMODE_UP:
377                 aPos.X() = devRect.Left();
378                 aPos.Y() = devRect.Top()-aSize.Height()+1;
379                 if ( aPos.Y() < aScreenRect.Top() )
380                     bBreak = sal_False;
381                 if( bBreak )
382                 {
383                     e1 = devRect.TopLeft();
384                     e2 = devRect.TopRight();
385                     // set non-zero height
386                     e2.Y()++;
387                     // don't clip corners
388                     e1.X()++;
389                     e2.X()--;
390                 }
391                 break;
392             case FLOATWIN_POPUPMODE_DOWN:
393                 aPos = devRect.BottomLeft();
394                 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
395                     bBreak = sal_False;
396                 if( bBreak )
397                 {
398                     e1 = devRect.BottomLeft();
399                     e2 = devRect.BottomRight();
400                     // set non-zero height
401                     e2.Y()++;
402                     // don't clip corners
403                     e1.X()++;
404                     e2.X()--;
405                 }
406                 break;
407         }
408 
409         // Evt. noch anpassen
410         if ( bBreak && !(nFlags & FLOATWIN_POPUPMODE_NOAUTOARRANGE) )
411         {
412             if ( (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_LEFT)  ||
413                  (nArrangeAry[nArrangeIndex] == FLOATWIN_POPUPMODE_RIGHT) )
414             {
415                 if ( aPos.Y()+aSize.Height() > aScreenRect.Bottom() )
416                 {
417                     aPos.Y() = devRect.Bottom()-aSize.Height()+1;
418                     if ( aPos.Y() < aScreenRect.Top() )
419                         aPos.Y() = aScreenRect.Top();
420                 }
421             }
422             else
423             {
424                 if( bRTL ) // --- RTL --- we're comparing screen coordinates here
425                 {
426                     if( devRectRTL.Right()-aSize.Width()+1 < aScreenRect.Left() )
427                         aPos.X() -= aScreenRect.Left() - devRectRTL.Right() + aSize.Width() - 1;
428                     else if( aPos.X() + aSize.Width() > aScreenRect.Right() )
429                     {
430                         aPos.X() -= aSize.Width()-2; // popup to left instead
431                         aPos.Y() -= 2;
432                     }
433                 }
434                 else if ( aPos.X()+aSize.Width() > aScreenRect.Right() )
435                 {
436                     aPos.X() = devRect.Right()-aSize.Width()+1;
437                     if ( aPos.X() < aScreenRect.Left() )
438                         aPos.X() = aScreenRect.Left();
439                 }
440             }
441         }
442 
443         if ( bBreak )
444             break;
445     }
446     if ( nArrangeIndex > 4 )
447         nArrangeIndex = 4;
448 
449     rArrangeIndex = nArrangeIndex;
450 
451     aPos = pW->AbsoluteScreenToOutputPixel( aPos );
452 
453     // store a cliprect that can be used to clip the common edge of the itemrect and the floating window
454     if( pFloatingWindow )
455     {
456         pFloatingWindow->mpImplData->maItemEdgeClipRect =
457             Rectangle( e1, e2 );
458     }
459 
460     // caller expects cordinates relative to top-level win
461     return pW->OutputToScreenPixel( aPos );
462 }
463 
464 // -----------------------------------------------------------------------
465 
466 FloatingWindow* FloatingWindow::ImplFloatHitTest( Window* pReference, const Point& rPos, sal_uInt16& rHitTest )
467 {
468     FloatingWindow* pWin = this;
469 
470     Point aAbsolute( rPos );
471 
472     // compare coordinates in absolute screen coordinates
473     if( pReference->ImplHasMirroredGraphics()  )
474     {
475         if(!pReference->IsRTLEnabled() )
476             // --- RTL --- re-mirror back to get device coordiantes
477             pReference->ImplReMirror( aAbsolute );
478 
479         Rectangle aRect( pReference->ScreenToOutputPixel(aAbsolute), Size(1,1) ) ;
480         aRect = pReference->ImplOutputToUnmirroredAbsoluteScreenPixel( aRect );
481         aAbsolute = aRect.TopLeft();
482     }
483     else
484         aAbsolute = Point( pReference->OutputToAbsoluteScreenPixel(
485             pReference->ScreenToOutputPixel(rPos) ) );
486 
487     do
488     {
489         // compute the floating window's size in absolute screen coordinates
490 
491         // use the border window to have the exact position
492         Window *pBorderWin = pWin->GetWindow( WINDOW_BORDER );
493 
494         Point aPt;  // the top-left corner in output coordinates ie (0,0)
495         Rectangle devRect( pBorderWin->ImplOutputToUnmirroredAbsoluteScreenPixel( Rectangle( aPt, pBorderWin->GetSizePixel()) ) ) ;
496         if ( devRect.IsInside( aAbsolute ) )
497         {
498             rHitTest = IMPL_FLOATWIN_HITTEST_WINDOW;
499             return pWin;
500         }
501 
502         // test, if mouse is in rectangle, (this is typically the rect of the active
503         // toolbox item or similar)
504         // note: maFloatRect is set in FloatingWindow::StartPopupMode() and
505         //       is already in absolute device coordinates
506         if ( pWin->maFloatRect.IsInside( aAbsolute ) )
507         {
508             rHitTest = IMPL_FLOATWIN_HITTEST_RECT;
509             return pWin;
510         }
511 
512         pWin = pWin->mpNextFloat;
513     }
514     while ( pWin );
515 
516     rHitTest = IMPL_FLOATWIN_HITTEST_OUTSIDE;
517     return NULL;
518 }
519 
520 // -----------------------------------------------------------------------
521 
522 FloatingWindow* FloatingWindow::ImplFindLastLevelFloat()
523 {
524     FloatingWindow* pWin = this;
525     FloatingWindow* pLastFoundWin = pWin;
526 
527     do
528     {
529         if ( pWin->GetPopupModeFlags() & FLOATWIN_POPUPMODE_NEWLEVEL )
530             pLastFoundWin = pWin;
531 
532         pWin = pWin->mpNextFloat;
533     }
534     while ( pWin );
535 
536     return pLastFoundWin;
537 }
538 
539 // -----------------------------------------------------------------------
540 
541 sal_Bool FloatingWindow::ImplIsFloatPopupModeWindow( const Window* pWindow )
542 {
543     FloatingWindow* pWin = this;
544 
545     do
546     {
547         if ( pWin->mpFirstPopupModeWin == pWindow )
548             return sal_True;
549 
550         pWin = pWin->mpNextFloat;
551     }
552     while ( pWin );
553 
554     return sal_False;
555 }
556 
557 // -----------------------------------------------------------------------
558 
559 IMPL_LINK( FloatingWindow, ImplEndPopupModeHdl, void*, EMPTYARG )
560 {
561     mnPostId            = 0;
562     mnPopupModeFlags    = 0;
563     mbPopupMode         = sal_False;
564     PopupModeEnd();
565     return 0;
566 }
567 
568 // -----------------------------------------------------------------------
569 
570 long FloatingWindow::Notify( NotifyEvent& rNEvt )
571 {
572     // Zuerst Basisklasse rufen wegen TabSteuerung
573     long nRet = SystemWindow::Notify( rNEvt );
574     if ( !nRet )
575     {
576         if ( rNEvt.GetType() == EVENT_KEYINPUT )
577         {
578             const KeyEvent* pKEvt = rNEvt.GetKeyEvent();
579             KeyCode         aKeyCode = pKEvt->GetKeyCode();
580             sal_uInt16          nKeyCode = aKeyCode.GetCode();
581 
582             if ( (nKeyCode == KEY_ESCAPE) && (GetStyle() & WB_CLOSEABLE) )
583             {
584                 Close();
585                 return sal_True;
586             }
587         }
588     }
589 
590     return nRet;
591 }
592 
593 // -----------------------------------------------------------------------
594 
595 void FloatingWindow::StateChanged( StateChangedType nType )
596 {
597     SystemWindow::StateChanged( nType );
598 
599     if ( nType == STATE_CHANGE_CONTROLBACKGROUND )
600     {
601         ImplInitSettings();
602         Invalidate();
603     }
604 }
605 
606 // -----------------------------------------------------------------------
607 
608 void FloatingWindow::DataChanged( const DataChangedEvent& rDCEvt )
609 {
610     SystemWindow::DataChanged( rDCEvt );
611 
612     if ( (rDCEvt.GetType() == DATACHANGED_SETTINGS) &&
613          (rDCEvt.GetFlags() & SETTINGS_STYLE) )
614     {
615         ImplInitSettings();
616         Invalidate();
617     }
618 }
619 
620 // -----------------------------------------------------------------------
621 
622 void FloatingWindow::ImplCallPopupModeEnd()
623 {
624     // PopupMode wurde beendet
625     mbInPopupMode = sal_False;
626 
627     // Handler asyncron rufen
628     if ( !mnPostId )
629         Application::PostUserEvent( mnPostId, LINK( this, FloatingWindow, ImplEndPopupModeHdl ) );
630 }
631 
632 // -----------------------------------------------------------------------
633 
634 void FloatingWindow::PopupModeEnd()
635 {
636     maPopupModeEndHdl.Call( this );
637 }
638 
639 // -----------------------------------------------------------------------
640 
641 void FloatingWindow::SetTitleType( sal_uInt16 nTitle )
642 {
643     if ( (mnTitle != nTitle) && mpWindowImpl->mpBorderWindow )
644     {
645         mnTitle = nTitle;
646         Size aOutSize = GetOutputSizePixel();
647         sal_uInt16 nTitleStyle;
648         if ( nTitle == FLOATWIN_TITLE_NORMAL )
649             nTitleStyle = BORDERWINDOW_TITLE_SMALL;
650         else if ( nTitle == FLOATWIN_TITLE_TEAROFF )
651             nTitleStyle = BORDERWINDOW_TITLE_TEAROFF;
652         else // nTitle == FLOATWIN_TITLE_NONE
653             nTitleStyle = BORDERWINDOW_TITLE_NONE;
654         ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->SetTitleType( nTitleStyle, aOutSize );
655         ((ImplBorderWindow*)mpWindowImpl->mpBorderWindow)->GetBorder( mpWindowImpl->mnLeftBorder, mpWindowImpl->mnTopBorder, mpWindowImpl->mnRightBorder, mpWindowImpl->mnBottomBorder );
656     }
657 }
658 
659 // -----------------------------------------------------------------------
660 
661 void FloatingWindow::StartPopupMode( const Rectangle& rRect, sal_uLong nFlags )
662 {
663     // avoid flickering
664     if ( IsVisible() )
665         Show( sal_False, SHOW_NOFOCUSCHANGE );
666 
667     if ( IsRollUp() )
668         RollDown();
669 
670     // remove title
671     mnOldTitle = mnTitle;
672     if ( nFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF )
673         SetTitleType( FLOATWIN_TITLE_TEAROFF );
674     else
675         SetTitleType( FLOATWIN_TITLE_NONE );
676 
677     // avoid close on focus change for decorated floating windows only
678     if( mpWindowImpl->mbFrame && (GetStyle() & WB_MOVEABLE) )
679         nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
680 
681     // #102010# For debugging Accessibility
682     static const char* pEnv = getenv("SAL_FLOATWIN_NOAPPFOCUSCLOSE" );
683     if( pEnv && *pEnv )
684         nFlags |= FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
685 
686     // compute window position according to flags and arrangement
687     sal_uInt16 nArrangeIndex;
688     SetPosPixel( ImplCalcPos( this, rRect, nFlags, nArrangeIndex ) );
689 
690     // set data and display window
691     // convert maFloatRect to absolute device coordinates
692     // so they can be compared across different frames
693     // !!! rRect is expected to be in screen coordinates of the parent frame window !!!
694     maFloatRect             = rRect;
695     if( GetParent()->ImplHasMirroredGraphics() )
696     {
697         maFloatRect.SetPos( GetParent()->ScreenToOutputPixel( rRect.TopLeft() ) );
698         maFloatRect = GetParent()->ImplOutputToUnmirroredAbsoluteScreenPixel( maFloatRect );
699     }
700     else
701         maFloatRect.SetPos( GetParent()->OutputToAbsoluteScreenPixel( GetParent()->ScreenToOutputPixel( rRect.TopLeft() ) ) );
702 
703     maFloatRect.Left()     -= 2;
704     maFloatRect.Top()      -= 2;
705     maFloatRect.Right()    += 2;
706     maFloatRect.Bottom()   += 2;
707     mnPopupModeFlags        = nFlags;
708     mbInPopupMode           = sal_True;
709     mbPopupMode             = sal_True;
710     mbPopupModeCanceled     = sal_False;
711     mbPopupModeTearOff      = sal_False;
712     mbMouseDown             = sal_False;
713 
714     mbOldSaveBackMode       = IsSaveBackgroundEnabled();
715     EnableSaveBackground();
716 
717     // add FloatingWindow to list of windows that are in popup mode
718     ImplSVData* pSVData = ImplGetSVData();
719     mpNextFloat = pSVData->maWinData.mpFirstFloat;
720     pSVData->maWinData.mpFirstFloat = this;
721     if( nFlags & FLOATWIN_POPUPMODE_GRABFOCUS )
722     {
723         // force key input even without focus (useful for menues)
724         mbGrabFocus = sal_True;
725     }
726     Show( sal_True, SHOW_NOACTIVATE );
727 }
728 
729 // -----------------------------------------------------------------------
730 
731 void FloatingWindow::StartPopupMode( ToolBox* pBox, sal_uLong nFlags )
732 {
733     // get selected button
734     sal_uInt16 nItemId = pBox->GetDownItemId();
735     if ( !nItemId )
736         return;
737 
738     mpImplData->mpBox = pBox;
739     pBox->ImplFloatControl( sal_True, this );
740 
741     // retrieve some data from the ToolBox
742     Rectangle aRect = pBox->GetItemRect( nItemId );
743     Point aPos;
744     // convert to parent's screen coordinates
745     aPos = GetParent()->OutputToScreenPixel( GetParent()->AbsoluteScreenToOutputPixel( pBox->OutputToAbsoluteScreenPixel( aRect.TopLeft() ) ) );
746     aRect.SetPos( aPos );
747 
748     nFlags |=
749         FLOATWIN_POPUPMODE_NOFOCUSCLOSE 	|
750 //        FLOATWIN_POPUPMODE_NOMOUSECLOSE		|
751         FLOATWIN_POPUPMODE_ALLMOUSEBUTTONCLOSE |
752 //        FLOATWIN_POPUPMODE_NOMOUSERECTCLOSE	|   // #105968# floating toolboxes should close when clicked in (parent's) float rect
753         FLOATWIN_POPUPMODE_NOMOUSEUPCLOSE;
754 //        	|      FLOATWIN_POPUPMODE_NOAPPFOCUSCLOSE;
755 
756 /*
757  *  FLOATWIN_POPUPMODE_NOKEYCLOSE		|
758  *  don't set since it disables closing floaters with escape
759  */
760 
761     // Flags fuer Positionierung bestimmen
762     if ( !(nFlags & (FLOATWIN_POPUPMODE_DOWN | FLOATWIN_POPUPMODE_UP |
763                      FLOATWIN_POPUPMODE_LEFT | FLOATWIN_POPUPMODE_RIGHT |
764                      FLOATWIN_POPUPMODE_NOAUTOARRANGE)) )
765     {
766          if ( pBox->IsHorizontal() )
767              nFlags |= FLOATWIN_POPUPMODE_DOWN;
768          else
769              nFlags |= FLOATWIN_POPUPMODE_RIGHT;
770     }
771 
772     // FloatingModus starten
773     StartPopupMode( aRect, nFlags );
774 }
775 
776 // -----------------------------------------------------------------------
777 
778 void FloatingWindow::ImplEndPopupMode( sal_uInt16 nFlags, sal_uLong nFocusId )
779 {
780     if ( !mbInPopupMode )
781         return;
782 
783     ImplSVData* pSVData = ImplGetSVData();
784 
785     mbInCleanUp = sal_True; // prevent killing this window due to focus change while working with it
786 
787     // Bei allen nachfolgenden PopupMode-Fenster den Modus auch beenden
788     while ( pSVData->maWinData.mpFirstFloat && pSVData->maWinData.mpFirstFloat != this )
789         pSVData->maWinData.mpFirstFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL );
790 
791 
792     // Fenster aus der Liste austragen
793     pSVData->maWinData.mpFirstFloat = mpNextFloat;
794     mpNextFloat = NULL;
795 
796     sal_uLong nPopupModeFlags = mnPopupModeFlags;
797 
798     // Wenn nicht abgerissen wurde, dann Fenster wieder Hiden
799     if ( !(nFlags & FLOATWIN_POPUPMODEEND_TEAROFF) ||
800          !(nPopupModeFlags & FLOATWIN_POPUPMODE_ALLOWTEAROFF) )
801     {
802         Show( sal_False, SHOW_NOFOCUSCHANGE );
803 
804         // Focus evt. auf ein entsprechendes FloatingWindow weiterschalten
805         if ( nFocusId )
806             Window::EndSaveFocus( nFocusId );
807         else if ( pSVData->maWinData.mpFocusWin && pSVData->maWinData.mpFirstFloat &&
808                   ImplIsWindowOrChild( pSVData->maWinData.mpFocusWin ) )
809             pSVData->maWinData.mpFirstFloat->GrabFocus();
810         mbPopupModeTearOff = sal_False;
811     }
812     else
813     {
814         mbPopupModeTearOff = sal_True;
815         if ( nFocusId )
816             Window::EndSaveFocus( nFocusId, sal_False );
817     }
818     EnableSaveBackground( mbOldSaveBackMode );
819 
820     mbPopupModeCanceled = (nFlags & FLOATWIN_POPUPMODEEND_CANCEL) != 0;
821 
822     // Gegebenenfalls den Title wieder herstellen
823     SetTitleType( mnOldTitle );
824 
825     // ToolBox wieder auf normal schalten
826     if ( mpImplData->mpBox )
827     {
828         mpImplData->mpBox->ImplFloatControl( sal_False, this );
829         mpImplData->mpBox = NULL;
830     }
831 
832     // Je nach Parameter den PopupModeEnd-Handler rufen
833     if ( !(nFlags & FLOATWIN_POPUPMODEEND_DONTCALLHDL) )
834         ImplCallPopupModeEnd();
835 
836     // Je nach Parameter die restlichen Fenster auch noch schliessen
837     if ( nFlags & FLOATWIN_POPUPMODEEND_CLOSEALL )
838     {
839         if ( !(nPopupModeFlags & FLOATWIN_POPUPMODE_NEWLEVEL) )
840         {
841             if ( pSVData->maWinData.mpFirstFloat )
842             {
843                 FloatingWindow* pLastLevelFloat = pSVData->maWinData.mpFirstFloat->ImplFindLastLevelFloat();
844                 pLastLevelFloat->EndPopupMode( FLOATWIN_POPUPMODEEND_CANCEL | FLOATWIN_POPUPMODEEND_CLOSEALL );
845             }
846         }
847     }
848 
849     mbInCleanUp = sal_False;
850 }
851 
852 // -----------------------------------------------------------------------
853 
854 void FloatingWindow::EndPopupMode( sal_uInt16 nFlags )
855 {
856     ImplEndPopupMode( nFlags );
857 }
858 
859 // -----------------------------------------------------------------------
860 
861 void FloatingWindow::AddPopupModeWindow( Window* pWindow )
862 {
863     // !!! bisher erst 1 Fenster und noch keine Liste
864     mpFirstPopupModeWin = pWindow;
865 }
866 
867 // -----------------------------------------------------------------------
868 
869 void FloatingWindow::RemovePopupModeWindow( Window* pWindow )
870 {
871     // !!! bisher erst 1 Fenster und noch keine Liste
872     if ( mpFirstPopupModeWin == pWindow )
873         mpFirstPopupModeWin = NULL;
874 }
875 
876