X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/5879692fb9ebe65fa7aca9f6227531aa279134e5..27de83cd5b05a06ce08af0203d5d8ffecce83de3:/src/mac/carbon/window.cpp diff --git a/src/mac/carbon/window.cpp b/src/mac/carbon/window.cpp index 565c2b38a7..804c0c2650 100644 --- a/src/mac/carbon/window.cpp +++ b/src/mac/carbon/window.cpp @@ -171,6 +171,8 @@ static const EventTypeSpec eventList[] = static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handler , EventRef event , void *data ) { OSStatus result = eventNotHandledErr ; + static wxWindowMac* targetFocusWindow = NULL; + static wxWindowMac* formerFocusWindow = NULL; wxMacCarbonEvent cEvent( event ) ; @@ -209,7 +211,7 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl if ( thisWindow->MacIsUserPane() ) { static float color = 0.5 ; - static channel = 0 ; + static int channel = 0 ; HIRect bounds; CGContextRef cgContext = cEvent.GetParameter(kEventParamCGContextRef) ; @@ -232,17 +234,21 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl bool created = false ; CGContextRef cgContext = NULL ; OSStatus err = cEvent.GetParameter(kEventParamCGContextRef, &cgContext) ; - wxASSERT_MSG( err == noErr , wxT("Unable to retrieve CGContextRef") ) ; + if ( err != noErr ) + { + wxFAIL_MSG("Unable to retrieve CGContextRef"); + } + thisWindow->MacSetCGContextRef( cgContext ) ; { wxMacCGContextStateSaver sg( cgContext ) ; - float alpha = 1.0 ; + CGFloat alpha = (CGFloat)1.0 ; { wxWindow* iter = thisWindow ; while ( iter ) { - alpha *= (float) iter->GetTransparent()/255.0 ; + alpha *= (CGFloat)( iter->GetTransparent()/255.0 ) ; if ( iter->IsTopLevel() ) iter = NULL ; else @@ -276,7 +282,13 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl break ; case kEventControlVisibilityChanged : - thisWindow->MacVisibilityChanged() ; + // we might have two native controls attributed to the same wxWindow instance + // eg a scrollview and an embedded textview, make sure we only fire for the 'outer' + // control, as otherwise native and wx visibility are different + if ( thisWindow->GetPeer() != NULL && thisWindow->GetPeer()->GetControlRef() == controlRef ) + { + thisWindow->MacVisibilityChanged() ; + } break ; case kEventControlEnabledStateChanged : @@ -308,6 +320,11 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl case kEventControlFocusPartChanged : // the event is emulated by wxmac for systems lower than 10.5 { + if ( UMAGetSystemVersion() < 0x1050 ) + { + // as it is synthesized here, we have to manually avoid propagation + result = noErr; + } ControlPartCode previousControlPart = cEvent.GetParameter(kEventParamControlPreviousPart , typeControlPartCode ); ControlPartCode currentControlPart = cEvent.GetParameter(kEventParamControlCurrentPart , typeControlPartCode ); @@ -334,8 +351,10 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl inKillFocusEvent = true ; wxFocusEvent event( wxEVT_KILL_FOCUS, thisWindow->GetId()); event.SetEventObject(thisWindow); + event.SetWindow(targetFocusWindow); thisWindow->HandleWindowEvent(event) ; inKillFocusEvent = false ; + targetFocusWindow = NULL; } } else if ( previousControlPart == 0 ) @@ -353,7 +372,9 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl wxFocusEvent event(wxEVT_SET_FOCUS, thisWindow->GetId()); event.SetEventObject(thisWindow); + event.SetWindow(formerFocusWindow); thisWindow->HandleWindowEvent(event) ; + formerFocusWindow = NULL; } } break; @@ -367,7 +388,17 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl } #endif ControlPartCode controlPart = cEvent.GetParameter(kEventParamControlPart , typeControlPartCode ); - + if ( controlPart != kControlFocusNoPart ) + { + targetFocusWindow = thisWindow; + wxLogTrace(_T("Focus"), _T("focus to be set(%p)"), wx_static_cast(void*, thisWindow)); + } + else + { + formerFocusWindow = thisWindow; + wxLogTrace(_T("Focus"), _T("focus to be lost(%p)"), wx_static_cast(void*, thisWindow)); + } + ControlPartCode previousControlPart = 0; verify_noerr( HIViewGetFocusPart(controlRef, &previousControlPart)); @@ -384,27 +415,31 @@ static pascal OSStatus wxMacWindowControlEventHandler( EventHandlerCallRef handl { // 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 ); + if ( result == noErr ) + { + 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( kEventParamPostTarget, typeEventTargetRef, GetControlEventTarget( controlRef ) ); + iEvent.SetParameter( kEventParamControlPreviousPart, typeControlPartCode, previousControlPart ); + iEvent.SetParameter( kEventParamControlCurrentPart, typeControlPartCode, currentControlPart ); + +#if 1 + // TODO test this first, avoid double posts etc... + PostEventToQueue( GetMainEventQueue(), evRef , kEventPriorityHigh ); #else - wxMacWindowControlEventHandler( NULL , evRef , data ) ; + wxMacWindowControlEventHandler( NULL , evRef , data ) ; #endif - ReleaseEvent( evRef ) ; + ReleaseEvent( evRef ) ; + } #else // old implementation, to be removed if the new one works if ( controlPart == kControlFocusNoPart ) @@ -865,7 +900,6 @@ wxWindowMac::wxWindowMac(wxWindowMac *parent, void wxWindowMac::Init() { m_peer = NULL ; - m_frozenness = 0 ; m_macAlpha = 255 ; m_cgContextRef = NULL ; @@ -880,9 +914,6 @@ void wxWindowMac::Init() m_macIsUserPane = true; m_clipChildren = false ; m_cachedClippedRectValid = false ; - - // we need a valid font for the encodings - wxWindowBase::SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT)); } wxWindowMac::~wxWindowMac() @@ -1109,7 +1140,7 @@ void wxWindowMac::MacUpdateControlFont() { m_peer->SetFont( GetFont() , GetForegroundColour() , GetWindowStyle() ) ; // do not trigger refreshes upon invisible and possible partly created objects - if ( MacIsReallyShown() ) + if ( IsShownOnScreen() ) Refresh() ; } @@ -1175,9 +1206,14 @@ void wxWindowMac::SetFocus() // 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 + wxLogTrace(_T("Focus"), _T("before wxWindow::SetFocus(%p) %d"), wx_static_cast(void*, this), GetName().c_str()); OSStatus err = m_peer->SetFocus( kControlFocusNextPart ) ; if ( err == errCouldntSetFocus ) + { + wxLogTrace(_T("Focus"), _T("in wxWindow::SetFocus(%p) errCouldntSetFocus"), wx_static_cast(void*, this)); return ; + } + wxLogTrace(_T("Focus"), _T("after wxWindow::SetFocus(%p)"), wx_static_cast(void*, this)); SetUserFocusWindow( (WindowRef)MacGetTopLevelWindowRef() ); } @@ -1400,7 +1436,7 @@ void wxWindowMac::MacWindowToRootWindow( int *x , int *y ) const if ( !IsTopLevel() ) { - wxTopLevelWindowMac* top = MacGetTopLevelWindow(); + wxNonOwnedWindow* top = MacGetTopLevelWindow(); if (top) { pt.x -= MacGetLeftBorderSize() ; @@ -1443,7 +1479,7 @@ void wxWindowMac::MacRootWindowToWindow( int *x , int *y ) const if ( !IsTopLevel() ) { - wxTopLevelWindowMac* top = MacGetTopLevelWindow(); + wxNonOwnedWindow* top = MacGetTopLevelWindow(); if (top) { wxMacControl::Convert( &pt , top->m_peer , m_peer ) ; @@ -1574,7 +1610,7 @@ bool wxWindowMac::SetCursor(const wxCursor& cursor) wxWindowMac *mouseWin = 0 ; { - wxTopLevelWindowMac *tlw = MacGetTopLevelWindow() ; + wxNonOwnedWindow *tlw = MacGetTopLevelWindow() ; WindowRef window = (WindowRef) ( tlw ? tlw->MacGetWindowRef() : 0 ) ; ControlPartCode part ; @@ -1674,7 +1710,7 @@ void wxWindowMac::MacInvalidateBorders() if ( m_peer == NULL ) return ; - bool vis = MacIsReallyShown() ; + bool vis = IsShownOnScreen() ; if ( !vis ) return ; @@ -1943,7 +1979,7 @@ void wxWindowMac::SetLabel(const wxString& title) m_peer->SetLabel( wxStripMenuCodes(m_label, wxStrip_Mnemonics) ) ; // do not trigger refreshes upon invisible and possible partly created objects - if ( MacIsReallyShown() ) + if ( IsShownOnScreen() ) Refresh() ; } @@ -1989,31 +2025,6 @@ void wxWindowMac::MacEnabledStateChanged() // status queries on the inherited window's state // -bool wxWindowMac::MacIsReallyShown() -{ - // only under OSX the visibility of the TLW is taken into account - if ( m_isBeingDeleted ) - return false ; - -#if TARGET_API_MAC_OSX - if ( m_peer && m_peer->Ok() ) - return m_peer->IsVisible(); -#endif - - wxWindow* win = this ; - while ( win->IsShown() ) - { - if ( win->IsTopLevel() ) - return true ; - - win = win->GetParent() ; - if ( win == NULL ) - return true ; - } - - return false ; -} - bool wxWindowMac::MacIsReallyEnabled() { return m_peer->IsEnabled() ; @@ -2075,7 +2086,7 @@ void wxWindowMac::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect) if ( m_peer == NULL ) return ; - if ( !MacIsReallyShown() ) + if ( !IsShownOnScreen() ) return ; if ( rect ) @@ -2091,38 +2102,25 @@ void wxWindowMac::Refresh(bool WXUNUSED(eraseBack), const wxRect *rect) } } -void wxWindowMac::Freeze() +void wxWindowMac::DoFreeze() { #if TARGET_API_MAC_OSX - if ( !m_frozenness++ ) - { - if ( m_peer && m_peer->Ok() ) - m_peer->SetDrawingEnabled( false ) ; - } + if ( m_peer && m_peer->Ok() ) + m_peer->SetDrawingEnabled( false ) ; #endif } -void wxWindowMac::Thaw() +void wxWindowMac::DoThaw() { #if TARGET_API_MAC_OSX - wxASSERT_MSG( m_frozenness > 0, wxT("Thaw() without matching Freeze()") ); - - if ( !--m_frozenness ) + if ( m_peer && m_peer->Ok() ) { - if ( m_peer && m_peer->Ok() ) - { - m_peer->SetDrawingEnabled( true ) ; - m_peer->InvalidateWithChildren() ; - } + m_peer->SetDrawingEnabled( true ) ; + m_peer->InvalidateWithChildren() ; } #endif } -bool wxWindowMac::IsFrozen() const -{ - return m_frozenness != 0; -} - wxWindowMac *wxGetActiveWindow() { // actually this is a windows-only concept @@ -2151,6 +2149,12 @@ void wxWindowMac::OnEraseBackground(wxEraseEvent& event) { event.GetDC()->Clear() ; } + else if ( GetBackgroundStyle() == wxBG_STYLE_CUSTOM ) + { + // don't skip the event here, custom background means that the app + // is drawing it itself in its OnPaint(), so don't draw it at all + // now to avoid flicker + } else { event.Skip() ; @@ -2277,7 +2281,7 @@ void wxWindowMac::MacPaintGrowBox() } else { - CGContextSetRGBFillColor( cgContext, 1.0, 1.0 , 1.0 , 1.0 ); + CGContextSetRGBFillColor( cgContext, (CGFloat) 1.0, (CGFloat)1.0 ,(CGFloat) 1.0 , (CGFloat)1.0 ); } CGContextFillRect( cgContext, cgrect ); CGContextRestoreGState( cgContext ); @@ -2516,7 +2520,7 @@ void wxWindowMac::OnInternalIdle() { // This calls the UI-update mechanism (querying windows for // menu/toolbar/control state information) - if (wxUpdateUIEvent::CanUpdate(this) && IsShown()) + if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen()) UpdateWindowUI(wxUPDATE_UI_FROMIDLE); } @@ -2588,14 +2592,14 @@ void wxWindowMac::ClearBackground() void wxWindowMac::Update() { - wxTopLevelWindowMac* top = MacGetTopLevelWindow(); + wxNonOwnedWindow* top = MacGetTopLevelWindow(); if (top) top->MacPerformUpdates() ; } -wxTopLevelWindowMac* wxWindowMac::MacGetTopLevelWindow() const +wxNonOwnedWindow* wxWindowMac::MacGetTopLevelWindow() const { - wxTopLevelWindowMac* win = NULL ; + wxNonOwnedWindow* win = NULL ; WindowRef window = (WindowRef) MacGetTopLevelWindowRef() ; if ( window ) win = wxFindWinFromMacWindow( window ) ; @@ -2628,7 +2632,7 @@ const wxRegion& wxWindowMac::MacGetVisibleRegion( bool includeOuterStructures ) { static wxRegion emptyrgn ; - if ( !m_isBeingDeleted && MacIsReallyShown() /*m_peer->IsVisible() */ ) + if ( !m_isBeingDeleted && IsShownOnScreen() ) { MacUpdateClippedRects() ; if ( includeOuterStructures ) @@ -2846,7 +2850,7 @@ WXWindow wxWindowMac::MacGetTopLevelWindowRef() const #if wxUSE_POPUPWIN wxPopupWindow* popupwin = wxDynamicCast(iter,wxPopupWindow); if ( popupwin ) - return popupwin->MacGetPopupWindowRef(); + return popupwin->MacGetWindowRef(); #endif } iter = iter->GetParent() ; @@ -3167,11 +3171,15 @@ void wxWindowMac::OnMouseEvent( wxMouseEvent &event ) void wxWindowMac::OnPaint( wxPaintEvent & WXUNUSED(event) ) { - if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL - && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT ) - CallNextEventHandler( - (EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , - (EventRef) wxTheApp->MacGetCurrentEvent() ) ; + // for native controls: call their native paint method + if ( !MacIsUserPane() || ( IsTopLevel() && GetBackgroundStyle() == wxBG_STYLE_SYSTEM ) ) + { + if ( wxTheApp->MacGetCurrentEvent() != NULL && wxTheApp->MacGetCurrentEventHandlerCallRef() != NULL + && GetBackgroundStyle() != wxBG_STYLE_TRANSPARENT ) + CallNextEventHandler( + (EventHandlerCallRef)wxTheApp->MacGetCurrentEventHandlerCallRef() , + (EventRef) wxTheApp->MacGetCurrentEvent() ) ; + } } void wxWindowMac::MacHandleControlClick(WXWidget WXUNUSED(control), @@ -3233,3 +3241,29 @@ wxByte wxWindowMac::GetTransparent() const { return m_macAlpha ; } + +bool wxWindowMac::IsShownOnScreen() const +{ +#if TARGET_API_MAC_OSX + if ( m_peer && m_peer->Ok() ) + { + bool peerVis = m_peer->IsVisible(); + bool wxVis = wxWindowBase::IsShownOnScreen(); + if( peerVis != wxVis ) + { + // CS : put a breakpoint here to investigate differences + // between native an wx visibilities + // the only place where I've encountered them until now + // are the hiding/showing sequences where the vis-changed event is + // first sent to the innermost control, while wx does things + // from the outmost control + wxVis = wxWindowBase::IsShownOnScreen(); + return wxVis; + } + + return m_peer->IsVisible(); + } +#endif + + return wxWindowBase::IsShownOnScreen(); +}