Merge lp:~dandrader/qtmir/multiSurfaceApp into lp:qtmir

Proposed by Daniel d'Andrada
Status: Superseded
Proposed branch: lp:~dandrader/qtmir/multiSurfaceApp
Merge into: lp:qtmir
Diff against target: 945 lines (+259/-134)
17 files modified
CMakeLists.txt (+1/-1)
debian/control (+2/-2)
src/modules/Unity/Application/mirbuffersgtexture.cpp (+18/-10)
src/modules/Unity/Application/mirsurface.cpp (+48/-37)
src/modules/Unity/Application/mirsurface.h (+10/-1)
src/modules/Unity/Application/mirsurfaceinterface.h (+4/-0)
src/modules/Unity/Application/mirsurfaceitem.cpp (+51/-8)
src/modules/Unity/Application/mirsurfaceitem.h (+9/-0)
src/modules/Unity/Application/mirsurfacemanager.cpp (+1/-1)
src/modules/Unity/Application/session.cpp (+73/-54)
src/modules/Unity/Application/session.h (+8/-4)
src/modules/Unity/Application/session_interface.h (+16/-4)
tests/modules/ApplicationManager/application_manager_test.cpp (+1/-1)
tests/modules/SessionManager/session_test.cpp (+3/-3)
tests/modules/common/fake_mirsurface.h (+2/-0)
tests/modules/common/fake_session.h (+4/-2)
tests/modules/common/mock_session.h (+8/-6)
To merge this branch: bzr merge lp:~dandrader/qtmir/multiSurfaceApp
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Needs Fixing
Michael Zanetti (community) functional testing Approve
Gerry Boland (community) code Approve
Review via email: mp+267395@code.launchpad.net

This proposal has been superseded by a proposal from 2015-12-01.

Commit message

Make Session hold multiple surfaces

Description of the change

* Are there any related MPs required for this MP to build/function as expected? Please list.
https://code.launchpad.net/~dandrader/unity8/multiSurfaceApp/+merge/271613

* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes.

* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
N/A

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~dandrader/qtmir/multiSurfaceApp updated
359. By Daniel van Vugt

MirSurfaceItem: Remove an unnecessary and potentially infinite loop
(LP: #1477430)

We only need to "drop" or consume one frame to do the job of waking
the client up.
 Fixes: #1477430
Approved by: Gerry Boland, PS Jenkins bot

360. By Gerry Boland

authorizeSession incorrectly edits desktopFilePath supplied by desktop_file_hint Fixes: #1483225
Approved by: Daniel d'Andrada, PS Jenkins bot

361. By Gerry Boland

Standardize licences to LGPLv3, update years, remove authors Fixes: #1483664
Approved by: Daniel d'Andrada

362. By Gerry Boland

Add vivid changelog entry as it was released

363. By CI Train Bot Account

Releasing 0.4.5+15.04.20150812.1-0ubuntu1

Revision history for this message
Gerry Boland (gerboland) wrote :

Please merge trunk, many conflicts have appeared.

+void Session::appendSurface
+void Session::reallyAppendSurface
these names confuse me. Perhaps rename to something like:
appendSurface -> registerSurface
reallyAppendSurface -> appendSurface

 qDebug() << "Application::suspend - no surface to call stopFrameDropper() on!";
I think we can move this to category logging

+ return const_cast<ObjectListModel<MirSurfaceInterface>*>(&m_surfaces);
const_cast needed here? Can't the pointer be a pointer to a const object?

=== modified file 'src/modules/Unity/Application/session.h'
+ QList<MirSurfaceInterface*> m_blankSurfaces;
What use is this? I only see you append to and remove from this list, but never use it for anything.

+ Q_PROPERTY(MirSurfaceInterface* lastSurface READ lastSurface NOTIFY lastSurfaceChanged CONSTANT);
Can you add a "REMOVEME" comment to this, this is not an API I want to keep. It also not very correct, as what if the surface pointed to is removed, but other surfaces exist - should it not be updated?

review: Needs Fixing
lp:~dandrader/qtmir/multiSurfaceApp updated
364. By Alberto Aguirre

Remove protobuf - it is not used anymore.
Approved by: Gerry Boland

365. By CI Train Bot Account

Releasing 0.4.5+15.10.20150817-0ubuntu1

366. By CI Train Bot Account

Resync trunk.

367. By Daniel d'Andrada

Enable multiple MirSurfaceItems rendering the same MirSurface

So MirSurface is the model and MirSurfaceItem is the view+controller.

+ Make MirSurfaceItem instantiable from QML
+ Isolate all mir::scene::Surface code inside MirSurface
+ Enhanced qml-demo-shell: you can now move, resize and *clone* windows
Approved by: Gerry Boland

368. By Daniel d'Andrada

Allow resizing an app that is in the process of getting suspended.

Happens when you lock the phone while showing an app in landscape. As
the display turns off, shell rotates itself back to portrait and starts
suspending the app. Fixes: #1466510
Approved by: Gerry Boland

369. By CI Train Bot Account

Releasing 0.4.6+15.04.20150827.1-0ubuntu1

370. By Michał Sawicz

No-change rebuild to resync vivid+overlay and wily
Approved by: Michael Zanetti

371. By CI Train Bot Account

Releasing 0.4.6+15.10.20150904-0ubuntu1

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> Please merge trunk, many conflicts have appeared.

Done.

> +void Session::appendSurface
> +void Session::reallyAppendSurface
> these names confuse me. Perhaps rename to something like:
> appendSurface -> registerSurface
> reallyAppendSurface -> appendSurface

Done.

> qDebug() << "Application::suspend - no surface to call stopFrameDropper()
> on!";
> I think we can move this to category logging

Done.

> + return const_cast<ObjectListModel<MirSurfaceInterface>*>(&m_surfaces);
> const_cast needed here? Can't the pointer be a pointer to a const object?

Right. I was just blindly following the signature of childSessions. Fixed.

> === modified file 'src/modules/Unity/Application/session.h'
> + QList<MirSurfaceInterface*> m_blankSurfaces;
> What use is this? I only see you append to and remove from this list, but
> never use it for anything.

Originally it was meant to keep track of the surfaces that were registered but not yet appended. But later it turned out that this wasn't needed after all. Removed.

> + Q_PROPERTY(MirSurfaceInterface* lastSurface READ lastSurface NOTIFY
> lastSurfaceChanged CONSTANT);
> Can you add a "REMOVEME" comment to this, this is not an API I want to keep.
> It also not very correct, as what if the surface pointed to is removed, but
> other surfaces exist - should it not be updated?

This will be removed once unity8 starts using Session.surfaces. Ie, once it actually starts supporting multiple surfaces per application. It was just way too awkward to have untiy8 fetching the last surface from Session.surfaces in QML. Hence this property.

Added the FIXME comment to the property declaration.

lastSurface is being updated correctly as the surfaces model changes.

lp:~dandrader/qtmir/multiSurfaceApp updated
372. By Daniel van Vugt

Stop waking up every 200ms if there's nothing to wake up for.
It's just wasting battery.

This solves at least half of LP: #1479250. Although the regular
wakeup problem is solved by this, Unity8 continues to use noticeable
CPU while idle (obviously in much less frequent intervals now). Fixes: #1479250
Approved by: Gerry Boland

373. By Daniel d'Andrada

MirSurfaceItem gets dirty when it's set to draw a different (or no) surface Fixes: #1492185
Approved by: Gerry Boland

374. By Daniel d'Andrada

QtEventFeeder: log the pointer events it gets from Mir
Approved by: PS Jenkins bot, Gerry Boland

375. By CI Train Bot Account

Releasing 0.4.6+15.10.20150914-0ubuntu1

376. By Daniel d'Andrada

Update surface focus when a surface enters or leaves a MirSurfaceItem

+ Refactor MirSurfaceItem so that it talks to a MirSurfaceInterface
  instead of the concrete MirSurface class
+ Make MirSurface::setFocus() more robust Fixes: #1491034, #1495437
Approved by: PS Jenkins bot, Gerry Boland

377. By CI Train Bot Account

Releasing 0.4.6+15.10.20150918-0ubuntu1

378. By Cemil Azizoglu

Port gl_bind_to_texture to the new TextureSource interface.
Update for Mir 0.16 release.
Approved by: Alan Griffiths

379. By CI Train Bot Account

Releasing 0.4.6+15.10.20150923-0ubuntu1

380. By Michał Sawicz

Bump application API version
Approved by: Daniel d'Andrada

381. By CI Train Bot Account

Releasing 0.4.6+15.10.20150925-0ubuntu1

Revision history for this message
Gerry Boland (gerboland) wrote :

Code looks ok to me. There's a unity8 change needed to enable this fully though. Could you please link that MP here.

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

> Code looks ok to me. There's a unity8 change needed to enable this fully
> though. Could you please link that MP here.

Done

lp:~dandrader/qtmir/multiSurfaceApp updated
382. By Daniel d'Andrada

MirSurfaceItem: texture must be manipulated only from the scene graph thread

Do not delete the texture from within the GUI thread ever, even if the
MirSurfaceItem is no longer holding the MirSurface that provided it.
Otherwise you run the risk of having the scene graph thread dereferencing
a pointer to a texture that no longer exists.

This also fixes fd leak LP: #1495871 (which was a texture/buffer leak). Fixes: #1495871, #1499388
Approved by: Gerry Boland, PS Jenkins bot

383. By Gerry Boland

Add "Closing" state to Application, use it to distinguish user-induced close from app-induced close. Don't clear QML cache if user-induced.

Much code taken from a partially-related branch by Nick Dedekind:
https://code.launchpad.net/~nick-dedekind/qtmir/polite-close/+merge/262188

Note there is 1 disabled test, which needs additional work to fix. Fixes: #1500372
Approved by: PS Jenkins bot

384. By CI Train Bot Account

Releasing 0.4.6+15.10.20150930.1-0ubuntu1

385. By Alexandros Frantzis

Update for Mir 0.17 changes

386. By CI Train Bot Account

Releasing 0.4.6+15.10.20151008.2-0ubuntu1

387. By Albert Astals Cid

Don't search for the element again

Approved by: Gerry Boland, PS Jenkins bot

388. By Daniel d'Andrada

Shell draws its own cursor using the new Cursor QML element
Approved by: Lukáš Tinkl, Gerry Boland

389. By Gerry Boland

Initial multimonitor support - react correctly to Mir DisplayConfiguration changes.

On Mir DisplayConfiguration changes, QtMir now correctly:
1. blocks Mir until it has stopped all renderers and has their GL contexts released
2. reads the new DisplayConfiguration, matches any existing ScreenWindows to new DisplayBuffers should they change (as Mir may destroy and create it on us)
3. restarts all renderers

This also solves shutdown crash issues due to raciness of mir destroying the GL context backing the shell's QWindow before its renderer had stopped.

Add Unity.Screens qml module to advertise current screen state to QML. Fixes: #1436735, #1488831, #1488863
Approved by: Daniel d'Andrada

390. By Michał Sawicz

MirSurfaceItem: Survive holding a surface with an empty texture

Survive having a surface whose texture holds no mir buffer at all.
Instead of crashing in such situation we simply don't render it.
Approved by: Gerry Boland

391. By Michał Sawicz

Improve multimonitor support

* Removed magic:
 - Don't automagically select the screen where a window will be show.
   Let shell decide.
 - Don't automagically focus a window. Let shell handle it.

* Let shell know when a screen is about to be removed so that it has
  the opportunity to move or destroy a window in it before it's too late.
  - Added QGuiApplication::onScreenAboutToBeRemoved

* Added logging to key events
Approved by: Michał Sawicz

392. By Alan Griffiths

Opaquify MirWindowManager to control visibility of upcoming Window Management work
Approved by: Gerry Boland, PS Jenkins bot

393. By Lukáš Tinkl

React to surface modifications (window caption)
Approved by: Daniel d'Andrada

394. By Nick Dedekind

Removed the manipulation of the CMAKE_INSTALL_PREFIX from debian/rules
Approved by: Gerry Boland

395. By Nick Dedekind

Added touch performance tracing and test.
Approved by: Gerry Boland

396. By Lukáš Tinkl

Implement support for mouse wheel events; correctly pass around buttons Fixes: #1497091
Approved by: Gerry Boland

397. By Gerry Boland

Workaround for AutoPilot input coordinate positioning being outside screen geometry

398. By CI Train Bot Account

Releasing 0.4.6+15.10.20151021-0ubuntu1

Revision history for this message
Michael Zanetti (mzanetti) wrote :

I've tested it and it works.

review: Approve (functional testing)
lp:~dandrader/qtmir/multiSurfaceApp updated
399. By Michał Sawicz

Clean up packaging and fix autopkgtest on armhf
Approved by: Gerry Boland

400. By Michael Terry

Support new isTouchApp property to ApplicationInfoInterface and move lifecycle policy logic out of qtmir.

Now that qtmir won't decide policy for suspending anymore, we don't need all the lifecycleException handling in qtmir either. That can move to unity8.

But since the GSettings key for that was registered under the qtmir namespace (and there's no technical reason to migrate settings), I left the schema and classes dealing with GSettings alone, for future use.

401. By Nick Dedekind

Support server->client visibility change to stop rendering (lp:#1475678) Fixes: #1475678
Approved by: Daniel d'Andrada

402. By Alan Griffiths

Test harness for MirWindowManager (in preparation for more intelligent window management)
Approved by: Gerry Boland

403. By Nick Dedekind

Hand Qt millisecond timestamps rather than nanosecond. Fixes: #1510571, #1511076, #1511711
Approved by: Gerry Boland

404. By CI Train Bot Account

Releasing 0.4.6+16.04.20151102-0ubuntu1

405. By Nick Dedekind

Reverted occlusion detection (lp#1514556) Fixes: #1514556

406. By CI Train Bot Account

Releasing 0.4.6+16.04.20151110-0ubuntu1

407. By Gerry Boland

Fix armhf builds on Xenial by using -std=gnu99 instead of c99

Fixes this FTBFS on xenial:

In file included from /usr/include/lttng/tracepoint-rcu.h:26:0,
                 from /usr/include/lttng/tracepoint.h:29,
                 from /home/phablet/dev/projects/qtmir/qtmir/BUILD-xen/src/platforms/mirserver/tracepoints.h:10,
                 from /home/phablet/dev/projects/qtmir/qtmir/BUILD-xen/src/platforms/mirserver/tracepoints.c:7:
/usr/include/urcu/arch/generic.h: In function ‘caa_get_cycles’:
/usr/include/urcu/arch/generic.h:165:6: error: ‘CLOCK_MONOTONIC’ undeclared (first use in this function)
  if (caa_unlikely(clock_gettime(CLOCK_MONOTONIC, &ts)))
      ^
/usr/include/urcu/arch/generic.h:165:6: note: each undeclared identifier is reported only once for each function it appears in

Strictly should compile code with -std=gnu99 instead of -std=c99 to have the identifiers SIGEV_SIGNAL, sigeventStruct, and CLOCK_MONOTONIC available. These identifiers are declared when _POSIX_C_SOURCE is set to a value >= 199309L, which is the case with -std=gnu99. I could also have used -D_POSIX_C_SOURCE=199309L -std=c99 or have the macro defined in source code.

Did not impact wily as libuctu only started looking for CLOCK_MONOTONIC in Xenial release.
Approved by: Daniel d'Andrada

408. By CI Train Bot Account

Releasing 0.4.6+16.04.20151112-0ubuntu1

409. By Nick Dedekind

Update surface textures when dropping frames. Fixes: #1515356
Approved by: Gerry Boland

410. By CI Train Bot Account

Releasing 0.4.6+16.04.20151113-0ubuntu1

411. By Gerry Boland

Fix use of uninitialized variable
Approved by: Daniel d'Andrada, PS Jenkins bot

412. By Albert Astals Cid

Enable Efficient String Construction by default

See http://blog.qt.io/blog/2011/06/13/string-concatenation-with-qstringbuilder/
Approved by: Gerry Boland, PS Jenkins bot

413. By Michał Sawicz

Build with clang (tests/gmock fails and is unfixable on our side i'd say)
Approved by: Gerry Boland

414. By Gerry Boland

Use pid_t for PIDs.
Approved by: Daniel d'Andrada, PS Jenkins bot

415. By Loïc Molinari

Ensured Mir surface items with size less than or equal to zero are not rendered, as it's usually done for standard QtQuick items.
Approved by: Gerry Boland

416. By Nick Dedekind

Fix a crash when dropping a surface frame before Qt draws a surface item. Fixes: #1517139
Approved by: Gerry Boland

417. By CI Train Bot Account

Releasing 0.4.6+16.04.20151119-0ubuntu1

418. By Daniel d'Andrada

Implemented support for cursors set by client surfaces
Approved by: Lukáš Tinkl

419. By Gerry Boland

Manage frameSwapped signal/slot connection with MirSurface more strictly to avoid crash.

Direct Signal/slot connections across thread boundaries incur the same risks as any cross-thread calls. While connect/disconnect are thread safe methods, it is possible for a slot to be called while the slot owner is being deconstructed - and so not yet disconnected.

So watch for the Item's window change signal and disconnect signal immediately. Also move slot ownership to MirSurfaceItem to auto-disconnect more aggressively.
 Fixes: #1517571
Approved by: Daniel d'Andrada

420. By Daniel d'Andrada

Forward Mir mouse wheel events to the shell cursor Fixes: #1497091
Approved by: Lukáš Tinkl

421. By Daniel d'Andrada

Revert revision 415

The commit "Ensured Mir surface items with size less than or equal to zero are not rendered,
as it's usually done for standard QtQuick items." caused a regression.

MirSurface.size was being kept uninitialized, as QSize(-1,-1).

422. By CI Train Bot Account

Releasing 0.4.6+16.04.20151125-0ubuntu1

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
lp:~dandrader/qtmir/multiSurfaceApp updated
423. By Timo Jyrinki

Rebuild against Qt 5.5.1.

424. By Daniel d'Andrada

Merge lp:~dandrader/qtmir/surfaceItemFillMode

425. By Daniel d'Andrada

Make Session hold multiple surfaces

+ Standardize MirSurface debug messages and account for multiple surfaces per app

426. By Daniel d'Andrada

Merge surfaceItemFillMode again

427. By Daniel d'Andrada

Fix bad merge with polite-close

Unmerged revisions

427. By Daniel d'Andrada

Fix bad merge with polite-close

426. By Daniel d'Andrada

Merge surfaceItemFillMode again

425. By Daniel d'Andrada

Make Session hold multiple surfaces

+ Standardize MirSurface debug messages and account for multiple surfaces per app

424. By Daniel d'Andrada

Merge lp:~dandrader/qtmir/surfaceItemFillMode

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2015-11-25 15:38:50 +0000
+++ CMakeLists.txt 2015-12-01 12:47:17 +0000
@@ -75,7 +75,7 @@
75pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)75pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
76pkg_check_modules(QTDBUSTEST libqtdbustest-1 REQUIRED)76pkg_check_modules(QTDBUSTEST libqtdbustest-1 REQUIRED)
77pkg_check_modules(QTDBUSMOCK libqtdbusmock-1 REQUIRED)77pkg_check_modules(QTDBUSMOCK libqtdbusmock-1 REQUIRED)
78pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=11)78pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=12)
7979
80include_directories(${APPLICATION_API_INCLUDE_DIRS})80include_directories(${APPLICATION_API_INCLUDE_DIRS})
8181
8282
=== modified file 'debian/control'
--- debian/control 2015-11-25 15:38:50 +0000
+++ debian/control 2015-12-01 12:47:17 +0000
@@ -22,7 +22,7 @@
22 libubuntu-app-launch2-dev,22 libubuntu-app-launch2-dev,
23 libubuntu-application-api-dev (>= 2.1.0),23 libubuntu-application-api-dev (>= 2.1.0),
24 libudev-dev,24 libudev-dev,
25 libunity-api-dev (>= 7.103),25 libunity-api-dev (>= 7.104),
26 liburl-dispatcher1-dev,26 liburl-dispatcher1-dev,
27 libxkbcommon-dev,27 libxkbcommon-dev,
28 libxrender-dev,28 libxrender-dev,
@@ -93,7 +93,7 @@
93Conflicts: libqtmir,93Conflicts: libqtmir,
94 libunity-mir1,94 libunity-mir1,
95Provides: unity-application-impl,95Provides: unity-application-impl,
96 unity-application-impl-11,96 unity-application-impl-12,
97Description: Qt plugin for Unity specific Mir APIs97Description: Qt plugin for Unity specific Mir APIs
98 QtMir provides Qt/QML bindings for Mir features that are exposed through the98 QtMir provides Qt/QML bindings for Mir features that are exposed through the
99 qtmir-desktop or qtmir-android QPA plugin such as Application management99 qtmir-desktop or qtmir-android QPA plugin such as Application management
100100
=== modified file 'src/modules/Unity/Application/mirbuffersgtexture.cpp'
--- src/modules/Unity/Application/mirbuffersgtexture.cpp 2015-10-02 12:20:00 +0000
+++ src/modules/Unity/Application/mirbuffersgtexture.cpp 2015-12-01 12:47:17 +0000
@@ -21,6 +21,9 @@
21#include <mir/geometry/size.h>21#include <mir/geometry/size.h>
22#include <mir/renderer/gl/texture_source.h>22#include <mir/renderer/gl/texture_source.h>
2323
24// mirserver
25#include <logging.h>
26
24namespace mg = mir::geometry;27namespace mg = mir::geometry;
25namespace mrg = mir::renderer::gl;28namespace mrg = mir::renderer::gl;
2629
@@ -80,20 +83,25 @@
80 return m_mirBuffer->pixel_format() == mir_pixel_format_abgr_888883 return m_mirBuffer->pixel_format() == mir_pixel_format_abgr_8888
81 || m_mirBuffer->pixel_format() == mir_pixel_format_argb_8888;84 || m_mirBuffer->pixel_format() == mir_pixel_format_argb_8888;
82 } else {85 } else {
86 qCWarning(QTMIR_SURFACES) << "MirBufferSGTexture: hasAlphaChannel() called but there's no mir buffer to query";
83 return false;87 return false;
84 }88 }
85}89}
8690
87void MirBufferSGTexture::bind()91void MirBufferSGTexture::bind()
88{92{
89 Q_ASSERT(hasBuffer());93 if (hasBuffer()) {
90 glBindTexture(GL_TEXTURE_2D, m_textureId);94 glBindTexture(GL_TEXTURE_2D, m_textureId);
91 updateBindOptions(true/* force */);95 updateBindOptions(true/* force */);
9296
93 auto const texture_source =97 auto const texture_source =
94 dynamic_cast<mrg::TextureSource*>(m_mirBuffer->native_buffer_base());98 dynamic_cast<mrg::TextureSource*>(m_mirBuffer->native_buffer_base());
95 if (!texture_source)99 if (!texture_source)
96 throw std::logic_error("Buffer does not support GL rendering");100 throw std::logic_error("Buffer does not support GL rendering");
97101
98 texture_source->gl_bind_to_texture();102 texture_source->gl_bind_to_texture();
103 } else {
104 qCWarning(QTMIR_SURFACES) << "MirBufferSGTexture: bind() called but there's no mir buffer to bind to";
105 glBindTexture(GL_TEXTURE_2D, 0);
106 }
99}107}
100108
=== modified file 'src/modules/Unity/Application/mirsurface.cpp'
--- src/modules/Unity/Application/mirsurface.cpp 2015-11-25 15:38:39 +0000
+++ src/modules/Unity/Application/mirsurface.cpp 2015-12-01 12:47:17 +0000
@@ -25,6 +25,7 @@
2525
26// Mir26// Mir
27#include <mir/geometry/rectangle.h>27#include <mir/geometry/rectangle.h>
28#include <mir/graphics/buffer.h>
28#include <mir/events/event_builders.h>29#include <mir/events/event_builders.h>
29#include <mir/shell/shell.h>30#include <mir/shell/shell.h>
30#include <mir_toolkit/event.h>31#include <mir_toolkit/event.h>
@@ -34,6 +35,8 @@
3435
35using namespace qtmir;36using namespace qtmir;
3637
38#define DEBUG_MSG qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << (void*)this << "," << appId() <<"]::" << __func__
39
37namespace {40namespace {
3841
39// Would be better if QMouseEvent had nativeModifiers42// Would be better if QMouseEvent had nativeModifiers
@@ -216,7 +219,7 @@
216 Q_ASSERT(m_views.isEmpty());219 Q_ASSERT(m_views.isEmpty());
217220
218 if (m_session) {221 if (m_session) {
219 m_session->setSurface(nullptr);222 m_session->removeSurface(this);
220 }223 }
221224
222 QMutexLocker locker(&m_mutex);225 QMutexLocker locker(&m_mutex);
@@ -297,15 +300,14 @@
297 int framesPending = m_surface->buffers_ready_for_compositor(userId);300 int framesPending = m_surface->buffers_ready_for_compositor(userId);
298 if (framesPending > 0) {301 if (framesPending > 0) {
299 m_textureUpdated = false;302 m_textureUpdated = false;
300 303
301 locker.unlock();304 locker.unlock();
302 if (updateTexture()) {305 if (updateTexture()) {
303 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::dropPendingBuffer() dropped=1 left=" << framesPending-1;306 DEBUG_MSG << "() dropped=1 left=" << framesPending-1;
304 } else {307 } else {
305 // If we haven't managed to update the texture, don't keep banging away.308 // If we haven't managed to update the texture, don't keep banging away.
306 m_frameDropperTimer.stop();309 m_frameDropperTimer.stop();
307 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::dropPendingBuffer() dropped=0"310 DEBUG_MSG << "() dropped=0" << " left=" << framesPending << " - failed to upate texture";
308 << " left=" << framesPending << " - failed to upate texture";
309 }311 }
310 Q_EMIT frameDropped();312 Q_EMIT frameDropped();
311 } else {313 } else {
@@ -319,13 +321,13 @@
319321
320void MirSurface::stopFrameDropper()322void MirSurface::stopFrameDropper()
321{323{
322 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::stopFrameDropper()";324 DEBUG_MSG << "()";
323 m_frameDropperTimer.stop();325 m_frameDropperTimer.stop();
324}326}
325327
326void MirSurface::startFrameDropper()328void MirSurface::startFrameDropper()
327{329{
328 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::startFrameDropper()";330 DEBUG_MSG << "()";
329 if (!m_frameDropperTimer.isActive()) {331 if (!m_frameDropperTimer.isActive()) {
330 m_frameDropperTimer.start();332 m_frameDropperTimer.start();
331 }333 }
@@ -355,39 +357,53 @@
355 return texture->hasBuffer();357 return texture->hasBuffer();
356 }358 }
357359
358 const void* const userId = (void*)123;360 if (m_pendingBuffer) {
359 auto renderables = m_surface->generate_renderables(userId);
360
361 if (renderables.size() > 0 &&
362 (m_surface->buffers_ready_for_compositor(userId) > 0 || !texture->hasBuffer())
363 ) {
364 // Avoid holding two buffers for the compositor at the same time. Thus free the current361 // Avoid holding two buffers for the compositor at the same time. Thus free the current
365 // before acquiring the next362 // before acquiring the next
366 texture->freeBuffer();363 texture->freeBuffer();
367 texture->setBuffer(renderables[0]->buffer());364 texture->setBuffer(m_pendingBuffer);
365 m_pendingBuffer.reset();
368 ++m_currentFrameNumber;366 ++m_currentFrameNumber;
369367 }
370 if (texture->textureSize() != m_size) {368
371 m_size = texture->textureSize();369 m_textureUpdated = true;
372 QMetaObject::invokeMethod(this, "emitSizeChanged", Qt::QueuedConnection);370
371 return texture->hasBuffer();
372}
373
374void MirSurface::consumeBuffer()
375{
376 QMutexLocker locker(&m_mutex);
377 const void* const userId = (void*)123;
378 auto renderables = m_surface->generate_renderables(userId);
379
380 if (renderables.size() > 0 && m_surface->buffers_ready_for_compositor(userId) > 0) {
381 m_pendingBuffer = renderables[0]->buffer();
382
383 QSize size(m_pendingBuffer->size().width.as_int(),
384 m_pendingBuffer->size().height.as_int());
385 if (size != m_size) {
386 m_size = size;
387 Q_EMIT sizeChanged(m_size);
373 }388 }
374
375 m_textureUpdated = true;
376 }389 }
377390
378 if (m_surface->buffers_ready_for_compositor(userId) > 0) {391 if (m_surface->buffers_ready_for_compositor(userId) > 0) {
379 // restart the frame dropper to give MirSurfaceItems enough time to render the next frame.392 // restart the frame dropper to give MirSurfaceItems enough time to render the next frame.
380 // queued since the timer lives in a different thread393 QMetaObject::invokeMethod(&m_frameDropperTimer, "start", Qt::AutoConnection);
381 QMetaObject::invokeMethod(&m_frameDropperTimer, "start", Qt::QueuedConnection);
382 }394 }
383
384 return texture->hasBuffer();
385}395}
386396
387void MirSurface::onCompositorSwappedBuffers()397void MirSurface::onCompositorSwappedBuffers()
388{398{
389 QMutexLocker locker(&m_mutex);399 QMutexLocker locker(&m_mutex);
390 m_textureUpdated = false;400 m_textureUpdated = false;
401
402 if (m_texture && m_pendingBuffer) {
403 // No need to hold onto this buffer as it won't be used on the next frame.
404 MirBufferSGTexture *texture = static_cast<MirBufferSGTexture*>(m_texture.data());
405 texture->freeBuffer();
406 }
391}407}
392408
393bool MirSurface::numBuffersReadyForCompositor()409bool MirSurface::numBuffersReadyForCompositor()
@@ -406,12 +422,11 @@
406 // Temporary hotfix for http://pad.lv/1483752422 // Temporary hotfix for http://pad.lv/1483752
407 if (m_session->childSessions()->rowCount() > 0) {423 if (m_session->childSessions()->rowCount() > 0) {
408 // has child trusted session, ignore any focus change attempts424 // has child trusted session, ignore any focus change attempts
409 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::setFocus(" << focus425 DEBUG_MSG << "(" << focus << ") - has child trusted session, ignore any focus change attempts";
410 << ") - has child trusted session, ignore any focus change attempts";
411 return;426 return;
412 }427 }
413428
414 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::setFocus(" << focus << ")";429 DEBUG_MSG << "(" << focus << ")";
415430
416 if (focus) {431 if (focus) {
417 m_shell->set_surface_attribute(m_session->session(), m_surface, mir_surface_attrib_focus, mir_surface_focused);432 m_shell->set_surface_attribute(m_session->session(), m_surface, mir_surface_attrib_focus, mir_surface_focused);
@@ -430,9 +445,8 @@
430 if (clientIsRunning() && mirSizeIsDifferent) {445 if (clientIsRunning() && mirSizeIsDifferent) {
431 mir::geometry::Size newMirSize(width, height);446 mir::geometry::Size newMirSize(width, height);
432 m_surface->resize(newMirSize);447 m_surface->resize(newMirSize);
433 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::resize"448 DEBUG_MSG << " old (" << mirWidth << "," << mirHeight << ")"
434 << " old (" << mirWidth << "," << mirHeight << ")"449 << ", new (" << width << "," << height << ")";
435 << ", new (" << width << "," << height << ")";
436 }450 }
437}451}
438452
@@ -659,8 +673,7 @@
659void MirSurface::registerView(qintptr viewId)673void MirSurface::registerView(qintptr viewId)
660{674{
661 m_views.insert(viewId, MirSurface::View{false});675 m_views.insert(viewId, MirSurface::View{false});
662 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::registerView(" << viewId << ")"676 DEBUG_MSG << "(" << viewId << ")" << " after=" << m_views.count();
663 << " after=" << m_views.count();
664 if (m_views.count() == 1) {677 if (m_views.count() == 1) {
665 Q_EMIT isBeingDisplayedChanged();678 Q_EMIT isBeingDisplayedChanged();
666 }679 }
@@ -668,9 +681,8 @@
668681
669void MirSurface::unregisterView(qintptr viewId)682void MirSurface::unregisterView(qintptr viewId)
670{683{
671 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::unregisterView(" << viewId << ")"
672 << " after=" << m_views.count() << " live=" << m_live;
673 m_views.remove(viewId);684 m_views.remove(viewId);
685 DEBUG_MSG << "(" << viewId << ")" << " after=" << m_views.count() << " live=" << m_live;
674 if (m_views.count() == 0) {686 if (m_views.count() == 0) {
675 Q_EMIT isBeingDisplayedChanged();687 Q_EMIT isBeingDisplayedChanged();
676 if (m_session.isNull() || !m_live) {688 if (m_session.isNull() || !m_live) {
@@ -701,7 +713,7 @@
701 }713 }
702714
703 if (newVisible != visible()) {715 if (newVisible != visible()) {
704 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::updateVisibility(" << newVisible << ")";716 DEBUG_MSG << "(" << newVisible << ")";
705717
706 m_surface->configure(mir_surface_attrib_visibility,718 m_surface->configure(mir_surface_attrib_visibility,
707 newVisible ? mir_surface_visibility_exposed : mir_surface_visibility_occluded);719 newVisible ? mir_surface_visibility_exposed : mir_surface_visibility_occluded);
@@ -745,8 +757,7 @@
745757
746void MirSurface::setCursor(const QCursor &cursor)758void MirSurface::setCursor(const QCursor &cursor)
747{759{
748 qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::setCursor("760 DEBUG_MSG << "(" << qtCursorShapeToStr(cursor.shape()) << ")";
749 << qtCursorShapeToStr(cursor.shape()) << ")";
750761
751 m_cursor = cursor;762 m_cursor = cursor;
752 Q_EMIT cursorChanged(m_cursor);763 Q_EMIT cursorChanged(m_cursor);
753764
=== modified file 'src/modules/Unity/Application/mirsurface.h'
--- src/modules/Unity/Application/mirsurface.h 2015-11-25 15:38:39 +0000
+++ src/modules/Unity/Application/mirsurface.h 2015-12-01 12:47:17 +0000
@@ -35,7 +35,10 @@
35#include <mir/scene/surface.h>35#include <mir/scene/surface.h>
36#include <mir_toolkit/common.h>36#include <mir_toolkit/common.h>
3737
38namespace mir { namespace shell { class Shell; }}38namespace mir {
39 namespace shell { class Shell; }
40 namespace graphics { class Buffer; }
41}
3942
40class SurfaceObserver;43class SurfaceObserver;
4144
@@ -89,6 +92,8 @@
89 void unregisterView(qintptr viewId) override;92 void unregisterView(qintptr viewId) override;
90 void setViewVisibility(qintptr viewId, bool visible) override;93 void setViewVisibility(qintptr viewId, bool visible) override;
9194
95 void consumeBuffer() override;
96
92 // methods called from the rendering (scene graph) thread:97 // methods called from the rendering (scene graph) thread:
93 QSharedPointer<QSGTexture> texture() override;98 QSharedPointer<QSGTexture> texture() override;
94 QSGTexture *weakTexture() const override { return m_texture.data(); }99 QSGTexture *weakTexture() const override { return m_texture.data(); }
@@ -120,7 +125,9 @@
120 QCursor cursor() const override;125 QCursor cursor() const override;
121126
122public Q_SLOTS:127public Q_SLOTS:
128 // methods called from the rendering (scene graph) thread:
123 void onCompositorSwappedBuffers() override;129 void onCompositorSwappedBuffers() override;
130 // end of methods called from the rendering (scene graph) thread
124131
125private Q_SLOTS:132private Q_SLOTS:
126 void dropPendingBuffer();133 void dropPendingBuffer();
@@ -163,6 +170,8 @@
163 QSize m_size;170 QSize m_size;
164171
165 QCursor m_cursor;172 QCursor m_cursor;
173
174 std::shared_ptr<mir::graphics::Buffer> m_pendingBuffer;
166};175};
167176
168} // namespace qtmir177} // namespace qtmir
169178
=== modified file 'src/modules/Unity/Application/mirsurfaceinterface.h'
--- src/modules/Unity/Application/mirsurfaceinterface.h 2015-11-25 15:38:39 +0000
+++ src/modules/Unity/Application/mirsurfaceinterface.h 2015-12-01 12:47:17 +0000
@@ -54,6 +54,8 @@
54 virtual void unregisterView(qintptr viewId) = 0;54 virtual void unregisterView(qintptr viewId) = 0;
55 virtual void setViewVisibility(qintptr viewId, bool visible) = 0;55 virtual void setViewVisibility(qintptr viewId, bool visible) = 0;
5656
57 virtual void consumeBuffer() = 0;
58
57 // methods called from the rendering (scene graph) thread:59 // methods called from the rendering (scene graph) thread:
58 virtual QSharedPointer<QSGTexture> texture() = 0;60 virtual QSharedPointer<QSGTexture> texture() = 0;
59 virtual QSGTexture *weakTexture() const = 0;61 virtual QSGTexture *weakTexture() const = 0;
@@ -88,7 +90,9 @@
88 void cursorChanged(const QCursor &cursor);90 void cursorChanged(const QCursor &cursor);
8991
90public Q_SLOTS:92public Q_SLOTS:
93 // methods called from the rendering (scene graph) thread:
91 virtual void onCompositorSwappedBuffers() = 0;94 virtual void onCompositorSwappedBuffers() = 0;
95 // end of methods called from the rendering (scene graph) thread
9296
93Q_SIGNALS:97Q_SIGNALS:
94 void firstFrameDrawn();98 void firstFrameDrawn();
9599
=== modified file 'src/modules/Unity/Application/mirsurfaceitem.cpp'
--- src/modules/Unity/Application/mirsurfaceitem.cpp 2015-11-25 15:38:54 +0000
+++ src/modules/Unity/Application/mirsurfaceitem.cpp 2015-12-01 12:47:17 +0000
@@ -92,6 +92,7 @@
92 , m_surfaceHeight(0)92 , m_surfaceHeight(0)
93 , m_orientationAngle(nullptr)93 , m_orientationAngle(nullptr)
94 , m_consumesInput(false)94 , m_consumesInput(false)
95 , m_fillMode(Stretch)
95{96{
96 qCDebug(QTMIR_SURFACES) << "MirSurfaceItem::MirSurfaceItem";97 qCDebug(QTMIR_SURFACES) << "MirSurfaceItem::MirSurfaceItem";
9798
@@ -227,7 +228,7 @@
227 }228 }
228229
229 if (m_surface->numBuffersReadyForCompositor() > 0) {230 if (m_surface->numBuffersReadyForCompositor() > 0) {
230 QTimer::singleShot(0, this, SLOT(update()));231 QTimer::singleShot(0, this, SLOT(polishAndUpdate()));
231 }232 }
232233
233 m_textureProvider->smooth = smooth();234 m_textureProvider->smooth = smooth();
@@ -235,20 +236,35 @@
235 QSGDefaultImageNode *node = static_cast<QSGDefaultImageNode*>(oldNode);236 QSGDefaultImageNode *node = static_cast<QSGDefaultImageNode*>(oldNode);
236 if (!node) {237 if (!node) {
237 node = new QSGDefaultImageNode;238 node = new QSGDefaultImageNode;
238 node->setTexture(m_textureProvider->texture());
239
240 node->setMipmapFiltering(QSGTexture::None);239 node->setMipmapFiltering(QSGTexture::None);
241 node->setHorizontalWrapMode(QSGTexture::ClampToEdge);240 node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
242 node->setVerticalWrapMode(QSGTexture::ClampToEdge);241 node->setVerticalWrapMode(QSGTexture::ClampToEdge);
243 node->setSubSourceRect(QRectF(0, 0, 1, 1));
244 } else {242 } else {
245 if (!m_lastFrameNumberRendered || (*m_lastFrameNumberRendered != m_surface->currentFrameNumber())) {243 if (!m_lastFrameNumberRendered || (*m_lastFrameNumberRendered != m_surface->currentFrameNumber())) {
246 node->markDirty(QSGNode::DirtyMaterial);244 node->markDirty(QSGNode::DirtyMaterial);
247 }245 }
248 }246 }
249247 node->setTexture(m_textureProvider->texture());
250 node->setTargetRect(QRectF(0, 0, width(), height()));248
251 node->setInnerTargetRect(QRectF(0, 0, width(), height()));249 if (m_fillMode == PadOrCrop) {
250 const QSize &textureSize = m_textureProvider->texture()->textureSize();
251
252 QRectF targetRect;
253 targetRect.setWidth(qMin(width(), static_cast<qreal>(textureSize.width())));
254 targetRect.setHeight(qMin(height(), static_cast<qreal>(textureSize.height())));
255
256 qreal u = targetRect.width() / textureSize.width();
257 qreal v = targetRect.height() / textureSize.height();
258 node->setSubSourceRect(QRectF(0, 0, u, v));
259
260 node->setTargetRect(targetRect);
261 node->setInnerTargetRect(targetRect);
262 } else {
263 // Stretch
264 node->setSubSourceRect(QRectF(0, 0, 1, 1));
265 node->setTargetRect(QRectF(0, 0, width(), height()));
266 node->setInnerTargetRect(QRectF(0, 0, width(), height()));
267 }
252268
253 node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);269 node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
254 node->setAntialiasing(antialiasing());270 node->setAntialiasing(antialiasing());
@@ -626,7 +642,7 @@
626642
627 // When a new mir frame gets posted we notify the QML engine that this item needs redrawing,643 // When a new mir frame gets posted we notify the QML engine that this item needs redrawing,
628 // schedules call to updatePaintNode() from the rendering thread644 // schedules call to updatePaintNode() from the rendering thread
629 connect(m_surface, &MirSurfaceInterface::framesPosted, this, &QQuickItem::update);645 connect(m_surface, &MirSurfaceInterface::framesPosted, this, &MirSurfaceItem::polishAndUpdate);
630646
631 connect(m_surface, &MirSurfaceInterface::stateChanged, this, &MirSurfaceItem::surfaceStateChanged);647 connect(m_surface, &MirSurfaceInterface::stateChanged, this, &MirSurfaceItem::surfaceStateChanged);
632 connect(m_surface, &MirSurfaceInterface::liveChanged, this, &MirSurfaceItem::liveChanged);648 connect(m_surface, &MirSurfaceInterface::liveChanged, this, &MirSurfaceItem::liveChanged);
@@ -730,6 +746,33 @@
730 }746 }
731}747}
732748
749MirSurfaceItem::FillMode MirSurfaceItem::fillMode() const
750{
751 return m_fillMode;
752}
753
754void MirSurfaceItem::setFillMode(FillMode value)
755{
756 if (m_fillMode != value) {
757 m_fillMode = value;
758 Q_EMIT fillModeChanged(m_fillMode);
759 }
760}
761
762void MirSurfaceItem::polishAndUpdate()
763{
764 polish();
765 update();
766}
767
768void MirSurfaceItem::updatePolish()
769{
770 if (!m_surface || !m_surface->live()) {
771 return;
772 }
773 m_surface->consumeBuffer();
774}
775
733} // namespace qtmir776} // namespace qtmir
734777
735#include "mirsurfaceitem.moc"778#include "mirsurfaceitem.moc"
736779
=== modified file 'src/modules/Unity/Application/mirsurfaceitem.h'
--- src/modules/Unity/Application/mirsurfaceitem.h 2015-11-25 15:38:44 +0000
+++ src/modules/Unity/Application/mirsurfaceitem.h 2015-12-01 12:47:17 +0000
@@ -68,6 +68,9 @@
68 int surfaceHeight() const override;68 int surfaceHeight() const override;
69 void setSurfaceHeight(int value) override;69 void setSurfaceHeight(int value) override;
7070
71 FillMode fillMode() const override;
72 void setFillMode(FillMode value) override;
73
71 ////////74 ////////
72 // QQuickItem75 // QQuickItem
7376
@@ -107,6 +110,8 @@
107110
108 void releaseResources() override;111 void releaseResources() override;
109112
113 void updatePolish() override;
114
110private Q_SLOTS:115private Q_SLOTS:
111 void scheduleMirSurfaceSizeUpdate();116 void scheduleMirSurfaceSizeUpdate();
112 void updateMirSurfaceSize();117 void updateMirSurfaceSize();
@@ -119,6 +124,8 @@
119124
120 void onWindowChanged(QQuickWindow *window);125 void onWindowChanged(QQuickWindow *window);
121126
127 void polishAndUpdate();
128
122private:129private:
123 void ensureTextureProvider();130 void ensureTextureProvider();
124131
@@ -168,6 +175,8 @@
168 Mir::OrientationAngle *m_orientationAngle;175 Mir::OrientationAngle *m_orientationAngle;
169176
170 bool m_consumesInput;177 bool m_consumesInput;
178
179 FillMode m_fillMode;
171};180};
172181
173} // namespace qtmir182} // namespace qtmir
174183
=== modified file 'src/modules/Unity/Application/mirsurfacemanager.cpp'
--- src/modules/Unity/Application/mirsurfacemanager.cpp 2015-10-09 15:35:05 +0000
+++ src/modules/Unity/Application/mirsurfacemanager.cpp 2015-12-01 12:47:17 +0000
@@ -110,7 +110,7 @@
110 }110 }
111111
112 if (session)112 if (session)
113 session->setSurface(qmlSurface);113 session->registerSurface(qmlSurface);
114114
115 // Only notify QML of surface creation once it has drawn its first frame.115 // Only notify QML of surface creation once it has drawn its first frame.
116 connect(qmlSurface, &MirSurfaceInterface::firstFrameDrawn, this, [=]() {116 connect(qmlSurface, &MirSurfaceInterface::firstFrameDrawn, this, [=]() {
117117
=== modified file 'src/modules/Unity/Application/session.cpp'
--- src/modules/Unity/Application/session.cpp 2015-08-31 09:51:28 +0000
+++ src/modules/Unity/Application/session.cpp 2015-12-01 12:47:17 +0000
@@ -46,7 +46,6 @@
46 : SessionInterface(parent)46 : SessionInterface(parent)
47 , m_session(session)47 , m_session(session)
48 , m_application(nullptr)48 , m_application(nullptr)
49 , m_surface(nullptr)
50 , m_parentSession(nullptr)49 , m_parentSession(nullptr)
51 , m_children(new SessionModel(this))50 , m_children(new SessionModel(this))
52 , m_fullscreen(false)51 , m_fullscreen(false)
@@ -86,10 +85,15 @@
86void Session::doSuspend()85void Session::doSuspend()
87{86{
88 Q_ASSERT(m_state == Session::Suspending);87 Q_ASSERT(m_state == Session::Suspending);
89 if (m_surface) {88
90 m_surface->stopFrameDropper();89
90 auto surfaceList = m_surfaces.list();
91 if (surfaceList.empty()) {
92 qCDebug(QTMIR_SESSIONS) << "Application::suspend - no surface to call stopFrameDropper() on!";
91 } else {93 } else {
92 qDebug() << "Application::suspend - no surface to call stopFrameDropper() on!";94 for (int i = 0; i < surfaceList.count(); ++i) {
95 surfaceList[i]->stopFrameDropper();
96 }
93 }97 }
94 setState(Suspended);98 setState(Suspended);
95}99}
@@ -120,14 +124,9 @@
120 return m_application;124 return m_application;
121}125}
122126
123MirSurfaceInterface* Session::surface() const127const ObjectListModel<MirSurfaceInterface>* Session::surfaces() const
124{128{
125 // Only notify QML of surface creation once it has drawn its first frame.129 return &m_surfaces;
126 if (m_surface && m_surface->isFirstFrameDrawn()) {
127 return m_surface;
128 } else {
129 return nullptr;
130 }
131}130}
132131
133SessionInterface* Session::parentSession() const132SessionInterface* Session::parentSession() const
@@ -166,55 +165,57 @@
166 Q_EMIT applicationChanged(application);165 Q_EMIT applicationChanged(application);
167}166}
168167
169void Session::setSurface(MirSurfaceInterface *newSurface)168void Session::registerSurface(MirSurfaceInterface *newSurface)
170{169{
171 qCDebug(QTMIR_SESSIONS) << "Session::setSurface - session=" << name() << "surface=" << newSurface;170 qCDebug(QTMIR_SESSIONS) << "Session::resgisterSurface - session=" << name() << "surface=" << newSurface;
172171
173 if (newSurface == m_surface) {172 // Only notify QML of surface creation once it has drawn its first frame.
174 return;173 if (newSurface->isFirstFrameDrawn()) {
175 }174 appendSurface(newSurface);
176175 } else {
177 if (m_surface) {176 connect(newSurface, &MirSurfaceInterface::firstFrameDrawn,
178 m_surface->disconnect(this);177 this, [this, newSurface]() { this->appendSurface(newSurface); });
179 }
180
181 MirSurfaceInterface *previousSurface = surface();
182 m_surface = newSurface;
183
184 if (newSurface) {
185 connect(newSurface, &MirSurfaceInterface::stateChanged,
186 this, &Session::updateFullscreenProperty);
187
188 // Only notify QML of surface creation once it has drawn its first frame.
189 if (m_surface->isFirstFrameDrawn()) {
190 setState(Running);
191 } else {
192 connect(newSurface, &MirSurfaceInterface::firstFrameDrawn,
193 this, &Session::onFirstSurfaceFrameDrawn);
194 }
195 }
196
197 if (previousSurface != surface()) {
198 qCDebug(QTMIR_SESSIONS).nospace() << "Session::surfaceChanged - session=" << this
199 << " surface=" << m_surface;
200 Q_EMIT surfaceChanged(m_surface);
201 }178 }
202179
203 updateFullscreenProperty();180 updateFullscreenProperty();
204}181}
205182
206void Session::onFirstSurfaceFrameDrawn()183void Session::appendSurface(MirSurfaceInterface *newSurface)
207{184{
208 qCDebug(QTMIR_SESSIONS).nospace() << "Session::surfaceChanged - session=" << this185 qCDebug(QTMIR_SESSIONS) << "Session::appendSurface - session=" << name() << "surface=" << newSurface;
209 << " surface=" << m_surface;186
210 Q_EMIT surfaceChanged(m_surface);187 connect(newSurface, &MirSurfaceInterface::stateChanged,
211 setState(Running);188 this, &Session::updateFullscreenProperty);
189
190 m_surfaces.insert(m_surfaces.rowCount(), newSurface);
191
192 Q_EMIT lastSurfaceChanged(newSurface);
193
194 if (m_state == Starting) {
195 setState(Running);
196 }
197}
198
199void Session::removeSurface(MirSurfaceInterface* surface)
200{
201 qCDebug(QTMIR_SESSIONS) << "Session::removeSurface - session=" << name() << "surface=" << surface;
202
203 surface->disconnect(this);
204
205 if (m_surfaces.contains(surface)) {
206 bool lastSurfaceWasRemoved = lastSurface() == surface;
207 m_surfaces.remove(surface);
208 if (lastSurfaceWasRemoved) {
209 Q_EMIT lastSurfaceChanged(lastSurface());
210 }
211 }
212}212}
213213
214void Session::updateFullscreenProperty()214void Session::updateFullscreenProperty()
215{215{
216 if (m_surface) {216 if (m_surfaces.rowCount() > 0) {
217 setFullscreen(m_surface->state() == Mir::FullscreenState);217 // TODO: Figure out something better
218 setFullscreen(m_surfaces.list().at(0)->state() == Mir::FullscreenState);
218 } else {219 } else {
219 // Keep the current value of the fullscreen property until we get a new220 // Keep the current value of the fullscreen property until we get a new
220 // surface221 // surface
@@ -264,8 +265,11 @@
264 Q_ASSERT(m_suspendTimer->isActive());265 Q_ASSERT(m_suspendTimer->isActive());
265 m_suspendTimer->stop();266 m_suspendTimer->stop();
266 } else if (m_state == Suspended) {267 } else if (m_state == Suspended) {
267 Q_ASSERT(m_surface);268 Q_ASSERT(m_surfaces.rowCount() > 0);
268 m_surface->startFrameDropper();269 auto surfaceList = m_surfaces.list();
270 for (int i = 0; i < surfaceList.count(); ++i) {
271 surfaceList[i]->startFrameDropper();
272 }
269 }273 }
270274
271 session()->set_lifecycle_state(mir_lifecycle_state_resumed);275 session()->set_lifecycle_state(mir_lifecycle_state_resumed);
@@ -285,10 +289,16 @@
285{289{
286 if (m_state != Stopped) {290 if (m_state != Stopped) {
287 stopPromptSessions();291 stopPromptSessions();
292
288 if (m_suspendTimer->isActive())293 if (m_suspendTimer->isActive())
289 m_suspendTimer->stop();294 m_suspendTimer->stop();
290 if (m_surface)295
291 m_surface->stopFrameDropper();296 {
297 auto surfaceList = m_surfaces.list();
298 for (int i = 0; i < surfaceList.count(); ++i) {
299 surfaceList[i]->stopFrameDropper();
300 }
301 }
292302
293 foreachChildSession([](SessionInterface* session) {303 foreachChildSession([](SessionInterface* session) {
294 session->stop();304 session->stop();
@@ -422,4 +432,13 @@
422 }432 }
423}433}
424434
435MirSurfaceInterface* Session::lastSurface() const
436{
437 if (m_surfaces.rowCount() > 0) {
438 return m_surfaces.list().last();
439 } else {
440 return nullptr;
441 }
442}
443
425} // namespace qtmir444} // namespace qtmir
426445
=== modified file 'src/modules/Unity/Application/session.h'
--- src/modules/Unity/Application/session.h 2015-08-31 09:51:28 +0000
+++ src/modules/Unity/Application/session.h 2015-12-01 12:47:17 +0000
@@ -52,14 +52,17 @@
52 //getters52 //getters
53 QString name() const override;53 QString name() const override;
54 unity::shell::application::ApplicationInfoInterface* application() const override;54 unity::shell::application::ApplicationInfoInterface* application() const override;
55 MirSurfaceInterface* surface() const override;55 MirSurfaceInterface* lastSurface() const override;
56 const ObjectListModel<MirSurfaceInterface>* surfaces() const override;
56 SessionInterface* parentSession() const override;57 SessionInterface* parentSession() const override;
57 State state() const override;58 State state() const override;
58 bool fullscreen() const override;59 bool fullscreen() const override;
59 bool live() const override;60 bool live() const override;
6061
61 void setApplication(unity::shell::application::ApplicationInfoInterface* item) override;62 void setApplication(unity::shell::application::ApplicationInfoInterface* item) override;
62 void setSurface(MirSurfaceInterface* surface) override;63
64 void registerSurface(MirSurfaceInterface* surface) override;
65 void removeSurface(MirSurfaceInterface* surface) override;
6366
64 void suspend() override;67 void suspend() override;
65 void resume() override;68 void resume() override;
@@ -88,7 +91,6 @@
8891
89private Q_SLOTS:92private Q_SLOTS:
90 void updateFullscreenProperty();93 void updateFullscreenProperty();
91 void onFirstSurfaceFrameDrawn();
9294
93private:95private:
94 void setParentSession(Session* session);96 void setParentSession(Session* session);
@@ -97,9 +99,11 @@
9799
98 void stopPromptSessions();100 void stopPromptSessions();
99101
102 void appendSurface(MirSurfaceInterface* surface);
103
100 std::shared_ptr<mir::scene::Session> m_session;104 std::shared_ptr<mir::scene::Session> m_session;
101 Application* m_application;105 Application* m_application;
102 MirSurfaceInterface* m_surface;106 ObjectListModel<MirSurfaceInterface> m_surfaces;
103 SessionInterface* m_parentSession;107 SessionInterface* m_parentSession;
104 SessionModel* m_children;108 SessionModel* m_children;
105 bool m_fullscreen;109 bool m_fullscreen;
106110
=== modified file 'src/modules/Unity/Application/session_interface.h'
--- src/modules/Unity/Application/session_interface.h 2015-08-31 09:51:28 +0000
+++ src/modules/Unity/Application/session_interface.h 2015-12-01 12:47:17 +0000
@@ -24,8 +24,12 @@
24#include <unity/shell/application/ApplicationInfoInterface.h>24#include <unity/shell/application/ApplicationInfoInterface.h>
2525
26// local26// local
27#include "objectlistmodel.h"
27#include "sessionmodel.h"28#include "sessionmodel.h"
2829
30// Qt
31#include <QQmlListProperty>
32
29namespace mir {33namespace mir {
30 namespace scene {34 namespace scene {
31 class Session;35 class Session;
@@ -39,7 +43,12 @@
3943
40class SessionInterface : public QObject {44class SessionInterface : public QObject {
41 Q_OBJECT45 Q_OBJECT
42 Q_PROPERTY(MirSurfaceInterface* surface READ surface NOTIFY surfaceChanged)46
47 // FIXME: Remove this once unity8 starts trully supporting multiple surfaces per applicaton.
48 // Ie, remove this once untiy8 moves from using this property to using the surfaces one.
49 Q_PROPERTY(MirSurfaceInterface* lastSurface READ lastSurface NOTIFY lastSurfaceChanged);
50
51 Q_PROPERTY(const ObjectListModel<MirSurfaceInterface>* surfaces READ surfaces CONSTANT);
43 Q_PROPERTY(unity::shell::application::ApplicationInfoInterface* application READ application NOTIFY applicationChanged DESIGNABLE false)52 Q_PROPERTY(unity::shell::application::ApplicationInfoInterface* application READ application NOTIFY applicationChanged DESIGNABLE false)
44 Q_PROPERTY(SessionInterface* parentSession READ parentSession NOTIFY parentSessionChanged DESIGNABLE false)53 Q_PROPERTY(SessionInterface* parentSession READ parentSession NOTIFY parentSessionChanged DESIGNABLE false)
45 Q_PROPERTY(SessionModel* childSessions READ childSessions DESIGNABLE false CONSTANT)54 Q_PROPERTY(SessionModel* childSessions READ childSessions DESIGNABLE false CONSTANT)
@@ -62,7 +71,8 @@
62 //getters71 //getters
63 virtual QString name() const = 0;72 virtual QString name() const = 0;
64 virtual unity::shell::application::ApplicationInfoInterface* application() const = 0;73 virtual unity::shell::application::ApplicationInfoInterface* application() const = 0;
65 virtual MirSurfaceInterface* surface() const = 0;74 virtual MirSurfaceInterface* lastSurface() const = 0;
75 virtual const ObjectListModel<MirSurfaceInterface>* surfaces() const = 0;
66 virtual SessionInterface* parentSession() const = 0;76 virtual SessionInterface* parentSession() const = 0;
67 virtual SessionModel* childSessions() const = 0;77 virtual SessionModel* childSessions() const = 0;
68 virtual State state() const = 0;78 virtual State state() const = 0;
@@ -73,7 +83,8 @@
7383
74 // For MirSurface and MirSurfaceManager use84 // For MirSurface and MirSurfaceManager use
7585
76 virtual void setSurface(MirSurfaceInterface* surface) = 0;86 virtual void registerSurface(MirSurfaceInterface* surface) = 0;
87 virtual void removeSurface(MirSurfaceInterface* surface) = 0;
7788
78 // For Application use89 // For Application use
7990
@@ -98,16 +109,17 @@
98 virtual void removePromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) = 0;109 virtual void removePromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) = 0;
99110
100Q_SIGNALS:111Q_SIGNALS:
101 void surfaceChanged(MirSurfaceInterface*);
102 void parentSessionChanged(SessionInterface*);112 void parentSessionChanged(SessionInterface*);
103 void applicationChanged(unity::shell::application::ApplicationInfoInterface* application);113 void applicationChanged(unity::shell::application::ApplicationInfoInterface* application);
104 void stateChanged(State state);114 void stateChanged(State state);
105 void fullscreenChanged(bool fullscreen);115 void fullscreenChanged(bool fullscreen);
106 void liveChanged(bool live);116 void liveChanged(bool live);
117 void lastSurfaceChanged(MirSurfaceInterface* surface);
107};118};
108119
109} // namespace qtmir120} // namespace qtmir
110121
111Q_DECLARE_METATYPE(qtmir::SessionInterface*)122Q_DECLARE_METATYPE(qtmir::SessionInterface*)
123Q_DECLARE_METATYPE(qtmir::ObjectListModel<qtmir::MirSurfaceInterface>*)
112124
113#endif // SESSION_INTERFACE_H125#endif // SESSION_INTERFACE_H
114126
=== modified file 'tests/modules/ApplicationManager/application_manager_test.cpp'
--- tests/modules/ApplicationManager/application_manager_test.cpp 2015-11-17 14:16:22 +0000
+++ tests/modules/ApplicationManager/application_manager_test.cpp 2015-12-01 12:47:17 +0000
@@ -50,7 +50,7 @@
5050
51 SessionInterface* qmlSession = sessionManager.findSession(mirSession);51 SessionInterface* qmlSession = sessionManager.findSession(mirSession);
52 if (qmlSession) {52 if (qmlSession) {
53 qmlSession->setSurface(qmlSurface);53 qmlSession->registerSurface(qmlSurface);
54 }54 }
5555
56 // I assume that applicationManager ignores the mirSurface parameter, so sending56 // I assume that applicationManager ignores the mirSurface parameter, so sending
5757
=== modified file 'tests/modules/SessionManager/session_test.cpp'
--- tests/modules/SessionManager/session_test.cpp 2015-10-08 11:20:30 +0000
+++ tests/modules/SessionManager/session_test.cpp 2015-12-01 12:47:17 +0000
@@ -58,7 +58,7 @@
58 EXPECT_EQ(Session::Starting, session->state());58 EXPECT_EQ(Session::Starting, session->state());
5959
60 FakeMirSurface *surface = new FakeMirSurface;60 FakeMirSurface *surface = new FakeMirSurface;
61 session->setSurface(surface);61 session->registerSurface(surface);
6262
63 // Still on Starting as the surface hasn't drawn its first frame yet63 // Still on Starting as the surface hasn't drawn its first frame yet
64 EXPECT_EQ(Session::Starting, session->state());64 EXPECT_EQ(Session::Starting, session->state());
@@ -228,7 +228,7 @@
228 auto session = std::make_shared<qtmir::Session>(mirSession, mirServer->the_prompt_session_manager());228 auto session = std::make_shared<qtmir::Session>(mirSession, mirServer->the_prompt_session_manager());
229 {229 {
230 FakeMirSurface *surface = new FakeMirSurface;230 FakeMirSurface *surface = new FakeMirSurface;
231 session->setSurface(surface);231 session->registerSurface(surface);
232 surface->drawFirstFrame();232 surface->drawFirstFrame();
233 }233 }
234 EXPECT_EQ(Session::Running, session->state());234 EXPECT_EQ(Session::Running, session->state());
@@ -259,7 +259,7 @@
259 auto session = std::make_shared<qtmir::Session>(mirSession, mirServer->the_prompt_session_manager());259 auto session = std::make_shared<qtmir::Session>(mirSession, mirServer->the_prompt_session_manager());
260 {260 {
261 FakeMirSurface *surface = new FakeMirSurface;261 FakeMirSurface *surface = new FakeMirSurface;
262 session->setSurface(surface);262 session->registerSurface(surface);
263 surface->drawFirstFrame();263 surface->drawFirstFrame();
264 }264 }
265 EXPECT_EQ(Session::Running, session->state());265 EXPECT_EQ(Session::Running, session->state());
266266
=== modified file 'tests/modules/common/fake_mirsurface.h'
--- tests/modules/common/fake_mirsurface.h 2015-11-25 15:38:39 +0000
+++ tests/modules/common/fake_mirsurface.h 2015-12-01 12:47:17 +0000
@@ -142,6 +142,8 @@
142 updateVisibility();142 updateVisibility();
143 }143 }
144144
145 void consumeBuffer() override {}
146
145 // methods called from the rendering (scene graph) thread:147 // methods called from the rendering (scene graph) thread:
146 QSharedPointer<QSGTexture> texture() override { return QSharedPointer<QSGTexture>(); }148 QSharedPointer<QSGTexture> texture() override { return QSharedPointer<QSGTexture>(); }
147 QSGTexture *weakTexture() const override { return nullptr; }149 QSGTexture *weakTexture() const override { return nullptr; }
148150
=== modified file 'tests/modules/common/fake_session.h'
--- tests/modules/common/fake_session.h 2015-10-20 09:57:17 +0000
+++ tests/modules/common/fake_session.h 2015-12-01 12:47:17 +0000
@@ -38,7 +38,8 @@
3838
39 QString name() const override { return QString("foo-session"); }39 QString name() const override { return QString("foo-session"); }
40 unity::shell::application::ApplicationInfoInterface* application() const override { return m_application; }40 unity::shell::application::ApplicationInfoInterface* application() const override { return m_application; }
41 MirSurfaceInterface* surface() const override { return nullptr; }41 MirSurfaceInterface* lastSurface() const override { return nullptr; }
42 const ObjectListModel<MirSurfaceInterface>* surfaces() const override { return nullptr; }
42 SessionInterface* parentSession() const override { return nullptr; }43 SessionInterface* parentSession() const override { return nullptr; }
43 SessionModel* childSessions() const override { return nullptr; }44 SessionModel* childSessions() const override { return nullptr; }
44 State state() const override { return m_state; }45 State state() const override { return m_state; }
@@ -49,7 +50,8 @@
4950
50 // For MirSurfaceItem and MirSurfaceManager use51 // For MirSurfaceItem and MirSurfaceManager use
5152
52 void setSurface(MirSurfaceInterface*) override {}53 void registerSurface(MirSurfaceInterface*) override {}
54 void removeSurface(MirSurfaceInterface*) override {}
5355
54 // For Application use56 // For Application use
5557
5658
=== modified file 'tests/modules/common/mock_session.h'
--- tests/modules/common/mock_session.h 2015-08-31 09:51:28 +0000
+++ tests/modules/common/mock_session.h 2015-12-01 12:47:17 +0000
@@ -36,16 +36,22 @@
3636
37 MOCK_CONST_METHOD0(name, QString());37 MOCK_CONST_METHOD0(name, QString());
38 MOCK_CONST_METHOD0(application, unity::shell::application::ApplicationInfoInterface*());38 MOCK_CONST_METHOD0(application, unity::shell::application::ApplicationInfoInterface*());
39 MOCK_CONST_METHOD0(surface, MirSurfaceInterface*());39 MOCK_CONST_METHOD0(lastSurface, MirSurfaceInterface*());
40 MOCK_CONST_METHOD0(surfaces, const ObjectListModel<MirSurfaceInterface>*());
40 MOCK_CONST_METHOD0(parentSession, SessionInterface*());41 MOCK_CONST_METHOD0(parentSession, SessionInterface*());
42 MOCK_CONST_METHOD0(childSessions, SessionModel*());
4143
42 MOCK_CONST_METHOD0(state, State());44 MOCK_CONST_METHOD0(state, State());
4345
44 MOCK_CONST_METHOD0(fullscreen, bool());46 MOCK_CONST_METHOD0(fullscreen, bool());
45 MOCK_CONST_METHOD0(live, bool());47 MOCK_CONST_METHOD0(live, bool());
4648
49 MOCK_CONST_METHOD0(session, std::shared_ptr<mir::scene::Session>());
50
51 MOCK_METHOD1(registerSurface, void(MirSurfaceInterface* surface));
52 MOCK_METHOD1(removeSurface, void(MirSurfaceInterface* surface));
53
47 MOCK_METHOD1(setApplication, void(unity::shell::application::ApplicationInfoInterface* item));54 MOCK_METHOD1(setApplication, void(unity::shell::application::ApplicationInfoInterface* item));
48 MOCK_METHOD1(setSurface, void(MirSurfaceInterface* surface));
4955
50 MOCK_METHOD0(suspend, void());56 MOCK_METHOD0(suspend, void());
51 MOCK_METHOD0(resume, void());57 MOCK_METHOD0(resume, void());
@@ -56,13 +62,9 @@
56 MOCK_METHOD1(removeChildSession, void(SessionInterface* session));62 MOCK_METHOD1(removeChildSession, void(SessionInterface* session));
57 MOCK_CONST_METHOD1(foreachChildSession, void(std::function<void(SessionInterface* session)> f));63 MOCK_CONST_METHOD1(foreachChildSession, void(std::function<void(SessionInterface* session)> f));
5864
59 MOCK_CONST_METHOD0(session, std::shared_ptr<mir::scene::Session>());
60
61 MOCK_CONST_METHOD0(activePromptSession, std::shared_ptr<mir::scene::PromptSession>());65 MOCK_CONST_METHOD0(activePromptSession, std::shared_ptr<mir::scene::PromptSession>());
62 MOCK_CONST_METHOD1(foreachPromptSession, void(std::function<void(const std::shared_ptr<mir::scene::PromptSession>&)> f));66 MOCK_CONST_METHOD1(foreachPromptSession, void(std::function<void(const std::shared_ptr<mir::scene::PromptSession>&)> f));
6367
64 MOCK_CONST_METHOD0(childSessions, SessionModel*());
65
66 void setState(State state) {68 void setState(State state) {
67 if (m_state != state) {69 if (m_state != state) {
68 m_state = state;70 m_state = state;

Subscribers

People subscribed via source and target branches