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 54 FloatingWindow::ImplData::ImplData() 55 { 56 mpBox = NULL; 57 } 58 59 FloatingWindow::ImplData::~ImplData() 60 { 61 } 62 63 Rectangle& FloatingWindow::ImplGetItemEdgeClipRect() 64 { 65 return mpImplData->maItemEdgeClipRect; 66 } 67 68 // ======================================================================= 69 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 dont 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, eg 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 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 164 FloatingWindow::FloatingWindow( Window* pParent, WinBits nStyle ) : 165 SystemWindow( WINDOW_FLOATINGWINDOW ) 166 { 167 ImplInit( pParent, nStyle ); 168 } 169 170 // ----------------------------------------------------------------------- 171 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 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 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 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 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 cordinates relative to top-level win 457 return pW->OutputToScreenPixel( aPos ); 458 } 459 460 // ----------------------------------------------------------------------- 461 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 coordiantes 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 ie (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 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 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 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 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 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 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 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 630 void FloatingWindow::PopupModeEnd() 631 { 632 maPopupModeEndHdl.Call( this ); 633 } 634 635 // ----------------------------------------------------------------------- 636 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 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 menues) 720 mbGrabFocus = sal_True; 721 } 722 Show( sal_True, SHOW_NOACTIVATE ); 723 } 724 725 // ----------------------------------------------------------------------- 726 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 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 850 void FloatingWindow::EndPopupMode( sal_uInt16 nFlags ) 851 { 852 ImplEndPopupMode( nFlags ); 853 } 854 855 // ----------------------------------------------------------------------- 856 857 void FloatingWindow::AddPopupModeWindow( Window* pWindow ) 858 { 859 // !!! bisher erst 1 Fenster und noch keine Liste 860 mpFirstPopupModeWin = pWindow; 861 } 862 863 // ----------------------------------------------------------------------- 864 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 872