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