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
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-11-25 15:38:50 +0000
3+++ CMakeLists.txt 2015-12-01 12:47:17 +0000
4@@ -75,7 +75,7 @@
5 pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
6 pkg_check_modules(QTDBUSTEST libqtdbustest-1 REQUIRED)
7 pkg_check_modules(QTDBUSMOCK libqtdbusmock-1 REQUIRED)
8-pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=11)
9+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=12)
10
11 include_directories(${APPLICATION_API_INCLUDE_DIRS})
12
13
14=== modified file 'debian/control'
15--- debian/control 2015-11-25 15:38:50 +0000
16+++ debian/control 2015-12-01 12:47:17 +0000
17@@ -22,7 +22,7 @@
18 libubuntu-app-launch2-dev,
19 libubuntu-application-api-dev (>= 2.1.0),
20 libudev-dev,
21- libunity-api-dev (>= 7.103),
22+ libunity-api-dev (>= 7.104),
23 liburl-dispatcher1-dev,
24 libxkbcommon-dev,
25 libxrender-dev,
26@@ -93,7 +93,7 @@
27 Conflicts: libqtmir,
28 libunity-mir1,
29 Provides: unity-application-impl,
30- unity-application-impl-11,
31+ unity-application-impl-12,
32 Description: Qt plugin for Unity specific Mir APIs
33 QtMir provides Qt/QML bindings for Mir features that are exposed through the
34 qtmir-desktop or qtmir-android QPA plugin such as Application management
35
36=== modified file 'src/modules/Unity/Application/mirbuffersgtexture.cpp'
37--- src/modules/Unity/Application/mirbuffersgtexture.cpp 2015-10-02 12:20:00 +0000
38+++ src/modules/Unity/Application/mirbuffersgtexture.cpp 2015-12-01 12:47:17 +0000
39@@ -21,6 +21,9 @@
40 #include <mir/geometry/size.h>
41 #include <mir/renderer/gl/texture_source.h>
42
43+// mirserver
44+#include <logging.h>
45+
46 namespace mg = mir::geometry;
47 namespace mrg = mir::renderer::gl;
48
49@@ -80,20 +83,25 @@
50 return m_mirBuffer->pixel_format() == mir_pixel_format_abgr_8888
51 || m_mirBuffer->pixel_format() == mir_pixel_format_argb_8888;
52 } else {
53+ qCWarning(QTMIR_SURFACES) << "MirBufferSGTexture: hasAlphaChannel() called but there's no mir buffer to query";
54 return false;
55 }
56 }
57
58 void MirBufferSGTexture::bind()
59 {
60- Q_ASSERT(hasBuffer());
61- glBindTexture(GL_TEXTURE_2D, m_textureId);
62- updateBindOptions(true/* force */);
63-
64- auto const texture_source =
65- dynamic_cast<mrg::TextureSource*>(m_mirBuffer->native_buffer_base());
66- if (!texture_source)
67- throw std::logic_error("Buffer does not support GL rendering");
68-
69- texture_source->gl_bind_to_texture();
70+ if (hasBuffer()) {
71+ glBindTexture(GL_TEXTURE_2D, m_textureId);
72+ updateBindOptions(true/* force */);
73+
74+ auto const texture_source =
75+ dynamic_cast<mrg::TextureSource*>(m_mirBuffer->native_buffer_base());
76+ if (!texture_source)
77+ throw std::logic_error("Buffer does not support GL rendering");
78+
79+ texture_source->gl_bind_to_texture();
80+ } else {
81+ qCWarning(QTMIR_SURFACES) << "MirBufferSGTexture: bind() called but there's no mir buffer to bind to";
82+ glBindTexture(GL_TEXTURE_2D, 0);
83+ }
84 }
85
86=== modified file 'src/modules/Unity/Application/mirsurface.cpp'
87--- src/modules/Unity/Application/mirsurface.cpp 2015-11-25 15:38:39 +0000
88+++ src/modules/Unity/Application/mirsurface.cpp 2015-12-01 12:47:17 +0000
89@@ -25,6 +25,7 @@
90
91 // Mir
92 #include <mir/geometry/rectangle.h>
93+#include <mir/graphics/buffer.h>
94 #include <mir/events/event_builders.h>
95 #include <mir/shell/shell.h>
96 #include <mir_toolkit/event.h>
97@@ -34,6 +35,8 @@
98
99 using namespace qtmir;
100
101+#define DEBUG_MSG qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << (void*)this << "," << appId() <<"]::" << __func__
102+
103 namespace {
104
105 // Would be better if QMouseEvent had nativeModifiers
106@@ -216,7 +219,7 @@
107 Q_ASSERT(m_views.isEmpty());
108
109 if (m_session) {
110- m_session->setSurface(nullptr);
111+ m_session->removeSurface(this);
112 }
113
114 QMutexLocker locker(&m_mutex);
115@@ -297,15 +300,14 @@
116 int framesPending = m_surface->buffers_ready_for_compositor(userId);
117 if (framesPending > 0) {
118 m_textureUpdated = false;
119-
120+
121 locker.unlock();
122 if (updateTexture()) {
123- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::dropPendingBuffer() dropped=1 left=" << framesPending-1;
124+ DEBUG_MSG << "() dropped=1 left=" << framesPending-1;
125 } else {
126 // If we haven't managed to update the texture, don't keep banging away.
127 m_frameDropperTimer.stop();
128- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::dropPendingBuffer() dropped=0"
129- << " left=" << framesPending << " - failed to upate texture";
130+ DEBUG_MSG << "() dropped=0" << " left=" << framesPending << " - failed to upate texture";
131 }
132 Q_EMIT frameDropped();
133 } else {
134@@ -319,13 +321,13 @@
135
136 void MirSurface::stopFrameDropper()
137 {
138- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::stopFrameDropper()";
139+ DEBUG_MSG << "()";
140 m_frameDropperTimer.stop();
141 }
142
143 void MirSurface::startFrameDropper()
144 {
145- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::startFrameDropper()";
146+ DEBUG_MSG << "()";
147 if (!m_frameDropperTimer.isActive()) {
148 m_frameDropperTimer.start();
149 }
150@@ -355,39 +357,53 @@
151 return texture->hasBuffer();
152 }
153
154- const void* const userId = (void*)123;
155- auto renderables = m_surface->generate_renderables(userId);
156-
157- if (renderables.size() > 0 &&
158- (m_surface->buffers_ready_for_compositor(userId) > 0 || !texture->hasBuffer())
159- ) {
160+ if (m_pendingBuffer) {
161 // Avoid holding two buffers for the compositor at the same time. Thus free the current
162 // before acquiring the next
163 texture->freeBuffer();
164- texture->setBuffer(renderables[0]->buffer());
165+ texture->setBuffer(m_pendingBuffer);
166+ m_pendingBuffer.reset();
167 ++m_currentFrameNumber;
168-
169- if (texture->textureSize() != m_size) {
170- m_size = texture->textureSize();
171- QMetaObject::invokeMethod(this, "emitSizeChanged", Qt::QueuedConnection);
172+ }
173+
174+ m_textureUpdated = true;
175+
176+ return texture->hasBuffer();
177+}
178+
179+void MirSurface::consumeBuffer()
180+{
181+ QMutexLocker locker(&m_mutex);
182+ const void* const userId = (void*)123;
183+ auto renderables = m_surface->generate_renderables(userId);
184+
185+ if (renderables.size() > 0 && m_surface->buffers_ready_for_compositor(userId) > 0) {
186+ m_pendingBuffer = renderables[0]->buffer();
187+
188+ QSize size(m_pendingBuffer->size().width.as_int(),
189+ m_pendingBuffer->size().height.as_int());
190+ if (size != m_size) {
191+ m_size = size;
192+ Q_EMIT sizeChanged(m_size);
193 }
194-
195- m_textureUpdated = true;
196 }
197
198 if (m_surface->buffers_ready_for_compositor(userId) > 0) {
199 // restart the frame dropper to give MirSurfaceItems enough time to render the next frame.
200- // queued since the timer lives in a different thread
201- QMetaObject::invokeMethod(&m_frameDropperTimer, "start", Qt::QueuedConnection);
202+ QMetaObject::invokeMethod(&m_frameDropperTimer, "start", Qt::AutoConnection);
203 }
204-
205- return texture->hasBuffer();
206 }
207
208 void MirSurface::onCompositorSwappedBuffers()
209 {
210 QMutexLocker locker(&m_mutex);
211 m_textureUpdated = false;
212+
213+ if (m_texture && m_pendingBuffer) {
214+ // No need to hold onto this buffer as it won't be used on the next frame.
215+ MirBufferSGTexture *texture = static_cast<MirBufferSGTexture*>(m_texture.data());
216+ texture->freeBuffer();
217+ }
218 }
219
220 bool MirSurface::numBuffersReadyForCompositor()
221@@ -406,12 +422,11 @@
222 // Temporary hotfix for http://pad.lv/1483752
223 if (m_session->childSessions()->rowCount() > 0) {
224 // has child trusted session, ignore any focus change attempts
225- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::setFocus(" << focus
226- << ") - has child trusted session, ignore any focus change attempts";
227+ DEBUG_MSG << "(" << focus << ") - has child trusted session, ignore any focus change attempts";
228 return;
229 }
230
231- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::setFocus(" << focus << ")";
232+ DEBUG_MSG << "(" << focus << ")";
233
234 if (focus) {
235 m_shell->set_surface_attribute(m_session->session(), m_surface, mir_surface_attrib_focus, mir_surface_focused);
236@@ -430,9 +445,8 @@
237 if (clientIsRunning() && mirSizeIsDifferent) {
238 mir::geometry::Size newMirSize(width, height);
239 m_surface->resize(newMirSize);
240- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::resize"
241- << " old (" << mirWidth << "," << mirHeight << ")"
242- << ", new (" << width << "," << height << ")";
243+ DEBUG_MSG << " old (" << mirWidth << "," << mirHeight << ")"
244+ << ", new (" << width << "," << height << ")";
245 }
246 }
247
248@@ -659,8 +673,7 @@
249 void MirSurface::registerView(qintptr viewId)
250 {
251 m_views.insert(viewId, MirSurface::View{false});
252- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::registerView(" << viewId << ")"
253- << " after=" << m_views.count();
254+ DEBUG_MSG << "(" << viewId << ")" << " after=" << m_views.count();
255 if (m_views.count() == 1) {
256 Q_EMIT isBeingDisplayedChanged();
257 }
258@@ -668,9 +681,8 @@
259
260 void MirSurface::unregisterView(qintptr viewId)
261 {
262- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::unregisterView(" << viewId << ")"
263- << " after=" << m_views.count() << " live=" << m_live;
264 m_views.remove(viewId);
265+ DEBUG_MSG << "(" << viewId << ")" << " after=" << m_views.count() << " live=" << m_live;
266 if (m_views.count() == 0) {
267 Q_EMIT isBeingDisplayedChanged();
268 if (m_session.isNull() || !m_live) {
269@@ -701,7 +713,7 @@
270 }
271
272 if (newVisible != visible()) {
273- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::updateVisibility(" << newVisible << ")";
274+ DEBUG_MSG << "(" << newVisible << ")";
275
276 m_surface->configure(mir_surface_attrib_visibility,
277 newVisible ? mir_surface_visibility_exposed : mir_surface_visibility_occluded);
278@@ -745,8 +757,7 @@
279
280 void MirSurface::setCursor(const QCursor &cursor)
281 {
282- qCDebug(QTMIR_SURFACES).nospace() << "MirSurface[" << appId() << "]::setCursor("
283- << qtCursorShapeToStr(cursor.shape()) << ")";
284+ DEBUG_MSG << "(" << qtCursorShapeToStr(cursor.shape()) << ")";
285
286 m_cursor = cursor;
287 Q_EMIT cursorChanged(m_cursor);
288
289=== modified file 'src/modules/Unity/Application/mirsurface.h'
290--- src/modules/Unity/Application/mirsurface.h 2015-11-25 15:38:39 +0000
291+++ src/modules/Unity/Application/mirsurface.h 2015-12-01 12:47:17 +0000
292@@ -35,7 +35,10 @@
293 #include <mir/scene/surface.h>
294 #include <mir_toolkit/common.h>
295
296-namespace mir { namespace shell { class Shell; }}
297+namespace mir {
298+ namespace shell { class Shell; }
299+ namespace graphics { class Buffer; }
300+}
301
302 class SurfaceObserver;
303
304@@ -89,6 +92,8 @@
305 void unregisterView(qintptr viewId) override;
306 void setViewVisibility(qintptr viewId, bool visible) override;
307
308+ void consumeBuffer() override;
309+
310 // methods called from the rendering (scene graph) thread:
311 QSharedPointer<QSGTexture> texture() override;
312 QSGTexture *weakTexture() const override { return m_texture.data(); }
313@@ -120,7 +125,9 @@
314 QCursor cursor() const override;
315
316 public Q_SLOTS:
317+ // methods called from the rendering (scene graph) thread:
318 void onCompositorSwappedBuffers() override;
319+ // end of methods called from the rendering (scene graph) thread
320
321 private Q_SLOTS:
322 void dropPendingBuffer();
323@@ -163,6 +170,8 @@
324 QSize m_size;
325
326 QCursor m_cursor;
327+
328+ std::shared_ptr<mir::graphics::Buffer> m_pendingBuffer;
329 };
330
331 } // namespace qtmir
332
333=== modified file 'src/modules/Unity/Application/mirsurfaceinterface.h'
334--- src/modules/Unity/Application/mirsurfaceinterface.h 2015-11-25 15:38:39 +0000
335+++ src/modules/Unity/Application/mirsurfaceinterface.h 2015-12-01 12:47:17 +0000
336@@ -54,6 +54,8 @@
337 virtual void unregisterView(qintptr viewId) = 0;
338 virtual void setViewVisibility(qintptr viewId, bool visible) = 0;
339
340+ virtual void consumeBuffer() = 0;
341+
342 // methods called from the rendering (scene graph) thread:
343 virtual QSharedPointer<QSGTexture> texture() = 0;
344 virtual QSGTexture *weakTexture() const = 0;
345@@ -88,7 +90,9 @@
346 void cursorChanged(const QCursor &cursor);
347
348 public Q_SLOTS:
349+ // methods called from the rendering (scene graph) thread:
350 virtual void onCompositorSwappedBuffers() = 0;
351+ // end of methods called from the rendering (scene graph) thread
352
353 Q_SIGNALS:
354 void firstFrameDrawn();
355
356=== modified file 'src/modules/Unity/Application/mirsurfaceitem.cpp'
357--- src/modules/Unity/Application/mirsurfaceitem.cpp 2015-11-25 15:38:54 +0000
358+++ src/modules/Unity/Application/mirsurfaceitem.cpp 2015-12-01 12:47:17 +0000
359@@ -92,6 +92,7 @@
360 , m_surfaceHeight(0)
361 , m_orientationAngle(nullptr)
362 , m_consumesInput(false)
363+ , m_fillMode(Stretch)
364 {
365 qCDebug(QTMIR_SURFACES) << "MirSurfaceItem::MirSurfaceItem";
366
367@@ -227,7 +228,7 @@
368 }
369
370 if (m_surface->numBuffersReadyForCompositor() > 0) {
371- QTimer::singleShot(0, this, SLOT(update()));
372+ QTimer::singleShot(0, this, SLOT(polishAndUpdate()));
373 }
374
375 m_textureProvider->smooth = smooth();
376@@ -235,20 +236,35 @@
377 QSGDefaultImageNode *node = static_cast<QSGDefaultImageNode*>(oldNode);
378 if (!node) {
379 node = new QSGDefaultImageNode;
380- node->setTexture(m_textureProvider->texture());
381-
382 node->setMipmapFiltering(QSGTexture::None);
383 node->setHorizontalWrapMode(QSGTexture::ClampToEdge);
384 node->setVerticalWrapMode(QSGTexture::ClampToEdge);
385- node->setSubSourceRect(QRectF(0, 0, 1, 1));
386 } else {
387 if (!m_lastFrameNumberRendered || (*m_lastFrameNumberRendered != m_surface->currentFrameNumber())) {
388 node->markDirty(QSGNode::DirtyMaterial);
389 }
390 }
391-
392- node->setTargetRect(QRectF(0, 0, width(), height()));
393- node->setInnerTargetRect(QRectF(0, 0, width(), height()));
394+ node->setTexture(m_textureProvider->texture());
395+
396+ if (m_fillMode == PadOrCrop) {
397+ const QSize &textureSize = m_textureProvider->texture()->textureSize();
398+
399+ QRectF targetRect;
400+ targetRect.setWidth(qMin(width(), static_cast<qreal>(textureSize.width())));
401+ targetRect.setHeight(qMin(height(), static_cast<qreal>(textureSize.height())));
402+
403+ qreal u = targetRect.width() / textureSize.width();
404+ qreal v = targetRect.height() / textureSize.height();
405+ node->setSubSourceRect(QRectF(0, 0, u, v));
406+
407+ node->setTargetRect(targetRect);
408+ node->setInnerTargetRect(targetRect);
409+ } else {
410+ // Stretch
411+ node->setSubSourceRect(QRectF(0, 0, 1, 1));
412+ node->setTargetRect(QRectF(0, 0, width(), height()));
413+ node->setInnerTargetRect(QRectF(0, 0, width(), height()));
414+ }
415
416 node->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
417 node->setAntialiasing(antialiasing());
418@@ -626,7 +642,7 @@
419
420 // When a new mir frame gets posted we notify the QML engine that this item needs redrawing,
421 // schedules call to updatePaintNode() from the rendering thread
422- connect(m_surface, &MirSurfaceInterface::framesPosted, this, &QQuickItem::update);
423+ connect(m_surface, &MirSurfaceInterface::framesPosted, this, &MirSurfaceItem::polishAndUpdate);
424
425 connect(m_surface, &MirSurfaceInterface::stateChanged, this, &MirSurfaceItem::surfaceStateChanged);
426 connect(m_surface, &MirSurfaceInterface::liveChanged, this, &MirSurfaceItem::liveChanged);
427@@ -730,6 +746,33 @@
428 }
429 }
430
431+MirSurfaceItem::FillMode MirSurfaceItem::fillMode() const
432+{
433+ return m_fillMode;
434+}
435+
436+void MirSurfaceItem::setFillMode(FillMode value)
437+{
438+ if (m_fillMode != value) {
439+ m_fillMode = value;
440+ Q_EMIT fillModeChanged(m_fillMode);
441+ }
442+}
443+
444+void MirSurfaceItem::polishAndUpdate()
445+{
446+ polish();
447+ update();
448+}
449+
450+void MirSurfaceItem::updatePolish()
451+{
452+ if (!m_surface || !m_surface->live()) {
453+ return;
454+ }
455+ m_surface->consumeBuffer();
456+}
457+
458 } // namespace qtmir
459
460 #include "mirsurfaceitem.moc"
461
462=== modified file 'src/modules/Unity/Application/mirsurfaceitem.h'
463--- src/modules/Unity/Application/mirsurfaceitem.h 2015-11-25 15:38:44 +0000
464+++ src/modules/Unity/Application/mirsurfaceitem.h 2015-12-01 12:47:17 +0000
465@@ -68,6 +68,9 @@
466 int surfaceHeight() const override;
467 void setSurfaceHeight(int value) override;
468
469+ FillMode fillMode() const override;
470+ void setFillMode(FillMode value) override;
471+
472 ////////
473 // QQuickItem
474
475@@ -107,6 +110,8 @@
476
477 void releaseResources() override;
478
479+ void updatePolish() override;
480+
481 private Q_SLOTS:
482 void scheduleMirSurfaceSizeUpdate();
483 void updateMirSurfaceSize();
484@@ -119,6 +124,8 @@
485
486 void onWindowChanged(QQuickWindow *window);
487
488+ void polishAndUpdate();
489+
490 private:
491 void ensureTextureProvider();
492
493@@ -168,6 +175,8 @@
494 Mir::OrientationAngle *m_orientationAngle;
495
496 bool m_consumesInput;
497+
498+ FillMode m_fillMode;
499 };
500
501 } // namespace qtmir
502
503=== modified file 'src/modules/Unity/Application/mirsurfacemanager.cpp'
504--- src/modules/Unity/Application/mirsurfacemanager.cpp 2015-10-09 15:35:05 +0000
505+++ src/modules/Unity/Application/mirsurfacemanager.cpp 2015-12-01 12:47:17 +0000
506@@ -110,7 +110,7 @@
507 }
508
509 if (session)
510- session->setSurface(qmlSurface);
511+ session->registerSurface(qmlSurface);
512
513 // Only notify QML of surface creation once it has drawn its first frame.
514 connect(qmlSurface, &MirSurfaceInterface::firstFrameDrawn, this, [=]() {
515
516=== modified file 'src/modules/Unity/Application/session.cpp'
517--- src/modules/Unity/Application/session.cpp 2015-08-31 09:51:28 +0000
518+++ src/modules/Unity/Application/session.cpp 2015-12-01 12:47:17 +0000
519@@ -46,7 +46,6 @@
520 : SessionInterface(parent)
521 , m_session(session)
522 , m_application(nullptr)
523- , m_surface(nullptr)
524 , m_parentSession(nullptr)
525 , m_children(new SessionModel(this))
526 , m_fullscreen(false)
527@@ -86,10 +85,15 @@
528 void Session::doSuspend()
529 {
530 Q_ASSERT(m_state == Session::Suspending);
531- if (m_surface) {
532- m_surface->stopFrameDropper();
533+
534+
535+ auto surfaceList = m_surfaces.list();
536+ if (surfaceList.empty()) {
537+ qCDebug(QTMIR_SESSIONS) << "Application::suspend - no surface to call stopFrameDropper() on!";
538 } else {
539- qDebug() << "Application::suspend - no surface to call stopFrameDropper() on!";
540+ for (int i = 0; i < surfaceList.count(); ++i) {
541+ surfaceList[i]->stopFrameDropper();
542+ }
543 }
544 setState(Suspended);
545 }
546@@ -120,14 +124,9 @@
547 return m_application;
548 }
549
550-MirSurfaceInterface* Session::surface() const
551+const ObjectListModel<MirSurfaceInterface>* Session::surfaces() const
552 {
553- // Only notify QML of surface creation once it has drawn its first frame.
554- if (m_surface && m_surface->isFirstFrameDrawn()) {
555- return m_surface;
556- } else {
557- return nullptr;
558- }
559+ return &m_surfaces;
560 }
561
562 SessionInterface* Session::parentSession() const
563@@ -166,55 +165,57 @@
564 Q_EMIT applicationChanged(application);
565 }
566
567-void Session::setSurface(MirSurfaceInterface *newSurface)
568+void Session::registerSurface(MirSurfaceInterface *newSurface)
569 {
570- qCDebug(QTMIR_SESSIONS) << "Session::setSurface - session=" << name() << "surface=" << newSurface;
571-
572- if (newSurface == m_surface) {
573- return;
574- }
575-
576- if (m_surface) {
577- m_surface->disconnect(this);
578- }
579-
580- MirSurfaceInterface *previousSurface = surface();
581- m_surface = newSurface;
582-
583- if (newSurface) {
584- connect(newSurface, &MirSurfaceInterface::stateChanged,
585- this, &Session::updateFullscreenProperty);
586-
587- // Only notify QML of surface creation once it has drawn its first frame.
588- if (m_surface->isFirstFrameDrawn()) {
589- setState(Running);
590- } else {
591- connect(newSurface, &MirSurfaceInterface::firstFrameDrawn,
592- this, &Session::onFirstSurfaceFrameDrawn);
593- }
594- }
595-
596- if (previousSurface != surface()) {
597- qCDebug(QTMIR_SESSIONS).nospace() << "Session::surfaceChanged - session=" << this
598- << " surface=" << m_surface;
599- Q_EMIT surfaceChanged(m_surface);
600+ qCDebug(QTMIR_SESSIONS) << "Session::resgisterSurface - session=" << name() << "surface=" << newSurface;
601+
602+ // Only notify QML of surface creation once it has drawn its first frame.
603+ if (newSurface->isFirstFrameDrawn()) {
604+ appendSurface(newSurface);
605+ } else {
606+ connect(newSurface, &MirSurfaceInterface::firstFrameDrawn,
607+ this, [this, newSurface]() { this->appendSurface(newSurface); });
608 }
609
610 updateFullscreenProperty();
611 }
612
613-void Session::onFirstSurfaceFrameDrawn()
614-{
615- qCDebug(QTMIR_SESSIONS).nospace() << "Session::surfaceChanged - session=" << this
616- << " surface=" << m_surface;
617- Q_EMIT surfaceChanged(m_surface);
618- setState(Running);
619+void Session::appendSurface(MirSurfaceInterface *newSurface)
620+{
621+ qCDebug(QTMIR_SESSIONS) << "Session::appendSurface - session=" << name() << "surface=" << newSurface;
622+
623+ connect(newSurface, &MirSurfaceInterface::stateChanged,
624+ this, &Session::updateFullscreenProperty);
625+
626+ m_surfaces.insert(m_surfaces.rowCount(), newSurface);
627+
628+ Q_EMIT lastSurfaceChanged(newSurface);
629+
630+ if (m_state == Starting) {
631+ setState(Running);
632+ }
633+}
634+
635+void Session::removeSurface(MirSurfaceInterface* surface)
636+{
637+ qCDebug(QTMIR_SESSIONS) << "Session::removeSurface - session=" << name() << "surface=" << surface;
638+
639+ surface->disconnect(this);
640+
641+ if (m_surfaces.contains(surface)) {
642+ bool lastSurfaceWasRemoved = lastSurface() == surface;
643+ m_surfaces.remove(surface);
644+ if (lastSurfaceWasRemoved) {
645+ Q_EMIT lastSurfaceChanged(lastSurface());
646+ }
647+ }
648 }
649
650 void Session::updateFullscreenProperty()
651 {
652- if (m_surface) {
653- setFullscreen(m_surface->state() == Mir::FullscreenState);
654+ if (m_surfaces.rowCount() > 0) {
655+ // TODO: Figure out something better
656+ setFullscreen(m_surfaces.list().at(0)->state() == Mir::FullscreenState);
657 } else {
658 // Keep the current value of the fullscreen property until we get a new
659 // surface
660@@ -264,8 +265,11 @@
661 Q_ASSERT(m_suspendTimer->isActive());
662 m_suspendTimer->stop();
663 } else if (m_state == Suspended) {
664- Q_ASSERT(m_surface);
665- m_surface->startFrameDropper();
666+ Q_ASSERT(m_surfaces.rowCount() > 0);
667+ auto surfaceList = m_surfaces.list();
668+ for (int i = 0; i < surfaceList.count(); ++i) {
669+ surfaceList[i]->startFrameDropper();
670+ }
671 }
672
673 session()->set_lifecycle_state(mir_lifecycle_state_resumed);
674@@ -285,10 +289,16 @@
675 {
676 if (m_state != Stopped) {
677 stopPromptSessions();
678+
679 if (m_suspendTimer->isActive())
680 m_suspendTimer->stop();
681- if (m_surface)
682- m_surface->stopFrameDropper();
683+
684+ {
685+ auto surfaceList = m_surfaces.list();
686+ for (int i = 0; i < surfaceList.count(); ++i) {
687+ surfaceList[i]->stopFrameDropper();
688+ }
689+ }
690
691 foreachChildSession([](SessionInterface* session) {
692 session->stop();
693@@ -422,4 +432,13 @@
694 }
695 }
696
697+MirSurfaceInterface* Session::lastSurface() const
698+{
699+ if (m_surfaces.rowCount() > 0) {
700+ return m_surfaces.list().last();
701+ } else {
702+ return nullptr;
703+ }
704+}
705+
706 } // namespace qtmir
707
708=== modified file 'src/modules/Unity/Application/session.h'
709--- src/modules/Unity/Application/session.h 2015-08-31 09:51:28 +0000
710+++ src/modules/Unity/Application/session.h 2015-12-01 12:47:17 +0000
711@@ -52,14 +52,17 @@
712 //getters
713 QString name() const override;
714 unity::shell::application::ApplicationInfoInterface* application() const override;
715- MirSurfaceInterface* surface() const override;
716+ MirSurfaceInterface* lastSurface() const override;
717+ const ObjectListModel<MirSurfaceInterface>* surfaces() const override;
718 SessionInterface* parentSession() const override;
719 State state() const override;
720 bool fullscreen() const override;
721 bool live() const override;
722
723 void setApplication(unity::shell::application::ApplicationInfoInterface* item) override;
724- void setSurface(MirSurfaceInterface* surface) override;
725+
726+ void registerSurface(MirSurfaceInterface* surface) override;
727+ void removeSurface(MirSurfaceInterface* surface) override;
728
729 void suspend() override;
730 void resume() override;
731@@ -88,7 +91,6 @@
732
733 private Q_SLOTS:
734 void updateFullscreenProperty();
735- void onFirstSurfaceFrameDrawn();
736
737 private:
738 void setParentSession(Session* session);
739@@ -97,9 +99,11 @@
740
741 void stopPromptSessions();
742
743+ void appendSurface(MirSurfaceInterface* surface);
744+
745 std::shared_ptr<mir::scene::Session> m_session;
746 Application* m_application;
747- MirSurfaceInterface* m_surface;
748+ ObjectListModel<MirSurfaceInterface> m_surfaces;
749 SessionInterface* m_parentSession;
750 SessionModel* m_children;
751 bool m_fullscreen;
752
753=== modified file 'src/modules/Unity/Application/session_interface.h'
754--- src/modules/Unity/Application/session_interface.h 2015-08-31 09:51:28 +0000
755+++ src/modules/Unity/Application/session_interface.h 2015-12-01 12:47:17 +0000
756@@ -24,8 +24,12 @@
757 #include <unity/shell/application/ApplicationInfoInterface.h>
758
759 // local
760+#include "objectlistmodel.h"
761 #include "sessionmodel.h"
762
763+// Qt
764+#include <QQmlListProperty>
765+
766 namespace mir {
767 namespace scene {
768 class Session;
769@@ -39,7 +43,12 @@
770
771 class SessionInterface : public QObject {
772 Q_OBJECT
773- Q_PROPERTY(MirSurfaceInterface* surface READ surface NOTIFY surfaceChanged)
774+
775+ // FIXME: Remove this once unity8 starts trully supporting multiple surfaces per applicaton.
776+ // Ie, remove this once untiy8 moves from using this property to using the surfaces one.
777+ Q_PROPERTY(MirSurfaceInterface* lastSurface READ lastSurface NOTIFY lastSurfaceChanged);
778+
779+ Q_PROPERTY(const ObjectListModel<MirSurfaceInterface>* surfaces READ surfaces CONSTANT);
780 Q_PROPERTY(unity::shell::application::ApplicationInfoInterface* application READ application NOTIFY applicationChanged DESIGNABLE false)
781 Q_PROPERTY(SessionInterface* parentSession READ parentSession NOTIFY parentSessionChanged DESIGNABLE false)
782 Q_PROPERTY(SessionModel* childSessions READ childSessions DESIGNABLE false CONSTANT)
783@@ -62,7 +71,8 @@
784 //getters
785 virtual QString name() const = 0;
786 virtual unity::shell::application::ApplicationInfoInterface* application() const = 0;
787- virtual MirSurfaceInterface* surface() const = 0;
788+ virtual MirSurfaceInterface* lastSurface() const = 0;
789+ virtual const ObjectListModel<MirSurfaceInterface>* surfaces() const = 0;
790 virtual SessionInterface* parentSession() const = 0;
791 virtual SessionModel* childSessions() const = 0;
792 virtual State state() const = 0;
793@@ -73,7 +83,8 @@
794
795 // For MirSurface and MirSurfaceManager use
796
797- virtual void setSurface(MirSurfaceInterface* surface) = 0;
798+ virtual void registerSurface(MirSurfaceInterface* surface) = 0;
799+ virtual void removeSurface(MirSurfaceInterface* surface) = 0;
800
801 // For Application use
802
803@@ -98,16 +109,17 @@
804 virtual void removePromptSession(const std::shared_ptr<mir::scene::PromptSession>& session) = 0;
805
806 Q_SIGNALS:
807- void surfaceChanged(MirSurfaceInterface*);
808 void parentSessionChanged(SessionInterface*);
809 void applicationChanged(unity::shell::application::ApplicationInfoInterface* application);
810 void stateChanged(State state);
811 void fullscreenChanged(bool fullscreen);
812 void liveChanged(bool live);
813+ void lastSurfaceChanged(MirSurfaceInterface* surface);
814 };
815
816 } // namespace qtmir
817
818 Q_DECLARE_METATYPE(qtmir::SessionInterface*)
819+Q_DECLARE_METATYPE(qtmir::ObjectListModel<qtmir::MirSurfaceInterface>*)
820
821 #endif // SESSION_INTERFACE_H
822
823=== modified file 'tests/modules/ApplicationManager/application_manager_test.cpp'
824--- tests/modules/ApplicationManager/application_manager_test.cpp 2015-11-17 14:16:22 +0000
825+++ tests/modules/ApplicationManager/application_manager_test.cpp 2015-12-01 12:47:17 +0000
826@@ -50,7 +50,7 @@
827
828 SessionInterface* qmlSession = sessionManager.findSession(mirSession);
829 if (qmlSession) {
830- qmlSession->setSurface(qmlSurface);
831+ qmlSession->registerSurface(qmlSurface);
832 }
833
834 // I assume that applicationManager ignores the mirSurface parameter, so sending
835
836=== modified file 'tests/modules/SessionManager/session_test.cpp'
837--- tests/modules/SessionManager/session_test.cpp 2015-10-08 11:20:30 +0000
838+++ tests/modules/SessionManager/session_test.cpp 2015-12-01 12:47:17 +0000
839@@ -58,7 +58,7 @@
840 EXPECT_EQ(Session::Starting, session->state());
841
842 FakeMirSurface *surface = new FakeMirSurface;
843- session->setSurface(surface);
844+ session->registerSurface(surface);
845
846 // Still on Starting as the surface hasn't drawn its first frame yet
847 EXPECT_EQ(Session::Starting, session->state());
848@@ -228,7 +228,7 @@
849 auto session = std::make_shared<qtmir::Session>(mirSession, mirServer->the_prompt_session_manager());
850 {
851 FakeMirSurface *surface = new FakeMirSurface;
852- session->setSurface(surface);
853+ session->registerSurface(surface);
854 surface->drawFirstFrame();
855 }
856 EXPECT_EQ(Session::Running, session->state());
857@@ -259,7 +259,7 @@
858 auto session = std::make_shared<qtmir::Session>(mirSession, mirServer->the_prompt_session_manager());
859 {
860 FakeMirSurface *surface = new FakeMirSurface;
861- session->setSurface(surface);
862+ session->registerSurface(surface);
863 surface->drawFirstFrame();
864 }
865 EXPECT_EQ(Session::Running, session->state());
866
867=== modified file 'tests/modules/common/fake_mirsurface.h'
868--- tests/modules/common/fake_mirsurface.h 2015-11-25 15:38:39 +0000
869+++ tests/modules/common/fake_mirsurface.h 2015-12-01 12:47:17 +0000
870@@ -142,6 +142,8 @@
871 updateVisibility();
872 }
873
874+ void consumeBuffer() override {}
875+
876 // methods called from the rendering (scene graph) thread:
877 QSharedPointer<QSGTexture> texture() override { return QSharedPointer<QSGTexture>(); }
878 QSGTexture *weakTexture() const override { return nullptr; }
879
880=== modified file 'tests/modules/common/fake_session.h'
881--- tests/modules/common/fake_session.h 2015-10-20 09:57:17 +0000
882+++ tests/modules/common/fake_session.h 2015-12-01 12:47:17 +0000
883@@ -38,7 +38,8 @@
884
885 QString name() const override { return QString("foo-session"); }
886 unity::shell::application::ApplicationInfoInterface* application() const override { return m_application; }
887- MirSurfaceInterface* surface() const override { return nullptr; }
888+ MirSurfaceInterface* lastSurface() const override { return nullptr; }
889+ const ObjectListModel<MirSurfaceInterface>* surfaces() const override { return nullptr; }
890 SessionInterface* parentSession() const override { return nullptr; }
891 SessionModel* childSessions() const override { return nullptr; }
892 State state() const override { return m_state; }
893@@ -49,7 +50,8 @@
894
895 // For MirSurfaceItem and MirSurfaceManager use
896
897- void setSurface(MirSurfaceInterface*) override {}
898+ void registerSurface(MirSurfaceInterface*) override {}
899+ void removeSurface(MirSurfaceInterface*) override {}
900
901 // For Application use
902
903
904=== modified file 'tests/modules/common/mock_session.h'
905--- tests/modules/common/mock_session.h 2015-08-31 09:51:28 +0000
906+++ tests/modules/common/mock_session.h 2015-12-01 12:47:17 +0000
907@@ -36,16 +36,22 @@
908
909 MOCK_CONST_METHOD0(name, QString());
910 MOCK_CONST_METHOD0(application, unity::shell::application::ApplicationInfoInterface*());
911- MOCK_CONST_METHOD0(surface, MirSurfaceInterface*());
912+ MOCK_CONST_METHOD0(lastSurface, MirSurfaceInterface*());
913+ MOCK_CONST_METHOD0(surfaces, const ObjectListModel<MirSurfaceInterface>*());
914 MOCK_CONST_METHOD0(parentSession, SessionInterface*());
915+ MOCK_CONST_METHOD0(childSessions, SessionModel*());
916
917 MOCK_CONST_METHOD0(state, State());
918
919 MOCK_CONST_METHOD0(fullscreen, bool());
920 MOCK_CONST_METHOD0(live, bool());
921
922+ MOCK_CONST_METHOD0(session, std::shared_ptr<mir::scene::Session>());
923+
924+ MOCK_METHOD1(registerSurface, void(MirSurfaceInterface* surface));
925+ MOCK_METHOD1(removeSurface, void(MirSurfaceInterface* surface));
926+
927 MOCK_METHOD1(setApplication, void(unity::shell::application::ApplicationInfoInterface* item));
928- MOCK_METHOD1(setSurface, void(MirSurfaceInterface* surface));
929
930 MOCK_METHOD0(suspend, void());
931 MOCK_METHOD0(resume, void());
932@@ -56,13 +62,9 @@
933 MOCK_METHOD1(removeChildSession, void(SessionInterface* session));
934 MOCK_CONST_METHOD1(foreachChildSession, void(std::function<void(SessionInterface* session)> f));
935
936- MOCK_CONST_METHOD0(session, std::shared_ptr<mir::scene::Session>());
937-
938 MOCK_CONST_METHOD0(activePromptSession, std::shared_ptr<mir::scene::PromptSession>());
939 MOCK_CONST_METHOD1(foreachPromptSession, void(std::function<void(const std::shared_ptr<mir::scene::PromptSession>&)> f));
940
941- MOCK_CONST_METHOD0(childSessions, SessionModel*());
942-
943 void setState(State state) {
944 if (m_state != state) {
945 m_state = state;

Subscribers

People subscribed via source and target branches