Check for the clipboard manager when looping due to app quiting
authorAlbert Astals Cid <aacid@kde.org>
Thu, 5 Jan 2012 10:11:27 +0000 (11:11 +0100)
committerQt by Nokia <qt-info@nokia.com>
Thu, 5 Jan 2012 13:59:12 +0000 (14:59 +0100)
One can be extremely unlucky and on session logout get this:
 * All apps are going down
 * A Qt app checks if the clipboard manager is there to yield its clipboard contents
   * The clipboard manager is still there
 * Then just after that check, the clipboard manager finishes because of the session end
 * This means the Qt app will loop for 5 seconds trying to yield its clipboard contents
   to a clipboard manager that is not there anymore

Change-Id: Ia89670d4deb72f12e660a0d7aa5b2d212955d6fe
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
src/plugins/platforms/xcb/qxcbclipboard.cpp
src/plugins/platforms/xcb/qxcbclipboard.h

index 3c3469a..24de788 100644 (file)
@@ -208,7 +208,7 @@ QXcbClipboard::~QXcbClipboard()
             connection()->sync();
 
             // waiting until the clipboard manager fetches the content.
-            if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, 5000)) {
+            if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, 5000, true)) {
                 qWarning("QClipboard: Unable to receive an event from the "
                          "clipboard manager in a reasonable time");
             }
@@ -726,7 +726,7 @@ namespace
     };
 }
 
-xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int type, int timeout)
+xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int type, int timeout, bool checkManager)
 {
     QElapsedTimer timer;
     timer.start();
@@ -736,6 +736,16 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int
         if (e)
             return e;
 
+        if (checkManager) {
+            xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER));
+            xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(xcb_connection(), cookie, 0);
+            if (!reply || reply->owner == XCB_NONE) {
+                free(reply);
+                return 0;
+            }
+            free(reply);
+        }
+
         // process other clipboard events, since someone is probably requesting data from us
         ClipboardEvent clipboard(connection());
         e = connection()->checkEvent(clipboard);
index 9debdce..e9ddb70 100644 (file)
@@ -85,7 +85,7 @@ public:
     QByteArray getSelection(xcb_atom_t selection, xcb_atom_t target, xcb_atom_t property);
 
 private:
-    xcb_generic_event_t *waitForClipboardEvent(xcb_window_t win, int type, int timeout);
+    xcb_generic_event_t *waitForClipboardEvent(xcb_window_t win, int type, int timeout, bool needsManager = false);
 
     xcb_atom_t sendTargetsSelection(QMimeData *d, xcb_window_t window, xcb_atom_t property);
     xcb_atom_t sendSelection(QMimeData *d, xcb_atom_t target, xcb_window_t window, xcb_atom_t property);