Merge lp:~townsend/libertine/fix-focus-tracking into lp:libertine
- fix-focus-tracking
- Merge into devel
Status: | Merged |
---|---|
Approved by: | Larry Price |
Approved revision: | 303 |
Merged at revision: | 300 |
Proposed branch: | lp:~townsend/libertine/fix-focus-tracking |
Merge into: | lp:libertine |
Diff against target: |
304 lines (+132/-63) 5 files modified
CMakeLists.txt (+0/-1) debian/control (+0/-1) pasted/CMakeLists.txt (+1/-1) pasted/pasted.cpp (+111/-57) pasted/pasted.h (+20/-3) |
To merge this branch: | bzr merge lp:~townsend/libertine/fix-focus-tracking |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Libertine CI Bot | continuous-integration | Approve | |
Larry Price | Approve | ||
Review via email:
|
Commit message
pasted: Switch to using an X event based model with a worker thread instead of the QTimer polling method. This avoids races and missed focus status.
Description of the change
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Libertine CI Bot (libertine-ci-bot) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:300
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
None: 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:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Larry Price (larryprice) wrote : | # |
few easy inlines - i'll try to verify that it still works in the morning
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Christopher Townsend (townsend) wrote : | # |
Thanks for reviewing. I addressed your question and will make some changes.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:301
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
None: 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:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:302
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
None: 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:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Larry Price (larryprice) wrote : | # |
some inline suggestions. wrapping up an sbuild of the arm version now to test on frieza.
- 303. By Christopher Townsend
-
Changes and fixes based on feedback.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Larry Price (larryprice) wrote : | # |
lgtm! very nice updates
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Libertine CI Bot (libertine-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:303
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
None: 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:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2016-09-06 12:36:47 +0000 | |||
3 | +++ CMakeLists.txt 2016-09-08 18:47:27 +0000 | |||
4 | @@ -20,7 +20,6 @@ | |||
5 | 20 | find_package(Qt5Gui REQUIRED) | 20 | find_package(Qt5Gui REQUIRED) |
6 | 21 | find_package(Qt5Quick REQUIRED) | 21 | find_package(Qt5Quick REQUIRED) |
7 | 22 | find_package(Qt5Widgets REQUIRED) | 22 | find_package(Qt5Widgets REQUIRED) |
8 | 23 | find_package(Qt5X11Extras REQUIRED) | ||
9 | 24 | find_package(Gettext REQUIRED) | 23 | find_package(Gettext REQUIRED) |
10 | 25 | find_package(Intltool REQUIRED) | 24 | find_package(Intltool REQUIRED) |
11 | 26 | find_package(X11 REQUIRED) | 25 | find_package(X11 REQUIRED) |
12 | 27 | 26 | ||
13 | === modified file 'debian/control' | |||
14 | --- debian/control 2016-09-06 12:36:47 +0000 | |||
15 | +++ debian/control 2016-09-08 18:47:27 +0000 | |||
16 | @@ -13,7 +13,6 @@ | |||
17 | 13 | libgirepository1.0-dev, | 13 | libgirepository1.0-dev, |
18 | 14 | libglib2.0-dev, | 14 | libglib2.0-dev, |
19 | 15 | libgtest-dev, | 15 | libgtest-dev, |
20 | 16 | libqt5x11extras5-dev, | ||
21 | 17 | libx11-dev, | 16 | libx11-dev, |
22 | 18 | lsb-release, | 17 | lsb-release, |
23 | 19 | python3-apt, | 18 | python3-apt, |
24 | 20 | 19 | ||
25 | === modified file 'pasted/CMakeLists.txt' | |||
26 | --- pasted/CMakeLists.txt 2016-08-10 12:23:31 +0000 | |||
27 | +++ pasted/CMakeLists.txt 2016-09-08 18:47:27 +0000 | |||
28 | @@ -6,5 +6,5 @@ | |||
29 | 6 | 6 | ||
30 | 7 | qt5_use_modules(pasted DBus) | 7 | qt5_use_modules(pasted DBus) |
31 | 8 | 8 | ||
33 | 9 | target_link_libraries(pasted Qt5::Core Qt5::Gui Qt5::Widgets Qt5::X11Extras content-hub X11) | 9 | target_link_libraries(pasted Qt5::Core Qt5::Gui Qt5::Widgets content-hub X11) |
34 | 10 | install(TARGETS pasted RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) | 10 | install(TARGETS pasted RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) |
35 | 11 | 11 | ||
36 | === modified file 'pasted/pasted.cpp' | |||
37 | --- pasted/pasted.cpp 2016-09-01 20:01:52 +0000 | |||
38 | +++ pasted/pasted.cpp 2016-09-08 18:47:27 +0000 | |||
39 | @@ -19,12 +19,102 @@ | |||
40 | 19 | 19 | ||
41 | 20 | #include "pasted.h" | 20 | #include "pasted.h" |
42 | 21 | 21 | ||
43 | 22 | #include <QDBusInterface> | ||
44 | 22 | #include <QDebug> | 23 | #include <QDebug> |
45 | 24 | #include <QThread> | ||
46 | 23 | 25 | ||
47 | 24 | #include <QX11Info> | ||
48 | 25 | #include <X11/Xatom.h> | 26 | #include <X11/Xatom.h> |
49 | 26 | 27 | ||
50 | 27 | 28 | ||
51 | 29 | namespace | ||
52 | 30 | { | ||
53 | 31 | |||
54 | 32 | constexpr auto MIR_WM_PERSISTENT_ID = "_MIR_WM_PERSISTENT_ID"; | ||
55 | 33 | constexpr auto UNITY_FOCUSINFO_SERVICE = "com.canonical.Unity.FocusInfo"; | ||
56 | 34 | constexpr auto UNITY_FOCUSINFO_PATH = "/com/canonical/Unity/FocusInfo"; | ||
57 | 35 | constexpr auto UNITY_FOCUSINFO_INTERFACE = "com.canonical.Unity.FocusInfo"; | ||
58 | 36 | constexpr auto UNITY_FOCUSINFO_METHOD = "isSurfaceFocused"; | ||
59 | 37 | |||
60 | 38 | |||
61 | 39 | static QString getPersistentSurfaceId() | ||
62 | 40 | { | ||
63 | 41 | Display *dpy = XOpenDisplay(NULL); | ||
64 | 42 | Atom prop = XInternAtom(dpy, MIR_WM_PERSISTENT_ID, 0), | ||
65 | 43 | type; // unused | ||
66 | 44 | int form, // unused | ||
67 | 45 | status; | ||
68 | 46 | unsigned long remain, // unused | ||
69 | 47 | len; // unused | ||
70 | 48 | unsigned char *data = nullptr; | ||
71 | 49 | QString persistentSurfaceId; | ||
72 | 50 | |||
73 | 51 | status = XGetWindowProperty(dpy, XDefaultRootWindow(dpy), prop, 0, 1024, 0, | ||
74 | 52 | XA_STRING, &type, &form, &len, &remain, &data); | ||
75 | 53 | |||
76 | 54 | if (status) | ||
77 | 55 | { | ||
78 | 56 | qDebug() << "Failure retrieving the persistentSurfaceID!"; | ||
79 | 57 | } | ||
80 | 58 | else | ||
81 | 59 | { | ||
82 | 60 | persistentSurfaceId = (const char *)data; | ||
83 | 61 | } | ||
84 | 62 | |||
85 | 63 | XCloseDisplay(dpy); | ||
86 | 64 | XFree(data); | ||
87 | 65 | |||
88 | 66 | return persistentSurfaceId; | ||
89 | 67 | } | ||
90 | 68 | |||
91 | 69 | } //anonymous namespace | ||
92 | 70 | |||
93 | 71 | |||
94 | 72 | void XEventWorker:: | ||
95 | 73 | checkForAppFocus() | ||
96 | 74 | { | ||
97 | 75 | bool hasFocus = false; | ||
98 | 76 | XEvent event; | ||
99 | 77 | |||
100 | 78 | QDBusInterface *unityFocus = new QDBusInterface(UNITY_FOCUSINFO_SERVICE, | ||
101 | 79 | UNITY_FOCUSINFO_PATH, | ||
102 | 80 | UNITY_FOCUSINFO_INTERFACE, | ||
103 | 81 | QDBusConnection::sessionBus(), | ||
104 | 82 | this); | ||
105 | 83 | |||
106 | 84 | QString surfaceId = getPersistentSurfaceId(); | ||
107 | 85 | |||
108 | 86 | QDBusReply<bool> isFocused = unityFocus->call(UNITY_FOCUSINFO_METHOD, surfaceId); | ||
109 | 87 | |||
110 | 88 | if (isFocused == true) | ||
111 | 89 | { | ||
112 | 90 | focusChanged(); | ||
113 | 91 | hasFocus = true; | ||
114 | 92 | } | ||
115 | 93 | |||
116 | 94 | Display *dpy = XOpenDisplay(NULL); | ||
117 | 95 | XSelectInput(dpy, XDefaultRootWindow(dpy), FocusChangeMask); | ||
118 | 96 | |||
119 | 97 | while (1) | ||
120 | 98 | { | ||
121 | 99 | XNextEvent(dpy, &event); | ||
122 | 100 | |||
123 | 101 | isFocused = unityFocus->call(UNITY_FOCUSINFO_METHOD, surfaceId); | ||
124 | 102 | |||
125 | 103 | if (hasFocus == false && isFocused == true) | ||
126 | 104 | { | ||
127 | 105 | qDebug() << "Surface is focused"; | ||
128 | 106 | focusChanged(); | ||
129 | 107 | hasFocus = true; | ||
130 | 108 | } | ||
131 | 109 | else if (hasFocus == true && isFocused == false) | ||
132 | 110 | { | ||
133 | 111 | qDebug() << "Surface lost focus"; | ||
134 | 112 | hasFocus = false; | ||
135 | 113 | } | ||
136 | 114 | } | ||
137 | 115 | } | ||
138 | 116 | |||
139 | 117 | |||
140 | 28 | Pasted:: | 118 | Pasted:: |
141 | 29 | Pasted(int argc, char** argv) | 119 | Pasted(int argc, char** argv) |
142 | 30 | : QApplication(argc, argv) | 120 | : QApplication(argc, argv) |
143 | @@ -32,15 +122,9 @@ | |||
144 | 32 | , content_hub_(cuc::Hub::Client::instance()) | 122 | , content_hub_(cuc::Hub::Client::instance()) |
145 | 33 | , mimeDataX_(new QMimeData) | 123 | , mimeDataX_(new QMimeData) |
146 | 34 | , lastMimeData_() | 124 | , lastMimeData_() |
147 | 35 | , rootWindowHasFocus_(false) | ||
148 | 36 | , firstSeenWindow_(None) | ||
149 | 37 | { | 125 | { |
150 | 38 | setApplicationName("pasted"); | 126 | setApplicationName("pasted"); |
151 | 39 | 127 | ||
152 | 40 | QTimer *timer = new QTimer(this); | ||
153 | 41 | connect(timer, &QTimer::timeout, this, &Pasted::checkForAppFocus); | ||
154 | 42 | timer->start(400); | ||
155 | 43 | |||
156 | 44 | connect(clipboard_, &QClipboard::dataChanged, this, &Pasted::handleXClipboard); | 128 | connect(clipboard_, &QClipboard::dataChanged, this, &Pasted::handleXClipboard); |
157 | 45 | } | 129 | } |
158 | 46 | 130 | ||
159 | @@ -81,36 +165,6 @@ | |||
160 | 81 | } | 165 | } |
161 | 82 | 166 | ||
162 | 83 | 167 | ||
163 | 84 | void Pasted:: | ||
164 | 85 | checkForAppFocus() | ||
165 | 86 | { | ||
166 | 87 | Window w; | ||
167 | 88 | int revert_to; // unused | ||
168 | 89 | |||
169 | 90 | XGetInputFocus(QX11Info::display(), &w, &revert_to); | ||
170 | 91 | |||
171 | 92 | if (firstSeenWindow_ == None && w != None) | ||
172 | 93 | { | ||
173 | 94 | firstSeenWindow_ = w; | ||
174 | 95 | } | ||
175 | 96 | |||
176 | 97 | if (w == None && rootWindowHasFocus_ == true) | ||
177 | 98 | { | ||
178 | 99 | qDebug() << "Xmir lost focus"; | ||
179 | 100 | rootWindowHasFocus_ = false; | ||
180 | 101 | } | ||
181 | 102 | else if ((w == PointerRoot || | ||
182 | 103 | (w && firstSeenWindow_ == PointerRoot)) | ||
183 | 104 | && rootWindowHasFocus_ == false) | ||
184 | 105 | { | ||
185 | 106 | qDebug() << "Xmir gained focus"; | ||
186 | 107 | rootWindowHasFocus_ = true; | ||
187 | 108 | setPersistentSurfaceId(); | ||
188 | 109 | handleContentHubPasteboard(); | ||
189 | 110 | } | ||
190 | 111 | } | ||
191 | 112 | |||
192 | 113 | |||
193 | 114 | bool Pasted:: | 168 | bool Pasted:: |
194 | 115 | compareMimeData(const QMimeData *a, const QMimeData *b) | 169 | compareMimeData(const QMimeData *a, const QMimeData *b) |
195 | 116 | { | 170 | { |
196 | @@ -180,29 +234,19 @@ | |||
197 | 180 | { | 234 | { |
198 | 181 | if (persistentSurfaceId_.isEmpty()) | 235 | if (persistentSurfaceId_.isEmpty()) |
199 | 182 | { | 236 | { |
219 | 183 | Atom prop = XInternAtom(QX11Info::display(), "_MIR_WM_PERSISTENT_ID", 0), | 237 | persistentSurfaceId_ = getPersistentSurfaceId(); |
201 | 184 | type; // unused | ||
202 | 185 | int form, // unused | ||
203 | 186 | status; | ||
204 | 187 | unsigned long remain, // unused | ||
205 | 188 | len; // unused | ||
206 | 189 | unsigned char *data; | ||
207 | 190 | status = XGetWindowProperty(QX11Info::display(), XDefaultRootWindow(QX11Info::display()), prop, | ||
208 | 191 | 0, 1024, 0, XA_STRING, &type, &form, &len, &remain, &data); | ||
209 | 192 | |||
210 | 193 | if (status) | ||
211 | 194 | { | ||
212 | 195 | qDebug() << "Failure retrieving the persistentSurfaceID!"; | ||
213 | 196 | } | ||
214 | 197 | else | ||
215 | 198 | { | ||
216 | 199 | qDebug() << "Setting persistentSurfaceId"; | ||
217 | 200 | persistentSurfaceId_ = (const char *)data; | ||
218 | 201 | } | ||
220 | 202 | } | 238 | } |
221 | 203 | } | 239 | } |
222 | 204 | 240 | ||
223 | 205 | 241 | ||
224 | 242 | void Pasted:: | ||
225 | 243 | appFocused() | ||
226 | 244 | { | ||
227 | 245 | setPersistentSurfaceId(); | ||
228 | 246 | handleContentHubPasteboard(); | ||
229 | 247 | } | ||
230 | 248 | |||
231 | 249 | |||
232 | 206 | int | 250 | int |
233 | 207 | main(int argc, char* argv[]) | 251 | main(int argc, char* argv[]) |
234 | 208 | { | 252 | { |
235 | @@ -210,5 +254,15 @@ | |||
236 | 210 | 254 | ||
237 | 211 | Pasted pasted(argc, argv); | 255 | Pasted pasted(argc, argv); |
238 | 212 | 256 | ||
240 | 213 | pasted.exec(); | 257 | QThread t; |
241 | 258 | XEventWorker worker; | ||
242 | 259 | |||
243 | 260 | worker.moveToThread(&t); | ||
244 | 261 | |||
245 | 262 | QObject::connect(&worker, &XEventWorker::focusChanged, &pasted, &Pasted::appFocused); | ||
246 | 263 | QObject::connect(&t, &QThread::started, &worker, &XEventWorker::checkForAppFocus); | ||
247 | 264 | |||
248 | 265 | t.start(); | ||
249 | 266 | |||
250 | 267 | return pasted.exec(); | ||
251 | 214 | } | 268 | } |
252 | 215 | 269 | ||
253 | === modified file 'pasted/pasted.h' | |||
254 | --- pasted/pasted.h 2016-08-29 15:33:05 +0000 | |||
255 | +++ pasted/pasted.h 2016-09-08 18:47:27 +0000 | |||
256 | @@ -33,6 +33,23 @@ | |||
257 | 33 | namespace cuc = com::ubuntu::content; | 33 | namespace cuc = com::ubuntu::content; |
258 | 34 | 34 | ||
259 | 35 | 35 | ||
260 | 36 | class XEventWorker | ||
261 | 37 | : public QObject | ||
262 | 38 | { | ||
263 | 39 | Q_OBJECT | ||
264 | 40 | |||
265 | 41 | public: | ||
266 | 42 | XEventWorker() = default; | ||
267 | 43 | virtual ~XEventWorker() = default; | ||
268 | 44 | |||
269 | 45 | signals: | ||
270 | 46 | void focusChanged(); | ||
271 | 47 | |||
272 | 48 | public slots: | ||
273 | 49 | void checkForAppFocus(); | ||
274 | 50 | }; | ||
275 | 51 | |||
276 | 52 | |||
277 | 36 | class Pasted | 53 | class Pasted |
278 | 37 | : public QApplication | 54 | : public QApplication |
279 | 38 | { | 55 | { |
280 | @@ -42,6 +59,9 @@ | |||
281 | 42 | Pasted(int argc, char** argv); | 59 | Pasted(int argc, char** argv); |
282 | 43 | virtual ~Pasted() = default; | 60 | virtual ~Pasted() = default; |
283 | 44 | 61 | ||
284 | 62 | public slots: | ||
285 | 63 | void appFocused(); | ||
286 | 64 | |||
287 | 45 | private: | 65 | private: |
288 | 46 | void updateLastMimeData(const QMimeData *source); | 66 | void updateLastMimeData(const QMimeData *source); |
289 | 47 | void updateXMimeData(const QMimeData *source); | 67 | void updateXMimeData(const QMimeData *source); |
290 | @@ -53,15 +73,12 @@ | |||
291 | 53 | 73 | ||
292 | 54 | private slots: | 74 | private slots: |
293 | 55 | void handleXClipboard(); | 75 | void handleXClipboard(); |
294 | 56 | void checkForAppFocus(); | ||
295 | 57 | 76 | ||
296 | 58 | private: | 77 | private: |
297 | 59 | QClipboard *clipboard_; | 78 | QClipboard *clipboard_; |
298 | 60 | cuc::Hub *content_hub_; | 79 | cuc::Hub *content_hub_; |
299 | 61 | QMimeData *mimeDataX_; | 80 | QMimeData *mimeDataX_; |
300 | 62 | std::unique_ptr<QMimeData> lastMimeData_; | 81 | std::unique_ptr<QMimeData> lastMimeData_; |
301 | 63 | bool rootWindowHasFocus_; | ||
302 | 64 | Window firstSeenWindow_; | ||
303 | 65 | QString persistentSurfaceId_; | 82 | QString persistentSurfaceId_; |
304 | 66 | }; | 83 | }; |
305 | 67 | 84 |
FAILED: Continuous integration, rev:300 /jenkins. canonical. com/libertine/ job/lp- libertine- ci/120/ /jenkins. canonical. com/libertine/ job/build/ 332 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=amd64, release= vivid+overlay, testname= default/ 265 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=amd64, release= xenial+ overlay, testname= default/ 265/console /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=amd64, release= yakkety, testname= default/ 265 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=i386, release= vivid+overlay, testname= default/ 265 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=i386, release= xenial+ overlay, testname= default/ 265 /jenkins. canonical. com/libertine/ job/test- 0-autopkgtest/ label=i386, release= yakkety, testname= default/ 265 /jenkins. canonical. com/libertine/ job/lp- generic- update- mp/252/ console /jenkins. canonical. com/libertine/ job/build- 0-fetch/ 334 /jenkins. canonical. com/libertine/ job/build- 1-sourcepkg/ release= vivid+overlay/ 317 /jenkins. canonical. com/libertine/ job/build- 1-sourcepkg/ release= xenial+ overlay/ 317 /jenkins. canonical. com/libertine/ job/build- 1-sourcepkg/ release= yakkety/ 317 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= vivid+overlay/ 316 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= vivid+overlay/ 316/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= xenial+ overlay/ 316 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= xenial+ overlay/ 316/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= yakkety/ 316 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=amd64, release= yakkety/ 316/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= vivid+overlay/ 316 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= vivid+overlay/ 316/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= xenial+ overlay/ 316 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= xenial+ overlay/ 316/artifact/ output/ *zip*/output. zip /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= yakkety/ 316 /jenkins. canonical. com/libertine/ job/build- 2-binpkg/ arch=i386, release= yakkety/ 316/artifact/ output/ *zip*/output. zip
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
None: 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:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/libertine/ job/lp- libertine- ci/120/ rebuild
https:/