Index: /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp	(revision 3288)
+++ /trunk/src/VBox/Frontends/VBoxSDL/Framebuffer.cpp	(revision 3289)
@@ -387,8 +387,8 @@
 #ifdef __LINUX__
     /*
-     * SDL does not allow us to make this call from any other
-     * thread. So we have to send an event to the main SDL
-     * thread and process it there. For sake of simplicity, we encode
-     * all information in the event parameters.
+     * SDL does not allow us to make this call from any other thread than
+     * the main SDL thread (which initialized the video mode). So we have
+     * to send an event to the main SDL thread and process it there. For
+     * sake of simplicity, we encode all information in the event parameters.
      */
     SDL_Event event;
@@ -398,9 +398,5 @@
     event.user.data1 = (void*)(x << 16 | y);
     event.user.data2 = (void*)(w << 16 | h);
-    int rc = SDL_PushEvent(&event);
-    NOREF(rc);
-    AssertMsg(!rc, ("SDL_PushEvent returned SDL error '%s'\n", SDL_GetError()));
-    /* in order to not flood the SDL event queue, yield the CPU */
-    RTThreadYield();
+    PushNotifyUpdateEvent(&event);
 #else /* !__LINUX__ */
     update(x, y, w, h, true /* fGuestRelative */);
@@ -438,7 +434,7 @@
 
     /*
-     * SDL does not allow us to make this call from any other
-     * thread. So we have to send an event to the main SDL
-     * thread and tell VBox to wait.
+     * SDL does not allow us to make this call from any other thread than
+     * the main thread (the one which initialized the video mode). So we
+     * have to send an event to the main SDL thread and tell VBox to wait.
      */
     if (!finished)
@@ -447,16 +443,16 @@
         return E_FAIL;
     }
-    mGuestXRes = w;
-    mGuestYRes = h;
+    mGuestXRes   = w;
+    mGuestYRes   = h;
     mPixelFormat = pixelFormat;
-    mPtrVRAM = vram;
-    mLineSize = lineSize;
+    mPtrVRAM     = vram;
+    mLineSize    = lineSize;
 
     SDL_Event event;
     event.type       = SDL_USEREVENT;
     event.user.type  = SDL_USER_EVENT_RESIZE;
-    int rc = SDL_PushEvent(&event);
-    NOREF(rc);
-    AssertMsg(!rc, ("SDL_PushEvent returned SDL error '%s'\n", SDL_GetError()));
+
+    /* Try multiple times if necessary */
+    PushSDLEventForSure(&event);
 
     /* we want this request to be processed quickly, so yield the CPU */
Index: /trunk/src/VBox/Frontends/VBoxSDL/Helper.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/Helper.cpp	(revision 3288)
+++ /trunk/src/VBox/Frontends/VBoxSDL/Helper.cpp	(revision 3289)
@@ -24,4 +24,5 @@
 #include <VBox/err.h>
 #include <VBox/log.h>
+#include <iprt/asm.h>
 #include <iprt/assert.h>
 #include <iprt/thread.h>
@@ -39,5 +40,9 @@
 
 /** global flag indicating that the event queue thread should terminate */
-bool volatile   g_fTerminateXPCOMQueueThread = false;
+static bool volatile   g_fTerminateXPCOMQueueThread = false;
+
+/** How many XPCOM user events are on air. Only allow one pending event to prevent
+ * an overflow of the SDL event queue. */
+static volatile int32_t g_s32XPCOMEventsPending;
 
 /** Semaphore the XPCOM event thread will sleep on while it waits for the main thread to process pending requests. */
@@ -72,26 +77,43 @@
         if ((n > 0) && !g_fTerminateXPCOMQueueThread)
         {
-            /*
-             * Post the event and wait for it to be processed. If we don't wait,
-             * we'll flood the queue on SMP systems and when the main thread is busy.
-             * In the event of a push error, we'll yield the timeslice and retry.
+	    /*
+	     * Wait until all XPCOM events are processed. 1s just for sanity.
              */
-            SDL_Event event = {0};
-            event.type = SDL_USEREVENT;
-            event.user.type = SDL_USER_EVENT_XPCOM_EVENTQUEUE;
-            rc = SDL_PushEvent(&event);
-            if (!rc)
-            {
-                RTSemEventWait(g_EventSemXPCOMQueueThread, 100);
-                cErrors = 0;
+	    int iWait = 1000;
+	    /*
+	     * Don't post an event if there is a pending XPCOM event to prevent an
+	     * overflow of the SDL event queue.
+	     */
+	    if (g_s32XPCOMEventsPending < 1)
+	    {
+                /*
+		 * Post the event and wait for it to be processed. If we don't wait,
+		 * we'll flood the queue on SMP systems and when the main thread is busy.
+		 * In the event of a push error, we'll yield the timeslice and retry.
+		 */
+                SDL_Event event = {0};
+                event.type = SDL_USEREVENT;
+                event.user.type = SDL_USER_EVENT_XPCOM_EVENTQUEUE;
+                rc = SDL_PushEvent(&event);
+                if (!rc)
+                {
+                    /* success */
+                    ASMAtomicIncS32(&g_s32XPCOMEventsPending);
+                    cErrors = 0;
+                }
+                else
+                {
+                    /* failure */
+                    cErrors++;
+                    if (!RTThreadYield())
+                        RTThreadSleep(2);
+                    iWait = (cErrors >= 10) ? RT_MIN(cErrors - 8, 50) : 0;
+                }
             }
             else
-            {
-                cErrors++;
-                if (!RTThreadYield())
-                    RTThreadSleep(2);
-                if (cErrors >= 10)
-                    RTSemEventWait(g_EventSemXPCOMQueueThread, RT_MIN(cErrors - 8, 50));
-            }
+                Log2(("not enqueueing SDL XPCOM event (%d)\n", g_s32XPCOMEventsPending));
+
+            if (iWait)
+                RTSemEventWait(g_EventSemXPCOMQueueThread, iWait);
         }
     } while (!g_fTerminateXPCOMQueueThread);
@@ -115,4 +137,12 @@
     AssertRC(rc);
     return rc;
+}
+
+/*
+ * Notify the XPCOM tread that we consumed an XPCOM event.
+ */
+void consumedXPCOMUserEvent(void)
+{
+    ASMAtomicDecS32(&g_s32XPCOMEventsPending);
 }
 
@@ -139,6 +169,3 @@
 }
 
-
-
 #endif /* USE_XPCOM_QUEUE_THREAD */
-
Index: /trunk/src/VBox/Frontends/VBoxSDL/Helper.h
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/Helper.h	(revision 3288)
+++ /trunk/src/VBox/Frontends/VBoxSDL/Helper.h	(revision 3289)
@@ -37,4 +37,9 @@
 int startXPCOMEventQueueThread(int eqFD);
 
+/*
+ * Notify the XPCOM thread that we consumed an XPCOM event
+ */
+void consumedXPCOMUserEvent(void);
+
 /**
  * Signal to the XPCOM even queue thread that it should select for more events.
Index: /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 3288)
+++ /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.cpp	(revision 3289)
@@ -140,4 +140,5 @@
 static Uint32  StartupTimer(Uint32 interval, void *param);
 static Uint32  ResizeTimer(Uint32 interval, void *param);
+static int     WaitSDLEvent(SDL_Event *event);
 
 
@@ -203,4 +204,7 @@
 #endif
 
+static RTSEMEVENT g_EventSemSDLEvents;
+static volatile int32_t g_cNotifyUpdateEventsPending;
+
 /**
  * Callback handler for VirtualBox events
@@ -297,7 +301,5 @@
                     event.type       = SDL_USEREVENT;
                     event.user.type  = SDL_USER_EVENT_SECURELABEL_UPDATE;
-                    int rc = SDL_PushEvent(&event);
-                    NOREF(rc);
-                    AssertMsg(!rc, ("SDL_PushEvent returned with SDL error '%s'\n", SDL_GetError()));
+                    PushSDLEventForSure(&event);
                 }
             }
@@ -414,6 +416,5 @@
         event.user.data1 = data;
 
-        int rc = SDL_PushEvent (&event);
-        AssertMsg(!rc, ("SDL_PushEvent returned with SDL error '%s'\n", SDL_GetError()));
+        int rc = PushSDLEventForSure (&event);
         if (rc)
             delete data;
@@ -432,7 +433,5 @@
         event.user.type = SDL_USER_EVENT_GUEST_CAP_CHANGED;
 
-        int rc = SDL_PushEvent (&event);
-        NOREF(rc);
-        AssertMsg(!rc, ("SDL_PushEvent returned with SDL error '%s'\n", SDL_GetError()));
+        PushSDLEventForSure (&event);
         return S_OK;
     }
@@ -465,7 +464,5 @@
         }
 
-        int rc = SDL_PushEvent(&event);
-        NOREF(rc);
-        AssertMsg(!rc, ("SDL_PushEvent returned with SDL error '%s'\n", SDL_GetError()));
+        PushSDLEventForSure(&event);
         return S_OK;
     }
@@ -1290,4 +1287,8 @@
     }
 
+    /* create SDL event semaphore */
+    rc = RTSemEventCreate(&g_EventSemSDLEvents);
+    AssertReleaseRC(rc);
+
     rc = virtualBox->OpenSession(session, uuid);
     if (FAILED(rc))
@@ -1880,5 +1881,5 @@
              * Wait for SDL events.
              */
-            if (SDL_WaitEvent(&event))
+            if (WaitSDLEvent(&event))
             {
                 switch (event.type)
@@ -1915,4 +1916,5 @@
                     {
                         LogFlow(("SDL_USER_EVENT_XPCOM_EVENTQUEUE: processing XPCOM event queue...\n"));
+                        consumedXPCOMUserEvent();
                         eventQ->ProcessPendingEvents();
                         signalXPCOMEventQueueThread();
@@ -2004,5 +2006,5 @@
 #endif
     LogFlow(("VBoxSDL: Entering big event loop\n"));
-    while (SDL_WaitEvent(&event))
+    while (WaitSDLEvent(&event))
     {
         switch (event.type)
@@ -2254,4 +2256,5 @@
                  * Decode event parameters.
                  */
+                ASMAtomicDecS32(&g_cNotifyUpdateEventsPending);
                 #define DECODEX(event) ((intptr_t)(event).user.data1 >> 16)
                 #define DECODEY(event) ((intptr_t)(event).user.data1 & 0xFFFF)
@@ -2678,10 +2681,10 @@
         case SDLK_CLEAR:            return 0x;
         case SDLK_KP_EQUALS:        return 0x;
-        case SDLK_COMPOSE:	    return 0x;
+        case SDLK_COMPOSE:          return 0x;
         case SDLK_HELP:             return 0x;
         case SDLK_BREAK:            return 0x;
-        case SDLK_POWER:	    return 0x;
-        case SDLK_EURO:		    return 0x;
-        case SDLK_UNDO:		    return 0x;
+        case SDLK_POWER:            return 0x;
+        case SDLK_EURO:             return 0x;
+        case SDLK_UNDO:             return 0x;
 #endif
         default:
@@ -3537,5 +3540,5 @@
          */
         SDL_Event event;
-        if (SDL_WaitEvent(&event))
+        if (WaitSDLEvent(&event))
         {
             switch (event.type)
@@ -4272,4 +4275,5 @@
     event.user.type = SDL_USER_EVENT_TIMER;
     SDL_PushEvent(&event);
+    RTSemEventSignal(g_EventSemSDLEvents);
     return interval;
 }
@@ -4284,6 +4288,70 @@
     event.type      = SDL_USEREVENT;
     event.user.type = SDL_USER_EVENT_WINDOW_RESIZE_DONE;
-    SDL_PushEvent(&event);
+    PushSDLEventForSure(&event);
     /* one-shot */
     return 0;
 }
+
+/**
+ * Wait for the next SDL event. Don't use SDL_WaitEvent since this function
+ * calls SDL_Delay(10) if the event queue is empty.
+ */
+static int WaitSDLEvent(SDL_Event *event)
+{
+    for (;;)
+    {
+        int rc = SDL_PollEvent (event);
+        if (rc == 1)
+            return 1;
+        /* Immediately wake up if new SDL events are available. This does not
+         * work for internal SDL events. Don't wait more than 10ms. */
+        RTSemEventWait(g_EventSemSDLEvents, 10);
+    }
+}
+
+/**
+ * Ensure that an SDL event is really enqueued. Try multiple times if necessary.
+ */
+int PushSDLEventForSure(SDL_Event *event)
+{
+    int ntries = 10;
+    for (; ntries > 0; ntries--)
+    {
+        int rc = SDL_PushEvent(event);
+        RTSemEventSignal(g_EventSemSDLEvents);
+        if (rc == 0)
+            return 0;
+        Log(("PushSDLEventForSure: waiting for 2ms\n"));
+        RTThreadSleep(2);
+    }
+    LogRel(("WARNING: Failed to enqueue SDL event %d.%d!\n",
+           event->type, event->type == SDL_USEREVENT ? event->user.type : 0));
+    return -1;
+}
+
+#ifdef __LINUX__
+/**
+ * Special SDL_PushEvent function for NotifyUpdate events. These events may occur in bursts
+ * so make sure they don't flood the SDL event queue.
+ */
+void PushNotifyUpdateEvent(SDL_Event *event)
+{
+    int rc = SDL_PushEvent(event);
+    RTSemEventSignal(g_EventSemSDLEvents);
+    AssertMsg(!rc, ("SDL_PushEvent returned SDL error\n"));
+    /* A global counter is faster than SDL_PeepEvents() */
+    if (!rc)
+        ASMAtomicIncS32(&g_cNotifyUpdateEventsPending);
+    /* In order to not flood the SDL event queue, yield the CPU or (if there are already many
+     * events queued) even sleep */
+    if (g_cNotifyUpdateEventsPending > 96)
+    {
+        /* Too many NotifyUpdate events, sleep for a small amount to give the main thread time
+         * to handle these events. The SDL queue can hold up to 128 events. */
+        Log(("PushNotifyUpdateEvent: Sleep 1ms\n"));
+        RTThreadSleep(1);
+    }
+    else
+        RTThreadYield();
+}
+#endif /* __LINUX__ */
Index: /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.h
===================================================================
--- /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.h	(revision 3288)
+++ /trunk/src/VBox/Frontends/VBoxSDL/VBoxSDL.h	(revision 3289)
@@ -72,3 +72,8 @@
 #endif /* VBOX_WIN32_UI */
 
+#ifdef __LINUX__
+void PushNotifyUpdateEvent(SDL_Event *event);
+#endif
+int  PushSDLEventForSure(SDL_Event *event);
+
 #endif // __H_VBOXSDL
