Merge lp:~dandrader/qtubuntu/improve-resize into lp:qtubuntu

Proposed by Daniel d'Andrada
Status: Superseded
Proposed branch: lp:~dandrader/qtubuntu/improve-resize
Merge into: lp:qtubuntu
Diff against target: 324 lines (+58/-84)
4 files modified
debian/control (+1/-1)
src/ubuntumirclient/input.cpp (+28/-27)
src/ubuntumirclient/window.cpp (+29/-52)
src/ubuntumirclient/window.h (+0/-4)
To merge this branch: bzr merge lp:~dandrader/qtubuntu/improve-resize
Reviewer Review Type Date Requested Status
Gerry Boland (community) Needs Fixing
PS Jenkins bot continuous-integration Approve
Review via email: mp+258912@code.launchpad.net

This proposal has been superseded by a proposal from 2015-06-03.

Commit message

Drastically improve surface resize responsiveness

QWindowSystemInterface::handle[...]() methods are thread safe, thus there's no need to have intermetiate methods between the rendering thread and such calls.

There was also some miscommunication between the now absent handleBufferResize() slot from the main thread and the swapbuffer handler from the render thread.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Gerry Boland (gerboland) wrote :

=== modified file 'src/ubuntumirclient/input.cpp'
+/*
+*/
necessary change?

In testing with mir_proving_server, I notice one problem: the surface size QML requests is not the size it gets. Think the geometry.setY() call is problematic now. This used to work before.

Remainder looks good. Am worried that there are 3+ threads (Qt GUI, Qt renderers, Mir input) all interacting with this class tho.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 13/05/15 09:12, Gerry Boland wrote:
> === modified file 'src/ubuntumirclient/input.cpp'
> +/*
> +*/
> necessary change?

Yes, code won't build otherwise in a debug config. I've the same change
in another top-approved-but-not-yet-landed MP.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> In testing with mir_proving_server, I notice one problem: the surface size QML
> requests is not the size it gets.

This also happens with lp:qtubuntu.

I request (w=600,h=600) and get a geometry of (x=0,y=26,w=600,h=574). It's interesting that h+y=600. That's with mir_proving_server.

260. By Daniel d'Andrada

Merge lp:~mir-team/qtubuntu/track-mir-deprecations

261. By Daniel d'Andrada

Refactor optional logging and remove trailing whitespace

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/control'
--- debian/control 2015-03-05 19:54:57 +0000
+++ debian/control 2015-06-03 13:24:47 +0000
@@ -17,7 +17,7 @@
17 qtbase5-private-dev,17 qtbase5-private-dev,
18 qtdeclarative5-dev,18 qtdeclarative5-dev,
19 libqt5sensors5-dev,19 libqt5sensors5-dev,
20 libmirclient-dev (>= 0.11.0),20 libmirclient-dev (>= 0.13.0),
21# if you don't have have commit access to this branch but would like to upload21# if you don't have have commit access to this branch but would like to upload
22# directly to Ubuntu, don't worry: your changes will be merged back into the22# directly to Ubuntu, don't worry: your changes will be merged back into the
23# upstream branch23# upstream branch
2424
=== modified file 'src/ubuntumirclient/input.cpp'
--- src/ubuntumirclient/input.cpp 2015-02-17 17:39:47 +0000
+++ src/ubuntumirclient/input.cpp 2015-06-03 13:24:47 +0000
@@ -160,6 +160,7 @@
160#ifndef QT_NO_DEBUG160#ifndef QT_NO_DEBUG
161161
162162
163/*
163static const char* nativeEventTypeToStr(MirEventType t)164static const char* nativeEventTypeToStr(MirEventType t)
164{165{
165 switch (t)166 switch (t)
@@ -185,7 +186,7 @@
185 return "invalid";186 return "invalid";
186 }187 }
187}188}
188189*/
189190
190#endif191#endif
191192
@@ -275,7 +276,7 @@
275276
276void UbuntuInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *ev)277void UbuntuInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *ev)
277{278{
278 const MirTouchInputEvent *tev = mir_input_event_get_touch_input_event(ev);279 const MirTouchEvent *tev = mir_input_event_get_touch_event(ev);
279280
280 // FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That281 // FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That
281 // needs to be fixed as soon as the compat input lib adds query support.282 // needs to be fixed as soon as the compat input lib adds query support.
@@ -286,30 +287,30 @@
286287
287 // TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left288 // TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left
288 // as Qt::TouchPointMoved289 // as Qt::TouchPointMoved
289 const unsigned int kPointerCount = mir_touch_input_event_get_touch_count(tev);290 const unsigned int kPointerCount = mir_touch_event_point_count(tev);
290 for (unsigned int i = 0; i < kPointerCount; ++i) {291 for (unsigned int i = 0; i < kPointerCount; ++i) {
291 QWindowSystemInterface::TouchPoint touchPoint;292 QWindowSystemInterface::TouchPoint touchPoint;
292293
293 const float kX = mir_touch_input_event_get_touch_axis_value(tev, i, mir_touch_input_axis_x) + kWindowGeometry.x();294 const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x) + kWindowGeometry.x();
294 const float kY = mir_touch_input_event_get_touch_axis_value(tev, i, mir_touch_input_axis_y) + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere295 const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y) + kWindowGeometry.y(); // see bug lp:1346633 workaround comments elsewhere
295 const float kW = mir_touch_input_event_get_touch_axis_value(tev, i, mir_touch_input_axis_touch_major);296 const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major);
296 const float kH = mir_touch_input_event_get_touch_axis_value(tev, i, mir_touch_input_axis_touch_minor);297 const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor);
297 const float kP = mir_touch_input_event_get_touch_axis_value(tev, i, mir_touch_input_axis_pressure);298 const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure);
298 touchPoint.id = mir_touch_input_event_get_touch_id(tev, i);299 touchPoint.id = mir_touch_event_id(tev, i);
299 touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());300 touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());
300 touchPoint.area = QRectF(kX - (kW / 2.0), kY - (kH / 2.0), kW, kH);301 touchPoint.area = QRectF(kX - (kW / 2.0), kY - (kH / 2.0), kW, kH);
301 touchPoint.pressure = kP / kMaxPressure;302 touchPoint.pressure = kP / kMaxPressure;
302303
303 MirTouchInputEventTouchAction touch_action = mir_touch_input_event_get_touch_action(tev, i);304 MirTouchAction touch_action = mir_touch_event_action(tev, i);
304 switch (touch_action)305 switch (touch_action)
305 {306 {
306 case mir_touch_input_event_action_down:307 case mir_touch_action_down:
307 touchPoint.state = Qt::TouchPointPressed;308 touchPoint.state = Qt::TouchPointPressed;
308 break;309 break;
309 case mir_touch_input_event_action_up:310 case mir_touch_action_up:
310 touchPoint.state = Qt::TouchPointReleased;311 touchPoint.state = Qt::TouchPointReleased;
311 break;312 break;
312 case mir_touch_input_event_action_change:313 case mir_touch_action_change:
313 default:314 default:
314 touchPoint.state = Qt::TouchPointMoved;315 touchPoint.state = Qt::TouchPointMoved;
315 }316 }
@@ -363,23 +364,23 @@
363364
364void UbuntuInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *event)365void UbuntuInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *event)
365{366{
366 const MirKeyInputEvent *key_event = mir_input_event_get_key_input_event(event);367 const MirKeyboardEvent *key_event = mir_input_event_get_keyboard_event(event);
367368
368 ulong timestamp = mir_input_event_get_event_time(event) / 1000000;369 ulong timestamp = mir_input_event_get_event_time(event) / 1000000;
369 xkb_keysym_t xk_sym = mir_key_input_event_get_key_code(key_event);370 xkb_keysym_t xk_sym = mir_keyboard_event_key_code(key_event);
370371
371 // Key modifier and unicode index mapping.372 // Key modifier and unicode index mapping.
372 auto modifiers = qt_modifiers_from_mir(mir_key_input_event_get_modifiers(key_event));373 auto modifiers = qt_modifiers_from_mir(mir_keyboard_event_modifiers(key_event));
373374
374 MirKeyInputEventAction action = mir_key_input_event_get_action(key_event);375 MirKeyboardAction action = mir_keyboard_event_action(key_event);
375 QEvent::Type keyType = action == mir_key_input_event_action_up376 QEvent::Type keyType = action == mir_keyboard_action_up
376 ? QEvent::KeyRelease : QEvent::KeyPress;377 ? QEvent::KeyRelease : QEvent::KeyPress;
377378
378 char s[2];379 char s[2];
379 int sym = translateKeysym(xk_sym, s, sizeof(s));380 int sym = translateKeysym(xk_sym, s, sizeof(s));
380 QString text = QString::fromLatin1(s);381 QString text = QString::fromLatin1(s);
381382
382 bool is_auto_rep = action == mir_key_input_event_action_repeat;383 bool is_auto_rep = action == mir_keyboard_action_repeat;
383384
384 QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();385 QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext();
385 if (context) {386 if (context) {
@@ -396,14 +397,14 @@
396397
397namespace398namespace
398{399{
399Qt::MouseButtons extract_buttons(const MirPointerInputEvent *pev)400Qt::MouseButtons extract_buttons(const MirPointerEvent *pev)
400{401{
401 Qt::MouseButtons buttons = Qt::NoButton;402 Qt::MouseButtons buttons = Qt::NoButton;
402 if (mir_pointer_input_event_get_button_state(pev, mir_pointer_input_button_primary))403 if (mir_pointer_event_button_state(pev, mir_pointer_button_primary))
403 buttons |= Qt::LeftButton;404 buttons |= Qt::LeftButton;
404 if (mir_pointer_input_event_get_button_state(pev, mir_pointer_input_button_secondary))405 if (mir_pointer_event_button_state(pev, mir_pointer_button_secondary))
405 buttons |= Qt::RightButton;406 buttons |= Qt::RightButton;
406 if (mir_pointer_input_event_get_button_state(pev, mir_pointer_input_button_tertiary))407 if (mir_pointer_event_button_state(pev, mir_pointer_button_tertiary))
407 buttons |= Qt::MidButton;408 buttons |= Qt::MidButton;
408409
409 // TODO: Should mir back and forward buttons exist?410 // TODO: Should mir back and forward buttons exist?
@@ -416,12 +417,12 @@
416{417{
417 auto timestamp = mir_input_event_get_event_time(ev) / 1000000;418 auto timestamp = mir_input_event_get_event_time(ev) / 1000000;
418419
419 auto pev = mir_input_event_get_pointer_input_event(ev);420 auto pev = mir_input_event_get_pointer_event(ev);
420 auto modifiers = qt_modifiers_from_mir(mir_pointer_input_event_get_modifiers(pev));421 auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev));
421 auto buttons = extract_buttons(pev);422 auto buttons = extract_buttons(pev);
422423
423 auto local_point = QPointF(mir_pointer_input_event_get_axis_value(pev, mir_pointer_input_axis_x),424 auto local_point = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x),
424 mir_pointer_input_event_get_axis_value(pev, mir_pointer_input_axis_y));425 mir_pointer_event_axis_value(pev, mir_pointer_axis_y));
425 426
426 QWindowSystemInterface::handleMouseEvent(window, timestamp, local_point, local_point /* Should we omit global point instead? */,427 QWindowSystemInterface::handleMouseEvent(window, timestamp, local_point, local_point /* Should we omit global point instead? */,
427 buttons, modifiers);428 buttons, modifiers);
428429
=== modified file 'src/ubuntumirclient/window.cpp'
--- src/ubuntumirclient/window.cpp 2015-02-23 19:53:45 +0000
+++ src/ubuntumirclient/window.cpp 2015-06-03 13:24:47 +0000
@@ -96,7 +96,6 @@
96 WId id;96 WId id;
97 UbuntuInput* input;97 UbuntuInput* input;
98 Qt::WindowState state;98 Qt::WindowState state;
99 QRect geometry;
100 MirConnection *connection;99 MirConnection *connection;
101 MirSurface* surface;100 MirSurface* surface;
102 QSize bufferSize;101 QSize bufferSize;
@@ -119,8 +118,7 @@
119 UbuntuWindow* platformWindow = static_cast<UbuntuWindow*>(context);118 UbuntuWindow* platformWindow = static_cast<UbuntuWindow*>(context);
120 platformWindow->priv()->surface = surface;119 platformWindow->priv()->surface = surface;
121120
122 MirEventDelegate handler = {eventCallback, context};121 mir_surface_set_event_handler(surface, eventCallback, context);
123 mir_surface_set_event_handler(surface, &handler);
124}122}
125123
126UbuntuWindow::UbuntuWindow(QWindow* w, QSharedPointer<UbuntuClipboard> clipboard, UbuntuScreen* screen,124UbuntuWindow::UbuntuWindow(QWindow* w, QSharedPointer<UbuntuClipboard> clipboard, UbuntuScreen* screen,
@@ -141,8 +139,8 @@
141 d->id = id++;139 d->id = id++;
142140
143 // Use client geometry if set explicitly, use available screen geometry otherwise.141 // Use client geometry if set explicitly, use available screen geometry otherwise.
144 d->geometry = window()->geometry() != screen->geometry() ?142 QPlatformWindow::setGeometry(window()->geometry() != screen->geometry() ?
145 window()->geometry() : screen->availableGeometry();143 window()->geometry() : screen->availableGeometry());
146 createWindow();144 createWindow();
147 DLOG("UbuntuWindow::UbuntuWindow (this=%p, w=%p, screen=%p, input=%p)", this, w, screen, input);145 DLOG("UbuntuWindow::UbuntuWindow (this=%p, w=%p, screen=%p, input=%p)", this, w, screen, input);
148}146}
@@ -254,7 +252,7 @@
254 geometry.setY(panelHeight);252 geometry.setY(panelHeight);
255 } else {253 } else {
256 printf("UbuntuWindow - regular geometry\n");254 printf("UbuntuWindow - regular geometry\n");
257 geometry = d->geometry;255 geometry = this->geometry();
258 geometry.setY(panelHeight);256 geometry.setY(panelHeight);
259 }257 }
260258
@@ -279,7 +277,7 @@
279 mir_surface_spec_release(spec);277 mir_surface_spec_release(spec);
280278
281 DASSERT(d->surface != NULL);279 DASSERT(d->surface != NULL);
282 d->createEGLSurface((EGLNativeWindowType)mir_surface_get_egl_native_window(d->surface));280 d->createEGLSurface((EGLNativeWindowType)mir_buffer_stream_get_egl_native_window(mir_surface_get_buffer_stream(d->surface)));
283281
284 if (d->state == Qt::WindowFullScreen) {282 if (d->state == Qt::WindowFullScreen) {
285 // TODO: We could set this on creation once surface spec supports it (mps already up)283 // TODO: We could set this on creation once surface spec supports it (mps already up)
@@ -315,22 +313,16 @@
315313
316void UbuntuWindow::handleSurfaceResize(int width, int height)314void UbuntuWindow::handleSurfaceResize(int width, int height)
317{315{
316 QMutexLocker(&d->mutex);
318 LOG("UbuntuWindow::handleSurfaceResize(width=%d, height=%d)", width, height);317 LOG("UbuntuWindow::handleSurfaceResize(width=%d, height=%d)", width, height);
319318
320 // The current buffer size hasn't actually changed. so just render on it and swap319 // The current buffer size hasn't actually changed. so just render on it and swap
321 // buffers until we render on a buffer with the target size.320 // buffers until we render on a buffer with the target size.
322321
323 bool shouldSwapBuffers;322 d->targetBufferSize.rwidth() = width;
324323 d->targetBufferSize.rheight() = height;
325 {324
326 QMutexLocker(&d->mutex);325 if (d->bufferSize != d->targetBufferSize) {
327 d->targetBufferSize.rwidth() = width;
328 d->targetBufferSize.rheight() = height;
329
330 shouldSwapBuffers = d->bufferSize != d->targetBufferSize;
331 }
332
333 if (shouldSwapBuffers) {
334 QWindowSystemInterface::handleExposeEvent(window(), geometry());326 QWindowSystemInterface::handleExposeEvent(window(), geometry());
335 } else {327 } else {
336 qWarning("[ubuntumirclient QPA] UbuntuWindow::handleSurfaceResize"328 qWarning("[ubuntumirclient QPA] UbuntuWindow::handleSurfaceResize"
@@ -357,35 +349,6 @@
357 QWindowSystemInterface::handleWindowActivated(activatedWindow, Qt::ActiveWindowFocusReason);349 QWindowSystemInterface::handleWindowActivated(activatedWindow, Qt::ActiveWindowFocusReason);
358}350}
359351
360void UbuntuWindow::handleBufferResize(int width, int height)
361{
362 DLOG("UbuntuWindow::handleBufferResize(width=%d, height=%d)", width, height);
363
364 QRect oldGeometry;
365 QRect newGeometry;
366
367 {
368 QMutexLocker(&d->mutex);
369 oldGeometry = geometry();
370 newGeometry = oldGeometry;
371 newGeometry.setWidth(width);
372 newGeometry.setHeight(height);
373
374 d->bufferSize.rwidth() = width;
375 d->bufferSize.rheight() = height;
376 d->geometry = newGeometry;
377 }
378
379 QPlatformWindow::setGeometry(newGeometry);
380 QWindowSystemInterface::handleGeometryChange(window(), newGeometry, oldGeometry);
381 QWindowSystemInterface::handleExposeEvent(window(), newGeometry);
382}
383
384void UbuntuWindow::forceRedraw()
385{
386 QWindowSystemInterface::handleExposeEvent(window(), geometry());
387}
388
389void UbuntuWindow::setWindowState(Qt::WindowState state)352void UbuntuWindow::setWindowState(Qt::WindowState state)
390{353{
391 QMutexLocker(&d->mutex);354 QMutexLocker(&d->mutex);
@@ -407,7 +370,7 @@
407370
408 {371 {
409 QMutexLocker(&d->mutex);372 QMutexLocker(&d->mutex);
410 d->geometry = rect;373 QPlatformWindow::setGeometry(rect);
411 doMoveResize = d->state != Qt::WindowFullScreen && d->state != Qt::WindowMaximized;374 doMoveResize = d->state != Qt::WindowFullScreen && d->state != Qt::WindowMaximized;
412 }375 }
413376
@@ -451,16 +414,30 @@
451414
452 if (sizeKnown && (d->bufferSize.width() != newBufferWidth ||415 if (sizeKnown && (d->bufferSize.width() != newBufferWidth ||
453 d->bufferSize.height() != newBufferHeight)) {416 d->bufferSize.height() != newBufferHeight)) {
454 QMetaObject::invokeMethod(this, "handleBufferResize",417
455 Qt::QueuedConnection,418 DLOG("UbuntuWindow::onBuffersSwapped_threadSafe - buffer size changed from (%d,%d) to (%d,%d)",
456 Q_ARG(int, newBufferWidth), Q_ARG(int, newBufferHeight));419 d->bufferSize.width(), d->bufferSize.height(), newBufferWidth, newBufferHeight);
420
421 d->bufferSize.rwidth() = newBufferWidth;
422 d->bufferSize.rheight() = newBufferHeight;
423
424 QRect newGeometry;
425
426 newGeometry = geometry();
427 newGeometry.setWidth(d->bufferSize.width());
428 newGeometry.setHeight(d->bufferSize.height());
429
430 QPlatformWindow::setGeometry(newGeometry);
431 QWindowSystemInterface::handleGeometryChange(window(), newGeometry, QRect());
432 QWindowSystemInterface::handleExposeEvent(window(), newGeometry);
433
457 } else {434 } else {
458 // buffer size hasn't changed435 // buffer size hasn't changed
459 if (d->targetBufferSize.isValid()) {436 if (d->targetBufferSize.isValid()) {
460 if (d->bufferSize != d->targetBufferSize) {437 if (d->bufferSize != d->targetBufferSize) {
461 // but we still didn't reach the promised buffer size from the mir resize event.438 // but we still didn't reach the promised buffer size from the mir resize event.
462 // thus keep swapping buffers439 // thus keep swapping buffers
463 QMetaObject::invokeMethod(this, "forceRedraw", Qt::QueuedConnection);440 QWindowSystemInterface::handleExposeEvent(window(), geometry());
464 } else {441 } else {
465 // target met. we have just provided a render with the target size and442 // target met. we have just provided a render with the target size and
466 // can therefore finally rest.443 // can therefore finally rest.
467444
=== modified file 'src/ubuntumirclient/window.h'
--- src/ubuntumirclient/window.h 2015-02-04 16:14:43 +0000
+++ src/ubuntumirclient/window.h 2015-06-03 13:24:47 +0000
@@ -49,10 +49,6 @@
4949
50 UbuntuWindowPrivate* priv() { return d; }50 UbuntuWindowPrivate* priv() { return d; }
5151
52public Q_SLOTS:
53 void handleBufferResize(int width, int height);
54 void forceRedraw();
55
56private:52private:
57 void createWindow();53 void createWindow();
58 void moveResize(const QRect& rect);54 void moveResize(const QRect& rect);

Subscribers

People subscribed via source and target branches