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