use selection changed events from XFixes
properly initialize the XFixes extension and then use the selection changed events to notify Qt apps. Reviewed-by: Samuelbb10
parent
8ffbdae179
commit
7a64f12cfe
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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()))
|
||||
|
|
|
|||
Loading…
Reference in New Issue