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