diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbclipboard.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbclipboard.cpp | 122 |
1 files changed, 36 insertions, 86 deletions
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index b091928e8c..84831cdbe5 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -42,16 +42,13 @@ #include "qxcbconnection.h" #include "qxcbscreen.h" #include "qxcbmime.h" +#include "qxcbwindow.h" #include <private/qguiapplication_p.h> #include <QElapsedTimer> #include <QtCore/QDebug> -#define class class_name // Workaround XCB-ICCCM 3.8 breakage -#include <xcb/xcb_icccm.h> -#undef class - QT_BEGIN_NAMESPACE #ifndef QT_NO_CLIPBOARD @@ -156,6 +153,7 @@ private: QByteArray format_atoms; }; +namespace { class INCRTransaction; typedef QMap<xcb_window_t,INCRTransaction*> TransactionMap; static TransactionMap *transactions = 0; @@ -262,6 +260,7 @@ private: uint offset; int abort_timer; }; +} // unnamed namespace const int QXcbClipboard::clipboard_timeout = 5000; @@ -276,18 +275,6 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c) m_timestamp[QClipboard::Selection] = XCB_CURRENT_TIME; m_owner = connection()->getQtSelectionOwner(); -#ifndef QT_NO_DEBUG - QByteArray ba("Qt clipboard window"); - xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - m_owner, - atom(QXcbAtom::_NET_WM_NAME), - atom(QXcbAtom::UTF8_STRING), - 8, - ba.length(), - ba.constData()); -#endif - if (connection()->hasXFixes()) { const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER | XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY | @@ -314,7 +301,7 @@ QXcbClipboard::~QXcbClipboard() connection()->sync(); // waiting until the clipboard manager fetches the content. - if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, clipboard_timeout, true)) { + if (!waitForClipboardEvent(m_owner, XCB_SELECTION_NOTIFY, true)) { qWarning("QXcbClipboard: Unable to receive an event from the " "clipboard manager in a reasonable time"); } @@ -467,17 +454,9 @@ xcb_window_t QXcbClipboard::requestor() const platformScreen->screen()->root_visual, // visual 0, // value mask 0); // value list -#ifndef QT_NO_DEBUG - QByteArray ba("Qt clipboard requestor window"); - xcb_change_property(xcb_connection(), - XCB_PROP_MODE_REPLACE, - window, - atom(QXcbAtom::_NET_WM_NAME), - atom(QXcbAtom::UTF8_STRING), - 8, - ba.length(), - ba.constData()); -#endif + + QXcbWindow::setWindowTitle(connection(), window, + QStringLiteral("Qt Clipboard Requestor Window")); uint32_t mask = XCB_EVENT_MASK_PROPERTY_CHANGE; xcb_change_window_attributes(xcb_connection(), window, XCB_CW_EVENT_MASK, &mask); @@ -600,7 +579,7 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req) return; } - Q_DECLARE_XCB_EVENT(event, xcb_selection_notify_event_t); + q_padded_xcb_event<xcb_selection_notify_event_t> event = {}; event.response_type = XCB_SELECTION_NOTIFY; event.requestor = req->requestor; event.selection = req->selection; @@ -824,73 +803,44 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, return ok; } - -namespace +xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t window, int type, bool checkManager) { - class Notify { - public: - Notify(xcb_window_t win, int t) - : window(win), type(t) {} - xcb_window_t window; - int type; - bool checkEvent(xcb_generic_event_t *event) const { - if (!event) - return false; - int t = event->response_type & 0x7f; - if (t != type) + QElapsedTimer timer; + timer.start(); + do { + auto e = connection()->checkEvent([window, type](xcb_generic_event_t *event, int eventType) { + if (eventType != type) return false; - if (t == XCB_PROPERTY_NOTIFY) { - xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event; - if (pn->window == window) + if (eventType == XCB_PROPERTY_NOTIFY) { + auto propertyNotify = reinterpret_cast<xcb_property_notify_event_t *>(event); + if (propertyNotify->window == window) return true; - } else if (t == XCB_SELECTION_NOTIFY) { - xcb_selection_notify_event_t *sn = (xcb_selection_notify_event_t *)event; - if (sn->requestor == window) + } else if (eventType == XCB_SELECTION_NOTIFY) { + auto selectionNotify = reinterpret_cast<xcb_selection_notify_event_t *>(event); + if (selectionNotify->requestor == window) return true; } return false; - } - }; - class ClipboardEvent { - public: - ClipboardEvent(QXcbConnection *c) - { clipboard = c->internAtom("CLIPBOARD"); } - xcb_atom_t clipboard; - bool checkEvent(xcb_generic_event_t *e) const { - if (!e) - return false; - int type = e->response_type & 0x7f; - if (type == XCB_SELECTION_REQUEST) { - xcb_selection_request_event_t *sr = (xcb_selection_request_event_t *)e; - return sr->selection == XCB_ATOM_PRIMARY || sr->selection == clipboard; - } else if (type == XCB_SELECTION_CLEAR) { - xcb_selection_clear_event_t *sc = (xcb_selection_clear_event_t *)e; - return sc->selection == XCB_ATOM_PRIMARY || sc->selection == clipboard; - } - return false; - } - }; -} - -xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int type, int timeout, bool checkManager) -{ - QElapsedTimer timer; - timer.start(); - do { - Notify notify(win, type); - xcb_generic_event_t *e = connection()->checkEvent(notify); - if (e) + }); + if (e) // found the waited for event return e; if (checkManager) { auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER)); if (!reply || reply->owner == XCB_NONE) - return 0; + return nullptr; } // process other clipboard events, since someone is probably requesting data from us - ClipboardEvent clipboard(connection()); - e = connection()->checkEvent(clipboard); + auto clipboardAtom = atom(QXcbAtom::CLIPBOARD); + e = connection()->checkEvent([clipboardAtom](xcb_generic_event_t *event, int type) { + xcb_atom_t selection = XCB_ATOM_NONE; + if (type == XCB_SELECTION_REQUEST) + selection = reinterpret_cast<xcb_selection_request_event_t *>(event)->selection; + else if (type == XCB_SELECTION_CLEAR) + selection = reinterpret_cast<xcb_selection_clear_event_t *>(event)->selection; + return selection == XCB_ATOM_PRIMARY || selection == clipboardAtom; + }); if (e) { connection()->handleXcbEvent(e); free(e); @@ -900,9 +850,9 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int // sleep 50 ms, so we don't use up CPU cycles all the time. QThread::msleep(50); - } while (timer.elapsed() < timeout); + } while (timer.elapsed() < clipboard_timeout); - return 0; + return nullptr; } QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb_atom_t property, int nbytes, bool nullterm) @@ -924,7 +874,7 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb for (;;) { connection()->flush(); - xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY, clipboard_timeout); + xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY); if (!ge) break; xcb_property_notify_event_t *event = (xcb_property_notify_event_t *)ge; @@ -987,7 +937,7 @@ QByteArray QXcbClipboard::getSelection(xcb_atom_t selection, xcb_atom_t target, connection()->sync(); - xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_SELECTION_NOTIFY, clipboard_timeout); + xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_SELECTION_NOTIFY); bool no_selection = !ge || ((xcb_selection_notify_event_t *)ge)->property == XCB_NONE; free(ge); |