summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2011-06-18 22:50:30 +0200
committerLars Knoll <lars.knoll@nokia.com>2011-06-20 13:31:52 +0200
commit7a64f12cfe03b673ebb3c5e9e0396c6a504620d8 (patch)
tree95e0d377fdb67b2c3166d8b58ce934d9c3229f02
parent8ffbdae179ea91f5d9524ec4768990994a4ce3fb (diff)
use selection changed events from XFixes
properly initialize the XFixes extension and then use the selection changed events to notify Qt apps. Reviewed-by: Samuel
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp50
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp24
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h4
4 files changed, 58 insertions, 22 deletions
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index ea7cefb972..31f82443de 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -163,6 +163,28 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
m_timestamp[QClipboard::Selection] = XCB_CURRENT_TIME;
m_screen = connection()->screens().at(connection()->primaryScreen());
+
+ int x = 0, y = 0, w = 3, h = 3;
+
+ m_owner = xcb_generate_id(xcb_connection());
+ Q_XCB_CALL(xcb_create_window(xcb_connection(),
+ XCB_COPY_FROM_PARENT, // depth -- same as root
+ m_owner, // window id
+ m_screen->screen()->root, // parent window id
+ x, y, w, h,
+ 0, // border width
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
+ m_screen->screen()->root_visual, // visual
+ 0, // value mask
+ 0)); // value list
+
+ if (connection()->hasXFixes()) {
+ const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
+ XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
+ XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE;
+ Q_XCB_CALL(xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, XCB_ATOM_PRIMARY, mask));
+ Q_XCB_CALL(xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, atom(QXcbAtom::CLIPBOARD), mask));
+ }
}
QXcbClipboard::~QXcbClipboard()
@@ -322,24 +344,6 @@ void QXcbClipboard::setRequestor(xcb_window_t window)
xcb_window_t QXcbClipboard::owner() const
{
- if (!m_owner) {
- int x = 0, y = 0, w = 3, h = 3;
-
- xcb_window_t window = xcb_generate_id(xcb_connection());
- Q_XCB_CALL(xcb_create_window(xcb_connection(),
- XCB_COPY_FROM_PARENT, // depth -- same as root
- window, // window id
- m_screen->screen()->root, // parent window id
- x, y, w, h,
- 0, // border width
- XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
- m_screen->screen()->root_visual, // visual
- 0, // value mask
- 0)); // value list
-
- QXcbClipboard *that = const_cast<QXcbClipboard *>(this);
- that->m_owner = window;
- }
return m_owner;
}
@@ -554,6 +558,16 @@ void QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t *req)
xcb_send_event(xcb_connection(), false, req->requestor, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
}
+void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_event_t *event)
+{
+ QClipboard::Mode mode = modeForAtom(event->selection);
+ if (event->owner != owner() && m_clientClipboard[mode] && m_timestamp[mode] < event->selection_timestamp) {
+ setMimeData(0, mode);
+ emitChanged(mode);
+ }
+}
+
+
static inline int maxSelectionIncr(xcb_connection_t *c)
{
int l = xcb_get_maximum_request_length(c);
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h
index db31051ee7..d23f93529b 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.h
+++ b/src/plugins/platforms/xcb/qxcbclipboard.h
@@ -45,6 +45,7 @@
#include <QPlatformClipboard>
#include <qxcbobject.h>
#include <xcb/xcb.h>
+#include <xcb/xfixes.h>
class QXcbConnection;
class QXcbScreen;
@@ -71,6 +72,7 @@ public:
void handleSelectionRequest(xcb_selection_request_event_t *event);
void handleSelectionClearRequest(xcb_selection_clear_event_t *event);
+ void handleXFixesSelectionRequest(xcb_xfixes_selection_notify_event_t *event);
bool clipboardReadProperty(xcb_window_t win, xcb_atom_t property, bool deleteProperty, QByteArray *buffer, int *size, xcb_atom_t *type, int *format) const;
QByteArray clipboardReadIncrementalProperty(xcb_window_t win, xcb_atom_t property, int nbytes, bool nullterm);
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index eddc3305d1..d6460339a2 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -90,6 +90,7 @@ QXcbConnection::QXcbConnection(const char *displayName)
, m_dri2_support_probed(false)
, m_has_support_for_dri2(false)
#endif
+ , xfixes_first_event(0)
{
m_primaryScreen = 0;
@@ -110,6 +111,8 @@ QXcbConnection::QXcbConnection(const char *displayName)
m_connection = xcb_connect(m_displayName.constData(), &primaryScreen);
#endif //XCB_USE_XLIB
+ xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id);
+
m_setup = xcb_get_setup(xcb_connection());
initializeAllAtoms();
@@ -124,14 +127,14 @@ QXcbConnection::QXcbConnection(const char *displayName)
xcb_screen_next(&it);
}
+ initializeXFixes();
+ initializeXRender();
+
m_wmSupport = new QXcbWMSupport(this);
m_keyboard = new QXcbKeyboard(this);
m_clipboard = new QXcbClipboard(this);
m_drag = new QXcbDrag(this);
- initializeXFixes();
- initializeXRender();
-
#ifdef XCB_USE_DRI2
initializeDri2();
#endif
@@ -506,6 +509,15 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
handled = false;
break;
}
+
+ if (!handled) {
+ if (response_type == xfixes_first_event + XCB_XFIXES_SELECTION_NOTIFY) {
+ setTime(((xcb_xfixes_selection_notify_event_t *)event)->timestamp);
+ m_clipboard->handleXFixesSelectionRequest((xcb_xfixes_selection_notify_event_t *)event);
+ handled = true;
+ }
+ }
+
if (handled)
printXcbEvent("Handled XCB event", event);
else
@@ -842,7 +854,9 @@ void QXcbConnection::sync()
void QXcbConnection::initializeXFixes()
{
xcb_generic_error_t *error = 0;
- xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id);
+ const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id);
+ xfixes_first_event = reply->first_event;
+
xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection,
XCB_XFIXES_MAJOR_VERSION,
XCB_XFIXES_MINOR_VERSION);
@@ -851,8 +865,10 @@ void QXcbConnection::initializeXFixes()
if (!xfixes_query || error || xfixes_query->major_version < 2) {
qWarning("Failed to initialize XFixes");
free(error);
+ xfixes_first_event = 0;
}
free(xfixes_query);
+
}
void QXcbConnection::initializeXRender()
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 9413b682c3..6cc7e13d02 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -286,6 +286,8 @@ public:
inline xcb_timestamp_t time() const { return m_time; }
inline void setTime(xcb_timestamp_t t) { if (t > m_time) m_time = t; }
+ bool hasXFixes() const { return xfixes_first_event > 0; }
+
private slots:
void processXcbEvents();
@@ -347,6 +349,8 @@ private:
WindowMapper m_mapper;
QVector<PeekFunc> m_peekFuncs;
+
+ uint32_t xfixes_first_event;
};
#define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display()))