X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/84f6927eca931441abec9b6d21c0e412841eaab9..d6fd667bc19986e20f7ca33976061d57d89bc41c:/src/mac/carbon/window.cpp diff --git a/src/mac/carbon/window.cpp b/src/mac/carbon/window.cpp index 563960faea..f9549fda4d 100644 --- a/src/mac/carbon/window.cpp +++ b/src/mac/carbon/window.cpp @@ -35,6 +35,7 @@ #include "wx/spinctrl.h" #include "wx/log.h" #include "wx/geometry.h" +#include "wx/textctrl.h" #include "wx/toolbar.h" #include "wx/dc.h" @@ -51,6 +52,8 @@ #ifndef __DARWIN__ #include #include +#include +#include #endif #if TARGET_API_MAC_OSX @@ -66,7 +69,6 @@ #include extern wxList wxPendingDelete; -wxWindowMac* gFocusWindow = NULL ; #ifdef __WXUNIVERSAL__ IMPLEMENT_ABSTRACT_CLASS(wxWindowMac, wxWindowBase) @@ -82,7 +84,7 @@ BEGIN_EVENT_TABLE(wxWindowMac, wxWindowBase) // TODO EVT_PAINT(wxWindowMac::OnPaint) EVT_SYS_COLOUR_CHANGED(wxWindowMac::OnSysColourChanged) EVT_INIT_DIALOG(wxWindowMac::OnInitDialog) - EVT_SET_FOCUS(wxWindowMac::OnSetFocus) +// EVT_SET_FOCUS(wxWindowMac::OnSetFocus) EVT_MOUSE_EVENTS(wxWindowMac::OnMouseEvent) END_EVENT_TABLE() @@ -102,25 +104,32 @@ END_EVENT_TABLE() extern long wxMacTranslateKey(unsigned char key, unsigned char code) ; pascal OSStatus wxMacSetupControlBackground( ControlRef iControl , SInt16 iMessage , SInt16 iDepth , Boolean iIsColor ) ; -#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_3 +#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[] = { + { kEventClassControl , kEventControlHit } , #if TARGET_API_MAC_OSX { kEventClassControl , kEventControlDraw } , { kEventClassControl , kEventControlVisibilityChanged } , { kEventClassControl , kEventControlEnabledStateChanged } , { kEventClassControl , kEventControlHiliteChanged } , -// { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only + { kEventClassControl , kEventControlSetFocusPart } , + + { kEventClassService , kEventServiceGetTypes }, + { kEventClassService , kEventServiceCopy }, + { kEventClassService , kEventServicePaste }, + + // { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only // { kEventClassControl , kEventControlBoundsChanged } , - - {} -#else - {} #endif } ; @@ -137,6 +146,7 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl switch( GetEventKind( event ) ) { +#if TARGET_API_MAC_OSX case kEventControlDraw : { RgnHandle updateRgn = NULL ; @@ -149,7 +159,7 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl // GrafPtr myport = cEvent.GetParameter(kEventParamGrafPort,typeGrafPtr) ; #if 0 - // in case we would need a coregraphics compliant background erase first + // in case we would need a coregraphics compliant background erase first // now usable to track redraws CGContextRef cgContext = cEvent.GetParameter(kEventParamCGContextRef) ; if ( thisWindow->MacIsUserPane() ) @@ -184,12 +194,136 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl case kEventControlHiliteChanged : thisWindow->MacHiliteChanged() ; break ; + case kEventControlSetFocusPart : + { + Boolean focusEverything = false ; + ControlPartCode controlPart = cEvent.GetParameter(kEventParamControlPart , typeControlPartCode ); + if ( cEvent.GetParameter(kEventParamControlFocusEverything , &focusEverything ) == noErr ) + { + } + if ( controlPart == kControlFocusNoPart ) + { + #if wxUSE_CARET + if ( thisWindow->GetCaret() ) + { + thisWindow->GetCaret()->OnKillFocus(); + } + #endif // wxUSE_CARET + wxFocusEvent event(wxEVT_KILL_FOCUS, thisWindow->GetId()); + event.SetEventObject(thisWindow); + thisWindow->GetEventHandler()->ProcessEvent(event) ; + } + else + { + // panel wants to track the window which was the last to have focus in it + wxChildFocusEvent eventFocus(thisWindow); + thisWindow->GetEventHandler()->ProcessEvent(eventFocus); + + #if wxUSE_CARET + if ( thisWindow->GetCaret() ) + { + thisWindow->GetCaret()->OnSetFocus(); + } + #endif // wxUSE_CARET + + wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId()); + event.SetEventObject(thisWindow); + thisWindow->GetEventHandler()->ProcessEvent(event) ; + } + if ( thisWindow->MacIsUserPane() ) + result = noErr ; + } + break ; +#endif + case kEventControlHit : + { + result = thisWindow->MacControlHit( handler , event ) ; + } + break ; default : break ; } return result ; } +static pascal OSStatus wxMacWindowServiceEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) +{ + OSStatus result = eventNotHandledErr ; + + wxMacCarbonEvent cEvent( event ) ; + + ControlRef controlRef ; + wxWindowMac* thisWindow = (wxWindowMac*) data ; + wxTextCtrl* textCtrl = wxDynamicCast( thisWindow , wxTextCtrl ) ; + cEvent.GetParameter( kEventParamDirectObject , &controlRef ) ; + + switch( GetEventKind( event ) ) + { + case kEventServiceGetTypes : + if( textCtrl ) + { + long from, to ; + textCtrl->GetSelection( &from , &to ) ; + + CFMutableArrayRef copyTypes = 0 , pasteTypes = 0; + if( from != to ) + copyTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServiceCopyTypes , typeCFMutableArrayRef ) ; + if ( textCtrl->IsEditable() ) + pasteTypes = cEvent.GetParameter< CFMutableArrayRef >( kEventParamServicePasteTypes , typeCFMutableArrayRef ) ; + + static const OSType textDataTypes[] = { kTXNTextData /* , 'utxt' , 'PICT', 'MooV', 'AIFF' */ }; + for ( size_t i = 0 ; i < WXSIZEOF(textDataTypes) ; ++i ) + { + CFStringRef typestring = CreateTypeStringWithOSType(textDataTypes[i]); + if ( typestring ) + { + if ( copyTypes ) + CFArrayAppendValue (copyTypes, typestring) ; + if ( pasteTypes ) + CFArrayAppendValue (pasteTypes, typestring) ; + CFRelease( typestring ) ; + } + } + result = noErr ; + } + break ; + case kEventServiceCopy : + if ( textCtrl ) + { + long from, to ; + 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() ) ) ; + result = noErr ; + } + break ; + 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 ; +#if wxUSE_UNICODE + textCtrl->WriteText( wxString( content , wxConvLocal ) ); +#else + textCtrl->WriteText( wxString( content ) ) ; +#endif + delete[] content ; + result = noErr ; + } + break ; + } + + return result ; +} + pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) { OSStatus result = eventNotHandledErr ; @@ -199,6 +333,8 @@ pascal OSStatus wxMacWindowEventHandler( EventHandlerCallRef handler , EventRef case kEventClassControl : result = wxMacWindowControlEventHandler( handler, event, data ) ; break ; + case kEventClassService : + result = wxMacWindowServiceEventHandler( handler, event , data ) ; default : break ; } @@ -423,9 +559,28 @@ pascal void wxMacLiveScrollbarActionProc( ControlRef control , ControlPartCode p // constructors and such // ---------------------------------------------------------------------------- +wxWindowMac::wxWindowMac() +{ + Init(); +} + +wxWindowMac::wxWindowMac(wxWindowMac *parent, + wxWindowID id, + const wxPoint& pos , + const wxSize& size , + long style , + const wxString& name ) +{ + Init(); + Create(parent, id, pos, size, style, name); +} + void wxWindowMac::Init() { + m_frozenness = 0 ; +#if WXWIN_COMPATIBILITY_2_4 m_backgroundTransparent = FALSE; +#endif // as all windows are created with WS_VISIBLE style... m_isShown = TRUE; @@ -461,6 +616,8 @@ void wxWindowMac::Init() wxMacSetupControlBackgroundUPP = NewControlColorUPP( wxMacSetupControlBackground ) ; } + // we need a valid font for the encodings + wxWindowBase::SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); } // Destructor @@ -516,11 +673,6 @@ wxWindowMac::~wxWindowMac() frame->SetLastFocus( NULL ) ; } - if ( gFocusWindow == this ) - { - gFocusWindow = NULL ; - } - DestroyChildren(); // delete our drop target if we've got one @@ -537,6 +689,7 @@ wxWindowMac::~wxWindowMac() void wxWindowMac::MacInstallEventHandler() { + wxAssociateControlWithMacControl( (ControlRef) m_macControl , this ) ; InstallControlEventHandler( (ControlRef) m_macControl, GetwxMacWindowEventHandlerUPP(), GetEventTypeCount(eventList), eventList, this, (EventHandlerRef *)&m_macControlEventHandler); @@ -563,10 +716,18 @@ bool wxWindowMac::Create(wxWindowMac *parent, wxWindowID id, { Rect bounds = wxMacGetBoundsForControl( this , pos , size ) ; - UInt32 features = kControlSupportsEmbedding | kControlSupportsLiveFeedback | kControlHasSpecialBackground | - kControlSupportsCalcBestRect | kControlHandlesTracking | kControlSupportsFocus | kControlWantsActivate | kControlWantsIdle; - - ::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds, kControlSupportsEmbedding , (ControlRef*) &m_macControl); + UInt32 features = 0 + | kControlSupportsEmbedding +// | kControlSupportsLiveFeedback +// | kControlHasSpecialBackground +// | kControlSupportsCalcBestRect +// | kControlHandlesTracking + | kControlSupportsFocus +// | kControlWantsActivate +// | kControlWantsIdle + ; + + ::CreateUserPaneControl( MAC_WXHWND(GetParent()->MacGetTopLevelWindowRef()) , &bounds, features , (ControlRef*) &m_macControl); MacPostControlCreate(pos,size) ; #if !TARGET_API_MAC_OSX @@ -607,7 +768,6 @@ void wxWindowMac::MacPostControlCreate(const wxPoint& pos, const wxSize& size) { wxASSERT_MSG( (ControlRef) m_macControl != NULL , wxT("No valid mac control") ) ; - wxAssociateControlWithMacControl( (ControlRef) m_macControl , this ) ; ::SetControlReference( (ControlRef) m_macControl , (long) this ) ; MacInstallEventHandler(); @@ -627,29 +787,24 @@ void wxWindowMac::MacPostControlCreate(const wxPoint& pos, const wxSize& size) UMASetControlTitle( (ControlRef) m_macControl , wxStripMenuCodes(m_label) , m_font.GetEncoding() ) ; - wxSize new_size = size ; if (!m_macIsUserPane) - { - wxSize best_size( DoGetBestSize() ); - - if (size.x == -1) { - new_size.x = best_size.x; - } - if (size.y == -1) { - new_size.y = best_size.y; - } - SetSize( pos.x, pos.y , new_size.x, new_size.y,wxSIZE_USE_EXISTING ); + { + SetInitialBestSize(size); } SetCursor( *wxSTANDARD_CURSOR ) ; - } void wxWindowMac::DoSetWindowVariant( wxWindowVariant variant ) { - wxASSERT( m_macControl != NULL ) ; + // Don't assert, in case we set the window variant before + // the window is created + // wxASSERT( m_macControl != NULL ) ; - m_windowVariant = variant ; + m_windowVariant = variant ; + + if (!m_macControl) + return; ControlSize size ; ThemeFontID themeFont = kThemeSystemFont ; @@ -780,73 +935,59 @@ bool wxWindowMac::SetBackgroundColour(const wxColour& col ) bool wxWindowMac::MacCanFocus() const { - wxASSERT( m_macControl != NULL ) ; - - return true ; +#if 0 + // there is currently no way to determinate whether the window is running in full keyboard + // access mode, therefore we cannot rely on these features yet + UInt32 features = 0 ; + GetControlFeatures( (ControlRef) m_macControl , &features ) ; + return features & ( kControlSupportsFocus | kControlGetsFocusOnClick ) ; +#endif + return true ; } void wxWindowMac::SetFocus() { - if ( gFocusWindow == this ) - return ; - if ( AcceptsFocus() ) { - if (gFocusWindow ) - { -#if wxUSE_CARET - // Deal with caret - if ( gFocusWindow->m_caret ) - { - gFocusWindow->m_caret->OnKillFocus(); - } -#endif // wxUSE_CARET -#ifndef __WXUNIVERSAL__ - wxWindow* control = wxDynamicCast( gFocusWindow , wxWindow ) ; - // TODO we must use the built-in focusing - if ( control && control->GetHandle() /* && control->MacIsReallyShown() */ ) - { - UMASetKeyboardFocus( (WindowRef) gFocusWindow->MacGetTopLevelWindowRef() , (ControlRef) control->GetHandle() , kControlFocusNoPart ) ; - control->MacRedrawControl() ; - } +#if !TARGET_API_MAC_OSX + wxWindow* former = FindFocus() ; #endif - // Without testing the window id, for some reason - // a kill focus event can still be sent to - // the control just being focussed. - int thisId = this->m_windowId; - int gFocusWindowId = gFocusWindow->m_windowId; - if (gFocusWindowId != thisId) - { - wxFocusEvent event(wxEVT_KILL_FOCUS, gFocusWindow->m_windowId); - event.SetEventObject(gFocusWindow); - gFocusWindow->GetEventHandler()->ProcessEvent(event) ; - } + OSStatus err = SetKeyboardFocus( (WindowRef) MacGetTopLevelWindowRef() , (ControlRef) GetHandle() , 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 + if ( err == errCouldntSetFocus ) + return ; + +#if !TARGET_API_MAC_OSX + // emulate carbon events when running under carbonlib where they are not natively available + if ( former ) + { + EventRef evRef = NULL ; + verify_noerr( MacCreateEvent( NULL , kEventClassControl , kEventControlSetFocusPart , TicksToEventTime( TickCount() ) , kEventAttributeUserEvent , + &evRef ) ); + + wxMacCarbonEvent cEvent( evRef ) ; + cEvent.SetParameter( kEventParamDirectObject , (ControlRef) former->GetHandle() ) ; + cEvent.SetParameter(kEventParamControlPart , typeControlPartCode , kControlFocusNoPart ) ; + + wxMacWindowEventHandler( NULL , evRef , former ) ; + ReleaseEvent(evRef) ; } - gFocusWindow = this ; + // send new focus event { - #if wxUSE_CARET - // Deal with caret - if ( m_caret ) - { - m_caret->OnSetFocus(); - } - #endif // wxUSE_CARET - // panel wants to track the window which was the last to have focus in it - wxChildFocusEvent eventFocus(this); - GetEventHandler()->ProcessEvent(eventFocus); - - #ifndef __WXUNIVERSAL__ - wxControl* control = wxDynamicCast( gFocusWindow , wxControl ) ; - if ( control && control->GetHandle() ) - { - UMASetKeyboardFocus( (WindowRef) gFocusWindow->MacGetTopLevelWindowRef() , (ControlRef) control->GetHandle() , kControlFocusNextPart ) ; - } - #endif - wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId); - event.SetEventObject(this); - GetEventHandler()->ProcessEvent(event) ; + EventRef evRef = NULL ; + verify_noerr( MacCreateEvent( NULL , kEventClassControl , kEventControlSetFocusPart , TicksToEventTime( TickCount() ) , kEventAttributeUserEvent , + &evRef ) ); + + wxMacCarbonEvent cEvent( evRef ) ; + cEvent.SetParameter( kEventParamDirectObject , (ControlRef) GetHandle() ) ; + cEvent.SetParameter(kEventParamControlPart , typeControlPartCode , kControlFocusNextPart ) ; + + wxMacWindowEventHandler( NULL , evRef , this ) ; + ReleaseEvent(evRef) ; } +#endif } } @@ -905,11 +1046,7 @@ void wxWindowMac::MacGetPositionAndSizeFromControl(int& x, int& y, if ( tlw ) { Point tlworigin = { 0 , 0 } ; - GrafPtr port ; - ::GetPort( &port ) ; - ::SetPort( UMAGetWindowPort( (WindowRef) tlw->MacGetWindowRef() ) ) ; - ::LocalToGlobal( &tlworigin ) ; - ::SetPort( port ) ; + QDLocalToGlobalPoint( UMAGetWindowPort( (WindowRef) tlw->MacGetWindowRef() ) , &tlworigin ) ; x = tlworigin.h ; y = tlworigin.v ; } @@ -918,7 +1055,7 @@ void wxWindowMac::MacGetPositionAndSizeFromControl(int& x, int& y, bool wxWindowMac::MacGetBoundsForControl(const wxPoint& pos, const wxSize& size, int& x, int& y, - int& w, int& h) const + int& w, int& h , bool adjustOrigin ) const { x = (int)pos.x; y = (int)pos.y; @@ -928,7 +1065,8 @@ bool wxWindowMac::MacGetBoundsForControl(const wxPoint& pos, #if !TARGET_API_MAC_OSX GetParent()->MacWindowToRootWindow( &x , &y ) ; #endif - + if ( adjustOrigin ) + AdjustForParentClientOrigin( x , y ) ; return true ; } @@ -1003,8 +1141,7 @@ void wxWindowMac::DoScreenToClient(int *x, int *y) const if(x) localwhere.h = * x ; if(y) localwhere.v = * y ; - wxMacPortSaver s((GrafPtr)GetWindowPort( window )) ; - ::GlobalToLocal( &localwhere ) ; + QDGlobalToLocalPoint( GetWindowPort( window ) , &localwhere ) ; if(x) *x = localwhere.h ; if(y) *y = localwhere.v ; @@ -1031,9 +1168,7 @@ void wxWindowMac::DoClientToScreen(int *x, int *y) const Point localwhere = { 0,0 }; if(x) localwhere.h = * x ; if(y) localwhere.v = * y ; - - wxMacPortSaver s((GrafPtr)GetWindowPort( window )) ; - ::LocalToGlobal( &localwhere ) ; + QDLocalToGlobalPoint( GetWindowPort( window ) , &localwhere ) ; if(x) *x = localwhere.h ; if(y) *y = localwhere.v ; } @@ -1064,7 +1199,8 @@ void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const if ( x ) pt.x = *x ; if ( y ) pt.y = *y ; - HIViewConvertPoint( &pt , (ControlRef) m_macControl , (ControlRef) MacGetTopLevelWindow()->GetHandle() ) ; + if ( !IsTopLevel() ) + HIViewConvertPoint( &pt , (ControlRef) m_macControl , (ControlRef) MacGetTopLevelWindow()->GetHandle() ) ; if ( x ) *x = (int) pt.x ; if ( y ) *y = (int) pt.y ; @@ -1096,7 +1232,8 @@ void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const if ( x ) pt.x = *x ; if ( y ) pt.y = *y ; - HIViewConvertPoint( &pt , (ControlRef) MacGetTopLevelWindow()->GetHandle() , (ControlRef) m_macControl ) ; + if ( !IsTopLevel() ) + HIViewConvertPoint( &pt , (ControlRef) MacGetTopLevelWindow()->GetHandle() , (ControlRef) m_macControl ) ; if ( x ) *x = (int) pt.x ; if ( y ) *y = (int) pt.y ; @@ -1121,6 +1258,30 @@ void wxWindowMac::MacRootWindowToWindow( short *x , short *y ) const if ( y ) *y = y1 ; } +void wxWindowMac::MacGetContentAreaInset( int &left , int &top , int &right , int &bottom ) +{ + RgnHandle rgn = NewRgn() ; + Rect content ; + if ( GetControlRegion( (ControlRef) m_macControl , kControlContentMetaPart , rgn ) == noErr ) + { + GetRegionBounds( rgn , &content ) ; + DisposeRgn( rgn ) ; + } + else + { + GetControlBounds( (ControlRef) m_macControl , &content ) ; + } + Rect structure ; + GetControlBounds( (ControlRef) m_macControl , &structure ) ; +#if !TARGET_API_MAC_OSX + OffsetRect( &content , -structure.left , -structure.top ) ; +#endif + left = content.left - structure.left ; + top = content.top - structure.top ; + right = structure.right - content.right ; + bottom = structure.bottom - content.bottom ; +} + wxSize wxWindowMac::DoGetSizeFromClientSize( const wxSize & size ) const { wxSize sizeTotal = size; @@ -1358,7 +1519,8 @@ void wxWindowMac::DoMoveWindow(int x, int y, int width, int height) if ( doMove || doResize ) { - Rect r = wxMacGetBoundsForControl(this , wxPoint( actualX,actualY), wxSize( actualWidth, actualHeight ) ) ; + // we don't adjust twice for the origin + Rect r = wxMacGetBoundsForControl(this , wxPoint( actualX,actualY), wxSize( actualWidth, actualHeight ) , false ) ; bool vis = IsControlVisible( (ControlRef) m_macControl ) ; #if TARGET_API_MAC_OSX // the HIViewSetFrame call itself should invalidate the areas, but when testing with the UnicodeTextCtrl it does not ! @@ -1369,13 +1531,9 @@ void wxWindowMac::DoMoveWindow(int x, int y, int width, int height) if ( vis ) SetControlVisibility( (ControlRef)m_macControl , true , true ) ; #else -// TODO TEST SetControlBounds( (ControlRef) m_macControl , &r ) ; if ( vis ) SetControlVisibility( (ControlRef)m_macControl , false , true ) ; - if ( doMove ) - MoveControl( (ControlRef) m_macControl , r.left , r.top ) ; - if ( doSize ) - SizeControl( (ControlRef) m_macControl , r.right-r.left , r.bottom-r.top ) ; + SetControlBounds( (ControlRef) m_macControl , &r ) ; if ( vis ) SetControlVisibility( (ControlRef)m_macControl , true , true ) ; #endif @@ -1518,9 +1676,14 @@ wxPoint wxWindowMac::GetClientAreaOrigin() const GetRegionBounds( rgn , &content ) ; DisposeRgn( rgn ) ; #if !TARGET_API_MAC_OSX - Rect structure ; - GetControlBounds( (ControlRef) m_macControl , &structure ) ; - OffsetRect( &content , -structure.left , -structure.top ) ; + // if the content rgn is empty / not supported + // don't attempt to correct the coordinates to wxWindow relative ones + if (!::EmptyRect( &content ) ) + { + Rect structure ; + GetControlBounds( (ControlRef) m_macControl , &structure ) ; + OffsetRect( &content , -structure.left , -structure.top ) ; + } #endif return wxPoint( content.left + MacGetLeftBorderSize( ) , content.top + MacGetTopBorderSize( ) ); @@ -1578,10 +1741,17 @@ bool wxWindowMac::Enable(bool enable) return FALSE; bool former = MacIsReallyEnabled() ; +#if TARGET_API_MAC_OSX if ( enable ) EnableControl( (ControlRef) m_macControl ) ; else DisableControl( (ControlRef) m_macControl ) ; +#else + if ( enable ) + ActivateControl( (ControlRef) m_macControl ) ; + else + DeactivateControl( (ControlRef) m_macControl ) ; +#endif if ( former != MacIsReallyEnabled() ) MacPropagateEnabledStateChanged() ; @@ -1683,7 +1853,11 @@ bool wxWindowMac::MacIsReallyShown() bool wxWindowMac::MacIsReallyEnabled() { +#if TARGET_API_MAC_OSX return IsControlEnabled( (ControlRef) m_macControl ) ; +#else + return IsControlActive( (ControlRef) m_macControl ) ; +#endif } bool wxWindowMac::MacIsReallyHilited() @@ -1691,6 +1865,13 @@ bool wxWindowMac::MacIsReallyHilited() return IsControlActive( (ControlRef) m_macControl ) ; } +void wxWindowMac::MacFlashInvalidAreas() +{ +#if TARGET_API_MAC_OSX + HIViewFlashDirtyArea( (WindowRef) MacGetTopLevelWindowRef() ) ; +#endif +} + // // // @@ -1809,6 +1990,51 @@ void wxWindowMac::Refresh(bool eraseBack, const wxRect *rect) #endif } +void wxWindowMac::Freeze() +{ +#if TARGET_API_MAC_OSX + if ( !m_frozenness++ ) + { + HIViewSetDrawingEnabled( (HIViewRef) m_macControl , false ) ; + } +#endif +} + +#if TARGET_API_MAC_OSX +static void InvalidateControlAndChildren( HIViewRef control ) +{ + HIViewSetNeedsDisplay( control , true ) ; + UInt16 childrenCount = 0 ; + OSStatus err = CountSubControls( control , &childrenCount ) ; + if ( err == errControlIsNotEmbedder ) + return ; + wxASSERT_MSG( err == noErr , wxT("Unexpected error when accessing subcontrols") ) ; + + for ( UInt16 i = childrenCount ; i >=1 ; --i ) + { + HIViewRef child ; + err = GetIndexedSubControl( control , i , & child ) ; + if ( err == errControlIsNotEmbedder ) + return ; + InvalidateControlAndChildren( child ) ; + } +} +#endif + +void wxWindowMac::Thaw() +{ +#if TARGET_API_MAC_OSX + wxASSERT_MSG( m_frozenness > 0, _T("Thaw() without matching Freeze()") ); + + if ( !--m_frozenness ) + { + HIViewSetDrawingEnabled( (HIViewRef) m_macControl , true ) ; + InvalidateControlAndChildren( (HIViewRef) m_macControl ) ; + // HIViewSetNeedsDisplay( (HIViewRef) m_macControl , true ) ; + } +#endif +} + void wxWindowMac::MacRedrawControl() { /* @@ -2064,57 +2290,62 @@ void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect) { - wxClientDC dc(this) ; - wxMacPortSetter helper(&dc) ; int width , height ; GetClientSize( &width , &height ) ; - +#if TARGET_API_MAC_OSX + // 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, + // TODO write optimal workaround + HIRect scrollrect = CGRectMake( MacGetLeftBorderSize() , MacGetTopBorderSize() , width , height ) ; + if ( rect ) + { + HIRect scrollarea = CGRectMake( rect->x , rect->y , rect->width , rect->height) ; + scrollrect = CGRectIntersection( scrollrect , scrollarea ) ; + } + if ( HIViewGetNeedsDisplay( (ControlRef) m_macControl ) ) + { + // becuase HIViewScrollRect does not scroll the already invalidated area we have two options + // either immediate redraw or full invalidate +#if 1 + // is the better overall solution, as it does not slow down scrolling + HIViewSetNeedsDisplay( (ControlRef) m_macControl , true ) ; +#else + // this would be the preferred version for fast drawing controls + if( UMAGetSystemVersion() < 0x1030 ) + Update() ; + else + HIViewRender((ControlRef) m_macControl) ; +#endif + } + HIViewScrollRect ( (ControlRef) m_macControl , &scrollrect , dx ,dy ) ; +#else wxPoint pos; pos.x = pos.y = 0; - + Rect scrollrect; - // TODO take out the boundaries - GetControlBounds( (ControlRef) m_macControl, &scrollrect); - RgnHandle updateRgn = NewRgn() ; - 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 ) ; -#if TARGET_CARBON - //KO: The docs say ScrollRect creates an update region, which thus calls an update event - // but it seems the update only refreshes the background of the control, rather than calling - // kEventControlDraw, so we need to force a proper update here. There has to be a better - // way of doing this... (Note that code below under !TARGET_CARBON does not work either...) - Update(); -#endif - // we also have to scroll the update rgn in this rectangle - // in order not to loose updates -#if !TARGET_CARBON - 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 ) ; + + { + wxClientDC dc(this) ; + wxMacPortSetter helper(&dc) ; + + GetControlBounds( (ControlRef) m_macControl, &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 ) ; } - InvalWindowRgn(rootWindow , updateRgn ) ; - DisposeRgn( updateRgn ) ; - DisposeRgn( formerUpdateRgn ) ; - DisposeRgn( scrollRgn ) ; + // ScrollWindowRect( (WindowRef) MacGetTopLevelWindowRef() , &scrollrect , dx , dy , kScrollWindowInvalidate, updateRgn ) ; #endif } @@ -2140,9 +2371,6 @@ void wxWindowMac::ScrollWindow(int dx, int dy, const wxRect *rect) child->SetSize( x+dx, y+dy, w, h ); } } - -// TODO remove, was moved higher up Update() ; - } void wxWindowMac::MacOnScroll(wxScrollEvent &event ) @@ -2178,7 +2406,9 @@ void wxWindowMac::MacOnScroll(wxScrollEvent &event ) // Get the window with the focus wxWindowMac *wxWindowBase::FindFocus() { - return gFocusWindow ; + ControlRef control ; + GetKeyboardFocus( GetUserFocusWindow() , &control ) ; + return wxFindControlFromMacControl( control ) ; } void wxWindowMac::OnSetFocus(wxFocusEvent& event) @@ -2208,11 +2438,17 @@ void wxWindowMac::OnInternalIdle() // Raise the window to the top of the Z order void wxWindowMac::Raise() { +#if TARGET_API_MAC_OSX + HIViewSetZOrder((ControlRef)m_macControl,kHIViewZOrderAbove, NULL) ; +#endif } // Lower the window to the bottom of the Z order void wxWindowMac::Lower() { +#if TARGET_API_MAC_OSX + HIViewSetZOrder((ControlRef)m_macControl,kHIViewZOrderBelow, NULL) ; +#endif } @@ -2272,7 +2508,37 @@ wxString wxWindowMac::MacGetToolTipString( wxPoint &pt ) void wxWindowMac::Update() { #if TARGET_API_MAC_OSX - HIViewSetNeedsDisplay( (ControlRef) m_macControl , true ) ; + WindowRef window = (WindowRef)MacGetTopLevelWindowRef() ; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3 + // for composited windows this also triggers a redraw of all + // invalid views in the window + if( UMAGetSystemVersion() >= 0x1030 ) + HIWindowFlush(window) ; + else +#endif + { + // the only way to trigger the redrawing on earlier systems is to call + // ReceiveNextEvent + + EventRef currentEvent = (EventRef) wxTheApp->MacGetCurrentEvent() ; + UInt32 currentEventClass = 0 ; + UInt32 currentEventKind = 0 ; + if ( currentEvent != NULL ) + { + currentEventClass = ::GetEventClass( currentEvent ) ; + currentEventKind = ::GetEventKind( currentEvent ) ; + } + if ( currentEventClass != kEventClassMenu ) + { + // when tracking a menu, strange redraw errors occur if we flush now, so leave.. + + EventRef theEvent; + OSStatus status = noErr ; + status = ReceiveNextEvent( 0 , NULL , kEventDurationNoWait , false , &theEvent ) ; + } + else + HIViewSetNeedsDisplay( (ControlRef) m_macControl , true ) ; + } #else ::Draw1Control( (ControlRef) m_macControl ) ; #endif @@ -2362,10 +2628,6 @@ wxRegion wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures ) */ bool wxWindowMac::MacDoRedraw( WXHRGN updatergnr , long time ) { - // we let the OS handle root control redraws - if ( m_macControl == MacGetTopLevelWindow()->GetHandle() ) - return false ; - RgnHandle updatergn = (RgnHandle) updatergnr ; bool handled = false ; @@ -2686,62 +2948,6 @@ void wxWindowMac::OnMouseEvent( wxMouseEvent &event ) if ( ! GetEventHandler()->ProcessEvent(evtCtx) ) event.Skip() ; } - else if (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK ) - { - - int x = event.m_x ; - int y = event.m_y ; - - if ( MacGetTopLevelWindow()->MacUsesCompositing() == false ) - { - // OS Needs it in tlw content area coordinates - MacClientToRootWindow( &x , &y ) ; - } - else - { - // OS Needs it in window not client coordinates - wxPoint origin = GetClientAreaOrigin() ; - x += origin.x ; - y += origin.y ; - } - Point localwhere ; - SInt16 controlpart ; - - localwhere.h = x ; - localwhere.v = y ; - - short modifiers = 0; - - if ( !event.m_leftDown && !event.m_rightDown ) - modifiers |= btnState ; - - if ( event.m_shiftDown ) - modifiers |= shiftKey ; - - if ( event.m_controlDown ) - modifiers |= controlKey ; - - if ( event.m_altDown ) - modifiers |= optionKey ; - - if ( event.m_metaDown ) - modifiers |= cmdKey ; - - bool handled = false ; - - if ( ::IsControlActive( (ControlRef) m_macControl ) ) - { - controlpart = ::HandleControlClick( (ControlRef) m_macControl , localwhere , modifiers , (ControlActionUPP) -1 ) ; - wxTheApp->s_lastMouseDown = 0 ; - if ( controlpart != kControlNoPart ) - { - MacHandleControlClick((WXWidget) (ControlRef) m_macControl , controlpart , false /* mouse not down anymore */ ) ; - handled = true ; - } - } - if ( !handled ) - event.Skip() ; - } else { event.Skip() ; @@ -2750,16 +2956,20 @@ void wxWindowMac::OnMouseEvent( wxMouseEvent &event ) void wxWindowMac::MacHandleControlClick( WXWidget control , wxInt16 controlpart , bool WXUNUSED( mouseStillDown ) ) { - wxASSERT_MSG( (ControlRef) m_macControl != NULL , wxT("No valid mac control") ) ; } -Rect wxMacGetBoundsForControl( wxWindow* window , const wxPoint& pos , const wxSize &size ) +Rect wxMacGetBoundsForControl( wxWindow* window , const wxPoint& pos , const wxSize &size , bool adjustForOrigin ) { int x ,y , w ,h ; - window->MacGetBoundsForControl( pos , size , x , y, w, h ) ; + window->MacGetBoundsForControl( pos , size , x , y, w, h , adjustForOrigin) ; Rect bounds = { y , x , y+h , x+w }; return bounds ; } +wxInt32 wxWindowMac::MacControlHit(WXEVENTHANDLERREF WXUNUSED(handler) , WXEVENTREF WXUNUSED(event) ) +{ + return eventNotHandledErr ; +} +