]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/event.cpp
combobox buglet when inserting item
[wxWidgets.git] / src / common / event.cpp
index d367b21ec57ee8c7d9447d950e17f9cf2c6b77cb..2f4f8be170758692659a2a7079c5534a6b959092 100644 (file)
 
 #endif // !USE_SHARED_LIBRARY
 
 
 #endif // !USE_SHARED_LIBRARY
 
+#if wxUSE_THREADS
+/* To put pending event handlers */
+extern wxList *wxPendingEvents;
+extern wxCriticalSection *wxPendingEventsLocker;
+#endif
+
 /*
  * General wxWindows events, covering
  * all interesting things that might happen (button clicking, resizing,
 /*
  * General wxWindows events, covering
  * all interesting things that might happen (button clicking, resizing,
@@ -96,6 +102,23 @@ wxEvent::wxEvent(int theId)
     m_id = theId;
     m_skipped = FALSE;
     m_callbackUserData = (wxObject *) NULL;
     m_id = theId;
     m_skipped = FALSE;
     m_callbackUserData = (wxObject *) NULL;
+    m_isCommandEvent = FALSE;
+}
+
+wxObject *wxEvent::Clone() const
+{
+    wxEvent *event = (wxEvent *)wxObject::Clone();
+
+    event->m_eventType = m_eventType;
+    event->m_eventObject = m_eventObject;
+    event->m_eventHandle = m_eventHandle;
+    event->m_timeStamp = m_timeStamp;
+    event->m_id = m_id;
+    event->m_skipped = m_skipped;
+    event->m_callbackUserData = m_callbackUserData;
+    event->m_isCommandEvent = m_isCommandEvent;
+
+    return event;
 }
 
 /*
 }
 
 /*
@@ -111,7 +134,8 @@ wxCommandEvent::wxCommandEvent(wxEventType commandType, int theId)
     m_extraLong = 0;
     m_commandInt = 0;
     m_id = theId;
     m_extraLong = 0;
     m_commandInt = 0;
     m_id = theId;
-    m_commandString = (char *) NULL;
+    m_commandString = (wxChar *) NULL;
+    m_isCommandEvent = TRUE;
 }
 
 /*
 }
 
 /*
@@ -163,7 +187,7 @@ bool wxMouseEvent::ButtonDClick(int but) const
         case 3:
             return RightDClick();
         default:
         case 3:
             return RightDClick();
         default:
-            wxFAIL_MSG("invalid parameter in wxMouseEvent::ButtonDClick");
+            wxFAIL_MSG(_T("invalid parameter in wxMouseEvent::ButtonDClick"));
     }
 
     return FALSE;
     }
 
     return FALSE;
@@ -184,7 +208,7 @@ bool wxMouseEvent::ButtonDown(int but) const
         case 3:
             return RightDown();
         default:
         case 3:
             return RightDown();
         default:
-            wxFAIL_MSG("invalid parameter in wxMouseEvent::ButtonDown");
+            wxFAIL_MSG(_T("invalid parameter in wxMouseEvent::ButtonDown"));
     }
 
     return FALSE;
     }
 
     return FALSE;
@@ -204,7 +228,7 @@ bool wxMouseEvent::ButtonUp(int but) const
         case 3:
             return RightUp();
         default:
         case 3:
             return RightUp();
         default:
-            wxFAIL_MSG("invalid parameter in wxMouseEvent::ButtonUp");
+            wxFAIL_MSG(_T("invalid parameter in wxMouseEvent::ButtonUp"));
     }
 
     return FALSE;
     }
 
     return FALSE;
@@ -223,7 +247,7 @@ bool wxMouseEvent::Button(int but) const
         case 3:
             return (RightDown() || RightUp() || RightDClick());
         default:
         case 3:
             return (RightDown() || RightUp() || RightDClick());
         default:
-            wxFAIL_MSG("invalid parameter in wxMouseEvent::Button");
+            wxFAIL_MSG(_T("invalid parameter in wxMouseEvent::Button"));
     }
 
     return FALSE;
     }
 
     return FALSE;
@@ -241,7 +265,7 @@ bool wxMouseEvent::ButtonIsDown(int but) const
         case 3:
             return RightIsDown();
         default:
         case 3:
             return RightIsDown();
         default:
-            wxFAIL_MSG("invalid parameter in wxMouseEvent::ButtonIsDown");
+            wxFAIL_MSG(_T("invalid parameter in wxMouseEvent::ButtonIsDown"));
     }
 
     return FALSE;
     }
 
     return FALSE;
@@ -280,6 +304,11 @@ wxEvtHandler::wxEvtHandler()
     m_previousHandler = (wxEvtHandler *) NULL;
     m_enabled = TRUE;
     m_dynamicEvents = (wxList *) NULL;
     m_previousHandler = (wxEvtHandler *) NULL;
     m_enabled = TRUE;
     m_dynamicEvents = (wxList *) NULL;
+    m_isWindow = FALSE;
+#if wxUSE_THREADS
+    m_eventsLocker = new wxCriticalSection();
+#endif
+    m_pendingEvents = (wxList *) NULL;
 }
 
 wxEvtHandler::~wxEvtHandler()
 }
 
 wxEvtHandler::~wxEvtHandler()
@@ -303,7 +332,52 @@ wxEvtHandler::~wxEvtHandler()
         }
         delete m_dynamicEvents;
     };
         }
         delete m_dynamicEvents;
     };
+
+#if wxUSE_THREADS
+    if (m_pendingEvents)
+      delete m_pendingEvents;
+
+    delete m_eventsLocker;
+#endif
+}
+
+#if wxUSE_THREADS
+bool wxEvtHandler::ProcessThreadEvent(wxEvent& event)
+{
+    wxEvent *event_main;
+    wxCriticalSectionLocker locker(*m_eventsLocker);
+
+    // check that we are really in a child thread
+    wxASSERT( !wxThread::IsMain() );
+
+    if (m_pendingEvents == NULL)
+      m_pendingEvents = new wxList();
+
+    event_main = (wxEvent *)event.Clone();
+
+    m_pendingEvents->Append(event_main);
+
+    wxPendingEventsLocker->Enter();
+    wxPendingEvents->Append(this);
+    wxPendingEventsLocker->Leave();
+
+    return TRUE;
+}
+
+void wxEvtHandler::ProcessPendingEvents()
+{
+    wxCriticalSectionLocker locker(*m_eventsLocker);
+    wxNode *node = m_pendingEvents->First();
+    wxEvent *event;
+
+    while (node != NULL) {
+      event = (wxEvent *)node->Data();
+      ProcessEvent(*event);
+      delete node;
+      node = m_pendingEvents->First();
+    }
 }
 }
+#endif
 
 /*
  * Event table stuff
 
 /*
  * Event table stuff
@@ -311,14 +385,20 @@ wxEvtHandler::~wxEvtHandler()
 
 bool wxEvtHandler::ProcessEvent(wxEvent& event)
 {
 
 bool wxEvtHandler::ProcessEvent(wxEvent& event)
 {
-    bool isWindow = IsKindOf(CLASSINFO(wxWindow));
+    // check that our flag corresponds to reality
+    wxASSERT( m_isWindow == IsKindOf(CLASSINFO(wxWindow)) );
 
     // An event handler can be enabled or disabled
     if ( GetEvtHandlerEnabled() )
     {
 
     // An event handler can be enabled or disabled
     if ( GetEvtHandlerEnabled() )
     {
+#if wxUSE_THREADS
+       // Check whether we are in a child thread.
+        if (!wxThread::IsMain())
+          return ProcessThreadEvent(event);
+#endif
         // Handle per-instance dynamic event tables first
 
         // Handle per-instance dynamic event tables first
 
-        if (SearchDynamicEventTable( event ))
+        if ( m_dynamicEvents && SearchDynamicEventTable(event) )
             return TRUE;
 
         // Then static per-class event tables
             return TRUE;
 
         // Then static per-class event tables
@@ -333,24 +413,26 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
         // THIS CAN BE CURED if PushEventHandler is used instead of
         // SetEventHandler, and then processing will be passed down the
         // chain of event handlers.
         // THIS CAN BE CURED if PushEventHandler is used instead of
         // SetEventHandler, and then processing will be passed down the
         // chain of event handlers.
-        if ( isWindow )
+        if ( m_isWindow )
         {
             wxWindow *win = (wxWindow *)this;
 
             // Can only use the validator of the window which
             // is receiving the event
         {
             wxWindow *win = (wxWindow *)this;
 
             // Can only use the validator of the window which
             // is receiving the event
-            if ( (win == event.GetEventObject()) &&
-                    win->GetValidator() &&
-                    win->GetValidator()->ProcessEvent(event))
+            if ( win == event.GetEventObject() )
             {
             {
-                return TRUE;
+                wxValidator *validator = win->GetValidator();
+                if ( validator && validator->ProcessEvent(event) )
+                {
+                    return TRUE;
+                }
             }
         }
 
         // Search upwards through the inheritance hierarchy
             }
         }
 
         // Search upwards through the inheritance hierarchy
-        while (table)
+        while ( table )
         {
         {
-            if (SearchEventTable((wxEventTable&)*table, event))
+            if ( SearchEventTable((wxEventTable&)*table, event) )
                 return TRUE;
             table = table->baseTable;
         }
                 return TRUE;
             table = table->baseTable;
         }
@@ -366,23 +448,25 @@ bool wxEvtHandler::ProcessEvent(wxEvent& event)
     // Carry on up the parent-child hierarchy,
     // but only if event is a command event: it wouldn't
     // make sense for a parent to receive a child's size event, for example
     // Carry on up the parent-child hierarchy,
     // but only if event is a command event: it wouldn't
     // make sense for a parent to receive a child's size event, for example
-    if ( isWindow && event.IsKindOf(CLASSINFO(wxCommandEvent)) )
+    if ( m_isWindow && event.IsCommandEvent() )
     {
         wxWindow *win = (wxWindow *)this;
         wxWindow *parent = win->GetParent();
         if (parent && !parent->IsBeingDeleted())
     {
         wxWindow *win = (wxWindow *)this;
         wxWindow *parent = win->GetParent();
         if (parent && !parent->IsBeingDeleted())
-            return win->GetParent()->GetEventHandler()->ProcessEvent(event);
+            return parent->GetEventHandler()->ProcessEvent(event);
     }
 
     // Last try - application object.
     }
 
     // Last try - application object.
-    // Special case: don't pass wxEVT_IDLE to wxApp, since it'll always swallow
-    // it. wxEVT_IDLE is sent explicitly to wxApp so it will be processed
-    // appropriately via SearchEventTable.
-    if ( wxTheApp && (this != wxTheApp) && (event.GetEventType() != wxEVT_IDLE)
-       )
+    if ( wxTheApp && (this != wxTheApp) )
     {
     {
-        if ( wxTheApp->ProcessEvent(event) )
-            return TRUE;
+        // Special case: don't pass wxEVT_IDLE to wxApp, since it'll always
+        // swallow it. wxEVT_IDLE is sent explicitly to wxApp so it will be
+        // processed appropriately via SearchEventTable.
+        if ( event.GetEventType() != wxEVT_IDLE )
+        {
+            if ( wxTheApp->ProcessEvent(event) )
+                return TRUE;
+        }
     }
 
     return FALSE;
     }
 
     return FALSE;
@@ -395,7 +479,11 @@ bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
 
     // BC++ doesn't like while (table.entries[i].m_fn)
 
 
     // BC++ doesn't like while (table.entries[i].m_fn)
 
+#ifdef __SC__
+    while (table.entries[i].m_fn != 0)
+#else
     while (table.entries[i].m_fn != 0L)
     while (table.entries[i].m_fn != 0L)
+#endif
     {
         if ((event.GetEventType() == table.entries[i].m_eventType) &&
                 (table.entries[i].m_id == -1 || // Match, if event spec says any id will do (id == -1)
     {
         if ((event.GetEventType() == table.entries[i].m_eventType) &&
                 (table.entries[i].m_id == -1 || // Match, if event spec says any id will do (id == -1)
@@ -417,7 +505,6 @@ bool wxEvtHandler::SearchEventTable(wxEventTable& table, wxEvent& event)
     }
     return FALSE;
 }
     }
     return FALSE;
 }
-
 void wxEvtHandler::Connect( int id, int lastId,
                             wxEventType eventType,
                             wxObjectEventFunction func,
 void wxEvtHandler::Connect( int id, int lastId,
                             wxEventType eventType,
                             wxObjectEventFunction func,
@@ -438,7 +525,8 @@ void wxEvtHandler::Connect( int id, int lastId,
 
 bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event )
 {
 
 bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event )
 {
-    if (!m_dynamicEvents) return FALSE;
+    wxCHECK_MSG( m_dynamicEvents, FALSE,
+                 _T("caller should check that we have dynamic events") );
 
     int commandId = event.GetId();
 
 
     int commandId = event.GetId();
 
@@ -472,6 +560,7 @@ bool wxEvtHandler::SearchDynamicEventTable( wxEvent& event )
     return FALSE;
 };
 
     return FALSE;
 };
 
+#if WXWIN_COMPATIBILITY
 bool wxEvtHandler::OnClose()
 {
     if (GetNextHandler())
 bool wxEvtHandler::OnClose()
 {
     if (GetNextHandler())
@@ -479,3 +568,28 @@ bool wxEvtHandler::OnClose()
     else
         return FALSE;
 }
     else
         return FALSE;
 }
+#endif // WXWIN_COMPATIBILITY
+
+// Find a window with the focus, that is also a descendant of the given window.
+// This is used to determine the window to initially send commands to.
+wxWindow* wxFindFocusDescendant(wxWindow* ancestor)
+{
+    // Process events starting with the window with the focus, if any.
+    wxWindow* focusWin = wxWindow::FindFocus();
+    wxWindow* win = focusWin;
+
+    // Check if this is a descendant of this frame.
+    // If not, win will be set to NULL.
+    while (win)
+    {
+        if (win == ancestor)
+            break;
+        else
+            win = win->GetParent();
+    }
+    if (win == (wxWindow*) NULL)
+        focusWin = (wxWindow*) NULL;
+
+    return focusWin;
+}
+