diff --git a/inc/dd.h b/inc/dd.h
index 564567a..d024439 100644
--- a/inc/dd.h
+++ b/inc/dd.h
@@ -107,8 +107,8 @@ typedef struct CNCDDRAW
     char shader[MAX_PATH];
     BOOL wine;
     BOOL altenter;
-    BOOL hidecursor;
     HCURSOR old_cursor;
+    int show_cursor_count;
     BOOL accurate_timers;
     BOOL resizable;
     BOOL nonexclusive;
diff --git a/src/config.c b/src/config.c
index 3660ea9..1513dcd 100644
--- a/src/config.c
+++ b/src/config.c
@@ -40,7 +40,7 @@ void cfg_load()
     g_ddraw->border = cfg_get_bool("border", TRUE);
     g_ddraw->boxing = cfg_get_bool("boxing", FALSE);
     g_ddraw->maintas = cfg_get_bool("maintas", FALSE);
-    g_ddraw->adjmouse = cfg_get_bool("adjmouse", TRUE);
+    g_ddraw->adjmouse = cfg_get_bool("adjmouse", TRUE) || !cfg_get_bool("handlemouse", TRUE);
     g_ddraw->devmode = cfg_get_bool("devmode", FALSE);
     g_ddraw->vsync = cfg_get_bool("vsync", FALSE);
     g_ddraw->noactivateapp = cfg_get_bool("noactivateapp", FALSE);
diff --git a/src/dd.c b/src/dd.c
index 4ece9b5..4826bd9 100644
--- a/src/dd.c
+++ b/src/dd.c
@@ -819,13 +819,15 @@ HRESULT dd_SetCooperativeLevel(HWND hwnd, DWORD dwFlags)
             SetPixelFormat(g_ddraw->render.hdc, ChoosePixelFormat(g_ddraw->render.hdc, &pfd), &pfd);
         }
 
+        int cursor_count = real_ShowCursor(TRUE) - 1;
+        InterlockedExchange(&g_ddraw->show_cursor_count, cursor_count);
+        real_ShowCursor(FALSE);
+
         /* Make sure the cursor is visible in windowed mode initially */
-        if (g_ddraw->windowed)
+        if (g_ddraw->windowed && !g_ddraw->fullscreen)
         {
-            CURSORINFO ci = { .cbSize = sizeof(CURSORINFO) };
-            if (real_GetCursorInfo(&ci) && ci.flags == 0)
+            if (cursor_count < 0)
             {
-                g_ddraw->hidecursor = TRUE;
                 while (real_ShowCursor(TRUE) < 0);
             }
 
diff --git a/src/directinput.c b/src/directinput.c
index 01547a3..5733e0e 100644
--- a/src/directinput.c
+++ b/src/directinput.c
@@ -97,9 +97,14 @@ static HRESULT WINAPI fake_di_CreateDevice(
 
     if (SUCCEEDED(result) && !real_did_SetCooperativeLevel)
     {
-        if (rguid && IsEqualGUID(&GUID_SysMouse, rguid))
+        if (rguid && IsEqualGUID(&GUID_SysMouse, rguid) && g_ddraw)
         {
-            while (real_ShowCursor(FALSE) >= 0);
+            if (g_ddraw->locked || g_ddraw->devmode)
+            {
+                while (real_ShowCursor(FALSE) >= 0);
+            }
+
+            InterlockedExchange(&g_ddraw->show_cursor_count, -1);
         }
 
         real_did_SetCooperativeLevel =
diff --git a/src/mouse.c b/src/mouse.c
index 6fc82ea..e7c26ee 100644
--- a/src/mouse.c
+++ b/src/mouse.c
@@ -55,10 +55,19 @@ void mouse_lock()
 
         real_SetCursor(g_ddraw->old_cursor);
 
-        if (g_ddraw->hidecursor)
+        int cur_count = real_ShowCursor(TRUE) - 1;
+        real_ShowCursor(FALSE);
+
+        int game_count = InterlockedExchangeAdd(&g_ddraw->show_cursor_count, 0);
+
+        if (cur_count > game_count)
         {
-            g_ddraw->hidecursor = FALSE;
-            real_ShowCursor(FALSE);
+            while (real_ShowCursor(FALSE) > game_count);
+        }
+
+        if (cur_count < game_count)
+        {
+            while (real_ShowCursor(TRUE) < game_count);
         }
 
         real_ClipCursor(&rc);
@@ -96,7 +105,6 @@ void mouse_unlock()
         CURSORINFO ci = { .cbSize = sizeof(CURSORINFO) };
         if (real_GetCursorInfo(&ci) && ci.flags == 0)
         {
-            g_ddraw->hidecursor = TRUE;
             while (real_ShowCursor(TRUE) < 0);
         }
 
diff --git a/src/winapi_hooks.c b/src/winapi_hooks.c
index 15fc67c..d15f611 100644
--- a/src/winapi_hooks.c
+++ b/src/winapi_hooks.c
@@ -114,21 +114,34 @@ BOOL WINAPI fake_ClipCursor(const RECT* lpRect)
 
 int WINAPI fake_ShowCursor(BOOL bShow)
 {
-    static int count;
+    if (g_ddraw)
+    {
+        if (g_ddraw->locked || g_ddraw->devmode)
+        {
+            int count = real_ShowCursor(bShow);
+            InterlockedExchange(&g_ddraw->show_cursor_count, count);
+            return count;
+        }
+        else
+        {
+            return bShow ?
+                InterlockedIncrement(&g_ddraw->show_cursor_count) :
+                InterlockedDecrement(&g_ddraw->show_cursor_count);
+        }
+    }
 
-    //if (g_ddraw)
-        return real_ShowCursor(bShow);
-
-    return bShow ? ++count : --count;
+    return real_ShowCursor(bShow);
 }
 
 HCURSOR WINAPI fake_SetCursor(HCURSOR hCursor)
 {
     if (g_ddraw)
+    {
         g_ddraw->old_cursor = hCursor;
 
-    if (g_ddraw && (g_ddraw->locked || g_ddraw->devmode))
-        return real_SetCursor(hCursor);
+        if (g_ddraw->locked || g_ddraw->devmode)
+            return real_SetCursor(hCursor);
+    }
 
     return NULL;
 }
@@ -206,10 +219,16 @@ BOOL WINAPI fake_SetCursorPos(int X, int Y)
 
     POINT pt = { X, Y };
 
-    if (g_ddraw && g_ddraw->adjmouse)
+    if (g_ddraw)
     {
-        pt.x = (LONG)(pt.x * g_ddraw->render.scale_w);
-        pt.y = (LONG)(pt.y * g_ddraw->render.scale_h);
+        if (g_ddraw->adjmouse)
+        {
+            pt.x = (LONG)(pt.x * g_ddraw->render.scale_w);
+            pt.y = (LONG)(pt.y * g_ddraw->render.scale_h);
+        }
+
+        pt.x += g_ddraw->render.viewport.x;
+        pt.y += g_ddraw->render.viewport.y;
     }
 
     return g_ddraw && real_ClientToScreen(g_ddraw->hwnd, &pt) && real_SetCursorPos(pt.x, pt.y);
diff --git a/src/wndproc.c b/src/wndproc.c
index 902b96d..779f6aa 100644
--- a/src/wndproc.c
+++ b/src/wndproc.c
@@ -737,8 +737,6 @@ LRESULT CALLBACK fake_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam
                 g_ddraw->cursor.x = (DWORD)((x - g_ddraw->render.viewport.x) * g_ddraw->render.unscale_w);
                 g_ddraw->cursor.y = (DWORD)((y - g_ddraw->render.viewport.y) * g_ddraw->render.unscale_h);
 
-                g_ddraw->hidecursor = FALSE;
-
                 mouse_lock();
             }
             break;