diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index e0eeb08..59fdf25 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian.cpp
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -59,7 +59,6 @@ QT_BEGIN_NAMESPACE
 
 #define WAKE_UP_PRIORITY CActive::EPriorityStandard
 #define TIMER_PRIORITY CActive::EPriorityHigh
-#define NULLTIMER_PRIORITY CActive::EPriorityLow
 #define COMPLETE_DEFERRED_ACTIVE_OBJECTS_PRIORITY CActive::EPriorityIdle
 
 static inline int qt_pipe_write(int socket, const char *data, qint64 len)
@@ -124,16 +123,8 @@ private:
 };
 
 /*
- * This class is designed to aid in implementing event handling in a more round robin fashion. We
- * cannot change active objects that we do not own, but the active objects that Qt owns will use
- * this as a base class with convenience functions.
- *
- * Here is how it works: On every RunL, the deriving class should call maybeQueueForLater().
- * This will return whether the active object has been queued, or whether it should run immediately.
- * Queued objects will run again after other events have been processed.
- *
- * The QCompleteDeferredAOs class is a special object that runs after all others, which will
- * reactivate the objects that were previously not run.
+ * This class can be used as a base class for Qt active objects, but currently does not offer
+ * any special functionality.
  */
 QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher)
     : CActive(priority),
@@ -146,25 +137,11 @@ QActiveObject::QActiveObject(TInt priority, QEventDispatcherSymbian *dispatcher)
 
 QActiveObject::~QActiveObject()
 {
-    if (m_hasRunAgain)
-        m_dispatcher->removeDeferredActiveObject(this);
 }
 
 bool QActiveObject::maybeQueueForLater()
 {
-    Q_ASSERT(!m_hasRunAgain);
-
-    if (!m_hasAlreadyRun || m_dispatcher->iterationCount() != m_iterationCount) {
-        // First occurrence of this event in this iteration.
-        m_hasAlreadyRun = true;
-        m_iterationCount = m_dispatcher->iterationCount();
-        return false;
-    } else {
-        // The event has already occurred.
-        m_dispatcher->addDeferredActiveObject(this);
-        m_hasRunAgain = true;
-        return true;
-    }
+    return false;
 }
 
 bool QActiveObject::maybeDeferSocketEvent()
@@ -233,7 +210,7 @@ void QWakeUpActiveObject::RunL()
 }
 
 QTimerActiveObject::QTimerActiveObject(QEventDispatcherSymbian *dispatcher, SymbianTimerInfo *timerInfo)
-    : QActiveObject((timerInfo->interval) ? TIMER_PRIORITY : NULLTIMER_PRIORITY , dispatcher),
+    : QActiveObject(TIMER_PRIORITY, dispatcher),
       m_timerInfo(timerInfo), m_expectedTimeSinceLastEvent(0)
 {
     // start the timeout timer to ensure initialisation
@@ -708,6 +685,123 @@ void QSocketActiveObject::deleteLater()
     }
 }
 
+/* Round robin active object scheduling for Qt apps.
+ *
+ * Qt and Symbian have different views on how events should be handled. Qt expects
+ * round-robin event processing, whereas Symbian implements a strict priority based
+ * system.
+ *
+ * This scheduler class, and its use in QEventDispatcherSymbian::processEvents,
+ * introduces round robin scheduling for high priority active objects, but leaves
+ * those with low priorities scheduled in priority order.
+ * The algorithm used is that, during each call to processEvents, any pre-existing
+ * runnable active object may run, but only once. Active objects with priority
+ * lower than EPriorityStandard can only run if no higher priority active object
+ * has run.
+ * This is done by implementing an alternative scheduling algorithm which requires
+ * access to the internal members of the active object system. The iSpare member of
+ * CActive is replaced with a flag indicating that the object is new (CBase zero
+ * initialization sets this), or not run, or ran. Only active objects with the
+ * not run flag are allowed to run.
+ */
+class QtRRActiveScheduler
+{
+public:
+    static void MarkReadyToRun();
+    enum RunResult {
+        NothingFound,
+        ObjectRun,
+        ObjectDelayed
+    };
+    static RunResult RunMarkedIfReady(TInt &runPriority, TInt minimumPriority);
+
+private:
+    // active scheduler access kit, for gaining access to the internals of active objects for
+    // alternative active scheduler implementations.
+    class TRequestStatusAccess
+        {
+    public:
+        enum { ERequestActiveFlags = 3 };  // TRequestStatus::EActive | TRequestStatus::ERequestPending
+        TInt iStatus;
+        TUint iFlags;
+        };
+
+    class CActiveDataAccess : public CBase
+    {
+    public:
+        TRequestStatusAccess iStatus;
+        TPriQueLink iLink;
+        enum TMarks
+        {
+            ENewObject,     // CBase zero initialization sets this, new objects cannot be run in the processEvents in which they are created
+            ENotRun,        // This object has not yet run in the current processEvents call
+            ERan            // This object has run in the current processEvents call
+        };
+        int iMark;      //TAny* iSpare;
+    };
+
+    class CActiveFuncAccess : public CActive
+    {
+    public:
+        // these functions are needed in RunMarkedIfReady
+        using CActive::RunL;
+        using CActive::RunError;
+    };
+
+    class CActiveSchedulerAccess : public CBase
+    {
+    public:
+        struct TLoop;
+        TLoop* iStack;
+        TPriQue<CActiveFuncAccess> iActiveQ;
+        TAny* iSpare;
+    };
+};
+
+void QtRRActiveScheduler::MarkReadyToRun()
+{
+    CActiveScheduler *pS=CActiveScheduler::Current();
+    if (pS!=NULL)
+    {
+        TDblQueIter<CActive> iterator(((CActiveSchedulerAccess*)pS)->iActiveQ);
+        for (CActive* active=iterator++; active!=NULL; active=iterator++) {
+            ((CActiveDataAccess*)active)->iMark = CActiveDataAccess::ENotRun;
+        }
+    }
+}
+
+QtRRActiveScheduler::RunResult QtRRActiveScheduler::RunMarkedIfReady(TInt &runPriority, TInt minimumPriority)
+{
+    RunResult result = NothingFound;
+    TInt error=KErrNone;
+    CActiveScheduler *pS=CActiveScheduler::Current();
+    if (pS!=NULL) {
+        TDblQueIter<CActiveFuncAccess> iterator(((CActiveSchedulerAccess*)pS)->iActiveQ);
+        for (CActiveFuncAccess *active=iterator++; active!=NULL; active=iterator++) {
+            CActiveDataAccess *dataAccess = (CActiveDataAccess*)active;
+            if (active->IsActive() && (active->iStatus!=KRequestPending)) {
+                int& mark = dataAccess->iMark;
+                if (mark == CActiveDataAccess::ENotRun && active->Priority()>=minimumPriority) {
+                    mark = CActiveDataAccess::ERan;
+                    runPriority = active->Priority();
+                    dataAccess->iStatus.iFlags&=~TRequestStatusAccess::ERequestActiveFlags;
+                    int vptr = *(int*)active;       // vptr can be used to identify type when debugging leaves
+                    TRAP(error, active->RunL());
+                    if (error!=KErrNone)
+                        error=active->RunError(error);
+                    if (error) {
+                        qWarning("Active object (ptr=0x%08x, vptr=0x%08x) leave: %i\n", active, vptr, error);
+                        pS->Error(error);
+                    }
+                    return ObjectRun;
+                }
+                result = ObjectDelayed;
+            }
+        }
+    }
+    return result;
+}
+
 #ifdef QT_SYMBIAN_PRIORITY_DROP
 class QIdleDetectorThread
 {
@@ -864,6 +958,7 @@ void QEventDispatcherSymbian::closingDown()
 
 bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags flags )
 {
+    const bool useRRScheduler = true;
     bool handledAnyEvent = false;
     bool oldNoSocketEventsValue = m_noSocketEvents;
     bool oldInsideTimerEventValue = m_insideTimerEvent;
@@ -894,8 +989,9 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
             handledAnyEvent = sendDeferredSocketEvents();
         }
 
-        bool handledSymbianEvent = false;
+        QtRRActiveScheduler::RunResult handledSymbianEvent = QtRRActiveScheduler::NothingFound;
         m_interrupt = false;
+        int minPriority = KMinTInt;
 
 #ifdef QT_SYMBIAN_PRIORITY_DROP
         QElapsedTimer eventTimer;
@@ -921,6 +1017,10 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
                 CActiveScheduler::Current()->WaitForAnyRequest();
             }
 
+            if (useRRScheduler && handledSymbianEvent == QtRRActiveScheduler::NothingFound) {
+                QtRRActiveScheduler::MarkReadyToRun();
+            }
+
 #ifdef QT_SYMBIAN_PRIORITY_DROP
             if (idleDetectorThread()->hasRun()) {
                 if (m_delay > baseDelay)
@@ -936,11 +1036,31 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
             eventTimer.start();
 #endif
 
-            TInt error;
-            handledSymbianEvent = CActiveScheduler::RunIfReady(error, KMinTInt);
-            if (error) {
-                qWarning("CActiveScheduler::RunIfReady() returned error: %i\n", error);
-                CActiveScheduler::Current()->Error(error);
+            if (useRRScheduler) {
+                // Standard or above priority AOs are scheduled round robin.
+                // Lower priority AOs can only run if nothing higher priority has run.
+                int runPriority = minPriority;
+                handledSymbianEvent = QtRRActiveScheduler::RunMarkedIfReady(runPriority, minPriority);
+                minPriority = qMin(runPriority, int(CActive::EPriorityStandard));
+            } else {
+                TInt error;
+                handledSymbianEvent =
+                      CActiveScheduler::RunIfReady(error, minPriority)
+                    ? QtRRActiveScheduler::ObjectRun
+                    : QtRRActiveScheduler::NothingFound;
+                if (error) {
+                    qWarning("CActiveScheduler::RunIfReady() returned error: %i\n", error);
+                    CActiveScheduler::Current()->Error(error);
+                }
+            }
+
+            if (handledSymbianEvent == QtRRActiveScheduler::NothingFound) {
+                // no runnable or delayed active object was found, the signal that caused us to get here must be bad
+                qFatal("QEventDispatcherSymbian::processEvents(): Caught Symbian stray signal");
+            } else if (handledSymbianEvent == QtRRActiveScheduler::ObjectDelayed) {
+                // signal the thread to compensate for the un-handled signal absorbed
+                RThread().RequestSignal();
+                break;
             }
 
 #ifdef QT_SYMBIAN_PRIORITY_DROP
@@ -949,10 +1069,8 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
             m_avgEventTime = (m_avgEventTime * 95 + eventDur * 5) / 100;
 #endif
 
-            if (!handledSymbianEvent) {
-                qFatal("QEventDispatcherSymbian::processEvents(): Caught Symbian stray signal");
-            }
             handledAnyEvent = true;
+
             if (m_interrupt) {
                 break;
             }
diff --git a/src/gui/kernel/qeventdispatcher_s60.cpp b/src/gui/kernel/qeventdispatcher_s60.cpp
index 2d92c89..a05b24e 100644
--- a/src/gui/kernel/qeventdispatcher_s60.cpp
+++ b/src/gui/kernel/qeventdispatcher_s60.cpp
@@ -58,47 +58,17 @@ QtEikonEnv::~QtEikonEnv()
 
 void QtEikonEnv::RunL()
 {
-    QEventDispatcherS60 *dispatcher = qobject_cast<QEventDispatcherS60 *>(QAbstractEventDispatcher::instance());
-    if (!dispatcher) {
-        CEikonEnv::RunL();
-        return;
-    }
-
-    if (m_lastIterationCount != dispatcher->iterationCount()) {
-        m_hasAlreadyRun = false;
-        m_lastIterationCount = dispatcher->iterationCount();
-    }
-
-    if (m_hasAlreadyRun) {
-        // Fool the active scheduler into believing we are still waiting for events.
-        // The window server thinks we are not, however.
-        m_savedStatusCode = iStatus.Int();
-        iStatus = KRequestPending;
-        SetActive();
-        dispatcher->queueDeferredActiveObjectsCompletion();
-    } else {
-        m_hasAlreadyRun = true;
-        CEikonEnv::RunL();
-    }
+    CEikonEnv::RunL();
+    return;
 }
 
 void QtEikonEnv::DoCancel()
 {
-    complete();
-
     CEikonEnv::DoCancel();
 }
 
 void QtEikonEnv::complete()
 {
-    if (m_hasAlreadyRun) {
-        if (m_savedStatusCode != KRequestPending) {
-            TRequestStatus *status = &iStatus;
-            QEventDispatcherSymbian::RequestComplete(status, m_savedStatusCode);
-            m_savedStatusCode = KRequestPending;
-        }
-        m_hasAlreadyRun = false;
-    }
 }
 
 QEventDispatcherS60::QEventDispatcherS60(QObject *parent)
