Fix timing issue in incremental data retrieval mechanism
Make sure that we are not reading wrong PropertyNotify events. From icccm: Requestors may receive a property of type INCR in response to any target that results in selection data. This indicates that the owner will send the actual data incrementally. The selection requestor: - Waits for the SelectionNotify event. - Loops: + Retrieving data using GetProperty with the delete argument True. + Waiting for a PropertyNotify with the state argument NewValue. - Waits until the property named by the PropertyNotify event is zero-length. - Deletes the zero-length property. The issue with the current approach was that after receiving INCR we simply fetched the first PropertyNotify event from the queue, where timestamp indicates that it was generated before INCR, which is not what need. We need PropertyNotify events with a timestamp older than the one on INCR. Task-number: QTBUG-32045 Change-Id: I3b9a006f7d346f67c51e1a296d67a9dc89efadb1 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
This commit is contained in:
parent
bc6f5b3ff6
commit
663c5186e8
@ -272,6 +272,7 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
|
||||
, m_owner(XCB_NONE)
|
||||
, m_incr_active(false)
|
||||
, m_clipboard_closing(false)
|
||||
, m_incr_receive_time(0)
|
||||
{
|
||||
Q_ASSERT(QClipboard::Clipboard == 0);
|
||||
Q_ASSERT(QClipboard::Selection == 1);
|
||||
@ -733,7 +734,7 @@ static inline int maxSelectionIncr(xcb_connection_t *c)
|
||||
return (l > 65536 ? 65536*4 : l*4) - 100;
|
||||
}
|
||||
|
||||
bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, bool deleteProperty, QByteArray *buffer, int *size, xcb_atom_t *type, int *format) const
|
||||
bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property, bool deleteProperty, QByteArray *buffer, int *size, xcb_atom_t *type, int *format)
|
||||
{
|
||||
int maxsize = maxSelectionIncr(xcb_connection());
|
||||
ulong bytes_left; // bytes_after
|
||||
@ -809,7 +810,8 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
|
||||
// correct size, not 0-term.
|
||||
if (size)
|
||||
*size = buffer_offset;
|
||||
|
||||
if (*type == atom(QXcbAtom::INCR))
|
||||
m_incr_receive_time = connection()->getTimestamp();
|
||||
if (deleteProperty)
|
||||
xcb_delete_property(xcb_connection(), win, property);
|
||||
|
||||
@ -913,6 +915,7 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb
|
||||
bool alloc_error = false;
|
||||
int length;
|
||||
int offset = 0;
|
||||
xcb_timestamp_t prev_time = m_incr_receive_time;
|
||||
|
||||
if (nbytes > 0) {
|
||||
// Reserve buffer + zero-terminator (for text data)
|
||||
@ -927,10 +930,14 @@ QByteArray QXcbClipboard::clipboardReadIncrementalProperty(xcb_window_t win, xcb
|
||||
xcb_generic_event_t *ge = waitForClipboardEvent(win, XCB_PROPERTY_NOTIFY, clipboard_timeout);
|
||||
if (!ge)
|
||||
break;
|
||||
|
||||
xcb_property_notify_event_t *event = (xcb_property_notify_event_t *)ge;
|
||||
if (event->atom != property || event->state != XCB_PROPERTY_NEW_VALUE)
|
||||
|
||||
if (event->atom != property
|
||||
|| event->state != XCB_PROPERTY_NEW_VALUE
|
||||
|| event->time < prev_time)
|
||||
continue;
|
||||
prev_time = event->time;
|
||||
|
||||
if (clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0)) {
|
||||
if (length == 0) { // no more data, we're done
|
||||
if (nullterm) {
|
||||
|
@ -78,7 +78,7 @@ public:
|
||||
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;
|
||||
bool clipboardReadProperty(xcb_window_t win, xcb_atom_t property, bool deleteProperty, QByteArray *buffer, int *size, xcb_atom_t *type, int *format);
|
||||
QByteArray clipboardReadIncrementalProperty(xcb_window_t win, xcb_atom_t property, int nbytes, bool nullterm);
|
||||
|
||||
QByteArray getDataInFormat(xcb_atom_t modeAtom, xcb_atom_t fmtatom);
|
||||
@ -113,6 +113,7 @@ private:
|
||||
|
||||
bool m_incr_active;
|
||||
bool m_clipboard_closing;
|
||||
xcb_timestamp_t m_incr_receive_time;
|
||||
};
|
||||
|
||||
#endif // QT_NO_CLIPBOARD
|
||||
|
Loading…
Reference in New Issue
Block a user