From: David Elliott Date: Sat, 18 Aug 2007 05:05:40 +0000 (+0000) Subject: Change kCFRunLoopBeforeWaiting to kCFRunLoopExit when setting up the run loop X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/1f361be22fdb0ddc5385b31a7a3ebfa230d36d7d?ds=inline Change kCFRunLoopBeforeWaiting to kCFRunLoopExit when setting up the run loop observer for synthesized mouse moved events and add a lengthy comment explaining the reason for the change. Copyright 2007 Software 2000 Ltd. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@48149 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/src/cocoa/window.mm b/src/cocoa/window.mm index d89d7de1a5..d4b353822c 100644 --- a/src/cocoa/window.mm +++ b/src/cocoa/window.mm @@ -1495,7 +1495,27 @@ void wxCocoaMouseMovedEventSynthesizer::AddRunLoopObserver() , NULL , NULL }; - m_runLoopObserver.reset(CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeWaiting, TRUE, 0, SynthesizeMouseMovedEvent, &observerContext)); + + // The kCFRunLoopExit observation point is used such that we hook the run loop after it has already decided that + // it is going to exit which is generally for the purpose of letting the event loop process the next Cocoa event. + + // Executing our procedure within the run loop (e.g. kCFRunLoopBeforeWaiting which was used before) results + // in our observer procedure being called before the run loop has decided that it is going to return control to + // the Cocoa event loop. One major problem is uncovered by the wxGenericHyperlinkCtrl (consider this to be "user + // code") which changes the window's cursor and thus causes the cursor rectangle's to be invalidated. + + // Cocoa implements this invalidation using a delayed notification scheme whereby the resetCursorRects method + // won't be called until the CFRunLoop gets around to it. If the CFRunLoop has not yet exited then it will get + // around to it before letting the event loop do its work. This has some very odd effects on the way the + // newly created tracking rects function. In particular, we will often miss the mouseExited: message if the + // user flicks the mouse quickly enough such that the mouse is already outside of the tracking rect by the + // time the new one is built. + + // Observing from the kCFRunLoopExit point gives Cocoa's event loop an opportunity to chew some events before it cedes + // control back to the CFRunLoop, thus causing the delayed notifications to fire at an appropriate time and + // the mouseExited: message to be sent properly. + + m_runLoopObserver.reset(CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopExit, TRUE, 0, SynthesizeMouseMovedEvent, &observerContext)); CFRunLoopAddObserver([[NSRunLoop currentRunLoop] getCFRunLoop], m_runLoopObserver, kCFRunLoopCommonModes); wxLogTrace(wxTRACE_COCOA_TrackingRect, wxT("Added tracking rect run loop observer")); }