1/////////////////////////////////////////////////////////////////////////////// 2// Name: src/mac/carbon/toplevel.cpp 3// Purpose: implements wxTopLevelWindow for Mac 4// Author: Stefan Csomor 5// Modified by: 6// Created: 24.09.01 7// RCS-ID: $Id: toplevel.cpp 67125 2011-03-04 16:36:47Z SC $ 8// Copyright: (c) 2001-2004 Stefan Csomor 9// License: wxWindows licence 10/////////////////////////////////////////////////////////////////////////////// 11 12// ============================================================================ 13// declarations 14// ============================================================================ 15 16// ---------------------------------------------------------------------------- 17// headers 18// ---------------------------------------------------------------------------- 19 20// For compilers that support precompilation, includes "wx.h". 21#include "wx/wxprec.h" 22 23#ifdef __BORLANDC__ 24 #pragma hdrstop 25#endif 26 27#include "wx/toplevel.h" 28 29#ifndef WX_PRECOMP 30 #include "wx/app.h" 31 #include "wx/frame.h" 32 #include "wx/string.h" 33 #include "wx/log.h" 34 #include "wx/intl.h" 35 #include "wx/settings.h" 36 #include "wx/strconv.h" 37 #include "wx/control.h" 38#endif //WX_PRECOMP 39 40#include "wx/mac/uma.h" 41#include "wx/mac/aga.h" 42#include "wx/tooltip.h" 43#include "wx/dnd.h" 44 45#if wxUSE_SYSTEM_OPTIONS 46 #include "wx/sysopt.h" 47#endif 48 49#ifndef __DARWIN__ 50#include <ToolUtils.h> 51#endif 52 53// for targeting OSX 54#include "wx/mac/private.h" 55 56// ---------------------------------------------------------------------------- 57// constants 58// ---------------------------------------------------------------------------- 59 60// unified title and toolbar constant - not in Tiger headers, so we duplicate it here 61#define kWindowUnifiedTitleAndToolbarAttribute (1 << 7) 62 63// trace mask for activation tracing messages 64static const wxChar *TRACE_ACTIVATE = _T("activation"); 65 66// ---------------------------------------------------------------------------- 67// globals 68// ---------------------------------------------------------------------------- 69 70// list of all frames and modeless dialogs 71wxWindowList wxModelessWindows; 72 73static pascal long wxShapedMacWindowDef(short varCode, WindowRef window, SInt16 message, SInt32 param); 74 75// ============================================================================ 76// wxTopLevelWindowMac implementation 77// ============================================================================ 78 79BEGIN_EVENT_TABLE(wxTopLevelWindowMac, wxTopLevelWindowBase) 80END_EVENT_TABLE() 81 82// --------------------------------------------------------------------------- 83// Carbon Events 84// --------------------------------------------------------------------------- 85 86static const EventTypeSpec eventList[] = 87{ 88 // TODO: remove control related event like key and mouse (except for WindowLeave events) 89 90 { kEventClassKeyboard, kEventRawKeyDown } , 91 { kEventClassKeyboard, kEventRawKeyRepeat } , 92 { kEventClassKeyboard, kEventRawKeyUp } , 93 { kEventClassKeyboard, kEventRawKeyModifiersChanged } , 94 95 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } , 96 { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } , 97 98 { kEventClassWindow , kEventWindowShown } , 99 { kEventClassWindow , kEventWindowActivated } , 100 { kEventClassWindow , kEventWindowDeactivated } , 101 { kEventClassWindow , kEventWindowBoundsChanging } , 102 { kEventClassWindow , kEventWindowBoundsChanged } , 103 { kEventClassWindow , kEventWindowClose } , 104 105 // we have to catch these events on the toplevel window level, 106 // as controls don't get the raw mouse events anymore 107 108 { kEventClassMouse , kEventMouseDown } , 109 { kEventClassMouse , kEventMouseUp } , 110 { kEventClassMouse , kEventMouseWheelMoved } , 111 { kEventClassMouse , kEventMouseMoved } , 112 { kEventClassMouse , kEventMouseDragged } , 113} ; 114 115static pascal OSStatus KeyboardEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) 116{ 117 OSStatus result = eventNotHandledErr ; 118 // call DoFindFocus instead of FindFocus, because for Composite Windows(like WxGenericListCtrl) 119 // FindFocus does not return the actual focus window, but the enclosing window 120 wxWindow* focus = wxWindow::DoFindFocus(); 121 if ( focus == NULL ) 122 focus = (wxTopLevelWindowMac*) data ; 123 124 unsigned char charCode ; 125 wxChar uniChar[2] ; 126 uniChar[0] = 0; 127 uniChar[1] = 0; 128 129 UInt32 keyCode ; 130 UInt32 modifiers ; 131 Point point ; 132 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ; 133 134#if wxUSE_UNICODE 135 ByteCount dataSize = 0 ; 136 if ( GetEventParameter( event, kEventParamKeyUnicodes, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr ) 137 { 138 UniChar buf[2] ; 139 int numChars = dataSize / sizeof( UniChar) + 1; 140 141 UniChar* charBuf = buf ; 142 143 if ( numChars * 2 > 4 ) 144 charBuf = new UniChar[ numChars ] ; 145 GetEventParameter( event, kEventParamKeyUnicodes, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ; 146 charBuf[ numChars - 1 ] = 0; 147 148#if SIZEOF_WCHAR_T == 2 149 uniChar = charBuf[0] ; 150#else 151 wxMBConvUTF16 converter ; 152 converter.MB2WC( uniChar , (const char*)charBuf , 2 ) ; 153#endif 154 155 if ( numChars * 2 > 4 ) 156 delete[] charBuf ; 157 } 158#endif 159 160 GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode ); 161 GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode ); 162 GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers ); 163 GetEventParameter( event, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point ); 164 165 UInt32 message = (keyCode << 8) + charCode; 166 switch ( GetEventKind( event ) ) 167 { 168 case kEventRawKeyRepeat : 169 case kEventRawKeyDown : 170 { 171 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ; 172 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ; 173 wxTheApp->MacSetCurrentEvent( event , handler ) ; 174 if ( /* focus && */ wxTheApp->MacSendKeyDownEvent( 175 focus , message , modifiers , when , point.h , point.v , uniChar[0] ) ) 176 { 177 result = noErr ; 178 } 179 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ; 180 } 181 break ; 182 183 case kEventRawKeyUp : 184 if ( /* focus && */ wxTheApp->MacSendKeyUpEvent( 185 focus , message , modifiers , when , point.h , point.v , uniChar[0] ) ) 186 { 187 result = noErr ; 188 } 189 break ; 190 191 case kEventRawKeyModifiersChanged : 192 { 193 wxKeyEvent event(wxEVT_KEY_DOWN); 194 195 event.m_shiftDown = modifiers & shiftKey; 196 event.m_controlDown = modifiers & controlKey; 197 event.m_altDown = modifiers & optionKey; 198 event.m_metaDown = modifiers & cmdKey; 199 event.m_x = point.h; 200 event.m_y = point.v; 201 202#if wxUSE_UNICODE 203 event.m_uniChar = uniChar[0] ; 204#endif 205 206 event.SetTimestamp(when); 207 event.SetEventObject(focus); 208 209 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & controlKey ) 210 { 211 event.m_keyCode = WXK_CONTROL ; 212 event.SetEventType( ( modifiers & controlKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; 213 focus->GetEventHandler()->ProcessEvent( event ) ; 214 } 215 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & shiftKey ) 216 { 217 event.m_keyCode = WXK_SHIFT ; 218 event.SetEventType( ( modifiers & shiftKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; 219 focus->GetEventHandler()->ProcessEvent( event ) ; 220 } 221 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & optionKey ) 222 { 223 event.m_keyCode = WXK_ALT ; 224 event.SetEventType( ( modifiers & optionKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; 225 focus->GetEventHandler()->ProcessEvent( event ) ; 226 } 227 if ( /* focus && */ (modifiers ^ wxApp::s_lastModifiers ) & cmdKey ) 228 { 229 event.m_keyCode = WXK_COMMAND ; 230 event.SetEventType( ( modifiers & cmdKey ) ? wxEVT_KEY_DOWN : wxEVT_KEY_UP ) ; 231 focus->GetEventHandler()->ProcessEvent( event ) ; 232 } 233 234 wxApp::s_lastModifiers = modifiers ; 235 } 236 break ; 237 238 default: 239 break; 240 } 241 242 return result ; 243} 244 245// we don't interfere with foreign controls on our toplevel windows, therefore we always give back eventNotHandledErr 246// for windows that we didn't create (like eg Scrollbars in a databrowser), or for controls where we did not handle the 247// mouse down at all 248// 249// This handler can also be called from app level where data (ie target window) may be null or a non wx window 250 251wxWindow* g_MacLastWindow = NULL ; 252 253EventMouseButton g_lastButton = 0 ; 254bool g_lastButtonWasFakeRight = false ; 255 256void SetupMouseEvent( wxMouseEvent &wxevent , wxMacCarbonEvent &cEvent ) 257{ 258 UInt32 modifiers = cEvent.GetParameter<UInt32>(kEventParamKeyModifiers, typeUInt32) ; 259 Point screenMouseLocation = cEvent.GetParameter<Point>(kEventParamMouseLocation) ; 260 261 // these parameters are not given for all events 262 EventMouseButton button = 0 ; 263 UInt32 clickCount = 0 ; 264 UInt32 mouseChord = 0; 265 266 cEvent.GetParameter<EventMouseButton>( kEventParamMouseButton, typeMouseButton , &button ) ; 267 cEvent.GetParameter<UInt32>( kEventParamClickCount, typeUInt32 , &clickCount ) ; 268 // the chord is the state of the buttons pressed currently 269 cEvent.GetParameter<UInt32>( kEventParamMouseChord, typeUInt32 , &mouseChord ) ; 270 271 wxevent.m_x = screenMouseLocation.h; 272 wxevent.m_y = screenMouseLocation.v; 273 wxevent.m_shiftDown = modifiers & shiftKey; 274 wxevent.m_controlDown = modifiers & controlKey; 275 wxevent.m_altDown = modifiers & optionKey; 276 wxevent.m_metaDown = modifiers & cmdKey; 277 wxevent.SetTimestamp( cEvent.GetTicks() ) ; 278 279 // a control click is interpreted as a right click 280 bool thisButtonIsFakeRight = false ; 281 if ( button == kEventMouseButtonPrimary && (modifiers & controlKey) ) 282 { 283 button = kEventMouseButtonSecondary ; 284 thisButtonIsFakeRight = true ; 285 } 286 287 // otherwise we report double clicks by connecting a left click with a ctrl-left click 288 if ( clickCount > 1 && button != g_lastButton ) 289 clickCount = 1 ; 290 291 // we must make sure that our synthetic 'right' button corresponds in 292 // mouse down, moved and mouse up, and does not deliver a right down and left up 293 294 if ( cEvent.GetKind() == kEventMouseDown ) 295 { 296 g_lastButton = button ; 297 g_lastButtonWasFakeRight = thisButtonIsFakeRight ; 298 } 299 300 if ( button == 0 ) 301 { 302 g_lastButton = 0 ; 303 g_lastButtonWasFakeRight = false ; 304 } 305 else if ( g_lastButton == kEventMouseButtonSecondary && g_lastButtonWasFakeRight ) 306 button = g_lastButton ; 307 308 // Adjust the chord mask to remove the primary button and add the 309 // secondary button. It is possible that the secondary button is 310 // already pressed, e.g. on a mouse connected to a laptop, but this 311 // possibility is ignored here: 312 if( thisButtonIsFakeRight && ( mouseChord & 1U ) ) 313 mouseChord = ((mouseChord & ~1U) | 2U); 314 315 if(mouseChord & 1U) 316 wxevent.m_leftDown = true ; 317 if(mouseChord & 2U) 318 wxevent.m_rightDown = true ; 319 if(mouseChord & 4U) 320 wxevent.m_middleDown = true ; 321 322 // translate into wx types 323 switch ( cEvent.GetKind() ) 324 { 325 case kEventMouseDown : 326 switch ( button ) 327 { 328 case kEventMouseButtonPrimary : 329 wxevent.SetEventType( clickCount > 1 ? wxEVT_LEFT_DCLICK : wxEVT_LEFT_DOWN ) ; 330 break ; 331 332 case kEventMouseButtonSecondary : 333 wxevent.SetEventType( clickCount > 1 ? wxEVT_RIGHT_DCLICK : wxEVT_RIGHT_DOWN ) ; 334 break ; 335 336 case kEventMouseButtonTertiary : 337 wxevent.SetEventType( clickCount > 1 ? wxEVT_MIDDLE_DCLICK : wxEVT_MIDDLE_DOWN ) ; 338 break ; 339 340 default: 341 break ; 342 } 343 break ; 344 345 case kEventMouseUp : 346 switch ( button ) 347 { 348 case kEventMouseButtonPrimary : 349 wxevent.SetEventType( wxEVT_LEFT_UP ) ; 350 break ; 351 352 case kEventMouseButtonSecondary : 353 wxevent.SetEventType( wxEVT_RIGHT_UP ) ; 354 break ; 355 356 case kEventMouseButtonTertiary : 357 wxevent.SetEventType( wxEVT_MIDDLE_UP ) ; 358 break ; 359 360 default: 361 break ; 362 } 363 break ; 364 365 case kEventMouseWheelMoved : 366 { 367 EventMouseWheelAxis axis = cEvent.GetParameter<EventMouseWheelAxis>(kEventParamMouseWheelAxis, typeMouseWheelAxis) ; 368 SInt32 delta = cEvent.GetParameter<SInt32>(kEventParamMouseWheelDelta, typeSInt32) ; 369 370 if ( axis == kEventMouseWheelAxisX || 371 axis == kEventMouseWheelAxisY ) 372 { 373 wxevent.SetEventType( wxEVT_MOUSEWHEEL ) ; 374 wxevent.m_wheelRotation = delta; 375 wxevent.m_wheelDelta = 1; 376 wxevent.m_linesPerAction = 1; 377 } 378 else 379 { 380 wxevent.SetEventType( wxEVT_NULL ); 381 } 382 } 383 break ; 384 case kEventMouseEntered : 385 case kEventMouseExited : 386 case kEventMouseDragged : 387 case kEventMouseMoved : 388 wxevent.SetEventType( wxEVT_MOTION ) ; 389 break; 390 default : 391 break ; 392 } 393} 394 395ControlRef wxMacFindSubControl( wxTopLevelWindowMac* toplevelWindow, const Point& location , ControlRef superControl , ControlPartCode *outPart ) 396{ 397 if ( superControl ) 398 { 399 UInt16 childrenCount = 0 ; 400 ControlHandle sibling ; 401 Rect r ; 402 OSStatus err = CountSubControls( superControl , &childrenCount ) ; 403 if ( err == errControlIsNotEmbedder ) 404 return NULL ; 405 406 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") ) ; 407 408 for ( UInt16 i = childrenCount ; i >=1 ; --i ) 409 { 410 err = GetIndexedSubControl( superControl , i , & sibling ) ; 411 if ( err == errControlIsNotEmbedder ) 412 return NULL ; 413 414 wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") ) ; 415 if ( IsControlVisible( sibling ) ) 416 { 417 UMAGetControlBoundsInWindowCoords( sibling , &r ) ; 418 if ( MacPtInRect( location , &r ) ) 419 { 420 ControlHandle child = wxMacFindSubControl( toplevelWindow , location , sibling , outPart ) ; 421 if ( child ) 422 { 423 return child ; 424 } 425 else 426 { 427 Point testLocation = location ; 428 429 if ( toplevelWindow ) 430 { 431 testLocation.h -= r.left ; 432 testLocation.v -= r.top ; 433 } 434 435 *outPart = TestControl( sibling , testLocation ) ; 436 437 return sibling ; 438 } 439 } 440 } 441 } 442 } 443 444 return NULL ; 445} 446 447ControlRef wxMacFindControlUnderMouse( wxTopLevelWindowMac* toplevelWindow , const Point& location , WindowRef window , ControlPartCode *outPart ) 448{ 449#if TARGET_API_MAC_OSX 450 if ( UMAGetSystemVersion() >= 0x1030 ) 451 { 452 HIPoint pt = CGPointMake(location.h, location.v); 453 HIViewRef contentView = NULL ; 454 HIViewFindByID( HIViewGetRoot( window ), kHIViewWindowContentID, &contentView ); 455 HIViewConvertPoint( &pt, contentView, NULL ); 456 HIViewRef control = NULL; 457 if ( HIViewGetSubviewHit( HIViewGetRoot( window ), &pt, true, &control ) == noErr ) 458 { 459 if ( control != NULL ) 460 { 461 if ( HIViewConvertPoint( &pt, NULL, control ) == noErr ) 462 HIViewGetPartHit(control, &pt, outPart); 463 } 464 } 465 return control ; 466 } 467#endif 468 469 ControlRef rootControl = NULL ; 470 verify_noerr( GetRootControl( window , &rootControl ) ) ; 471 472 return wxMacFindSubControl( toplevelWindow , location , rootControl , outPart ) ; 473} 474 475#define NEW_CAPTURE_HANDLING 1 476 477pascal OSStatus wxMacTopLevelMouseEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) 478{ 479 wxTopLevelWindowMac* toplevelWindow = (wxTopLevelWindowMac*) data ; 480 481 OSStatus result = eventNotHandledErr ; 482 483 wxMacCarbonEvent cEvent( event ) ; 484 485 Point screenMouseLocation = cEvent.GetParameter<Point>(kEventParamMouseLocation) ; 486 Point windowMouseLocation = screenMouseLocation ; 487 488 WindowRef window = NULL; 489 short windowPart = ::FindWindow(screenMouseLocation, &window); 490 491 wxWindow* currentMouseWindow = NULL ; 492 ControlRef control = NULL ; 493 494#if NEW_CAPTURE_HANDLING 495 if ( wxApp::s_captureWindow ) 496 { 497 window = (WindowRef) wxApp::s_captureWindow->MacGetTopLevelWindowRef() ; 498 windowPart = inContent ; 499 } 500#endif 501 502 if ( window ) 503 { 504 wxMacGlobalToLocal( window, &windowMouseLocation ) ; 505 506 if ( wxApp::s_captureWindow 507#if !NEW_CAPTURE_HANDLING 508 && wxApp::s_captureWindow->MacGetTopLevelWindowRef() == (WXWindow) window && windowPart == inContent 509#endif 510 ) 511 { 512 currentMouseWindow = wxApp::s_captureWindow ; 513 } 514 else if ( IsWindowActive(window) && (windowPart == inContent||windowPart == inStructure) ) 515 { 516 ControlPartCode part ; 517 control = wxMacFindControlUnderMouse( toplevelWindow , windowMouseLocation , window , &part ) ; 518 // if there is no control below the mouse position, send the event to the toplevel window itself 519 if ( control == 0 ) 520 { 521 currentMouseWindow = (wxWindow*) data ; 522 } 523 else 524 { 525 currentMouseWindow = (wxWindow*) wxFindControlFromMacControl( control ) ; 526#ifndef __WXUNIVERSAL__ 527 if ( currentMouseWindow == NULL && cEvent.GetKind() == kEventMouseMoved ) 528 { 529#if wxUSE_TOOLBAR 530 // for wxToolBar to function we have to send certaint events to it 531 // instead of its children (wxToolBarTools) 532 ControlRef parent ; 533 GetSuperControl(control, &parent ); 534 wxWindow *wxParent = (wxWindow*) wxFindControlFromMacControl( parent ) ; 535 if ( wxParent && wxParent->IsKindOf( CLASSINFO( wxToolBar ) ) ) 536 currentMouseWindow = wxParent ; 537#endif 538 } 539#endif 540 } 541 542 // disabled windows must not get any input messages 543 if ( currentMouseWindow && !currentMouseWindow->MacIsReallyEnabled() ) 544 currentMouseWindow = NULL; 545 } 546 } 547 548 wxMouseEvent wxevent(wxEVT_LEFT_DOWN); 549 SetupMouseEvent( wxevent , cEvent ) ; 550 551 // handle all enter / leave events 552 553 if ( currentMouseWindow != g_MacLastWindow ) 554 { 555 if ( g_MacLastWindow ) 556 { 557 wxMouseEvent eventleave(wxevent); 558 eventleave.SetEventType( wxEVT_LEAVE_WINDOW ); 559 g_MacLastWindow->ScreenToClient( &eventleave.m_x, &eventleave.m_y ); 560 eventleave.SetEventObject( g_MacLastWindow ) ; 561 wxevent.SetId( g_MacLastWindow->GetId() ) ; 562 563#if wxUSE_TOOLTIPS 564 wxToolTip::RelayEvent( g_MacLastWindow , eventleave); 565#endif 566 567 g_MacLastWindow->GetEventHandler()->ProcessEvent(eventleave); 568 } 569 570 if ( currentMouseWindow ) 571 { 572 wxMouseEvent evententer(wxevent); 573 evententer.SetEventType( wxEVT_ENTER_WINDOW ); 574 currentMouseWindow->ScreenToClient( &evententer.m_x, &evententer.m_y ); 575 evententer.SetEventObject( currentMouseWindow ) ; 576 wxevent.SetId( currentMouseWindow->GetId() ) ; 577 578#if wxUSE_TOOLTIPS 579 wxToolTip::RelayEvent( currentMouseWindow , evententer ); 580#endif 581 582 currentMouseWindow->GetEventHandler()->ProcessEvent(evententer); 583 } 584 585 g_MacLastWindow = currentMouseWindow ; 586 } 587 588 if ( windowPart == inMenuBar ) 589 { 590 // special case menu bar, as we are having a low-level runloop we must do it ourselves 591 if ( cEvent.GetKind() == kEventMouseDown ) 592 { 593 ::MenuSelect( screenMouseLocation ) ; 594 ::HiliteMenu(0); 595 result = noErr ; 596 } 597 } 598 else if ( currentMouseWindow ) 599 { 600 wxWindow *currentMouseWindowParent = currentMouseWindow->GetParent(); 601 602 currentMouseWindow->ScreenToClient( &wxevent.m_x , &wxevent.m_y ) ; 603 604 wxevent.SetEventObject( currentMouseWindow ) ; 605 wxevent.SetId( currentMouseWindow->GetId() ) ; 606 607 // make tooltips current 608 609#if wxUSE_TOOLTIPS 610 if ( wxevent.GetEventType() == wxEVT_MOTION ) 611 wxToolTip::RelayEvent( currentMouseWindow , wxevent ); 612#endif 613 614 if ( currentMouseWindow->GetEventHandler()->ProcessEvent(wxevent) ) 615 { 616 /* 617 // this code is dangerous in case the delete in the mouse down occured further up in the chain, trying alternative 618 619 if ((currentMouseWindowParent != NULL) && 620 (currentMouseWindowParent->GetChildren().Find(currentMouseWindow) == NULL)) 621 */ 622 // deleted in the meantime 623 if ( g_MacLastWindow == NULL ) 624 currentMouseWindow = NULL; 625 626 result = noErr; 627 } 628 else 629 { 630 // if the user code did _not_ handle the event, then perform the 631 // default processing 632 if ( wxevent.GetEventType() == wxEVT_LEFT_DOWN ) 633 { 634 // ... that is set focus to this window 635 if (currentMouseWindow->AcceptsFocus() && wxWindow::FindFocus()!=currentMouseWindow) 636 currentMouseWindow->SetFocus(); 637 } 638 639 640#ifndef __WXMAC_OSX__ 641 // if built-in find control is finding the wrong control (ie static box instead of overlaid 642 // button, we cannot let the standard handler do its job, but must handle manually 643 // this only can happen < 10.3 644 if ( cEvent.GetKind() == kEventMouseDown ) 645 { 646 if ( currentMouseWindow->MacIsReallyEnabled() ) 647 { 648 EventModifiers modifiers = cEvent.GetParameter<EventModifiers>(kEventParamKeyModifiers, typeUInt32) ; 649 Point clickLocation = windowMouseLocation ; 650 651 currentMouseWindow->MacRootWindowToWindow( &clickLocation.h , &clickLocation.v ) ; 652 653 HandleControlClick( (ControlRef) currentMouseWindow->GetHandle() , clickLocation , 654 modifiers , (ControlActionUPP ) -1 ) ; 655 656 if ((currentMouseWindowParent != NULL) && 657 (currentMouseWindowParent->GetChildren().Find(currentMouseWindow) == NULL)) 658 { 659 currentMouseWindow = NULL; 660 } 661 } 662 663 result = noErr ; 664 } 665#endif 666 } 667 668 if ( cEvent.GetKind() == kEventMouseUp && wxApp::s_captureWindow ) 669 { 670 wxApp::s_captureWindow = NULL ; 671 // update cursor ? 672 } 673 674 // update cursor 675 676 wxWindow* cursorTarget = currentMouseWindow ; 677 wxPoint cursorPoint( wxevent.m_x , wxevent.m_y ) ; 678 679 extern wxCursor gGlobalCursor; 680 681 if (!gGlobalCursor.IsOk()) 682 { 683 while ( cursorTarget && !cursorTarget->MacSetupCursor( cursorPoint ) ) 684 { 685 cursorTarget = cursorTarget->GetParent() ; 686 if ( cursorTarget ) 687 cursorPoint += cursorTarget->GetPosition(); 688 } 689 } 690 691 } 692 else // currentMouseWindow == NULL 693 { 694 // don't mess with controls we don't know about 695 // for some reason returning eventNotHandledErr does not lead to the correct behaviour 696 // so we try sending them the correct control directly 697 if ( cEvent.GetKind() == kEventMouseDown && toplevelWindow && control ) 698 { 699 EventModifiers modifiers = cEvent.GetParameter<EventModifiers>(kEventParamKeyModifiers, typeUInt32) ; 700 Point clickLocation = windowMouseLocation ; 701#if TARGET_API_MAC_OSX 702 HIPoint hiPoint ; 703 hiPoint.x = clickLocation.h ; 704 hiPoint.y = clickLocation.v ; 705 HIViewConvertPoint( &hiPoint , (ControlRef) toplevelWindow->GetHandle() , control ) ; 706 clickLocation.h = (int)hiPoint.x ; 707 clickLocation.v = (int)hiPoint.y ; 708#endif // TARGET_API_MAC_OSX 709 710 HandleControlClick( control , clickLocation , modifiers , (ControlActionUPP ) -1 ) ; 711 result = noErr ; 712 } 713 } 714 715 return result ; 716} 717 718static pascal OSStatus wxMacTopLevelWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) 719{ 720 OSStatus result = eventNotHandledErr ; 721 722 wxMacCarbonEvent cEvent( event ) ; 723 724 // WindowRef windowRef = cEvent.GetParameter<WindowRef>(kEventParamDirectObject) ; 725 wxTopLevelWindowMac* toplevelWindow = (wxTopLevelWindowMac*) data ; 726 727 switch ( GetEventKind( event ) ) 728 { 729 case kEventWindowActivated : 730 { 731 toplevelWindow->MacActivate( cEvent.GetTicks() , true) ; 732 wxActivateEvent wxevent(wxEVT_ACTIVATE, true , toplevelWindow->GetId()); 733 wxevent.SetTimestamp( cEvent.GetTicks() ) ; 734 wxevent.SetEventObject(toplevelWindow); 735 toplevelWindow->GetEventHandler()->ProcessEvent(wxevent); 736 // we still sending an eventNotHandledErr in order to allow for default processing 737 } 738 break ; 739 740 case kEventWindowDeactivated : 741 { 742 toplevelWindow->MacActivate(cEvent.GetTicks() , false) ; 743 wxActivateEvent wxevent(wxEVT_ACTIVATE, false , toplevelWindow->GetId()); 744 wxevent.SetTimestamp( cEvent.GetTicks() ) ; 745 wxevent.SetEventObject(toplevelWindow); 746 toplevelWindow->GetEventHandler()->ProcessEvent(wxevent); 747 // we still sending an eventNotHandledErr in order to allow for default processing 748 } 749 break ; 750 751 case kEventWindowShown : 752 toplevelWindow->Refresh() ; 753 result = noErr ; 754 break ; 755 756 case kEventWindowClose : 757 toplevelWindow->Close() ; 758 result = noErr ; 759 break ; 760 761 case kEventWindowBoundsChanged : 762 { 763 UInt32 attributes = cEvent.GetParameter<UInt32>(kEventParamAttributes, typeUInt32) ; 764 Rect newRect = cEvent.GetParameter<Rect>(kEventParamCurrentBounds) ; 765 wxRect r( newRect.left , newRect.top , newRect.right - newRect.left , newRect.bottom - newRect.top ) ; 766 if ( attributes & kWindowBoundsChangeSizeChanged ) 767 { 768#ifndef __WXUNIVERSAL__ 769 // according to the other ports we handle this within the OS level 770 // resize event, not within a wxSizeEvent 771 wxFrame *frame = wxDynamicCast( toplevelWindow , wxFrame ) ; 772 if ( frame ) 773 { 774 frame->PositionBars(); 775 } 776#endif 777 wxSizeEvent event( r.GetSize() , toplevelWindow->GetId() ) ; 778 event.SetEventObject( toplevelWindow ) ; 779 780 toplevelWindow->GetEventHandler()->ProcessEvent(event) ; 781 toplevelWindow->wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified 782 } 783 784 if ( attributes & kWindowBoundsChangeOriginChanged ) 785 { 786 wxMoveEvent event( r.GetLeftTop() , toplevelWindow->GetId() ) ; 787 event.SetEventObject( toplevelWindow ) ; 788 toplevelWindow->GetEventHandler()->ProcessEvent(event) ; 789 } 790 791 result = noErr ; 792 } 793 break ; 794 795 case kEventWindowBoundsChanging : 796 { 797 UInt32 attributes = cEvent.GetParameter<UInt32>(kEventParamAttributes,typeUInt32) ; 798 Rect newRect = cEvent.GetParameter<Rect>(kEventParamCurrentBounds) ; 799 800 if ( (attributes & kWindowBoundsChangeSizeChanged) || (attributes & kWindowBoundsChangeOriginChanged) ) 801 { 802 // all (Mac) rects are in content area coordinates, all wxRects in structure coordinates 803 int left , top , right , bottom ; 804 toplevelWindow->MacGetContentAreaInset( left , top , right , bottom ) ; 805 806 wxRect r( 807 newRect.left - left, 808 newRect.top - top, 809 newRect.right - newRect.left + left + right, 810 newRect.bottom - newRect.top + top + bottom ) ; 811 812 // this is a EVT_SIZING not a EVT_SIZE type ! 813 wxSizeEvent wxevent( r , toplevelWindow->GetId() ) ; 814 wxevent.SetEventObject( toplevelWindow ) ; 815 wxRect adjustR = r ; 816 if ( toplevelWindow->GetEventHandler()->ProcessEvent(wxevent) ) 817 adjustR = wxevent.GetRect() ; 818 819 if ( toplevelWindow->GetMaxWidth() != -1 && adjustR.GetWidth() > toplevelWindow->GetMaxWidth() ) 820 adjustR.SetWidth( toplevelWindow->GetMaxWidth() ) ; 821 if ( toplevelWindow->GetMaxHeight() != -1 && adjustR.GetHeight() > toplevelWindow->GetMaxHeight() ) 822 adjustR.SetHeight( toplevelWindow->GetMaxHeight() ) ; 823 if ( toplevelWindow->GetMinWidth() != -1 && adjustR.GetWidth() < toplevelWindow->GetMinWidth() ) 824 adjustR.SetWidth( toplevelWindow->GetMinWidth() ) ; 825 if ( toplevelWindow->GetMinHeight() != -1 && adjustR.GetHeight() < toplevelWindow->GetMinHeight() ) 826 adjustR.SetHeight( toplevelWindow->GetMinHeight() ) ; 827 const Rect adjustedRect = { adjustR.y + top , adjustR.x + left , adjustR.y + adjustR.height - bottom , adjustR.x + adjustR.width - right } ; 828 if ( !EqualRect( &newRect , &adjustedRect ) ) 829 cEvent.SetParameter<Rect>( kEventParamCurrentBounds , &adjustedRect ) ; 830 toplevelWindow->wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified 831 } 832 833 result = noErr ; 834 } 835 break ; 836 837 default : 838 break ; 839 } 840 841 return result ; 842} 843 844// mix this in from window.cpp 845pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) ; 846 847pascal OSStatus wxMacTopLevelEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) 848{ 849 OSStatus result = eventNotHandledErr ; 850 851 switch ( GetEventClass( event ) ) 852 { 853 case kEventClassTextInput : 854 result = wxMacUnicodeTextEventHandler( handler, event , data ) ; 855 break ; 856 857 case kEventClassKeyboard : 858 result = KeyboardEventHandler( handler, event , data ) ; 859 break ; 860 861 case kEventClassWindow : 862 result = wxMacTopLevelWindowEventHandler( handler, event , data ) ; 863 break ; 864 865 case kEventClassMouse : 866 result = wxMacTopLevelMouseEventHandler( handler, event , data ) ; 867 break ; 868 869 default : 870 break ; 871 } 872 873 return result ; 874} 875 876DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacTopLevelEventHandler ) 877 878// --------------------------------------------------------------------------- 879// wxWindowMac utility functions 880// --------------------------------------------------------------------------- 881 882// Find an item given the Macintosh Window Reference 883 884WX_DECLARE_HASH_MAP(WindowRef, wxTopLevelWindowMac*, wxPointerHash, wxPointerEqual, MacWindowMap); 885 886static MacWindowMap wxWinMacWindowList; 887 888wxTopLevelWindowMac *wxFindWinFromMacWindow(WindowRef inWindowRef) 889{ 890 MacWindowMap::iterator node = wxWinMacWindowList.find(inWindowRef); 891 892 return (node == wxWinMacWindowList.end()) ? NULL : node->second; 893} 894 895void wxAssociateWinWithMacWindow(WindowRef inWindowRef, wxTopLevelWindowMac *win) ; 896void wxAssociateWinWithMacWindow(WindowRef inWindowRef, wxTopLevelWindowMac *win) 897{ 898 // adding NULL WindowRef is (first) surely a result of an error and 899 // nothing else :-) 900 wxCHECK_RET( inWindowRef != (WindowRef) NULL, wxT("attempt to add a NULL WindowRef to window list") ); 901 902 wxWinMacWindowList[inWindowRef] = win; 903} 904 905void wxRemoveMacWindowAssociation(wxTopLevelWindowMac *win) ; 906void wxRemoveMacWindowAssociation(wxTopLevelWindowMac *win) 907{ 908 MacWindowMap::iterator it; 909 for ( it = wxWinMacWindowList.begin(); it != wxWinMacWindowList.end(); ++it ) 910 { 911 if ( it->second == win ) 912 { 913 wxWinMacWindowList.erase(it); 914 break; 915 } 916 } 917} 918 919// ---------------------------------------------------------------------------- 920// wxTopLevelWindowMac creation 921// ---------------------------------------------------------------------------- 922 923wxTopLevelWindowMac *wxTopLevelWindowMac::s_macDeactivateWindow = NULL; 924 925typedef struct 926{ 927 wxPoint m_position ; 928 wxSize m_size ; 929 bool m_wasResizable ; 930} FullScreenData ; 931 932void wxTopLevelWindowMac::Init() 933{ 934 m_iconized = 935 m_maximizeOnShow = false; 936 m_macWindow = NULL ; 937 938 m_macEventHandler = NULL ; 939 m_macFullScreenData = NULL ; 940} 941 942wxMacDeferredWindowDeleter::wxMacDeferredWindowDeleter( WindowRef windowRef ) 943{ 944 m_macWindow = windowRef ; 945} 946 947wxMacDeferredWindowDeleter::~wxMacDeferredWindowDeleter() 948{ 949 UMADisposeWindow( (WindowRef) m_macWindow ) ; 950} 951 952bool wxTopLevelWindowMac::Create(wxWindow *parent, 953 wxWindowID id, 954 const wxString& title, 955 const wxPoint& pos, 956 const wxSize& size, 957 long style, 958 const wxString& name) 959{ 960 // init our fields 961 Init(); 962 963 m_windowStyle = style; 964 965 SetName( name ); 966 967 m_windowId = id == -1 ? NewControlId() : id; 968 wxWindow::SetLabel( title ) ; 969 970 DoMacCreateRealWindow( parent, title, pos , size , style , name ) ; 971 972 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); 973 974 if (GetExtraStyle() & wxFRAME_EX_METAL) 975 MacSetMetalAppearance(true); 976 977 wxTopLevelWindows.Append(this); 978 979 if ( parent ) 980 parent->AddChild(this); 981 982 return true; 983} 984 985bool wxTopLevelWindowMac::Destroy() 986{ 987 // NB: this will get called during destruction if we don't do it now, 988 // and may fire a kill focus event on a control being destroyed 989 if (m_macWindow) 990 ClearKeyboardFocus( (WindowRef)m_macWindow ); 991 992 return wxTopLevelWindowBase::Destroy(); 993} 994 995wxTopLevelWindowMac::~wxTopLevelWindowMac() 996{ 997 if ( m_macWindow ) 998 { 999#if wxUSE_TOOLTIPS 1000 wxToolTip::NotifyWindowDelete(m_macWindow) ; 1001#endif 1002 wxPendingDelete.Append( new wxMacDeferredWindowDeleter( (WindowRef) m_macWindow ) ) ; 1003 } 1004 1005 if ( m_macEventHandler ) 1006 { 1007 ::RemoveEventHandler((EventHandlerRef) m_macEventHandler); 1008 m_macEventHandler = NULL ; 1009 } 1010 1011 wxRemoveMacWindowAssociation( this ) ; 1012 1013 if ( wxModelessWindows.Find(this) ) 1014 wxModelessWindows.DeleteObject(this); 1015 1016 FullScreenData *data = (FullScreenData *) m_macFullScreenData ; 1017 delete data ; 1018 m_macFullScreenData = NULL ; 1019 1020 // avoid dangling refs 1021 if ( s_macDeactivateWindow == this ) 1022 s_macDeactivateWindow = NULL; 1023} 1024 1025 1026// ---------------------------------------------------------------------------- 1027// wxTopLevelWindowMac maximize/minimize 1028// ---------------------------------------------------------------------------- 1029 1030void wxTopLevelWindowMac::Maximize(bool maximize) 1031{ 1032 Point idealSize = { 0 , 0 } ; 1033 if ( maximize ) 1034 { 1035#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 1036 HIRect bounds ; 1037 HIWindowGetAvailablePositioningBounds(kCGNullDirectDisplay,kHICoordSpace72DPIGlobal, 1038 &bounds); 1039 idealSize.h = bounds.size.width; 1040 idealSize.v = bounds.size.height; 1041#else 1042 Rect rect ; 1043 GetAvailableWindowPositioningBounds(GetMainDevice(),&rect) ; 1044 idealSize.h = rect.right - rect.left ; 1045 idealSize.v = rect.bottom - rect.top ; 1046#endif 1047 } 1048 ZoomWindowIdeal( (WindowRef)m_macWindow , maximize ? inZoomOut : inZoomIn , &idealSize ) ; 1049} 1050 1051bool wxTopLevelWindowMac::IsMaximized() const 1052{ 1053 return IsWindowInStandardState( (WindowRef)m_macWindow , NULL , NULL ) ; 1054} 1055 1056void wxTopLevelWindowMac::Iconize(bool iconize) 1057{ 1058 if ( IsWindowCollapsable( (WindowRef)m_macWindow) ) 1059 CollapseWindow( (WindowRef)m_macWindow , iconize ) ; 1060} 1061 1062bool wxTopLevelWindowMac::IsIconized() const 1063{ 1064 return IsWindowCollapsed((WindowRef)m_macWindow ) ; 1065} 1066 1067void wxTopLevelWindowMac::Restore() 1068{ 1069 if ( IsMaximized() ) 1070 Maximize(false); 1071 else if ( IsIconized() ) 1072 Iconize(false); 1073} 1074 1075// ---------------------------------------------------------------------------- 1076// wxTopLevelWindowMac misc 1077// ---------------------------------------------------------------------------- 1078 1079wxPoint wxTopLevelWindowMac::GetClientAreaOrigin() const 1080{ 1081 return wxPoint(0, 0) ; 1082} 1083 1084void wxTopLevelWindowMac::SetIcon(const wxIcon& icon) 1085{ 1086 // this sets m_icon 1087 wxTopLevelWindowBase::SetIcon(icon); 1088} 1089 1090void wxTopLevelWindowMac::MacSetBackgroundBrush( const wxBrush &brush ) 1091{ 1092 wxTopLevelWindowBase::MacSetBackgroundBrush( brush ) ; 1093 1094 if ( m_macBackgroundBrush.Ok() && m_macBackgroundBrush.GetStyle() != wxTRANSPARENT && m_macBackgroundBrush.MacGetBrushKind() == kwxMacBrushTheme ) 1095 { 1096 SetThemeWindowBackground( (WindowRef) m_macWindow , m_macBackgroundBrush.MacGetTheme() , false ) ; 1097 } 1098} 1099 1100void wxTopLevelWindowMacInstallTopLevelWindowEventHandler(WindowRef window, EventHandlerRef* handler, void *ref) 1101{ 1102 InstallWindowEventHandler(window, GetwxMacTopLevelEventHandlerUPP(), 1103 GetEventTypeCount(eventList), eventList, ref, handler ); 1104} 1105 1106void wxTopLevelWindowMac::MacInstallTopLevelWindowEventHandler() 1107{ 1108 if ( m_macEventHandler != NULL ) 1109 { 1110 verify_noerr( ::RemoveEventHandler( (EventHandlerRef) m_macEventHandler ) ) ; 1111 } 1112 wxTopLevelWindowMacInstallTopLevelWindowEventHandler(MAC_WXHWND(m_macWindow),(EventHandlerRef *)&m_macEventHandler,this); 1113} 1114 1115void wxTopLevelWindowMac::MacCreateRealWindow( 1116 const wxString& title, 1117 const wxPoint& pos, 1118 const wxSize& size, 1119 long style, 1120 const wxString& name ) 1121{ 1122 DoMacCreateRealWindow( NULL, title, pos, size, style, name ); 1123} 1124 1125void wxTopLevelWindowMac::DoMacCreateRealWindow( 1126 wxWindow* parent, 1127 const wxString& title, 1128 const wxPoint& pos, 1129 const wxSize& size, 1130 long style, 1131 const wxString& name ) 1132{ 1133 OSStatus err = noErr ; 1134 SetName(name); 1135 m_windowStyle = style; 1136 m_isShown = false; 1137 1138 // create frame. 1139 int x = (int)pos.x; 1140 int y = (int)pos.y; 1141 1142 Rect theBoundsRect; 1143 wxRect display = wxGetClientDisplayRect() ; 1144 1145 if ( x == wxDefaultPosition.x ) 1146 x = display.x ; 1147 1148 if ( y == wxDefaultPosition.y ) 1149 y = display.y ; 1150 1151 int w = WidthDefault(size.x); 1152 int h = HeightDefault(size.y); 1153 1154 ::SetRect(&theBoundsRect, x, y , x + w, y + h); 1155 1156 // translate the window attributes in the appropriate window class and attributes 1157 WindowClass wclass = 0; 1158 WindowAttributes attr = kWindowNoAttributes ; 1159 WindowGroupRef group = NULL ; 1160 bool activationScopeSet = false; 1161 WindowActivationScope activationScope = kWindowActivationScopeNone; 1162 1163 if ( HasFlag( wxFRAME_TOOL_WINDOW) ) 1164 { 1165 if ( 1166 HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) || 1167 HasFlag( wxSYSTEM_MENU ) || HasFlag( wxCAPTION ) || 1168 HasFlag(wxTINY_CAPTION_HORIZ) || HasFlag(wxTINY_CAPTION_VERT) 1169 ) 1170 { 1171 if ( HasFlag( wxSTAY_ON_TOP ) ) 1172 wclass = kUtilityWindowClass; 1173 else 1174 wclass = kFloatingWindowClass; 1175 1176 if ( HasFlag(wxTINY_CAPTION_VERT) ) 1177 attr |= kWindowSideTitlebarAttribute ; 1178 } 1179 else 1180 { 1181 if ( HasFlag( wxNO_BORDER ) ) 1182 { 1183 wclass = kSimpleWindowClass ; 1184 } 1185 else 1186 { 1187 wclass = kPlainWindowClass ; 1188 } 1189 activationScopeSet = true; 1190 activationScope = kWindowActivationScopeNone; 1191 } 1192 } 1193 else if ( HasFlag( wxPOPUP_WINDOW ) ) 1194 { 1195 // TEMPORARY HACK! 1196 // Until we've got a real wxPopupWindow class on wxMac make it a 1197 // little easier for wxFrame to be used to emulate it and workaround 1198 // the lack of wxPopupWindow. 1199 if ( HasFlag( wxBORDER_NONE ) ) 1200 wclass = kHelpWindowClass ; // has no border 1201 else 1202 wclass = kPlainWindowClass ; // has a single line border, it will have to do for now 1203 //attr |= kWindowNoShadowAttribute; // turn off the shadow Should we?? 1204 group = GetWindowGroupOfClass( // float above other windows 1205 kFloatingWindowClass) ; 1206 } 1207 else if ( HasFlag( wxCAPTION ) ) 1208 { 1209 wclass = kDocumentWindowClass ; 1210 attr |= kWindowInWindowMenuAttribute ; 1211 } 1212#if defined( __WXMAC__ ) && TARGET_API_MAC_OSX && ( MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_2 ) 1213 else if ( HasFlag( wxFRAME_DRAWER ) ) 1214 { 1215 wclass = kDrawerWindowClass; 1216 } 1217#endif //10.2 and up 1218 else 1219 { 1220 if ( HasFlag( wxMINIMIZE_BOX ) || HasFlag( wxMAXIMIZE_BOX ) || 1221 HasFlag( wxCLOSE_BOX ) || HasFlag( wxSYSTEM_MENU ) ) 1222 { 1223 wclass = kDocumentWindowClass ; 1224 } 1225 else if ( HasFlag( wxNO_BORDER ) ) 1226 { 1227 wclass = kSimpleWindowClass ; 1228 } 1229 else 1230 { 1231 wclass = kPlainWindowClass ; 1232 } 1233 } 1234 1235 if ( wclass != kPlainWindowClass ) 1236 { 1237 if ( HasFlag( wxMINIMIZE_BOX ) ) 1238 attr |= kWindowCollapseBoxAttribute ; 1239 1240 if ( HasFlag( wxMAXIMIZE_BOX ) ) 1241 attr |= kWindowFullZoomAttribute ; 1242 1243 if ( HasFlag( wxRESIZE_BORDER ) ) 1244 attr |= kWindowResizableAttribute ; 1245 1246 if ( HasFlag( wxCLOSE_BOX) ) 1247 attr |= kWindowCloseBoxAttribute ; 1248 } 1249 1250 // turn on live resizing (OS X only) 1251 if (UMAGetSystemVersion() >= 0x1000) 1252 attr |= kWindowLiveResizeAttribute; 1253 1254 if ( HasFlag(wxSTAY_ON_TOP) ) 1255 group = GetWindowGroupOfClass(kUtilityWindowClass) ; 1256 1257 if ( HasFlag( wxFRAME_FLOAT_ON_PARENT ) ) 1258 group = GetWindowGroupOfClass(kFloatingWindowClass) ; 1259 1260 if ( group == NULL && parent != NULL ) 1261 { 1262 WindowRef parenttlw = (WindowRef) parent->MacGetTopLevelWindowRef(); 1263 if( parenttlw ) 1264 group = GetWindowGroupParent( GetWindowGroup( parenttlw ) ); 1265 } 1266 1267 attr |= kWindowCompositingAttribute; 1268#if 0 // wxMAC_USE_CORE_GRAPHICS ; TODO : decide on overall handling of high dpi screens (pixel vs userscale) 1269 attr |= kWindowFrameworkScaledAttribute; 1270#endif 1271 1272 if ( HasFlag(wxFRAME_SHAPED) ) 1273 { 1274 WindowDefSpec customWindowDefSpec; 1275 customWindowDefSpec.defType = kWindowDefProcPtr; 1276 customWindowDefSpec.u.defProc = 1277#ifdef __LP64__ 1278 (WindowDefUPP) wxShapedMacWindowDef; 1279#else 1280 NewWindowDefUPP(wxShapedMacWindowDef); 1281#endif 1282 err = ::CreateCustomWindow( &customWindowDefSpec, wclass, 1283 attr, &theBoundsRect, 1284 (WindowRef*) &m_macWindow); 1285 } 1286 else 1287 { 1288 err = ::CreateNewWindow( wclass , attr , &theBoundsRect , (WindowRef*)&m_macWindow ) ; 1289 } 1290 1291 if ( err == noErr && m_macWindow != NULL && group != NULL ) 1292 SetWindowGroup( (WindowRef) m_macWindow , group ) ; 1293 1294 wxCHECK_RET( err == noErr, wxT("Mac OS error when trying to create new window") ); 1295 1296 // setup a separate group for each window, so that overlays can be handled easily 1297 1298 WindowGroupRef overlaygroup = NULL; 1299 verify_noerr( CreateWindowGroup( kWindowGroupAttrMoveTogether | kWindowGroupAttrLayerTogether | kWindowGroupAttrHideOnCollapse, &overlaygroup )); 1300 verify_noerr( SetWindowGroupParent( overlaygroup, GetWindowGroup( (WindowRef) m_macWindow ))); 1301 verify_noerr( SetWindowGroup( (WindowRef) m_macWindow , overlaygroup )); 1302 1303 if ( activationScopeSet ) 1304 { 1305 verify_noerr( SetWindowActivationScope( (WindowRef) m_macWindow , activationScope )); 1306 } 1307 1308 // the create commands are only for content rect, 1309 // so we have to set the size again as structure bounds 1310 SetWindowBounds( (WindowRef) m_macWindow , kWindowStructureRgn , &theBoundsRect ) ; 1311 1312 wxAssociateWinWithMacWindow( (WindowRef) m_macWindow , this ) ; 1313 UMASetWTitle( (WindowRef) m_macWindow , title , GetFont().GetEncoding() ) ; 1314 m_peer = new wxMacControl(this , true /*isRootControl*/) ; 1315 1316 // There is a bug in 10.2.X for ::GetRootControl returning the window view instead of 1317 // the content view, so we have to retrieve it explicitly 1318 HIViewFindByID( HIViewGetRoot( (WindowRef) m_macWindow ) , kHIViewWindowContentID , 1319 m_peer->GetControlRefAddr() ) ; 1320 if ( !m_peer->Ok() ) 1321 { 1322 // compatibility mode fallback 1323 GetRootControl( (WindowRef) m_macWindow , m_peer->GetControlRefAddr() ) ; 1324 } 1325 1326 // the root control level handler 1327 MacInstallEventHandler( (WXWidget) m_peer->GetControlRef() ) ; 1328 1329 // Causes the inner part of the window not to be metal 1330 // if the style is used before window creation. 1331#if 0 // TARGET_API_MAC_OSX 1332 if ( m_macUsesCompositing && m_macWindow != NULL ) 1333 { 1334 if ( GetExtraStyle() & wxFRAME_EX_METAL ) 1335 MacSetMetalAppearance( true ) ; 1336 } 1337#endif 1338 1339#if TARGET_API_MAC_OSX 1340 if ( m_macWindow != NULL ) 1341 { 1342 MacSetUnifiedAppearance( true ) ; 1343 } 1344#endif 1345 1346 HIViewRef growBoxRef = 0 ; 1347 err = HIViewFindByID( HIViewGetRoot( (WindowRef)m_macWindow ), kHIViewWindowGrowBoxID, &growBoxRef ); 1348 if ( err == noErr && growBoxRef != 0 ) 1349 HIGrowBoxViewSetTransparent( growBoxRef, true ) ; 1350 1351 // the frame window event handler 1352 InstallStandardEventHandler( GetWindowEventTarget(MAC_WXHWND(m_macWindow)) ) ; 1353 MacInstallTopLevelWindowEventHandler() ; 1354 1355 DoSetWindowVariant( m_windowVariant ) ; 1356 1357 m_macFocus = NULL ; 1358 1359 if ( HasFlag(wxFRAME_SHAPED) ) 1360 { 1361 // default shape matches the window size 1362 wxRegion rgn( 0, 0, w, h ); 1363 SetShape( rgn ); 1364 } 1365 1366 wxWindowCreateEvent event(this); 1367 GetEventHandler()->ProcessEvent(event); 1368} 1369 1370void wxTopLevelWindowMac::ClearBackground() 1371{ 1372 wxWindow::ClearBackground() ; 1373} 1374 1375// Raise the window to the top of the Z order 1376void wxTopLevelWindowMac::Raise() 1377{ 1378 ::SelectWindow( (WindowRef)m_macWindow ) ; 1379} 1380 1381// Lower the window to the bottom of the Z order 1382void wxTopLevelWindowMac::Lower() 1383{ 1384 ::SendBehind( (WindowRef)m_macWindow , NULL ) ; 1385} 1386 1387void wxTopLevelWindowMac::MacDelayedDeactivation(long timestamp) 1388{ 1389 if (s_macDeactivateWindow) 1390 { 1391 wxLogTrace(TRACE_ACTIVATE, 1392 wxT("Doing delayed deactivation of %p"), 1393 s_macDeactivateWindow); 1394 1395 s_macDeactivateWindow->MacActivate(timestamp, false); 1396 } 1397} 1398 1399void wxTopLevelWindowMac::MacActivate( long timestamp , bool inIsActivating ) 1400{ 1401 wxLogTrace(TRACE_ACTIVATE, wxT("TopLevel=%p::MacActivate"), this); 1402 1403 if (s_macDeactivateWindow == this) 1404 s_macDeactivateWindow = NULL; 1405 1406 MacDelayedDeactivation(timestamp); 1407 MacPropagateHiliteChanged() ; 1408} 1409 1410void wxTopLevelWindowMac::SetTitle(const wxString& title) 1411{ 1412 SetLabel( title ) ; 1413} 1414 1415void wxTopLevelWindowMac::SetLabel(const wxString& title) 1416{ 1417 m_label = title; 1418 UMASetWTitle( (WindowRef)m_macWindow , title , GetFont().GetEncoding() ) ; 1419} 1420 1421wxString wxTopLevelWindowMac::GetTitle() const 1422{ 1423 return wxWindow::GetLabel(); 1424} 1425 1426bool wxTopLevelWindowMac::Show(bool show) 1427{ 1428 if ( !wxTopLevelWindowBase::Show(show) ) 1429 return false; 1430 1431 bool plainTransition = false; 1432 1433#if wxUSE_SYSTEM_OPTIONS 1434 // code contributed by Ryan Wilcox December 18, 2003 1435 plainTransition = UMAGetSystemVersion() >= 0x1000 ; 1436 if ( wxSystemOptions::HasOption(wxMAC_WINDOW_PLAIN_TRANSITION) ) 1437 plainTransition = ( wxSystemOptions::GetOptionInt( wxMAC_WINDOW_PLAIN_TRANSITION ) == 1 ) ; 1438#endif 1439 1440 if (show) 1441 { 1442 if ( plainTransition ) 1443 ::ShowWindow( (WindowRef)m_macWindow ); 1444 else 1445 ::TransitionWindow( (WindowRef)m_macWindow, kWindowZoomTransitionEffect, kWindowShowTransitionAction, NULL ); 1446 1447 ::SelectWindow( (WindowRef)m_macWindow ) ; 1448 1449 // because apps expect a size event to occur at this moment 1450 wxSizeEvent event(GetSize() , m_windowId); 1451 event.SetEventObject(this); 1452 GetEventHandler()->ProcessEvent(event); 1453 } 1454 else 1455 { 1456 if ( plainTransition ) 1457 ::HideWindow( (WindowRef)m_macWindow ); 1458 else 1459 ::TransitionWindow( (WindowRef)m_macWindow, kWindowZoomTransitionEffect, kWindowHideTransitionAction, NULL ); 1460 } 1461 1462 MacPropagateVisibilityChanged() ; 1463 1464 return true ; 1465} 1466 1467bool wxTopLevelWindowMac::ShowFullScreen(bool show, long style) 1468{ 1469 if ( show ) 1470 { 1471 FullScreenData *data = (FullScreenData *)m_macFullScreenData ; 1472 delete data ; 1473 data = new FullScreenData() ; 1474 1475 m_macFullScreenData = data ; 1476 data->m_position = GetPosition() ; 1477 data->m_size = GetSize() ; 1478 data->m_wasResizable = MacGetWindowAttributes() & kWindowResizableAttribute ; 1479 1480 if ( style & wxFULLSCREEN_NOMENUBAR ) 1481 HideMenuBar() ; 1482 1483 wxRect client = wxGetClientDisplayRect() ; 1484 1485 int left , top , right , bottom ; 1486 int x, y, w, h ; 1487 1488 x = client.x ; 1489 y = client.y ; 1490 w = client.width ; 1491 h = client.height ; 1492 1493 MacGetContentAreaInset( left , top , right , bottom ) ; 1494 1495 if ( style & wxFULLSCREEN_NOCAPTION ) 1496 { 1497 y -= top ; 1498 h += top ; 1499 } 1500 1501 if ( style & wxFULLSCREEN_NOBORDER ) 1502 { 1503 x -= left ; 1504 w += left + right ; 1505 h += bottom ; 1506 } 1507 1508 if ( style & wxFULLSCREEN_NOTOOLBAR ) 1509 { 1510 // TODO 1511 } 1512 1513 if ( style & wxFULLSCREEN_NOSTATUSBAR ) 1514 { 1515 // TODO 1516 } 1517 1518 SetSize( x , y , w, h ) ; 1519 if ( data->m_wasResizable ) 1520 MacChangeWindowAttributes( kWindowNoAttributes , kWindowResizableAttribute ) ; 1521 } 1522 else if ( m_macFullScreenData != NULL ) 1523 { 1524 ShowMenuBar() ; 1525 FullScreenData *data = (FullScreenData *) m_macFullScreenData ; 1526 if ( data->m_wasResizable ) 1527 MacChangeWindowAttributes( kWindowResizableAttribute , kWindowNoAttributes ) ; 1528 SetPosition( data->m_position ) ; 1529 SetSize( data->m_size ) ; 1530 1531 delete data ; 1532 m_macFullScreenData = NULL ; 1533 } 1534 1535 return false; 1536} 1537 1538bool wxTopLevelWindowMac::IsFullScreen() const 1539{ 1540 return m_macFullScreenData != NULL ; 1541} 1542 1543 1544bool wxTopLevelWindowMac::SetTransparent(wxByte alpha) 1545{ 1546 OSStatus result = SetWindowAlpha((WindowRef)m_macWindow, float(alpha)/255.0); 1547 return result == noErr; 1548} 1549 1550 1551bool wxTopLevelWindowMac::CanSetTransparent() 1552{ 1553 return true; 1554} 1555 1556 1557void wxTopLevelWindowMac::SetExtraStyle(long exStyle) 1558{ 1559 if ( GetExtraStyle() == exStyle ) 1560 return ; 1561 1562 wxTopLevelWindowBase::SetExtraStyle( exStyle ) ; 1563 1564#if TARGET_API_MAC_OSX 1565 if ( m_macWindow != NULL ) 1566 { 1567 bool metal = GetExtraStyle() & wxFRAME_EX_METAL ; 1568 1569 if ( MacGetMetalAppearance() != metal ) 1570 { 1571 if ( MacGetUnifiedAppearance() ) 1572 MacSetUnifiedAppearance( !metal ) ; 1573 1574 MacSetMetalAppearance( metal ) ; 1575 } 1576 } 1577#endif 1578} 1579 1580// TODO: switch to structure bounds - 1581// we are still using coordinates of the content view 1582// 1583void wxTopLevelWindowMac::MacGetContentAreaInset( int &left , int &top , int &right , int &bottom ) 1584{ 1585 Rect content, structure ; 1586 1587 GetWindowBounds( (WindowRef) m_macWindow, kWindowStructureRgn , &structure ) ; 1588 GetWindowBounds( (WindowRef) m_macWindow, kWindowContentRgn , &content ) ; 1589 1590 left = content.left - structure.left ; 1591 top = content.top - structure.top ; 1592 right = structure.right - content.right ; 1593 bottom = structure.bottom - content.bottom ; 1594} 1595 1596void wxTopLevelWindowMac::DoMoveWindow(int x, int y, int width, int height) 1597{ 1598 m_cachedClippedRectValid = false ; 1599 Rect bounds = { y , x , y + height , x + width } ; 1600 verify_noerr(SetWindowBounds( (WindowRef) m_macWindow, kWindowStructureRgn , &bounds )) ; 1601 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified 1602} 1603 1604void wxTopLevelWindowMac::DoGetPosition( int *x, int *y ) const 1605{ 1606 Rect bounds ; 1607 1608 verify_noerr(GetWindowBounds((WindowRef) m_macWindow, kWindowStructureRgn , &bounds )) ; 1609 1610 if (x) 1611 *x = bounds.left ; 1612 if (y) 1613 *y = bounds.top ; 1614} 1615 1616void wxTopLevelWindowMac::DoGetSize( int *width, int *height ) const 1617{ 1618 Rect bounds ; 1619 1620 verify_noerr(GetWindowBounds((WindowRef) m_macWindow, kWindowStructureRgn , &bounds )) ; 1621 1622 if (width) 1623 *width = bounds.right - bounds.left ; 1624 if (height) 1625 *height = bounds.bottom - bounds.top ; 1626} 1627 1628void wxTopLevelWindowMac::DoGetClientSize( int *width, int *height ) const 1629{ 1630 Rect bounds ; 1631 1632 verify_noerr(GetWindowBounds((WindowRef) m_macWindow, kWindowContentRgn , &bounds )) ; 1633 1634 if (width) 1635 *width = bounds.right - bounds.left ; 1636 if (height) 1637 *height = bounds.bottom - bounds.top ; 1638} 1639 1640void wxTopLevelWindowMac::DoCentre(int dir) 1641{ 1642 if ( m_macWindow != 0 ) 1643 wxTopLevelWindowBase::DoCentre(dir); 1644} 1645 1646void wxTopLevelWindowMac::MacSetMetalAppearance( bool set ) 1647{ 1648#if TARGET_API_MAC_OSX 1649 if ( MacGetUnifiedAppearance() ) 1650 MacSetUnifiedAppearance( false ) ; 1651 1652 MacChangeWindowAttributes( set ? kWindowMetalAttribute : kWindowNoAttributes , 1653 set ? kWindowNoAttributes : kWindowMetalAttribute ) ; 1654#endif 1655} 1656 1657bool wxTopLevelWindowMac::MacGetMetalAppearance() const 1658{ 1659#if TARGET_API_MAC_OSX 1660 return MacGetWindowAttributes() & kWindowMetalAttribute ; 1661#else 1662 return false; 1663#endif 1664} 1665 1666void wxTopLevelWindowMac::MacSetUnifiedAppearance( bool set ) 1667{ 1668#if TARGET_API_MAC_OSX 1669 if ( UMAGetSystemVersion() >= 0x1040 ) 1670 { 1671 if ( MacGetMetalAppearance() ) 1672 MacSetMetalAppearance( false ) ; 1673 1674 MacChangeWindowAttributes( set ? kWindowUnifiedTitleAndToolbarAttribute : kWindowNoAttributes , 1675 set ? kWindowNoAttributes : kWindowUnifiedTitleAndToolbarAttribute) ; 1676 1677 // For some reason, Tiger uses white as the background color for this appearance, 1678 // while most apps using it use the typical striped background. Restore that behavior 1679 // for wx. 1680 // TODO: Determine if we need this on Leopard as well. (should be harmless either way, 1681 // though) 1682 SetBackgroundColour( wxSYS_COLOUR_WINDOW ) ; 1683 } 1684#endif 1685} 1686 1687bool wxTopLevelWindowMac::MacGetUnifiedAppearance() const 1688{ 1689#if TARGET_API_MAC_OSX 1690 if ( UMAGetSystemVersion() >= 0x1040 ) 1691 return MacGetWindowAttributes() & kWindowUnifiedTitleAndToolbarAttribute ; 1692 else 1693#endif 1694 return false; 1695} 1696 1697void wxTopLevelWindowMac::MacChangeWindowAttributes( wxUint32 attributesToSet , wxUint32 attributesToClear ) 1698{ 1699 ChangeWindowAttributes( (WindowRef)m_macWindow, attributesToSet, attributesToClear ) ; 1700} 1701 1702wxUint32 wxTopLevelWindowMac::MacGetWindowAttributes() const 1703{ 1704 UInt32 attr = 0 ; 1705 GetWindowAttributes( (WindowRef) m_macWindow, &attr ) ; 1706 1707 return attr ; 1708} 1709 1710void wxTopLevelWindowMac::MacPerformUpdates() 1711{ 1712#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 1713 // for composited windows this also triggers a redraw of all 1714 // invalid views in the window 1715 if ( UMAGetSystemVersion() >= 0x1030 ) 1716 HIWindowFlush((WindowRef) m_macWindow) ; 1717 else 1718#endif 1719 { 1720 // the only way to trigger the redrawing on earlier systems is to call 1721 // ReceiveNextEvent 1722 1723 EventRef currentEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ; 1724 UInt32 currentEventClass = 0 ; 1725 if ( currentEvent != NULL ) 1726 { 1727 currentEventClass = ::GetEventClass( currentEvent ) ; 1728 ::GetEventKind( currentEvent ) ; 1729 } 1730 1731 if ( currentEventClass != kEventClassMenu ) 1732 { 1733 // when tracking a menu, strange redraw errors occur if we flush now, so leave.. 1734 EventRef theEvent; 1735 ReceiveNextEvent( 0 , NULL , kEventDurationNoWait , false , &theEvent ) ; 1736 } 1737 } 1738} 1739 1740// Attracts the users attention to this window if the application is 1741// inactive (should be called when a background event occurs) 1742 1743static pascal void wxMacNMResponse( NMRecPtr ptr ) 1744{ 1745 NMRemove( ptr ) ; 1746 DisposePtr( (Ptr)ptr ) ; 1747} 1748 1749void wxTopLevelWindowMac::RequestUserAttention(int flags ) 1750{ 1751 NMRecPtr notificationRequest = (NMRecPtr) NewPtr( sizeof( NMRec) ) ; 1752 static wxMacNMUPP nmupp( wxMacNMResponse ); 1753 1754 memset( notificationRequest , 0 , sizeof(*notificationRequest) ) ; 1755 notificationRequest->qType = nmType ; 1756 notificationRequest->nmMark = 1 ; 1757 notificationRequest->nmIcon = 0 ; 1758 notificationRequest->nmSound = 0 ; 1759 notificationRequest->nmStr = NULL ; 1760 notificationRequest->nmResp = nmupp ; 1761 1762 verify_noerr( NMInstall( notificationRequest ) ) ; 1763} 1764 1765// --------------------------------------------------------------------------- 1766// Shape implementation 1767// --------------------------------------------------------------------------- 1768 1769 1770bool wxTopLevelWindowMac::SetShape(const wxRegion& region) 1771{ 1772 wxCHECK_MSG( HasFlag(wxFRAME_SHAPED), false, 1773 _T("Shaped windows must be created with the wxFRAME_SHAPED style.")); 1774 1775 // The empty region signifies that the shape 1776 // should be removed from the window. 1777 if ( region.IsEmpty() ) 1778 { 1779 wxSize sz = GetClientSize(); 1780 wxRegion rgn(0, 0, sz.x, sz.y); 1781 if ( rgn.IsEmpty() ) 1782 return false ; 1783 else 1784 return SetShape(rgn); 1785 } 1786 1787 // Make a copy of the region 1788 RgnHandle shapeRegion = NewRgn(); 1789 CopyRgn( (RgnHandle)region.GetWXHRGN(), shapeRegion ); 1790 1791 // Dispose of any shape region we may already have 1792 RgnHandle oldRgn = (RgnHandle)GetWRefCon( (WindowRef)MacGetWindowRef() ); 1793 if ( oldRgn ) 1794 DisposeRgn(oldRgn); 1795 1796 // Save the region so we can use it later 1797 SetWRefCon((WindowRef)MacGetWindowRef(), (URefCon)shapeRegion); 1798 1799 // inform the window manager that the window has changed shape 1800 ReshapeCustomWindow((WindowRef)MacGetWindowRef()); 1801 1802 return true; 1803} 1804 1805// --------------------------------------------------------------------------- 1806// Support functions for shaped windows, based on Apple's CustomWindow sample at 1807// http://developer.apple.com/samplecode/Sample_Code/Human_Interface_Toolbox/Mac_OS_High_Level_Toolbox/CustomWindow.htm 1808// --------------------------------------------------------------------------- 1809 1810static void wxShapedMacWindowGetPos(WindowRef window, Rect* inRect) 1811{ 1812#if 1 1813 // under 10.6 we are getting errors during construction otherwise 1814 ::GetWindowBounds(window, kWindowGlobalPortRgn, inRect); 1815#else 1816 GetWindowPortBounds(window, inRect); 1817 1818 Point pt = { inRect->top ,inRect->left }; 1819 wxMacLocalToGlobal( window, &pt ) ; 1820 inRect->bottom += pt.v - inRect->top; 1821 inRect->right += pt.h - inRect->left; 1822 inRect->top = pt.v; 1823 inRect->left = pt.h; 1824#endif 1825} 1826 1827static SInt32 wxShapedMacWindowGetFeatures(WindowRef window, SInt32 param) 1828{ 1829 /*------------------------------------------------------ 1830 Define which options your custom window supports. 1831 --------------------------------------------------------*/ 1832 //just enable everything for our demo 1833 *(OptionBits*)param = 1834 //kWindowCanGrow | 1835 //kWindowCanZoom | 1836 //kWindowCanCollapse | 1837 //kWindowCanGetWindowRegion | 1838 //kWindowHasTitleBar | 1839 //kWindowSupportsDragHilite | 1840 kWindowCanDrawInCurrentPort | 1841 //kWindowCanMeasureTitle | 1842 kWindowWantsDisposeAtProcessDeath | 1843 kWindowSupportsGetGrowImageRegion | 1844 kWindowDefSupportsColorGrafPort; 1845 1846 return 1; 1847} 1848 1849// The content region is left as a rectangle matching the window size, this is 1850// so the origin in the paint event, and etc. still matches what the 1851// programmer expects. 1852static void wxShapedMacWindowContentRegion(WindowRef window, RgnHandle rgn) 1853{ 1854 SetEmptyRgn(rgn); 1855 wxTopLevelWindowMac* win = wxFindWinFromMacWindow(window); 1856 if (win) 1857 { 1858 Rect windowRect ; 1859 wxShapedMacWindowGetPos( window, &windowRect ) ; 1860#if 1 1861 // the port rectangle of the window may be larger than the window was set, 1862 // therefore we clip at the right and bottom of the shape 1863 RgnHandle cachedRegion = (RgnHandle) GetWRefCon(window); 1864 1865 if (cachedRegion) 1866 { 1867 CopyRgn(cachedRegion, rgn); // make a copy of our cached region 1868 OffsetRgn(rgn, windowRect.left, windowRect.top); // position it over window 1869 Rect r; 1870 GetRegionBounds(rgn,&r); 1871 r.left = windowRect.left; 1872 r.top = windowRect.top; 1873 RectRgn( rgn , &r ) ; 1874 } 1875#else 1876 RectRgn( rgn , &windowRect ) ; 1877#endif 1878 } 1879} 1880 1881// The structure region is set to the shape given to the SetShape method. 1882static void wxShapedMacWindowStructureRegion(WindowRef window, RgnHandle rgn) 1883{ 1884 RgnHandle cachedRegion = (RgnHandle) GetWRefCon(window); 1885 1886 SetEmptyRgn(rgn); 1887 if (cachedRegion) 1888 { 1889 Rect windowRect; 1890 wxShapedMacWindowGetPos(window, &windowRect); // how big is the window 1891 CopyRgn(cachedRegion, rgn); // make a copy of our cached region 1892 OffsetRgn(rgn, windowRect.left, windowRect.top); // position it over window 1893 //MapRgn(rgn, &mMaskSize, &windowRect); //scale it to our actual window size 1894 } 1895} 1896 1897static SInt32 wxShapedMacWindowGetRegion(WindowRef window, SInt32 param) 1898{ 1899 GetWindowRegionPtr rgnRec = (GetWindowRegionPtr)param; 1900 1901 if (rgnRec == NULL) 1902 return paramErr; 1903 1904 switch (rgnRec->regionCode) 1905 { 1906 case kWindowStructureRgn: 1907 wxShapedMacWindowStructureRegion(window, rgnRec->winRgn); 1908 break; 1909 1910 case kWindowContentRgn: 1911 wxShapedMacWindowContentRegion(window, rgnRec->winRgn); 1912 break; 1913 1914 default: 1915 SetEmptyRgn(rgnRec->winRgn); 1916 break; 1917 } 1918 1919 return noErr; 1920} 1921 1922// Determine the region of the window which was hit 1923// 1924static SInt32 wxShapedMacWindowHitTest(WindowRef window, SInt32 param) 1925{ 1926 Point hitPoint; 1927 static RgnHandle tempRgn = NULL; 1928 1929 if (tempRgn == NULL) 1930 tempRgn = NewRgn(); 1931 1932 // get the point clicked 1933 SetPt( &hitPoint, LoWord(param), HiWord(param) ); 1934 1935 // Mac OS 8.5 or later 1936 wxShapedMacWindowStructureRegion(window, tempRgn); 1937 if (PtInRgn( hitPoint, tempRgn )) //in window content region? 1938 return wInContent; 1939 1940 // no significant area was hit 1941 return wNoHit; 1942} 1943 1944static pascal long wxShapedMacWindowDef(short varCode, WindowRef window, SInt16 message, SInt32 param) 1945{ 1946 switch (message) 1947 { 1948 case kWindowMsgHitTest: 1949 return wxShapedMacWindowHitTest(window, param); 1950 1951 case kWindowMsgGetFeatures: 1952 return wxShapedMacWindowGetFeatures(window, param); 1953 1954 // kWindowMsgGetRegion is sent during CreateCustomWindow and ReshapeCustomWindow 1955 case kWindowMsgGetRegion: 1956 return wxShapedMacWindowGetRegion(window, param); 1957 1958 default: 1959 break; 1960 } 1961 1962 return 0; 1963} 1964