[gtk+/2.24: 5/7] win32: retry loop when calling OpenClipboard()
- From: Marc-Andre Lureau <malureau src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/2.24: 5/7] win32: retry loop when calling OpenClipboard()
- Date: Thu, 24 Apr 2014 14:05:31 +0000 (UTC)
commit 92e9edfc5f11a8a75296ff58d2323dfb764e838e
Author: Marc-André Lureau <marcandre lureau gmail com>
Date: Thu Aug 22 17:28:59 2013 +0200
win32: retry loop when calling OpenClipboard()
The msdn page says: "OpenClipboard fails if another window has the
clipboard open". And there doesn't seem to be any event when the
clipboard is free again. Since multiple applications may watch and open
it simultaneously, it is easy to reach this error. So do a best effort
with a horrible blocking retry loop...
https://bugzilla.gnome.org/show_bug.cgi?id=706610
gdk/win32/gdkdisplay-win32.c | 2 +-
gdk/win32/gdkprivate-win32.h | 2 +
gdk/win32/gdkproperty-win32.c | 2 +-
gdk/win32/gdkselection-win32.c | 49 +++++++++++++++++++++++++++++++---------
4 files changed, 42 insertions(+), 13 deletions(-)
---
diff --git a/gdk/win32/gdkdisplay-win32.c b/gdk/win32/gdkdisplay-win32.c
index bc90c3a..735069c 100644
--- a/gdk/win32/gdkdisplay-win32.c
+++ b/gdk/win32/gdkdisplay-win32.c
@@ -377,7 +377,7 @@ inner_clipboard_window_procedure (HWND hwnd,
GdkEvent *event;
GdkWindow *owner;
- success = OpenClipboard (hwnd);
+ success = _gdk_win32_open_clipboard (hwnd);
g_return_val_if_fail (success, 0);
hwndOwner = GetClipboardOwner ();
owner = gdk_win32_window_lookup_for_display (_gdk_display, hwndOwner);
diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h
index 7899533..93a60c0 100644
--- a/gdk/win32/gdkprivate-win32.h
+++ b/gdk/win32/gdkprivate-win32.h
@@ -291,6 +291,8 @@ void _gdk_win32_adjust_client_rect (GdkWindow *window,
void _gdk_selection_property_delete (GdkWindow *);
+gboolean _gdk_win32_open_clipboard (HWND new_owner);
+
void _gdk_dropfiles_store (gchar *data);
void _gdk_wchar_text_handle (GdkFont *font,
diff --git a/gdk/win32/gdkproperty-win32.c b/gdk/win32/gdkproperty-win32.c
index 9a7537b..ce25780 100644
--- a/gdk/win32/gdkproperty-win32.c
+++ b/gdk/win32/gdkproperty-win32.c
@@ -196,7 +196,7 @@ gdk_property_change (GdkWindow *window,
{
if (type == _utf8_string)
{
- if (!OpenClipboard (GDK_WINDOW_HWND (window)))
+ if (!_gdk_win32_open_clipboard (GDK_WINDOW_HWND (window)))
{
WIN32_API_FAILED ("OpenClipboard");
return;
diff --git a/gdk/win32/gdkselection-win32.c b/gdk/win32/gdkselection-win32.c
index 41d4d3d..94e8350 100644
--- a/gdk/win32/gdkselection-win32.c
+++ b/gdk/win32/gdkselection-win32.c
@@ -294,8 +294,8 @@ gdk_selection_owner_set_for_display (GdkDisplay *display,
else
hwnd = NULL;
- if (!API_CALL (OpenClipboard, (hwnd)))
- return FALSE;
+ if (!_gdk_win32_open_clipboard (hwnd))
+ return FALSE;
_ignore_destroy_clipboard = TRUE;
GDK_NOTE (DND, g_print ("... EmptyClipboard()\n"));
@@ -420,8 +420,8 @@ gdk_selection_convert (GdkWindow *requestor,
gboolean has_png = FALSE;
gboolean has_bmp = FALSE;
- if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
- return;
+ if (!_gdk_win32_open_clipboard (GDK_WINDOW_HWND (requestor)))
+ return;
targets = g_new (GdkAtom, CountClipboardFormats ());
ntargets = 0;
@@ -524,8 +524,8 @@ gdk_selection_convert (GdkWindow *requestor,
* contents of the clipboard. Get the clipboard data, and store
* it for later.
*/
- if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
- return;
+ if (!_gdk_win32_open_clipboard (GDK_WINDOW_HWND (requestor)))
+ return;
if ((hdata = GetClipboardData (CF_UNICODETEXT)) != NULL)
{
@@ -571,8 +571,8 @@ gdk_selection_convert (GdkWindow *requestor,
}
else if (selection == GDK_SELECTION_CLIPBOARD && target == _image_bmp)
{
- if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
- return;
+ if (!_gdk_win32_open_clipboard (GDK_WINDOW_HWND (requestor)))
+ return;
if ((hdata = GetClipboardData (CF_DIB)) != NULL)
{
@@ -748,8 +748,8 @@ gdk_selection_convert (GdkWindow *requestor,
gchar *mapped_target_name;
UINT fmt = 0;
- if (!API_CALL (OpenClipboard, (GDK_WINDOW_HWND (requestor))))
- return;
+ if (!_gdk_win32_open_clipboard (GDK_WINDOW_HWND (requestor)))
+ return;
mapped_target_name = get_mapped_gdk_atom_name (target);
@@ -862,6 +862,33 @@ gdk_selection_property_get (GdkWindow *requestor,
return prop->length;
}
+gboolean
+_gdk_win32_open_clipboard (HWND new_owner)
+{
+ guint8 tries;
+
+ /* msdn: "OpenClipboard fails if another window has the clipboard
+ * open" There doesn't seem to be an event when the clipboard is
+ * free again. Since multiple applications may watch and open it
+ * simultaneously we do our best effort here with this horrible
+ * blocking retry loop...
+ */
+
+ /* try 8 * 1/4s = 2s */
+ for (tries = 0; tries < 8; tries++)
+ {
+ if (OpenClipboard (new_owner))
+ return TRUE;
+
+ GDK_NOTE (DND, g_print ("_gdk_win32_open_clipboard: try %d, error %d\n",
+ tries, GetLastError ()));
+
+ g_usleep (G_USEC_PER_SEC / 4);
+ }
+
+ return FALSE;
+}
+
void
_gdk_selection_property_delete (GdkWindow *window)
{
@@ -1191,7 +1218,7 @@ gdk_win32_selection_add_targets (GdkWindow *owner,
hwnd = GDK_WINDOW_HWND (owner);
}
- if (!API_CALL (OpenClipboard, (hwnd)))
+ if (!_gdk_win32_open_clipboard (hwnd))
return;
/* We have a very simple strategy: If some kind of pixmap image
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]