X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6548fabe00fca91c3638eaab45dd4132286ed18e..d6fd667bc19986e20f7ca33976061d57d89bc41c:/src/mac/carbon/window.cpp diff --git a/src/mac/carbon/window.cpp b/src/mac/carbon/window.cpp index 0d5bf2fab7..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 @@ -120,7 +123,12 @@ static const EventTypeSpec eventList[] = { kEventClassControl , kEventControlEnabledStateChanged } , { kEventClassControl , kEventControlHiliteChanged } , { kEventClassControl , kEventControlSetFocusPart } , -// { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only + + { kEventClassService , kEventServiceGetTypes }, + { kEventClassService , kEventServiceCopy }, + { kEventClassService , kEventServicePaste }, + + // { kEventClassControl , kEventControlInvalidateForSizeChange } , // 10.3 only // { kEventClassControl , kEventControlBoundsChanged } , #endif } ; @@ -222,6 +230,8 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl event.SetEventObject(thisWindow); thisWindow->GetEventHandler()->ProcessEvent(event) ; } + if ( thisWindow->MacIsUserPane() ) + result = noErr ; } break ; #endif @@ -236,6 +246,84 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl 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 ; @@ -245,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 ; } @@ -469,6 +559,22 @@ 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 ; @@ -610,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 @@ -673,22 +787,12 @@ 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 ) @@ -942,11 +1046,7 @@ void wxWindowMac::MacGetPositionAndSizeFromControl(int& x, int& y, if ( tlw ) { Point tlworigin = { 0 , 0 } ; - GrafPtr port ; - bool swapped = QDSwapPort( UMAGetWindowPort( (WindowRef) tlw->MacGetWindowRef() ) , &port ) ; - ::LocalToGlobal( &tlworigin ) ; - if ( swapped ) - ::SetPort( port ) ; + QDLocalToGlobalPoint( UMAGetWindowPort( (WindowRef) tlw->MacGetWindowRef() ) , &tlworigin ) ; x = tlworigin.h ; y = tlworigin.v ; } @@ -1041,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 ; @@ -1069,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 ; } @@ -1579,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( ) ); @@ -1639,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() ; @@ -1744,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() @@ -1752,6 +1865,13 @@ bool wxWindowMac::MacIsReallyHilited() return IsControlActive( (ControlRef) m_macControl ) ; } +void wxWindowMac::MacFlashInvalidAreas() +{ +#if TARGET_API_MAC_OSX + HIViewFlashDirtyArea( (WindowRef) MacGetTopLevelWindowRef() ) ; +#endif +} + // // // @@ -2170,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 } @@ -2246,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 ) @@ -2386,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