1///////////////////////////////////////////////////////////////////////////// 2// Name: src/mac/carbon/window.cpp 3// Purpose: wxWindowMac 4// Author: Stefan Csomor 5// Modified by: 6// Created: 1998-01-01 7// RCS-ID: $Id: window.cpp 62132 2009-09-25 16:15:22Z JS $ 8// Copyright: (c) Stefan Csomor 9// Licence: wxWindows licence 10///////////////////////////////////////////////////////////////////////////// 11 12#include "wx/wxprec.h" 13 14#include "wx/window.h" 15 16#ifndef WX_PRECOMP 17 #include "wx/log.h" 18 #include "wx/app.h" 19 #include "wx/utils.h" 20 #include "wx/panel.h" 21 #include "wx/frame.h" 22 #include "wx/dc.h" 23 #include "wx/dcclient.h" 24 #include "wx/button.h" 25 #include "wx/menu.h" 26 #include "wx/dialog.h" 27 #include "wx/settings.h" 28 #include "wx/msgdlg.h" 29 #include "wx/scrolbar.h" 30 #include "wx/statbox.h" 31 #include "wx/textctrl.h" 32 #include "wx/toolbar.h" 33 #include "wx/layout.h" 34 #include "wx/statusbr.h" 35 #include "wx/menuitem.h" 36 #include "wx/treectrl.h" 37 #include "wx/listctrl.h" 38#endif 39 40#include "wx/tooltip.h" 41#include "wx/spinctrl.h" 42#include "wx/geometry.h" 43 44#if wxUSE_LISTCTRL 45 #include "wx/listctrl.h" 46#endif 47 48#if wxUSE_TREECTRL 49 #include "wx/treectrl.h" 50#endif 51 52#if wxUSE_CARET 53 #include "wx/caret.h" 54#endif 55 56#if wxUSE_POPUPWIN 57 #include "wx/popupwin.h" 58#endif 59 60#if wxUSE_DRAG_AND_DROP 61#include "wx/dnd.h" 62#endif 63 64#include "wx/mac/uma.h" 65 66#define MAC_SCROLLBAR_SIZE 15 67#define MAC_SMALL_SCROLLBAR_SIZE 11 68 69#ifndef __DARWIN__ 70#include <Windows.h> 71#include <ToolUtils.h> 72#include <MacTextEditor.h> 73#endif 74 75#if TARGET_API_MAC_OSX 76#ifndef __HIVIEW__ 77 #include <HIToolbox/HIView.h> 78#endif 79#endif 80 81#include <string.h> 82 83#ifdef __WXUNIVERSAL__ 84 IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase) 85#else 86 IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase) 87#endif 88 89BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase) 90 EVT_NC_PAINT(wxWindowMac::OnNcPaint) 91 EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground) 92#if TARGET_API_MAC_OSX 93 EVT_PAINT(wxWindowMac::OnPaint) 94#endif 95// EVT_SET_FOCUS(wxWindowMac::OnSetFocus) 96// EVT_KILL_FOCUS(wxWindowMac::OnSetFocus) 97 EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent) 98END_EVENT_TABLE() 99 100#define wxMAC_DEBUG_REDRAW 0 101#ifndef wxMAC_DEBUG_REDRAW 102#define wxMAC_DEBUG_REDRAW 0 103#endif 104 105// --------------------------------------------------------------------------- 106// Utility Routines to move between different coordinate systems 107// --------------------------------------------------------------------------- 108 109/* 110 * Right now we have the following setup : 111 * a border that is not part of the native control is always outside the 112 * control's border (otherwise we loose all native intelligence, future ways 113 * may be to have a second embedding control responsible for drawing borders 114 * and backgrounds eventually) 115 * so all this border calculations have to be taken into account when calling 116 * native methods or getting native oriented data 117 * so we have three coordinate systems here 118 * wx client coordinates 119 * wx window coordinates (including window frames) 120 * native coordinates 121 */ 122 123// 124// originating from native control 125// 126 127 128void wxMacNativeToWindow( const wxWindowMac* window , RgnHandle handle ) 129{ 130 OffsetRgn( handle , window->MacGetLeftBorderSize() , window->MacGetTopBorderSize() ) ; 131} 132 133void wxMacNativeToWindow( const wxWindowMac* window , Rect *rect ) 134{ 135 OffsetRect( rect , window->MacGetLeftBorderSize() , window->MacGetTopBorderSize() ) ; 136} 137 138// 139// directed towards native control 140// 141 142void wxMacWindowToNative( const wxWindowMac* window , RgnHandle handle ) 143{ 144 OffsetRgn( handle , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() ); 145} 146 147void wxMacWindowToNative( const wxWindowMac* window , Rect *rect ) 148{ 149 OffsetRect( rect , -window->MacGetLeftBorderSize() , -window->MacGetTopBorderSize() ) ; 150} 151 152// --------------------------------------------------------------------------- 153// Carbon Events 154// --------------------------------------------------------------------------- 155 156#if TARGET_API_MAC_OSX 157 158#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3 159enum 160{ 161 kEventControlVisibilityChanged = 157 162}; 163#endif 164 165#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 166enum { 167 kEventControlFocusPartChanged = 164 168}; 169#endif 170 171#endif 172 173static const EventTypeSpec eventList[] = 174{ 175 { kEventClassCommand, kEventProcessCommand } , 176 { kEventClassCommand, kEventCommandUpdateStatus } , 177 178 { kEventClassControl , kEventControlGetClickActivation } , 179 { kEventClassControl , kEventControlHit } , 180 181 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } , 182 { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } , 183 184 { kEventClassControl , kEventControlDraw } , 185#if TARGET_API_MAC_OSX 186 { kEventClassControl , kEventControlVisibilityChanged } , 187 { kEventClassControl , kEventControlEnabledStateChanged } , 188 { kEventClassControl , kEventControlHiliteChanged } , 189 190 { kEventClassControl , kEventControlActivate } , 191 { kEventClassControl , kEventControlDeactivate } , 192#endif 193 { kEventClassControl , kEventControlSetFocusPart } , 194 { kEventClassControl , kEventControlFocusPartChanged } , 195 196 { kEventClassService , kEventServiceGetTypes }, 197 { kEventClassService , kEventServiceCopy }, 198 { kEventClassService , kEventServicePaste }, 199 200// { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only 201// { kEventClassControl , kEventControlBoundsChanged } , 202} ; 203 204static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) 205{ 206 OSStatus result = eventNotHandledErr ; 207 208 wxMacCarbonEvent cEvent( event ) ; 209 210 ControlRef controlRef ; 211 wxWindowMac* thisWindow = (wxWindowMac*) data ; 212 213 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ; 214 215 switch ( GetEventKind( event ) ) 216 { 217#if TARGET_API_MAC_OSX 218 case kEventControlDraw : 219 { 220 RgnHandle updateRgn = NULL ; 221 RgnHandle allocatedRgn = NULL ; 222 wxRegion visRegion = thisWindow->MacGetVisibleRegion() ; 223 224 if ( cEvent.GetParameter<RgnHandle>(kEventParamRgnHandle, &updateRgn) != noErr ) 225 { 226 updateRgn = (RgnHandle) visRegion.GetWXHRGN() ; 227 } 228 else 229 { 230 if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 ) 231 { 232 // as this update region is in native window locals we must adapt it to wx window local 233 allocatedRgn = NewRgn() ; 234 CopyRgn( updateRgn , allocatedRgn ) ; 235 236 // hide the given region by the new region that must be shifted 237 wxMacNativeToWindow( thisWindow , allocatedRgn ) ; 238 updateRgn = allocatedRgn ; 239 } 240 } 241 242 Rect rgnBounds ; 243 GetRegionBounds( updateRgn , &rgnBounds ) ; 244 245#if wxMAC_DEBUG_REDRAW 246 if ( thisWindow->MacIsUserPane() ) 247 { 248 static float color = 0.5 ; 249 static channel = 0 ; 250 HIRect bounds; 251 CGContextRef cgContext = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef) ; 252 253 HIViewGetBounds( controlRef, &bounds ); 254 CGContextSetRGBFillColor( cgContext, channel == 0 ? color : 0.5 , 255 channel == 1 ? color : 0.5 , channel == 2 ? color : 0.5 , 1 ); 256 CGContextFillRect( cgContext, bounds ); 257 color += 0.1 ; 258 if ( color > 0.9 ) 259 { 260 color = 0.5 ; 261 channel++ ; 262 if ( channel == 3 ) 263 channel = 0 ; 264 } 265 } 266#endif 267 268 { 269#if wxMAC_USE_CORE_GRAPHICS 270 bool created = false ; 271 CGContextRef cgContext = NULL ; 272 OSStatus err = cEvent.GetParameter<CGContextRef>(kEventParamCGContextRef, &cgContext) ; 273 wxASSERT_MSG( err == noErr , wxT("Unable to retrieve CGContextRef") ) ; 274 thisWindow->MacSetCGContextRef( cgContext ) ; 275 276 { 277 wxMacCGContextStateSaver sg( cgContext ) ; 278 float alpha = 1.0 ; 279 { 280 wxWindowMac* iter = thisWindow ; 281 while ( iter ) 282 { 283 alpha *= (float) iter->GetTransparent()/255.0 ; 284 if ( iter->IsTopLevel() ) 285 iter = NULL ; 286 else 287 iter = iter->GetParent() ; 288 } 289 } 290 CGContextSetAlpha( cgContext , alpha ) ; 291#endif 292 if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) ) 293 result = noErr ; 294 295#if wxMAC_USE_CORE_GRAPHICS 296 thisWindow->MacSetCGContextRef( NULL ) ; 297 } 298 299 if ( created ) 300 CGContextRelease( cgContext ) ; 301#endif 302 } 303 304 if ( allocatedRgn ) 305 DisposeRgn( allocatedRgn ) ; 306 } 307 break ; 308 309 case kEventControlVisibilityChanged : 310 thisWindow->MacVisibilityChanged() ; 311 break ; 312 313 case kEventControlEnabledStateChanged : 314 thisWindow->MacEnabledStateChanged() ; 315 break ; 316 317 case kEventControlHiliteChanged : 318 thisWindow->MacHiliteChanged() ; 319 break ; 320 321 case kEventControlActivate : 322 case kEventControlDeactivate : 323 // FIXME: we should have a virtual function for this! 324#if wxUSE_TREECTRL 325 if ( thisWindow->IsKindOf( CLASSINFO( wxTreeCtrl ) ) ) 326 thisWindow->Refresh(); 327#endif 328#if wxUSE_LISTCTRL 329 if ( thisWindow->IsKindOf( CLASSINFO( wxListCtrl ) ) ) 330 thisWindow->Refresh(); 331#endif 332 break ; 333#endif // TARGET_API_MAC_OSX 334 335 // 336 // focus handling 337 // different handling on OS X 338 // 339 340 case kEventControlFocusPartChanged : 341 // the event is emulated by wxmac for systems lower than 10.5 342 { 343 ControlPartCode previousControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPreviousPart , typeControlPartCode ); 344 ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlCurrentPart , typeControlPartCode ); 345 if ( currentControlPart == 0 ) 346 { 347 if ( thisWindow->IsBeingDeleted() == false ) 348 { 349 // kill focus 350#if wxUSE_CARET 351 if ( thisWindow->GetCaret() ) 352 thisWindow->GetCaret()->OnKillFocus(); 353#endif 354 355 wxLogTrace(_T("focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow)); 356 357 // remove this as soon as posting the synthesized event works properly 358 static bool inKillFocusEvent = false ; 359 360 if ( !inKillFocusEvent ) 361 { 362 inKillFocusEvent = true ; 363 wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId()); 364 event.SetEventObject(thisWindow); 365 // Call this function before sending the event, in case the window is destroyed. 366 thisWindow->wxWindowMac::OnSetFocus(event); 367 thisWindow->GetEventHandler()->ProcessEvent(event) ; 368 inKillFocusEvent = false ; 369 } 370 } 371 } 372 else if ( previousControlPart == 0 ) 373 { 374 if ( thisWindow->IsBeingDeleted() == false ) 375 { 376 // set focus 377 // panel wants to track the window which was the last to have focus in it 378 wxLogTrace(_T("focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow)); 379 wxChildFocusEvent eventFocus((wxWindow*)thisWindow); 380 thisWindow->GetEventHandler()->ProcessEvent(eventFocus); 381 382#if wxUSE_CARET 383 if ( thisWindow->GetCaret() ) 384 thisWindow->GetCaret()->OnSetFocus(); 385#endif 386 387 wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId()); 388 event.SetEventObject(thisWindow); 389 thisWindow->GetEventHandler()->ProcessEvent(event) ; 390 thisWindow->wxWindowMac::OnSetFocus(event); 391 } 392 } 393 } 394 break; 395 case kEventControlSetFocusPart : 396 { 397#ifdef __WXMAC_OSX__ 398 Boolean focusEverything = false ; 399 if ( cEvent.GetParameter<Boolean>(kEventParamControlFocusEverything , &focusEverything ) == noErr ) 400 { 401 // put a breakpoint here to catch focus everything events 402 } 403#endif 404 ControlPartCode controlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode ); 405 406 ControlPartCode previousControlPart = 0; 407 verify_noerr( HIViewGetFocusPart(controlRef, &previousControlPart)); 408 409 if ( thisWindow->MacIsUserPane() ) 410 { 411 if ( controlPart != kControlFocusNoPart ) 412 cEvent.SetParameter<ControlPartCode>( kEventParamControlPart, typeControlPartCode, 1 ) ; 413 result = noErr ; 414 } 415 else 416 result = CallNextEventHandler(handler, event); 417 418 if ( UMAGetSystemVersion() < 0x1050 ) 419 { 420// set back to 0 if problems arise 421#if 1 422 ControlPartCode currentControlPart = cEvent.GetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode ); 423 // synthesize the event focus changed event 424 EventRef evRef = NULL ; 425 426 OSStatus err = MacCreateEvent( 427 NULL , kEventClassControl , kEventControlFocusPartChanged , TicksToEventTime( TickCount() ) , 428 kEventAttributeUserEvent , &evRef ); 429 verify_noerr( err ); 430 431 wxMacCarbonEvent iEvent( evRef ) ; 432 iEvent.SetParameter<ControlRef>( kEventParamDirectObject , controlRef ) ; 433 iEvent.SetParameter<ControlPartCode>( kEventParamControlPreviousPart, typeControlPartCode, previousControlPart ) ; 434 iEvent.SetParameter<ControlPartCode>( kEventParamControlCurrentPart, typeControlPartCode, currentControlPart ) ; 435 436#if 0 437 // TODO test this first, avoid double posts etc... 438 PostEventToQueue( GetMainEventQueue(), evRef , kEventPriorityHigh ); 439#else 440 wxMacWindowControlEventHandler( NULL , evRef , data ) ; 441#endif 442 ReleaseEvent( evRef ) ; 443#else 444 // old implementation, to be removed if the new one works 445 if ( controlPart == kControlFocusNoPart ) 446 { 447#if wxUSE_CARET 448 if ( thisWindow->GetCaret() ) 449 thisWindow->GetCaret()->OnKillFocus(); 450#endif 451 452 wxLogTrace(_T("focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow)); 453 454 static bool inKillFocusEvent = false ; 455 456 if ( !inKillFocusEvent ) 457 { 458 inKillFocusEvent = true ; 459 wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId()); 460 event.SetEventObject(thisWindow); 461 thisWindow->GetEventHandler()->ProcessEvent(event) ; 462 inKillFocusEvent = false ; 463 } 464 } 465 else 466 { 467 // panel wants to track the window which was the last to have focus in it 468 wxLogTrace(_T("focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow)); 469 wxChildFocusEvent eventFocus((wxWindow*)thisWindow); 470 thisWindow->GetEventHandler()->ProcessEvent(eventFocus); 471 472 #if wxUSE_CARET 473 if ( thisWindow->GetCaret() ) 474 thisWindow->GetCaret()->OnSetFocus(); 475 #endif 476 477 wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId()); 478 event.SetEventObject(thisWindow); 479 thisWindow->GetEventHandler()->ProcessEvent(event) ; 480 } 481#endif 482 } 483 } 484 break ; 485 486 case kEventControlHit : 487 result = thisWindow->MacControlHit( handler , event ) ; 488 break ; 489 490 case kEventControlGetClickActivation : 491 { 492 // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise) 493 WindowRef owner = cEvent.GetParameter<WindowRef>(kEventParamWindowRef); 494 if ( !IsWindowActive(owner) ) 495 { 496 cEvent.SetParameter(kEventParamClickActivation,typeClickActivationResult, (UInt32) kActivateAndIgnoreClick) ; 497 result = noErr ; 498 } 499 } 500 break ; 501 502 default : 503 break ; 504 } 505 506 return result ; 507} 508 509static pascal OSStatus wxMacWindowServiceEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) 510{ 511 OSStatus result = eventNotHandledErr ; 512 513 wxMacCarbonEvent cEvent( event ) ; 514 515 ControlRef controlRef ; 516 wxWindowMac* thisWindow = (wxWindowMac*) data ; 517 wxTextCtrl* textCtrl = wxDynamicCast( thisWindow , wxTextCtrl ) ; 518 cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ; 519 520 switch ( GetEventKind( event ) ) 521 { 522 case kEventServiceGetTypes : 523 if ( textCtrl ) 524 { 525 long from, to ; 526 textCtrl->GetSelection( &from , &to ) ; 527 528 CFMutableArrayRef copyTypes = 0 , pasteTypes = 0; 529 if ( from != to ) 530 copyTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServiceCopyTypes , typeCFMutableArrayRef ) ; 531 if ( textCtrl->IsEditable() ) 532 pasteTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServicePasteTypes , typeCFMutableArrayRef ) ; 533 534 static const OSType textDataTypes[] = { kTXNTextData /* , 'utxt', 'PICT', 'MooV', 'AIFF' */ }; 535 for ( size_t i = 0 ; i < WXSIZEOF(textDataTypes) ; ++i ) 536 { 537 CFStringRef typestring = CreateTypeStringWithOSType(textDataTypes[i]); 538 if ( typestring ) 539 { 540 if ( copyTypes ) 541 CFArrayAppendValue(copyTypes, typestring) ; 542 if ( pasteTypes ) 543 CFArrayAppendValue(pasteTypes, typestring) ; 544 545 CFRelease( typestring ) ; 546 } 547 } 548 549 result = noErr ; 550 } 551 break ; 552 553 case kEventServiceCopy : 554 if ( textCtrl ) 555 { 556 long from, to ; 557 558 textCtrl->GetSelection( &from , &to ) ; 559 wxString val = textCtrl->GetValue() ; 560 val = val.Mid( from , to - from ) ; 561 PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef ); 562 verify_noerr( PasteboardClear( pasteboard ) ) ; 563 PasteboardSynchronize( pasteboard ); 564 CFDataRef data = CFDataCreate( kCFAllocatorDefault, (UInt8*)val.c_str(), val.length() ); 565 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) 1, CFSTR("com.apple.traditional-mac-plain-text"), data, 0); 566 CFRelease( data ); 567 result = noErr ; 568 } 569 break ; 570 571 case kEventServicePaste : 572 if ( textCtrl ) 573 { 574 PasteboardRef pasteboard = cEvent.GetParameter<PasteboardRef>( kEventParamPasteboardRef, typePasteboardRef ); 575 PasteboardSynchronize( pasteboard ); 576 ItemCount itemCount; 577 verify_noerr( PasteboardGetItemCount( pasteboard, &itemCount ) ); 578 for( UInt32 itemIndex = 1; itemIndex <= itemCount; itemIndex++ ) 579 { 580 PasteboardItemID itemID; 581 if ( PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID ) == noErr ) 582 { 583 CFDataRef flavorData = NULL; 584 if ( PasteboardCopyItemFlavorData( pasteboard, itemID, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData ) == noErr ) 585 { 586 CFIndex flavorDataSize = CFDataGetLength( flavorData ); 587 char *content = new char[flavorDataSize+1] ; 588 memcpy( content, CFDataGetBytePtr( flavorData ), flavorDataSize ); 589 content[flavorDataSize]=0; 590 CFRelease( flavorData ); 591#if wxUSE_UNICODE 592 textCtrl->WriteText( wxString( content , wxConvLocal ) ); 593#else 594 textCtrl->WriteText( wxString( content ) ) ; 595#endif 596 597 delete[] content ; 598 result = noErr ; 599 } 600 } 601 } 602 } 603 break ; 604 605 default: 606 break ; 607 } 608 609 return result ; 610} 611 612pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) 613{ 614 OSStatus result = eventNotHandledErr ; 615 wxWindowMac* focus = (wxWindowMac*) data ; 616 617 wchar_t* uniChars = NULL ; 618 UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ; 619 620 UniChar* charBuf = NULL; 621 ByteCount dataSize = 0 ; 622 int numChars = 0 ; 623 UniChar buf[2] ; 624 if ( GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr ) 625 { 626 numChars = dataSize / sizeof( UniChar) + 1; 627 charBuf = buf ; 628 629 if ( (size_t) numChars * 2 > sizeof(buf) ) 630 charBuf = new UniChar[ numChars ] ; 631 else 632 charBuf = buf ; 633 634 uniChars = new wchar_t[ numChars ] ; 635 GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ; 636 charBuf[ numChars - 1 ] = 0; 637#if SIZEOF_WCHAR_T == 2 638 uniChars = (wchar_t*) charBuf ; 639/* memcpy( uniChars , charBuf , numChars * 2 ) ;*/ // is there any point in copying charBuf over itself? (in fact, memcpy isn't even guaranteed to work correctly if the source and destination ranges overlap...) 640#else 641 // the resulting string will never have more chars than the utf16 version, so this is safe 642 wxMBConvUTF16 converter ; 643 numChars = converter.MB2WC( uniChars , (const char*)charBuf , numChars ) ; 644#endif 645 } 646 647 switch ( GetEventKind( event ) ) 648 { 649 case kEventTextInputUpdateActiveInputArea : 650 { 651 // An IME input event may return several characters, but we need to send one char at a time to 652 // EVT_CHAR 653 for (int pos=0 ; pos < numChars ; pos++) 654 { 655 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ; 656 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ; 657 wxTheApp->MacSetCurrentEvent( event , handler ) ; 658 659 UInt32 message = uniChars[pos] < 128 ? (char)uniChars[pos] : '?'; 660/* 661 NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent 662 multiple times to update the active range during inline input, so this handler will often receive 663 uncommited text, which should usually not trigger side effects. It might be a good idea to check the 664 kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h). 665 On the other hand, it can be useful for some applications to react to uncommitted text (for example, 666 to update a status display), as long as it does not disrupt the inline input session. Ideally, wx 667 should add new event types to support advanced text input. For now, I would keep things as they are. 668 669 However, the code that was being used caused additional problems: 670 UInt32 message = (0 << 8) + ((char)uniChars[pos] ); 671 Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline 672 input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji 673 for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB 674 (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D 675 (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress. 676 Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only 677 overlap with Unicode within the (7-bit) ASCII range. 678 But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks 679 for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII 680 characters as they are and replaces the rest with '?', ensuring that update events are triggered. 681 It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but 682 I don't have time to look into that right now. 683 -- CL 684*/ 685 if ( wxTheApp->MacSendCharEvent((wxWindow*) 686 focus , message , 0 , when , 0 , 0 , uniChars[pos] ) ) 687 { 688 result = noErr ; 689 } 690 691 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ; 692 } 693 } 694 break ; 695 case kEventTextInputUnicodeForKeyEvent : 696 { 697 UInt32 keyCode, modifiers ; 698 Point point ; 699 EventRef rawEvent ; 700 unsigned char charCode ; 701 702 GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ; 703 GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode ); 704 GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode ); 705 GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers ); 706 GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point ); 707 708 UInt32 message = (keyCode << 8) + charCode; 709 710 // An IME input event may return several characters, but we need to send one char at a time to 711 // EVT_CHAR 712 for (int pos=0 ; pos < numChars ; pos++) 713 { 714 WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ; 715 WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ; 716 wxTheApp->MacSetCurrentEvent( event , handler ) ; 717 718 if ( wxTheApp->MacSendCharEvent((wxWindow*) 719 focus , message , modifiers , when , point.h , point.v , uniChars[pos] ) ) 720 { 721 result = noErr ; 722 } 723 724 wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ; 725 } 726 } 727 break; 728 default: 729 break ; 730 } 731 732 delete [] uniChars ; 733 if ( charBuf != buf ) 734 delete [] charBuf ; 735 736 return result ; 737} 738 739static pascal OSStatus wxMacWindowCommandEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) 740{ 741 OSStatus result = eventNotHandledErr ; 742 wxWindowMac* focus = (wxWindowMac*) data ; 743 744 HICommand command ; 745 746 wxMacCarbonEvent cEvent( event ) ; 747 cEvent.GetParameter<HICommand>(kEventParamDirectObject,typeHICommand,&command) ; 748 749 wxMenuItem* item = NULL ; 750 wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ; 751 int id = wxMacCommandToId( command.commandID ) ; 752 753 if ( item ) 754 { 755 wxASSERT( itemMenu != NULL ) ; 756 757 switch ( cEvent.GetKind() ) 758 { 759 case kEventProcessCommand : 760 result = itemMenu->MacHandleCommandProcess( item, id, focus ); 761 break ; 762 763 case kEventCommandUpdateStatus: 764 result = itemMenu->MacHandleCommandUpdateStatus( item, id, focus ); 765 break ; 766 767 default : 768 break ; 769 } 770 } 771 return result ; 772} 773 774pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) 775{ 776 EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ; 777 EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ; 778 wxTheApp->MacSetCurrentEvent( event , handler ) ; 779 OSStatus result = eventNotHandledErr ; 780 781 switch ( GetEventClass( event ) ) 782 { 783 case kEventClassCommand : 784 result = wxMacWindowCommandEventHandler( handler , event , data ) ; 785 break ; 786 787 case kEventClassControl : 788 result = wxMacWindowControlEventHandler( handler, event, data ) ; 789 break ; 790 791 case kEventClassService : 792 result = wxMacWindowServiceEventHandler( handler, event , data ) ; 793 break ; 794 795 case kEventClassTextInput : 796 result = wxMacUnicodeTextEventHandler( handler , event , data ) ; 797 break ; 798 799 default : 800 break ; 801 } 802 803 wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ; 804 805 return result ; 806} 807 808DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler ) 809 810#if !TARGET_API_MAC_OSX 811 812// --------------------------------------------------------------------------- 813// UserPane events for non OSX builds 814// --------------------------------------------------------------------------- 815 816static pascal void wxMacControlUserPaneDrawProc(ControlRef control, SInt16 part) 817{ 818 wxWindow * win = wxFindControlFromMacControl(control) ; 819 if ( win ) 820 win->MacControlUserPaneDrawProc(part) ; 821} 822wxMAC_DEFINE_PROC_GETTER( ControlUserPaneDrawUPP , wxMacControlUserPaneDrawProc ) ; 823 824static pascal ControlPartCode wxMacControlUserPaneHitTestProc(ControlRef control, Point where) 825{ 826 wxWindow * win = wxFindControlFromMacControl(control) ; 827 if ( win ) 828 return win->MacControlUserPaneHitTestProc(where.h , where.v) ; 829 else 830 return kControlNoPart ; 831} 832wxMAC_DEFINE_PROC_GETTER( ControlUserPaneHitTestUPP , wxMacControlUserPaneHitTestProc ) ; 833 834static pascal ControlPartCode wxMacControlUserPaneTrackingProc(ControlRef control, Point startPt, ControlActionUPP actionProc) 835{ 836 wxWindow * win = wxFindControlFromMacControl(control) ; 837 if ( win ) 838 return win->MacControlUserPaneTrackingProc( startPt.h , startPt.v , (void*) actionProc) ; 839 else 840 return kControlNoPart ; 841} 842wxMAC_DEFINE_PROC_GETTER( ControlUserPaneTrackingUPP , wxMacControlUserPaneTrackingProc ) ; 843 844static pascal void wxMacControlUserPaneIdleProc(ControlRef control) 845{ 846 wxWindow * win = wxFindControlFromMacControl(control) ; 847 if ( win ) 848 win->MacControlUserPaneIdleProc() ; 849} 850wxMAC_DEFINE_PROC_GETTER( ControlUserPaneIdleUPP , wxMacControlUserPaneIdleProc ) ; 851 852static pascal ControlPartCode wxMacControlUserPaneKeyDownProc(ControlRef control, SInt16 keyCode, SInt16 charCode, SInt16 modifiers) 853{ 854 wxWindow * win = wxFindControlFromMacControl(control) ; 855 if ( win ) 856 return win->MacControlUserPaneKeyDownProc(keyCode,charCode,modifiers) ; 857 else 858 return kControlNoPart ; 859} 860wxMAC_DEFINE_PROC_GETTER( ControlUserPaneKeyDownUPP , wxMacControlUserPaneKeyDownProc ) ; 861 862static pascal void wxMacControlUserPaneActivateProc(ControlRef control, Boolean activating) 863{ 864 wxWindow * win = wxFindControlFromMacControl(control) ; 865 if ( win ) 866 win->MacControlUserPaneActivateProc(activating) ; 867} 868wxMAC_DEFINE_PROC_GETTER( ControlUserPaneActivateUPP , wxMacControlUserPaneActivateProc ) ; 869 870static pascal ControlPartCode wxMacControlUserPaneFocusProc(ControlRef control, ControlFocusPart action) 871{ 872 wxWindow * win = wxFindControlFromMacControl(control) ; 873 if ( win ) 874 return win->MacControlUserPaneFocusProc(action) ; 875 else 876 return kControlNoPart ; 877} 878wxMAC_DEFINE_PROC_GETTER( ControlUserPaneFocusUPP , wxMacControlUserPaneFocusProc ) ; 879 880static pascal void wxMacControlUserPaneBackgroundProc(ControlRef control, ControlBackgroundPtr info) 881{ 882 wxWindow * win = wxFindControlFromMacControl(control) ; 883 if ( win ) 884 win->MacControlUserPaneBackgroundProc(info) ; 885} 886wxMAC_DEFINE_PROC_GETTER( ControlUserPaneBackgroundUPP , wxMacControlUserPaneBackgroundProc ) ; 887 888void wxWindowMac::MacControlUserPaneDrawProc(wxInt16 part) 889{ 890 int x = 0 , y = 0; 891 RgnHandle rgn = NewRgn() ; 892 GetClip( rgn ) ; 893 MacWindowToRootWindow( &x, &y ) ; 894 OffsetRgn( rgn , -x , -y ) ; 895 wxMacWindowStateSaver sv( this ) ; 896 SectRgn( rgn , (RgnHandle) MacGetVisibleRegion().GetWXHRGN() , rgn ) ; 897 MacDoRedraw( rgn , 0 ) ; 898 DisposeRgn( rgn ) ; 899} 900 901wxInt16 wxWindowMac::MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y) 902{ 903 return kControlNoPart ; 904} 905 906wxInt16 wxWindowMac::MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc) 907{ 908 return kControlNoPart ; 909} 910 911void wxWindowMac::MacControlUserPaneIdleProc() 912{ 913} 914 915wxInt16 wxWindowMac::MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers) 916{ 917 return kControlNoPart ; 918} 919 920void wxWindowMac::MacControlUserPaneActivateProc(bool activating) 921{ 922} 923 924wxInt16 wxWindowMac::MacControlUserPaneFocusProc(wxInt16 action) 925{ 926 if ( AcceptsFocus() ) 927 return 1 ; 928 else 929 return kControlNoPart ; 930} 931 932void wxWindowMac::MacControlUserPaneBackgroundProc(void* info) 933{ 934} 935 936#endif 937 938// --------------------------------------------------------------------------- 939// Scrollbar Tracking for all 940// --------------------------------------------------------------------------- 941 942pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode ) ; 943pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode partCode ) 944{ 945 if ( partCode != 0) 946 { 947 wxWindowMac* wx = wxFindControlFromMacControl( control ) ; 948 if ( wx ) 949 wx->MacHandleControlClick( (WXWidget) control , partCode , true /* stillDown */ ) ; 950 } 951} 952wxMAC_DEFINE_PROC_GETTER( ControlActionUPP , wxMacLiveScrollbarActionProc ) ; 953 954// =========================================================================== 955// implementation 956// =========================================================================== 957 958// note that we are now guarding against m_peer being NULL which happens if the real class used 959// is a wxMenuBar, as in wx inheritance this also is a wxWindow 960 961WX_DECLARE_HASH_MAP(ControlRef, wxWindowMac*, wxPointerHash, wxPointerEqual, MacControlMap); 962 963static MacControlMap wxWinMacControlList; 964 965wxWindowMac *wxFindControlFromMacControl(ControlRef inControl ) 966{ 967 MacControlMap::iterator node = wxWinMacControlList.find(inControl); 968 969 return (node == wxWinMacControlList.end()) ? NULL : node->second; 970} 971 972void wxAssociateControlWithMacControl(ControlRef inControl, wxWindowMac *control) 973{ 974 // adding NULL ControlRef is (first) surely a result of an error and 975 // (secondly) breaks native event processing 976 wxCHECK_RET( inControl != (ControlRef) NULL, wxT("attempt to add a NULL WindowRef to window list") ); 977 978 wxWinMacControlList[inControl] = control; 979} 980 981void wxRemoveMacControlAssociation(wxWindowMac *control) 982{ 983 // iterate over all the elements in the class 984 // is the iterator stable ? as we might have two associations pointing to the same wxWindow 985 // we should go on... 986 987 bool found = true ; 988 while ( found ) 989 { 990 found = false ; 991 MacControlMap::iterator it; 992 for ( it = wxWinMacControlList.begin(); it != wxWinMacControlList.end(); ++it ) 993 { 994 if ( it->second == control ) 995 { 996 wxWinMacControlList.erase(it); 997 found = true ; 998 break; 999 } 1000 } 1001 } 1002} 1003 1004// ---------------------------------------------------------------------------- 1005 // constructors and such 1006// ---------------------------------------------------------------------------- 1007 1008wxWindowMac::wxWindowMac() 1009{ 1010 Init(); 1011} 1012 1013wxWindowMac::wxWindowMac(wxWindowMac *parent, 1014 wxWindowID id, 1015 const wxPoint& pos , 1016 const wxSize& size , 1017 long style , 1018 const wxString& name ) 1019{ 1020 Init(); 1021 Create(parent, id, pos, size, style, name); 1022} 1023 1024void wxWindowMac::Init() 1025{ 1026 m_peer = NULL ; 1027 m_frozenness = 0 ; 1028 m_macAlpha = 255 ; 1029 1030#if WXWIN_COMPATIBILITY_2_4 1031 m_backgroundTransparent = false; 1032#endif 1033 1034#if wxMAC_USE_CORE_GRAPHICS 1035 m_cgContextRef = NULL ; 1036#endif 1037 1038 // as all windows are created with WS_VISIBLE style... 1039 m_isShown = true; 1040 1041 m_hScrollBar = NULL ; 1042 m_vScrollBar = NULL ; 1043 m_macBackgroundBrush = wxNullBrush ; 1044 1045 m_macIsUserPane = true; 1046 m_clipChildren = false ; 1047 m_cachedClippedRectValid = false ; 1048} 1049 1050wxWindowMac::~wxWindowMac() 1051{ 1052 SendDestroyEvent(); 1053 1054 m_isBeingDeleted = true; 1055 1056 MacInvalidateBorders() ; 1057 1058#ifndef __WXUNIVERSAL__ 1059 // VS: make sure there's no wxFrame with last focus set to us: 1060 for ( wxWindow *win = GetParent(); win; win = win->GetParent() ) 1061 { 1062 wxFrame *frame = wxDynamicCast(win, wxFrame); 1063 if ( frame ) 1064 { 1065 if ( frame->GetLastFocus() == this ) 1066 frame->SetLastFocus((wxWindow*)NULL); 1067 break; 1068 } 1069 } 1070#endif 1071 1072 // destroy children before destroying this window itself 1073 DestroyChildren(); 1074 1075 // wxRemoveMacControlAssociation( this ) ; 1076 // If we delete an item, we should initialize the parent panel, 1077 // because it could now be invalid. 1078 wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent((wxWindow*)this), wxTopLevelWindow); 1079 if ( tlw ) 1080 { 1081 if ( tlw->GetDefaultItem() == (wxButton*) this) 1082 tlw->SetDefaultItem(NULL); 1083 } 1084 1085 if ( m_peer && m_peer->Ok() ) 1086 { 1087 // in case the callback might be called during destruction 1088 wxRemoveMacControlAssociation( this) ; 1089 ::RemoveEventHandler( (EventHandlerRef ) m_macControlEventHandler ) ; 1090 // we currently are not using this hook 1091 // ::SetControlColorProc( *m_peer , NULL ) ; 1092 m_peer->Dispose() ; 1093 } 1094 1095 if ( g_MacLastWindow == this ) 1096 g_MacLastWindow = NULL ; 1097 1098#ifndef __WXUNIVERSAL__ 1099 wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( (wxWindow*)this ) , wxFrame ) ; 1100 if ( frame ) 1101 { 1102 if ( frame->GetLastFocus() == this ) 1103 frame->SetLastFocus( NULL ) ; 1104 } 1105#endif 1106 1107 // delete our drop target if we've got one 1108#if wxUSE_DRAG_AND_DROP 1109 if ( m_dropTarget != NULL ) 1110 { 1111 delete m_dropTarget; 1112 m_dropTarget = NULL; 1113 } 1114#endif 1115 1116 delete m_peer ; 1117} 1118 1119WXWidget wxWindowMac::GetHandle() const 1120{ 1121 if( m_peer ) 1122 return (WXWidget) m_peer->GetControlRef() ; 1123 else 1124 return NULL; 1125} 1126 1127void wxWindowMac::MacInstallEventHandler( WXWidget control ) 1128{ 1129 wxAssociateControlWithMacControl( (ControlRef) control , this ) ; 1130 InstallControlEventHandler( (ControlRef)control , GetwxMacWindowEventHandlerUPP(), 1131 GetEventTypeCount(eventList), eventList, this, 1132 (EventHandlerRef *)&m_macControlEventHandler); 1133 1134#if !TARGET_API_MAC_OSX 1135 if ( (ControlRef) control == m_peer->GetControlRef() ) 1136 { 1137 m_peer->SetData<ControlUserPaneDrawUPP>(kControlEntireControl, kControlUserPaneDrawProcTag, GetwxMacControlUserPaneDrawProc()) ; 1138 m_peer->SetData<ControlUserPaneHitTestUPP>(kControlEntireControl, kControlUserPaneHitTestProcTag, GetwxMacControlUserPaneHitTestProc()) ; 1139 m_peer->SetData<ControlUserPaneTrackingUPP>(kControlEntireControl, kControlUserPaneTrackingProcTag, GetwxMacControlUserPaneTrackingProc()) ; 1140 m_peer->SetData<ControlUserPaneIdleUPP>(kControlEntireControl, kControlUserPaneIdleProcTag, GetwxMacControlUserPaneIdleProc()) ; 1141 m_peer->SetData<ControlUserPaneKeyDownUPP>(kControlEntireControl, kControlUserPaneKeyDownProcTag, GetwxMacControlUserPaneKeyDownProc()) ; 1142 m_peer->SetData<ControlUserPaneActivateUPP>(kControlEntireControl, kControlUserPaneActivateProcTag, GetwxMacControlUserPaneActivateProc()) ; 1143 m_peer->SetData<ControlUserPaneFocusUPP>(kControlEntireControl, kControlUserPaneFocusProcTag, GetwxMacControlUserPaneFocusProc()) ; 1144 m_peer->SetData<ControlUserPaneBackgroundUPP>(kControlEntireControl, kControlUserPaneBackgroundProcTag, GetwxMacControlUserPaneBackgroundProc()) ; 1145 } 1146#endif 1147} 1148 1149// Constructor 1150bool wxWindowMac::Create(wxWindowMac *parent, 1151 wxWindowID id, 1152 const wxPoint& pos, 1153 const wxSize& size, 1154 long style, 1155 const wxString& name) 1156{ 1157 wxCHECK_MSG( parent, false, wxT("can't create wxWindowMac without parent") ); 1158 1159 if ( !CreateBase(parent, id, pos, size, style, wxDefaultValidator, name) ) 1160 return false; 1161 1162 m_windowVariant = parent->GetWindowVariant() ; 1163 1164 if ( m_macIsUserPane ) 1165 { 1166 Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ; 1167 1168 UInt32 features = 0 1169 | kControlSupportsEmbedding 1170 | kControlSupportsLiveFeedback 1171 | kControlGetsFocusOnClick 1172// | kControlHasSpecialBackground 1173// | kControlSupportsCalcBestRect 1174 | kControlHandlesTracking 1175 | kControlSupportsFocus 1176 | kControlWantsActivate 1177 | kControlWantsIdle ; 1178 1179 m_peer = new wxMacControl((wxWindow*)this) ; 1180 OSStatus err =::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds, features , m_peer->GetControlRefAddr() ); 1181 verify_noerr( err ); 1182 1183 MacPostControlCreate(pos, size) ; 1184 } 1185 1186#ifndef __WXUNIVERSAL__ 1187 // Don't give scrollbars to wxControls unless they ask for them 1188 if ( (! IsKindOf(CLASSINFO(wxControl)) && ! IsKindOf(CLASSINFO(wxStatusBar))) 1189 || (IsKindOf(CLASSINFO(wxControl)) && ((style & wxHSCROLL) || (style & wxVSCROLL)))) 1190 { 1191 MacCreateScrollBars( style ) ; 1192 } 1193#endif 1194 1195 wxWindowCreateEvent event((wxWindow*)this); 1196 GetEventHandler()->AddPendingEvent(event); 1197 1198 return true; 1199} 1200 1201void wxWindowMac::MacChildAdded() 1202{ 1203 if ( m_vScrollBar ) 1204 m_vScrollBar->Raise() ; 1205 if ( m_hScrollBar ) 1206 m_hScrollBar->Raise() ; 1207} 1208 1209void wxWindowMac::MacPostControlCreate(const wxPoint& pos, const wxSize& size) 1210{ 1211 wxASSERT_MSG( m_peer != NULL && m_peer->Ok() , wxT("No valid mac control") ) ; 1212 1213 m_peer->SetReference( (URefCon) this ) ; 1214 GetParent()->AddChild( this ); 1215 1216 MacInstallEventHandler( (WXWidget) m_peer->GetControlRef() ); 1217 1218 ControlRef container = (ControlRef) GetParent()->GetHandle() ; 1219 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ; 1220 ::EmbedControl( m_peer->GetControlRef() , container ) ; 1221 GetParent()->MacChildAdded() ; 1222 1223 // adjust font, controlsize etc 1224 DoSetWindowVariant( m_windowVariant ) ; 1225 1226 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ; 1227 1228 if (!m_macIsUserPane) 1229 SetInitialSize(size); 1230 1231 SetCursor( *wxSTANDARD_CURSOR ) ; 1232} 1233 1234void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant ) 1235{ 1236 // Don't assert, in case we set the window variant before 1237 // the window is created 1238 // wxASSERT( m_peer->Ok() ) ; 1239 1240 m_windowVariant = variant ; 1241 1242 if (m_peer == NULL || !m_peer->Ok()) 1243 return; 1244 1245 ControlSize size ; 1246 ThemeFontID themeFont = kThemeSystemFont ; 1247 1248 // we will get that from the settings later 1249 // and make this NORMAL later, but first 1250 // we have a few calculations that we must fix 1251 1252 switch ( variant ) 1253 { 1254 case wxWINDOW_VARIANT_NORMAL : 1255 size = kControlSizeNormal; 1256 themeFont = kThemeSystemFont ; 1257 break ; 1258 1259 case wxWINDOW_VARIANT_SMALL : 1260 size = kControlSizeSmall; 1261 themeFont = kThemeSmallSystemFont ; 1262 break ; 1263 1264 case wxWINDOW_VARIANT_MINI : 1265 if (UMAGetSystemVersion() >= 0x1030 ) 1266 { 1267 // not always defined in the headers 1268 size = 3 ; 1269 themeFont = 109 ; 1270 } 1271 else 1272 { 1273 size = kControlSizeSmall; 1274 themeFont = kThemeSmallSystemFont ; 1275 } 1276 break ; 1277 1278 case wxWINDOW_VARIANT_LARGE : 1279 size = kControlSizeLarge; 1280 themeFont = kThemeSystemFont ; 1281 break ; 1282 1283 default: 1284 wxFAIL_MSG(_T("unexpected window variant")); 1285 break ; 1286 } 1287 1288 m_peer->SetData<ControlSize>(kControlEntireControl, kControlSizeTag, &size ) ; 1289 1290 wxFont font ; 1291 font.MacCreateThemeFont( themeFont ) ; 1292 SetFont( font ) ; 1293} 1294 1295wxVisualAttributes wxWindowMac::GetDefaultAttributes() const 1296{ 1297 if ( !m_peer ) 1298 return wxWindowBase::GetDefaultAttributes(); 1299 wxVisualAttributes attrs; 1300 attrs.font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT); 1301 attrs.colFg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT); 1302 attrs.colBg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW); //white 1303 1304 return attrs; 1305} 1306 1307void wxWindowMac::MacUpdateControlFont() 1308{ 1309 if ( m_peer ) 1310 m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ; 1311 // do not trigger refreshes upon invisible and possible partly created objects 1312 if ( MacIsReallyShown() ) 1313 Refresh() ; 1314} 1315 1316bool wxWindowMac::SetFont(const wxFont& font) 1317{ 1318 bool retval = wxWindowBase::SetFont( font ); 1319 1320 MacUpdateControlFont() ; 1321 1322 return retval; 1323} 1324 1325bool wxWindowMac::SetForegroundColour(const wxColour& col ) 1326{ 1327 bool retval = wxWindowBase::SetForegroundColour( col ); 1328 1329 if (retval) 1330 MacUpdateControlFont(); 1331 1332 return retval; 1333} 1334 1335bool wxWindowMac::SetBackgroundColour(const wxColour& col ) 1336{ 1337 if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol ) 1338 return false ; 1339 1340 wxBrush brush ; 1341 wxColour newCol(GetBackgroundColour()); 1342 1343 if ( newCol == wxSystemSettings::GetColour( wxSYS_COLOUR_WINDOW ) ) 1344 brush.MacSetTheme( kThemeBrushDocumentWindowBackground ) ; 1345 else if ( newCol == wxSystemSettings::GetColour( wxSYS_COLOUR_3DFACE ) ) 1346 brush.MacSetTheme( kThemeBrushDialogBackgroundActive ) ; 1347 else 1348 brush.SetColour( newCol ) ; 1349 1350 MacSetBackgroundBrush( brush ) ; 1351 MacUpdateControlFont() ; 1352 1353 return true ; 1354} 1355 1356void wxWindowMac::MacSetBackgroundBrush( const wxBrush &brush ) 1357{ 1358 m_macBackgroundBrush = brush ; 1359 1360 if ( m_peer ) 1361 m_peer->SetBackground( brush ) ; 1362} 1363 1364bool wxWindowMac::MacCanFocus() const 1365{ 1366 // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so 1367 // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning, 1368 // but the value range is nowhere documented 1369 Boolean keyExistsAndHasValidFormat ; 1370 CFIndex fullKeyboardAccess = CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) , 1371 kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat ); 1372 1373 if ( keyExistsAndHasValidFormat && fullKeyboardAccess > 0 ) 1374 { 1375 return true ; 1376 } 1377 else 1378 { 1379 UInt32 features = 0 ; 1380 if ( m_peer ) 1381 m_peer->GetFeatures( &features ) ; 1382 1383 return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ; 1384 } 1385} 1386 1387static bool wxIsWindowOrParentDisabled(wxWindow* w) 1388{ 1389 while (w && !w->IsTopLevel()) 1390 { 1391 if (!w->IsEnabled()) 1392 return true; 1393 w = w->GetParent(); 1394 } 1395 return false; 1396} 1397 1398void wxWindowMac::SetFocus() 1399{ 1400 if ( m_peer == NULL ) 1401 return; 1402 1403 if ( !AcceptsFocus() ) 1404 return ; 1405 1406 if (wxIsWindowOrParentDisabled(this)) 1407 return; 1408 1409 wxWindow* former = FindFocus() ; 1410 if ( former == this ) 1411 return ; 1412 1413 // as we cannot rely on the control features to find out whether we are in full keyboard mode, 1414 // we can only leave in case of an error 1415 1416 wxLogTrace(_T("focus"), _T("SetFocus(%p)"), wx_static_cast(void*, this)); 1417 1418 OSStatus err = m_peer->SetFocus( kControlFocusNextPart ) ; 1419 wxLogTrace(_T("focus"), _T("m_peer->SetFocus received %d"), err); 1420 1421 if ( err == errCouldntSetFocus ) 1422 return ; 1423 1424 if ( GetUserFocusWindow() != (WindowRef)MacGetTopLevelWindowRef() ) 1425 SetUserFocusWindow( (WindowRef)MacGetTopLevelWindowRef() ); 1426 1427#if !TARGET_API_MAC_OSX 1428 // emulate carbon events when running under CarbonLib where they are not natively available 1429 if ( former ) 1430 { 1431 EventRef evRef = NULL ; 1432 1433 err = MacCreateEvent( 1434 NULL , kEventClassControl , kEventControlSetFocusPart , TicksToEventTime( TickCount() ) , 1435 kEventAttributeUserEvent , &evRef ); 1436 verify_noerr( err ); 1437 1438 wxMacCarbonEvent cEvent( evRef ) ; 1439 cEvent.SetParameter<ControlRef>( kEventParamDirectObject , (ControlRef) former->GetHandle() ) ; 1440 cEvent.SetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode , kControlFocusNoPart ) ; 1441 1442 wxMacWindowEventHandler( NULL , evRef , former ) ; 1443 ReleaseEvent( evRef ) ; 1444 } 1445 1446 // send new focus event 1447 { 1448 EventRef evRef = NULL ; 1449 1450 err = MacCreateEvent( 1451 NULL , kEventClassControl , kEventControlSetFocusPart , TicksToEventTime( TickCount() ) , 1452 kEventAttributeUserEvent , &evRef ); 1453 verify_noerr( err ); 1454 1455 wxMacCarbonEvent cEvent( evRef ) ; 1456 cEvent.SetParameter<ControlRef>( kEventParamDirectObject , (ControlRef) GetHandle() ) ; 1457 cEvent.SetParameter<ControlPartCode>(kEventParamControlPart , typeControlPartCode , kControlFocusNextPart ) ; 1458 1459 wxMacWindowEventHandler( NULL , evRef , this ) ; 1460 ReleaseEvent( evRef ) ; 1461 } 1462#endif 1463} 1464 1465void wxWindowMac::DoCaptureMouse() 1466{ 1467 wxApp::s_captureWindow = (wxWindow*)this ; 1468} 1469 1470wxWindow * wxWindowBase::GetCapture() 1471{ 1472 return wxApp::s_captureWindow ; 1473} 1474 1475void wxWindowMac::DoReleaseMouse() 1476{ 1477 wxApp::s_captureWindow = NULL ; 1478} 1479 1480#if wxUSE_DRAG_AND_DROP 1481 1482void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget) 1483{ 1484 if ( m_dropTarget != NULL ) 1485 delete m_dropTarget; 1486 1487 m_dropTarget = pDropTarget; 1488 if ( m_dropTarget != NULL ) 1489 { 1490 // TODO: 1491 } 1492} 1493 1494#endif 1495 1496// Old-style File Manager Drag & Drop 1497void wxWindowMac::DragAcceptFiles(bool accept) 1498{ 1499 // TODO: 1500} 1501 1502// Returns the size of the native control. In the case of the toplevel window 1503// this is the content area root control 1504 1505void wxWindowMac::MacGetPositionAndSizeFromControl(int& x, int& y, 1506 int& w, int& h) const 1507{ 1508 wxFAIL_MSG( wxT("Not currently supported") ) ; 1509} 1510 1511// From a wx position / size calculate the appropriate size of the native control 1512 1513bool wxWindowMac::MacGetBoundsForControl( 1514 const wxPoint& pos, 1515 const wxSize& size, 1516 int& x, int& y, 1517 int& w, int& h , bool adjustOrigin ) const 1518{ 1519 // the desired size, minus the border pixels gives the correct size of the control 1520 x = (int)pos.x; 1521 y = (int)pos.y; 1522 1523 // TODO: the default calls may be used as soon as PostCreateControl Is moved here 1524 w = wxMax(size.x, 0) ; // WidthDefault( size.x ); 1525 h = wxMax(size.y, 0) ; // HeightDefault( size.y ) ; 1526 1527 x += MacGetLeftBorderSize() ; 1528 y += MacGetTopBorderSize() ; 1529 w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ; 1530 h -= MacGetTopBorderSize() + MacGetBottomBorderSize() ; 1531 1532 if ( adjustOrigin ) 1533 AdjustForParentClientOrigin( x , y ) ; 1534 1535 // this is in window relative coordinate, as this parent may have a border, its physical position is offset by this border 1536 if ( !GetParent()->IsTopLevel() ) 1537 { 1538 x -= GetParent()->MacGetLeftBorderSize() ; 1539 y -= GetParent()->MacGetTopBorderSize() ; 1540 } 1541 1542 return true ; 1543} 1544 1545// Get window size (not client size) 1546void wxWindowMac::DoGetSize(int *x, int *y) const 1547{ 1548 Rect bounds = { 0,0,0,0 }; 1549 if( m_peer ) 1550 m_peer->GetRect( &bounds ) ; 1551 1552 if (x) 1553 *x = bounds.right - bounds.left + MacGetLeftBorderSize() + MacGetRightBorderSize() ; 1554 if (y) 1555 *y = bounds.bottom - bounds.top + MacGetTopBorderSize() + MacGetBottomBorderSize() ; 1556} 1557 1558// get the position of the bounds of this window in client coordinates of its parent 1559void wxWindowMac::DoGetPosition(int *x, int *y) const 1560{ 1561 Rect bounds = { 0,0,0,0 }; 1562 if ( m_peer ) 1563 m_peer->GetRect( &bounds ) ; 1564 1565 int x1 = bounds.left ; 1566 int y1 = bounds.top ; 1567 1568 // get the wx window position from the native one 1569 x1 -= MacGetLeftBorderSize() ; 1570 y1 -= MacGetTopBorderSize() ; 1571 1572 if ( !IsTopLevel() ) 1573 { 1574 wxWindow *parent = GetParent(); 1575 if ( parent ) 1576 { 1577 // we must first adjust it to be in window coordinates of the parent, 1578 // as otherwise it gets lost by the ClientAreaOrigin fix 1579 x1 += parent->MacGetLeftBorderSize() ; 1580 y1 += parent->MacGetTopBorderSize() ; 1581 1582 // and now to client coordinates 1583 wxPoint pt(parent->GetClientAreaOrigin()); 1584 x1 -= pt.x ; 1585 y1 -= pt.y ; 1586 } 1587 } 1588 1589 if (x) 1590 *x = x1 ; 1591 if (y) 1592 *y = y1 ; 1593} 1594 1595void wxWindowMac::DoScreenToClient(int *x, int *y) const 1596{ 1597 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ; 1598 wxCHECK_RET( window , wxT("TopLevel Window missing") ) ; 1599 1600 Point localwhere = { 0, 0 } ; 1601 1602 if (x) 1603 localwhere.h = *x ; 1604 if (y) 1605 localwhere.v = *y ; 1606 1607 wxMacGlobalToLocal( window , &localwhere ) ; 1608 1609 if (x) 1610 *x = localwhere.h ; 1611 if (y) 1612 *y = localwhere.v ; 1613 1614 MacRootWindowToWindow( x , y ) ; 1615 1616 wxPoint origin = GetClientAreaOrigin() ; 1617 if (x) 1618 *x -= origin.x ; 1619 if (y) 1620 *y -= origin.y ; 1621} 1622 1623void wxWindowMac::DoClientToScreen(int *x, int *y) const 1624{ 1625 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ; 1626 wxCHECK_RET( window , wxT("TopLevel window missing") ) ; 1627 1628 wxPoint origin = GetClientAreaOrigin() ; 1629 if (x) 1630 *x += origin.x ; 1631 if (y) 1632 *y += origin.y ; 1633 1634 MacWindowToRootWindow( x , y ) ; 1635 1636 Point localwhere = { 0, 0 }; 1637 if (x) 1638 localwhere.h = *x ; 1639 if (y) 1640 localwhere.v = *y ; 1641 1642 wxMacLocalToGlobal( window, &localwhere ) ; 1643 1644 if (x) 1645 *x = localwhere.h ; 1646 if (y) 1647 *y = localwhere.v ; 1648} 1649 1650void wxWindowMac::MacClientToRootWindow( int *x , int *y ) const 1651{ 1652 wxPoint origin = GetClientAreaOrigin() ; 1653 if (x) 1654 *x += origin.x ; 1655 if (y) 1656 *y += origin.y ; 1657 1658 MacWindowToRootWindow( x , y ) ; 1659} 1660 1661void wxWindowMac::MacRootWindowToClient( int *x , int *y ) const 1662{ 1663 MacRootWindowToWindow( x , y ) ; 1664 1665 wxPoint origin = GetClientAreaOrigin() ; 1666 if (x) 1667 *x -= origin.x ; 1668 if (y) 1669 *y -= origin.y ; 1670} 1671 1672void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const 1673{ 1674 wxPoint pt ; 1675 1676 if (x) 1677 pt.x = *x ; 1678 if (y) 1679 pt.y = *y ; 1680 1681 if ( !IsTopLevel() ) 1682 { 1683 wxTopLevelWindowMac* top = MacGetTopLevelWindow(); 1684 if (top) 1685 { 1686 pt.x -= MacGetLeftBorderSize() ; 1687 pt.y -= MacGetTopBorderSize() ; 1688 wxMacControl::Convert( &pt , m_peer , top->m_peer ) ; 1689 } 1690 } 1691 1692 if (x) 1693 *x = (int) pt.x ; 1694 if (y) 1695 *y = (int) pt.y ; 1696} 1697 1698void wxWindowMac::MacWindowToRootWindow( short *x , short *y ) const 1699{ 1700 int x1 , y1 ; 1701 1702 if (x) 1703 x1 = *x ; 1704 if (y) 1705 y1 = *y ; 1706 1707 MacWindowToRootWindow( &x1 , &y1 ) ; 1708 1709 if (x) 1710 *x = x1 ; 1711 if (y) 1712 *y = y1 ; 1713} 1714 1715void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const 1716{ 1717 wxPoint pt ; 1718 1719 if (x) 1720 pt.x = *x ; 1721 if (y) 1722 pt.y = *y ; 1723 1724 if ( !IsTopLevel() ) 1725 { 1726 wxTopLevelWindowMac* top = MacGetTopLevelWindow(); 1727 if (top) 1728 { 1729 wxMacControl::Convert( &pt , top->m_peer , m_peer ) ; 1730 pt.x += MacGetLeftBorderSize() ; 1731 pt.y += MacGetTopBorderSize() ; 1732 } 1733 } 1734 1735 if (x) 1736 *x = (int) pt.x ; 1737 if (y) 1738 *y = (int) pt.y ; 1739} 1740 1741void wxWindowMac::MacRootWindowToWindow( short *x , short *y ) const 1742{ 1743 int x1 , y1 ; 1744 1745 if (x) 1746 x1 = *x ; 1747 if (y) 1748 y1 = *y ; 1749 1750 MacRootWindowToWindow( &x1 , &y1 ) ; 1751 1752 if (x) 1753 *x = x1 ; 1754 if (y) 1755 *y = y1 ; 1756} 1757 1758void wxWindowMac::MacGetContentAreaInset( int &left , int &top , int &right , int &bottom ) 1759{ 1760 RgnHandle rgn = NewRgn() ; 1761 1762 if ( m_peer != NULL && m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr ) 1763 { 1764 Rect structure, content ; 1765 1766 GetRegionBounds( rgn , &content ) ; 1767 m_peer->GetRect( &structure ) ; 1768 OffsetRect( &structure, -structure.left , -structure.top ) ; 1769 1770 left = content.left - structure.left ; 1771 top = content.top - structure.top ; 1772 right = structure.right - content.right ; 1773 bottom = structure.bottom - content.bottom ; 1774 } 1775 else 1776 { 1777 left = top = right = bottom = 0 ; 1778 } 1779 1780 DisposeRgn( rgn ) ; 1781} 1782 1783wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size ) const 1784{ 1785 wxSize sizeTotal = size; 1786 1787 RgnHandle rgn = NewRgn() ; 1788 if ( m_peer != NULL && m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr ) 1789 { 1790 Rect content, structure ; 1791 GetRegionBounds( rgn , &content ) ; 1792 m_peer->GetRect( &structure ) ; 1793 1794 // structure is in parent coordinates, but we only need width and height, so it's ok 1795 1796 sizeTotal.x += (structure.right - structure.left) - (content.right - content.left) ; 1797 sizeTotal.y += (structure.bottom - structure.top) - (content.bottom - content.top) ; 1798 } 1799 1800 DisposeRgn( rgn ) ; 1801 1802 sizeTotal.x += MacGetLeftBorderSize() + MacGetRightBorderSize() ; 1803 sizeTotal.y += MacGetTopBorderSize() + MacGetBottomBorderSize() ; 1804 1805 return sizeTotal; 1806} 1807 1808// Get size *available for subwindows* i.e. excluding menu bar etc. 1809void wxWindowMac::DoGetClientSize( int *x, int *y ) const 1810{ 1811 int ww, hh; 1812 1813 Rect content = { 0,0,0,0 }; 1814 if ( m_peer ) 1815 { 1816 RgnHandle rgn = NewRgn() ; 1817 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr ) 1818 GetRegionBounds( rgn , &content ) ; 1819 else 1820 m_peer->GetRect( &content ) ; 1821 DisposeRgn( rgn ) ; 1822 } 1823 1824 ww = content.right - content.left ; 1825 hh = content.bottom - content.top ; 1826 1827 if (m_hScrollBar && m_hScrollBar->IsShown() ) 1828 hh -= m_hScrollBar->GetSize().y ; 1829 1830 if (m_vScrollBar && m_vScrollBar->IsShown() ) 1831 ww -= m_vScrollBar->GetSize().x ; 1832 1833 if (x) 1834 *x = ww; 1835 if (y) 1836 *y = hh; 1837} 1838 1839bool wxWindowMac::SetCursor(const wxCursor& cursor) 1840{ 1841 if (m_cursor.IsSameAs(cursor)) 1842 return false; 1843 1844 if (!cursor.IsOk()) 1845 { 1846 if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) ) 1847 return false ; 1848 } 1849 else 1850 { 1851 if ( ! wxWindowBase::SetCursor( cursor ) ) 1852 return false ; 1853 } 1854 1855 wxASSERT_MSG( m_cursor.Ok(), 1856 wxT("cursor must be valid after call to the base version")); 1857 1858 wxWindowMac *mouseWin = 0 ; 1859 { 1860 wxTopLevelWindowMac *tlw = MacGetTopLevelWindow() ; 1861 WindowRef window = (WindowRef) ( tlw ? tlw->MacGetWindowRef() : 0 ) ; 1862 1863 ControlPartCode part ; 1864 ControlRef control ; 1865 Point pt ; 1866 #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 1867 HIPoint hiPoint ; 1868 HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint); 1869 pt.h = hiPoint.x; 1870 pt.v = hiPoint.y; 1871 #else 1872 CGrafPtr savePort ; 1873 Boolean swapped = QDSwapPort( GetWindowPort( window ) , &savePort ) ; 1874 1875 // TODO: If we ever get a GetCurrentEvent... replacement 1876 // for the mouse position, use it... 1877 1878 1879 GetMouse( &pt ) ; 1880#endif 1881 control = wxMacFindControlUnderMouse( tlw , pt , window , &part ) ; 1882 if ( control ) 1883 mouseWin = wxFindControlFromMacControl( control ) ; 1884 1885#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 1886 if ( swapped ) 1887 QDSwapPort( savePort , NULL ) ; 1888#endif 1889 } 1890 1891 if ( mouseWin == this && !wxIsBusy() ) 1892 m_cursor.MacInstall() ; 1893 1894 return true ; 1895} 1896 1897#if wxUSE_MENUS 1898bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y) 1899{ 1900#ifndef __WXUNIVERSAL__ 1901 menu->SetInvokingWindow((wxWindow*)this); 1902 menu->UpdateUI(); 1903 1904 if ( x == wxDefaultCoord && y == wxDefaultCoord ) 1905 { 1906 wxPoint mouse = wxGetMousePosition(); 1907 x = mouse.x; 1908 y = mouse.y; 1909 } 1910 else 1911 { 1912 ClientToScreen( &x , &y ) ; 1913 } 1914 1915 menu->MacBeforeDisplay( true ) ; 1916 long menuResult = ::PopUpMenuSelect((MenuHandle) menu->GetHMenu() , y, x, 0) ; 1917 if ( HiWord(menuResult) != 0 ) 1918 { 1919 MenuCommand macid; 1920 GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult)) , LoWord(menuResult) , &macid ); 1921 int id = wxMacCommandToId( macid ); 1922 wxMenuItem* item = NULL ; 1923 wxMenu* realmenu ; 1924 item = menu->FindItem( id, &realmenu ) ; 1925 if ( item ) 1926 { 1927 if (item->IsCheckable()) 1928 item->Check( !item->IsChecked() ) ; 1929 1930 menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ; 1931 } 1932 } 1933 1934 menu->MacAfterDisplay( true ) ; 1935 menu->SetInvokingWindow( NULL ); 1936 1937 return true; 1938#else 1939 // actually this shouldn't be called, because universal is having its own implementation 1940 return false; 1941#endif 1942} 1943#endif 1944 1945// ---------------------------------------------------------------------------- 1946// tooltips 1947// ---------------------------------------------------------------------------- 1948 1949#if wxUSE_TOOLTIPS 1950 1951void wxWindowMac::DoSetToolTip(wxToolTip *tooltip) 1952{ 1953 wxWindowBase::DoSetToolTip(tooltip); 1954 1955 if ( m_tooltip ) 1956 m_tooltip->SetWindow((wxWindow*)this); 1957} 1958 1959#endif 1960 1961void wxWindowMac::MacInvalidateBorders() 1962{ 1963 if ( m_peer == NULL ) 1964 return ; 1965 1966 bool vis = MacIsReallyShown() ; 1967 if ( !vis ) 1968 return ; 1969 1970 int outerBorder = MacGetLeftBorderSize() ; 1971 if ( m_peer->NeedsFocusRect() && m_peer->HasFocus() ) 1972 outerBorder += 4 ; 1973 1974 if ( outerBorder == 0 ) 1975 return ; 1976 1977 // now we know that we have something to do at all 1978 1979 // as the borders are drawn on the parent we have to properly invalidate all these areas 1980 RgnHandle updateInner , updateOuter; 1981 Rect rect ; 1982 1983 // this rectangle is in HIViewCoordinates under OSX and in Window Coordinates under Carbon 1984 updateInner = NewRgn() ; 1985 updateOuter = NewRgn() ; 1986 1987 m_peer->GetRect( &rect ) ; 1988 RectRgn( updateInner, &rect ) ; 1989 InsetRect( &rect , -outerBorder , -outerBorder ) ; 1990 RectRgn( updateOuter, &rect ) ; 1991 DiffRgn( updateOuter, updateInner , updateOuter ) ; 1992 1993#ifdef __WXMAC_OSX__ 1994 GetParent()->m_peer->SetNeedsDisplay( updateOuter ) ; 1995#else 1996 WindowRef tlw = (WindowRef) MacGetTopLevelWindowRef() ; 1997 if ( tlw ) 1998 InvalWindowRgn( tlw , updateOuter ) ; 1999#endif 2000 2001 DisposeRgn( updateOuter ) ; 2002 DisposeRgn( updateInner ) ; 2003} 2004 2005void wxWindowMac::DoMoveWindow(int x, int y, int width, int height) 2006{ 2007 // this is never called for a toplevel window, so we know we have a parent 2008 int former_x , former_y , former_w, former_h ; 2009 2010 // Get true coordinates of former position 2011 DoGetPosition( &former_x , &former_y ) ; 2012 DoGetSize( &former_w , &former_h ) ; 2013 2014 wxWindow *parent = GetParent(); 2015 if ( parent ) 2016 { 2017 wxPoint pt(parent->GetClientAreaOrigin()); 2018 former_x += pt.x ; 2019 former_y += pt.y ; 2020 } 2021 2022 int actualWidth = width ; 2023 int actualHeight = height ; 2024 int actualX = x; 2025 int actualY = y; 2026 2027 if ((m_minWidth != -1) && (actualWidth < m_minWidth)) 2028 actualWidth = m_minWidth; 2029 if ((m_minHeight != -1) && (actualHeight < m_minHeight)) 2030 actualHeight = m_minHeight; 2031 if ((m_maxWidth != -1) && (actualWidth > m_maxWidth)) 2032 actualWidth = m_maxWidth; 2033 if ((m_maxHeight != -1) && (actualHeight > m_maxHeight)) 2034 actualHeight = m_maxHeight; 2035 2036 bool doMove = false, doResize = false ; 2037 2038 if ( actualX != former_x || actualY != former_y ) 2039 doMove = true ; 2040 2041 if ( actualWidth != former_w || actualHeight != former_h ) 2042 doResize = true ; 2043 2044 if ( m_peer != NULL && ( doMove || doResize ) ) 2045 { 2046 // as the borders are drawn outside the native control, we adjust now 2047 2048 wxRect bounds( wxPoint( actualX + MacGetLeftBorderSize() ,actualY + MacGetTopBorderSize() ), 2049 wxSize( actualWidth - (MacGetLeftBorderSize() + MacGetRightBorderSize()) , 2050 actualHeight - (MacGetTopBorderSize() + MacGetBottomBorderSize()) ) ) ; 2051 2052 Rect r ; 2053 wxMacRectToNative( &bounds , &r ) ; 2054 2055 if ( !GetParent()->IsTopLevel() ) 2056 wxMacWindowToNative( GetParent() , &r ) ; 2057 2058 MacInvalidateBorders() ; 2059 2060 m_cachedClippedRectValid = false ; 2061 m_peer->SetRect( &r ) ; 2062 2063 wxWindowMac::MacSuperChangedPosition() ; // like this only children will be notified 2064 2065 MacInvalidateBorders() ; 2066 2067 MacRepositionScrollBars() ; 2068 if ( doMove ) 2069 { 2070 wxPoint point(actualX, actualY); 2071 wxMoveEvent event(point, m_windowId); 2072 event.SetEventObject(this); 2073 GetEventHandler()->ProcessEvent(event) ; 2074 } 2075 2076 if ( doResize ) 2077 { 2078 MacRepositionScrollBars() ; 2079 wxSize size(actualWidth, actualHeight); 2080 wxSizeEvent event(size, m_windowId); 2081 event.SetEventObject(this); 2082 GetEventHandler()->ProcessEvent(event); 2083 } 2084 } 2085} 2086 2087wxSize wxWindowMac::DoGetBestSize() const 2088{ 2089 if ( m_peer == NULL || m_macIsUserPane || IsTopLevel() ) 2090 { 2091 return wxWindowBase::DoGetBestSize() ; 2092 } 2093 else 2094 { 2095 Rect bestsize = { 0 , 0 , 0 , 0 } ; 2096 int bestWidth, bestHeight ; 2097 2098 m_peer->GetBestRect( &bestsize ) ; 2099 if ( EmptyRect( &bestsize ) ) 2100 { 2101 bestsize.left = 2102 bestsize.top = 0 ; 2103 bestsize.right = 2104 bestsize.bottom = 16 ; 2105 2106 if ( IsKindOf( CLASSINFO( wxScrollBar ) ) ) 2107 { 2108 bestsize.bottom = 16 ; 2109 } 2110 #if wxUSE_SPINBTN 2111 else if ( IsKindOf( CLASSINFO( wxSpinButton ) ) ) 2112 { 2113 bestsize.bottom = 24 ; 2114 } 2115 #endif 2116 else 2117 { 2118 // return wxWindowBase::DoGetBestSize() ; 2119 } 2120 } 2121 // wx-borders are being drawn outside the native control 2122 bestWidth = bestsize.right - bestsize.left + MacGetLeftBorderSize() + 2123 MacGetRightBorderSize(); 2124 bestHeight = bestsize.bottom - bestsize.top + MacGetTopBorderSize() + 2125 MacGetBottomBorderSize(); 2126 if ( bestHeight < 10 ) 2127 bestHeight = 13 ; 2128 return wxSize(bestWidth, bestHeight); 2129 } 2130} 2131 2132// set the size of the window: if the dimensions are positive, just use them, 2133// but if any of them is equal to -1, it means that we must find the value for 2134// it ourselves (unless sizeFlags contains wxSIZE_ALLOW_MINUS_ONE flag, in 2135// which case -1 is a valid value for x and y) 2136// 2137// If sizeFlags contains wxSIZE_AUTO_WIDTH/HEIGHT flags (default), we calculate 2138// the width/height to best suit our contents, otherwise we reuse the current 2139// width/height 2140void wxWindowMac::DoSetSize(int x, int y, int width, int height, int sizeFlags) 2141{ 2142 // get the current size and position... 2143 int currentX, currentY; 2144 int currentW, currentH; 2145 2146 GetPosition(¤tX, ¤tY); 2147 GetSize(¤tW, ¤tH); 2148 2149 // ... and don't do anything (avoiding flicker) if it's already ok 2150 if ( x == currentX && y == currentY && 2151 width == currentW && height == currentH && ( height != -1 && width != -1 ) ) 2152 { 2153 // TODO: REMOVE 2154 MacRepositionScrollBars() ; // we might have a real position shift 2155 2156 return; 2157 } 2158 2159 if ( !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE) ) 2160 { 2161 if ( x == wxDefaultCoord ) 2162 x = currentX; 2163 if ( y == wxDefaultCoord ) 2164 y = currentY; 2165 } 2166 2167 AdjustForParentClientOrigin( x, y, sizeFlags ); 2168 2169 wxSize size = wxDefaultSize; 2170 if ( width == wxDefaultCoord ) 2171 { 2172 if ( sizeFlags & wxSIZE_AUTO_WIDTH ) 2173 { 2174 size = DoGetBestSize(); 2175 width = size.x; 2176 } 2177 else 2178 { 2179 // just take the current one 2180 width = currentW; 2181 } 2182 } 2183 2184 if ( height == wxDefaultCoord ) 2185 { 2186 if ( sizeFlags & wxSIZE_AUTO_HEIGHT ) 2187 { 2188 if ( size.x == wxDefaultCoord ) 2189 size = DoGetBestSize(); 2190 // else: already called DoGetBestSize() above 2191 2192 height = size.y; 2193 } 2194 else 2195 { 2196 // just take the current one 2197 height = currentH; 2198 } 2199 } 2200 2201 DoMoveWindow( x, y, width, height ); 2202} 2203 2204wxPoint wxWindowMac::GetClientAreaOrigin() const 2205{ 2206 Rect content = { 0,0,0,0 }; 2207 if ( m_peer ) 2208 { 2209 RgnHandle rgn = NewRgn() ; 2210 2211 if ( m_peer->GetRegion( kControlContentMetaPart , rgn ) == noErr ) 2212 { 2213 GetRegionBounds( rgn , &content ) ; 2214 } 2215 else 2216 { 2217 content.left = 2218 content.top = 0 ; 2219 } 2220 2221 DisposeRgn( rgn ) ; 2222 } 2223 2224 return wxPoint( content.left + MacGetLeftBorderSize() , content.top + MacGetTopBorderSize() ); 2225} 2226 2227void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight) 2228{ 2229 if ( clientwidth != wxDefaultCoord || clientheight != wxDefaultCoord ) 2230 { 2231 int currentclientwidth , currentclientheight ; 2232 int currentwidth , currentheight ; 2233 2234 GetClientSize( ¤tclientwidth , ¤tclientheight ) ; 2235 GetSize( ¤twidth , ¤theight ) ; 2236 2237 DoSetSize( wxDefaultCoord , wxDefaultCoord , currentwidth + clientwidth - currentclientwidth , 2238 currentheight + clientheight - currentclientheight , wxSIZE_USE_EXISTING ) ; 2239 } 2240} 2241 2242void wxWindowMac::SetLabel(const wxString& title) 2243{ 2244 m_label = title ; 2245 2246 if ( m_peer && m_peer->Ok() ) 2247 m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ; 2248 2249 // do not trigger refreshes upon invisible and possible partly created objects 2250 if ( MacIsReallyShown() ) 2251 Refresh() ; 2252} 2253 2254wxString wxWindowMac::GetLabel() const 2255{ 2256 return m_label ; 2257} 2258 2259bool wxWindowMac::Show(bool show) 2260{ 2261 bool former = MacIsReallyShown() ; 2262 if ( !wxWindowBase::Show(show) ) 2263 return false; 2264 2265 // TODO: use visibilityChanged Carbon Event for OSX 2266 if ( m_peer ) 2267 m_peer->SetVisibility( show , true ) ; 2268 2269 if ( former != MacIsReallyShown() ) 2270 MacPropagateVisibilityChanged() ; 2271 2272 return true; 2273} 2274 2275bool wxWindowMac::Enable(bool enable) 2276{ 2277 wxASSERT( m_peer->Ok() ) ; 2278 bool former = MacIsReallyEnabled() ; 2279 if ( !wxWindowBase::Enable(enable) ) 2280 return false; 2281 2282 if ( m_peer ) 2283 m_peer->Enable( enable ) ; 2284 2285 if ( former != MacIsReallyEnabled() ) 2286 MacPropagateEnabledStateChanged() ; 2287 2288 return true; 2289} 2290 2291// 2292// status change propagations (will be not necessary for OSX later ) 2293// 2294 2295void wxWindowMac::MacPropagateVisibilityChanged() 2296{ 2297#if !TARGET_API_MAC_OSX 2298 MacVisibilityChanged() ; 2299 2300 wxWindowMac *child; 2301 wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); 2302 while ( node ) 2303 { 2304 child = node->GetData(); 2305 if ( child->IsShown() ) 2306 child->MacPropagateVisibilityChanged() ; 2307 2308 node = node->GetNext(); 2309 } 2310#endif 2311} 2312 2313void wxWindowMac::MacPropagateEnabledStateChanged() 2314{ 2315#if !TARGET_API_MAC_OSX 2316 MacEnabledStateChanged() ; 2317 2318 wxWindowMac *child; 2319 wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); 2320 while ( node ) 2321 { 2322 child = node->GetData(); 2323 if ( child->IsEnabled() ) 2324 child->MacPropagateEnabledStateChanged() ; 2325 2326 node = node->GetNext(); 2327 } 2328#endif 2329} 2330 2331void wxWindowMac::MacPropagateHiliteChanged() 2332{ 2333#if !TARGET_API_MAC_OSX 2334 MacHiliteChanged() ; 2335 2336 wxWindowMac *child; 2337 wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); 2338 while ( node ) 2339 { 2340 child = node->GetData(); 2341 if (child /* && child->IsEnabled() */) 2342 child->MacPropagateHiliteChanged() ; 2343 2344 node = node->GetNext(); 2345 } 2346#endif 2347} 2348 2349// 2350// status change notifications 2351// 2352 2353void wxWindowMac::MacVisibilityChanged() 2354{ 2355} 2356 2357void wxWindowMac::MacHiliteChanged() 2358{ 2359} 2360 2361void wxWindowMac::MacEnabledStateChanged() 2362{ 2363} 2364 2365// 2366// status queries on the inherited window's state 2367// 2368 2369bool wxWindowMac::MacIsReallyShown() 2370{ 2371 // only under OSX the visibility of the TLW is taken into account 2372 if ( m_isBeingDeleted ) 2373 return false ; 2374 2375#if TARGET_API_MAC_OSX 2376 if ( m_peer && m_peer->Ok() ) 2377 return m_peer->IsVisible(); 2378#endif 2379 2380 wxWindowMac* win = this ; 2381 while ( win->IsShown() ) 2382 { 2383 if ( win->IsTopLevel() ) 2384 return true ; 2385 2386 win = win->GetParent() ; 2387 if ( win == NULL ) 2388 return true ; 2389 } 2390 2391 return false ; 2392} 2393 2394bool wxWindowMac::MacIsReallyEnabled() 2395{ 2396 if ( m_peer ) 2397 return m_peer->IsEnabled() ; 2398 else 2399 return false; 2400} 2401 2402bool wxWindowMac::MacIsReallyHilited() 2403{ 2404 if ( m_peer ) 2405 return m_peer->IsActive(); 2406 else 2407 return false; 2408} 2409 2410void wxWindowMac::MacFlashInvalidAreas() 2411{ 2412#if TARGET_API_MAC_OSX 2413 HIViewFlashDirtyArea( (WindowRef) MacGetTopLevelWindowRef() ) ; 2414#endif 2415} 2416 2417int wxWindowMac::GetCharHeight() const 2418{ 2419 if ( m_peer ) 2420 { 2421 wxClientDC dc( (wxWindow*)this ) ; 2422 return dc.GetCharHeight() ; 2423 } 2424 else 2425 return 16; // an arbitrary amount, just to avoid problems with introspection on a wxMenuBar 2426} 2427 2428int wxWindowMac::GetCharWidth() const 2429{ 2430 if ( m_peer ) 2431 { 2432 wxClientDC dc( (wxWindow*)this ) ; 2433 return dc.GetCharWidth() ; 2434 } 2435 else 2436 return 8; // an arbitrary amount, just to avoid problems with introspection on a wxMenuBar 2437} 2438 2439void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y, 2440 int *descent, int *externalLeading, const wxFont *theFont ) const 2441{ 2442 const wxFont *fontToUse = theFont; 2443 wxFont tempFont; 2444 if ( !fontToUse ) 2445 { 2446 tempFont = GetFont(); 2447 fontToUse = &tempFont; 2448 } 2449 2450 wxClientDC dc( (wxWindow*)this ) ; 2451 long lx,ly,ld,le ; 2452 dc.GetTextExtent( string , &lx , &ly , &ld, &le, (wxFont *)fontToUse ) ; 2453 if ( externalLeading ) 2454 *externalLeading = le ; 2455 if ( descent ) 2456 *descent = ld ; 2457 if ( x ) 2458 *x = lx ; 2459 if ( y ) 2460 *y = ly ; 2461} 2462 2463/* 2464 * Rect is given in client coordinates, for further reading, read wxTopLevelWindowMac::InvalidateRect 2465 * we always intersect with the entire window, not only with the client area 2466 */ 2467 2468void wxWindowMac::Refresh(bool eraseBack, const wxRect *rect) 2469{ 2470 if ( m_peer == NULL ) 2471 return ; 2472 2473 if ( !MacIsReallyShown() ) 2474 return ; 2475 2476 if ( rect ) 2477 { 2478 Rect r ; 2479 2480 wxMacRectToNative( rect , &r ) ; 2481 m_peer->SetNeedsDisplay( &r ) ; 2482 } 2483 else 2484 { 2485 m_peer->SetNeedsDisplay() ; 2486 } 2487} 2488 2489void wxWindowMac::Freeze() 2490{ 2491#if TARGET_API_MAC_OSX 2492 if ( !m_frozenness++ ) 2493 { 2494 if ( m_peer && m_peer->Ok() ) 2495 m_peer->SetDrawingEnabled( false ) ; 2496 } 2497#endif 2498} 2499 2500void wxWindowMac::Thaw() 2501{ 2502#if TARGET_API_MAC_OSX 2503 wxASSERT_MSG( m_frozenness > 0, wxT("Thaw() without matching Freeze()") ); 2504 2505 if ( !--m_frozenness ) 2506 { 2507 if ( m_peer && m_peer->Ok() ) 2508 { 2509 m_peer->SetDrawingEnabled( true ) ; 2510 m_peer->InvalidateWithChildren() ; 2511 } 2512 } 2513#endif 2514} 2515 2516bool wxWindowMac::IsFrozen() const 2517{ 2518 return m_frozenness != 0; 2519} 2520 2521wxWindow *wxGetActiveWindow() 2522{ 2523 // actually this is a windows-only concept 2524 return NULL; 2525} 2526 2527// Coordinates relative to the window 2528void wxWindowMac::WarpPointer(int x_pos, int y_pos) 2529{ 2530 int x = x_pos; 2531 int y = y_pos; 2532 DoClientToScreen(&x, &y); 2533 CGPoint cgpoint = CGPointMake( x, y ); 2534 CGWarpMouseCursorPosition( cgpoint ); 2535 2536 // At least GTK sends a mouse moved event after WarpMouse 2537 wxMouseEvent event(wxEVT_MOTION); 2538 event.m_x = x_pos; 2539 event.m_y = y_pos; 2540 wxMouseState mState = ::wxGetMouseState(); 2541 2542 event.m_altDown = mState.AltDown(); 2543 event.m_controlDown = mState.ControlDown(); 2544 event.m_leftDown = mState.LeftDown(); 2545 event.m_middleDown = mState.MiddleDown(); 2546 event.m_rightDown = mState.RightDown(); 2547 event.m_metaDown = mState.MetaDown(); 2548 event.m_shiftDown = mState.ShiftDown(); 2549 event.SetId(GetId()); 2550 event.SetEventObject(this); 2551 GetEventHandler()->ProcessEvent(event); 2552} 2553 2554void wxWindowMac::OnEraseBackground(wxEraseEvent& event) 2555{ 2556 if ( MacGetTopLevelWindow() == NULL ) 2557 return ; 2558 2559#if TARGET_API_MAC_OSX 2560 if ( !m_macBackgroundBrush.Ok() || m_macBackgroundBrush.GetStyle() == wxTRANSPARENT ) 2561 { 2562 event.Skip() ; 2563 } 2564 else 2565#endif 2566 { 2567 event.GetDC()->Clear() ; 2568 } 2569} 2570 2571void wxWindowMac::OnNcPaint( wxNcPaintEvent& event ) 2572{ 2573 event.Skip() ; 2574} 2575 2576int wxWindowMac::GetScrollPos(int orient) const 2577{ 2578 if ( orient == wxHORIZONTAL ) 2579 { 2580 if ( m_hScrollBar ) 2581 return m_hScrollBar->GetThumbPosition() ; 2582 } 2583 else 2584 { 2585 if ( m_vScrollBar ) 2586 return m_vScrollBar->GetThumbPosition() ; 2587 } 2588 2589 return 0; 2590} 2591 2592// This now returns the whole range, not just the number 2593// of positions that we can scroll. 2594int wxWindowMac::GetScrollRange(int orient) const 2595{ 2596 if ( orient == wxHORIZONTAL ) 2597 { 2598 if ( m_hScrollBar ) 2599 return m_hScrollBar->GetRange() ; 2600 } 2601 else 2602 { 2603 if ( m_vScrollBar ) 2604 return m_vScrollBar->GetRange() ; 2605 } 2606 2607 return 0; 2608} 2609 2610int wxWindowMac::GetScrollThumb(int orient) const 2611{ 2612 if ( orient == wxHORIZONTAL ) 2613 { 2614 if ( m_hScrollBar ) 2615 return m_hScrollBar->GetThumbSize() ; 2616 } 2617 else 2618 { 2619 if ( m_vScrollBar ) 2620 return m_vScrollBar->GetThumbSize() ; 2621 } 2622 2623 return 0; 2624} 2625 2626void wxWindowMac::SetScrollPos(int orient, int pos, bool refresh) 2627{ 2628 if ( orient == wxHORIZONTAL ) 2629 { 2630 if ( m_hScrollBar ) 2631 m_hScrollBar->SetThumbPosition( pos ) ; 2632 } 2633 else 2634 { 2635 if ( m_vScrollBar ) 2636 m_vScrollBar->SetThumbPosition( pos ) ; 2637 } 2638} 2639 2640// 2641// we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef 2642// our own window origin is at leftOrigin/rightOrigin 2643// 2644 2645void wxWindowMac::MacPaintGrowBox() 2646{ 2647 if ( IsTopLevel() ) 2648 return ; 2649 2650#if wxMAC_USE_CORE_GRAPHICS 2651 if ( m_peer != NULL && MacHasScrollBarCorner() ) 2652 { 2653 Rect rect ; 2654 2655 CGContextRef cgContext = (CGContextRef) MacGetCGContextRef() ; 2656 wxASSERT( cgContext ) ; 2657 2658 m_peer->GetRect( &rect ) ; 2659 2660 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ; 2661 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ; 2662 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ; 2663 CGContextSaveGState( cgContext ); 2664 2665 if ( m_macBackgroundBrush.Ok() && m_macBackgroundBrush.GetStyle() != wxTRANSPARENT ) 2666 { 2667 wxMacCoreGraphicsColour bkgnd( m_macBackgroundBrush ) ; 2668 bkgnd.Apply( cgContext ); 2669 } 2670 else 2671 { 2672 CGContextSetRGBFillColor( cgContext, 1.0, 1.0 , 1.0 , 1.0 ); 2673 } 2674 CGContextFillRect( cgContext, cgrect ); 2675 CGContextRestoreGState( cgContext ); 2676 } 2677#endif 2678} 2679 2680 2681void wxWindowMac::MacPaintBorders( int leftOrigin , int rightOrigin ) 2682{ 2683 if ( m_peer == NULL || IsTopLevel() ) 2684 return ; 2685 2686 Rect rect ; 2687 bool hasFocus = m_peer->NeedsFocusRect() && m_peer->HasFocus() ; 2688 2689 // back to the surrounding frame rectangle 2690 m_peer->GetRect( &rect ) ; 2691 InsetRect( &rect, -1 , -1 ) ; 2692 2693#if wxMAC_USE_CORE_GRAPHICS 2694 { 2695 CGRect cgrect = CGRectMake( rect.left , rect.top , rect.right - rect.left , 2696 rect.bottom - rect.top ) ; 2697 2698 HIThemeFrameDrawInfo info ; 2699 memset( &info, 0 , sizeof(info) ) ; 2700 2701 info.version = 0 ; 2702 info.kind = 0 ; 2703 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ; 2704 info.isFocused = hasFocus ; 2705 2706 CGContextRef cgContext = (CGContextRef) GetParent()->MacGetCGContextRef() ; 2707 wxASSERT( cgContext ) ; 2708 2709 if ( HasFlag(wxRAISED_BORDER) || HasFlag(wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) ) 2710 { 2711 info.kind = kHIThemeFrameTextFieldSquare ; 2712 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ; 2713 } 2714 else if ( HasFlag(wxSIMPLE_BORDER) ) 2715 { 2716 info.kind = kHIThemeFrameListBox ; 2717 HIThemeDrawFrame( &cgrect , &info , cgContext , kHIThemeOrientationNormal ) ; 2718 } 2719 else if ( hasFocus ) 2720 { 2721 HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ; 2722 } 2723#if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself 2724 m_peer->GetRect( &rect ) ; 2725 if ( MacHasScrollBarCorner() ) 2726 { 2727 int variant = (m_hScrollBar == NULL ? m_vScrollBar : m_hScrollBar ) ->GetWindowVariant(); 2728 int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ; 2729 CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ; 2730 CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ; 2731 HIThemeGrowBoxDrawInfo info ; 2732 memset( &info, 0, sizeof(info) ) ; 2733 info.version = 0 ; 2734 info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ; 2735 info.kind = kHIThemeGrowBoxKindNone ; 2736 // contrary to the docs ...SizeSmall does not work 2737 info.size = kHIThemeGrowBoxSizeNormal ; 2738 info.direction = 0 ; 2739 HIThemeDrawGrowBox( &cgpoint , &info , cgContext , kHIThemeOrientationNormal ) ; 2740 } 2741#endif 2742 } 2743 #else 2744 { 2745 wxTopLevelWindowMac* top = MacGetTopLevelWindow(); 2746 if ( top ) 2747 { 2748 wxPoint pt(0, 0) ; 2749 wxMacControl::Convert( &pt , GetParent()->m_peer , top->m_peer ) ; 2750 OffsetRect( &rect , pt.x , pt.y ) ; 2751 } 2752 2753 if ( HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) ) 2754 DrawThemeEditTextFrame( &rect, IsEnabled() ? kThemeStateActive : kThemeStateInactive ) ; 2755 else if ( HasFlag(wxSIMPLE_BORDER) ) 2756 DrawThemeListBoxFrame( &rect, IsEnabled() ? kThemeStateActive : kThemeStateInactive ) ; 2757 2758 if ( hasFocus ) 2759 DrawThemeFocusRect( &rect , true ) ; 2760 /* 2761 if ( hasBothScrollbars ) // hasBothScrollbars is not declared 2762 { 2763 // GetThemeStandaloneGrowBoxBounds 2764 // DrawThemeStandaloneNoGrowBox 2765 } 2766 */ 2767 } 2768#endif 2769} 2770 2771void wxWindowMac::RemoveChild( wxWindowBase *child ) 2772{ 2773 if ( child == m_hScrollBar ) 2774 m_hScrollBar = NULL ; 2775 if ( child == m_vScrollBar ) 2776 m_vScrollBar = NULL ; 2777 2778 wxWindowBase::RemoveChild( child ) ; 2779} 2780 2781// New function that will replace some of the above. 2782void wxWindowMac::SetScrollbar(int orient, int pos, int thumbVisible, 2783 int range, bool refresh) 2784{ 2785 bool showScroller; 2786 bool triggerSizeEvent = false; 2787 2788 if ( orient == wxHORIZONTAL ) 2789 { 2790 if ( m_hScrollBar ) 2791 { 2792 showScroller = HasFlag( wxALWAYS_SHOW_SB ) || ((range != 0) && (range > thumbVisible)); 2793 if ( m_hScrollBar->IsShown() != showScroller ) 2794 { 2795 m_hScrollBar->Show( showScroller ); 2796 triggerSizeEvent = true; 2797 } 2798 2799 m_hScrollBar->SetScrollbar( pos , thumbVisible , range , thumbVisible , refresh ) ; 2800 } 2801 } 2802 else 2803 { 2804 if ( m_vScrollBar ) 2805 { 2806 showScroller = HasFlag( wxALWAYS_SHOW_SB ) || ((range != 0) && (range > thumbVisible)); 2807 if ( m_vScrollBar->IsShown() != showScroller ) 2808 { 2809 m_vScrollBar->Show( showScroller ) ; 2810 triggerSizeEvent = true; 2811 } 2812 2813 m_vScrollBar->SetScrollbar( pos , thumbVisible , range , thumbVisible , refresh ) ; 2814 } 2815 } 2816 2817 MacRepositionScrollBars() ; 2818 if ( triggerSizeEvent ) 2819 { 2820 wxSizeEvent event(GetSize(), m_windowId); 2821 event.SetEventObject(this); 2822 GetEventHandler()->ProcessEvent(event); 2823 } 2824} 2825 2826// Does a physical scroll 2827void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect) 2828{ 2829 if ( dx == 0 && dy == 0 ) 2830 return ; 2831 2832 int width , height ; 2833 GetClientSize( &width , &height ) ; 2834 2835 if ( m_peer != NULL ) 2836 { 2837 // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control 2838 // area is scrolled, this does not occur if width and height are 2 pixels less, 2839 // TODO: write optimal workaround 2840 wxRect scrollrect( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ; 2841 if ( rect ) 2842 scrollrect.Intersect( *rect ) ; 2843 2844 if ( m_peer->GetNeedsDisplay() ) 2845 { 2846 // because HIViewScrollRect does not scroll the already invalidated area we have two options 2847 // in case there is already a pending redraw on that area 2848 // either immediate redraw or full invalidate 2849#if 1 2850 // is the better overall solution, as it does not slow down scrolling 2851 m_peer->SetNeedsDisplay() ; 2852#else 2853 // this would be the preferred version for fast drawing controls 2854 2855#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 2856 if ( UMAGetSystemVersion() >= 0x1030 ) 2857 HIViewRender(m_peer->GetControlRef()) ; 2858 else 2859#endif 2860 Update() ; 2861#endif 2862 } 2863 2864 // as the native control might be not a 0/0 wx window coordinates, we have to offset 2865 scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ; 2866 m_peer->ScrollRect( &scrollrect , dx , dy ) ; 2867 2868#if 0 2869 // this would be the preferred version for fast drawing controls 2870 HIViewRender(m_peer->GetControlRef()) ; 2871#endif 2872 } 2873 2874 wxWindowMac *child; 2875 int x, y, w, h; 2876 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext()) 2877 { 2878 child = node->GetData(); 2879 if (child == NULL) 2880 continue; 2881 if (child == m_vScrollBar) 2882 continue; 2883 if (child == m_hScrollBar) 2884 continue; 2885 if (child->IsTopLevel()) 2886 continue; 2887 2888 child->GetPosition( &x, &y ); 2889 child->GetSize( &w, &h ); 2890 if (rect) 2891 { 2892 wxRect rc( x, y, w, h ); 2893 if (rect->Intersects( rc )) 2894 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE ); 2895 } 2896 else 2897 { 2898 child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE ); 2899 } 2900 } 2901} 2902 2903void wxWindowMac::MacOnScroll( wxScrollEvent &event ) 2904{ 2905 if ( event.GetEventObject() == m_vScrollBar || event.GetEventObject() == m_hScrollBar ) 2906 { 2907 wxScrollWinEvent wevent; 2908 wevent.SetPosition(event.GetPosition()); 2909 wevent.SetOrientation(event.GetOrientation()); 2910 wevent.SetEventObject(this); 2911 2912 if (event.GetEventType() == wxEVT_SCROLL_TOP) 2913 wevent.SetEventType( wxEVT_SCROLLWIN_TOP ); 2914 else if (event.GetEventType() == wxEVT_SCROLL_BOTTOM) 2915 wevent.SetEventType( wxEVT_SCROLLWIN_BOTTOM ); 2916 else if (event.GetEventType() == wxEVT_SCROLL_LINEUP) 2917 wevent.SetEventType( wxEVT_SCROLLWIN_LINEUP ); 2918 else if (event.GetEventType() == wxEVT_SCROLL_LINEDOWN) 2919 wevent.SetEventType( wxEVT_SCROLLWIN_LINEDOWN ); 2920 else if (event.GetEventType() == wxEVT_SCROLL_PAGEUP) 2921 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEUP ); 2922 else if (event.GetEventType() == wxEVT_SCROLL_PAGEDOWN) 2923 wevent.SetEventType( wxEVT_SCROLLWIN_PAGEDOWN ); 2924 else if (event.GetEventType() == wxEVT_SCROLL_THUMBTRACK) 2925 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBTRACK ); 2926 else if (event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE) 2927 wevent.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE ); 2928 2929 GetEventHandler()->ProcessEvent(wevent); 2930 } 2931} 2932 2933// Get the window with the focus 2934wxWindow *wxWindowBase::DoFindFocus() 2935{ 2936 ControlRef control ; 2937 GetKeyboardFocus( GetUserFocusWindow() , &control ) ; 2938 wxLogTrace(_T("focus"), _T("FindFocus(windowref=%p, peer =%p, wxwindow = %p)"), 2939 wx_static_cast(void*, GetUserFocusWindow()), wx_static_cast(void*, control) 2940 , wx_static_cast(void*, wxFindControlFromMacControl( control ))); 2941 return (wxWindow*)wxFindControlFromMacControl( control ) ; 2942} 2943 2944void wxWindowMac::OnSetFocus( wxFocusEvent& event ) 2945{ 2946 if ( m_peer != NULL && MacGetTopLevelWindow() && m_peer->NeedsFocusRect() ) 2947 { 2948#if wxMAC_USE_CORE_GRAPHICS 2949 GetParent()->Refresh() ; 2950#else 2951 wxMacWindowStateSaver sv( this ) ; 2952 Rect rect ; 2953 2954 m_peer->GetRect( &rect ) ; 2955 // auf den umgebenden Rahmen zurck 2956 InsetRect( &rect, -1 , -1 ) ; 2957 2958 wxTopLevelWindowMac* top = MacGetTopLevelWindow(); 2959 if ( top ) 2960 { 2961 wxPoint pt(0, 0) ; 2962 wxMacControl::Convert( &pt , GetParent()->m_peer , top->m_peer ) ; 2963 rect.left += pt.x ; 2964 rect.right += pt.x ; 2965 rect.top += pt.y ; 2966 rect.bottom += pt.y ; 2967 } 2968 2969 bool bIsFocusEvent = (event.GetEventType() == wxEVT_SET_FOCUS); 2970 DrawThemeFocusRect( &rect , bIsFocusEvent ) ; 2971 if ( !bIsFocusEvent ) 2972 { 2973 // as this erases part of the frame we have to redraw borders 2974 // and because our z-ordering is not always correct (staticboxes) 2975 // we have to invalidate things, we cannot simple redraw 2976 MacInvalidateBorders() ; 2977 } 2978#endif 2979 } 2980} 2981 2982void wxWindowMac::OnInternalIdle() 2983{ 2984 // This calls the UI-update mechanism (querying windows for 2985 // menu/toolbar/control state information) 2986 if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen()) 2987 UpdateWindowUI(wxUPDATE_UI_FROMIDLE); 2988} 2989 2990// Raise the window to the top of the Z order 2991void wxWindowMac::Raise() 2992{ 2993 if( m_peer ) 2994 m_peer->SetZOrder( true , NULL ) ; 2995} 2996 2997// Lower the window to the bottom of the Z order 2998void wxWindowMac::Lower() 2999{ 3000 if ( m_peer ) 3001 m_peer->SetZOrder( false , NULL ) ; 3002} 3003 3004// static wxWindow *gs_lastWhich = NULL; 3005 3006bool wxWindowMac::MacSetupCursor( const wxPoint& pt ) 3007{ 3008 // first trigger a set cursor event 3009 3010 wxPoint clientorigin = GetClientAreaOrigin() ; 3011 wxSize clientsize = GetClientSize() ; 3012 wxCursor cursor ; 3013 if ( wxRect2DInt( clientorigin.x , clientorigin.y , clientsize.x , clientsize.y ).Contains( wxPoint2DInt( pt ) ) ) 3014 { 3015 wxSetCursorEvent event( pt.x , pt.y ); 3016 3017 bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event); 3018 if ( processedEvtSetCursor && event.HasCursor() ) 3019 { 3020 cursor = event.GetCursor() ; 3021 } 3022 else 3023 { 3024 // the test for processedEvtSetCursor is here to prevent using m_cursor 3025 // if the user code caught EVT_SET_CURSOR() and returned nothing from 3026 // it - this is a way to say that our cursor shouldn't be used for this 3027 // point 3028 if ( !processedEvtSetCursor && m_cursor.Ok() ) 3029 cursor = m_cursor ; 3030 3031 if ( !wxIsBusy() && !GetParent() ) 3032 cursor = *wxSTANDARD_CURSOR ; 3033 } 3034 3035 if ( cursor.Ok() ) 3036 cursor.MacInstall() ; 3037 } 3038 3039 return cursor.Ok() ; 3040} 3041 3042wxString wxWindowMac::MacGetToolTipString( wxPoint &pt ) 3043{ 3044#if wxUSE_TOOLTIPS 3045 if ( m_tooltip ) 3046 return m_tooltip->GetTip() ; 3047#endif 3048 3049 return wxEmptyString ; 3050} 3051 3052void wxWindowMac::ClearBackground() 3053{ 3054 Refresh() ; 3055 Update() ; 3056} 3057 3058void wxWindowMac::Update() 3059{ 3060 if ( m_peer == NULL ) 3061 return ; 3062#if TARGET_API_MAC_OSX 3063 wxTopLevelWindowMac* top = MacGetTopLevelWindow(); 3064 if (top) 3065 top->MacPerformUpdates() ; 3066#else 3067 ::Draw1Control( m_peer->GetControlRef() ) ; 3068#endif 3069} 3070 3071wxTopLevelWindowMac* wxWindowMac::MacGetTopLevelWindow() const 3072{ 3073 wxTopLevelWindowMac* win = NULL ; 3074 WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ; 3075 if ( window ) 3076 win = wxFindWinFromMacWindow( window ) ; 3077 3078 return win ; 3079} 3080 3081const wxRect& wxWindowMac::MacGetClippedClientRect() const 3082{ 3083 MacUpdateClippedRects() ; 3084 3085 return m_cachedClippedClientRect ; 3086} 3087 3088const wxRect& wxWindowMac::MacGetClippedRect() const 3089{ 3090 MacUpdateClippedRects() ; 3091 3092 return m_cachedClippedRect ; 3093} 3094 3095const wxRect&wxWindowMac:: MacGetClippedRectWithOuterStructure() const 3096{ 3097 MacUpdateClippedRects() ; 3098 3099 return m_cachedClippedRectWithOuterStructure ; 3100} 3101 3102const wxRegion& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures ) 3103{ 3104 static wxRegion emptyrgn ; 3105 3106 if ( !m_isBeingDeleted && MacIsReallyShown() /*m_peer->IsVisible() */ ) 3107 { 3108 MacUpdateClippedRects() ; 3109 if ( includeOuterStructures ) 3110 return m_cachedClippedRegionWithOuterStructure ; 3111 else 3112 return m_cachedClippedRegion ; 3113 } 3114 else 3115 { 3116 return emptyrgn ; 3117 } 3118} 3119 3120void wxWindowMac::MacUpdateClippedRects() const 3121{ 3122 if ( m_cachedClippedRectValid ) 3123 return ; 3124 3125 if ( m_peer == NULL ) 3126 return; 3127 3128 // includeOuterStructures is true if we try to draw somthing like a focus ring etc. 3129 // also a window dc uses this, in this case we only clip in the hierarchy for hard 3130 // borders like a scrollwindow, splitter etc otherwise we end up in a paranoia having 3131 // to add focus borders everywhere 3132 3133 Rect r, rIncludingOuterStructures ; 3134 3135 m_peer->GetRect( &r ) ; 3136 r.left -= MacGetLeftBorderSize() ; 3137 r.top -= MacGetTopBorderSize() ; 3138 r.bottom += MacGetBottomBorderSize() ; 3139 r.right += MacGetRightBorderSize() ; 3140 3141 r.right -= r.left ; 3142 r.bottom -= r.top ; 3143 r.left = 0 ; 3144 r.top = 0 ; 3145 3146 rIncludingOuterStructures = r ; 3147 InsetRect( &rIncludingOuterStructures , -4 , -4 ) ; 3148 3149 wxRect cl = GetClientRect() ; 3150 Rect rClient = { cl.y , cl.x , cl.y + cl.height , cl.x + cl.width } ; 3151 3152 int x , y ; 3153 wxSize size ; 3154 const wxWindowMac* child = this ; 3155 const wxWindowMac* parent = NULL ; 3156 3157 while ( !child->IsTopLevel() && ( parent = child->GetParent() ) != NULL ) 3158 { 3159 if ( parent->MacIsChildOfClientArea((wxWindow*)child) ) 3160 { 3161 size = parent->GetClientSize() ; 3162 wxPoint origin = parent->GetClientAreaOrigin() ; 3163 x = origin.x ; 3164 y = origin.y ; 3165 } 3166 else 3167 { 3168 // this will be true for scrollbars, toolbars etc. 3169 size = parent->GetSize() ; 3170 y = parent->MacGetTopBorderSize() ; 3171 x = parent->MacGetLeftBorderSize() ; 3172 size.x -= parent->MacGetLeftBorderSize() + parent->MacGetRightBorderSize() ; 3173 size.y -= parent->MacGetTopBorderSize() + parent->MacGetBottomBorderSize() ; 3174 } 3175 3176 parent->MacWindowToRootWindow( &x, &y ) ; 3177 MacRootWindowToWindow( &x , &y ) ; 3178 3179 Rect rparent = { y , x , y + size.y , x + size.x } ; 3180 3181 // the wxwindow and client rects will always be clipped 3182 SectRect( &r , &rparent , &r ) ; 3183 SectRect( &rClient , &rparent , &rClient ) ; 3184 3185 // the structure only at 'hard' borders 3186 if ( parent->MacClipChildren() || 3187 ( parent->GetParent() && parent->GetParent()->MacClipGrandChildren() ) ) 3188 { 3189 SectRect( &rIncludingOuterStructures , &rparent , &rIncludingOuterStructures ) ; 3190 } 3191 3192 child = parent ; 3193 } 3194 3195 m_cachedClippedRect = wxRect( r.left , r.top , r.right - r.left , r.bottom - r.top ) ; 3196 m_cachedClippedClientRect = wxRect( rClient.left , rClient.top , 3197 rClient.right - rClient.left , rClient.bottom - rClient.top ) ; 3198 m_cachedClippedRectWithOuterStructure = wxRect( 3199 rIncludingOuterStructures.left , rIncludingOuterStructures.top , 3200 rIncludingOuterStructures.right - rIncludingOuterStructures.left , 3201 rIncludingOuterStructures.bottom - rIncludingOuterStructures.top ) ; 3202 3203 m_cachedClippedRegionWithOuterStructure = wxRegion( m_cachedClippedRectWithOuterStructure ) ; 3204 m_cachedClippedRegion = wxRegion( m_cachedClippedRect ) ; 3205 m_cachedClippedClientRegion = wxRegion( m_cachedClippedClientRect ) ; 3206 3207 m_cachedClippedRectValid = true ; 3208} 3209 3210/* 3211 This function must not change the updatergn ! 3212 */ 3213bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time ) 3214{ 3215 bool handled = false ; 3216 Rect updatebounds ; 3217 RgnHandle updatergn = (RgnHandle) updatergnr ; 3218 GetRegionBounds( updatergn , &updatebounds ) ; 3219 3220 // wxLogDebug(wxT("update for %s bounds %d, %d, %d, %d"), wxString(GetClassInfo()->GetClassName()).c_str(), updatebounds.left, updatebounds.top , updatebounds.right , updatebounds.bottom ) ; 3221 3222 if ( !EmptyRgn(updatergn) ) 3223 { 3224 RgnHandle newupdate = NewRgn() ; 3225 wxSize point = GetClientSize() ; 3226 wxPoint origin = GetClientAreaOrigin() ; 3227 SetRectRgn( newupdate , origin.x , origin.y , origin.x + point.x , origin.y + point.y ) ; 3228 SectRgn( newupdate , updatergn , newupdate ) ; 3229 3230 // first send an erase event to the entire update area 3231 { 3232 // for the toplevel window this really is the entire area 3233 // for all the others only their client area, otherwise they 3234 // might be drawing with full alpha and eg put blue into 3235 // the grow-box area of a scrolled window (scroll sample) 3236 wxDC* dc = new wxWindowDC((wxWindow*)this); 3237 if ( IsTopLevel() ) 3238 dc->SetClippingRegion(wxRegion(updatergn)); 3239 else 3240 dc->SetClippingRegion(wxRegion(newupdate)); 3241 3242 wxEraseEvent eevent( GetId(), dc ); 3243 eevent.SetEventObject( this ); 3244 GetEventHandler()->ProcessEvent( eevent ); 3245 delete dc ; 3246 } 3247 3248 MacPaintGrowBox(); 3249 3250 // calculate a client-origin version of the update rgn and set m_updateRegion to that 3251 OffsetRgn( newupdate , -origin.x , -origin.y ) ; 3252 m_updateRegion = newupdate ; 3253 DisposeRgn( newupdate ) ; 3254 3255 if ( !m_updateRegion.Empty() ) 3256 { 3257 // paint the window itself 3258 3259 wxPaintEvent event(GetId()); 3260 event.SetTimestamp(time); 3261 event.SetEventObject(this); 3262 GetEventHandler()->ProcessEvent(event); 3263 handled = true ; 3264 } 3265 3266 // now we cannot rely on having its borders drawn by a window itself, as it does not 3267 // get the updateRgn wide enough to always do so, so we do it from the parent 3268 // this would also be the place to draw any custom backgrounds for native controls 3269 // in Composited windowing 3270 wxPoint clientOrigin = GetClientAreaOrigin() ; 3271 3272 wxWindowMac *child; 3273 int x, y, w, h; 3274 for (wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); node; node = node->GetNext()) 3275 { 3276 child = node->GetData(); 3277 if (child == NULL) 3278 continue; 3279 if (child == m_vScrollBar) 3280 continue; 3281 if (child == m_hScrollBar) 3282 continue; 3283 if (child->IsTopLevel()) 3284 continue; 3285 if (!child->IsShown()) 3286 continue; 3287 3288 // only draw those in the update region (add a safety margin of 10 pixels for shadow effects 3289 3290 child->GetPosition( &x, &y ); 3291 child->GetSize( &w, &h ); 3292 Rect childRect = { y , x , y + h , x + w } ; 3293 OffsetRect( &childRect , clientOrigin.x , clientOrigin.y ) ; 3294 InsetRect( &childRect , -10 , -10) ; 3295 3296 if ( RectInRgn( &childRect , updatergn ) ) 3297 { 3298 // paint custom borders 3299 wxNcPaintEvent eventNc( child->GetId() ); 3300 eventNc.SetEventObject( child ); 3301 if ( !child->GetEventHandler()->ProcessEvent( eventNc ) ) 3302 { 3303#if wxMAC_USE_CORE_GRAPHICS 3304 child->MacPaintBorders(0, 0) ; 3305#else 3306 { 3307 wxWindowDC dc(this) ; 3308 dc.SetClippingRegion(wxRegion(updatergn)); 3309 wxMacPortSetter helper(&dc) ; 3310 child->MacPaintBorders(0, 0) ; 3311 } 3312#endif 3313 } 3314 } 3315 } 3316 } 3317 3318 return handled ; 3319} 3320 3321 3322WXWindow wxWindowMac::MacGetTopLevelWindowRef() const 3323{ 3324 wxWindowMac *iter = (wxWindowMac*)this ; 3325 3326 while ( iter ) 3327 { 3328 if ( iter->IsTopLevel() ) 3329 { 3330 wxTopLevelWindow* toplevel = wxDynamicCast(iter,wxTopLevelWindow); 3331 if ( toplevel ) 3332 return toplevel->MacGetWindowRef(); 3333#if wxUSE_POPUPWIN 3334 wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow); 3335 if ( popupwin ) 3336 return popupwin->MacGetPopupWindowRef(); 3337#endif 3338 } 3339 iter = iter->GetParent() ; 3340 } 3341 3342 return NULL ; 3343} 3344 3345bool wxWindowMac::MacHasScrollBarCorner() const 3346{ 3347 /* Returns whether the scroll bars in a wxScrolledWindow should be 3348 * shortened. Scroll bars should be shortened if either: 3349 * 3350 * - both scroll bars are visible, or 3351 * 3352 * - there is a resize box in the parent frame's corner and this 3353 * window shares the bottom and right edge with the parent 3354 * frame. 3355 */ 3356 3357 if ( m_hScrollBar == NULL && m_vScrollBar == NULL ) 3358 return false; 3359 3360 if ( ( m_hScrollBar && m_hScrollBar->IsShown() ) 3361 && ( m_vScrollBar && m_vScrollBar->IsShown() ) ) 3362 { 3363 // Both scroll bars visible 3364 return true; 3365 } 3366 else 3367 { 3368 wxPoint thisWindowBottomRight = GetScreenRect().GetBottomRight(); 3369 3370 for ( const wxWindow *win = this; win; win = win->GetParent() ) 3371 { 3372 const wxFrame *frame = wxDynamicCast( win, wxFrame ) ; 3373 if ( frame ) 3374 { 3375 if ( frame->GetWindowStyleFlag() & wxRESIZE_BORDER ) 3376 { 3377 // Parent frame has resize handle 3378 wxPoint frameBottomRight = frame->GetScreenRect().GetBottomRight(); 3379 3380 // Note: allow for some wiggle room here as wxMac's 3381 // window rect calculations seem to be imprecise 3382 if ( abs( thisWindowBottomRight.x - frameBottomRight.x ) <= 2 3383 && abs( thisWindowBottomRight.y - frameBottomRight.y ) <= 2 ) 3384 { 3385 // Parent frame has resize handle and shares 3386 // right bottom corner 3387 return true ; 3388 } 3389 else 3390 { 3391 // Parent frame has resize handle but doesn't 3392 // share right bottom corner 3393 return false ; 3394 } 3395 } 3396 else 3397 { 3398 // Parent frame doesn't have resize handle 3399 return false ; 3400 } 3401 } 3402 } 3403 3404 // No parent frame found 3405 return false ; 3406 } 3407} 3408 3409void wxWindowMac::MacCreateScrollBars( long style ) 3410{ 3411 wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ; 3412 3413 if ( style & ( wxVSCROLL | wxHSCROLL ) ) 3414 { 3415 int scrlsize = MAC_SCROLLBAR_SIZE ; 3416 if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI ) 3417 { 3418 scrlsize = MAC_SMALL_SCROLLBAR_SIZE ; 3419 } 3420 3421 int adjust = MacHasScrollBarCorner() ? scrlsize - 1: 0 ; 3422 int width, height ; 3423 GetClientSize( &width , &height ) ; 3424 3425 wxPoint vPoint(width - scrlsize, 0) ; 3426 wxSize vSize(scrlsize, height - adjust) ; 3427 wxPoint hPoint(0, height - scrlsize) ; 3428 wxSize hSize(width - adjust, scrlsize) ; 3429 3430 // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize) 3431 if ( style & wxVSCROLL ) 3432 { 3433 m_vScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, vPoint, vSize , wxVERTICAL); 3434 m_vScrollBar->SetMinSize( wxDefaultSize ); 3435 } 3436 3437 if ( style & wxHSCROLL ) 3438 { 3439 m_hScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, hPoint, hSize , wxHORIZONTAL); 3440 m_hScrollBar->SetMinSize( wxDefaultSize ); 3441 } 3442 } 3443 3444 // because the create does not take into account the client area origin 3445 // we might have a real position shift 3446 MacRepositionScrollBars() ; 3447} 3448 3449bool wxWindowMac::MacIsChildOfClientArea( const wxWindow* child ) const 3450{ 3451 bool result = ((child == NULL) || ((child != m_hScrollBar) && (child != m_vScrollBar))); 3452 3453 return result ; 3454} 3455 3456void wxWindowMac::MacRepositionScrollBars() 3457{ 3458 if ( !m_hScrollBar && !m_vScrollBar ) 3459 return ; 3460 3461 int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ; 3462 int adjust = MacHasScrollBarCorner() ? scrlsize - 1 : 0 ; 3463 3464 // get real client area 3465 int width, height ; 3466 GetSize( &width , &height ); 3467 3468 width -= MacGetLeftBorderSize() + MacGetRightBorderSize(); 3469 height -= MacGetTopBorderSize() + MacGetBottomBorderSize(); 3470 3471 wxPoint vPoint( width - scrlsize, 0 ) ; 3472 wxSize vSize( scrlsize, height - adjust ) ; 3473 wxPoint hPoint( 0 , height - scrlsize ) ; 3474 wxSize hSize( width - adjust, scrlsize ) ; 3475 3476#if 0 3477 int x = 0, y = 0, w, h ; 3478 GetSize( &w , &h ) ; 3479 3480 MacClientToRootWindow( &x , &y ) ; 3481 MacClientToRootWindow( &w , &h ) ; 3482 3483 wxWindowMac *iter = (wxWindowMac*)this ; 3484 3485 int totW = 10000 , totH = 10000; 3486 while ( iter ) 3487 { 3488 if ( iter->IsTopLevel() ) 3489 { 3490 iter->GetSize( &totW , &totH ) ; 3491 break ; 3492 } 3493 3494 iter = iter->GetParent() ; 3495 } 3496 3497 if ( x == 0 ) 3498 { 3499 hPoint.x = -1 ; 3500 hSize.x += 1 ; 3501 } 3502 if ( y == 0 ) 3503 { 3504 vPoint.y = -1 ; 3505 vSize.y += 1 ; 3506 } 3507 3508 if ( w - x >= totW ) 3509 { 3510 hSize.x += 1 ; 3511 vPoint.x += 1 ; 3512 } 3513 if ( h - y >= totH ) 3514 { 3515 vSize.y += 1 ; 3516 hPoint.y += 1 ; 3517 } 3518#endif 3519 3520 if ( m_vScrollBar ) 3521 m_vScrollBar->SetSize( vPoint.x , vPoint.y, vSize.x, vSize.y , wxSIZE_ALLOW_MINUS_ONE ); 3522 if ( m_hScrollBar ) 3523 m_hScrollBar->SetSize( hPoint.x , hPoint.y, hSize.x, hSize.y, wxSIZE_ALLOW_MINUS_ONE ); 3524} 3525 3526bool wxWindowMac::AcceptsFocus() const 3527{ 3528 return MacCanFocus() && wxWindowBase::AcceptsFocus(); 3529} 3530 3531void wxWindowMac::MacSuperChangedPosition() 3532{ 3533 // only window-absolute structures have to be moved i.e. controls 3534 3535 m_cachedClippedRectValid = false ; 3536 3537 wxWindowMac *child; 3538 wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); 3539 while ( node ) 3540 { 3541 child = node->GetData(); 3542 child->MacSuperChangedPosition() ; 3543 3544 node = node->GetNext(); 3545 } 3546} 3547 3548void wxWindowMac::MacTopLevelWindowChangedPosition() 3549{ 3550 // only screen-absolute structures have to be moved i.e. glcanvas 3551 3552 wxWindowMac *child; 3553 wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); 3554 while ( node ) 3555 { 3556 child = node->GetData(); 3557 child->MacTopLevelWindowChangedPosition() ; 3558 3559 node = node->GetNext(); 3560 } 3561} 3562 3563long wxWindowMac::MacGetLeftBorderSize() const 3564{ 3565 if ( IsTopLevel() ) 3566 return 0 ; 3567 3568 SInt32 border = 0 ; 3569 3570 if (HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER)) 3571 { 3572 // this metric is only the 'outset' outside the simple frame rect 3573 GetThemeMetric( kThemeMetricEditTextFrameOutset , &border ) ; 3574 border += 1 ; 3575 } 3576 else if (HasFlag(wxSIMPLE_BORDER)) 3577 { 3578 // this metric is only the 'outset' outside the simple frame rect 3579 GetThemeMetric( kThemeMetricListBoxFrameOutset , &border ) ; 3580 border += 1 ; 3581 } 3582 3583 return border ; 3584} 3585 3586long wxWindowMac::MacGetRightBorderSize() const 3587{ 3588 // they are all symmetric in mac themes 3589 return MacGetLeftBorderSize() ; 3590} 3591 3592long wxWindowMac::MacGetTopBorderSize() const 3593{ 3594 // they are all symmetric in mac themes 3595 return MacGetLeftBorderSize() ; 3596} 3597 3598long wxWindowMac::MacGetBottomBorderSize() const 3599{ 3600 // they are all symmetric in mac themes 3601 return MacGetLeftBorderSize() ; 3602} 3603 3604long wxWindowMac::MacRemoveBordersFromStyle( long style ) 3605{ 3606 return style & ~wxBORDER_MASK ; 3607} 3608 3609// Find the wxWindowMac at the current mouse position, returning the mouse 3610// position. 3611wxWindow * wxFindWindowAtPointer( wxPoint& pt ) 3612{ 3613 pt = wxGetMousePosition(); 3614 wxWindowMac* found = wxFindWindowAtPoint(pt); 3615 3616 return (wxWindow*) found; 3617} 3618 3619// Get the current mouse position. 3620wxPoint wxGetMousePosition() 3621{ 3622 int x, y; 3623 3624 wxGetMousePosition( &x, &y ); 3625 3626 return wxPoint(x, y); 3627} 3628 3629void wxWindowMac::OnMouseEvent( wxMouseEvent &event ) 3630{ 3631 if ( event.GetEventType() == wxEVT_RIGHT_DOWN ) 3632 { 3633 // copied from wxGTK : CS 3634 // VZ: shouldn't we move this to base class then? 3635 3636 // generate a "context menu" event: this is similar to wxEVT_RIGHT_DOWN 3637 // except that: 3638 // 3639 // (a) it's a command event and so is propagated to the parent 3640 // (b) under MSW it can be generated from kbd too 3641 // (c) it uses screen coords (because of (a)) 3642 wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, 3643 this->GetId(), 3644 this->ClientToScreen(event.GetPosition())); 3645 evtCtx.SetEventObject(this); 3646 if ( ! GetEventHandler()->ProcessEvent(evtCtx) ) 3647 event.Skip() ; 3648 } 3649 else 3650 { 3651 event.Skip() ; 3652 } 3653} 3654 3655void wxWindowMac::OnPaint( wxPaintEvent & event ) 3656{ 3657 if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL ) 3658 CallNextEventHandler( 3659 (EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , 3660 (EventRef) wxTheApp->MacGetCurrentEvent() ) ; 3661} 3662 3663void wxWindowMac::MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool WXUNUSED( mouseStillDown ) ) 3664{ 3665} 3666 3667Rect wxMacGetBoundsForControl( wxWindowMac* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin ) 3668{ 3669 int x, y, w, h ; 3670 3671 window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin ) ; 3672 Rect bounds = { y, x, y + h, x + w }; 3673 3674 return bounds ; 3675} 3676 3677wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) ) 3678{ 3679 return eventNotHandledErr ; 3680} 3681 3682bool wxWindowMac::Reparent(wxWindowBase *newParentBase) 3683{ 3684 wxWindowMac *newParent = (wxWindowMac *)newParentBase; 3685 if ( !wxWindowBase::Reparent(newParent) ) 3686 return false; 3687 3688 // copied from MacPostControlCreate 3689 if ( m_peer ) 3690 { 3691 ControlRef container = (ControlRef) GetParent()->GetHandle() ; 3692 3693 wxASSERT_MSG( container != NULL , wxT("No valid mac container control") ) ; 3694 3695 ::EmbedControl( m_peer->GetControlRef() , container ) ; 3696 3697 MacChildAdded(); 3698 } 3699 return true; 3700} 3701 3702bool wxWindowMac::SetTransparent(wxByte alpha) 3703{ 3704#if wxMAC_USE_CORE_GRAPHICS 3705 if ( alpha != m_macAlpha ) 3706 { 3707 m_macAlpha = alpha ; 3708 Refresh() ; 3709 } 3710 return true ; 3711#else 3712 return false ; 3713#endif 3714} 3715 3716 3717bool wxWindowMac::CanSetTransparent() 3718{ 3719#if wxMAC_USE_CORE_GRAPHICS 3720 return true ; 3721#else 3722 return false ; 3723#endif 3724} 3725 3726wxByte wxWindowMac::GetTransparent() const 3727{ 3728 return m_macAlpha ; 3729} 3730