diff --git a/src/client.c b/src/client.c
index 33f31ad87c642e0b851171189c67dbfad2714a7b..f385fe4a446671ceb20d85f878e492fe7edafdf6 100644
--- a/src/client.c
+++ b/src/client.c
@@ -2564,6 +2564,7 @@ void clientFrameAll()
     Client *new_focus;
     Window w1, w2, *wins = NULL;
     XWindowAttributes attr;
+    XEvent an_event;
 
     TRACE("entering clientFrameAll");
 
@@ -2586,6 +2587,10 @@ void clientFrameAll()
             clientFrame(wins[i], TRUE);
         }
     }
+    XSync(dpy, FALSE);
+    /* Just get rid of EnterNotify events caused by reparenting */
+    while(XCheckTypedEvent(dpy, EnterNotify, &an_event))
+        ;
     MyXUngrabServer();
     if(wins)
     {
@@ -2663,6 +2668,42 @@ Client *clientGetFromWindow(Window w, int mode)
     return NULL;
 }
 
+Client *clientAtPosition(int x, int y, Client * exclude)
+{
+    /* This function does the same as XQueryPointer but w/out the race
+       conditions caused by querying the X server
+     */
+    GSList *reverse = NULL;
+    GSList *windows_stack_copy = NULL;
+    GSList *list_of_windows = NULL;
+    GSList *index;
+    Client *c = NULL;
+    Client *c2 = NULL;
+    
+    TRACE("entering clientAtPos");
+    
+    windows_stack_copy = g_slist_copy(windows_stack);
+    list_of_windows = g_slist_reverse(windows_stack_copy);
+    for(index = list_of_windows; index; index = g_slist_next(index))
+    {
+        c2 = (Client *) index->data;
+        if (clientSelectMask(c2, 0) && (c2 != exclude))
+        {
+            if ((frameX(c2) < x) && (frameX(c2) + frameWidth(c2) > x) && (frameY(c2) < y) && (frameY(c2) + frameHeight(c2) > y))
+            {
+                c = c2;
+                break;
+            }
+        }
+    }
+    if(windows_stack_copy)
+    {
+        g_slist_free(windows_stack_copy);
+    }
+    
+    return c;
+}
+
 static inline gboolean clientSelectMask(Client * c, int mask)
 {
     gboolean okay = TRUE;
@@ -2757,7 +2798,9 @@ void clientPassFocus(Client * c)
     GSList *list_of_windows = NULL;
     Client *new_focus = NULL;
     Client *c2;
-    unsigned int i;
+    Window dr, window;
+    int rx, ry, wx, wy;
+    unsigned int i, mask;
 
     TRACE("entering clientPassFocus");
 
@@ -2766,16 +2809,23 @@ void clientPassFocus(Client * c)
         return;
     }
 
-    list_of_windows = clientListTransients(c);
-    for(c2 = c->next, i = 0; (c2) && (i < client_count); c2 = c2->next, i++)
+    if (params.click_to_focus)
     {
-        if (clientSelectMask(c2, 0) && !g_slist_find(list_of_windows, (gconstpointer) c2))
+        list_of_windows = clientListTransients(c);
+        for(c2 = c->next, i = 0; (c2) && (i < client_count); c2 = c2->next, i++)
         {
-            new_focus = c2;
-            break;
+            if (clientSelectMask(c2, 0) && !g_slist_find(list_of_windows, (gconstpointer) c2))
+            {
+                new_focus = c2;
+                break;
+            }
         }
+        g_slist_free(list_of_windows);
+    }
+    else if (XQueryPointer(dpy, root, &dr, &window, &rx, &ry, &wx, &wy, &mask))
+    {
+        new_focus = clientAtPosition(rx, ry, c);
     }
-    g_slist_free(list_of_windows);
     if (!new_focus)
     {
         new_focus = clientGetTopMostFocusable(c->win_layer, c);
diff --git a/src/client.h b/src/client.h
index 5edaebade1bfdb7fc412ad57d466b18746f8267d..9991ea5527281965bff80a99bf6ab4acfdf711d6 100644
--- a/src/client.h
+++ b/src/client.h
@@ -246,6 +246,7 @@ void clientUpdateAllFrames(gboolean);
 void clientGrabKeys(Client *);
 void clientUngrabKeys(Client *);
 Client *clientGetFromWindow(Window, int);
+Client *clientAtPosition(int, int, Client *);
 Client *clientGetNext(Client *, int);
 void clientPassFocus(Client *);
 void clientShow(Client *, gboolean);
diff --git a/src/workspaces.c b/src/workspaces.c
index f5f455b8bc775d8f9fd022c08d3b014e5b583fd0..4757e0bce1e9d9864583430604fe290498a39dca 100644
--- a/src/workspaces.c
+++ b/src/workspaces.c
@@ -36,10 +36,13 @@
 
 void workspaceSwitch(int new_ws, Client * c2)
 {
-    Client *c, *f = NULL;
+    Client *c, *new_focus = NULL;
     Client *previous;
     GSList *list_of_windows;
     GSList *index;
+    Window dr, window;
+    int rx, ry, wx, wy;
+    unsigned int mask;
     unsigned long data[1];
     XEvent an_event;
 
@@ -66,19 +69,6 @@ void workspaceSwitch(int new_ws, Client * c2)
     }
     
     previous = clientGetFocus();
-    if(previous)
-    {
-        CLIENT_FLAG_SET(previous, CLIENT_FLAG_FOCUS);
-        if(CLIENT_FLAG_TEST(previous, CLIENT_FLAG_STICKY) || (previous == c2))
-        {
-            f = previous;
-        }
-        else
-        {
-            clientSetFocus(c2, FALSE);
-        }
-    }
-
     list_of_windows = clientGetStackList();
     /* First pass */
     for(index = list_of_windows; index; index = g_slist_next(index))
@@ -86,6 +76,11 @@ void workspaceSwitch(int new_ws, Client * c2)
         c = (Client *) index->data;
         if(CLIENT_FLAG_TEST_AND_NOT(c, CLIENT_FLAG_VISIBLE, CLIENT_FLAG_STICKY) && !clientIsTransient(c) && ((c->win_workspace != new_ws)))
         {
+            if (c == previous)
+            {
+                CLIENT_FLAG_SET(previous, CLIENT_FLAG_FOCUS);
+                clientSetFocus(NULL, FALSE);
+            }
             clientHide(c, new_ws, FALSE);
         }
     }
@@ -98,18 +93,23 @@ void workspaceSwitch(int new_ws, Client * c2)
         if(CLIENT_FLAG_TEST(c, CLIENT_FLAG_STICKY | CLIENT_FLAG_VISIBLE))
         {
             clientSetWorkspace(c, new_ws, TRUE);
+            if(c == previous)
+            {
+                new_focus = c;
+            }
+            CLIENT_FLAG_UNSET(c, CLIENT_FLAG_FOCUS);
         }
-        else
+        else if((c->win_workspace == new_ws) && !CLIENT_FLAG_TEST(c, CLIENT_FLAG_HIDDEN))
         {
-            if((c->win_workspace == new_ws) && !clientIsTransient(c) && !CLIENT_FLAG_TEST(c, CLIENT_FLAG_HIDDEN))
+            if (!clientIsTransient(c))
             {
                 clientShow(c, FALSE);
-                if((!f) && CLIENT_FLAG_TEST(c, CLIENT_FLAG_FOCUS))
-                {
-                    f = c;
-                }
-                CLIENT_FLAG_UNSET(c, CLIENT_FLAG_FOCUS);
             }
+            if((!new_focus) && CLIENT_FLAG_TEST(c, CLIENT_FLAG_FOCUS))
+            {
+                new_focus = c;
+            }
+            CLIENT_FLAG_UNSET(c, CLIENT_FLAG_FOCUS);
         }
     }
     
@@ -123,14 +123,22 @@ void workspaceSwitch(int new_ws, Client * c2)
     data[0] = new_ws;
     XChangeProperty(dpy, root, net_current_desktop, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
     workspaceUpdateArea(margins, gnome_margins);
-    /* Just get rid of EnterNotify events when using focus follow mouse */
     XSync(dpy, FALSE);
-    if(!params.click_to_focus)
+    if(!(params.click_to_focus))
     {
+        /* Just get rid of EnterNotify events when using focus follow mouse */
         while(XCheckTypedEvent(dpy, EnterNotify, &an_event))
             ;
+        if (!(c2) && (XQueryPointer(dpy, root, &dr, &window, &rx, &ry, &wx, &wy, &mask)))
+        {
+            c = clientAtPosition(rx, ry, NULL);
+            if (c)
+            {
+                new_focus = c;
+            }
+        }
     }
-    clientSetFocus(f, TRUE);
+    clientSetFocus(new_focus, TRUE);
 }
 
 void workspaceSetCount(int count)