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