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 <string> 32 33 #include "rtl/ustrbuf.hxx" 34 35 #include "osl/file.h" 36 37 #include "vcl/svapp.hxx" 38 #include "vcl/window.hxx" 39 #include "vcl/timer.hxx" 40 41 #include "aqua/saldata.hxx" 42 #include "aqua/salgdi.h" 43 #include "aqua/salframe.h" 44 #include "aqua/salmenu.h" 45 #include "aqua/saltimer.h" 46 #include "aqua/salinst.h" 47 #include "aqua/salframeview.h" 48 #include "aqua/aqua11yfactory.h" 49 50 #include "salwtype.hxx" 51 52 #include "premac.h" 53 // needed for theming 54 // FIXME: move theming code to salnativewidgets.cxx 55 #include <Carbon/Carbon.h> 56 #include "postmac.h" 57 58 59 using namespace std; 60 61 // ======================================================================= 62 63 AquaSalFrame* AquaSalFrame::s_pCaptureFrame = NULL; 64 65 // ======================================================================= 66 67 AquaSalFrame::AquaSalFrame( SalFrame* pParent, sal_uLong salFrameStyle ) : 68 mpWindow(nil), 69 mpView(nil), 70 mpDockMenuEntry(nil), 71 mpGraphics(NULL), 72 mpParent(NULL), 73 mnMinWidth(0), 74 mnMinHeight(0), 75 mnMaxWidth(0), 76 mnMaxHeight(0), 77 mbGraphics(false), 78 mbFullScreen( false ), 79 mbShown(false), 80 mbInitShow(true), 81 mbPositioned(false), 82 mbSized(false), 83 mbPresentation( false ), 84 mnStyle( salFrameStyle ), 85 mnStyleMask( 0 ), 86 mnLastEventTime( 0 ), 87 mnLastModifierFlags( 0 ), 88 mpMenu( NULL ), 89 mnExtStyle( 0 ), 90 mePointerStyle( POINTER_ARROW ), 91 mnTrackingRectTag( 0 ), 92 mrClippingPath( 0 ), 93 mnICOptions( 0 ) 94 { 95 maSysData.nSize = sizeof( SystemEnvData ); 96 97 mpParent = dynamic_cast<AquaSalFrame*>(pParent); 98 99 initWindowAndView(); 100 101 SalData* pSalData = GetSalData(); 102 pSalData->maFrames.push_front( this ); 103 pSalData->maFrameCheck.insert( this ); 104 } 105 106 // ----------------------------------------------------------------------- 107 108 AquaSalFrame::~AquaSalFrame() 109 { 110 // if the frame is destroyed and has the current menubar 111 // set the default menubar 112 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu ) 113 AquaSalMenu::setDefaultMenu(); 114 115 // cleanup clipping stuff 116 ResetClipRegion(); 117 118 [SalFrameView unsetMouseFrame: this]; 119 120 SalData* pSalData = GetSalData(); 121 pSalData->maFrames.remove( this ); 122 pSalData->maFrameCheck.erase( this ); 123 124 DBG_ASSERT( this != s_pCaptureFrame, "capture frame destroyed" ); 125 if( this == s_pCaptureFrame ) 126 s_pCaptureFrame = NULL; 127 128 if ( mpGraphics ) 129 delete mpGraphics; 130 131 if( mpDockMenuEntry ) 132 // life cycle comment: the menu has ownership of the item, so no release 133 [AquaSalInstance::GetDynamicDockMenu() removeItem: mpDockMenuEntry]; 134 if ( mpView ) { 135 [AquaA11yFactory revokeView: mpView]; 136 [mpView release]; 137 } 138 if ( mpWindow ) 139 [mpWindow release]; 140 } 141 142 // ----------------------------------------------------------------------- 143 144 void AquaSalFrame::initWindowAndView() 145 { 146 // initialize mirroring parameters 147 // FIXME: screens changing 148 NSScreen * pScreen = [mpWindow screen]; 149 if( pScreen == nil ) 150 pScreen = [NSScreen mainScreen]; 151 maScreenRect = [pScreen frame]; 152 153 // calculate some default geometry 154 NSRect aVisibleRect = [pScreen visibleFrame]; 155 CocoaToVCL( aVisibleRect ); 156 157 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x + aVisibleRect.size.width / 10); 158 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y + aVisibleRect.size.height / 10); 159 maGeometry.nWidth = static_cast<unsigned int>(aVisibleRect.size.width * 0.8); 160 maGeometry.nHeight = static_cast<unsigned int>(aVisibleRect.size.height * 0.8); 161 162 // calculate style mask 163 if( (mnStyle & SAL_FRAME_STYLE_FLOAT) || 164 (mnStyle & SAL_FRAME_STYLE_OWNERDRAWDECORATION) ) 165 mnStyleMask = NSBorderlessWindowMask; 166 else if( mnStyle & SAL_FRAME_STYLE_DEFAULT ) 167 { 168 mnStyleMask = NSTitledWindowMask | 169 NSMiniaturizableWindowMask | 170 NSResizableWindowMask | 171 NSClosableWindowMask; 172 // make default window "maximized" 173 maGeometry.nX = static_cast<int>(aVisibleRect.origin.x); 174 maGeometry.nY = static_cast<int>(aVisibleRect.origin.y); 175 maGeometry.nWidth = static_cast<int>(aVisibleRect.size.width); 176 maGeometry.nHeight = static_cast<int>(aVisibleRect.size.height); 177 mbPositioned = mbSized = true; 178 } 179 else 180 { 181 if( (mnStyle & SAL_FRAME_STYLE_MOVEABLE) ) 182 { 183 mnStyleMask |= NSTitledWindowMask; 184 if( mpParent == NULL ) 185 mnStyleMask |= NSMiniaturizableWindowMask; 186 } 187 if( (mnStyle & SAL_FRAME_STYLE_SIZEABLE) ) 188 mnStyleMask |= NSResizableWindowMask; 189 if( (mnStyle & SAL_FRAME_STYLE_CLOSEABLE) ) 190 mnStyleMask |= NSClosableWindowMask; 191 // documentation says anything other than NSBorderlessWindowMask (=0) 192 // should also include NSTitledWindowMask; 193 if( mnStyleMask != 0 ) 194 mnStyleMask |= NSTitledWindowMask; 195 } 196 197 // #i91990# support GUI-less (daemon) execution 198 @try 199 { 200 mpWindow = [[SalFrameWindow alloc] initWithSalFrame: this]; 201 mpView = [[SalFrameView alloc] initWithSalFrame: this]; 202 } 203 @catch ( id exception ) 204 { 205 return; 206 } 207 208 if( (mnStyle & SAL_FRAME_STYLE_TOOLTIP) ) 209 [mpWindow setIgnoresMouseEvents: YES]; 210 else 211 [mpWindow setAcceptsMouseMovedEvents: YES]; 212 [mpWindow setHasShadow: YES]; 213 [mpWindow setDelegate: mpWindow]; 214 215 NSRect aRect = { { 0,0 }, { maGeometry.nWidth, maGeometry.nHeight } }; 216 mnTrackingRectTag = [mpView addTrackingRect: aRect owner: mpView userData: nil assumeInside: NO]; 217 218 maSysData.pView = mpView; 219 220 UpdateFrameGeometry(); 221 222 [mpWindow setContentView: mpView]; 223 } 224 225 // ----------------------------------------------------------------------- 226 227 void AquaSalFrame::CocoaToVCL( NSRect& io_rRect, bool bRelativeToScreen ) 228 { 229 if( bRelativeToScreen ) 230 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height); 231 else 232 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height); 233 } 234 235 void AquaSalFrame::VCLToCocoa( NSRect& io_rRect, bool bRelativeToScreen ) 236 { 237 if( bRelativeToScreen ) 238 io_rRect.origin.y = maScreenRect.size.height - (io_rRect.origin.y+io_rRect.size.height); 239 else 240 io_rRect.origin.y = maGeometry.nHeight - (io_rRect.origin.y+io_rRect.size.height); 241 } 242 243 void AquaSalFrame::CocoaToVCL( NSPoint& io_rPoint, bool bRelativeToScreen ) 244 { 245 if( bRelativeToScreen ) 246 io_rPoint.y = maScreenRect.size.height - io_rPoint.y; 247 else 248 io_rPoint.y = maGeometry.nHeight - io_rPoint.y; 249 } 250 251 void AquaSalFrame::VCLToCocoa( NSPoint& io_rPoint, bool bRelativeToScreen ) 252 { 253 if( bRelativeToScreen ) 254 io_rPoint.y = maScreenRect.size.height - io_rPoint.y; 255 else 256 io_rPoint.y = maGeometry.nHeight - io_rPoint.y; 257 } 258 259 // ----------------------------------------------------------------------- 260 261 void AquaSalFrame::screenParametersChanged() 262 { 263 UpdateFrameGeometry(); 264 265 if( mpGraphics ) 266 mpGraphics->updateResolution(); 267 CallCallback( SALEVENT_DISPLAYCHANGED, 0 ); 268 } 269 270 // ----------------------------------------------------------------------- 271 272 SalGraphics* AquaSalFrame::GetGraphics() 273 { 274 if ( mbGraphics ) 275 return NULL; 276 277 if ( !mpGraphics ) 278 { 279 mpGraphics = new AquaSalGraphics; 280 mpGraphics->SetWindowGraphics( this ); 281 } 282 283 mbGraphics = TRUE; 284 return mpGraphics; 285 } 286 287 // ----------------------------------------------------------------------- 288 289 void AquaSalFrame::ReleaseGraphics( SalGraphics *pGraphics ) 290 { 291 (void)pGraphics; 292 DBG_ASSERT( pGraphics == mpGraphics, "graphics released on wrong frame" ); 293 mbGraphics = FALSE; 294 } 295 296 // ----------------------------------------------------------------------- 297 298 sal_Bool AquaSalFrame::PostEvent( void *pData ) 299 { 300 GetSalData()->mpFirstInstance->PostUserEvent( this, SALEVENT_USEREVENT, pData ); 301 return TRUE; 302 } 303 304 // ----------------------------------------------------------------------- 305 void AquaSalFrame::SetTitle(const XubString& rTitle) 306 { 307 if ( !mpWindow ) 308 return; 309 310 // #i113170# may not be the main thread if called from UNO API 311 SalData::ensureThreadAutoreleasePool(); 312 313 NSString* pTitle = CreateNSString( rTitle ); 314 [mpWindow setTitle: pTitle]; 315 316 // create an entry in the dock menu 317 const sal_uLong nAppWindowStyle = (SAL_FRAME_STYLE_CLOSEABLE | SAL_FRAME_STYLE_MOVEABLE); 318 if( mpParent == NULL && 319 (mnStyle & nAppWindowStyle) == nAppWindowStyle ) 320 { 321 if( mpDockMenuEntry == NULL ) 322 { 323 NSMenu* pDock = AquaSalInstance::GetDynamicDockMenu(); 324 mpDockMenuEntry = [pDock insertItemWithTitle: pTitle 325 action: @selector(dockMenuItemTriggered:) 326 keyEquivalent: @"" 327 atIndex: 0]; 328 [mpDockMenuEntry setTarget: mpWindow]; 329 330 // TODO: image (either the generic window image or an icon 331 // check mark (for "main" window ?) 332 } 333 else 334 [mpDockMenuEntry setTitle: pTitle]; 335 } 336 337 if (pTitle) 338 [pTitle release]; 339 } 340 341 // ----------------------------------------------------------------------- 342 343 void AquaSalFrame::SetIcon( sal_uInt16 ) 344 { 345 } 346 347 // ----------------------------------------------------------------------- 348 349 void AquaSalFrame::SetRepresentedURL( const rtl::OUString& i_rDocURL ) 350 { 351 // #i113170# may not be the main thread if called from UNO API 352 SalData::ensureThreadAutoreleasePool(); 353 354 if( i_rDocURL.indexOfAsciiL( "file:", 5 ) == 0 ) 355 { 356 rtl::OUString aSysPath; 357 osl_getSystemPathFromFileURL( i_rDocURL.pData, &aSysPath.pData ); 358 NSString* pStr = CreateNSString( aSysPath ); 359 if( pStr ) 360 { 361 [pStr autorelease]; 362 [mpWindow setRepresentedFilename: pStr]; 363 } 364 } 365 } 366 367 // ----------------------------------------------------------------------- 368 369 void AquaSalFrame::initShow() 370 { 371 mbInitShow = false; 372 if( ! mbPositioned && ! mbFullScreen ) 373 { 374 Rectangle aScreenRect; 375 GetWorkArea( aScreenRect ); 376 if( mpParent ) // center relative to parent 377 { 378 // center on parent 379 long nNewX = mpParent->maGeometry.nX + ((long)mpParent->maGeometry.nWidth - (long)maGeometry.nWidth)/2; 380 if( nNewX < aScreenRect.Left() ) 381 nNewX = aScreenRect.Left(); 382 if( long(nNewX + maGeometry.nWidth) > aScreenRect.Right() ) 383 nNewX = aScreenRect.Right() - maGeometry.nWidth-1; 384 long nNewY = mpParent->maGeometry.nY + ((long)mpParent->maGeometry.nHeight - (long)maGeometry.nHeight)/2; 385 if( nNewY < aScreenRect.Top() ) 386 nNewY = aScreenRect.Top(); 387 if( nNewY > aScreenRect.Bottom() ) 388 nNewY = aScreenRect.Bottom() - maGeometry.nHeight-1; 389 SetPosSize( nNewX - mpParent->maGeometry.nX, 390 nNewY - mpParent->maGeometry.nY, 391 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ); 392 } 393 else if( ! (mnStyle & SAL_FRAME_STYLE_SIZEABLE) ) 394 { 395 // center on screen 396 long nNewX = (aScreenRect.GetWidth() - maGeometry.nWidth)/2; 397 long nNewY = (aScreenRect.GetHeight() - maGeometry.nHeight)/2; 398 SetPosSize( nNewX, nNewY, 0, 0, SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y ); 399 } 400 } 401 402 // make sure the view is present in the wrapper list before any children receive focus 403 [AquaA11yFactory registerView: mpView]; 404 } 405 406 void AquaSalFrame::SendPaintEvent( const Rectangle* pRect ) 407 { 408 SalPaintEvent aPaintEvt( 0, 0, maGeometry.nWidth, maGeometry.nHeight, true ); 409 if( pRect ) 410 { 411 aPaintEvt.mnBoundX = pRect->Left(); 412 aPaintEvt.mnBoundY = pRect->Top(); 413 aPaintEvt.mnBoundWidth = pRect->GetWidth(); 414 aPaintEvt.mnBoundHeight = pRect->GetHeight(); 415 } 416 417 CallCallback(SALEVENT_PAINT, &aPaintEvt); 418 } 419 420 // ----------------------------------------------------------------------- 421 422 void AquaSalFrame::Show(sal_Bool bVisible, sal_Bool bNoActivate) 423 { 424 if ( !mpWindow ) 425 return; 426 427 // #i113170# may not be the main thread if called from UNO API 428 SalData::ensureThreadAutoreleasePool(); 429 430 mbShown = bVisible; 431 if(bVisible) 432 { 433 if( mbInitShow ) 434 initShow(); 435 436 CallCallback(SALEVENT_RESIZE, 0); 437 // trigger filling our backbuffer 438 SendPaintEvent(); 439 440 if( bNoActivate || [mpWindow canBecomeKeyWindow] == NO ) 441 [mpWindow orderFront: NSApp]; 442 else 443 [mpWindow makeKeyAndOrderFront: NSApp]; 444 445 if( mpParent ) 446 { 447 /* #i92674# #i96433# we do not want an invisible parent to show up (which adding a visible 448 child implicitly does). However we also do not want a parentless toolbar. 449 450 HACK: try to decide when we should not insert a child to its parent 451 floaters and ownerdraw windows have not yet shown up in cases where 452 we don't want the parent to become visible 453 */ 454 if( mpParent->mbShown || (mnStyle & (SAL_FRAME_STYLE_OWNERDRAWDECORATION | SAL_FRAME_STYLE_FLOAT) ) ) 455 { 456 [mpParent->mpWindow addChildWindow: mpWindow ordered: NSWindowAbove]; 457 } 458 } 459 460 if( mbPresentation ) 461 [mpWindow makeMainWindow]; 462 } 463 else 464 { 465 // if the frame holding the current menubar gets hidden 466 // show the default menubar 467 if( mpMenu && mpMenu->mbMenuBar && AquaSalMenu::pCurrentMenuBar == mpMenu ) 468 AquaSalMenu::setDefaultMenu(); 469 470 // #i90440# #i94443# work around the focus going back to some other window 471 // if a child gets hidden for a parent window 472 if( mpParent && mpParent->mbShown && [mpWindow isKeyWindow] ) 473 [mpParent->mpWindow makeKeyAndOrderFront: NSApp]; 474 475 [SalFrameView unsetMouseFrame: this]; 476 if( mpParent && [mpWindow parentWindow] == mpParent->mpWindow ) 477 [mpParent->mpWindow removeChildWindow: mpWindow]; 478 479 [mpWindow orderOut: NSApp]; 480 } 481 } 482 483 // ----------------------------------------------------------------------- 484 485 void AquaSalFrame::Enable( sal_Bool ) 486 { 487 } 488 489 // ----------------------------------------------------------------------- 490 491 void AquaSalFrame::SetMinClientSize( long nWidth, long nHeight ) 492 { 493 // #i113170# may not be the main thread if called from UNO API 494 SalData::ensureThreadAutoreleasePool(); 495 496 mnMinWidth = nWidth; 497 mnMinHeight = nHeight; 498 499 if( mpWindow ) 500 { 501 // Always add the decoration as the dimension concerns only 502 // the content rectangle 503 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration; 504 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration; 505 506 NSSize aSize = { nWidth, nHeight }; 507 508 // Size of full window (content+structure) although we only 509 // have the client size in arguments 510 [mpWindow setMinSize: aSize]; 511 } 512 } 513 514 // ----------------------------------------------------------------------- 515 516 void AquaSalFrame::SetMaxClientSize( long nWidth, long nHeight ) 517 { 518 // #i113170# may not be the main thread if called from UNO API 519 SalData::ensureThreadAutoreleasePool(); 520 521 mnMaxWidth = nWidth; 522 mnMaxHeight = nHeight; 523 524 if( mpWindow ) 525 { 526 // Always add the decoration as the dimension concerns only 527 // the content rectangle 528 nWidth += maGeometry.nLeftDecoration + maGeometry.nRightDecoration; 529 nHeight += maGeometry.nTopDecoration + maGeometry.nBottomDecoration; 530 531 // Carbon windows can't have a size greater than 32767x32767 532 if (nWidth>32767) nWidth=32767; 533 if (nHeight>32767) nHeight=32767; 534 535 NSSize aSize = { nWidth, nHeight }; 536 537 // Size of full window (content+structure) although we only 538 // have the client size in arguments 539 [mpWindow setMaxSize: aSize]; 540 } 541 } 542 543 // ----------------------------------------------------------------------- 544 545 void AquaSalFrame::SetClientSize( long nWidth, long nHeight ) 546 { 547 // #i113170# may not be the main thread if called from UNO API 548 SalData::ensureThreadAutoreleasePool(); 549 550 if( mpWindow ) 551 { 552 NSSize aSize = { nWidth, nHeight }; 553 554 [mpWindow setContentSize: aSize]; 555 UpdateFrameGeometry(); 556 if( mbShown ) 557 // trigger filling our backbuffer 558 SendPaintEvent(); 559 } 560 } 561 562 // ----------------------------------------------------------------------- 563 564 void AquaSalFrame::GetClientSize( long& rWidth, long& rHeight ) 565 { 566 if( mbShown || mbInitShow ) 567 { 568 rWidth = maGeometry.nWidth; 569 rHeight = maGeometry.nHeight; 570 } 571 else 572 { 573 rWidth = 0; 574 rHeight = 0; 575 } 576 } 577 578 // ----------------------------------------------------------------------- 579 580 void AquaSalFrame::SetWindowState( const SalFrameState* pState ) 581 { 582 // #i113170# may not be the main thread if called from UNO API 583 SalData::ensureThreadAutoreleasePool(); 584 585 if ( mpWindow ) 586 { 587 // set normal state 588 NSRect aStateRect = [mpWindow frame]; 589 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask]; 590 CocoaToVCL( aStateRect ); 591 if( pState->mnMask & SAL_FRAMESTATE_MASK_X ) 592 aStateRect.origin.x = float(pState->mnX); 593 if( pState->mnMask & SAL_FRAMESTATE_MASK_Y ) 594 aStateRect.origin.y = float(pState->mnY); 595 if( pState->mnMask & SAL_FRAMESTATE_MASK_WIDTH ) 596 aStateRect.size.width = float(pState->mnWidth); 597 if( pState->mnMask & SAL_FRAMESTATE_MASK_HEIGHT ) 598 aStateRect.size.height = float(pState->mnHeight); 599 VCLToCocoa( aStateRect ); 600 aStateRect = [NSWindow frameRectForContentRect: aStateRect styleMask: mnStyleMask]; 601 602 [mpWindow setFrame: aStateRect display: NO]; 603 if( pState->mnState == SAL_FRAMESTATE_MINIMIZED ) 604 [mpWindow miniaturize: NSApp]; 605 else if( [mpWindow isMiniaturized] ) 606 [mpWindow deminiaturize: NSApp]; 607 608 609 /* ZOOMED is not really maximized (actually it toggles between a user set size and 610 the program specified one), but comes closest since the default behavior is 611 "maximized" if the user did not intervene 612 */ 613 if( pState->mnState == SAL_FRAMESTATE_MAXIMIZED ) 614 { 615 if(! [mpWindow isZoomed]) 616 [mpWindow zoom: NSApp]; 617 } 618 else 619 { 620 if( [mpWindow isZoomed] ) 621 [mpWindow zoom: NSApp]; 622 } 623 } 624 625 // get new geometry 626 UpdateFrameGeometry(); 627 628 sal_uInt16 nEvent = 0; 629 if( pState->mnMask & (SAL_FRAMESTATE_MASK_X | SAL_FRAMESTATE_MASK_X) ) 630 { 631 mbPositioned = true; 632 nEvent = SALEVENT_MOVE; 633 } 634 635 if( pState->mnMask & (SAL_FRAMESTATE_MASK_WIDTH | SAL_FRAMESTATE_MASK_HEIGHT) ) 636 { 637 mbSized = true; 638 nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE; 639 } 640 // send event that we were moved/sized 641 if( nEvent ) 642 CallCallback( nEvent, NULL ); 643 644 if( mbShown && mpWindow ) 645 { 646 // trigger filling our backbuffer 647 SendPaintEvent(); 648 649 // tell the system the views need to be updated 650 [mpWindow display]; 651 } 652 } 653 654 // ----------------------------------------------------------------------- 655 656 sal_Bool AquaSalFrame::GetWindowState( SalFrameState* pState ) 657 { 658 if ( !mpWindow ) 659 return FALSE; 660 661 // #i113170# may not be the main thread if called from UNO API 662 SalData::ensureThreadAutoreleasePool(); 663 664 pState->mnMask = SAL_FRAMESTATE_MASK_X | 665 SAL_FRAMESTATE_MASK_Y | 666 SAL_FRAMESTATE_MASK_WIDTH | 667 SAL_FRAMESTATE_MASK_HEIGHT | 668 #if 0 669 SAL_FRAMESTATE_MASK_MAXIMIZED_X | 670 SAL_FRAMESTATE_MASK_MAXIMIZED_Y | 671 SAL_FRAMESTATE_MASK_MAXIMIZED_WIDTH | 672 SAL_FRAMESTATE_MASK_MAXIMIZED_HEIGHT | 673 #endif 674 SAL_FRAMESTATE_MASK_STATE; 675 676 NSRect aStateRect = [mpWindow frame]; 677 aStateRect = [NSWindow contentRectForFrameRect: aStateRect styleMask: mnStyleMask]; 678 CocoaToVCL( aStateRect ); 679 pState->mnX = long(aStateRect.origin.x); 680 pState->mnY = long(aStateRect.origin.y); 681 pState->mnWidth = long(aStateRect.size.width); 682 pState->mnHeight = long(aStateRect.size.height); 683 684 if( [mpWindow isMiniaturized] ) 685 pState->mnState = SAL_FRAMESTATE_MINIMIZED; 686 else if( ! [mpWindow isZoomed] ) 687 pState->mnState = SAL_FRAMESTATE_NORMAL; 688 else 689 pState->mnState = SAL_FRAMESTATE_MAXIMIZED; 690 691 return TRUE; 692 } 693 694 // ----------------------------------------------------------------------- 695 696 void AquaSalFrame::SetScreenNumber(unsigned int nScreen) 697 { 698 if ( !mpWindow ) 699 return; 700 701 // #i113170# may not be the main thread if called from UNO API 702 SalData::ensureThreadAutoreleasePool(); 703 704 NSArray* pScreens = [NSScreen screens]; 705 Rectangle aRet; 706 NSScreen* pScreen = nil; 707 if( pScreens && nScreen < [pScreens count] ) 708 { 709 // get new screen frame 710 pScreen = [pScreens objectAtIndex: nScreen]; 711 NSRect aNewScreen = [pScreen frame]; 712 713 // get current screen frame 714 pScreen = [mpWindow screen]; 715 if( pScreen ) 716 { 717 NSRect aCurScreen = [pScreen frame]; 718 if( aCurScreen.origin.x != aNewScreen.origin.x || 719 aCurScreen.origin.y != aNewScreen.origin.y ) 720 { 721 NSRect aFrameRect = [mpWindow frame]; 722 aFrameRect.origin.x += aNewScreen.origin.x - aCurScreen.origin.x; 723 aFrameRect.origin.y += aNewScreen.origin.y - aCurScreen.origin.y; 724 [mpWindow setFrame: aFrameRect display: NO]; 725 UpdateFrameGeometry(); 726 } 727 } 728 } 729 } 730 731 // ----------------------------------------------------------------------- 732 733 void AquaSalFrame::ShowFullScreen( sal_Bool bFullScreen, sal_Int32 nDisplay ) 734 { 735 if ( !mpWindow ) 736 return; 737 738 // #i113170# may not be the main thread if called from UNO API 739 SalData::ensureThreadAutoreleasePool(); 740 741 if( mbFullScreen == bFullScreen ) 742 return; 743 744 mbFullScreen = bFullScreen; 745 if( bFullScreen ) 746 { 747 // hide the dock and the menubar if we are on the menu screen 748 // which is always on index 0 according to documentation 749 bool bHideMenu = (nDisplay == 0); 750 751 NSRect aNewContentRect = { { 0, 0 }, { 0, 0 } }; 752 // get correct screen 753 NSScreen* pScreen = nil; 754 NSArray* pScreens = [NSScreen screens]; 755 if( pScreens ) 756 { 757 if( nDisplay >= 0 && (unsigned int)nDisplay < [pScreens count] ) 758 pScreen = [pScreens objectAtIndex: nDisplay]; 759 else 760 { 761 // this means span all screens 762 bHideMenu = true; 763 NSEnumerator* pEnum = [pScreens objectEnumerator]; 764 while( (pScreen = [pEnum nextObject]) != nil ) 765 { 766 NSRect aScreenRect = [pScreen frame]; 767 if( aScreenRect.origin.x < aNewContentRect.origin.x ) 768 { 769 aNewContentRect.size.width += aNewContentRect.origin.x - aScreenRect.origin.x; 770 aNewContentRect.origin.x = aScreenRect.origin.x; 771 } 772 if( aScreenRect.origin.y < aNewContentRect.origin.y ) 773 { 774 aNewContentRect.size.height += aNewContentRect.origin.y - aScreenRect.origin.y; 775 aNewContentRect.origin.y = aScreenRect.origin.y; 776 } 777 if( aScreenRect.origin.x + aScreenRect.size.width > aNewContentRect.origin.x + aNewContentRect.size.width ) 778 aNewContentRect.size.width = aScreenRect.origin.x + aScreenRect.size.width - aNewContentRect.origin.x; 779 if( aScreenRect.origin.y + aScreenRect.size.height > aNewContentRect.origin.y + aNewContentRect.size.height ) 780 aNewContentRect.size.height = aScreenRect.origin.y + aScreenRect.size.height - aNewContentRect.origin.y; 781 } 782 } 783 } 784 if( aNewContentRect.size.width == 0 && aNewContentRect.size.height == 0 ) 785 { 786 if( pScreen == nil ) 787 pScreen = [mpWindow screen]; 788 if( pScreen == nil ) 789 pScreen = [NSScreen mainScreen]; 790 791 aNewContentRect = [pScreen frame]; 792 } 793 794 if( bHideMenu ) 795 [NSMenu setMenuBarVisible:NO]; 796 797 maFullScreenRect = [mpWindow frame]; 798 { 799 [mpWindow setFrame: [NSWindow frameRectForContentRect: aNewContentRect styleMask: mnStyleMask] display: mbShown ? YES : NO]; 800 } 801 802 UpdateFrameGeometry(); 803 804 if( mbShown ) 805 CallCallback( SALEVENT_MOVERESIZE, NULL ); 806 } 807 else 808 { 809 { 810 [mpWindow setFrame: maFullScreenRect display: mbShown ? YES : NO]; 811 } 812 UpdateFrameGeometry(); 813 814 if( mbShown ) 815 CallCallback( SALEVENT_MOVERESIZE, NULL ); 816 817 // show the dock and the menubar 818 [NSMenu setMenuBarVisible:YES]; 819 } 820 if( mbShown ) 821 // trigger filling our backbuffer 822 SendPaintEvent(); 823 } 824 825 // ----------------------------------------------------------------------- 826 827 class PreventSleepTimer : public AutoTimer 828 { 829 public: 830 PreventSleepTimer() 831 { 832 SetTimeout( 30000 ); 833 Start(); 834 } 835 836 virtual ~PreventSleepTimer() 837 { 838 } 839 840 virtual void Timeout() 841 { 842 UpdateSystemActivity(OverallAct); 843 } 844 }; 845 846 void AquaSalFrame::StartPresentation( sal_Bool bStart ) 847 { 848 if ( !mpWindow ) 849 return; 850 851 // #i113170# may not be the main thread if called from UNO API 852 SalData::ensureThreadAutoreleasePool(); 853 854 if( bStart ) 855 { 856 mpActivityTimer.reset( new PreventSleepTimer() ); 857 [mpWindow setLevel: NSScreenSaverWindowLevel]; 858 if( mbShown ) 859 [mpWindow makeMainWindow]; 860 } 861 else 862 { 863 mpActivityTimer.reset(); 864 [mpWindow setLevel: NSNormalWindowLevel]; 865 } 866 } 867 868 // ----------------------------------------------------------------------- 869 870 void AquaSalFrame::SetAlwaysOnTop( sal_Bool ) 871 { 872 } 873 874 // ----------------------------------------------------------------------- 875 876 void AquaSalFrame::ToTop(sal_uInt16 nFlags) 877 { 878 if ( !mpWindow ) 879 return; 880 881 // #i113170# may not be the main thread if called from UNO API 882 SalData::ensureThreadAutoreleasePool(); 883 884 // #i113170# may not be the main thread if called from UNO API 885 SalData::ensureThreadAutoreleasePool(); 886 887 if( ! (nFlags & SAL_FRAME_TOTOP_RESTOREWHENMIN) ) 888 { 889 if( ! [mpWindow isVisible] || [mpWindow isMiniaturized] ) 890 return; 891 } 892 if( nFlags & SAL_FRAME_TOTOP_GRABFOCUS ) 893 [mpWindow makeKeyAndOrderFront: NSApp]; 894 else 895 [mpWindow orderFront: NSApp]; 896 } 897 898 // ----------------------------------------------------------------------- 899 900 NSCursor* AquaSalFrame::getCurrentCursor() const 901 { 902 NSCursor* pCursor = nil; 903 switch( mePointerStyle ) 904 { 905 case POINTER_TEXT: pCursor = [NSCursor IBeamCursor]; break; 906 case POINTER_CROSS: pCursor = [NSCursor crosshairCursor]; break; 907 case POINTER_HAND: 908 case POINTER_MOVE: pCursor = [NSCursor openHandCursor]; break; 909 case POINTER_NSIZE: pCursor = [NSCursor resizeUpCursor]; break; 910 case POINTER_SSIZE: pCursor = [NSCursor resizeDownCursor]; break; 911 case POINTER_ESIZE: pCursor = [NSCursor resizeRightCursor]; break; 912 case POINTER_WSIZE: pCursor = [NSCursor resizeLeftCursor]; break; 913 case POINTER_ARROW: pCursor = [NSCursor arrowCursor]; break; 914 case POINTER_VSPLIT: 915 case POINTER_VSIZEBAR: 916 case POINTER_WINDOW_NSIZE: 917 case POINTER_WINDOW_SSIZE: 918 pCursor = [NSCursor resizeUpDownCursor]; break; 919 case POINTER_HSPLIT: 920 case POINTER_HSIZEBAR: 921 case POINTER_WINDOW_ESIZE: 922 case POINTER_WINDOW_WSIZE: 923 pCursor = [NSCursor resizeLeftRightCursor]; break; 924 case POINTER_REFHAND: pCursor = [NSCursor pointingHandCursor]; break; 925 926 default: 927 pCursor = GetSalData()->getCursor( mePointerStyle ); 928 if( pCursor == nil ) 929 { 930 DBG_ERROR( "unmapped cursor" ); 931 pCursor = [NSCursor arrowCursor]; 932 } 933 break; 934 } 935 return pCursor; 936 } 937 938 void AquaSalFrame::SetPointer( PointerStyle ePointerStyle ) 939 { 940 if ( !mpWindow ) 941 return; 942 943 // #i113170# may not be the main thread if called from UNO API 944 SalData::ensureThreadAutoreleasePool(); 945 946 if( ePointerStyle >= POINTER_COUNT || ePointerStyle == mePointerStyle ) 947 return; 948 mePointerStyle = ePointerStyle; 949 950 [mpWindow invalidateCursorRectsForView: mpView]; 951 } 952 953 // ----------------------------------------------------------------------- 954 955 void AquaSalFrame::SetPointerPos( long nX, long nY ) 956 { 957 // FIXME: use Cocoa functions 958 959 // FIXME: multiscreen support 960 CGPoint aPoint = { nX + maGeometry.nX, nY + maGeometry.nY }; 961 CGDirectDisplayID mainDisplayID = CGMainDisplayID(); 962 CGDisplayMoveCursorToPoint( mainDisplayID, aPoint ); 963 } 964 965 // ----------------------------------------------------------------------- 966 967 void AquaSalFrame::Flush( void ) 968 { 969 if( !(mbGraphics && mpGraphics && mpView && mbShown) ) 970 return; 971 972 // #i113170# may not be the main thread if called from UNO API 973 SalData::ensureThreadAutoreleasePool(); 974 975 976 [mpView setNeedsDisplay: YES]; 977 978 // outside of the application's event loop (e.g. IntroWindow) 979 // nothing would trigger paint event handling 980 // => fall back to synchronous painting 981 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) 982 { 983 [mpView display]; 984 } 985 } 986 987 // ----------------------------------------------------------------------- 988 989 void AquaSalFrame::Flush( const Rectangle& rRect ) 990 { 991 if( !(mbGraphics && mpGraphics && mpView && mbShown) ) 992 return; 993 994 // #i113170# may not be the main thread if called from UNO API 995 SalData::ensureThreadAutoreleasePool(); 996 997 NSRect aNSRect = { {rRect.Left(), rRect.Top()}, { rRect.GetWidth(), rRect.GetHeight() } }; 998 VCLToCocoa( aNSRect, false ); 999 [mpView setNeedsDisplayInRect: aNSRect]; 1000 1001 // outside of the application's event loop (e.g. IntroWindow) 1002 // nothing would trigger paint event handling 1003 // => fall back to synchronous painting 1004 if( ImplGetSVData()->maAppData.mnDispatchLevel <= 0 ) 1005 { 1006 [mpView display]; 1007 } 1008 } 1009 1010 // ----------------------------------------------------------------------- 1011 1012 void AquaSalFrame::Sync() 1013 { 1014 if( mbGraphics && mpGraphics && mpView && mbShown ) 1015 { 1016 // #i113170# may not be the main thread if called from UNO API 1017 SalData::ensureThreadAutoreleasePool(); 1018 1019 [mpView setNeedsDisplay: YES]; 1020 [mpView display]; 1021 } 1022 } 1023 1024 // ----------------------------------------------------------------------- 1025 1026 void AquaSalFrame::SetInputContext( SalInputContext* pContext ) 1027 { 1028 if (!pContext) 1029 { 1030 mnICOptions = 0; 1031 return; 1032 } 1033 1034 mnICOptions = pContext->mnOptions; 1035 1036 if(!(pContext->mnOptions & SAL_INPUTCONTEXT_TEXT)) 1037 return; 1038 } 1039 1040 // ----------------------------------------------------------------------- 1041 1042 void AquaSalFrame::EndExtTextInput( sal_uInt16 ) 1043 { 1044 } 1045 1046 // ----------------------------------------------------------------------- 1047 1048 XubString AquaSalFrame::GetKeyName( sal_uInt16 nKeyCode ) 1049 { 1050 static std::map< sal_uInt16, rtl::OUString > aKeyMap; 1051 if( aKeyMap.empty() ) 1052 { 1053 sal_uInt16 i; 1054 for( i = KEY_A; i <= KEY_Z; i++ ) 1055 aKeyMap[ i ] = rtl::OUString( sal_Unicode( 'A' + (i - KEY_A) ) ); 1056 for( i = KEY_0; i <= KEY_9; i++ ) 1057 aKeyMap[ i ] = rtl::OUString( sal_Unicode( '0' + (i - KEY_0) ) ); 1058 for( i = KEY_F1; i <= KEY_F26; i++ ) 1059 { 1060 rtl::OUStringBuffer aKey( 3 ); 1061 aKey.append( sal_Unicode( 'F' ) ); 1062 aKey.append( sal_Int32( i - KEY_F1 + 1 ) ); 1063 aKeyMap[ i ] = aKey.makeStringAndClear(); 1064 } 1065 1066 aKeyMap[ KEY_DOWN ] = rtl::OUString( sal_Unicode( 0x21e3 ) ); 1067 aKeyMap[ KEY_UP ] = rtl::OUString( sal_Unicode( 0x21e1 ) ); 1068 aKeyMap[ KEY_LEFT ] = rtl::OUString( sal_Unicode( 0x21e0 ) ); 1069 aKeyMap[ KEY_RIGHT ] = rtl::OUString( sal_Unicode( 0x21e2 ) ); 1070 aKeyMap[ KEY_HOME ] = rtl::OUString( sal_Unicode( 0x2196 ) ); 1071 aKeyMap[ KEY_END ] = rtl::OUString( sal_Unicode( 0x2198 ) ); 1072 aKeyMap[ KEY_PAGEUP ] = rtl::OUString( sal_Unicode( 0x21de ) ); 1073 aKeyMap[ KEY_PAGEDOWN ] = rtl::OUString( sal_Unicode( 0x21df ) ); 1074 aKeyMap[ KEY_RETURN ] = rtl::OUString( sal_Unicode( 0x21a9 ) ); 1075 aKeyMap[ KEY_ESCAPE ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "esc" ) ); 1076 aKeyMap[ KEY_TAB ] = rtl::OUString( sal_Unicode( 0x21e5 ) ); 1077 aKeyMap[ KEY_BACKSPACE ]= rtl::OUString( sal_Unicode( 0x232b ) ); 1078 aKeyMap[ KEY_SPACE ] = rtl::OUString( sal_Unicode( 0x2423 ) ); 1079 aKeyMap[ KEY_DELETE ] = rtl::OUString( sal_Unicode( 0x2326 ) ); 1080 aKeyMap[ KEY_ADD ] = rtl::OUString( sal_Unicode( '+' ) ); 1081 aKeyMap[ KEY_SUBTRACT ] = rtl::OUString( sal_Unicode( '-' ) ); 1082 aKeyMap[ KEY_DIVIDE ] = rtl::OUString( sal_Unicode( '/' ) ); 1083 aKeyMap[ KEY_MULTIPLY ] = rtl::OUString( sal_Unicode( '*' ) ); 1084 aKeyMap[ KEY_POINT ] = rtl::OUString( sal_Unicode( '.' ) ); 1085 aKeyMap[ KEY_COMMA ] = rtl::OUString( sal_Unicode( ',' ) ); 1086 aKeyMap[ KEY_LESS ] = rtl::OUString( sal_Unicode( '<' ) ); 1087 aKeyMap[ KEY_GREATER ] = rtl::OUString( sal_Unicode( '>' ) ); 1088 aKeyMap[ KEY_EQUAL ] = rtl::OUString( sal_Unicode( '=' ) ); 1089 aKeyMap[ KEY_OPEN ] = rtl::OUString( sal_Unicode( 0x23cf ) ); 1090 1091 /* yet unmapped KEYCODES: 1092 aKeyMap[ KEY_INSERT ] = rtl::OUString( sal_Unicode( ) ); 1093 aKeyMap[ KEY_CUT ] = rtl::OUString( sal_Unicode( ) ); 1094 aKeyMap[ KEY_COPY ] = rtl::OUString( sal_Unicode( ) ); 1095 aKeyMap[ KEY_PASTE ] = rtl::OUString( sal_Unicode( ) ); 1096 aKeyMap[ KEY_UNDO ] = rtl::OUString( sal_Unicode( ) ); 1097 aKeyMap[ KEY_REPEAT ] = rtl::OUString( sal_Unicode( ) ); 1098 aKeyMap[ KEY_FIND ] = rtl::OUString( sal_Unicode( ) ); 1099 aKeyMap[ KEY_PROPERTIES ] = rtl::OUString( sal_Unicode( ) ); 1100 aKeyMap[ KEY_FRONT ] = rtl::OUString( sal_Unicode( ) ); 1101 aKeyMap[ KEY_CONTEXTMENU ] = rtl::OUString( sal_Unicode( ) ); 1102 aKeyMap[ KEY_MENU ] = rtl::OUString( sal_Unicode( ) ); 1103 aKeyMap[ KEY_HELP ] = rtl::OUString( sal_Unicode( ) ); 1104 aKeyMap[ KEY_HANGUL_HANJA ] = rtl::OUString( sal_Unicode( ) ); 1105 aKeyMap[ KEY_DECIMAL ] = rtl::OUString( sal_Unicode( ) ); 1106 aKeyMap[ KEY_TILDE ] = rtl::OUString( sal_Unicode( ) ); 1107 aKeyMap[ KEY_QUOTELEFT ]= rtl::OUString( sal_Unicode( ) ); 1108 */ 1109 1110 } 1111 1112 rtl::OUStringBuffer aResult( 16 ); 1113 1114 sal_uInt16 nUnmodifiedCode = (nKeyCode & KEY_CODE); 1115 std::map< sal_uInt16, rtl::OUString >::const_iterator it = aKeyMap.find( nUnmodifiedCode ); 1116 if( it != aKeyMap.end() ) 1117 { 1118 if( (nKeyCode & KEY_SHIFT) != 0 ) 1119 aResult.append( sal_Unicode( 0x21e7 ) ); 1120 if( (nKeyCode & KEY_MOD1) != 0 ) 1121 aResult.append( sal_Unicode( 0x2318 ) ); 1122 // we do not really handle Alt (see below) 1123 // we map it to MOD3, whichis actually Command 1124 if( (nKeyCode & (KEY_MOD2|KEY_MOD3)) != 0 ) 1125 aResult.append( sal_Unicode( 0x2303 ) ); 1126 1127 aResult.append( it->second ); 1128 } 1129 1130 return aResult.makeStringAndClear(); 1131 } 1132 1133 // ----------------------------------------------------------------------- 1134 1135 XubString AquaSalFrame::GetSymbolKeyName( const XubString&, sal_uInt16 nKeyCode ) 1136 { 1137 return GetKeyName( nKeyCode ); 1138 } 1139 1140 // ----------------------------------------------------------------------- 1141 1142 static void getAppleScrollBarVariant(void) 1143 { 1144 bool bIsScrollbarDoubleMax = true; // default is DoubleMax 1145 1146 CFStringRef AppleScrollBarType = CFSTR("AppleScrollBarVariant"); 1147 if( AppleScrollBarType ) 1148 { 1149 CFStringRef ScrollBarVariant = ((CFStringRef)CFPreferencesCopyAppValue( AppleScrollBarType, kCFPreferencesCurrentApplication )); 1150 if( ScrollBarVariant ) 1151 { 1152 if( CFGetTypeID( ScrollBarVariant ) == CFStringGetTypeID() ) 1153 { 1154 // TODO: check for the less important variants "DoubleMin" and "DoubleBoth" too 1155 CFStringRef DoubleMax = CFSTR("DoubleMax"); 1156 if (DoubleMax) 1157 { 1158 if ( !CFStringCompare(ScrollBarVariant, DoubleMax, kCFCompareCaseInsensitive) ) 1159 bIsScrollbarDoubleMax = true; 1160 else 1161 bIsScrollbarDoubleMax = false; 1162 CFRelease(DoubleMax); 1163 } 1164 } 1165 CFRelease( ScrollBarVariant ); 1166 } 1167 CFRelease(AppleScrollBarType); 1168 } 1169 1170 GetSalData()->mbIsScrollbarDoubleMax = bIsScrollbarDoubleMax; 1171 1172 CFStringRef jumpScroll = CFSTR("AppleScrollerPagingBehavior"); 1173 if( jumpScroll ) 1174 { 1175 CFBooleanRef jumpStr = ((CFBooleanRef)CFPreferencesCopyAppValue( jumpScroll, kCFPreferencesCurrentApplication )); 1176 if( jumpStr ) 1177 { 1178 if( CFGetTypeID( jumpStr ) == CFBooleanGetTypeID() ) 1179 ImplGetSVData()->maNWFData.mbScrollbarJumpPage = (jumpStr == kCFBooleanTrue); 1180 CFRelease( jumpStr ); 1181 } 1182 CFRelease( jumpScroll ); 1183 } 1184 } 1185 1186 static Color getColor( NSColor* pSysColor, const Color& rDefault, NSWindow* pWin ) 1187 { 1188 Color aRet( rDefault ); 1189 if( pSysColor ) 1190 { 1191 // transform to RGB 1192 NSColor* pRBGColor = [pSysColor colorUsingColorSpaceName: NSDeviceRGBColorSpace device: [pWin deviceDescription]]; 1193 if( pRBGColor ) 1194 { 1195 float r = 0, g = 0, b = 0, a = 0; 1196 [pRBGColor getRed: &r green: &g blue: &b alpha: &a]; 1197 aRet = Color( int(r*255.999), int(g*255.999), int(b*255.999) ); 1198 /* 1199 do not release here; leads to duplicate free in yield 1200 it seems the converted color comes out autoreleased, although this 1201 is not documented 1202 [pRBGColor release]; 1203 */ 1204 } 1205 } 1206 return aRet; 1207 } 1208 1209 static Font getFont( NSFont* pFont, long nDPIY, const Font& rDefault ) 1210 { 1211 Font aResult( rDefault ); 1212 if( pFont ) 1213 { 1214 aResult.SetName( GetOUString( [pFont familyName] ) ); 1215 aResult.SetHeight( static_cast<int>(([pFont pointSize] * 72.0 / (float)nDPIY)+0.5) ); 1216 aResult.SetItalic( ([pFont italicAngle] != 0.0) ? ITALIC_NORMAL : ITALIC_NONE ); 1217 // FIMXE: bold ? 1218 } 1219 1220 return aResult; 1221 } 1222 1223 void AquaSalFrame::getResolution( long& o_rDPIX, long& o_rDPIY ) 1224 { 1225 if( ! mpGraphics ) 1226 { 1227 GetGraphics(); 1228 ReleaseGraphics( mpGraphics ); 1229 } 1230 mpGraphics->GetResolution( o_rDPIX, o_rDPIY ); 1231 } 1232 1233 // on OSX-Aqua the style settings are independent of the frame, so it does 1234 // not really belong here. Since the connection to the Appearance_Manager 1235 // is currently done in salnativewidgets.cxx this would be a good place. 1236 // On the other hand VCL's platform independent code currently only asks 1237 // SalFrames for system settings anyway, so moving the code somewhere else 1238 // doesn't make the anything cleaner for now 1239 void AquaSalFrame::UpdateSettings( AllSettings& rSettings ) 1240 { 1241 if ( !mpWindow ) 1242 return; 1243 1244 // #i113170# may not be the main thread if called from UNO API 1245 SalData::ensureThreadAutoreleasePool(); 1246 1247 [mpView lockFocus]; 1248 1249 StyleSettings aStyleSettings = rSettings.GetStyleSettings(); 1250 1251 // Background Color 1252 Color aBackgroundColor = Color( 0xEC, 0xEC, 0xEC ); 1253 aStyleSettings.Set3DColors( aBackgroundColor ); 1254 aStyleSettings.SetFaceColor( aBackgroundColor ); 1255 Color aInactiveTabColor( aBackgroundColor ); 1256 aInactiveTabColor.DecreaseLuminance( 32 ); 1257 aStyleSettings.SetInactiveTabColor( aInactiveTabColor ); 1258 1259 aStyleSettings.SetDialogColor( aBackgroundColor ); 1260 aStyleSettings.SetLightBorderColor( aBackgroundColor ); 1261 Color aShadowColor( aStyleSettings.GetShadowColor() ); 1262 aStyleSettings.SetDarkShadowColor( aShadowColor ); 1263 aShadowColor.IncreaseLuminance( 32 ); 1264 aStyleSettings.SetShadowColor( aShadowColor ); 1265 1266 // get the system font settings 1267 Font aAppFont = aStyleSettings.GetAppFont(); 1268 long nDPIX = 72, nDPIY = 72; 1269 getResolution( nDPIX, nDPIY ); 1270 aAppFont = getFont( [NSFont systemFontOfSize: 0], nDPIY, aAppFont ); 1271 1272 // TODO: better mapping of aqua<->ooo font settings 1273 aStyleSettings.SetAppFont( aAppFont ); 1274 aStyleSettings.SetHelpFont( aAppFont ); 1275 aStyleSettings.SetPushButtonFont( aAppFont ); 1276 1277 Font aTitleFont( getFont( [NSFont titleBarFontOfSize: 0], nDPIY, aAppFont ) ); 1278 aStyleSettings.SetTitleFont( aTitleFont ); 1279 aStyleSettings.SetFloatTitleFont( aTitleFont ); 1280 1281 Font aMenuFont( getFont( [NSFont menuFontOfSize: 0], nDPIY, aAppFont ) ); 1282 aStyleSettings.SetMenuFont( aMenuFont ); 1283 1284 aStyleSettings.SetToolFont( aAppFont ); 1285 1286 Font aLabelFont( getFont( [NSFont labelFontOfSize: 0], nDPIY, aAppFont ) ); 1287 aStyleSettings.SetLabelFont( aLabelFont ); 1288 aStyleSettings.SetInfoFont( aLabelFont ); 1289 aStyleSettings.SetRadioCheckFont( aLabelFont ); 1290 aStyleSettings.SetFieldFont( aLabelFont ); 1291 aStyleSettings.SetGroupFont( aLabelFont ); 1292 aStyleSettings.SetIconFont( aLabelFont ); 1293 1294 Color aHighlightColor( getColor( [NSColor selectedTextBackgroundColor], 1295 aStyleSettings.GetHighlightColor(), mpWindow ) ); 1296 aStyleSettings.SetHighlightColor( aHighlightColor ); 1297 Color aHighlightTextColor( getColor( [NSColor selectedTextColor], 1298 aStyleSettings.GetHighlightTextColor(), mpWindow ) ); 1299 aStyleSettings.SetHighlightTextColor( aHighlightTextColor ); 1300 1301 Color aMenuHighlightColor( getColor( [NSColor selectedMenuItemColor], 1302 aStyleSettings.GetMenuHighlightColor(), mpWindow ) ); 1303 aStyleSettings.SetMenuHighlightColor( aMenuHighlightColor ); 1304 Color aMenuHighlightTextColor( getColor( [NSColor selectedMenuItemTextColor], 1305 aStyleSettings.GetMenuHighlightTextColor(), mpWindow ) ); 1306 aStyleSettings.SetMenuHighlightTextColor( aMenuHighlightTextColor ); 1307 1308 aStyleSettings.SetMenuColor( aBackgroundColor ); 1309 Color aMenuTextColor( getColor( [NSColor textColor], 1310 aStyleSettings.GetMenuTextColor(), mpWindow ) ); 1311 aStyleSettings.SetMenuTextColor( aMenuTextColor ); 1312 aStyleSettings.SetMenuBarTextColor( aMenuTextColor ); 1313 1314 aStyleSettings.SetCursorBlinkTime( 500 ); 1315 1316 // no mnemonics on aqua 1317 aStyleSettings.SetOptions( aStyleSettings.GetOptions() | STYLE_OPTION_NOMNEMONICS ); 1318 1319 getAppleScrollBarVariant(); 1320 1321 // set scrollbar size 1322 aStyleSettings.SetScrollBarSize( static_cast<long int>([NSScroller scrollerWidth]) ); 1323 1324 // images in menus false for MacOSX 1325 aStyleSettings.SetUseImagesInMenus( false ); 1326 1327 rSettings.SetStyleSettings( aStyleSettings ); 1328 1329 [mpView unlockFocus]; 1330 } 1331 1332 // ----------------------------------------------------------------------- 1333 1334 const SystemEnvData* AquaSalFrame::GetSystemData() const 1335 { 1336 return &maSysData; 1337 } 1338 1339 // ----------------------------------------------------------------------- 1340 1341 void AquaSalFrame::Beep( SoundType eSoundType ) 1342 { 1343 switch( eSoundType ) 1344 { 1345 case SOUND_DISABLE: 1346 // don't beep 1347 break; 1348 default: 1349 NSBeep(); 1350 break; 1351 } 1352 } 1353 1354 // ----------------------------------------------------------------------- 1355 1356 void AquaSalFrame::SetPosSize(long nX, long nY, long nWidth, long nHeight, sal_uInt16 nFlags) 1357 { 1358 if ( !mpWindow ) 1359 return; 1360 1361 // #i113170# may not be the main thread if called from UNO API 1362 SalData::ensureThreadAutoreleasePool(); 1363 1364 sal_uInt16 nEvent = 0; 1365 1366 if( [mpWindow isMiniaturized] ) 1367 [mpWindow deminiaturize: NSApp]; // expand the window 1368 1369 if (nFlags & (SAL_FRAME_POSSIZE_X | SAL_FRAME_POSSIZE_Y)) 1370 { 1371 mbPositioned = true; 1372 nEvent = SALEVENT_MOVE; 1373 } 1374 1375 if (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) 1376 { 1377 mbSized = true; 1378 nEvent = (nEvent == SALEVENT_MOVE) ? SALEVENT_MOVERESIZE : SALEVENT_RESIZE; 1379 } 1380 1381 NSRect aFrameRect = [mpWindow frame]; 1382 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask]; 1383 1384 // position is always relative to parent frame 1385 NSRect aParentContentRect; 1386 1387 if( mpParent ) 1388 { 1389 if( Application::GetSettings().GetLayoutRTL() ) 1390 { 1391 if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 ) 1392 nX = mpParent->maGeometry.nWidth - nWidth-1 - nX; 1393 else 1394 nX = mpParent->maGeometry.nWidth - static_cast<long int>( aContentRect.size.width-1) - nX; 1395 } 1396 NSRect aParentFrameRect = [mpParent->mpWindow frame]; 1397 aParentContentRect = [NSWindow contentRectForFrameRect: aParentFrameRect styleMask: mpParent->mnStyleMask]; 1398 } 1399 else 1400 aParentContentRect = maScreenRect; // use screen if no parent 1401 1402 CocoaToVCL( aContentRect ); 1403 CocoaToVCL( aParentContentRect ); 1404 1405 bool bPaint = false; 1406 if( (nFlags & (SAL_FRAME_POSSIZE_WIDTH | SAL_FRAME_POSSIZE_HEIGHT)) != 0 ) 1407 { 1408 if( nWidth != aContentRect.size.width || nHeight != aContentRect.size.height ) 1409 bPaint = true; 1410 } 1411 1412 // use old window pos if no new pos requested 1413 if( (nFlags & SAL_FRAME_POSSIZE_X) != 0 ) 1414 aContentRect.origin.x = nX + aParentContentRect.origin.x; 1415 if( (nFlags & SAL_FRAME_POSSIZE_Y) != 0) 1416 aContentRect.origin.y = nY + aParentContentRect.origin.y; 1417 1418 // use old size if no new size requested 1419 if( (nFlags & SAL_FRAME_POSSIZE_WIDTH) != 0 ) 1420 aContentRect.size.width = nWidth; 1421 if( (nFlags & SAL_FRAME_POSSIZE_HEIGHT) != 0) 1422 aContentRect.size.height = nHeight; 1423 1424 VCLToCocoa( aContentRect ); 1425 1426 // do not display yet, we need to update our backbuffer 1427 { 1428 [mpWindow setFrame: [NSWindow frameRectForContentRect: aContentRect styleMask: mnStyleMask] display: NO]; 1429 } 1430 1431 UpdateFrameGeometry(); 1432 1433 if (nEvent) 1434 CallCallback(nEvent, NULL); 1435 1436 if( mbShown && bPaint ) 1437 { 1438 // trigger filling our backbuffer 1439 SendPaintEvent(); 1440 1441 // now inform the system that the views need to be drawn 1442 [mpWindow display]; 1443 } 1444 } 1445 1446 void AquaSalFrame::GetWorkArea( Rectangle& rRect ) 1447 { 1448 if ( !mpWindow ) 1449 return; 1450 1451 // #i113170# may not be the main thread if called from UNO API 1452 SalData::ensureThreadAutoreleasePool(); 1453 1454 NSScreen* pScreen = [mpWindow screen]; 1455 if( pScreen == nil ) 1456 pScreen = [NSScreen mainScreen]; 1457 NSRect aRect = [pScreen visibleFrame]; 1458 CocoaToVCL( aRect ); 1459 rRect.nLeft = static_cast<long>(aRect.origin.x); 1460 rRect.nTop = static_cast<long>(aRect.origin.y); 1461 rRect.nRight = static_cast<long>(aRect.origin.x + aRect.size.width - 1); 1462 rRect.nBottom = static_cast<long>(aRect.origin.y + aRect.size.height - 1); 1463 } 1464 1465 SalPointerState AquaSalFrame::GetPointerState() 1466 { 1467 // #i113170# may not be the main thread if called from UNO API 1468 SalData::ensureThreadAutoreleasePool(); 1469 1470 SalPointerState state; 1471 state.mnState = 0; 1472 1473 // get position 1474 NSPoint aPt = [mpWindow mouseLocationOutsideOfEventStream]; 1475 CocoaToVCL( aPt, false ); 1476 state.maPos = Point(static_cast<long>(aPt.x), static_cast<long>(aPt.y)); 1477 1478 NSEvent* pCur = [NSApp currentEvent]; 1479 bool bMouseEvent = false; 1480 if( pCur ) 1481 { 1482 bMouseEvent = true; 1483 switch( [pCur type] ) 1484 { 1485 case NSLeftMouseDown: state.mnState |= MOUSE_LEFT; break; 1486 case NSLeftMouseUp: break; 1487 case NSRightMouseDown: state.mnState |= MOUSE_RIGHT; break; 1488 case NSRightMouseUp: break; 1489 case NSOtherMouseDown: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break; 1490 case NSOtherMouseUp: break; 1491 case NSMouseMoved: break; 1492 case NSLeftMouseDragged: state.mnState |= MOUSE_LEFT; break; 1493 case NSRightMouseDragged: state.mnState |= MOUSE_RIGHT; break; 1494 case NSOtherMouseDragged: state.mnState |= ([pCur buttonNumber] == 2) ? MOUSE_MIDDLE : 0; break; 1495 break; 1496 default: 1497 bMouseEvent = false; 1498 break; 1499 } 1500 } 1501 if( bMouseEvent ) 1502 { 1503 unsigned int nMask = (unsigned int)[pCur modifierFlags]; 1504 if( (nMask & NSShiftKeyMask) != 0 ) 1505 state.mnState |= KEY_SHIFT; 1506 if( (nMask & NSControlKeyMask) != 0 ) 1507 state.mnState |= KEY_MOD3; 1508 if( (nMask & NSAlternateKeyMask) != 0 ) 1509 state.mnState |= KEY_MOD2; 1510 if( (nMask & NSCommandKeyMask) != 0 ) 1511 state.mnState |= KEY_MOD1; 1512 1513 } 1514 else 1515 { 1516 // FIXME: replace Carbon by Cocoa 1517 // Cocoa does not have an equivalent for GetCurrentEventButtonState 1518 // and GetCurrentEventKeyModifiers. 1519 // we could try to get away with tracking all events for modifierKeys 1520 // and all mouse events for button state in VCL_NSApllication::sendEvent, 1521 // but it is unclear whether this will get us the same result. 1522 // leave in GetCurrentEventButtonState and GetCurrentEventKeyModifiers for now 1523 1524 // fill in button state 1525 UInt32 nState = GetCurrentEventButtonState(); 1526 state.mnState = 0; 1527 if( nState & 1 ) 1528 state.mnState |= MOUSE_LEFT; // primary button 1529 if( nState & 2 ) 1530 state.mnState |= MOUSE_RIGHT; // secondary button 1531 if( nState & 4 ) 1532 state.mnState |= MOUSE_MIDDLE; // tertiary button 1533 1534 // fill in modifier state 1535 nState = GetCurrentEventKeyModifiers(); 1536 if( nState & shiftKey ) 1537 state.mnState |= KEY_SHIFT; 1538 if( nState & controlKey ) 1539 state.mnState |= KEY_MOD3; 1540 if( nState & optionKey ) 1541 state.mnState |= KEY_MOD2; 1542 if( nState & cmdKey ) 1543 state.mnState |= KEY_MOD1; 1544 } 1545 1546 1547 return state; 1548 } 1549 1550 bool AquaSalFrame::SetPluginParent( SystemParentData* ) 1551 { 1552 // plugin parent may be killed unexpectedly by 1553 // plugging process; 1554 1555 //TODO: implement 1556 return sal_False; 1557 } 1558 1559 sal_Bool AquaSalFrame::MapUnicodeToKeyCode( sal_Unicode , LanguageType , KeyCode& ) 1560 { 1561 // not supported yet 1562 return FALSE; 1563 } 1564 1565 LanguageType AquaSalFrame::GetInputLanguage() 1566 { 1567 //TODO: implement 1568 return LANGUAGE_DONTKNOW; 1569 } 1570 1571 void AquaSalFrame::DrawMenuBar() 1572 { 1573 } 1574 1575 void AquaSalFrame::SetMenu( SalMenu* pSalMenu ) 1576 { 1577 // #i113170# may not be the main thread if called from UNO API 1578 SalData::ensureThreadAutoreleasePool(); 1579 1580 AquaSalMenu* pMenu = static_cast<AquaSalMenu*>(pSalMenu); 1581 DBG_ASSERT( ! pMenu || pMenu->mbMenuBar, "setting non menubar on frame" ); 1582 mpMenu = pMenu; 1583 if( mpMenu ) 1584 mpMenu->setMainMenu(); 1585 } 1586 1587 void AquaSalFrame::SetExtendedFrameStyle( SalExtStyle nStyle ) 1588 { 1589 if ( mpWindow ) 1590 { 1591 // #i113170# may not be the main thread if called from UNO API 1592 SalData::ensureThreadAutoreleasePool(); 1593 1594 if( (mnExtStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) != (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ) 1595 [mpWindow setDocumentEdited: (nStyle & SAL_FRAME_EXT_STYLE_DOCMODIFIED) ? YES : NO]; 1596 } 1597 1598 mnExtStyle = nStyle; 1599 } 1600 1601 void AquaSalFrame::SetBackgroundBitmap( SalBitmap* ) 1602 { 1603 //TODO: implement 1604 } 1605 1606 SalBitmap* AquaSalFrame::SnapShot() 1607 { 1608 return mpGraphics ? mpGraphics->getBitmap( 0, 0, maGeometry.nWidth, maGeometry.nHeight ) : NULL; 1609 } 1610 1611 SalFrame* AquaSalFrame::GetParent() const 1612 { 1613 return mpParent; 1614 } 1615 1616 void AquaSalFrame::SetParent( SalFrame* pNewParent ) 1617 { 1618 bool bShown = mbShown; 1619 // remove from child list 1620 Show( FALSE ); 1621 mpParent = (AquaSalFrame*)pNewParent; 1622 // insert to correct parent and paint 1623 Show( bShown ); 1624 } 1625 1626 void AquaSalFrame::UpdateFrameGeometry() 1627 { 1628 if ( !mpWindow ) 1629 { 1630 return; 1631 } 1632 1633 // keep in mind that view and window coordinates are lower left 1634 // whereas vcl's are upper left 1635 1636 // update screen rect 1637 NSScreen * pScreen = [mpWindow screen]; 1638 if( pScreen ) 1639 { 1640 maScreenRect = [pScreen frame]; 1641 NSArray* pScreens = [NSScreen screens]; 1642 if( pScreens ) 1643 maGeometry.nScreenNumber = [pScreens indexOfObject: pScreen]; 1644 } 1645 1646 NSRect aFrameRect = [mpWindow frame]; 1647 NSRect aContentRect = [NSWindow contentRectForFrameRect: aFrameRect styleMask: mnStyleMask]; 1648 1649 // release old track rect 1650 [mpView removeTrackingRect: mnTrackingRectTag]; 1651 // install the new track rect 1652 NSRect aTrackRect = { { 0, 0 }, aContentRect.size }; 1653 mnTrackingRectTag = [mpView addTrackingRect: aTrackRect owner: mpView userData: nil assumeInside: NO]; 1654 1655 // convert to vcl convention 1656 CocoaToVCL( aFrameRect ); 1657 CocoaToVCL( aContentRect ); 1658 1659 maGeometry.nX = static_cast<int>(aContentRect.origin.x); 1660 maGeometry.nY = static_cast<int>(aContentRect.origin.y); 1661 1662 maGeometry.nLeftDecoration = static_cast<unsigned int>(aContentRect.origin.x - aFrameRect.origin.x); 1663 maGeometry.nRightDecoration = static_cast<unsigned int>((aFrameRect.origin.x + aFrameRect.size.width) - 1664 (aContentRect.origin.x + aContentRect.size.width)); 1665 1666 maGeometry.nTopDecoration = static_cast<unsigned int>(aContentRect.origin.y - aFrameRect.origin.y); 1667 maGeometry.nBottomDecoration = static_cast<unsigned int>((aFrameRect.origin.y + aFrameRect.size.height) - 1668 (aContentRect.origin.y + aContentRect.size.height)); 1669 1670 maGeometry.nWidth = static_cast<unsigned int>(aContentRect.size.width); 1671 maGeometry.nHeight = static_cast<unsigned int>(aContentRect.size.height); 1672 } 1673 1674 // ----------------------------------------------------------------------- 1675 1676 void AquaSalFrame::CaptureMouse( sal_Bool bCapture ) 1677 { 1678 /* Remark: 1679 we'll try to use a pidgin version of capture mouse 1680 on MacOSX (neither carbon nor cocoa) there is a 1681 CaptureMouse equivalent (in Carbon there is TrackMouseLocation 1682 but this is useless to use since it is blocking) 1683 1684 However on cocoa the active frame seems to get mouse events 1685 also outside the window, so we'll try to forward mouse events 1686 to the capture frame in the hope that one of our frames 1687 gets a mouse event. 1688 1689 This will break as soon as the user activates another app, but 1690 a mouse click will normally lead to a release of the mouse anyway. 1691 1692 Let's see how far we get this way. Alternatively we could use one 1693 large overlay window like we did for the carbon implementation, 1694 however that is resource intensive. 1695 */ 1696 1697 if( bCapture ) 1698 s_pCaptureFrame = this; 1699 else if( ! bCapture && s_pCaptureFrame == this ) 1700 s_pCaptureFrame = NULL; 1701 } 1702 1703 void AquaSalFrame::ResetClipRegion() 1704 { 1705 if ( !mpWindow ) 1706 { 1707 return; 1708 } 1709 1710 // #i113170# may not be the main thread if called from UNO API 1711 SalData::ensureThreadAutoreleasePool(); 1712 1713 // release old path and indicate no clipping 1714 CGPathRelease( mrClippingPath ); 1715 mrClippingPath = NULL; 1716 1717 if( mpView && mbShown ) 1718 [mpView setNeedsDisplay: YES]; 1719 if( mpWindow ) 1720 { 1721 [mpWindow setOpaque: YES]; 1722 [mpWindow invalidateShadow]; 1723 } 1724 } 1725 1726 void AquaSalFrame::BeginSetClipRegion( sal_uLong nRects ) 1727 { 1728 if ( !mpWindow ) 1729 { 1730 return; 1731 } 1732 1733 // #i113170# may not be the main thread if called from UNO API 1734 SalData::ensureThreadAutoreleasePool(); 1735 1736 // release old path 1737 if( mrClippingPath ) 1738 { 1739 CGPathRelease( mrClippingPath ); 1740 mrClippingPath = NULL; 1741 } 1742 1743 if( maClippingRects.size() > SAL_CLIPRECT_COUNT && nRects < maClippingRects.size() ) 1744 { 1745 std::vector<CGRect> aEmptyVec; 1746 maClippingRects.swap( aEmptyVec ); 1747 } 1748 maClippingRects.clear(); 1749 maClippingRects.reserve( nRects ); 1750 } 1751 1752 void AquaSalFrame::UnionClipRegion( long nX, long nY, long nWidth, long nHeight ) 1753 { 1754 // #i113170# may not be the main thread if called from UNO API 1755 SalData::ensureThreadAutoreleasePool(); 1756 1757 if( nWidth && nHeight ) 1758 { 1759 NSRect aRect = { { nX, nY }, { nWidth, nHeight } }; 1760 VCLToCocoa( aRect, false ); 1761 maClippingRects.push_back( CGRectMake(aRect.origin.x, aRect.origin.y, aRect.size.width, aRect.size.height) ); 1762 } 1763 } 1764 1765 void AquaSalFrame::EndSetClipRegion() 1766 { 1767 if ( !mpWindow ) 1768 { 1769 return; 1770 } 1771 1772 // #i113170# may not be the main thread if called from UNO API 1773 SalData::ensureThreadAutoreleasePool(); 1774 1775 if( ! maClippingRects.empty() ) 1776 { 1777 mrClippingPath = CGPathCreateMutable(); 1778 CGPathAddRects( mrClippingPath, NULL, &maClippingRects[0], maClippingRects.size() ); 1779 } 1780 if( mpView && mbShown ) 1781 [mpView setNeedsDisplay: YES]; 1782 if( mpWindow ) 1783 { 1784 [mpWindow setOpaque: (mrClippingPath != NULL) ? NO : YES]; 1785 [mpWindow setBackgroundColor: [NSColor clearColor]]; 1786 // shadow is invalidated when view gets drawn again 1787 } 1788 } 1789 1790