Merge lp:~gerboland/qtubuntu/add--more-surface-type-support into lp:qtubuntu
- add--more-surface-type-support
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Nick Dedekind |
Approved revision: | 301 |
Merged at revision: | 355 |
Proposed branch: | lp:~gerboland/qtubuntu/add--more-surface-type-support |
Merge into: | lp:qtubuntu |
Prerequisite: | lp:~gerboland/qtubuntu/rasterGLSurface |
Diff against target: |
535 lines (+264/-155) 2 files modified
src/ubuntumirclient/input.cpp (+2/-0) src/ubuntumirclient/window.cpp (+262/-155) |
To merge this branch: | bzr merge lp:~gerboland/qtubuntu/add--more-surface-type-support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Nick Dedekind (community) | Approve | ||
Unity8 CI Bot | continuous-integration | Approve | |
Lukáš Tinkl (community) | Needs Information | ||
Review via email:
|
This proposal supersedes a proposal from 2016-10-13.
Commit message
Add support for more surface types and surface repositioning.
Helps Menus, Dropdowns and Tooltips to work with Mir
Description of the change

Unity8 CI Bot (unity8-ci-bot) wrote : Posted in a previous version of this proposal | # |

Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:297
https:/
Executed test runs:
Click here to trigger a rebuild:
https:/

Lukáš Tinkl (lukas-kde) wrote : | # |
Just a curious question inline :)

Gerry Boland (gerboland) wrote : | # |
> Wouldn't Qt:Tool better be represented by mir_surface_
Maybe, but while Mir has the surface Type in an enum, it doesn't let me create surfaces of type satellite yet (i.e. no mir_connection_
This mapping is not final, I expect it to change in future. That's why I put the mapping in an obvious method.

Gerry Boland (gerboland) wrote : | # |
Hmm, I've broken OSK with this. Marking WIP until I sort that out

Gerry Boland (gerboland) wrote : | # |
Fixed

Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:299
https:/
Executed test runs:
Click here to trigger a rebuild:
https:/

Daniel d'Andrada (dandrader) wrote : | # |
"""
void UbuntuWindow:
493 {
494 - qCDebug(
495 + qCDebug(
"""
https:/
- 300. By Gerry Boland
-
Fix for dialogs crash

Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:300
https:/
Executed test runs:
Click here to trigger a rebuild:
https:/

Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
- 301. By Gerry Boland
-
This is not python, fix comment

Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:301
https:/
Executed test runs:
Click here to trigger a rebuild:
https:/

Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:301
https:/
Executed test runs:
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:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/

Nick Dedekind (nick-dedekind) wrote : | # |
Couple of comments.

Gerry Boland (gerboland) : | # |

Nick Dedekind (nick-dedekind) wrote : | # |
Ok, if you're confident! LGTM
- 302. By Gerry Boland
-
Only set internal position in setGeometry, not size
- 303. By Gerry Boland
-
Merge trunk & resolve conflict

Gerry Boland (gerboland) wrote : | # |
Hmm, I can't land this as it will break Autopilot tests on phones :(
Preview Diff
1 | === modified file 'src/ubuntumirclient/input.cpp' |
2 | --- src/ubuntumirclient/input.cpp 2016-10-24 11:31:55 +0000 |
3 | +++ src/ubuntumirclient/input.cpp 2016-11-04 13:24:44 +0000 |
4 | @@ -503,6 +503,8 @@ |
5 | const auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x), |
6 | mir_pointer_event_axis_value(pev, mir_pointer_axis_y)); |
7 | |
8 | + mLastInputWindow = platformWindow; |
9 | + |
10 | switch (action) { |
11 | case mir_pointer_action_button_up: |
12 | case mir_pointer_action_button_down: |
13 | |
14 | === modified file 'src/ubuntumirclient/window.cpp' |
15 | --- src/ubuntumirclient/window.cpp 2016-10-24 11:32:31 +0000 |
16 | +++ src/ubuntumirclient/window.cpp 2016-11-04 13:24:44 +0000 |
17 | @@ -24,6 +24,7 @@ |
18 | #include "logging.h" |
19 | |
20 | #include <mir_toolkit/mir_client_library.h> |
21 | +#include <mir_toolkit/version.h> |
22 | |
23 | // Qt |
24 | #include <qpa/qwindowsysteminterface.h> |
25 | @@ -123,6 +124,23 @@ |
26 | Q_UNREACHABLE(); |
27 | } |
28 | |
29 | +const char *mirSurfaceTypeToStr(MirSurfaceType type) |
30 | +{ |
31 | + switch (type) { |
32 | + case mir_surface_type_normal: return "Normal"; /**< AKA "regular" */ |
33 | + case mir_surface_type_utility: return "Utility"; /**< AKA "floating regular" */ |
34 | + case mir_surface_type_dialog: return "Dialog"; |
35 | + case mir_surface_type_gloss: return "Gloss"; |
36 | + case mir_surface_type_freestyle: return "Freestyle"; |
37 | + case mir_surface_type_menu: return "Menu"; |
38 | + case mir_surface_type_inputmethod: return "Input Method"; /**< AKA "OSK" or handwriting etc. */ |
39 | + case mir_surface_type_satellite: return "Satellite"; /**< AKA "toolbox"/"toolbar" */ |
40 | + case mir_surface_type_tip: return "Tip"; /**< AKA "tooltip" */ |
41 | + case mir_surface_types: Q_UNREACHABLE(); |
42 | + } |
43 | + return ""; |
44 | +} |
45 | + |
46 | MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state) |
47 | { |
48 | switch (state) { |
49 | @@ -139,6 +157,27 @@ |
50 | return mir_surface_state_unknown; // should never be reached |
51 | } |
52 | |
53 | +MirSurfaceType qtWindowTypeToMirSurfaceType(Qt::WindowType type) |
54 | +{ |
55 | + switch (type & Qt::WindowType_Mask) { |
56 | + case Qt::Dialog: |
57 | + return mir_surface_type_dialog; |
58 | + case Qt::Sheet: |
59 | + case Qt::Drawer: |
60 | + return mir_surface_type_utility; |
61 | + case Qt::Popup: |
62 | + case Qt::Tool: |
63 | + return mir_surface_type_menu; |
64 | + case Qt::ToolTip: |
65 | + return mir_surface_type_tip; |
66 | + case Qt::SplashScreen: |
67 | + return mir_surface_type_freestyle; |
68 | + case Qt::Window: |
69 | + default: |
70 | + return mir_surface_type_normal; |
71 | + } |
72 | +} |
73 | + |
74 | WId makeId() |
75 | { |
76 | static int id = 1; |
77 | @@ -164,51 +203,93 @@ |
78 | return parent ? static_cast<UbuntuWindow *>(parent->handle()) : nullptr; |
79 | } |
80 | |
81 | -Spec makeSurfaceSpec(QWindow *window, UbuntuInput *input, MirPixelFormat pixelFormat, MirConnection *connection) |
82 | -{ |
83 | - const auto geom = window->geometry(); |
84 | - const int width = geom.width() > 0 ? geom.width() : 1; |
85 | - const int height = geom.height() > 0 ? geom.height() : 1; |
86 | +bool requiresParent(const MirSurfaceType type) |
87 | +{ |
88 | + switch (type) { |
89 | + case mir_surface_type_dialog: //FIXME - not quite what the specification dictates, but is what Mir's api dictates |
90 | + case mir_surface_type_utility: |
91 | + case mir_surface_type_gloss: |
92 | + case mir_surface_type_menu: |
93 | + case mir_surface_type_satellite: |
94 | + case mir_surface_type_tip: |
95 | + return true; |
96 | + default: |
97 | + return false; |
98 | + } |
99 | +} |
100 | + |
101 | +bool requiresParent(const Qt::WindowType type) |
102 | +{ |
103 | + return requiresParent(qtWindowTypeToMirSurfaceType(type)); |
104 | +} |
105 | + |
106 | +bool isMovable(const Qt::WindowType type) |
107 | +{ |
108 | + auto mirType = qtWindowTypeToMirSurfaceType(type); |
109 | + switch (mirType) { |
110 | + case mir_surface_type_menu: |
111 | + case mir_surface_type_tip: |
112 | + return true; |
113 | + default: |
114 | + return false; |
115 | + } |
116 | +} |
117 | + |
118 | +Spec makeSurfaceSpec(QWindow *window, MirPixelFormat pixelFormat, UbuntuWindow *parentWindowHandle, |
119 | + MirConnection *connection) |
120 | +{ |
121 | + const auto geometry = window->geometry(); |
122 | + const int width = geometry.width() > 0 ? geometry.width() : 1; |
123 | + const int height = geometry.height() > 0 ? geometry.height() : 1; |
124 | + auto type = qtWindowTypeToMirSurfaceType(window->type()); |
125 | |
126 | if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) { |
127 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height); |
128 | - return Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)}; |
129 | - } |
130 | - |
131 | - const Qt::WindowType type = window->type(); |
132 | - if (type == Qt::Popup) { |
133 | - auto parent = transientParentFor(window); |
134 | - if (parent == nullptr) { |
135 | - //NOTE: We cannot have a parentless popup - |
136 | - //try using the last surface to receive input as that will most likely be |
137 | - //the one that caused this popup to be created |
138 | - parent = input->lastInputWindow(); |
139 | - } |
140 | - if (parent) { |
141 | - auto pos = geom.topLeft(); |
142 | - pos -= parent->geometry().topLeft(); |
143 | - MirRectangle location{pos.x(), pos.y(), 0, 0}; |
144 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating menu surface(width:%d, height:%d)", window, width, height); |
145 | - return Spec{mir_connection_create_spec_for_menu( |
146 | - connection, width, height, pixelFormat, parent->mirSurface(), |
147 | - &location, mir_edge_attachment_any)}; |
148 | - } else { |
149 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - cannot create a menu without a parent!", window); |
150 | - } |
151 | - } else if (type == Qt::Dialog) { |
152 | - auto parent = transientParentFor(window); |
153 | - if (parent) { |
154 | - // Modal dialog |
155 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating modal dialog (width=%d, height=%d", window, width, height); |
156 | - return Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent->mirSurface())}; |
157 | - } else { |
158 | - // TODO: do Qt parentless dialogs have the same semantics as mir? |
159 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating parentless dialog (width=%d, height=%d)", window, width, height); |
160 | - return Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)}; |
161 | - } |
162 | - } |
163 | - qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p) - creating normal surface(type=0x%x, width=%d, height=%d)", window, type, width, height); |
164 | - return Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)}; |
165 | + type = mir_surface_type_inputmethod; |
166 | + } |
167 | + |
168 | + MirRectangle location{geometry.x(), geometry.y(), 0, 0}; |
169 | + MirSurface *parent = nullptr; |
170 | + if (parentWindowHandle) { |
171 | + parent = parentWindowHandle->mirSurface(); |
172 | + // Qt uses absolute positioning, but Mir positions surfaces relative to parent. |
173 | + location.top -= parentWindowHandle->geometry().top(); |
174 | + location.left -= parentWindowHandle->geometry().left(); |
175 | + } |
176 | + |
177 | + Spec spec; |
178 | + |
179 | + switch (type) { |
180 | + case mir_surface_type_menu: |
181 | + spec = Spec{mir_connection_create_spec_for_menu(connection, width, height, pixelFormat, parent, |
182 | + &location, mir_edge_attachment_any)}; |
183 | + break; |
184 | + case mir_surface_type_dialog: |
185 | + spec = Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent)}; |
186 | + break; |
187 | + case mir_surface_type_utility: |
188 | + spec = Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)}; |
189 | + break; |
190 | + case mir_surface_type_tip: |
191 | +#if MIR_CLIENT_VERSION < MIR_VERSION_NUMBER(3, 4, 0) |
192 | + spec = Spec{mir_connection_create_spec_for_tooltip(connection, width, height, pixelFormat, parent, |
193 | + &location)}; |
194 | +#else |
195 | + spec = Spec{mir_connection_create_spec_for_tip(connection, width, height, pixelFormat, parent, |
196 | + &location, mir_edge_attachment_any)}; |
197 | +#endif |
198 | + break; |
199 | + case mir_surface_type_inputmethod: |
200 | + spec = Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)}; |
201 | + break; |
202 | + default: |
203 | + spec = Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)}; |
204 | + break; |
205 | + } |
206 | + |
207 | + qCDebug(ubuntumirclient, "makeSurfaceSpec(window=%p): %s spec (type=0x%x, position=(%d, %d)px, size=(%dx%d)px)", |
208 | + window, mirSurfaceTypeToStr(type), window->type(), location.left, location.top, width, height); |
209 | + |
210 | + return std::move(spec); |
211 | } |
212 | |
213 | void setSizingConstraints(MirSurfaceSpec *spec, const QSize& minSize, const QSize& maxSize, const QSize& increment) |
214 | @@ -229,11 +310,11 @@ |
215 | } |
216 | } |
217 | |
218 | -MirSurface *createMirSurface(QWindow *window, int mirOutputId, UbuntuInput *input, MirPixelFormat pixelFormat, |
219 | - MirConnection *connection, mir_surface_event_callback inputCallback, |
220 | - void* inputContext) |
221 | +MirSurface *createMirSurface(QWindow *window, int mirOutputId, UbuntuWindow *parentWindowHandle, |
222 | + MirPixelFormat pixelFormat, MirConnection *connection, |
223 | + mir_surface_event_callback inputCallback, void *inputContext) |
224 | { |
225 | - auto spec = makeSurfaceSpec(window, input, pixelFormat, connection); |
226 | + auto spec = makeSurfaceSpec(window, pixelFormat, parentWindowHandle, connection); |
227 | |
228 | // Install event handler as early as possible |
229 | mir_surface_spec_set_event_handler(spec.get(), inputCallback, inputContext); |
230 | @@ -256,6 +337,20 @@ |
231 | return surface; |
232 | } |
233 | |
234 | +UbuntuWindow *getParentIfNecessary(QWindow *window, UbuntuInput *input) |
235 | +{ |
236 | + UbuntuWindow *parentWindowHandle = nullptr; |
237 | + if (requiresParent(window->type())) { |
238 | + parentWindowHandle = transientParentFor(window); |
239 | + if (parentWindowHandle == nullptr) { |
240 | + // NOTE: Mir requires this surface have a parent. Try using the last surface to receive input as that will |
241 | + // most likely be the one that caused this surface to be created |
242 | + parentWindowHandle = input->lastInputWindow(); |
243 | + } |
244 | + } |
245 | + return parentWindowHandle; |
246 | +} |
247 | + |
248 | MirPixelFormat disableAlphaBufferIfPossible(MirPixelFormat pixelFormat) |
249 | { |
250 | switch(pixelFormat) { |
251 | @@ -287,98 +382,18 @@ |
252 | |
253 | } //namespace |
254 | |
255 | + |
256 | + |
257 | class UbuntuSurface |
258 | { |
259 | public: |
260 | - UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, UbuntuInput *input, MirConnection *connection) |
261 | - : mWindow(platformWindow->window()) |
262 | - , mPlatformWindow(platformWindow) |
263 | - , mInput(input) |
264 | - , mConnection(connection) |
265 | - , mEglDisplay(display) |
266 | - , mNeedsRepaint(false) |
267 | - , mParented(mWindow->transientParent() || mWindow->parent()) |
268 | - , mFormat(mWindow->requestedFormat()) |
269 | - , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal) |
270 | - { |
271 | - // Have Qt choose most suitable EGLConfig for the requested surface format, and update format to reflect it |
272 | - EGLConfig config = q_configFromGLFormat(display, mFormat, true); |
273 | - if (config == 0) { |
274 | - // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default |
275 | - // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a |
276 | - // 1.4 context, but the XCB EGL backend tries to honour it, and fails. The 1.4 context appears to |
277 | - // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default |
278 | - // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455). |
279 | - static const bool isMesa = QString(eglQueryString(display, EGL_VENDOR)).contains(QStringLiteral("Mesa")); |
280 | - if (isMesa) { |
281 | - qCDebug(ubuntumirclientGraphics, "Attempting to choose OpenGL 1.4 context which may suit Mesa"); |
282 | - mFormat.setMajorVersion(1); |
283 | - mFormat.setMinorVersion(4); |
284 | - config = q_configFromGLFormat(display, mFormat, true); |
285 | - } |
286 | - } |
287 | - if (config == 0) { |
288 | - qCritical() << "Qt failed to choose a suitable EGLConfig to suit the surface format" << mFormat; |
289 | - } |
290 | - |
291 | - mFormat = q_glFormatFromConfig(display, config, mFormat); |
292 | - |
293 | - // Have Mir decide the pixel format most suited to the chosen EGLConfig. This is the only way |
294 | - // Mir will know what EGLConfig has been chosen - it cannot deduce it from the buffers. |
295 | - auto pixelFormat = mir_connection_get_egl_pixel_format(connection, display, config); |
296 | - // But the chosen EGLConfig might have an alpha buffer enabled, even if not requested by the client. |
297 | - // If that's the case, try to edit the chosen pixel format in order to disable the alpha buffer. |
298 | - // This is an optimisation for the compositor, as it can avoid blending this surface. |
299 | - if (mWindow->requestedFormat().alphaBufferSize() < 0) { |
300 | - pixelFormat = disableAlphaBufferIfPossible(pixelFormat); |
301 | - } |
302 | - |
303 | - const auto outputId = static_cast<UbuntuScreen *>(mWindow->screen()->handle())->mirOutputId(); |
304 | - |
305 | - mMirSurface = createMirSurface(mWindow, outputId, input, pixelFormat, connection, surfaceEventCallback, this); |
306 | - mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirSurface), nullptr); |
307 | - |
308 | - mNeedsExposeCatchup = mir_surface_get_visibility(mMirSurface) == mir_surface_visibility_occluded; |
309 | - |
310 | - // Window manager can give us a final size different from what we asked for |
311 | - // so let's check what we ended up getting |
312 | - MirSurfaceParameters parameters; |
313 | - mir_surface_get_parameters(mMirSurface, ¶meters); |
314 | - |
315 | - auto geom = mWindow->geometry(); |
316 | - geom.setWidth(parameters.width); |
317 | - geom.setHeight(parameters.height); |
318 | - if (mWindow->windowState() == Qt::WindowFullScreen) { |
319 | - geom.moveTop(0); |
320 | - } else { |
321 | - geom.moveTop(panelHeight()); |
322 | - } |
323 | - |
324 | - // Assume that the buffer size matches the surface size at creation time |
325 | - mBufferSize = geom.size(); |
326 | - platformWindow->QPlatformWindow::setGeometry(geom); |
327 | - QWindowSystemInterface::handleGeometryChange(mWindow, geom); |
328 | - |
329 | - qCDebug(ubuntumirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title() |
330 | - << "role:" << roleFor(mWindow); |
331 | - qCDebug(ubuntumirclientGraphics) |
332 | - << "Requested format:" << mWindow->requestedFormat() |
333 | - << "\nActual format:" << mFormat |
334 | - << "with associated Mir pixel format:" << mirPixelFormatToStr(pixelFormat); |
335 | - } |
336 | - |
337 | - ~UbuntuSurface() |
338 | - { |
339 | - if (mEglSurface != EGL_NO_SURFACE) |
340 | - eglDestroySurface(mEglDisplay, mEglSurface); |
341 | - if (mMirSurface) |
342 | - mir_surface_release_sync(mMirSurface); |
343 | - } |
344 | + UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, UbuntuInput *input, MirConnection *connection); |
345 | + ~UbuntuSurface(); |
346 | |
347 | UbuntuSurface(const UbuntuSurface &) = delete; |
348 | UbuntuSurface& operator=(const UbuntuSurface &) = delete; |
349 | |
350 | - void resize(const QSize& newSize); |
351 | + void updateGeometry(const QRect &newGeometry); |
352 | void updateTitle(const QString& title); |
353 | void setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment); |
354 | |
355 | @@ -414,6 +429,7 @@ |
356 | UbuntuWindow * const mPlatformWindow; |
357 | UbuntuInput * const mInput; |
358 | MirConnection * const mConnection; |
359 | + UbuntuWindow * mParentWindowHandle{nullptr}; |
360 | |
361 | MirSurface* mMirSurface; |
362 | const EGLDisplay mEglDisplay; |
363 | @@ -423,6 +439,7 @@ |
364 | bool mParented; |
365 | QSize mBufferSize; |
366 | QSurfaceFormat mFormat; |
367 | + MirPixelFormat mPixelFormat; |
368 | |
369 | QMutex mTargetSizeMutex; |
370 | QSize mTargetSize; |
371 | @@ -430,23 +447,102 @@ |
372 | QString mPersistentIdStr; |
373 | }; |
374 | |
375 | -void UbuntuSurface::resize(const QSize& size) |
376 | -{ |
377 | - qCDebug(ubuntumirclient,"resize(window=%p, width=%d, height=%d)", mWindow, size.width(), size.height()); |
378 | - |
379 | - if (mWindow->windowState() == Qt::WindowFullScreen || mWindow->windowState() == Qt::WindowMaximized) { |
380 | - qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow); |
381 | - return; |
382 | - } |
383 | - |
384 | - if (size.isEmpty()) { |
385 | - qCDebug(ubuntumirclient, "resize(window=%p) - not resizing, size is empty", mWindow); |
386 | - return; |
387 | - } |
388 | - |
389 | - Spec spec{mir_connection_create_spec_for_changes(mConnection)}; |
390 | - mir_surface_spec_set_width(spec.get(), size.width()); |
391 | - mir_surface_spec_set_height(spec.get(), size.height()); |
392 | +UbuntuSurface::UbuntuSurface(UbuntuWindow *platformWindow, EGLDisplay display, UbuntuInput *input, MirConnection *connection) |
393 | + : mWindow(platformWindow->window()) |
394 | + , mPlatformWindow(platformWindow) |
395 | + , mInput(input) |
396 | + , mConnection(connection) |
397 | + , mEglDisplay(display) |
398 | + , mNeedsRepaint(false) |
399 | + , mParented(mWindow->transientParent() || mWindow->parent()) |
400 | + , mFormat(mWindow->requestedFormat()) |
401 | + , mShellChrome(mWindow->flags() & LowChromeWindowHint ? mir_shell_chrome_low : mir_shell_chrome_normal) |
402 | +{ |
403 | + // Have Qt choose most suitable EGLConfig for the requested surface format, and update format to reflect it |
404 | + EGLConfig config = q_configFromGLFormat(display, mFormat, true); |
405 | + if (config == 0) { |
406 | + // Older Intel Atom-based devices only support OpenGL 1.4 compatibility profile but by default |
407 | + // QML asks for at least OpenGL 2.0. The XCB GLX backend ignores this request and returns a |
408 | + // 1.4 context, but the XCB EGL backend tries to honour it, and fails. The 1.4 context appears to |
409 | + // have sufficient capabilities on MESA (i915) to render correctly however. So reduce the default |
410 | + // requested OpenGL version to 1.0 to ensure EGL will give us a working context (lp:1549455). |
411 | + static const bool isMesa = QString(eglQueryString(display, EGL_VENDOR)).contains(QStringLiteral("Mesa")); |
412 | + if (isMesa) { |
413 | + qCDebug(ubuntumirclientGraphics, "Attempting to choose OpenGL 1.4 context which may suit Mesa"); |
414 | + mFormat.setMajorVersion(1); |
415 | + mFormat.setMinorVersion(4); |
416 | + config = q_configFromGLFormat(display, mFormat, true); |
417 | + } |
418 | + } |
419 | + if (config == 0) { |
420 | + qCritical() << "Qt failed to choose a suitable EGLConfig to suit the surface format" << mFormat; |
421 | + } |
422 | + |
423 | + mFormat = q_glFormatFromConfig(display, config, mFormat); |
424 | + |
425 | + // Have Mir decide the pixel format most suited to the chosen EGLConfig. This is the only way |
426 | + // Mir will know what EGLConfig has been chosen - it cannot deduce it from the buffers. |
427 | + mPixelFormat = mir_connection_get_egl_pixel_format(connection, display, config); |
428 | + // But the chosen EGLConfig might have an alpha buffer enabled, even if not requested by the client. |
429 | + // If that's the case, try to edit the chosen pixel format in order to disable the alpha buffer. |
430 | + // This is an optimisation for the compositor, as it can avoid blending this surface. |
431 | + if (mWindow->requestedFormat().alphaBufferSize() < 0) { |
432 | + mPixelFormat = disableAlphaBufferIfPossible(mPixelFormat); |
433 | + } |
434 | + |
435 | + const auto outputId = static_cast<UbuntuScreen *>(mWindow->screen()->handle())->mirOutputId(); |
436 | + |
437 | + mParentWindowHandle = getParentIfNecessary(mWindow, input); |
438 | + |
439 | + mMirSurface = createMirSurface(mWindow, outputId, mParentWindowHandle, mPixelFormat, connection, surfaceEventCallback, this); |
440 | + mEglSurface = eglCreateWindowSurface(mEglDisplay, config, nativeWindowFor(mMirSurface), nullptr); |
441 | + |
442 | + mNeedsExposeCatchup = mir_surface_get_visibility(mMirSurface) == mir_surface_visibility_occluded; |
443 | + |
444 | + // Window manager can give us a final size different from what we asked for |
445 | + // so let's check what we ended up getting |
446 | + MirSurfaceParameters parameters; |
447 | + mir_surface_get_parameters(mMirSurface, ¶meters); |
448 | + |
449 | + auto geom = mWindow->geometry(); |
450 | + geom.setWidth(parameters.width); |
451 | + geom.setHeight(parameters.height); |
452 | + |
453 | + // Assume that the buffer size matches the surface size at creation time |
454 | + mBufferSize = geom.size(); |
455 | + platformWindow->QPlatformWindow::setGeometry(geom); |
456 | + QWindowSystemInterface::handleGeometryChange(mWindow, geom); |
457 | + |
458 | + qCDebug(ubuntumirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title() |
459 | + << "role:" << roleFor(mWindow); |
460 | + qCDebug(ubuntumirclientGraphics) |
461 | + << "Requested format:" << mWindow->requestedFormat() |
462 | + << "\nActual format:" << mFormat |
463 | + << "with associated Mir pixel format:" << mirPixelFormatToStr(mPixelFormat); |
464 | +} |
465 | + |
466 | +UbuntuSurface::~UbuntuSurface() |
467 | +{ |
468 | + if (mEglSurface != EGL_NO_SURFACE) |
469 | + eglDestroySurface(mEglDisplay, mEglSurface); |
470 | + if (mMirSurface) { |
471 | + mir_surface_release_sync(mMirSurface); |
472 | + } |
473 | +} |
474 | + |
475 | +void UbuntuSurface::updateGeometry(const QRect &newGeometry) |
476 | +{ |
477 | + qCDebug(ubuntumirclient,"updateGeometry(window=%p, width=%d, height=%d)", mWindow, |
478 | + newGeometry.width(), newGeometry.height()); |
479 | + |
480 | + Spec spec; |
481 | + if (isMovable(mWindow->type())) { |
482 | + spec = Spec{makeSurfaceSpec(mWindow, mPixelFormat, mParentWindowHandle, mConnection)}; |
483 | + } else { |
484 | + spec = Spec{mir_connection_create_spec_for_changes(mConnection)}; |
485 | + mir_surface_spec_set_width(spec.get(), newGeometry.width()); |
486 | + mir_surface_spec_set_height(spec.get(), newGeometry.height()); |
487 | + } |
488 | mir_surface_apply_spec(mMirSurface, spec.get()); |
489 | } |
490 | |
491 | @@ -690,7 +786,7 @@ |
492 | |
493 | void UbuntuWindow::handleSurfaceVisibilityChanged(bool visible) |
494 | { |
495 | - qCDebug(ubuntumirclient, "handleSurfaceVisibilityChanged(visible=%d)", visible); |
496 | + qCDebug(ubuntumirclient, "handleSurfaceVisibilityChanged(window=%p, visible=%d)", window(), visible); |
497 | |
498 | if (mWindowVisible == visible) return; |
499 | mWindowVisible = visible; |
500 | @@ -739,6 +835,10 @@ |
501 | */ |
502 | void UbuntuWindow::updatePanelHeightHack(bool enable) |
503 | { |
504 | + if ((window()->type() & Qt::WindowType_Mask) != Qt::Window) { // only plain windows get the hack |
505 | + return; |
506 | + } |
507 | + |
508 | QMutexLocker lock(&mMutex); |
509 | |
510 | QRect newGeometry = geometry(); |
511 | @@ -758,13 +858,20 @@ |
512 | void UbuntuWindow::setGeometry(const QRect &rect) |
513 | { |
514 | QMutexLocker lock(&mMutex); |
515 | + |
516 | + if (window()->windowState() == Qt::WindowFullScreen || window()->windowState() == Qt::WindowMaximized) { |
517 | + qCDebug(ubuntumirclient, "setGeometry(window=%p) - not resizing, window is maximized or fullscreen", window()); |
518 | + return; |
519 | + } |
520 | + |
521 | qCDebug(ubuntumirclient, "setGeometry (window=%p, position=(%d, %d)dp, size=(%dx%d)dp)", |
522 | window(), rect.x(), rect.y(), rect.width(), rect.height()); |
523 | - |
524 | - //NOTE: mir surfaces cannot be moved by the client so ignore the topLeft coordinates |
525 | - const auto newSize = rect.size(); |
526 | - |
527 | - mSurface->resize(newSize); |
528 | + // Immediately update internal geometry so Qt believes position updated |
529 | + QRect newPosition(geometry()); |
530 | + newPosition.moveTo(rect.topLeft()); |
531 | + QPlatformWindow::setGeometry(newPosition); |
532 | + |
533 | + mSurface->updateGeometry(rect); |
534 | // Note: don't call handleGeometryChange here, wait to see what Mir replies with. |
535 | } |
536 |
FAILED: Continuous integration, rev:297 /unity8- jenkins. ubuntu. com/job/ lp-qtubuntu- ci/145/
https:/
Executed test runs:
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-qtubuntu- ci/145/ rebuild
https:/