mirror of
https://github.com/glfw/glfw.git
synced 2024-11-10 00:51:47 +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: `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: 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
|
||||||
- [Cocoa] Moved main menu creation to GLFW initialization time (#1649)
|
- [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
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
* GLFW_PLATFORM_ERROR.
|
* 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
|
* @pointer_lifetime The specified string is copied before this function
|
||||||
* returns.
|
* returns.
|
||||||
*
|
*
|
||||||
@ -5842,6 +5847,11 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* window, const char* string);
|
|||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
|
||||||
* GLFW_FORMAT_UNAVAILABLE and @ref GLFW_PLATFORM_ERROR.
|
* 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
|
* @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
|
* should not free it yourself. It is valid until the next call to @ref
|
||||||
* glfwGetClipboardString or @ref glfwSetClipboardString, or until the library
|
* glfwGetClipboardString or @ref glfwSetClipboardString, or until the library
|
||||||
|
@ -2293,7 +2293,7 @@ void _glfwSetCursorWin32(_GLFWwindow* window, _GLFWcursor* cursor)
|
|||||||
|
|
||||||
void _glfwSetClipboardStringWin32(const char* string)
|
void _glfwSetClipboardStringWin32(const char* string)
|
||||||
{
|
{
|
||||||
int characterCount;
|
int characterCount, tries = 0;
|
||||||
HANDLE object;
|
HANDLE object;
|
||||||
WCHAR* buffer;
|
WCHAR* buffer;
|
||||||
|
|
||||||
@ -2321,13 +2321,21 @@ void _glfwSetClipboardStringWin32(const char* string)
|
|||||||
MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);
|
MultiByteToWideChar(CP_UTF8, 0, string, -1, buffer, characterCount);
|
||||||
GlobalUnlock(object);
|
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))
|
||||||
|
{
|
||||||
|
Sleep(1);
|
||||||
|
tries++;
|
||||||
|
|
||||||
|
if (tries == 3)
|
||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"Win32: Failed to open clipboard");
|
"Win32: Failed to open clipboard");
|
||||||
GlobalFree(object);
|
GlobalFree(object);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EmptyClipboard();
|
EmptyClipboard();
|
||||||
SetClipboardData(CF_UNICODETEXT, object);
|
SetClipboardData(CF_UNICODETEXT, object);
|
||||||
@ -2338,13 +2346,22 @@ const char* _glfwGetClipboardStringWin32(void)
|
|||||||
{
|
{
|
||||||
HANDLE object;
|
HANDLE object;
|
||||||
WCHAR* buffer;
|
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))
|
||||||
|
{
|
||||||
|
Sleep(1);
|
||||||
|
tries++;
|
||||||
|
|
||||||
|
if (tries == 3)
|
||||||
{
|
{
|
||||||
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
|
||||||
"Win32: Failed to open clipboard");
|
"Win32: Failed to open clipboard");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object = GetClipboardData(CF_UNICODETEXT);
|
object = GetClipboardData(CF_UNICODETEXT);
|
||||||
if (!object)
|
if (!object)
|
||||||
|
Loading…
Reference in New Issue
Block a user