Merge lp:~dandrader/qtubuntu/dbusClipboard into lp:qtubuntu
- dbusClipboard
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Robert Carr |
Approved revision: | 244 |
Merged at revision: | 247 |
Proposed branch: | lp:~dandrader/qtubuntu/dbusClipboard |
Merge into: | lp:qtubuntu |
Diff against target: |
580 lines (+282/-84) 8 files modified
src/ubuntumirclient/clipboard.cpp (+219/-73) src/ubuntumirclient/clipboard.h (+31/-2) src/ubuntumirclient/input.cpp (+3/-1) src/ubuntumirclient/integration.cpp (+6/-2) src/ubuntumirclient/integration.h (+4/-2) src/ubuntumirclient/ubuntumirclient.pro (+1/-1) src/ubuntumirclient/window.cpp (+15/-2) src/ubuntumirclient/window.h (+3/-1) |
To merge this branch: | bzr merge lp:~dandrader/qtubuntu/dbusClipboard |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Approve | |
Robert Carr (community) | Approve | ||
Review via email: mp+235502@code.launchpad.net |
Commit message
Use the global clipboard from D-Bus
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
Robert Carr (robertcarr) wrote : | # |
Why the commenting of debug statements at 412? Beyond that seems ok. The assert in serialization is less concerning on the client side than the server side.
Daniel d'Andrada (dandrader) wrote : | # |
> Why the commenting of debug statements at 412?
Because they're ridiculously verbose. A simple swipe produces dozens of lines. So I think it's better for them to be an opt-in thing that you manually enable when you're debugging events. But yeah, not directly related to the objective of that MP.
- 244. By Daniel d'Andrada
-
Implement contents size limitation on the global clipboard
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:244
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Robert Carr (robertcarr) wrote : | # |
thanks for applying fixes from other branch!
Preview Diff
1 | === modified file 'src/ubuntumirclient/clipboard.cpp' |
2 | --- src/ubuntumirclient/clipboard.cpp 2014-06-18 23:10:00 +0000 |
3 | +++ src/ubuntumirclient/clipboard.cpp 2014-09-23 11:49:39 +0000 |
4 | @@ -18,9 +18,9 @@ |
5 | |
6 | #include <QtCore/QMimeData> |
7 | #include <QtCore/QStringList> |
8 | - |
9 | -// Platform API |
10 | -#include <ubuntu/application/ui/clipboard.h> |
11 | +#include <QDBusInterface> |
12 | +#include <QDBusPendingCallWatcher> |
13 | +#include <QDBusPendingReply> |
14 | |
15 | // FIXME(loicm) The clipboard data format is not defined by Ubuntu Platform API |
16 | // which makes it impossible to have non-Qt applications communicate with Qt |
17 | @@ -29,19 +29,26 @@ |
18 | // embedding different mime types in the clipboard. |
19 | |
20 | // Data format: |
21 | -// number of mime types (4 bytes) |
22 | -// data layout (16 bytes * number of mime types) |
23 | -// mime type string offset (4 bytes) |
24 | -// mime type string size (4 bytes) |
25 | -// data offset (4 bytes) |
26 | -// data size (4 bytes) |
27 | +// number of mime types (sizeof(int)) |
28 | +// data layout ((4 * sizeof(int)) * number of mime types) |
29 | +// mime type string offset (sizeof(int)) |
30 | +// mime type string size (sizeof(int)) |
31 | +// data offset (sizeof(int)) |
32 | +// data size (sizeof(int)) |
33 | // data (n bytes) |
34 | |
35 | +namespace { |
36 | + |
37 | const int maxFormatsCount = 16; |
38 | const int maxBufferSize = 4 * 1024 * 1024; // 4 Mb |
39 | |
40 | +} |
41 | + |
42 | UbuntuClipboard::UbuntuClipboard() |
43 | : mMimeData(new QMimeData) |
44 | + , mIsOutdated(true) |
45 | + , mUpdatesDisabled(false) |
46 | + , mDBusSetupDone(false) |
47 | { |
48 | } |
49 | |
50 | @@ -50,80 +57,200 @@ |
51 | delete mMimeData; |
52 | } |
53 | |
54 | +void UbuntuClipboard::requestDBusClipboardContents() |
55 | +{ |
56 | + if (!mDBusSetupDone) { |
57 | + setupDBus(); |
58 | + } |
59 | + |
60 | + if (!mPendingGetContentsCall.isNull()) |
61 | + return; |
62 | + |
63 | + QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("GetContents"); |
64 | + |
65 | + mPendingGetContentsCall = new QDBusPendingCallWatcher(pendingCall, this); |
66 | + |
67 | + QObject::connect(mPendingGetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)), |
68 | + this, SLOT(onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher*))); |
69 | +} |
70 | + |
71 | +void UbuntuClipboard::onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher* call) |
72 | +{ |
73 | + Q_ASSERT(call == mPendingGetContentsCall.data()); |
74 | + |
75 | + QDBusPendingReply<QByteArray> reply = *call; |
76 | + if (reply.isError()) { |
77 | + qCritical("UbuntuClipboard - Failed to get system clipboard contents via D-Bus. %s, %s", |
78 | + qPrintable(reply.error().name()), qPrintable(reply.error().message())); |
79 | + // TODO: Might try again later a number of times... |
80 | + } else { |
81 | + QByteArray serializedMimeData = reply.argumentAt<0>(); |
82 | + updateMimeData(serializedMimeData); |
83 | + } |
84 | + call->deleteLater(); |
85 | +} |
86 | + |
87 | +void UbuntuClipboard::onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher *call) |
88 | +{ |
89 | + QDBusPendingReply<void> reply = *call; |
90 | + if (reply.isError()) { |
91 | + qCritical("UbuntuClipboard - Failed to set the system clipboard contents via D-Bus. %s, %s", |
92 | + qPrintable(reply.error().name()), qPrintable(reply.error().message())); |
93 | + // TODO: Might try again later a number of times... |
94 | + } |
95 | + call->deleteLater(); |
96 | +} |
97 | + |
98 | +void UbuntuClipboard::updateMimeData(const QByteArray &serializedMimeData) |
99 | +{ |
100 | + if (mUpdatesDisabled) |
101 | + return; |
102 | + |
103 | + QMimeData *newMimeData = deserializeMimeData(serializedMimeData); |
104 | + if (newMimeData) { |
105 | + delete mMimeData; |
106 | + mMimeData = newMimeData; |
107 | + mIsOutdated = false; |
108 | + emitChanged(QClipboard::Clipboard); |
109 | + } else { |
110 | + qWarning("UbuntuClipboard - Got invalid serialized mime data. Ignoring it."); |
111 | + } |
112 | +} |
113 | + |
114 | +void UbuntuClipboard::setupDBus() |
115 | +{ |
116 | + QDBusConnection dbusConnection = QDBusConnection::sessionBus(); |
117 | + |
118 | + bool ok = dbusConnection.connect( |
119 | + "com.canonical.QtMir", |
120 | + "/com/canonical/QtMir/Clipboard", |
121 | + "com.canonical.QtMir.Clipboard", |
122 | + "ContentsChanged", |
123 | + this, SLOT(updateMimeData(QByteArray))); |
124 | + if (!ok) { |
125 | + qCritical("UbuntuClipboard - Failed to connect to ContentsChanged signal form the D-Bus system clipboard."); |
126 | + } |
127 | + |
128 | + mDBusClipboard = new QDBusInterface("com.canonical.QtMir", |
129 | + "/com/canonical/QtMir/Clipboard", |
130 | + "com.canonical.QtMir.Clipboard", |
131 | + dbusConnection); |
132 | + |
133 | + mDBusSetupDone = true; |
134 | +} |
135 | + |
136 | +QByteArray UbuntuClipboard::serializeMimeData(QMimeData *mimeData) const |
137 | +{ |
138 | + const QStringList formats = mimeData->formats(); |
139 | + const int formatCount = qMin(formats.size(), maxFormatsCount); |
140 | + const int headerSize = sizeof(int) + (formatCount * 4 * sizeof(int)); |
141 | + int bufferSize = headerSize; |
142 | + |
143 | + for (int i = 0; i < formatCount; i++) |
144 | + bufferSize += formats[i].size() + mimeData->data(formats[i]).size(); |
145 | + |
146 | + QByteArray serializedMimeData; |
147 | + if (bufferSize <= maxBufferSize) { |
148 | + // Serialize data. |
149 | + serializedMimeData.resize(bufferSize); |
150 | + { |
151 | + char *buffer = serializedMimeData.data(); |
152 | + int* header = reinterpret_cast<int*>(serializedMimeData.data()); |
153 | + int offset = headerSize; |
154 | + header[0] = formatCount; |
155 | + for (int i = 0; i < formatCount; i++) { |
156 | + const int formatOffset = offset; |
157 | + const int formatSize = formats[i].size(); |
158 | + const int dataOffset = offset + formatSize; |
159 | + const int dataSize = mimeData->data(formats[i]).size(); |
160 | + memcpy(&buffer[formatOffset], formats[i].toLatin1().data(), formatSize); |
161 | + memcpy(&buffer[dataOffset], mimeData->data(formats[i]).data(), dataSize); |
162 | + header[i*4+1] = formatOffset; |
163 | + header[i*4+2] = formatSize; |
164 | + header[i*4+3] = dataOffset; |
165 | + header[i*4+4] = dataSize; |
166 | + offset += formatSize + dataSize; |
167 | + } |
168 | + } |
169 | + } else { |
170 | + qWarning("UbuntuClipboard: Not sending contents (%d bytes) to the global clipboard as it's" |
171 | + " bigger than the maximum allowed size of %d bytes", bufferSize, maxBufferSize); |
172 | + } |
173 | + |
174 | + return serializedMimeData; |
175 | +} |
176 | + |
177 | +QMimeData *UbuntuClipboard::deserializeMimeData(const QByteArray &serializedMimeData) const |
178 | +{ |
179 | + if (static_cast<std::size_t>(serializedMimeData.size()) < sizeof(int)) { |
180 | + // Data is invalid |
181 | + return nullptr; |
182 | + } |
183 | + |
184 | + QMimeData *mimeData = new QMimeData; |
185 | + |
186 | + const char* const buffer = serializedMimeData.constData(); |
187 | + const int* const header = reinterpret_cast<const int*>(serializedMimeData.constData()); |
188 | + |
189 | + const int count = qMin(header[0], maxFormatsCount); |
190 | + |
191 | + for (int i = 0; i < count; i++) { |
192 | + const int formatOffset = header[i*4+1]; |
193 | + const int formatSize = header[i*4+2]; |
194 | + const int dataOffset = header[i*4+3]; |
195 | + const int dataSize = header[i*4+4]; |
196 | + |
197 | + if (formatOffset + formatSize <= serializedMimeData.size() |
198 | + && dataOffset + dataSize <= serializedMimeData.size()) { |
199 | + |
200 | + QString mimeType = QString::fromLatin1(&buffer[formatOffset], formatSize); |
201 | + QByteArray mimeDataBytes(&buffer[dataOffset], dataSize); |
202 | + |
203 | + mimeData->setData(mimeType, mimeDataBytes); |
204 | + } |
205 | + } |
206 | + |
207 | + return mimeData; |
208 | +} |
209 | + |
210 | QMimeData* UbuntuClipboard::mimeData(QClipboard::Mode mode) |
211 | { |
212 | - Q_UNUSED(mode); |
213 | - // Get clipboard data. |
214 | - void* data = NULL; |
215 | - size_t size = 0; |
216 | - ua_ui_get_clipboard_content(&data, &size); |
217 | + if (mode != QClipboard::Clipboard) |
218 | + return nullptr; |
219 | |
220 | - // Deserialize, update and return mime data taking care of incorrectly |
221 | - // formatted input. |
222 | - mMimeData->clear(); |
223 | - if (static_cast<size_t>(size) > sizeof(int) // Should be at least that big to read the count. |
224 | - && data != NULL) { |
225 | - const char* const buffer = reinterpret_cast<char*>(data); |
226 | - const int* const header = reinterpret_cast<int*>(data); |
227 | - const int count = qMin(header[0], maxFormatsCount); |
228 | - for (int i = 0; i < count; i++) { |
229 | - const unsigned int formatOffset = header[i*4+1]; |
230 | - const unsigned int formatSize = header[i*4+2]; |
231 | - const unsigned int dataOffset = header[i*4+3]; |
232 | - const unsigned int dataSize = header[i*4+4]; |
233 | - if (formatOffset + formatSize <= size && dataOffset + dataSize <= size) { |
234 | - mMimeData->setData(QString(&buffer[formatOffset]), |
235 | - QByteArray(&buffer[dataOffset], dataSize)); |
236 | - } |
237 | - } |
238 | + if (mIsOutdated && mPendingGetContentsCall.isNull()) { |
239 | + requestDBusClipboardContents(); |
240 | } |
241 | + |
242 | + // Return whatever we have at the moment instead of blocking until we have something. |
243 | + // |
244 | + // This might be called during app startup just for the sake of checking if some |
245 | + // "Paste" UI control should be enabled or not. |
246 | + // We will emit QClipboard::changed() once we finally have something. |
247 | return mMimeData; |
248 | } |
249 | |
250 | void UbuntuClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode) |
251 | { |
252 | - Q_UNUSED(mode); |
253 | - if (mimeData == NULL) { |
254 | - ua_ui_set_clipboard_content(NULL, 0); |
255 | + if (mode != QClipboard::Clipboard) |
256 | return; |
257 | - } |
258 | - |
259 | - const QStringList formats = mimeData->formats(); |
260 | - const int count = qMin(formats.size(), maxFormatsCount); |
261 | - const int headerSize = sizeof(int) + count * 4 * sizeof(int); |
262 | - int bufferSize = headerSize; |
263 | - char* buffer; |
264 | - |
265 | - // Get the buffer size considering the header size, the NULL-terminated |
266 | - // formats and the non NULL-terminated data. |
267 | - for (int i = 0; i < count; i++) |
268 | - bufferSize += formats[i].size() + 1 + mimeData->data(formats[i]).size(); |
269 | - // FIXME(loicm) Implement max buffer size limitation. |
270 | - // FIXME(loicm) Remove ASSERT before release. |
271 | - Q_ASSERT(bufferSize <= maxBufferSize); |
272 | - |
273 | - // Serialize data. |
274 | - buffer = new char[bufferSize]; |
275 | - int* header = reinterpret_cast<int*>(buffer); |
276 | - int offset = headerSize; |
277 | - header[0] = count; |
278 | - for (int i = 0; i < count; i++) { |
279 | - const int formatOffset = offset; |
280 | - const int formatSize = formats[i].size() + 1; |
281 | - const int dataOffset = offset + formatSize; |
282 | - const int dataSize = mimeData->data(formats[i]).size(); |
283 | - memcpy(&buffer[formatOffset], formats[i].toLatin1().data(), formatSize); |
284 | - memcpy(&buffer[dataOffset], mimeData->data(formats[i]).data(), dataSize); |
285 | - header[i*4+1] = formatOffset; |
286 | - header[i*4+2] = formatSize; |
287 | - header[i*4+3] = dataOffset; |
288 | - header[i*4+4] = dataSize; |
289 | - offset += formatSize + dataSize; |
290 | - } |
291 | - |
292 | - // Set clipboard content. |
293 | - ua_ui_set_clipboard_content(reinterpret_cast<void*>(buffer), bufferSize); |
294 | - delete [] buffer; |
295 | + |
296 | + if (!mPendingGetContentsCall.isNull()) { |
297 | + // Ignore whatever comes from the system clipboard as we are going to change it anyway |
298 | + QObject::disconnect(mPendingGetContentsCall.data(), 0, this, 0); |
299 | + mUpdatesDisabled = true; |
300 | + mPendingGetContentsCall->waitForFinished(); |
301 | + mUpdatesDisabled = false; |
302 | + delete mPendingGetContentsCall.data(); |
303 | + } |
304 | + |
305 | + QByteArray serializedMimeData = serializeMimeData(mimeData); |
306 | + if (!serializedMimeData.isEmpty()) { |
307 | + setDBusClipboardContents(serializedMimeData); |
308 | + } |
309 | + |
310 | + mMimeData = mimeData; |
311 | + emitChanged(QClipboard::Clipboard); |
312 | } |
313 | |
314 | bool UbuntuClipboard::supportsMode(QClipboard::Mode mode) const |
315 | @@ -136,3 +263,22 @@ |
316 | Q_UNUSED(mode); |
317 | return false; |
318 | } |
319 | + |
320 | +void UbuntuClipboard::setDBusClipboardContents(const QByteArray &clipboardContents) |
321 | +{ |
322 | + if (!mPendingSetContentsCall.isNull()) { |
323 | + // Ignore any previous set call as we are going to overwrite it anyway |
324 | + QObject::disconnect(mPendingSetContentsCall.data(), 0, this, 0); |
325 | + mUpdatesDisabled = true; |
326 | + mPendingSetContentsCall->waitForFinished(); |
327 | + mUpdatesDisabled = false; |
328 | + delete mPendingSetContentsCall.data(); |
329 | + } |
330 | + |
331 | + QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("SetContents", clipboardContents); |
332 | + |
333 | + mPendingSetContentsCall = new QDBusPendingCallWatcher(pendingCall, this); |
334 | + |
335 | + QObject::connect(mPendingSetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)), |
336 | + this, SLOT(onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher*))); |
337 | +} |
338 | |
339 | === modified file 'src/ubuntumirclient/clipboard.h' |
340 | --- src/ubuntumirclient/clipboard.h 2014-06-18 23:10:00 +0000 |
341 | +++ src/ubuntumirclient/clipboard.h 2014-09-23 11:49:39 +0000 |
342 | @@ -19,8 +19,14 @@ |
343 | |
344 | #include <qpa/qplatformclipboard.h> |
345 | |
346 | -class UbuntuClipboard : public QPlatformClipboard |
347 | +#include <QMimeData> |
348 | +#include <QPointer> |
349 | +class QDBusInterface; |
350 | +class QDBusPendingCallWatcher; |
351 | + |
352 | +class UbuntuClipboard : public QObject, public QPlatformClipboard |
353 | { |
354 | + Q_OBJECT |
355 | public: |
356 | UbuntuClipboard(); |
357 | virtual ~UbuntuClipboard(); |
358 | @@ -31,8 +37,31 @@ |
359 | bool supportsMode(QClipboard::Mode mode) const override; |
360 | bool ownsMode(QClipboard::Mode mode) const override; |
361 | |
362 | + void requestDBusClipboardContents(); |
363 | + |
364 | +private Q_SLOTS: |
365 | + void onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher*); |
366 | + void onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher*); |
367 | + void updateMimeData(const QByteArray &serializedMimeData); |
368 | + |
369 | private: |
370 | - QMimeData* mMimeData; |
371 | + void setupDBus(); |
372 | + |
373 | + QByteArray serializeMimeData(QMimeData *mimeData) const; |
374 | + QMimeData *deserializeMimeData(const QByteArray &serializedMimeData) const; |
375 | + |
376 | + void setDBusClipboardContents(const QByteArray &clipboardContents); |
377 | + |
378 | + QMimeData *mMimeData; |
379 | + bool mIsOutdated; |
380 | + |
381 | + QPointer<QDBusInterface> mDBusClipboard; |
382 | + |
383 | + QPointer<QDBusPendingCallWatcher> mPendingGetContentsCall; |
384 | + QPointer<QDBusPendingCallWatcher> mPendingSetContentsCall; |
385 | + |
386 | + bool mUpdatesDisabled; |
387 | + bool mDBusSetupDone; |
388 | }; |
389 | |
390 | #endif // UBUNTU_CLIPBOARD_H |
391 | |
392 | === modified file 'src/ubuntumirclient/input.cpp' |
393 | --- src/ubuntumirclient/input.cpp 2014-08-14 09:45:04 +0000 |
394 | +++ src/ubuntumirclient/input.cpp 2014-09-23 11:49:39 +0000 |
395 | @@ -160,6 +160,7 @@ |
396 | } |
397 | |
398 | #ifndef QT_NO_DEBUG |
399 | +/* |
400 | static const char* nativeEventTypeToStr(int eventType) |
401 | { |
402 | switch (eventType) { |
403 | @@ -178,6 +179,7 @@ |
404 | return "INVALID!"; |
405 | } |
406 | } |
407 | +*/ |
408 | #endif |
409 | |
410 | void UbuntuInput::customEvent(QEvent* event) |
411 | @@ -199,7 +201,7 @@ |
412 | return; |
413 | } |
414 | |
415 | - DLOG("UbuntuInput::customEvent(type=%s)", nativeEventTypeToStr(nativeEvent->type)); |
416 | + //DLOG("UbuntuInput::customEvent(type=%s)", nativeEventTypeToStr(nativeEvent->type)); |
417 | |
418 | // Event dispatching. |
419 | switch (nativeEvent->type) { |
420 | |
421 | === modified file 'src/ubuntumirclient/integration.cpp' |
422 | --- src/ubuntumirclient/integration.cpp 2014-08-05 16:02:48 +0000 |
423 | +++ src/ubuntumirclient/integration.cpp 2014-09-23 11:49:39 +0000 |
424 | @@ -108,7 +108,6 @@ |
425 | |
426 | UbuntuClientIntegration::~UbuntuClientIntegration() |
427 | { |
428 | - delete mClipboard; |
429 | delete mInput; |
430 | delete mInputContext; |
431 | delete mScreen; |
432 | @@ -157,7 +156,7 @@ |
433 | QPlatformWindow* UbuntuClientIntegration::createPlatformWindow(QWindow* window) |
434 | { |
435 | QPlatformWindow* platformWindow = new UbuntuWindow( |
436 | - window, static_cast<UbuntuScreen*>(mScreen), mInput, mInstance); |
437 | + window, mClipboard, static_cast<UbuntuScreen*>(mScreen), mInput, mInstance); |
438 | platformWindow->requestActivateWindow(); |
439 | return platformWindow; |
440 | } |
441 | @@ -233,3 +232,8 @@ |
442 | } |
443 | return QPlatformIntegration::styleHint(hint); |
444 | } |
445 | + |
446 | +QPlatformClipboard* UbuntuClientIntegration::clipboard() const |
447 | +{ |
448 | + return mClipboard.data(); |
449 | +} |
450 | |
451 | === modified file 'src/ubuntumirclient/integration.h' |
452 | --- src/ubuntumirclient/integration.h 2014-08-05 16:02:48 +0000 |
453 | +++ src/ubuntumirclient/integration.h 2014-09-23 11:49:39 +0000 |
454 | @@ -18,6 +18,7 @@ |
455 | #define UBUNTU_CLIENT_INTEGRATION_H |
456 | |
457 | #include <qpa/qplatformintegration.h> |
458 | +#include <QSharedPointer> |
459 | |
460 | #include "platformservices.h" |
461 | |
462 | @@ -27,6 +28,7 @@ |
463 | #include <ubuntu/application/ui/options.h> |
464 | #include <ubuntu/application/ui/session.h> |
465 | |
466 | +class UbuntuClipboard; |
467 | class UbuntuInput; |
468 | class UbuntuScreen; |
469 | |
470 | @@ -48,7 +50,7 @@ |
471 | QPlatformServices *services() const override; |
472 | QPlatformWindow* createPlatformWindow(QWindow* window) const override; |
473 | QPlatformInputContext* inputContext() const override { return mInputContext; } |
474 | - QPlatformClipboard* clipboard() const override { return mClipboard; } |
475 | + QPlatformClipboard* clipboard() const override; |
476 | |
477 | QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context); |
478 | QPlatformWindow* createPlatformWindow(QWindow* window); |
479 | @@ -66,7 +68,7 @@ |
480 | UbuntuScreen* mScreen; |
481 | UbuntuInput* mInput; |
482 | QPlatformInputContext* mInputContext; |
483 | - QPlatformClipboard* mClipboard; |
484 | + QSharedPointer<UbuntuClipboard> mClipboard; |
485 | qreal mScaleFactor; |
486 | |
487 | // Platform API stuff |
488 | |
489 | === modified file 'src/ubuntumirclient/ubuntumirclient.pro' |
490 | --- src/ubuntumirclient/ubuntumirclient.pro 2014-08-14 13:18:24 +0000 |
491 | +++ src/ubuntumirclient/ubuntumirclient.pro 2014-09-23 11:49:39 +0000 |
492 | @@ -2,7 +2,7 @@ |
493 | TEMPLATE = lib |
494 | |
495 | QT -= gui |
496 | -QT += core-private gui-private platformsupport-private sensors |
497 | +QT += core-private gui-private platformsupport-private sensors dbus |
498 | |
499 | CONFIG += plugin no_keywords qpa/genericunixfontdatabase |
500 | |
501 | |
502 | === modified file 'src/ubuntumirclient/window.cpp' |
503 | --- src/ubuntumirclient/window.cpp 2014-08-08 14:04:13 +0000 |
504 | +++ src/ubuntumirclient/window.cpp 2014-09-23 11:49:39 +0000 |
505 | @@ -15,6 +15,7 @@ |
506 | */ |
507 | |
508 | // Local |
509 | +#include "clipboard.h" |
510 | #include "input.h" |
511 | #include "window.h" |
512 | #include "screen.h" |
513 | @@ -55,17 +56,17 @@ |
514 | QSize bufferSize; |
515 | QSize targetBufferSize; |
516 | QMutex mutex; |
517 | + QSharedPointer<UbuntuClipboard> clipboard; |
518 | }; |
519 | |
520 | static void eventCallback(void* context, const WindowEvent* event) |
521 | { |
522 | - DLOG("eventCallback (context=%p, event=%p)", context, event); |
523 | DASSERT(context != NULL); |
524 | UbuntuWindow* platformWindow = static_cast<UbuntuWindow*>(context); |
525 | platformWindow->priv()->input->postEvent(platformWindow, event); |
526 | } |
527 | |
528 | -UbuntuWindow::UbuntuWindow(QWindow* w, UbuntuScreen* screen, |
529 | +UbuntuWindow::UbuntuWindow(QWindow* w, QSharedPointer<UbuntuClipboard> clipboard, UbuntuScreen* screen, |
530 | UbuntuInput* input, UApplicationInstance* instance) |
531 | : QObject(nullptr), QPlatformWindow(w) |
532 | { |
533 | @@ -77,6 +78,7 @@ |
534 | d->input = input; |
535 | d->state = window()->windowState(); |
536 | d->uaInstance = instance; |
537 | + d->clipboard = clipboard; |
538 | |
539 | static int id = 1; |
540 | d->id = id++; |
541 | @@ -265,6 +267,17 @@ |
542 | { |
543 | LOG("UbuntuWindow::handleSurfaceFocusChange(focused=%s)", focused ? "true" : "false"); |
544 | QWindow *activatedWindow = focused ? window() : nullptr; |
545 | + |
546 | + // System clipboard contents might have changed while this window was unfocused and wihtout |
547 | + // this process getting notified about it because it might have been suspended (due to |
548 | + // application lifecycle policies), thus unable to listen to any changes notified through |
549 | + // D-Bus. |
550 | + // Therefore let's ensure we are up to date with the system clipboard now that we are getting |
551 | + // focused again. |
552 | + if (focused) { |
553 | + d->clipboard->requestDBusClipboardContents(); |
554 | + } |
555 | + |
556 | QWindowSystemInterface::handleWindowActivated(activatedWindow, Qt::ActiveWindowFocusReason); |
557 | } |
558 | |
559 | |
560 | === modified file 'src/ubuntumirclient/window.h' |
561 | --- src/ubuntumirclient/window.h 2014-08-08 12:05:21 +0000 |
562 | +++ src/ubuntumirclient/window.h 2014-09-23 11:49:39 +0000 |
563 | @@ -18,7 +18,9 @@ |
564 | #define UBUNTU_WINDOW_H |
565 | |
566 | #include <qpa/qplatformwindow.h> |
567 | +#include <QSharedPointer> |
568 | |
569 | +class UbuntuClipboard; |
570 | class UbuntuInput; |
571 | class UbuntuScreen; |
572 | class UbuntuWindowPrivate; |
573 | @@ -27,7 +29,7 @@ |
574 | { |
575 | Q_OBJECT |
576 | public: |
577 | - UbuntuWindow(QWindow* w, UbuntuScreen* screen, |
578 | + UbuntuWindow(QWindow* w, QSharedPointer<UbuntuClipboard> clipboard, UbuntuScreen* screen, |
579 | UbuntuInput* input, void* instance); |
580 | virtual ~UbuntuWindow(); |
581 |
PASSED: Continuous integration, rev:243 jenkins. qa.ubuntu. com/job/ qtubuntu- ci/162/ jenkins. qa.ubuntu. com/job/ qtubuntu- utopic- armhf-ci/ 28 jenkins. qa.ubuntu. com/job/ qtubuntu- utopic- armhf-ci/ 28/artifact/ work/output/ *zip*/output. zip
http://
Executed test runs:
SUCCESS: http://
deb: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/qtubuntu- ci/162/ rebuild
http://