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