Merge lp:~townsend/libertine/fix-pasted-xmir-rootless into lp:libertine
- fix-pasted-xmir-rootless
- Merge into devel
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Larry Price | ||||
Approved revision: | 441 | ||||
Merged at revision: | 444 | ||||
Proposed branch: | lp:~townsend/libertine/fix-pasted-xmir-rootless | ||||
Merge into: | lp:libertine | ||||
Diff against target: |
248 lines (+90/-53) 2 files modified
pasted/pasted.cpp (+77/-48) pasted/pasted.h (+13/-5) |
||||
To merge this branch: | bzr merge lp:~townsend/libertine/fix-pasted-xmir-rootless | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Libertine CI Bot | continuous-integration | Approve | |
Larry Price | Approve | ||
Review via email: mp+319507@code.launchpad.net |
Commit message
Fix pasted to work with rootless Xmir.
Description of the change
Libertine CI Bot (libertine-ci-bot) wrote : | # |
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:434
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Larry Price (larryprice) wrote : | # |
left some inline presents for you
- 435. By Christopher Townsend
-
Some cleanup based on review.
- 436. By Christopher Townsend
-
Merge lp:libertine.
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:436
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 437. By Christopher Townsend
-
Another bit of cleanup.
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:437
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Larry Price (larryprice) wrote : | # |
Whoops, guess I'm going to leave this open until ChrisTownsend returns...
This works for internal copy/paste, but does not work between apps. Is that expected for now and can you link the relevant bugs to this one when you get back?
- 438. By Christopher Townsend
-
Merge lp:libertine.
- 439. By Christopher Townsend
-
Merge lp:libertine.
- 440. By Christopher Townsend
-
Revert libertine.pot.
Libertine CI Bot (libertine-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:439
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:440
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:439
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
- 441. By Christopher Townsend
-
Add closing the disaply in the XEventWorker dtor.
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:441
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'pasted/pasted.cpp' | |||
2 | --- pasted/pasted.cpp 2017-03-20 19:22:25 +0000 | |||
3 | +++ pasted/pasted.cpp 2017-03-20 20:42:05 +0000 | |||
4 | @@ -36,9 +36,8 @@ | |||
5 | 36 | constexpr auto UNITY_FOCUSINFO_METHOD = "isSurfaceFocused"; | 36 | constexpr auto UNITY_FOCUSINFO_METHOD = "isSurfaceFocused"; |
6 | 37 | 37 | ||
7 | 38 | 38 | ||
9 | 39 | static QString getPersistentSurfaceId() | 39 | static QString getPersistentSurfaceId(Display *dpy, const Window& id) |
10 | 40 | { | 40 | { |
11 | 41 | Display *dpy = XOpenDisplay(NULL); | ||
12 | 42 | Atom prop = XInternAtom(dpy, MIR_WM_PERSISTENT_ID, 0), | 41 | Atom prop = XInternAtom(dpy, MIR_WM_PERSISTENT_ID, 0), |
13 | 43 | type; // unused | 42 | type; // unused |
14 | 44 | int form, // unused | 43 | int form, // unused |
15 | @@ -48,7 +47,7 @@ | |||
16 | 48 | unsigned char *data = nullptr; | 47 | unsigned char *data = nullptr; |
17 | 49 | QString persistentSurfaceId; | 48 | QString persistentSurfaceId; |
18 | 50 | 49 | ||
20 | 51 | status = XGetWindowProperty(dpy, XDefaultRootWindow(dpy), prop, 0, 1024, 0, | 50 | status = XGetWindowProperty(dpy, id, prop, 0, 1024, 0, |
21 | 52 | XA_STRING, &type, &form, &len, &remain, &data); | 51 | XA_STRING, &type, &form, &len, &remain, &data); |
22 | 53 | 52 | ||
23 | 54 | if (status) | 53 | if (status) |
24 | @@ -60,14 +59,13 @@ | |||
25 | 60 | persistentSurfaceId = (const char *)data; | 59 | persistentSurfaceId = (const char *)data; |
26 | 61 | } | 60 | } |
27 | 62 | 61 | ||
28 | 63 | XCloseDisplay(dpy); | ||
29 | 64 | XFree(data); | 62 | XFree(data); |
30 | 65 | 63 | ||
31 | 66 | return persistentSurfaceId; | 64 | return persistentSurfaceId; |
32 | 67 | } | 65 | } |
33 | 68 | 66 | ||
34 | 69 | 67 | ||
36 | 70 | void checkXServer() | 68 | Display *checkXServer() |
37 | 71 | { | 69 | { |
38 | 72 | char *display = getenv("DISPLAY"); | 70 | char *display = getenv("DISPLAY"); |
39 | 73 | 71 | ||
40 | @@ -84,55 +82,86 @@ | |||
41 | 84 | exit(-1); | 82 | exit(-1); |
42 | 85 | } | 83 | } |
43 | 86 | 84 | ||
47 | 87 | XCloseDisplay(dpy); | 85 | return dpy; |
45 | 88 | |||
46 | 89 | return; | ||
48 | 90 | } | 86 | } |
49 | 91 | 87 | ||
50 | 92 | } //anonymous namespace | 88 | } //anonymous namespace |
51 | 93 | 89 | ||
52 | 94 | 90 | ||
53 | 91 | XEventWorker:: | ||
54 | 92 | XEventWorker(Display *dpy) | ||
55 | 93 | : dpy_(dpy) | ||
56 | 94 | { | ||
57 | 95 | unityFocus_ = new QDBusInterface(UNITY_FOCUSINFO_SERVICE, | ||
58 | 96 | UNITY_FOCUSINFO_PATH, | ||
59 | 97 | UNITY_FOCUSINFO_INTERFACE, | ||
60 | 98 | QDBusConnection::sessionBus(), | ||
61 | 99 | this); | ||
62 | 100 | } | ||
63 | 101 | |||
64 | 102 | |||
65 | 103 | XEventWorker:: | ||
66 | 104 | ~XEventWorker() | ||
67 | 105 | { | ||
68 | 106 | XCloseDisplay(dpy_); | ||
69 | 107 | } | ||
70 | 108 | |||
71 | 109 | |||
72 | 110 | bool XEventWorker:: | ||
73 | 111 | isSurfaceFocused(const Window& focus_window) | ||
74 | 112 | { | ||
75 | 113 | surfaceId_ = getPersistentSurfaceId(dpy_, focus_window); | ||
76 | 114 | |||
77 | 115 | QDBusReply<bool> isFocused = unityFocus_->call(UNITY_FOCUSINFO_METHOD, surfaceId_); | ||
78 | 116 | |||
79 | 117 | return isFocused; | ||
80 | 118 | } | ||
81 | 119 | |||
82 | 120 | |||
83 | 95 | void XEventWorker:: | 121 | void XEventWorker:: |
84 | 96 | checkForAppFocus() | 122 | checkForAppFocus() |
85 | 97 | { | 123 | { |
86 | 98 | bool hasFocus = false; | 124 | bool hasFocus = false; |
87 | 125 | int focus_state; | ||
88 | 126 | Window focus_window; | ||
89 | 127 | |||
90 | 128 | XGetInputFocus(dpy_, &focus_window, &focus_state); | ||
91 | 129 | |||
92 | 130 | if (focus_window > PointerRoot) | ||
93 | 131 | { | ||
94 | 132 | if (isSurfaceFocused(focus_window)) | ||
95 | 133 | { | ||
96 | 134 | focusChanged(surfaceId_); | ||
97 | 135 | hasFocus = true; | ||
98 | 136 | } | ||
99 | 137 | } | ||
100 | 138 | |||
101 | 139 | XSelectInput(dpy_, XDefaultRootWindow(dpy_), FocusChangeMask); | ||
102 | 140 | |||
103 | 141 | bool focused = false; | ||
104 | 99 | XEvent event; | 142 | XEvent event; |
105 | 100 | 143 | ||
106 | 101 | QDBusInterface *unityFocus = new QDBusInterface(UNITY_FOCUSINFO_SERVICE, | ||
107 | 102 | UNITY_FOCUSINFO_PATH, | ||
108 | 103 | UNITY_FOCUSINFO_INTERFACE, | ||
109 | 104 | QDBusConnection::sessionBus(), | ||
110 | 105 | this); | ||
111 | 106 | |||
112 | 107 | QString surfaceId = getPersistentSurfaceId(); | ||
113 | 108 | |||
114 | 109 | QDBusReply<bool> isFocused = unityFocus->call(UNITY_FOCUSINFO_METHOD, surfaceId); | ||
115 | 110 | |||
116 | 111 | if (isFocused == true) | ||
117 | 112 | { | ||
118 | 113 | focusChanged(); | ||
119 | 114 | hasFocus = true; | ||
120 | 115 | } | ||
121 | 116 | |||
122 | 117 | Display *dpy = XOpenDisplay(NULL); | ||
123 | 118 | XSelectInput(dpy, XDefaultRootWindow(dpy), FocusChangeMask); | ||
124 | 119 | |||
125 | 120 | while (1) | 144 | while (1) |
126 | 121 | { | 145 | { |
141 | 122 | XNextEvent(dpy, &event); | 146 | XNextEvent(dpy_, &event); |
142 | 123 | 147 | ||
143 | 124 | isFocused = unityFocus->call(UNITY_FOCUSINFO_METHOD, surfaceId); | 148 | XGetInputFocus(dpy_, &focus_window, &focus_state); |
144 | 125 | 149 | ||
145 | 126 | if (hasFocus == false && isFocused == true) | 150 | if (focus_window > PointerRoot) |
146 | 127 | { | 151 | { |
147 | 128 | qDebug() << "Surface is focused"; | 152 | focused = isSurfaceFocused(focus_window); |
148 | 129 | focusChanged(); | 153 | |
149 | 130 | hasFocus = true; | 154 | if (hasFocus == false && focused == true) |
150 | 131 | } | 155 | { |
151 | 132 | else if (hasFocus == true && isFocused == false) | 156 | qDebug() << "Surface is focused"; |
152 | 133 | { | 157 | focusChanged(surfaceId_); |
153 | 134 | qDebug() << "Surface lost focus"; | 158 | hasFocus = true; |
154 | 135 | hasFocus = false; | 159 | } |
155 | 160 | else if (hasFocus == true && focused == false) | ||
156 | 161 | { | ||
157 | 162 | qDebug() << "Surface lost focus"; | ||
158 | 163 | hasFocus = false; | ||
159 | 164 | } | ||
160 | 136 | } | 165 | } |
161 | 137 | } | 166 | } |
162 | 138 | } | 167 | } |
163 | @@ -253,19 +282,19 @@ | |||
164 | 253 | 282 | ||
165 | 254 | 283 | ||
166 | 255 | void Pasted:: | 284 | void Pasted:: |
168 | 256 | setPersistentSurfaceId() | 285 | setPersistentSurfaceId(const QString& surfaceId) |
169 | 257 | { | 286 | { |
171 | 258 | if (persistentSurfaceId_.isEmpty()) | 287 | if (persistentSurfaceId_ != surfaceId) |
172 | 259 | { | 288 | { |
174 | 260 | persistentSurfaceId_ = getPersistentSurfaceId(); | 289 | persistentSurfaceId_ = surfaceId; |
175 | 261 | } | 290 | } |
176 | 262 | } | 291 | } |
177 | 263 | 292 | ||
178 | 264 | 293 | ||
179 | 265 | void Pasted:: | 294 | void Pasted:: |
181 | 266 | appFocused() | 295 | appFocused(const QString& surfaceId) |
182 | 267 | { | 296 | { |
184 | 268 | setPersistentSurfaceId(); | 297 | setPersistentSurfaceId(surfaceId); |
185 | 269 | handleContentHubPasteboard(); | 298 | handleContentHubPasteboard(); |
186 | 270 | } | 299 | } |
187 | 271 | 300 | ||
188 | @@ -275,12 +304,12 @@ | |||
189 | 275 | { | 304 | { |
190 | 276 | qSetMessagePattern(QString("%{appname}: %{message}")); | 305 | qSetMessagePattern(QString("%{appname}: %{message}")); |
191 | 277 | 306 | ||
193 | 278 | checkXServer(); | 307 | Display *dpy = checkXServer(); |
194 | 279 | 308 | ||
195 | 280 | Pasted pasted(argc, argv); | 309 | Pasted pasted(argc, argv); |
196 | 281 | 310 | ||
197 | 282 | QThread t; | 311 | QThread t; |
199 | 283 | XEventWorker worker; | 312 | XEventWorker worker(dpy); |
200 | 284 | 313 | ||
201 | 285 | worker.moveToThread(&t); | 314 | worker.moveToThread(&t); |
202 | 286 | 315 | ||
203 | 287 | 316 | ||
204 | === modified file 'pasted/pasted.h' | |||
205 | --- pasted/pasted.h 2016-09-12 17:59:56 +0000 | |||
206 | +++ pasted/pasted.h 2017-03-20 20:42:05 +0000 | |||
207 | @@ -39,14 +39,22 @@ | |||
208 | 39 | Q_OBJECT | 39 | Q_OBJECT |
209 | 40 | 40 | ||
210 | 41 | public: | 41 | public: |
213 | 42 | XEventWorker() = default; | 42 | XEventWorker(Display *dpy); |
214 | 43 | virtual ~XEventWorker() = default; | 43 | virtual ~XEventWorker(); |
215 | 44 | |||
216 | 45 | private: | ||
217 | 46 | bool isSurfaceFocused(const Window& focus_window); | ||
218 | 44 | 47 | ||
219 | 45 | signals: | 48 | signals: |
221 | 46 | void focusChanged(); | 49 | void focusChanged(const QString& surfaceId); |
222 | 47 | 50 | ||
223 | 48 | public slots: | 51 | public slots: |
224 | 49 | void checkForAppFocus(); | 52 | void checkForAppFocus(); |
225 | 53 | |||
226 | 54 | private: | ||
227 | 55 | Display *dpy_; | ||
228 | 56 | QDBusInterface *unityFocus_; | ||
229 | 57 | QString surfaceId_; | ||
230 | 50 | }; | 58 | }; |
231 | 51 | 59 | ||
232 | 52 | 60 | ||
233 | @@ -60,13 +68,13 @@ | |||
234 | 60 | virtual ~Pasted() = default; | 68 | virtual ~Pasted() = default; |
235 | 61 | 69 | ||
236 | 62 | public slots: | 70 | public slots: |
238 | 63 | void appFocused(); | 71 | void appFocused(const QString& surfaceId); |
239 | 64 | 72 | ||
240 | 65 | private: | 73 | private: |
241 | 66 | void updateLastMimeData(const QMimeData *source); | 74 | void updateLastMimeData(const QMimeData *source); |
242 | 67 | void updateXMimeData(const QMimeData *source); | 75 | void updateXMimeData(const QMimeData *source); |
243 | 68 | void handleContentHubPasteboard(); | 76 | void handleContentHubPasteboard(); |
245 | 69 | void setPersistentSurfaceId(); | 77 | void setPersistentSurfaceId(const QString& surfaceId); |
246 | 70 | 78 | ||
247 | 71 | static bool compareMimeData(const QMimeData *a, const QMimeData *b); | 79 | static bool compareMimeData(const QMimeData *a, const QMimeData *b); |
248 | 72 | static void copyMimeData(QMimeData& target, const QMimeData *source); | 80 | static void copyMimeData(QMimeData& target, const QMimeData *source); |
FAILED: Continuous integration, rev:434 /jenkins. canonical. com/libertine/ job/lp- libertine- ci/458/ /jenkins. canonical. com/libertine/ job/build/ 845/console /jenkins. canonical. com/libertine/ job/build- 0-fetch/ 855 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= xenial+ overlay/ 847 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= xenial+ overlay/ 847/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= zesty/847 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= zesty/847/ artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= xenial+ overlay/ 847/console /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= zesty/847 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= zesty/847/ artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/libertine/ job/lp- libertine- ci/458/ rebuild
https:/