]> git.saurik.com Git - wxWidgets.git/commitdiff
Fix a number of problems with tracking rectangles by avoiding rebuilding them when...
authorDavid Elliott <dfe@tgwbd.org>
Sun, 19 Aug 2007 03:25:17 +0000 (03:25 +0000)
committerDavid Elliott <dfe@tgwbd.org>
Sun, 19 Aug 2007 03:25:17 +0000 (03:25 +0000)
Copyright 2007 Software 2000 Ltd.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@48169 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/cocoa/trackingrectmanager.h
src/cocoa/window.mm

index 115791260657b2b975d132963062d2e26dee5310..40fac51aad10b09bdea3af9fb47bb0c3e17169e7 100644 (file)
@@ -23,6 +23,7 @@ public:
     wxCocoaTrackingRectManager(wxWindow *window);
     void ClearTrackingRect();
     void BuildTrackingRect();
+    void RebuildTrackingRectIfNeeded();
     void RebuildTrackingRect();
     bool IsOwnerOfEvent(NSEvent *anEvent);
     ~wxCocoaTrackingRectManager();
@@ -32,6 +33,7 @@ protected:
     wxWindow *m_window;
     bool m_isTrackingRectActive;
     int m_trackingRectTag;
+    NSRect m_trackingRectInWindowCoordinates;
 private:
     wxCocoaTrackingRectManager();
 };
index 194d5685bc4e2e2f46fa7f94e98b3ba4e1780a08..5b881d3c0fcf274beed71d08161e5d47e4f52b22 100644 (file)
@@ -811,8 +811,21 @@ void wxWindowCocoa::Cocoa_FrameChanged(void)
 bool wxWindowCocoa::Cocoa_resetCursorRects()
 {
     wxLogTrace(wxTRACE_COCOA,wxT("wxWindow=%p::Cocoa_resetCursorRects"),this);
+
+    // When we are called there may be a queued tracking rect event (mouse entered or exited) and
+    // we won't know it.  A specific example is wxGenericHyperlinkCtrl changing the cursor from its
+    // mouse exited event.  If the control happens to share the edge with its parent window which is
+    // also tracking mouse events then Cocoa receives two mouse exited events from the window server.
+    // The first one will cause wxGenericHyperlinkCtrl to call wxWindow::SetCursor which will
+    // invaildate the cursor rect causing Cocoa to schedule cursor rect reset with the run loop
+    // which willl in turn call us before exiting for the next user event.
+
+    // If we are the parent window then rebuilding our tracking rectangle will cause us to miss
+    // our mouse exited event because the already queued event will have the old tracking rect
+    // tag.  The simple solution is to only rebuild our tracking rect if we need to.
+
     if(m_visibleTrackingRectManager != NULL)
-        m_visibleTrackingRectManager->RebuildTrackingRect();
+        m_visibleTrackingRectManager->RebuildTrackingRectIfNeeded();
 
     if(!m_cursor.GetNSCursor())
         return false;
@@ -1591,8 +1604,12 @@ void wxCocoaTrackingRectManager::BuildTrackingRect()
 
     if([theView window] != nil)
     {
-        m_trackingRectTag = [theView addTrackingRect:[theView visibleRect] owner:theView userData:NULL assumeInside:NO];
+        NSRect visibleRect = [theView visibleRect];
+
+        m_trackingRectTag = [theView addTrackingRect:visibleRect owner:theView userData:NULL assumeInside:NO];
+        m_trackingRectInWindowCoordinates = [theView convertRect:visibleRect toView:nil];
         m_isTrackingRectActive = true;
+
         wxLogTrace(wxTRACE_COCOA_TrackingRect, wxT("%s@%p: Added tracking rect #%d"), m_window->GetClassInfo()->GetClassName(), m_window, m_trackingRectTag);
     }
 }
@@ -1602,6 +1619,21 @@ void wxCocoaTrackingRectManager::BeginSynthesizingEvents()
     s_mouseMovedSynthesizer.RegisterWxCocoaView(m_window);
 }
 
+void wxCocoaTrackingRectManager::RebuildTrackingRectIfNeeded()
+{
+    if(m_isTrackingRectActive)
+    {
+        NSView *theView = m_window->GetNSView();
+        NSRect currentRect = [theView convertRect:[theView visibleRect] toView:nil];
+        if(NSEqualRects(m_trackingRectInWindowCoordinates,currentRect))
+        {
+            wxLogTrace(wxTRACE_COCOA_TrackingRect, wxT("Ignored request to rebuild TR#%d"), m_trackingRectTag);
+            return;
+        }
+    }
+    RebuildTrackingRect();
+}
+
 void wxCocoaTrackingRectManager::RebuildTrackingRect()
 {
     ClearTrackingRect();