mirror of
				https://github.com/glfw/glfw.git
				synced 2025-10-30 20:22:30 +00:00 
			
		
		
		
	Win32: Improve clipboard contention issue
This is primarily a workaround for a GLFW application reading and/or writing to the clipboard in rapid succession and catching up with the Windows Clipboard History, which also has to contend for the lock.
This commit is contained in:
		
							parent
							
								
									2c3eb75748
								
							
						
					
					
						commit
						29885c6942
					
				| @ -234,6 +234,7 @@ information on what to include when reporting a bug. | ||||
|  - [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: XInput could reportedly provide invalid DPad bit masks (#2291) | ||||
|  - [Win32] Bugfix: Rapid clipboard calls could fail due to Clipboard History | ||||
|  - [Cocoa] Added support for `VK_EXT_metal_surface` (#1619) | ||||
|  - [Cocoa] Added locating the Vulkan loader at runtime in an application bundle | ||||
|  - [Cocoa] Moved main menu creation to GLFW initialization time (#1649) | ||||
|  | ||||
| @ -5814,6 +5814,11 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state); | ||||
|  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref | ||||
|  *  GLFW_PLATFORM_ERROR. | ||||
|  * | ||||
|  *  @remark @win32 The clipboard on Windows has a single global lock for reading and | ||||
|  *  writing.  GLFW tries to acquire it a few times, which is almost always enough.  If it | ||||
|  *  cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns. | ||||
|  *  It is safe to try this multiple times. | ||||
|  * | ||||
|  *  @pointer_lifetime The specified string is copied before this function | ||||
|  *  returns. | ||||
|  * | ||||
| @ -5842,6 +5847,11 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string); | ||||
|  *  @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref | ||||
|  *  GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR. | ||||
|  * | ||||
|  *  @remark @win32 The clipboard on Windows has a single global lock for reading and | ||||
|  *  writing.  GLFW tries to acquire it a few times, which is almost always enough.  If it | ||||
|  *  cannot acquire the lock then this function emits @ref GLFW_PLATFORM_ERROR and returns. | ||||
|  *  It is safe to try this multiple times. | ||||
|  * | ||||
|  *  @pointer_lifetime The returned string is allocated and freed by GLFW.  You | ||||
|  *  should not free it yourself.  It is valid until the next call to @ref | ||||
|  *  glfwGetClipboardString or @ref glfwSetClipboardString, or until the library | ||||
|  | ||||
| @ -2293,7 +2293,7 @@ void _glfwSetCursorWin32(_GLFWwindow* window, _GLFWcursor* cursor) | ||||
| 
 | ||||
| void _glfwSetClipboardStringWin32(const char* string) | ||||
| { | ||||
|     int characterCount; | ||||
|     int characterCount, tries = 0; | ||||
|     HANDLE object; | ||||
|     WCHAR* buffer; | ||||
| 
 | ||||
| @ -2321,12 +2321,20 @@ void _glfwSetClipboardStringWin32(const char* string) | ||||
|     MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount); | ||||
|     GlobalUnlock(object); | ||||
| 
 | ||||
|     if (!OpenClipboard(_glfw.win32.helperWindowHandle)) | ||||
|     // NOTE: Retry clipboard opening a few times as some other application may have it
 | ||||
|     //       open and also the Windows Clipboard History reads it after each update
 | ||||
|     while (!OpenClipboard(_glfw.win32.helperWindowHandle)) | ||||
|     { | ||||
|         _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, | ||||
|                              "Win32: Failed to open clipboard"); | ||||
|         GlobalFree(object); | ||||
|         return; | ||||
|         Sleep(1); | ||||
|         tries++; | ||||
| 
 | ||||
|         if (tries == 3) | ||||
|         { | ||||
|             _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, | ||||
|                                  "Win32: Failed to open clipboard"); | ||||
|             GlobalFree(object); | ||||
|             return; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     EmptyClipboard(); | ||||
| @ -2338,12 +2346,21 @@ const char* _glfwGetClipboardStringWin32(void) | ||||
| { | ||||
|     HANDLE object; | ||||
|     WCHAR* buffer; | ||||
|     int tries = 0; | ||||
| 
 | ||||
|     if (!OpenClipboard(_glfw.win32.helperWindowHandle)) | ||||
|     // NOTE: Retry clipboard opening a few times as some other application may have it
 | ||||
|     //       open and also the Windows Clipboard History reads it after each update
 | ||||
|     while (!OpenClipboard(_glfw.win32.helperWindowHandle)) | ||||
|     { | ||||
|         _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, | ||||
|                              "Win32: Failed to open clipboard"); | ||||
|         return NULL; | ||||
|         Sleep(1); | ||||
|         tries++; | ||||
| 
 | ||||
|         if (tries == 3) | ||||
|         { | ||||
|             _glfwInputErrorWin32(GLFW_PLATFORM_ERROR, | ||||
|                                  "Win32: Failed to open clipboard"); | ||||
|             return NULL; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     object = GetClipboardData(CF_UNICODETEXT); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user