Cygwin: clipboard: Add workaround for setting clipboard failure.

- OpenClipboard() just after CloseClipboard() sometimes fails. Due
  to this, /dev/clipboard sometimes fails to set CF_UNICODETEXT
  data. This patch add a workaround for this issue.
This commit is contained in:
Takashi Yano 2022-07-02 12:08:51 +09:00
parent 1db7cf5ce6
commit 9193f6efde
1 changed files with 34 additions and 13 deletions

View File

@ -20,6 +20,27 @@ details. */
#include <sys/clipboard.h> #include <sys/clipboard.h>
#include <unistd.h> #include <unistd.h>
/* Opening clipboard immediately after CloseClipboard()
sometimes fails. Therefore use retry-loop. */
static inline bool
open_clipboard ()
{
const int max_retry = 10;
for (int i = 0; i < max_retry; i++)
{
if (OpenClipboard (NULL))
return true;
Sleep (1);
}
return false;
}
static inline bool
close_clipboard ()
{
return CloseClipboard ();
}
/* /*
* Robert Collins: * Robert Collins:
* FIXME: should we use GetClipboardSequenceNumber to tell if the clipboard has * FIXME: should we use GetClipboardSequenceNumber to tell if the clipboard has
@ -30,9 +51,9 @@ fhandler_dev_clipboard::fhandler_dev_clipboard ()
: fhandler_base (), pos (0), membuffer (NULL), msize (0) : fhandler_base (), pos (0), membuffer (NULL), msize (0)
{ {
/* FIXME: check for errors and loop until we can open the clipboard */ /* FIXME: check for errors and loop until we can open the clipboard */
OpenClipboard (NULL); open_clipboard ();
cygnativeformat = RegisterClipboardFormatW (CYGWIN_NATIVE); cygnativeformat = RegisterClipboardFormatW (CYGWIN_NATIVE);
CloseClipboard (); close_clipboard ();
} }
/* /*
@ -54,7 +75,7 @@ fhandler_dev_clipboard::set_clipboard (const void *buf, size_t len)
{ {
HGLOBAL hmem; HGLOBAL hmem;
/* Native CYGWIN format */ /* Native CYGWIN format */
if (OpenClipboard (NULL)) if (open_clipboard ())
{ {
cygcb_t *clipbuf; cygcb_t *clipbuf;
@ -62,7 +83,7 @@ fhandler_dev_clipboard::set_clipboard (const void *buf, size_t len)
if (!hmem) if (!hmem)
{ {
__seterrno (); __seterrno ();
CloseClipboard (); close_clipboard ();
return -1; return -1;
} }
clipbuf = (cygcb_t *) GlobalLock (hmem); clipbuf = (cygcb_t *) GlobalLock (hmem);
@ -74,7 +95,7 @@ fhandler_dev_clipboard::set_clipboard (const void *buf, size_t len)
GlobalUnlock (hmem); GlobalUnlock (hmem);
EmptyClipboard (); EmptyClipboard ();
HANDLE ret = SetClipboardData (cygnativeformat, hmem); HANDLE ret = SetClipboardData (cygnativeformat, hmem);
CloseClipboard (); close_clipboard ();
/* According to MSDN, hmem must not be free'd after transferring the /* According to MSDN, hmem must not be free'd after transferring the
data to the clipboard via SetClipboardData. */ data to the clipboard via SetClipboardData. */
/* GlobalFree (hmem); */ /* GlobalFree (hmem); */
@ -92,7 +113,7 @@ fhandler_dev_clipboard::set_clipboard (const void *buf, size_t len)
set_errno (EILSEQ); set_errno (EILSEQ);
return -1; return -1;
} }
if (OpenClipboard (NULL)) if (open_clipboard ())
{ {
PWCHAR clipbuf; PWCHAR clipbuf;
@ -100,14 +121,14 @@ fhandler_dev_clipboard::set_clipboard (const void *buf, size_t len)
if (!hmem) if (!hmem)
{ {
__seterrno (); __seterrno ();
CloseClipboard (); close_clipboard ();
return -1; return -1;
} }
clipbuf = (PWCHAR) GlobalLock (hmem); clipbuf = (PWCHAR) GlobalLock (hmem);
sys_mbstowcs (clipbuf, len + 1, (const char *) buf); sys_mbstowcs (clipbuf, len + 1, (const char *) buf);
GlobalUnlock (hmem); GlobalUnlock (hmem);
HANDLE ret = SetClipboardData (CF_UNICODETEXT, hmem); HANDLE ret = SetClipboardData (CF_UNICODETEXT, hmem);
CloseClipboard (); close_clipboard ();
/* According to MSDN, hmem must not be free'd after transferring the /* According to MSDN, hmem must not be free'd after transferring the
data to the clipboard via SetClipboardData. */ data to the clipboard via SetClipboardData. */
/* GlobalFree (hmem); */ /* GlobalFree (hmem); */
@ -161,7 +182,7 @@ fhandler_dev_clipboard::fstat (struct stat *buf)
buf->st_ctim.tv_nsec = 0L; buf->st_ctim.tv_nsec = 0L;
buf->st_birthtim = buf->st_atim = buf->st_mtim = buf->st_ctim; buf->st_birthtim = buf->st_atim = buf->st_mtim = buf->st_ctim;
if (OpenClipboard (NULL)) if (open_clipboard ())
{ {
UINT formatlist[1] = { cygnativeformat }; UINT formatlist[1] = { cygnativeformat };
int format; int format;
@ -176,7 +197,7 @@ fhandler_dev_clipboard::fstat (struct stat *buf)
buf->st_size = clipbuf->cb_size; buf->st_size = clipbuf->cb_size;
GlobalUnlock (hglb); GlobalUnlock (hglb);
} }
CloseClipboard (); close_clipboard ();
} }
return 0; return 0;
@ -192,7 +213,7 @@ fhandler_dev_clipboard::read (void *ptr, size_t& len)
LPVOID cb_data; LPVOID cb_data;
int rach; int rach;
if (!OpenClipboard (NULL)) if (!open_clipboard ())
{ {
len = 0; len = 0;
return; return;
@ -203,7 +224,7 @@ fhandler_dev_clipboard::read (void *ptr, size_t& len)
|| !(hglb = GetClipboardData (format)) || !(hglb = GetClipboardData (format))
|| !(cb_data = GlobalLock (hglb))) || !(cb_data = GlobalLock (hglb)))
{ {
CloseClipboard (); close_clipboard ();
len = 0; len = 0;
return; return;
} }
@ -290,7 +311,7 @@ fhandler_dev_clipboard::read (void *ptr, size_t& len)
} }
} }
GlobalUnlock (hglb); GlobalUnlock (hglb);
CloseClipboard (); close_clipboard ();
len = ret; len = ret;
} }