Merge lp:~dandrader/qtmir/multiSurfaceApp into lp:qtmir
- multiSurfaceApp
- Merge into trunk
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 |
Related bugs: |
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:/
* 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
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:354
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 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
Gerry Boland (gerboland) wrote : | # |
Please merge trunk, many conflicts have appeared.
+void Session:
+void Session:
these names confuse me. Perhaps rename to something like:
appendSurface -> registerSurface
reallyAppendSurface -> appendSurface
qDebug() << "Application:
I think we can move this to category logging
+ return const_cast<
const_cast needed here? Can't the pointer be a pointer to a const object?
=== modified file 'src/modules/
+ QList<MirSurfac
What use is this? I only see you append to and remove from this list, but never use it for anything.
+ Q_PROPERTY(
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?
- 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
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:372
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
> Please merge trunk, many conflicts have appeared.
Done.
> +void Session:
> +void Session:
> these names confuse me. Perhaps rename to something like:
> appendSurface -> registerSurface
> reallyAppendSurface -> appendSurface
Done.
> qDebug() << "Application:
> on!";
> I think we can move this to category logging
Done.
> + return const_cast<
> 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/
> + QList<MirSurfac
> 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(
> 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.
- 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
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.
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
- 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 DisplayConfigur
ation changes. On Mir DisplayConfigur
ation 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 renderersThis 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::onScreenAbout ToBeRemoved * 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
Michael Zanetti (mzanetti) wrote : | # |
I've tested it and it works.
- 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 ApplicationInfo
Interface 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/tracepoin t-rcu.h: 26:0,
from /usr/include/ lttng/tracepoin t.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-qstringbui lder/
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
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:419
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:424
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 423. By Timo Jyrinki
-
Rebuild against Qt 5.5.1.
- 424. By Daniel d'Andrada
- 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
Preview Diff
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; |
FAILED: Continuous integration, rev:353 jenkins. qa.ubuntu. com/job/ qtmir-ci/ 353/ jenkins. qa.ubuntu. com/job/ qtmir-wily- amd64-ci/ 86/console jenkins. qa.ubuntu. com/job/ qtmir-wily- armhf-ci/ 86/console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/qtmir- ci/353/ rebuild
http://