mirror of
				https://github.com/glfw/glfw.git
				synced 2025-11-04 06:15:07 +00:00 
			
		
		
		
	Win 32: Fix disabled cursor mode when connected over RDP
Fixes #1276 Based on PR #1279 by @Pokechu22 Co-authored-by: Pokechu22 <8334194+Pokechu22@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									8e6c8d7eff
								
							
						
					
					
						commit
						c8521b7fda
					
				@ -279,6 +279,8 @@ video tutorials.
 | 
				
			|||||||
 - Jonas Ådahl
 | 
					 - Jonas Ådahl
 | 
				
			||||||
 - Lasse Öörni
 | 
					 - Lasse Öörni
 | 
				
			||||||
 - Leonard König
 | 
					 - Leonard König
 | 
				
			||||||
 | 
					 - Pokechu22
 | 
				
			||||||
 | 
					 - Guillaume Lebrun
 | 
				
			||||||
 - All the unmentioned and anonymous contributors in the GLFW community, for bug
 | 
					 - All the unmentioned and anonymous contributors in the GLFW community, for bug
 | 
				
			||||||
   reports, patches, feedback, testing and encouragement
 | 
					   reports, patches, feedback, testing and encouragement
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -236,6 +236,7 @@ information on what to include when reporting a bug.
 | 
				
			|||||||
 - [Win32] Bugfix: `glfwWaitEventsTimeout` did not return for some sent messages (#2408)
 | 
					 - [Win32] Bugfix: `glfwWaitEventsTimeout` did not return for some sent messages (#2408)
 | 
				
			||||||
 - [Win32] Bugfix: Fix pkg-config for dynamic library on Windows (#2386, #2420)
 | 
					 - [Win32] Bugfix: Fix pkg-config for dynamic library on Windows (#2386, #2420)
 | 
				
			||||||
 - [Win32] Bugfix: XInput could reportedly provide invalid DPad bit masks (#2291)
 | 
					 - [Win32] Bugfix: XInput could reportedly provide invalid DPad bit masks (#2291)
 | 
				
			||||||
 | 
					 - [Win32] Bugfix: Disabled cursor mode doesn't work right when connected over RDP (#1276)
 | 
				
			||||||
 - [Win32] Bugfix: Rapid clipboard calls could fail due to Clipboard History
 | 
					 - [Win32] Bugfix: Rapid clipboard calls could fail due to Clipboard History
 | 
				
			||||||
 - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619)
 | 
					 - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619)
 | 
				
			||||||
 - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle
 | 
					 - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle
 | 
				
			||||||
 | 
				
			|||||||
@ -430,6 +430,47 @@ static GLFWbool createHelperWindow(void)
 | 
				
			|||||||
   return GLFW_TRUE;
 | 
					   return GLFW_TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Creates the blank cursor
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					static void createBlankCursor(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // HACK: Create a transparent cursor as using the NULL cursor breaks
 | 
				
			||||||
 | 
					    //       using SetCursorPos when connected over RDP
 | 
				
			||||||
 | 
					    int cursorWidth = GetSystemMetrics(SM_CXCURSOR);
 | 
				
			||||||
 | 
					    int cursorHeight = GetSystemMetrics(SM_CYCURSOR);
 | 
				
			||||||
 | 
					    unsigned char* andMask = calloc(cursorWidth * cursorHeight / 8, sizeof(unsigned char));
 | 
				
			||||||
 | 
					    unsigned char* xorMask = calloc(cursorWidth * cursorHeight / 8, sizeof(unsigned char));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (andMask != NULL && xorMask != NULL) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        memset(andMask, 0xFF, (size_t)(cursorWidth * cursorHeight / 8));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Cursor creation might fail, but that's fine as we get NULL in that case,
 | 
				
			||||||
 | 
					        // which serves as an acceptable fallback blank cursor (other than on RDP)
 | 
				
			||||||
 | 
					        _glfw.win32.blankCursor = CreateCursor(NULL, 0, 0, cursorWidth, cursorHeight, andMask, xorMask);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        free(andMask);
 | 
				
			||||||
 | 
					        free(xorMask);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Initialize for remote sessions
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					static void initRemoteSession(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //Check if the current progress was started with Remote Desktop.
 | 
				
			||||||
 | 
					    _glfw.win32.isRemoteSession = GetSystemMetrics(SM_REMOTESESSION) > 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // With Remote desktop, we need to create a blank cursor because of the cursor is Set to NULL
 | 
				
			||||||
 | 
					    // if cannot be moved to center in capture mode. If not Remote Desktop win32.blankCursor stays NULL
 | 
				
			||||||
 | 
					    // and will perform has before (normal).
 | 
				
			||||||
 | 
					    if (_glfw.win32.isRemoteSession)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        createBlankCursor();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//////////////////////////////////////////////////////////////////////////
 | 
					//////////////////////////////////////////////////////////////////////////
 | 
				
			||||||
//////                       GLFW internal API                      //////
 | 
					//////                       GLFW internal API                      //////
 | 
				
			||||||
@ -699,12 +740,19 @@ int _glfwInitWin32(void)
 | 
				
			|||||||
    if (!createHelperWindow())
 | 
					    if (!createHelperWindow())
 | 
				
			||||||
        return GLFW_FALSE;
 | 
					        return GLFW_FALSE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Some hacks are needed to support Remote Desktop...
 | 
				
			||||||
 | 
					    initRemoteSession();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _glfwPollMonitorsWin32();
 | 
					    _glfwPollMonitorsWin32();
 | 
				
			||||||
    return GLFW_TRUE;
 | 
					    return GLFW_TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void _glfwTerminateWin32(void)
 | 
					void _glfwTerminateWin32(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (_glfw.win32.blankCursor)
 | 
				
			||||||
 | 
					        DestroyCursor(_glfw.win32.blankCursor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (_glfw.win32.deviceNotificationHandle)
 | 
					    if (_glfw.win32.deviceNotificationHandle)
 | 
				
			||||||
        UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
 | 
					        UnregisterDeviceNotification(_glfw.win32.deviceNotificationHandle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -430,6 +430,7 @@ typedef struct _GLFWwindowWin32
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // The last received cursor position, regardless of source
 | 
					    // The last received cursor position, regardless of source
 | 
				
			||||||
    int                 lastCursorPosX, lastCursorPosY;
 | 
					    int                 lastCursorPosX, lastCursorPosY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // The last received high surrogate when decoding pairs of UTF-16 messages
 | 
					    // The last received high surrogate when decoding pairs of UTF-16 messages
 | 
				
			||||||
    WCHAR               highSurrogate;
 | 
					    WCHAR               highSurrogate;
 | 
				
			||||||
} _GLFWwindowWin32;
 | 
					} _GLFWwindowWin32;
 | 
				
			||||||
@ -457,6 +458,10 @@ typedef struct _GLFWlibraryWin32
 | 
				
			|||||||
    RAWINPUT*           rawInput;
 | 
					    RAWINPUT*           rawInput;
 | 
				
			||||||
    int                 rawInputSize;
 | 
					    int                 rawInputSize;
 | 
				
			||||||
    UINT                mouseTrailSize;
 | 
					    UINT                mouseTrailSize;
 | 
				
			||||||
 | 
					    // Indicate if the process was started behind Remote Destop
 | 
				
			||||||
 | 
					    BOOL                isRemoteSession;
 | 
				
			||||||
 | 
					    // An invisible cursor, needed for special cases (see WM_INPUT handler)
 | 
				
			||||||
 | 
					    HCURSOR             blankCursor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    struct {
 | 
					    struct {
 | 
				
			||||||
        HINSTANCE                       instance;
 | 
					        HINSTANCE                       instance;
 | 
				
			||||||
 | 
				
			|||||||
@ -232,7 +232,10 @@ static void updateCursorImage(_GLFWwindow* window)
 | 
				
			|||||||
            SetCursor(LoadCursorW(NULL, IDC_ARROW));
 | 
					            SetCursor(LoadCursorW(NULL, IDC_ARROW));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        SetCursor(NULL);
 | 
					        //Connected via Remote Desktop, NULL cursor will present SetCursorPos the move the cursor.
 | 
				
			||||||
 | 
					        //using a blank cursor fix that.
 | 
				
			||||||
 | 
					        //When not via Remote Desktop, win32.blankCursor should be NULL
 | 
				
			||||||
 | 
					        SetCursor(_glfw.win32.blankCursor);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Sets the cursor clip rect to the window content area
 | 
					// Sets the cursor clip rect to the window content area
 | 
				
			||||||
@ -897,6 +900,8 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
 | 
				
			|||||||
            HRAWINPUT ri = (HRAWINPUT) lParam;
 | 
					            HRAWINPUT ri = (HRAWINPUT) lParam;
 | 
				
			||||||
            RAWINPUT* data = NULL;
 | 
					            RAWINPUT* data = NULL;
 | 
				
			||||||
            int dx, dy;
 | 
					            int dx, dy;
 | 
				
			||||||
 | 
					            int width, height;
 | 
				
			||||||
 | 
					            POINT pos;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (_glfw.win32.disabledCursorWindow != window)
 | 
					            if (_glfw.win32.disabledCursorWindow != window)
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
@ -924,8 +929,29 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM l
 | 
				
			|||||||
            data = _glfw.win32.rawInput;
 | 
					            data = _glfw.win32.rawInput;
 | 
				
			||||||
            if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
 | 
					            if (data->data.mouse.usFlags & MOUSE_MOVE_ABSOLUTE)
 | 
				
			||||||
            {   
 | 
					            {   
 | 
				
			||||||
                dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
 | 
					                if (_glfw.win32.isRemoteSession)
 | 
				
			||||||
                dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
 | 
					                {
 | 
				
			||||||
 | 
					                    //Remote Desktop Mode...
 | 
				
			||||||
 | 
					                    // As per https://github.com/Microsoft/DirectXTK/commit/ef56b63f3739381e451f7a5a5bd2c9779d2a7555
 | 
				
			||||||
 | 
					                    // MOUSE_MOVE_ABSOLUTE is a range from 0 through 65535, based on the screen size.
 | 
				
			||||||
 | 
					                    // As far as I can tell, absolute mode only occurs over RDP though.
 | 
				
			||||||
 | 
					                    width = GetSystemMetrics((data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) ? SM_CXVIRTUALSCREEN : SM_CXSCREEN);
 | 
				
			||||||
 | 
					                    height = GetSystemMetrics((data->data.mouse.usFlags & MOUSE_VIRTUAL_DESKTOP) ? SM_CYVIRTUALSCREEN : SM_CYSCREEN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    pos.x = (int)((data->data.mouse.lLastX / 65535.0f) * width);
 | 
				
			||||||
 | 
					                    pos.y = (int)((data->data.mouse.lLastY / 65535.0f) * height);
 | 
				
			||||||
 | 
					                    ScreenToClient(window->win32.handle, &pos);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    dx = pos.x - window->win32.lastCursorPosX;
 | 
				
			||||||
 | 
					                    dy = pos.y - window->win32.lastCursorPosY;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                else
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    //Normal mode... We should have the right absolute coords in data.mouse
 | 
				
			||||||
 | 
					                    dx = data->data.mouse.lLastX - window->win32.lastCursorPosX;
 | 
				
			||||||
 | 
					                    dy = data->data.mouse.lLastY - window->win32.lastCursorPosY;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -1432,11 +1458,13 @@ static int createNativeWindow(_GLFWwindow* window,
 | 
				
			|||||||
        window->win32.transparent = GLFW_TRUE;
 | 
					        window->win32.transparent = GLFW_TRUE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _glfwGetWindowSizeWin32(window, &window->win32.width, &window->win32.height);
 | 
					    _glfwGetWindowSizeWin32(window, &window->win32.width, &window->win32.height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return GLFW_TRUE;
 | 
					    return GLFW_TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
 | 
					GLFWbool _glfwCreateWindowWin32(_GLFWwindow* window,
 | 
				
			||||||
                                const _GLFWwndconfig* wndconfig,
 | 
					                                const _GLFWwndconfig* wndconfig,
 | 
				
			||||||
                                const _GLFWctxconfig* ctxconfig,
 | 
					                                const _GLFWctxconfig* ctxconfig,
 | 
				
			||||||
@ -1525,6 +1553,7 @@ void _glfwDestroyWindowWin32(_GLFWwindow* window)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (window->win32.smallIcon)
 | 
					    if (window->win32.smallIcon)
 | 
				
			||||||
        DestroyIcon(window->win32.smallIcon);
 | 
					        DestroyIcon(window->win32.smallIcon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title)
 | 
					void _glfwSetWindowTitleWin32(_GLFWwindow* window, const char* title)
 | 
				
			||||||
@ -2102,6 +2131,7 @@ void _glfwPollEventsWin32(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // NOTE: Re-center the cursor only if it has moved since the last call,
 | 
					        // NOTE: Re-center the cursor only if it has moved since the last call,
 | 
				
			||||||
        //       to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
 | 
					        //       to avoid breaking glfwWaitEvents with WM_MOUSEMOVE
 | 
				
			||||||
 | 
					        // The re-center is required in order to prevent the mouse cursor stopping at the edges of the screen.
 | 
				
			||||||
        if (window->win32.lastCursorPosX != width / 2 ||
 | 
					        if (window->win32.lastCursorPosX != width / 2 ||
 | 
				
			||||||
            window->win32.lastCursorPosY != height / 2)
 | 
					            window->win32.lastCursorPosY != height / 2)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user