]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/event.cpp
Show OLE errors using wxLogDebug() in wxAutomationObject.
[wxWidgets.git] / src / common / event.cpp
index 34ec269af161a4d5e5a2dfc76cd14efeb4896992..b6c0144752529d3bc6fae6a13971db34c6030464 100644 (file)
@@ -366,6 +366,7 @@ wxEvent::wxEvent(int theId, wxEventType commandType)
     m_isCommandEvent = false;
     m_propagationLevel = wxEVENT_PROPAGATE_NONE;
     m_wasProcessed = false;
     m_isCommandEvent = false;
     m_propagationLevel = wxEVENT_PROPAGATE_NONE;
     m_wasProcessed = false;
+    m_processHereOnly = false;
 }
 
 wxEvent::wxEvent(const wxEvent& src)
 }
 
 wxEvent::wxEvent(const wxEvent& src)
@@ -379,6 +380,7 @@ wxEvent::wxEvent(const wxEvent& src)
     , m_skipped(src.m_skipped)
     , m_isCommandEvent(src.m_isCommandEvent)
     , m_wasProcessed(false)
     , m_skipped(src.m_skipped)
     , m_isCommandEvent(src.m_isCommandEvent)
     , m_wasProcessed(false)
+    , m_processHereOnly(false)
 {
 }
 
 {
 }
 
@@ -395,7 +397,7 @@ wxEvent& wxEvent::operator=(const wxEvent& src)
     m_skipped = src.m_skipped;
     m_isCommandEvent = src.m_isCommandEvent;
 
     m_skipped = src.m_skipped;
     m_isCommandEvent = src.m_isCommandEvent;
 
-    // don't change m_wasProcessed
+    // don't change m_wasProcessed nor m_processHereOnly
 
     return *this;
 }
 
     return *this;
 }
@@ -752,6 +754,46 @@ wxKeyEvent::wxKeyEvent(const wxKeyEvent& evt)
 #endif
 }
 
 #endif
 }
 
+bool wxKeyEvent::IsKeyInCategory(int category) const
+{
+    switch ( GetKeyCode() )
+    {
+        case WXK_LEFT:
+        case WXK_RIGHT:
+        case WXK_UP:
+        case WXK_DOWN:
+        case WXK_NUMPAD_LEFT:
+        case WXK_NUMPAD_RIGHT:
+        case WXK_NUMPAD_UP:
+        case WXK_NUMPAD_DOWN:
+            return (category & WXK_CATEGORY_ARROW) != 0;
+
+        case WXK_PAGEDOWN:
+        case WXK_END:
+        case WXK_NUMPAD_PAGEUP:
+        case WXK_NUMPAD_PAGEDOWN:
+            return (category & WXK_CATEGORY_PAGING) != 0;
+
+        case WXK_HOME:
+        case WXK_PAGEUP:
+        case WXK_NUMPAD_HOME:
+        case WXK_NUMPAD_END:
+            return (category & WXK_CATEGORY_JUMP) != 0;
+
+        case WXK_TAB:
+        case WXK_NUMPAD_TAB:
+            return (category & WXK_CATEGORY_TAB) != 0;
+
+        case WXK_BACK:
+        case WXK_DELETE:
+        case WXK_NUMPAD_DELETE:
+            return (category & WXK_CATEGORY_CUT) != 0;
+
+        default:
+            return false;
+    }
+}
+
 // ----------------------------------------------------------------------------
 // wxWindowCreateEvent
 // ----------------------------------------------------------------------------
 // ----------------------------------------------------------------------------
 // wxWindowCreateEvent
 // ----------------------------------------------------------------------------
@@ -1290,6 +1332,18 @@ bool wxEvtHandler::TryBefore(wxEvent& event)
 
 bool wxEvtHandler::TryAfter(wxEvent& event)
 {
 
 bool wxEvtHandler::TryAfter(wxEvent& event)
 {
+    // We only want to pass the window to the application object once even if
+    // there are several chained handlers. Ensure that this is what happens by
+    // only calling DoTryApp() if there is no next handler (which would do it).
+    //
+    // Notice that, unlike simply calling TryAfter() on the last handler in the
+    // chain only from ProcessEvent(), this also works with wxWindow object in
+    // the middle of the chain: its overridden TryAfter() will still be called
+    // and propagate the event upwards the window hierarchy even if it's not
+    // the last one in the chain (which, admittedly, shouldn't happen often).
+    if ( GetNextHandler() )
+        return GetNextHandler()->TryAfter(event);
+
 #if WXWIN_COMPATIBILITY_2_8
     // as above, call the old virtual function for compatibility
     return TryParent(event);
 #if WXWIN_COMPATIBILITY_2_8
     // as above, call the old virtual function for compatibility
     return TryParent(event);
@@ -1300,11 +1354,12 @@ bool wxEvtHandler::TryAfter(wxEvent& event)
 
 bool wxEvtHandler::ProcessEvent(wxEvent& event)
 {
 
 bool wxEvtHandler::ProcessEvent(wxEvent& event)
 {
-    // allow the application to hook into event processing
+    // The very first thing we do is to allow the application to hook into
+    // event processing in order to globally pre-process all events.
     //
     //
-    // note that we should only do it if we're the first event handler called
+    // Note that we should only do it if we're the first event handler called
     // to avoid calling FilterEvent() multiple times as the event goes through
     // to avoid calling FilterEvent() multiple times as the event goes through
-    // the event handler chain and possibly upwards the window hierarchy
+    // the event handler chain and possibly upwards the window hierarchy.
     if ( !event.WasProcessed() )
     {
         if ( wxTheApp )
     if ( !event.WasProcessed() )
     {
         if ( wxTheApp )
@@ -1321,30 +1376,80 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
         }
     }
 
         }
     }
 
-    if ( ProcessEventHere(event) )
+    // Short circuit the event processing logic if we're requested to process
+    // this event in this handler only, see DoTryChain() for more details.
+    if ( event.ShouldProcessHereOnly() )
+        return TryHere(event);
+
+
+    // Try to process the event in this handler itself.
+    if ( ProcessEventLocally(event) )
         return true;
 
         return true;
 
-    // pass the event to the next handler, notice that we shouldn't call
-    // TryAfter() even if it doesn't handle the event as the last handler in
-    // the chain will do it
-    if ( GetNextHandler() )
-        return GetNextHandler()->ProcessEvent(event);
+    // If we still didn't find a handler, propagate the event upwards the
+    // window chain and/or to the application object.
+    if ( TryAfter(event) )
+        return true;
 
 
-    // propagate the event upwards the window chain and/or to the application
-    // object if it wasn't processed at this level
-    return TryAfter(event);
+
+    // No handler found anywhere, bail out.
+    return false;
 }
 
 }
 
-bool wxEvtHandler::ProcessEventHere(wxEvent& event)
+bool wxEvtHandler::ProcessEventLocally(wxEvent& event)
+{
+    // First try the hooks which should be called before our own handlers
+    if ( TryBefore(event) )
+        return true;
+
+    // Then try this handler itself, notice that we should not call
+    // ProcessEvent() on this one as we're already called from it, which
+    // explains why we do it here and not in DoTryChain()
+    if ( TryHere(event) )
+        return true;
+
+    // Finally try the event handlers chained to this one,
+    if ( DoTryChain(event) )
+        return true;
+
+    // And return false to indicate that we didn't find any handler at this
+    // level.
+    return false;
+}
+
+bool wxEvtHandler::DoTryChain(wxEvent& event)
+{
+    for ( wxEvtHandler *h = GetNextHandler(); h; h = h->GetNextHandler() )
+    {
+        // We need to process this event at the level of this handler only
+        // right now, the pre-/post-processing was either already done by
+        // ProcessEvent() from which we were called or will be done by it when
+        // we return.
+        //
+        // However we must call ProcessEvent() and not TryHere() because the
+        // existing code (including some in wxWidgets itself) expects the
+        // overridden ProcessEvent() in its custom event handlers pushed on a
+        // window to be called.
+        //
+        // So we must call ProcessEvent() but it must not do what it usually
+        // does. To resolve this paradox we pass a special "process here only"
+        // flag to ProcessEvent() via the event object itself. This ensures
+        // that if our own, base class, version is called, it will just call
+        // TryHere() and won't do anything else, just as we want it to.
+        wxEventProcessHereOnly processHereOnly(event);
+        if ( h->ProcessEvent(event) )
+            return true;
+    }
+
+    return false;
+}
+
+bool wxEvtHandler::TryHere(wxEvent& event)
 {
     // If the event handler is disabled it doesn't process any events
     if ( !GetEvtHandlerEnabled() )
         return false;
 
 {
     // If the event handler is disabled it doesn't process any events
     if ( !GetEvtHandlerEnabled() )
         return false;
 
-    // Try the hooks which should be called before our own handlers
-    if ( TryBefore(event) )
-        return true;
-
     // Handle per-instance dynamic event tables first
     if ( m_dynamicEvents && SearchDynamicEventTable(event) )
         return true;
     // Handle per-instance dynamic event tables first
     if ( m_dynamicEvents && SearchDynamicEventTable(event) )
         return true;