X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/586031781c170a51f71ead63ce0875c32745dcf0..908eeca88dee75d5ac3ba10d539fb7e0f5387d2c:/src/mac/carbon/window.cpp diff --git a/src/mac/carbon/window.cpp b/src/mac/carbon/window.cpp index 7116cf645f..6c158e6acd 100644 --- a/src/mac/carbon/window.cpp +++ b/src/mac/carbon/window.cpp @@ -11,61 +11,62 @@ #include "wx/wxprec.h" -#include "wx/menu.h" #include "wx/window.h" -#include "wx/dc.h" -#include "wx/dcclient.h" -#include "wx/utils.h" -#include "wx/app.h" -#include "wx/panel.h" -#include "wx/layout.h" -#include "wx/dialog.h" -#include "wx/scrolbar.h" -#include "wx/statbox.h" -#include "wx/button.h" -#include "wx/settings.h" -#include "wx/msgdlg.h" -#include "wx/frame.h" + +#ifndef WX_PRECOMP + #include "wx/log.h" + #include "wx/app.h" + #include "wx/utils.h" + #include "wx/panel.h" + #include "wx/frame.h" + #include "wx/dc.h" + #include "wx/dcclient.h" + #include "wx/button.h" + #include "wx/menu.h" + #include "wx/dialog.h" + #include "wx/settings.h" + #include "wx/msgdlg.h" + #include "wx/scrolbar.h" + #include "wx/statbox.h" + #include "wx/textctrl.h" + #include "wx/toolbar.h" + #include "wx/layout.h" + #include "wx/statusbr.h" + #include "wx/menuitem.h" + #include "wx/treectrl.h" + #include "wx/listctrl.h" +#endif + #include "wx/tooltip.h" -#include "wx/statusbr.h" -#include "wx/menuitem.h" #include "wx/spinctrl.h" -#include "wx/log.h" #include "wx/geometry.h" -#include "wx/textctrl.h" -#include "wx/toolbar.h" -#include "wx/dc.h" - -#if wxUSE_CARET - #include "wx/caret.h" +#if wxUSE_LISTCTRL + #include "wx/listctrl.h" #endif -#define MAC_SCROLLBAR_SIZE 15 -#define MAC_SMALL_SCROLLBAR_SIZE 11 - -#include "wx/mac/uma.h" - -#ifndef __DARWIN__ -#include -#include -#include -#include +#if wxUSE_TREECTRL + #include "wx/treectrl.h" #endif -#if TARGET_API_MAC_OSX -#ifndef __HIVIEW__ - #include +#if wxUSE_CARET + #include "wx/caret.h" #endif + +#if wxUSE_POPUPWIN + #include "wx/popupwin.h" #endif -#if wxUSE_DRAG_AND_DROP +#if wxUSE_DRAG_AND_DROP #include "wx/dnd.h" #endif -#include +#include "wx/mac/uma.h" + +#define MAC_SCROLLBAR_SIZE 15 +#define MAC_SMALL_SCROLLBAR_SIZE 11 -extern wxList wxPendingDelete; +#include #ifdef __WXUNIVERSAL__ IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase) @@ -76,11 +77,7 @@ extern wxList wxPendingDelete; BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase) EVT_NC_PAINT(wxWindowMac::OnNcPaint) EVT_ERASE_BACKGROUND(wxWindowMac::OnEraseBackground) -#if TARGET_API_MAC_OSX EVT_PAINT(wxWindowMac::OnPaint) -#endif - EVT_SET_FOCUS(wxWindowMac::OnSetFocus) - EVT_KILL_FOCUS(wxWindowMac::OnSetFocus) EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent) END_EVENT_TABLE() @@ -89,8 +86,6 @@ END_EVENT_TABLE() #define wxMAC_DEBUG_REDRAW 0 #endif -#define wxMAC_USE_THEME_BORDER 1 - // --------------------------------------------------------------------------- // Utility Routines to move between different coordinate systems // --------------------------------------------------------------------------- @@ -142,30 +137,28 @@ void wxMacWindowToNative( const wxWindow* window , Rect *rect ) // Carbon Events // --------------------------------------------------------------------------- -extern long wxMacTranslateKey(unsigned char key, unsigned char code) ; -pascal OSStatus wxMacSetupControlBackground( ControlRef iControl , SInt16 iMessage , SInt16 iDepth , Boolean iIsColor ) ; - -#if TARGET_API_MAC_OSX - -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3 -enum -{ - kEventControlVisibilityChanged = 157 -}; -#endif - -#endif - static const EventTypeSpec eventList[] = { + { kEventClassCommand, kEventProcessCommand } , + { kEventClassCommand, kEventCommandUpdateStatus } , + + { kEventClassControl , kEventControlGetClickActivation } , { kEventClassControl , kEventControlHit } , -#if TARGET_API_MAC_OSX + { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent } , + { kEventClassTextInput, kEventTextInputUpdateActiveInputArea } , + { kEventClassControl , kEventControlDraw } , + { kEventClassControl , kEventControlVisibilityChanged } , { kEventClassControl , kEventControlEnabledStateChanged } , { kEventClassControl , kEventControlHiliteChanged } , + + { kEventClassControl , kEventControlActivate } , + { kEventClassControl , kEventControlDeactivate } , + { kEventClassControl , kEventControlSetFocusPart } , + { kEventClassControl , kEventControlFocusPartChanged } , { kEventClassService , kEventServiceGetTypes }, { kEventClassService , kEventServiceCopy }, @@ -173,7 +166,6 @@ static const EventTypeSpec eventList[] = // { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only // { kEventClassControl , kEventControlBoundsChanged } , -#endif } ; static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) @@ -189,56 +181,30 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl switch ( GetEventKind( event ) ) { -#if TARGET_API_MAC_OSX case kEventControlDraw : { RgnHandle updateRgn = NULL ; RgnHandle allocatedRgn = NULL ; wxRegion visRegion = thisWindow->MacGetVisibleRegion() ; - Rect controlBounds ; - - if ( ! thisWindow->GetPeer()->IsCompositing() ) - { - if ( thisWindow->GetPeer()->IsRootControl() ) - thisWindow->GetPeer()->GetRect( &controlBounds ) ; - else - GetControlBounds( thisWindow->GetPeer()->GetControlRef() , &controlBounds ) ; - } if ( cEvent.GetParameter(kEventParamRgnHandle, &updateRgn) != noErr ) { - updateRgn = (RgnHandle) visRegion.GetWXHRGN() ; + HIShapeGetAsQDRgn( visRegion.GetWXHRGN(), updateRgn ); } else { - if ( ! thisWindow->GetPeer()->IsCompositing() ) + if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 ) { + // as this update region is in native window locals we must adapt it to wx window local allocatedRgn = NewRgn() ; CopyRgn( updateRgn , allocatedRgn ) ; - OffsetRgn( allocatedRgn , -controlBounds.left , -controlBounds.top ) ; // hide the given region by the new region that must be shifted wxMacNativeToWindow( thisWindow , allocatedRgn ) ; updateRgn = allocatedRgn ; } - else - { - if ( thisWindow->MacGetLeftBorderSize() != 0 || thisWindow->MacGetTopBorderSize() != 0 ) - { - // as this update region is in native window locals we must adapt it to wx window local - allocatedRgn = NewRgn() ; - CopyRgn( updateRgn , allocatedRgn ) ; - - // hide the given region by the new region that must be shifted - wxMacNativeToWindow( thisWindow , allocatedRgn ) ; - updateRgn = allocatedRgn ; - } - } } - Rect rgnBounds ; - GetRegionBounds( updateRgn , &rgnBounds ) ; - #if wxMAC_DEBUG_REDRAW if ( thisWindow->MacIsUserPane() ) { @@ -263,57 +229,45 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl #endif { -#if wxMAC_USE_CORE_GRAPHICS bool created = false ; CGContextRef cgContext = NULL ; - if ( cEvent.GetParameter(kEventParamCGContextRef, &cgContext) != noErr ) - { - wxASSERT( thisWindow->GetPeer()->IsCompositing() == false ) ; - - // this parameter is not provided on non-composited windows - created = true ; - - // rest of the code expects this to be already transformed and clipped for local - CGrafPtr port = GetWindowPort( (WindowRef) thisWindow->MacGetTopLevelWindowRef() ) ; - Rect bounds ; - GetPortBounds( port , &bounds ) ; - CreateCGContextForPort( port , &cgContext ) ; - - wxMacWindowToNative( thisWindow , updateRgn ) ; - OffsetRgn( updateRgn , controlBounds.left , controlBounds.top ) ; - ClipCGContextToRegion( cgContext , &bounds , updateRgn ) ; - wxMacNativeToWindow( thisWindow , updateRgn ) ; - OffsetRgn( updateRgn , -controlBounds.left , -controlBounds.top ) ; - - CGContextTranslateCTM( cgContext , 0 , bounds.bottom - bounds.top ) ; - CGContextScaleCTM( cgContext , 1 , -1 ) ; - - CGContextTranslateCTM( cgContext , controlBounds.left , controlBounds.top ) ; - -#if 0 - CGContextSetRGBFillColor( cgContext , 1.0 , 1.0 , 1.0 , 1.0 ) ; - CGContextFillRect( cgContext , - CGRectMake( 0 , 0 , - controlBounds.right - controlBounds.left , - controlBounds.bottom - controlBounds.top ) ); -#endif - } - + OSStatus err = cEvent.GetParameter(kEventParamCGContextRef, &cgContext) ; + wxASSERT_MSG( err == noErr , wxT("Unable to retrieve CGContextRef") ) ; thisWindow->MacSetCGContextRef( cgContext ) ; { wxMacCGContextStateSaver sg( cgContext ) ; -#endif + float alpha = 1.0 ; + { + wxWindow* iter = thisWindow ; + while ( iter ) + { + alpha *= (float) iter->GetTransparent()/255.0 ; + if ( iter->IsTopLevel() ) + iter = NULL ; + else + iter = iter->GetParent() ; + } + } + CGContextSetAlpha( cgContext , alpha ) ; + + if ( thisWindow->GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT ) + { + HIRect bounds; + HIViewGetBounds( controlRef, &bounds ); + CGContextClearRect( cgContext, bounds ); + } + + + if ( thisWindow->MacDoRedraw( updateRgn , cEvent.GetTicks() ) ) result = noErr ; -#if wxMAC_USE_CORE_GRAPHICS thisWindow->MacSetCGContextRef( NULL ) ; } if ( created ) CGContextRelease( cgContext ) ; -#endif } if ( allocatedRgn ) @@ -326,33 +280,53 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl break ; case kEventControlEnabledStateChanged : - thisWindow->MacEnabledStateChanged() ; + thisWindow->MacEnabledStateChanged(); break ; case kEventControlHiliteChanged : thisWindow->MacHiliteChanged() ; break ; + + case kEventControlActivate : + case kEventControlDeactivate : + // FIXME: we should have a virtual function for this! +#if wxUSE_TREECTRL + if ( thisWindow->IsKindOf( CLASSINFO( wxTreeCtrl ) ) ) + thisWindow->Refresh(); +#endif +#if wxUSE_LISTCTRL + if ( thisWindow->IsKindOf( CLASSINFO( wxListCtrl ) ) ) + thisWindow->Refresh(); #endif + break ; - // we emulate this event under Carbon CFM - case kEventControlSetFocusPart : + // + // focus handling + // different handling on OS X + // + + case kEventControlFocusPartChanged : + // the event is emulated by wxmac for systems lower than 10.5 { - Boolean focusEverything = false ; - ControlPartCode controlPart = cEvent.GetParameter(kEventParamControlPart , typeControlPartCode ); + ControlPartCode previousControlPart = cEvent.GetParameter(kEventParamControlPreviousPart , typeControlPartCode ); + ControlPartCode currentControlPart = cEvent.GetParameter(kEventParamControlCurrentPart , typeControlPartCode ); -#ifdef __WXMAC_OSX__ - if ( cEvent.GetParameter(kEventParamControlFocusEverything , &focusEverything ) == noErr ) + if ( thisWindow->MacGetTopLevelWindow() && thisWindow->GetPeer()->NeedsFocusRect() ) { + thisWindow->MacInvalidateBorders(); } -#endif - - if ( controlPart == kControlFocusNoPart ) + + if ( currentControlPart == 0 ) { + // kill focus #if wxUSE_CARET if ( thisWindow->GetCaret() ) thisWindow->GetCaret()->OnKillFocus(); #endif - + + wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow)); + + // remove this as soon as posting the synthesized event works properly static bool inKillFocusEvent = false ; if ( !inKillFocusEvent ) @@ -360,28 +334,117 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl inKillFocusEvent = true ; wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId()); event.SetEventObject(thisWindow); - thisWindow->GetEventHandler()->ProcessEvent(event) ; + thisWindow->HandleWindowEvent(event) ; inKillFocusEvent = false ; } } - else + else if ( previousControlPart == 0 ) { + // set focus // panel wants to track the window which was the last to have focus in it - wxChildFocusEvent eventFocus(thisWindow); - thisWindow->GetEventHandler()->ProcessEvent(eventFocus); - + wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow)); + wxChildFocusEvent eventFocus((wxWindow*)thisWindow); + thisWindow->HandleWindowEvent(eventFocus); + #if wxUSE_CARET if ( thisWindow->GetCaret() ) thisWindow->GetCaret()->OnSetFocus(); #endif - + wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId()); event.SetEventObject(thisWindow); - thisWindow->GetEventHandler()->ProcessEvent(event) ; + thisWindow->HandleWindowEvent(event) ; + } + } + break; + case kEventControlSetFocusPart : + { +#ifdef __WXMAC_OSX__ + Boolean focusEverything = false ; + if ( cEvent.GetParameter(kEventParamControlFocusEverything , &focusEverything ) == noErr ) + { + // put a breakpoint here to catch focus everything events } +#endif + ControlPartCode controlPart = cEvent.GetParameter(kEventParamControlPart , typeControlPartCode ); + + ControlPartCode previousControlPart = 0; + verify_noerr( HIViewGetFocusPart(controlRef, &previousControlPart)); if ( thisWindow->MacIsUserPane() ) + { + if ( controlPart != kControlFocusNoPart ) + cEvent.SetParameter( kEventParamControlPart, typeControlPartCode, 1 ) ; result = noErr ; + } + else + result = CallNextEventHandler(handler, event); + + if ( UMAGetSystemVersion() < 0x1050 ) + { +// set back to 0 if problems arise +#if 1 + ControlPartCode currentControlPart = cEvent.GetParameter(kEventParamControlPart , typeControlPartCode ); + // synthesize the event focus changed event + EventRef evRef = NULL ; + + OSStatus err = MacCreateEvent( + NULL , kEventClassControl , kEventControlFocusPartChanged , TicksToEventTime( TickCount() ) , + kEventAttributeUserEvent , &evRef ); + verify_noerr( err ); + + wxMacCarbonEvent iEvent( evRef ) ; + iEvent.SetParameter( kEventParamDirectObject , controlRef ) ; + iEvent.SetParameter( kEventParamControlPreviousPart, typeControlPartCode, previousControlPart ) ; + iEvent.SetParameter( kEventParamControlCurrentPart, typeControlPartCode, currentControlPart ) ; + +#if 0 + // TODO test this first, avoid double posts etc... + PostEventToQueue( GetMainEventQueue(), evRef , kEventPriorityHigh ); +#else + wxMacWindowControlEventHandler( NULL , evRef , data ) ; +#endif + ReleaseEvent( evRef ) ; +#else + // old implementation, to be removed if the new one works + if ( controlPart == kControlFocusNoPart ) + { +#if wxUSE_CARET + if ( thisWindow->GetCaret() ) + thisWindow->GetCaret()->OnKillFocus(); +#endif + + wxLogTrace(_T("Focus"), _T("focus lost(%p)"), wx_static_cast(void*, thisWindow)); + + static bool inKillFocusEvent = false ; + + if ( !inKillFocusEvent ) + { + inKillFocusEvent = true ; + wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId()); + event.SetEventObject(thisWindow); + thisWindow->HandleWindowEvent(event) ; + inKillFocusEvent = false ; + } + } + else + { + // panel wants to track the window which was the last to have focus in it + wxLogTrace(_T("Focus"), _T("focus set(%p)"), wx_static_cast(void*, thisWindow)); + wxChildFocusEvent eventFocus((wxWindow*)thisWindow); + thisWindow->HandleWindowEvent(eventFocus); + + #if wxUSE_CARET + if ( thisWindow->GetCaret() ) + thisWindow->GetCaret()->OnSetFocus(); + #endif + + wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId()); + event.SetEventObject(thisWindow); + thisWindow->HandleWindowEvent(event) ; + } +#endif + } } break ; @@ -389,6 +452,18 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl result = thisWindow->MacControlHit( handler , event ) ; break ; + case kEventControlGetClickActivation : + { + // fix to always have a proper activation for DataBrowser controls (stay in bkgnd otherwise) + WindowRef owner = cEvent.GetParameter(kEventParamWindowRef); + if ( !IsWindowActive(owner) ) + { + cEvent.SetParameter(kEventParamClickActivation,(UInt32) kActivateAndIgnoreClick) ; + result = noErr ; + } + } + break ; + default : break ; } @@ -396,7 +471,10 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl return result ; } -static pascal OSStatus wxMacWindowServiceEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) +static pascal OSStatus +wxMacWindowServiceEventHandler(EventHandlerCallRef WXUNUSED(handler), + EventRef event, + void *data) { OSStatus result = eventNotHandledErr ; @@ -448,9 +526,13 @@ static pascal OSStatus wxMacWindowServiceEventHandler( EventHandlerCallRef handl textCtrl->GetSelection( &from , &to ) ; wxString val = textCtrl->GetValue() ; val = val.Mid( from , to - from ) ; - ScrapRef scrapRef = cEvent.GetParameter< ScrapRef > ( kEventParamScrapRef , typeScrapRef ) ; - verify_noerr( ClearScrap( &scrapRef ) ) ; - verify_noerr( PutScrapFlavor( scrapRef , kTXNTextData , 0 , val.length() , val.c_str() ) ) ; + PasteboardRef pasteboard = cEvent.GetParameter( kEventParamPasteboardRef, typePasteboardRef ); + verify_noerr( PasteboardClear( pasteboard ) ) ; + PasteboardSynchronize( pasteboard ); + // TODO add proper conversion + CFDataRef data = CFDataCreate( kCFAllocatorDefault, (const UInt8*)val.c_str(), val.length() ); + PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) 1, CFSTR("com.apple.traditional-mac-plain-text"), data, 0); + CFRelease( data ); result = noErr ; } break ; @@ -458,22 +540,34 @@ static pascal OSStatus wxMacWindowServiceEventHandler( EventHandlerCallRef handl case kEventServicePaste : if ( textCtrl ) { - ScrapRef scrapRef = cEvent.GetParameter< ScrapRef > ( kEventParamScrapRef , typeScrapRef ) ; - Size textSize, pastedSize ; - verify_noerr( GetScrapFlavorSize(scrapRef, kTXNTextData, &textSize) ) ; - textSize++ ; - char *content = new char[textSize] ; - GetScrapFlavorData(scrapRef, kTXNTextData, &pastedSize, content ); - content[textSize - 1] = 0 ; - + PasteboardRef pasteboard = cEvent.GetParameter( kEventParamPasteboardRef, typePasteboardRef ); + PasteboardSynchronize( pasteboard ); + ItemCount itemCount; + verify_noerr( PasteboardGetItemCount( pasteboard, &itemCount ) ); + for( UInt32 itemIndex = 1; itemIndex <= itemCount; itemIndex++ ) + { + PasteboardItemID itemID; + if ( PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID ) == noErr ) + { + CFDataRef flavorData = NULL; + if ( PasteboardCopyItemFlavorData( pasteboard, itemID, CFSTR("com.apple.traditional-mac-plain-text"), &flavorData ) == noErr ) + { + CFIndex flavorDataSize = CFDataGetLength( flavorData ); + char *content = new char[flavorDataSize+1] ; + memcpy( content, CFDataGetBytePtr( flavorData ), flavorDataSize ); + content[flavorDataSize]=0; + CFRelease( flavorData ); #if wxUSE_UNICODE - textCtrl->WriteText( wxString( content , wxConvLocal ) ); + textCtrl->WriteText( wxString( content , wxConvLocal ) ); #else - textCtrl->WriteText( wxString( content ) ) ; + textCtrl->WriteText( wxString( content ) ) ; #endif - delete[] content ; - result = noErr ; + delete[] content ; + result = noErr ; + } + } + } } break ; @@ -484,161 +578,206 @@ static pascal OSStatus wxMacWindowServiceEventHandler( EventHandlerCallRef handl return result ; } -pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) +pascal OSStatus wxMacUnicodeTextEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) { - EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ; - EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ; - wxTheApp->MacSetCurrentEvent( event , handler ) ; OSStatus result = eventNotHandledErr ; + wxWindowMac* focus = (wxWindowMac*) data ; - switch ( GetEventClass( event ) ) + wchar_t* uniChars = NULL ; + UInt32 when = EventTimeToTicks( GetEventTime( event ) ) ; + + UniChar* charBuf = NULL; + ByteCount dataSize = 0 ; + int numChars = 0 ; + UniChar buf[2] ; + if ( GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, 0 , &dataSize, NULL ) == noErr ) { - case kEventClassControl : - result = wxMacWindowControlEventHandler( handler, event, data ) ; - break ; + numChars = dataSize / sizeof( UniChar) + 1; + charBuf = buf ; - case kEventClassService : - result = wxMacWindowServiceEventHandler( handler, event , data ) ; + if ( (size_t) numChars * 2 > sizeof(buf) ) + charBuf = new UniChar[ numChars ] ; + else + charBuf = buf ; + + uniChars = new wchar_t[ numChars ] ; + GetEventParameter( event, kEventParamTextInputSendText, typeUnicodeText, NULL, dataSize , NULL , charBuf ) ; + charBuf[ numChars - 1 ] = 0; +#if SIZEOF_WCHAR_T == 2 + uniChars = (wchar_t*) charBuf ; +/* 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...) +#else + // the resulting string will never have more chars than the utf16 version, so this is safe + wxMBConvUTF16 converter ; + numChars = converter.MB2WC( uniChars , (const char*)charBuf , numChars ) ; +#endif + } + + switch ( GetEventKind( event ) ) + { + case kEventTextInputUpdateActiveInputArea : + { + // An IME input event may return several characters, but we need to send one char at a time to + // EVT_CHAR + for (int pos=0 ; pos < numChars ; pos++) + { + WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ; + WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ; + wxTheApp->MacSetCurrentEvent( event , handler ) ; + + UInt32 message = uniChars[pos] < 128 ? (char)uniChars[pos] : '?'; +/* + NB: faking a charcode here is problematic. The kEventTextInputUpdateActiveInputArea event is sent + multiple times to update the active range during inline input, so this handler will often receive + uncommited text, which should usually not trigger side effects. It might be a good idea to check the + kEventParamTextInputSendFixLen parameter and verify if input is being confirmed (see CarbonEvents.h). + On the other hand, it can be useful for some applications to react to uncommitted text (for example, + to update a status display), as long as it does not disrupt the inline input session. Ideally, wx + should add new event types to support advanced text input. For now, I would keep things as they are. + + However, the code that was being used caused additional problems: + UInt32 message = (0 << 8) + ((char)uniChars[pos] ); + Since it simply truncated the unichar to the last byte, it ended up causing weird bugs with inline + input, such as switching to another field when one attempted to insert the character U+4E09 (the kanji + for "three"), because it was truncated to 09 (kTabCharCode), which was later "converted" to WXK_TAB + (still 09) in wxMacTranslateKey; or triggering the default button when one attempted to insert U+840D + (the kanji for "name"), which got truncated to 0D and interpreted as a carriage return keypress. + Note that even single-byte characters could have been misinterpreted, since MacRoman charcodes only + overlap with Unicode within the (7-bit) ASCII range. + But simply passing a NUL charcode would disable text updated events, because wxTextCtrl::OnChar checks + for codes within a specific range. Therefore I went for the solution seen above, which keeps ASCII + characters as they are and replaces the rest with '?', ensuring that update events are triggered. + It would be better to change wxTextCtrl::OnChar to look at the actual unicode character instead, but + I don't have time to look into that right now. + -- CL +*/ + if ( wxTheApp->MacSendCharEvent( + focus , message , 0 , when , 0 , 0 , uniChars[pos] ) ) + { + result = noErr ; + } + + wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ; + } + } break ; + case kEventTextInputUnicodeForKeyEvent : + { + UInt32 keyCode, modifiers ; + Point point ; + EventRef rawEvent ; + unsigned char charCode ; + + GetEventParameter( event, kEventParamTextInputSendKeyboardEvent, typeEventRef, NULL, sizeof(rawEvent), NULL, &rawEvent ) ; + GetEventParameter( rawEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &charCode ); + GetEventParameter( rawEvent, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode ); + GetEventParameter( rawEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifiers ); + GetEventParameter( rawEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &point ); + + UInt32 message = (keyCode << 8) + charCode; + + // An IME input event may return several characters, but we need to send one char at a time to + // EVT_CHAR + for (int pos=0 ; pos < numChars ; pos++) + { + WXEVENTREF formerEvent = wxTheApp->MacGetCurrentEvent() ; + WXEVENTHANDLERCALLREF formerHandler = wxTheApp->MacGetCurrentEventHandlerCallRef() ; + wxTheApp->MacSetCurrentEvent( event , handler ) ; - default : + if ( wxTheApp->MacSendCharEvent( + focus , message , modifiers , when , point.h , point.v , uniChars[pos] ) ) + { + result = noErr ; + } + + wxTheApp->MacSetCurrentEvent( formerEvent , formerHandler ) ; + } + } + break; + default: break ; } - wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ; + delete [] uniChars ; + if ( charBuf != buf ) + delete [] charBuf ; return result ; } -DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler ) - -#if !TARGET_API_MAC_OSX - -// --------------------------------------------------------------------------- -// UserPane events for non OSX builds -// --------------------------------------------------------------------------- - -static pascal void wxMacControlUserPaneDrawProc(ControlRef control, SInt16 part) +static pascal OSStatus +wxMacWindowCommandEventHandler(EventHandlerCallRef WXUNUSED(handler), + EventRef event, + void *data) { - wxWindow * win = wxFindControlFromMacControl(control) ; - if ( win ) - win->MacControlUserPaneDrawProc(part) ; -} -wxMAC_DEFINE_PROC_GETTER( ControlUserPaneDrawUPP , wxMacControlUserPaneDrawProc ) ; + OSStatus result = eventNotHandledErr ; + wxWindowMac* focus = (wxWindowMac*) data ; -static pascal ControlPartCode wxMacControlUserPaneHitTestProc(ControlRef control, Point where) -{ - wxWindow * win = wxFindControlFromMacControl(control) ; - if ( win ) - return win->MacControlUserPaneHitTestProc(where.h , where.v) ; - else - return kControlNoPart ; -} -wxMAC_DEFINE_PROC_GETTER( ControlUserPaneHitTestUPP , wxMacControlUserPaneHitTestProc ) ; + HICommand command ; -static pascal ControlPartCode wxMacControlUserPaneTrackingProc(ControlRef control, Point startPt, ControlActionUPP actionProc) -{ - wxWindow * win = wxFindControlFromMacControl(control) ; - if ( win ) - return win->MacControlUserPaneTrackingProc( startPt.h , startPt.v , (void*) actionProc) ; - else - return kControlNoPart ; -} -wxMAC_DEFINE_PROC_GETTER( ControlUserPaneTrackingUPP , wxMacControlUserPaneTrackingProc ) ; + wxMacCarbonEvent cEvent( event ) ; + cEvent.GetParameter(kEventParamDirectObject,typeHICommand,&command) ; -static pascal void wxMacControlUserPaneIdleProc(ControlRef control) -{ - wxWindow * win = wxFindControlFromMacControl(control) ; - if ( win ) - win->MacControlUserPaneIdleProc() ; -} -wxMAC_DEFINE_PROC_GETTER( ControlUserPaneIdleUPP , wxMacControlUserPaneIdleProc ) ; + wxMenuItem* item = NULL ; + wxMenu* itemMenu = wxFindMenuFromMacCommand( command , item ) ; + int id = wxMacCommandToId( command.commandID ) ; -static pascal ControlPartCode wxMacControlUserPaneKeyDownProc(ControlRef control, SInt16 keyCode, SInt16 charCode, SInt16 modifiers) -{ - wxWindow * win = wxFindControlFromMacControl(control) ; - if ( win ) - return win->MacControlUserPaneKeyDownProc(keyCode,charCode,modifiers) ; - else - return kControlNoPart ; -} -wxMAC_DEFINE_PROC_GETTER( ControlUserPaneKeyDownUPP , wxMacControlUserPaneKeyDownProc ) ; + if ( item ) + { + wxASSERT( itemMenu != NULL ) ; -static pascal void wxMacControlUserPaneActivateProc(ControlRef control, Boolean activating) -{ - wxWindow * win = wxFindControlFromMacControl(control) ; - if ( win ) - win->MacControlUserPaneActivateProc(activating) ; -} -wxMAC_DEFINE_PROC_GETTER( ControlUserPaneActivateUPP , wxMacControlUserPaneActivateProc ) ; + switch ( cEvent.GetKind() ) + { + case kEventProcessCommand : + result = itemMenu->MacHandleCommandProcess( item, id, focus ); + break ; -static pascal ControlPartCode wxMacControlUserPaneFocusProc(ControlRef control, ControlFocusPart action) -{ - wxWindow * win = wxFindControlFromMacControl(control) ; - if ( win ) - return win->MacControlUserPaneFocusProc(action) ; - else - return kControlNoPart ; -} -wxMAC_DEFINE_PROC_GETTER( ControlUserPaneFocusUPP , wxMacControlUserPaneFocusProc ) ; + case kEventCommandUpdateStatus: + result = itemMenu->MacHandleCommandUpdateStatus( item, id, focus ); + break ; -static pascal void wxMacControlUserPaneBackgroundProc(ControlRef control, ControlBackgroundPtr info) -{ - wxWindow * win = wxFindControlFromMacControl(control) ; - if ( win ) - win->MacControlUserPaneBackgroundProc(info) ; + default : + break ; + } + } + return result ; } -wxMAC_DEFINE_PROC_GETTER( ControlUserPaneBackgroundUPP , wxMacControlUserPaneBackgroundProc ) ; -void wxWindowMac::MacControlUserPaneDrawProc(wxInt16 part) +pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) { - int x = 0 , y = 0; - RgnHandle rgn = NewRgn() ; - GetClip( rgn ) ; - MacWindowToRootWindow( &x, &y ) ; - OffsetRgn( rgn , -x , -y ) ; - wxMacWindowStateSaver sv( this ) ; - SectRgn( rgn , (RgnHandle) MacGetVisibleRegion().GetWXHRGN() , rgn ) ; - MacDoRedraw( rgn , 0 ) ; - DisposeRgn( rgn ) ; -} + EventRef formerEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ; + EventHandlerCallRef formerEventHandlerCallRef = (EventHandlerCallRef) wxTheApp->MacGetCurrentEventHandlerCallRef() ; + wxTheApp->MacSetCurrentEvent( event , handler ) ; + OSStatus result = eventNotHandledErr ; -wxInt16 wxWindowMac::MacControlUserPaneHitTestProc(wxInt16 x, wxInt16 y) -{ - return kControlNoPart ; -} + switch ( GetEventClass( event ) ) + { + case kEventClassCommand : + result = wxMacWindowCommandEventHandler( handler , event , data ) ; + break ; -wxInt16 wxWindowMac::MacControlUserPaneTrackingProc(wxInt16 x, wxInt16 y, void* actionProc) -{ - return kControlNoPart ; -} + case kEventClassControl : + result = wxMacWindowControlEventHandler( handler, event, data ) ; + break ; -void wxWindowMac::MacControlUserPaneIdleProc() -{ -} + case kEventClassService : + result = wxMacWindowServiceEventHandler( handler, event , data ) ; + break ; -wxInt16 wxWindowMac::MacControlUserPaneKeyDownProc(wxInt16 keyCode, wxInt16 charCode, wxInt16 modifiers) -{ - return kControlNoPart ; -} + case kEventClassTextInput : + result = wxMacUnicodeTextEventHandler( handler , event , data ) ; + break ; -void wxWindowMac::MacControlUserPaneActivateProc(bool activating) -{ -} + default : + break ; + } -wxInt16 wxWindowMac::MacControlUserPaneFocusProc(wxInt16 action) -{ - if ( AcceptsFocus() ) - return 1 ; - else - return kControlNoPart ; -} + wxTheApp->MacSetCurrentEvent( formerEvent, formerEventHandlerCallRef ) ; -void wxWindowMac::MacControlUserPaneBackgroundProc(void* info) -{ + return result ; } -#endif +DEFINE_ONE_SHOT_HANDLER_GETTER( wxMacWindowEventHandler ) // --------------------------------------------------------------------------- // Scrollbar Tracking for all @@ -727,21 +866,16 @@ void wxWindowMac::Init() { m_peer = NULL ; m_frozenness = 0 ; - -#if WXWIN_COMPATIBILITY_2_4 - m_backgroundTransparent = false; -#endif - -#if wxMAC_USE_CORE_GRAPHICS + m_macAlpha = 255 ; m_cgContextRef = NULL ; -#endif // as all windows are created with WS_VISIBLE style... m_isShown = true; m_hScrollBar = NULL ; m_vScrollBar = NULL ; - m_macBackgroundBrush = wxNullBrush ; + m_hScrollBarAlwaysShown = false; + m_vScrollBarAlwaysShown = false; m_macIsUserPane = true; m_clipChildren = false ; @@ -751,7 +885,6 @@ void wxWindowMac::Init() wxWindowBase::SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); } -// Destructor wxWindowMac::~wxWindowMac() { SendDestroyEvent(); @@ -772,7 +905,7 @@ wxWindowMac::~wxWindowMac() break; } } -#endif // __WXUNIVERSAL__ +#endif // destroy children before destroying this window itself DestroyChildren(); @@ -780,11 +913,11 @@ wxWindowMac::~wxWindowMac() // wxRemoveMacControlAssociation( this ) ; // If we delete an item, we should initialize the parent panel, // because it could now be invalid. - wxWindow *parent = GetParent() ; - if ( parent ) + wxTopLevelWindow *tlw = wxDynamicCast(wxGetTopLevelParent(this), wxTopLevelWindow); + if ( tlw ) { - if (parent->GetDefaultItem() == (wxButton*) this) - parent->SetDefaultItem(NULL); + if ( tlw->GetDefaultItem() == (wxButton*) this) + tlw->SetDefaultItem(NULL); } if ( m_peer && m_peer->Ok() ) @@ -800,12 +933,14 @@ wxWindowMac::~wxWindowMac() if ( g_MacLastWindow == this ) g_MacLastWindow = NULL ; - wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( this ) , wxFrame ) ; +#ifndef __WXUNIVERSAL__ + wxFrame* frame = wxDynamicCast( wxGetTopLevelParent( (wxWindow*)this ) , wxFrame ) ; if ( frame ) { if ( frame->GetLastFocus() == this ) frame->SetLastFocus( NULL ) ; } +#endif // delete our drop target if we've got one #if wxUSE_DRAG_AND_DROP @@ -830,20 +965,6 @@ void wxWindowMac::MacInstallEventHandler( WXWidget control ) InstallControlEventHandler( (ControlRef)control , GetwxMacWindowEventHandlerUPP(), GetEventTypeCount(eventList), eventList, this, (EventHandlerRef *)&m_macControlEventHandler); - -#if !TARGET_API_MAC_OSX - if ( (ControlRef) control == m_peer->GetControlRef() ) - { - m_peer->SetData(kControlEntireControl, kControlUserPaneDrawProcTag, GetwxMacControlUserPaneDrawProc()) ; - m_peer->SetData(kControlEntireControl, kControlUserPaneHitTestProcTag, GetwxMacControlUserPaneHitTestProc()) ; - m_peer->SetData(kControlEntireControl, kControlUserPaneTrackingProcTag, GetwxMacControlUserPaneTrackingProc()) ; - m_peer->SetData(kControlEntireControl, kControlUserPaneIdleProcTag, GetwxMacControlUserPaneIdleProc()) ; - m_peer->SetData(kControlEntireControl, kControlUserPaneKeyDownProcTag, GetwxMacControlUserPaneKeyDownProc()) ; - m_peer->SetData(kControlEntireControl, kControlUserPaneActivateProcTag, GetwxMacControlUserPaneActivateProc()) ; - m_peer->SetData(kControlEntireControl, kControlUserPaneFocusProcTag, GetwxMacControlUserPaneFocusProc()) ; - m_peer->SetData(kControlEntireControl, kControlUserPaneBackgroundProcTag, GetwxMacControlUserPaneBackgroundProc()) ; - } -#endif } // Constructor @@ -906,11 +1027,11 @@ void wxWindowMac::MacChildAdded() m_hScrollBar->Raise() ; } -void wxWindowMac::MacPostControlCreate(const wxPoint& pos, const wxSize& size) +void wxWindowMac::MacPostControlCreate(const wxPoint& WXUNUSED(pos), const wxSize& size) { wxASSERT_MSG( m_peer != NULL && m_peer->Ok() , wxT("No valid mac control") ) ; - m_peer->SetReference( (long)this ) ; + m_peer->SetReference( (URefCon) this ) ; GetParent()->AddChild( this ); MacInstallEventHandler( (WXWidget) m_peer->GetControlRef() ); @@ -923,10 +1044,10 @@ void wxWindowMac::MacPostControlCreate(const wxPoint& pos, const wxSize& size) // adjust font, controlsize etc DoSetWindowVariant( m_windowVariant ) ; - m_peer->SetLabel( wxStripMenuCodes(m_label) ) ; + m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ; if (!m_macIsUserPane) - SetInitialBestSize(size); + SetInitialSize(size); SetCursor( *wxSTANDARD_CURSOR ) ; } @@ -962,17 +1083,9 @@ void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant ) break ; case wxWINDOW_VARIANT_MINI : - if (UMAGetSystemVersion() >= 0x1030 ) - { - // not always defined in the headers - size = 3 ; - themeFont = 109 ; - } - else - { - size = kControlSizeSmall; - themeFont = kThemeSmallSystemFont ; - } + // not always defined in the headers + size = 3 ; + themeFont = 109 ; break ; case wxWINDOW_VARIANT_LARGE : @@ -995,7 +1108,9 @@ void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant ) void wxWindowMac::MacUpdateControlFont() { m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ; - Refresh() ; + // do not trigger refreshes upon invisible and possible partly created objects + if ( MacIsReallyShown() ) + Refresh() ; } bool wxWindowMac::SetFont(const wxFont& font) @@ -1022,38 +1137,31 @@ bool wxWindowMac::SetBackgroundColour(const wxColour& col ) if ( !wxWindowBase::SetBackgroundColour(col) && m_hasBgCol ) return false ; - wxBrush brush ; - wxColour newCol(GetBackgroundColour()); - - if ( newCol == wxSystemSettings::GetColour( wxSYS_COLOUR_APPWORKSPACE ) ) - brush.MacSetTheme( kThemeBrushDocumentWindowBackground ) ; - else if ( newCol == wxSystemSettings::GetColour( wxSYS_COLOUR_3DFACE ) ) - brush.MacSetTheme( kThemeBrushDialogBackgroundActive ) ; - else - brush.SetColour( newCol ) ; - - MacSetBackgroundBrush( brush ) ; - MacUpdateControlFont() ; + m_peer->SetBackgroundColour( col ) ; return true ; } -void wxWindowMac::MacSetBackgroundBrush( const wxBrush &brush ) -{ - m_macBackgroundBrush = brush ; - m_peer->SetBackground( brush ) ; -} - bool wxWindowMac::MacCanFocus() const { - // there is currently no way to determine whether the window is running in full keyboard - // access mode, therefore we cannot rely on these features, yet the only other way would be - // to issue a SetKeyboardFocus event and verify after whether it succeeded, this would risk problems - // in event handlers... - UInt32 features = 0 ; - m_peer->GetFeatures( &features ) ; + // TODO : evaluate performance hits by looking up this value, eventually cache the results for a 1 sec or so + // CAUTION : the value returned currently is 0 or 2, I've also found values of 1 having the same meaning, + // but the value range is nowhere documented + Boolean keyExistsAndHasValidFormat ; + CFIndex fullKeyboardAccess = CFPreferencesGetAppIntegerValue( CFSTR("AppleKeyboardUIMode" ) , + kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat ); - return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ; + if ( keyExistsAndHasValidFormat && fullKeyboardAccess > 0 ) + { + return true ; + } + else + { + UInt32 features = 0 ; + m_peer->GetFeatures( &features ) ; + + return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ; + } } void wxWindowMac::SetFocus() @@ -1061,54 +1169,17 @@ void wxWindowMac::SetFocus() if ( !AcceptsFocus() ) return ; - wxWindow* former = FindFocus() ; - if ( former == this ) - return ; - - // as we cannot rely on the control features to find out whether we are in full keyboard mode, - // we can only leave in case of an error - OSStatus err = m_peer->SetFocus( kControlFocusNextPart ) ; - if ( err == errCouldntSetFocus ) - return ; - - SetUserFocusWindow( (WindowRef)MacGetTopLevelWindowRef() ); - -#if !TARGET_API_MAC_OSX - // emulate carbon events when running under CarbonLib where they are not natively available - if ( former ) - { - EventRef evRef = NULL ; - - err = MacCreateEvent( - NULL , kEventClassControl , kEventControlSetFocusPart , TicksToEventTime( TickCount() ) , - kEventAttributeUserEvent , &evRef ); - verify_noerr( err ); - - wxMacCarbonEvent cEvent( evRef ) ; - cEvent.SetParameter( kEventParamDirectObject , (ControlRef) former->GetHandle() ) ; - cEvent.SetParameter(kEventParamControlPart , typeControlPartCode , kControlFocusNoPart ) ; - - wxMacWindowEventHandler( NULL , evRef , former ) ; - ReleaseEvent( evRef ) ; - } - - // send new focus event - { - EventRef evRef = NULL ; - - err = MacCreateEvent( - NULL , kEventClassControl , kEventControlSetFocusPart , TicksToEventTime( TickCount() ) , - kEventAttributeUserEvent , &evRef ); - verify_noerr( err ); + wxWindow* former = FindFocus() ; + if ( former == this ) + return ; - wxMacCarbonEvent cEvent( evRef ) ; - cEvent.SetParameter( kEventParamDirectObject , (ControlRef) GetHandle() ) ; - cEvent.SetParameter(kEventParamControlPart , typeControlPartCode , kControlFocusNextPart ) ; + // as we cannot rely on the control features to find out whether we are in full keyboard mode, + // we can only leave in case of an error + OSStatus err = m_peer->SetFocus( kControlFocusNextPart ) ; + if ( err == errCouldntSetFocus ) + return ; - wxMacWindowEventHandler( NULL , evRef , this ) ; - ReleaseEvent( evRef ) ; - } -#endif + SetUserFocusWindow( (WindowRef)MacGetTopLevelWindowRef() ); } void wxWindowMac::DoCaptureMouse() @@ -1116,7 +1187,7 @@ void wxWindowMac::DoCaptureMouse() wxApp::s_captureWindow = this ; } -wxWindow* wxWindowBase::GetCapture() +wxWindow * wxWindowBase::GetCapture() { return wxApp::s_captureWindow ; } @@ -1142,8 +1213,8 @@ void wxWindowMac::SetDropTarget(wxDropTarget *pDropTarget) #endif -// Old style file-manager drag&drop -void wxWindowMac::DragAcceptFiles(bool accept) +// Old-style File Manager Drag & Drop +void wxWindowMac::DragAcceptFiles(bool WXUNUSED(accept)) { // TODO: } @@ -1151,8 +1222,10 @@ void wxWindowMac::DragAcceptFiles(bool accept) // Returns the size of the native control. In the case of the toplevel window // this is the content area root control -void wxWindowMac::MacGetPositionAndSizeFromControl(int& x, int& y, - int& w, int& h) const +void wxWindowMac::MacGetPositionAndSizeFromControl(int& WXUNUSED(x), + int& WXUNUSED(y), + int& WXUNUSED(w), + int& WXUNUSED(h)) const { wxFAIL_MSG( wxT("Not currently supported") ) ; } @@ -1165,10 +1238,7 @@ bool wxWindowMac::MacGetBoundsForControl( int& x, int& y, int& w, int& h , bool adjustOrigin ) const { - bool isCompositing = MacGetTopLevelWindow()->MacUsesCompositing() ; - // the desired size, minus the border pixels gives the correct size of the control - x = (int)pos.x; y = (int)pos.y; @@ -1176,9 +1246,6 @@ bool wxWindowMac::MacGetBoundsForControl( w = wxMax(size.x, 0) ; // WidthDefault( size.x ); h = wxMax(size.y, 0) ; // HeightDefault( size.y ) ; - if ( !isCompositing ) - GetParent()->MacWindowToRootWindow( &x , &y ) ; - x += MacGetLeftBorderSize() ; y += MacGetTopBorderSize() ; w -= MacGetLeftBorderSize() + MacGetRightBorderSize() ; @@ -1257,7 +1324,7 @@ void wxWindowMac::DoScreenToClient(int *x, int *y) const if (y) localwhere.v = *y ; - QDGlobalToLocalPoint( GetWindowPort( window ) , &localwhere ) ; + wxMacGlobalToLocal( window , &localwhere ) ; if (x) *x = localwhere.h ; @@ -1292,7 +1359,7 @@ void wxWindowMac::DoClientToScreen(int *x, int *y) const if (y) localwhere.v = *y ; - QDLocalToGlobalPoint( GetWindowPort( window ) , &localwhere ) ; + wxMacLocalToGlobal( window, &localwhere ) ; if (x) *x = localwhere.h ; @@ -1488,10 +1555,10 @@ void wxWindowMac::DoGetClientSize( int *x, int *y ) const bool wxWindowMac::SetCursor(const wxCursor& cursor) { - if (m_cursor == cursor) + if (m_cursor.IsSameAs(cursor)) return false; - if (wxNullCursor == cursor) + if (!cursor.IsOk()) { if ( ! wxWindowBase::SetCursor( *wxSTANDARD_CURSOR ) ) return false ; @@ -1509,23 +1576,27 @@ bool wxWindowMac::SetCursor(const wxCursor& cursor) { wxTopLevelWindowMac *tlw = MacGetTopLevelWindow() ; WindowRef window = (WindowRef) ( tlw ? tlw->MacGetWindowRef() : 0 ) ; - CGrafPtr savePort ; - Boolean swapped = QDSwapPort( GetWindowPort( window ) , &savePort ) ; - - // TODO: If we ever get a GetCurrentEvent... replacement - // for the mouse position, use it... - Point pt ; ControlPartCode part ; ControlRef control ; - - GetMouse( &pt ) ; - control = wxMacFindControlUnderMouse( tlw , pt , window , &part ) ; + Point pt ; + #if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5 + HIPoint hiPoint ; + HIGetMousePosition(kHICoordSpaceWindow, window, &hiPoint); + pt.h = hiPoint.x; + pt.v = hiPoint.y; + #else + GetGlobalMouse( &pt ); + int x = pt.h; + int y = pt.v; + ScreenToClient(&x, &y); + pt.h = x; + pt.v = y; +#endif + control = FindControlUnderMouse( pt , window , &part ) ; if ( control ) mouseWin = wxFindControlFromMacControl( control ) ; - if ( swapped ) - QDSwapPort( savePort , NULL ) ; } if ( mouseWin == this && !wxIsBusy() ) @@ -1537,10 +1608,11 @@ bool wxWindowMac::SetCursor(const wxCursor& cursor) #if wxUSE_MENUS bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y) { - menu->SetInvokingWindow(this); +#ifndef __WXUNIVERSAL__ + menu->SetInvokingWindow((wxWindow*)this); menu->UpdateUI(); - if ( x == -1 && y == -1 ) + if ( x == wxDefaultCoord && y == wxDefaultCoord ) { wxPoint mouse = wxGetMousePosition(); x = mouse.x; @@ -1555,21 +1627,29 @@ bool wxWindowMac::DoPopupMenu(wxMenu *menu, int x, int y) long menuResult = ::PopUpMenuSelect((MenuHandle) menu->GetHMenu() , y, x, 0) ; if ( HiWord(menuResult) != 0 ) { - MenuCommand id ; - GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult)) , LoWord(menuResult) , &id ) ; + MenuCommand macid; + GetMenuItemCommandID( GetMenuHandle(HiWord(menuResult)) , LoWord(menuResult) , &macid ); + int id = wxMacCommandToId( macid ); wxMenuItem* item = NULL ; wxMenu* realmenu ; item = menu->FindItem( id, &realmenu ) ; - if (item->IsCheckable()) - item->Check( !item->IsChecked() ) ; + if ( item ) + { + if (item->IsCheckable()) + item->Check( !item->IsChecked() ) ; - menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ; + menu->SendEvent( id , item->IsCheckable() ? item->IsChecked() : -1 ) ; + } } menu->MacAfterDisplay( true ) ; menu->SetInvokingWindow( NULL ); return true; +#else + // actually this shouldn't be called, because universal is having its own implementation + return false; +#endif } #endif @@ -1599,7 +1679,7 @@ void wxWindowMac::MacInvalidateBorders() return ; int outerBorder = MacGetLeftBorderSize() ; - if ( m_peer->NeedsFocusRect() && m_peer->HasFocus() ) + if ( m_peer->NeedsFocusRect() /* && m_peer->HasFocus() */ ) outerBorder += 4 ; if ( outerBorder == 0 ) @@ -1621,13 +1701,7 @@ void wxWindowMac::MacInvalidateBorders() RectRgn( updateOuter, &rect ) ; DiffRgn( updateOuter, updateInner , updateOuter ) ; -#ifdef __WXMAC_OSX__ GetParent()->m_peer->SetNeedsDisplay( updateOuter ) ; -#else - WindowRef tlw = (WindowRef) MacGetTopLevelWindowRef() ; - if ( tlw ) - InvalWindowRgn( tlw , updateOuter ) ; -#endif DisposeRgn( updateOuter ) ; DisposeRgn( updateInner ) ; @@ -1701,7 +1775,7 @@ void wxWindowMac::DoMoveWindow(int x, int y, int width, int height) wxPoint point(actualX, actualY); wxMoveEvent event(point, m_windowId); event.SetEventObject(this); - GetEventHandler()->ProcessEvent(event) ; + HandleWindowEvent(event) ; } if ( doResize ) @@ -1710,7 +1784,7 @@ void wxWindowMac::DoMoveWindow(int x, int y, int width, int height) wxSize size(actualWidth, actualHeight); wxSizeEvent event(size, m_windowId); event.SetEventObject(this); - GetEventHandler()->ProcessEvent(event); + HandleWindowEvent(event); } } } @@ -1848,7 +1922,7 @@ wxPoint wxWindowMac::GetClientAreaOrigin() const void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight) { - if ( clientheight != wxDefaultCoord || clientheight != wxDefaultCoord ) + if ( clientwidth != wxDefaultCoord || clientheight != wxDefaultCoord ) { int currentclientwidth , currentclientheight ; int currentwidth , currentheight ; @@ -1863,12 +1937,14 @@ void wxWindowMac::DoSetClientSize(int clientwidth, int clientheight) void wxWindowMac::SetLabel(const wxString& title) { - m_label = wxStripMenuCodes(title) ; + m_label = title ; if ( m_peer && m_peer->Ok() ) - m_peer->SetLabel( m_label ) ; + m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ; - Refresh() ; + // do not trigger refreshes upon invisible and possible partly created objects + if ( MacIsReallyShown() ) + Refresh() ; } wxString wxWindowMac::GetLabel() const @@ -1878,91 +1954,18 @@ wxString wxWindowMac::GetLabel() const bool wxWindowMac::Show(bool show) { - bool former = MacIsReallyShown() ; if ( !wxWindowBase::Show(show) ) return false; - // TODO: use visibilityChanged Carbon Event for OSX if ( m_peer ) m_peer->SetVisibility( show , true ) ; - if ( former != MacIsReallyShown() ) - MacPropagateVisibilityChanged() ; - return true; } -bool wxWindowMac::Enable(bool enable) +void wxWindowMac::DoEnable(bool enable) { - wxASSERT( m_peer->Ok() ) ; - bool former = MacIsReallyEnabled() ; - if ( !wxWindowBase::Enable(enable) ) - return false; - m_peer->Enable( enable ) ; - - if ( former != MacIsReallyEnabled() ) - MacPropagateEnabledStateChanged() ; - - return true; -} - -// -// status change propagations (will be not necessary for OSX later ) -// - -void wxWindowMac::MacPropagateVisibilityChanged() -{ -#if !TARGET_API_MAC_OSX - MacVisibilityChanged() ; - - wxWindowMac *child; - wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); - while ( node ) - { - child = node->GetData(); - if ( child->IsShown() ) - child->MacPropagateVisibilityChanged() ; - - node = node->GetNext(); - } -#endif -} - -void wxWindowMac::MacPropagateEnabledStateChanged() -{ -#if !TARGET_API_MAC_OSX - MacEnabledStateChanged() ; - - wxWindowMac *child; - wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); - while ( node ) - { - child = node->GetData(); - if ( child->IsEnabled() ) - child->MacPropagateEnabledStateChanged() ; - - node = node->GetNext(); - } -#endif -} - -void wxWindowMac::MacPropagateHiliteChanged() -{ -#if !TARGET_API_MAC_OSX - MacHiliteChanged() ; - - wxWindowMac *child; - wxWindowList::compatibility_iterator node = GetChildren().GetFirst(); - while ( node ) - { - child = node->GetData(); - if (child /* && child->IsEnabled() */) - child->MacPropagateHiliteChanged() ; - - node = node->GetNext(); - } -#endif } // @@ -1979,6 +1982,7 @@ void wxWindowMac::MacHiliteChanged() void wxWindowMac::MacEnabledStateChanged() { + OnEnabled( m_peer->IsEnabled() ); } // @@ -2049,7 +2053,7 @@ void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y, fontToUse = &m_font; wxClientDC dc( (wxWindowMac*) this ) ; - long lx,ly,ld,le ; + wxCoord lx,ly,ld,le ; dc.GetTextExtent( string , &lx , &ly , &ld, &le, (wxFont *)fontToUse ) ; if ( externalLeading ) *externalLeading = le ; @@ -2066,7 +2070,7 @@ void wxWindowMac::GetTextExtent(const wxString& string, int *x, int *y, * we always intersect with the entire window, not only with the client area */ -void wxWindowMac::Refresh(bool eraseBack, const wxRect *rect) +void wxWindowMac::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect) { if ( m_peer == NULL ) return ; @@ -2114,6 +2118,11 @@ void wxWindowMac::Thaw() #endif } +bool wxWindowMac::IsFrozen() const +{ + return m_frozenness != 0; +} + wxWindowMac *wxGetActiveWindow() { // actually this is a windows-only concept @@ -2121,7 +2130,7 @@ wxWindowMac *wxGetActiveWindow() } // Coordinates relative to the window -void wxWindowMac::WarpPointer(int x_pos, int y_pos) +void wxWindowMac::WarpPointer(int WXUNUSED(x_pos), int WXUNUSED(y_pos)) { // We really don't move the mouse programmatically under Mac. } @@ -2130,17 +2139,22 @@ void wxWindowMac::OnEraseBackground(wxEraseEvent& event) { if ( MacGetTopLevelWindow() == NULL ) return ; - +/* #if TARGET_API_MAC_OSX - if ( MacGetTopLevelWindow()->MacUsesCompositing() && (!m_macBackgroundBrush.Ok() || m_macBackgroundBrush.GetStyle() == wxTRANSPARENT ) ) + if ( !m_backgroundColour.Ok() || GetBackgroundStyle() == wxBG_STYLE_TRANSPARENT ) { - event.Skip() ; } else #endif +*/ + if ( GetBackgroundStyle() == wxBG_STYLE_COLOUR ) { event.GetDC()->Clear() ; } + else + { + event.Skip() ; + } } void wxWindowMac::OnNcPaint( wxNcPaintEvent& event ) @@ -2198,7 +2212,7 @@ int wxWindowMac::GetScrollThumb(int orient) const return 0; } -void wxWindowMac::SetScrollPos(int orient, int pos, bool refresh) +void wxWindowMac::SetScrollPos(int orient, int pos, bool WXUNUSED(refresh)) { if ( orient == wxHORIZONTAL ) { @@ -2212,26 +2226,76 @@ void wxWindowMac::SetScrollPos(int orient, int pos, bool refresh) } } +void +wxWindowMac::AlwaysShowScrollbars(bool hflag, bool vflag) +{ + bool needVisibilityUpdate = false; + + if ( m_hScrollBarAlwaysShown != hflag ) + { + m_hScrollBarAlwaysShown = hflag; + needVisibilityUpdate = true; + } + + if ( m_vScrollBarAlwaysShown != vflag ) + { + m_vScrollBarAlwaysShown = vflag; + needVisibilityUpdate = true; + } + + if ( needVisibilityUpdate ) + DoUpdateScrollbarVisibility(); +} + // // we draw borders and grow boxes, are already set up and clipped in the current port / cgContextRef // our own window origin is at leftOrigin/rightOrigin // -void wxWindowMac::MacPaintBorders( int leftOrigin , int rightOrigin ) +void wxWindowMac::MacPaintGrowBox() +{ + if ( IsTopLevel() ) + return ; + + if ( MacHasScrollBarCorner() ) + { + Rect rect ; + + CGContextRef cgContext = (CGContextRef) MacGetCGContextRef() ; + wxASSERT( cgContext ) ; + + m_peer->GetRect( &rect ) ; + + int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ; + CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ; + CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ; + CGContextSaveGState( cgContext ); + + if ( m_backgroundColour.Ok() ) + { + CGContextSetFillColorWithColor( cgContext, m_backgroundColour.GetCGColor() ); + } + else + { + CGContextSetRGBFillColor( cgContext, 1.0, 1.0 , 1.0 , 1.0 ); + } + CGContextFillRect( cgContext, cgrect ); + CGContextRestoreGState( cgContext ); + } +} + +void wxWindowMac::MacPaintBorders( int WXUNUSED(leftOrigin) , int WXUNUSED(rightOrigin) ) { if ( IsTopLevel() ) return ; Rect rect ; bool hasFocus = m_peer->NeedsFocusRect() && m_peer->HasFocus() ; - bool hasBothScrollbars = (m_hScrollBar && m_hScrollBar->IsShown()) && (m_vScrollBar && m_vScrollBar->IsShown()) ; // back to the surrounding frame rectangle m_peer->GetRect( &rect ) ; InsetRect( &rect, -1 , -1 ) ; -#if wxMAC_USE_CORE_GRAPHICS && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 - if ( UMAGetSystemVersion() >= 0x1030 ) { CGRect cgrect = CGRectMake( rect.left , rect.top , rect.right - rect.left , rect.bottom - rect.top ) ; @@ -2261,11 +2325,12 @@ void wxWindowMac::MacPaintBorders( int leftOrigin , int rightOrigin ) { HIThemeDrawFocusRect( &cgrect , true , cgContext , kHIThemeOrientationNormal ) ; } - +#if 0 // TODO REMOVE now done in a separate call earlier in drawing the window itself m_peer->GetRect( &rect ) ; - if ( hasBothScrollbars ) + if ( MacHasScrollBarCorner() ) { - int size = m_hScrollBar->GetWindowVariant() == wxWINDOW_VARIANT_NORMAL ? 16 : 12 ; + int variant = (m_hScrollBar == NULL ? m_vScrollBar : m_hScrollBar ) ->GetWindowVariant(); + int size = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ; CGRect cgrect = CGRectMake( rect.right - size , rect.bottom - size , size , size ) ; CGPoint cgpoint = CGPointMake( rect.right - size , rect.bottom - size ) ; HIThemeGrowBoxDrawInfo info ; @@ -2273,35 +2338,12 @@ void wxWindowMac::MacPaintBorders( int leftOrigin , int rightOrigin ) info.version = 0 ; info.state = IsEnabled() ? kThemeStateActive : kThemeStateInactive ; info.kind = kHIThemeGrowBoxKindNone ; + // contrary to the docs ...SizeSmall does not work info.size = kHIThemeGrowBoxSizeNormal ; - info.direction = kThemeGrowRight | kThemeGrowDown ; + info.direction = 0 ; HIThemeDrawGrowBox( &cgpoint , &info , cgContext , kHIThemeOrientationNormal ) ; } - } - else #endif - { - wxTopLevelWindowMac* top = MacGetTopLevelWindow(); - if ( top ) - { - wxPoint pt(0, 0) ; - wxMacControl::Convert( &pt , GetParent()->m_peer , top->m_peer ) ; - OffsetRect( &rect , pt.x , pt.y ) ; - } - - if ( HasFlag(wxRAISED_BORDER) || HasFlag( wxSUNKEN_BORDER) || HasFlag(wxDOUBLE_BORDER) ) - DrawThemeEditTextFrame( &rect, IsEnabled() ? kThemeStateActive : kThemeStateInactive ) ; - else if ( HasFlag(wxSIMPLE_BORDER) ) - DrawThemeListBoxFrame( &rect, IsEnabled() ? kThemeStateActive : kThemeStateInactive ) ; - - if ( hasFocus ) - DrawThemeFocusRect( &rect , true ) ; - - if ( hasBothScrollbars ) - { - // GetThemeStandaloneGrowBoxBounds - // DrawThemeStandaloneNoGrowBox - } } } @@ -2315,36 +2357,51 @@ void wxWindowMac::RemoveChild( wxWindowBase *child ) wxWindowBase::RemoveChild( child ) ; } -// New function that will replace some of the above. -void wxWindowMac::SetScrollbar(int orient, int pos, int thumbVisible, - int range, bool refresh) +void wxWindowMac::DoUpdateScrollbarVisibility() { - bool showScroller; + bool triggerSizeEvent = false; - if ( orient == wxHORIZONTAL ) + if ( m_hScrollBar ) { - if ( m_hScrollBar ) - { - showScroller = ((range != 0) && (range > thumbVisible)); - if ( m_hScrollBar->IsShown() != showScroller ) - m_hScrollBar->Show( showScroller ) ; + bool showHScrollBar = m_hScrollBarAlwaysShown || m_hScrollBar->IsNeeded(); - m_hScrollBar->SetScrollbar( pos , thumbVisible , range , thumbVisible , refresh ) ; + if ( m_hScrollBar->IsShown() != showHScrollBar ) + { + m_hScrollBar->Show( showHScrollBar ); + triggerSizeEvent = true; } } - else + + if ( m_vScrollBar) { - if ( m_vScrollBar ) - { - showScroller = ((range != 0) && (range > thumbVisible)); - if ( m_vScrollBar->IsShown() != showScroller ) - m_vScrollBar->Show( showScroller ) ; + bool showVScrollBar = m_vScrollBarAlwaysShown || m_vScrollBar->IsNeeded(); - m_vScrollBar->SetScrollbar( pos , thumbVisible , range , thumbVisible , refresh ) ; + if ( m_vScrollBar->IsShown() != showVScrollBar ) + { + m_vScrollBar->Show( showVScrollBar ) ; + triggerSizeEvent = true; } } MacRepositionScrollBars() ; + if ( triggerSizeEvent ) + { + wxSizeEvent event(GetSize(), m_windowId); + event.SetEventObject(this); + HandleWindowEvent(event); + } +} + +// New function that will replace some of the above. +void wxWindowMac::SetScrollbar(int orient, int pos, int thumb, + int range, bool refresh) +{ + if ( orient == wxHORIZONTAL && m_hScrollBar ) + m_hScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh); + else if ( orient == wxVERTICAL && m_vScrollBar ) + m_vScrollBar->SetScrollbar(pos, thumb, range, thumb, refresh); + + DoUpdateScrollbarVisibility(); } // Does a physical scroll @@ -2356,8 +2413,6 @@ void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect) int width , height ; GetClientSize( &width , &height ) ; -#if TARGET_API_MAC_OSX - if ( true /* m_peer->IsCompositing() */ ) { // note there currently is a bug in OSX which makes inefficient refreshes in case an entire control // area is scrolled, this does not occur if width and height are 2 pixels less, @@ -2369,19 +2424,14 @@ void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect) if ( m_peer->GetNeedsDisplay() ) { // because HIViewScrollRect does not scroll the already invalidated area we have two options: + // in case there is already a pending redraw on that area // either immediate redraw or full invalidate #if 1 // is the better overall solution, as it does not slow down scrolling m_peer->SetNeedsDisplay() ; #else // this would be the preferred version for fast drawing controls - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 - if ( UMAGetSystemVersion() >= 0x1030 && m_peer->IsCompositing() ) - HIViewRender(m_peer->GetControlRef()) ; - else -#endif - Update() ; + HIViewRender(m_peer->GetControlRef()) ; #endif } @@ -2389,76 +2439,10 @@ void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect) scrollrect.Offset( -MacGetLeftBorderSize() , -MacGetTopBorderSize() ) ; m_peer->ScrollRect( &scrollrect , dx , dy ) ; - // becuase HIViewScrollRect does not scroll the already invalidated area we have two options - // either immediate redraw or full invalidate #if 0 - // is the better overall solution, as it does not slow down scrolling - m_peer->SetNeedsDisplay() ; -#else // this would be the preferred version for fast drawing controls - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 - if ( UMAGetSystemVersion() >= 0x1030 && m_peer->IsCompositing() ) - HIViewRender(m_peer->GetControlRef()) ; - else -#endif - Update() ; -#endif - } - else + HIViewRender(m_peer->GetControlRef()) ; #endif - { - wxPoint pos; - pos.x = - pos.y = 0; - - Rect scrollrect; - RgnHandle updateRgn = NewRgn() ; - - { - wxClientDC dc(this) ; - wxMacPortSetter helper(&dc) ; - - m_peer->GetRectInWindowCoords( &scrollrect ) ; - //scrollrect.top += MacGetTopBorderSize() ; - //scrollrect.left += MacGetLeftBorderSize() ; - scrollrect.bottom = scrollrect.top + height ; - scrollrect.right = scrollrect.left + width ; - - if ( rect ) - { - Rect r = { dc.YLOG2DEVMAC(rect->y) , dc.XLOG2DEVMAC(rect->x) , dc.YLOG2DEVMAC(rect->y + rect->height) , - dc.XLOG2DEVMAC(rect->x + rect->width) } ; - SectRect( &scrollrect , &r , &scrollrect ) ; - } - - ScrollRect( &scrollrect , dx , dy , updateRgn ) ; - - // now scroll the former update region as well and add the new update region - WindowRef rootWindow = (WindowRef) MacGetTopLevelWindowRef() ; - RgnHandle formerUpdateRgn = NewRgn() ; - RgnHandle scrollRgn = NewRgn() ; - RectRgn( scrollRgn , &scrollrect ) ; - GetWindowUpdateRgn( rootWindow , formerUpdateRgn ) ; - Point pt = {0, 0} ; - LocalToGlobal( &pt ) ; - OffsetRgn( formerUpdateRgn , -pt.h , -pt.v ) ; - SectRgn( formerUpdateRgn , scrollRgn , formerUpdateRgn ) ; - - if ( !EmptyRgn( formerUpdateRgn ) ) - { - MacOffsetRgn( formerUpdateRgn , dx , dy ) ; - SectRgn( formerUpdateRgn , scrollRgn , formerUpdateRgn ) ; - InvalWindowRgn( rootWindow, formerUpdateRgn ) ; - } - - InvalWindowRgn(rootWindow, updateRgn ) ; - DisposeRgn( updateRgn ) ; - DisposeRgn( formerUpdateRgn ) ; - DisposeRgn( scrollRgn ) ; - } - - Update() ; } wxWindowMac *child; @@ -2481,11 +2465,11 @@ void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect) { wxRect rc( x, y, w, h ); if (rect->Intersects( rc )) - child->SetSize( x + dx, y + dy, w, h ); + child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE ); } else { - child->SetSize( x + dx, y + dy, w, h ); + child->SetSize( x + dx, y + dy, w, h, wxSIZE_AUTO|wxSIZE_ALLOW_MINUS_ONE ); } } } @@ -2516,7 +2500,7 @@ void wxWindowMac::MacOnScroll( wxScrollEvent &event ) else if (event.GetEventType() == wxEVT_SCROLL_THUMBRELEASE) wevent.SetEventType( wxEVT_SCROLLWIN_THUMBRELEASE ); - GetEventHandler()->ProcessEvent(wevent); + HandleWindowEvent(wevent); } } @@ -2528,62 +2512,11 @@ wxWindowMac *wxWindowBase::DoFindFocus() return wxFindControlFromMacControl( control ) ; } -void wxWindowMac::OnSetFocus( wxFocusEvent& event ) -{ - // panel wants to track the window which was the last to have focus in it, - // so we want to set ourselves as the window which last had focus - // - // notice that it's also important to do it upwards the tree because - // otherwise when the top level panel gets focus, it won't set it back to - // us, but to some other sibling - - // CS: don't know if this is still needed: - //wxChildFocusEvent eventFocus(this); - //(void)GetEventHandler()->ProcessEvent(eventFocus); - - if ( MacGetTopLevelWindow() && m_peer->NeedsFocusRect() ) - { -#if wxMAC_USE_CORE_GRAPHICS - GetParent()->Refresh() ; -#else - wxMacWindowStateSaver sv( this ) ; - Rect rect ; - - m_peer->GetRect( &rect ) ; - // auf den umgebenden Rahmen zurĀŸck - InsetRect( &rect, -1 , -1 ) ; - - wxTopLevelWindowMac* top = MacGetTopLevelWindow(); - if ( top ) - { - wxPoint pt(0, 0) ; - wxMacControl::Convert( &pt , GetParent()->m_peer , top->m_peer ) ; - rect.left += pt.x ; - rect.right += pt.x ; - rect.top += pt.y ; - rect.bottom += pt.y ; - } - - bool bIsFocusEvent = (event.GetEventType() == wxEVT_SET_FOCUS); - DrawThemeFocusRect( &rect , bIsFocusEvent ) ; - if ( !bIsFocusEvent ) - { - // as this erases part of the frame we have to redraw borders - // and because our z-ordering is not always correct (staticboxes) - // we have to invalidate things, we cannot simple redraw - MacInvalidateBorders() ; - } -#endif - } - - event.Skip(); -} - void wxWindowMac::OnInternalIdle() { // This calls the UI-update mechanism (querying windows for // menu/toolbar/control state information) - if (wxUpdateUIEvent::CanUpdate(this)) + if (wxUpdateUIEvent::CanUpdate(this) && IsShown()) UpdateWindowUI(wxUPDATE_UI_FROMIDLE); } @@ -2612,7 +2545,7 @@ bool wxWindowMac::MacSetupCursor( const wxPoint& pt ) { wxSetCursorEvent event( pt.x , pt.y ); - bool processedEvtSetCursor = GetEventHandler()->ProcessEvent(event); + bool processedEvtSetCursor = HandleWindowEvent(event); if ( processedEvtSetCursor && event.HasCursor() ) { cursor = event.GetCursor() ; @@ -2637,7 +2570,7 @@ bool wxWindowMac::MacSetupCursor( const wxPoint& pt ) return cursor.Ok() ; } -wxString wxWindowMac::MacGetToolTipString( wxPoint &pt ) +wxString wxWindowMac::MacGetToolTipString( wxPoint &WXUNUSED(pt) ) { #if wxUSE_TOOLTIPS if ( m_tooltip ) @@ -2655,11 +2588,9 @@ void wxWindowMac::ClearBackground() void wxWindowMac::Update() { -#if TARGET_API_MAC_OSX - MacGetTopLevelWindow()->MacPerformUpdates() ; -#else - ::Draw1Control( m_peer->GetControlRef() ) ; -#endif + wxTopLevelWindowMac* top = MacGetTopLevelWindow(); + if (top) + top->MacPerformUpdates() ; } wxTopLevelWindowMac* wxWindowMac::MacGetTopLevelWindow() const @@ -2801,7 +2732,7 @@ void wxWindowMac::MacUpdateClippedRects() const /* This function must not change the updatergn ! */ -bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time ) +bool wxWindowMac::MacDoRedraw( void* updatergnr , long time ) { bool handled = false ; Rect updatebounds ; @@ -2826,19 +2757,21 @@ bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time ) // the grow-box area of a scrolled window (scroll sample) wxDC* dc = new wxWindowDC(this); if ( IsTopLevel() ) - dc->SetClippingRegion(wxRegion(updatergn)); + dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(updatergn))); else - dc->SetClippingRegion(wxRegion(newupdate)); + dc->SetClippingRegion(wxRegion(HIShapeCreateWithQDRgn(newupdate))); wxEraseEvent eevent( GetId(), dc ); eevent.SetEventObject( this ); - GetEventHandler()->ProcessEvent( eevent ); + HandleWindowEvent( eevent ); delete dc ; } + MacPaintGrowBox(); + // calculate a client-origin version of the update rgn and set m_updateRegion to that OffsetRgn( newupdate , -origin.x , -origin.y ) ; - m_updateRegion = newupdate ; + m_updateRegion = wxRegion(HIShapeCreateWithQDRgn(newupdate)) ; DisposeRgn( newupdate ) ; if ( !m_updateRegion.Empty() ) @@ -2848,7 +2781,7 @@ bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time ) wxPaintEvent event; event.SetTimestamp(time); event.SetEventObject(this); - GetEventHandler()->ProcessEvent(event); + HandleWindowEvent(event); handled = true ; } @@ -2887,21 +2820,9 @@ bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time ) // paint custom borders wxNcPaintEvent eventNc( child->GetId() ); eventNc.SetEventObject( child ); - if ( !child->GetEventHandler()->ProcessEvent( eventNc ) ) + if ( !child->HandleWindowEvent( eventNc ) ) { -#if wxMAC_USE_CORE_GRAPHICS && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 - if ( UMAGetSystemVersion() >= 0x1030 ) - { - child->MacPaintBorders(0, 0) ; - } - else -#endif - { - wxWindowDC dc(this) ; - dc.SetClippingRegion(wxRegion(updatergn)); - wxMacPortSetter helper(&dc) ; - child->MacPaintBorders(0, 0) ; - } + child->MacPaintBorders(0, 0) ; } } } @@ -2918,32 +2839,99 @@ WXWindow wxWindowMac::MacGetTopLevelWindowRef() const while ( iter ) { if ( iter->IsTopLevel() ) - return ((wxTopLevelWindow*)iter)->MacGetWindowRef() ; - + { + wxTopLevelWindow* toplevel = wxDynamicCast(iter,wxTopLevelWindow); + if ( toplevel ) + return toplevel->MacGetWindowRef(); +#if wxUSE_POPUPWIN + wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow); + if ( popupwin ) + return popupwin->MacGetPopupWindowRef(); +#endif + } iter = iter->GetParent() ; } - wxASSERT_MSG( 1 , wxT("No valid mac root window") ) ; - return NULL ; } +bool wxWindowMac::MacHasScrollBarCorner() const +{ + /* Returns whether the scroll bars in a wxScrolledWindow should be + * shortened. Scroll bars should be shortened if either: + * + * - both scroll bars are visible, or + * + * - there is a resize box in the parent frame's corner and this + * window shares the bottom and right edge with the parent + * frame. + */ + + if ( m_hScrollBar == NULL && m_vScrollBar == NULL ) + return false; + + if ( ( m_hScrollBar && m_hScrollBar->IsShown() ) + && ( m_vScrollBar && m_vScrollBar->IsShown() ) ) + { + // Both scroll bars visible + return true; + } + else + { + wxPoint thisWindowBottomRight = GetScreenRect().GetBottomRight(); + + for ( const wxWindow *win = this; win; win = win->GetParent() ) + { + const wxFrame *frame = wxDynamicCast( win, wxFrame ) ; + if ( frame ) + { + if ( frame->GetWindowStyleFlag() & wxRESIZE_BORDER ) + { + // Parent frame has resize handle + wxPoint frameBottomRight = frame->GetScreenRect().GetBottomRight(); + + // Note: allow for some wiggle room here as wxMac's + // window rect calculations seem to be imprecise + if ( abs( thisWindowBottomRight.x - frameBottomRight.x ) <= 2 + && abs( thisWindowBottomRight.y - frameBottomRight.y ) <= 2 ) + { + // Parent frame has resize handle and shares + // right bottom corner + return true ; + } + else + { + // Parent frame has resize handle but doesn't + // share right bottom corner + return false ; + } + } + else + { + // Parent frame doesn't have resize handle + return false ; + } + } + } + + // No parent frame found + return false ; + } +} + void wxWindowMac::MacCreateScrollBars( long style ) { wxASSERT_MSG( m_vScrollBar == NULL && m_hScrollBar == NULL , wxT("attempt to create window twice") ) ; if ( style & ( wxVSCROLL | wxHSCROLL ) ) { - bool hasBoth = ( style & wxVSCROLL ) && ( style & wxHSCROLL ) ; int scrlsize = MAC_SCROLLBAR_SIZE ; - wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL ; if ( GetWindowVariant() == wxWINDOW_VARIANT_SMALL || GetWindowVariant() == wxWINDOW_VARIANT_MINI ) { scrlsize = MAC_SMALL_SCROLLBAR_SIZE ; - variant = wxWINDOW_VARIANT_SMALL ; } - int adjust = hasBoth ? scrlsize - 1: 0 ; + int adjust = MacHasScrollBarCorner() ? scrlsize - 1: 0 ; int width, height ; GetClientSize( &width , &height ) ; @@ -2952,11 +2940,18 @@ void wxWindowMac::MacCreateScrollBars( long style ) wxPoint hPoint(0, height - scrlsize) ; wxSize hSize(width - adjust, scrlsize) ; + // we have to set the min size to a smaller value, otherwise they cannot get smaller (InitialSize sets MinSize) if ( style & wxVSCROLL ) - m_vScrollBar = new wxScrollBar(this, wxID_ANY, vPoint, vSize , wxVERTICAL); + { + m_vScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, vPoint, vSize , wxVERTICAL); + m_vScrollBar->SetMinSize( wxDefaultSize ); + } if ( style & wxHSCROLL ) - m_hScrollBar = new wxScrollBar(this, wxID_ANY, hPoint, hSize , wxHORIZONTAL); + { + m_hScrollBar = new wxScrollBar((wxWindow*)this, wxID_ANY, hPoint, hSize , wxHORIZONTAL); + m_hScrollBar->SetMinSize( wxDefaultSize ); + } } // because the create does not take into account the client area origin @@ -2976,9 +2971,8 @@ void wxWindowMac::MacRepositionScrollBars() if ( !m_hScrollBar && !m_vScrollBar ) return ; - bool hasBoth = (m_hScrollBar && m_hScrollBar->IsShown()) && ( m_vScrollBar && m_vScrollBar->IsShown()) ; int scrlsize = m_hScrollBar ? m_hScrollBar->GetSize().y : ( m_vScrollBar ? m_vScrollBar->GetSize().x : MAC_SCROLLBAR_SIZE ) ; - int adjust = hasBoth ? scrlsize - 1 : 0 ; + int adjust = MacHasScrollBarCorner() ? scrlsize - 1 : 0 ; // get real client area int width, height ; @@ -3161,7 +3155,7 @@ void wxWindowMac::OnMouseEvent( wxMouseEvent &event ) wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, this->GetId(), this->ClientToScreen(event.GetPosition())); - if ( ! GetEventHandler()->ProcessEvent(evtCtx) ) + if ( ! HandleWindowEvent(evtCtx) ) event.Skip() ; } else @@ -3170,15 +3164,18 @@ void wxWindowMac::OnMouseEvent( wxMouseEvent &event ) } } -void wxWindowMac::OnPaint( wxPaintEvent & event ) +void wxWindowMac::OnPaint( wxPaintEvent & WXUNUSED(event) ) { - if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL ) + if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL + && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT ) CallNextEventHandler( (EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , (EventRef) wxTheApp->MacGetCurrentEvent() ) ; } -void wxWindowMac::MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool WXUNUSED( mouseStillDown ) ) +void wxWindowMac::MacHandleControlClick(WXWidget WXUNUSED(control), + wxInt16 WXUNUSED(controlpart), + bool WXUNUSED(mouseStillDown)) { } @@ -3212,3 +3209,26 @@ bool wxWindowMac::Reparent(wxWindowBase *newParentBase) return true; } + +bool wxWindowMac::SetTransparent(wxByte alpha) +{ + SetBackgroundStyle(wxBG_STYLE_TRANSPARENT); + + if ( alpha != m_macAlpha ) + { + m_macAlpha = alpha ; + Refresh() ; + } + return true ; +} + + +bool wxWindowMac::CanSetTransparent() +{ + return true ; +} + +wxByte wxWindowMac::GetTransparent() const +{ + return m_macAlpha ; +}