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