Merge lp:~dandrader/qtmir/fake-apps into lp:qtmir
- fake-apps
- Merge into trunk
Status: | Superseded |
---|---|
Proposed branch: | lp:~dandrader/qtmir/fake-apps |
Merge into: | lp:qtmir |
Diff against target: |
6497 lines (+4124/-669) 74 files modified
CMakeLists.txt (+3/-2) debian/control (+2/-2) debian/gles-patches/convert-to-gles.patch (+1/-1) src/common/debughelpers.cpp (+47/-1) src/common/debughelpers.h (+3/-1) src/common/windowcontrollerinterface.h (+2/-1) src/modules/Unity/Application/CMakeLists.txt (+9/-1) src/modules/Unity/Application/application.cpp (+1/-1) src/modules/Unity/Application/application.h (+0/-1) src/modules/Unity/Application/application_manager.cpp (+46/-34) src/modules/Unity/Application/application_manager.h (+3/-1) src/modules/Unity/Application/fake/fakeapplicationinfo.cpp (+26/-0) src/modules/Unity/Application/fake/fakeapplicationinfo.h (+93/-0) src/modules/Unity/Application/fake/fakemaliit.cpp (+76/-0) src/modules/Unity/Application/fake/fakemaliit.h (+47/-0) src/modules/Unity/Application/fake/fakemirclient.cpp (+685/-0) src/modules/Unity/Application/fake/fakemirclient.h (+177/-0) src/modules/Unity/Application/fake/fakeprompt.cpp (+320/-0) src/modules/Unity/Application/fake/fakeprompt.h (+155/-0) src/modules/Unity/Application/fake/faketaskcontroller.cpp (+683/-0) src/modules/Unity/Application/fake/faketaskcontroller.h (+157/-0) src/modules/Unity/Application/fake/windowattributes.h (+47/-0) src/modules/Unity/Application/mirtestsingleton.cpp (+211/-0) src/modules/Unity/Application/mirtestsingleton.h (+116/-0) src/modules/Unity/Application/plugin.cpp (+11/-1) src/modules/Unity/Application/resources/screenshots/gmail-webapp.svg (+343/-0) src/modules/Unity/Application/resources/screenshots/ubuntu-weather-app.svg (+201/-0) src/modules/Unity/Application/resources/surfaces.qrc (+39/-0) src/modules/Unity/Application/session.cpp (+13/-1) src/modules/Unity/Application/session_interface.h (+1/-1) src/modules/Unity/Application/sessionmanager.cpp (+0/-200) src/modules/Unity/Application/sessionmanager.h (+0/-90) src/modules/Unity/Application/surfacemanager.cpp (+4/-5) src/modules/Unity/Application/surfacemanager.h (+1/-3) src/modules/Unity/Application/taskcontroller.cpp (+196/-0) src/modules/Unity/Application/taskcontroller.h (+63/-5) src/platforms/mirserver/CMakeLists.txt (+2/-0) src/platforms/mirserver/argvHelper.h (+0/-52) src/platforms/mirserver/cursor.cpp (+5/-4) src/platforms/mirserver/cursor.h (+2/-2) src/platforms/mirserver/logging.cpp (+2/-1) src/platforms/mirserver/logging.h (+2/-1) src/platforms/mirserver/mirserverhooks.cpp (+9/-1) src/platforms/mirserver/mirserverhooks.h (+2/-1) src/platforms/mirserver/mirserverintegration.cpp (+2/-2) src/platforms/mirserver/mirserverintegration.h (+1/-1) src/platforms/mirserver/mirsingleton.cpp (+29/-1) src/platforms/mirserver/mirsingleton.h (+8/-1) src/platforms/mirserver/pidfetcher.cpp (+34/-0) src/platforms/mirserver/pidfetcher.h (+43/-0) src/platforms/mirserver/plugin.cpp (+3/-1) src/platforms/mirserver/qmirserver.cpp (+4/-2) src/platforms/mirserver/qmirserver.h (+1/-1) src/platforms/mirserver/qmirserver_p.cpp (+5/-18) src/platforms/mirserver/qmirserver_p.h (+3/-3) src/platforms/mirserver/qteventfeeder.cpp (+63/-23) src/platforms/mirserver/qteventfeeder.h (+4/-0) src/platforms/mirserver/windowmanagementpolicy.cpp (+7/-1) src/platforms/mirserver/windowmanagementpolicy.h (+1/-0) tests/framework/mock_renderable.cpp (+1/-1) tests/framework/mock_renderable.h (+3/-3) tests/framework/mock_task_controller.cpp (+2/-1) tests/framework/mock_task_controller.h (+1/-1) tests/framework/qtmir_test.cpp (+2/-4) tests/framework/qtmir_test.h (+2/-5) tests/mirserver/ArgvHelper/CMakeLists.txt (+0/-18) tests/mirserver/ArgvHelper/argvHelper_test.cpp (+0/-72) tests/mirserver/CMakeLists.txt (+0/-1) tests/modules/Application/application_test.cpp (+3/-0) tests/modules/ApplicationManager/application_manager_test.cpp (+70/-69) tests/modules/CMakeLists.txt (+1/-1) tests/modules/Session/CMakeLists.txt (+6/-6) tests/modules/Session/session_test.cpp (+2/-2) tests/modules/Session/taskcontroller_test.cpp (+17/-17) |
To merge this branch: | bzr merge lp:~dandrader/qtmir/fake-apps |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity8 CI Bot (community) | continuous-integration | Needs Fixing | |
Gerry Boland (community) | Needs Fixing | ||
Review via email: mp+316845@code.launchpad.net |
This proposal has been superseded by a proposal from 2017-02-14.
Commit message
Fake applications using internal mir clients when UNITY_TESTING is defined
Description of the change
Prereq-archive: ppa:ci-
* Are there any related MPs required for this MP to build/function as expected? Please list.
https:/
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
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:597
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Gerry Boland (gerboland) wrote : | # |
=== modified file 'src/common/
+ virtual void modify(const miral::Window &window, miral::
This is opening large functionality to the shell, which makes me suspicious. Digging I see it only used by MirSurface:
I dislike that, as shell should not be updating MirAL's information on surface min/max/inc limits, instead it should be the client (like it will happen in reality).
Can you redo the min/max/inc limit setting to use the client api instead, and remove this change?
=== modified file 'src/modules/
+ taskController.
+ procInfo = fakeTaskControl
reset too, for consistency
=== modified file 'src/modules/
+ SessionInterface *findSession(const mir::scene:
+ Application* findApplication
so these you've made public, but are also just for test use. Do comment about that fact then, just to make it clear.
Also, we need to avoid exposing mirserver apis and use MirAL's api instead. So use miral::Application instead of std::shared_
+ void onSessionStarti
is this fixing a bug? If so, would be good to separate that bug fix into a separate MP with a test.
I'll look at the Fake stuff last.
=== modified file 'src/modules/
+ Q_PROPERTY(int width READ width NOTIFY widthChanged)
+ Q_PROPERTY(int height READ height NOTIFY heightChanged)
why? size() gives this info out, and a single change signal too. You know I disapprove of this.
+ // Whether there's a MirSurfaceItem with active focus displaying this surface.
+ // This information is useful in shell tests
+ Q_PROPERTY(bool activeFocus READ activeFocus NOTIFY activeFocusChanged)
+
+ // Whether the MirSurface is exposed (true) or occluded (false)
+ // This information is useful in shell tests
+ Q_PROPERTY(bool exposed READ exposed NOTIFY exposedChanged)
Can you expose the client API for these? Wiring it through shell, you're missing out on testing the Mir->client communication.
+ // Used only by shell tests
+ Q_INVOKABLE void setMinimumWidth
+ Q_INVOKABLE void setMaximumWidth
+ Q_INVOKABLE void setMinimumHeigh
+ Q_INVOKABLE void setMaximumHeigh
+ Q_INVOKABLE void setWidthIncreme
+ Q_INVOKABLE void setHeightIncrem
Yeah as I said above, I dislike these here.
=== modified file 'src/modules/
What is going on here? What is this mouse & touch counting stuff for? Can't these things could be done in the client, and avoid the test code in the shell?
=== modified file 'src/modules/
+ const bool focusedBefore = focused();
and on.
Are you fixing a bug here? Can you separate that out into a separate MP with a test?
+ for (int i = 0; i < m_closingSurfac
Gerry Boland (gerboland) wrote : | # |
=== modified file 'src/platforms/
+ mir::Server *server() const;
You need to justify this. Again it is exposing mir server api, which we're trying to avoid.
=== modified file 'src/platforms/
-MirServerInteg
+MirServerInteg
Why?? This prevents Mir from processing any command line args. You really need to justify this reversal.
Daniel d'Andrada (dandrader) wrote : | # |
On 09/02/2017 14:17, Gerry Boland wrote:
> === modified file 'src/modules/
> What is going on here? What is this mouse & touch counting stuff for? Can't these things could be done in the client, and avoid the test code in the shell?
That would be lovely. Any suggestions?
Daniel d'Andrada (dandrader) wrote : | # |
On 09/02/2017 14:17, Gerry Boland wrote:
> + for (int i = 0; i < m_closingSurfac
> foreach nicer
That's debatable. I personally find Q_FOREACH to be an eyesore.
Gerry Boland (gerboland) wrote : | # |
Instead of exporting the whole of MirServer through the QPA, would be cleaner if you could just expose the bare minimum api needed for the test bits
Gerry Boland (gerboland) wrote : | # |
Can you also split the SessionManager-
Gerry Boland (gerboland) wrote : | # |
> On 09/02/2017 14:17, Gerry Boland wrote:
> > + for (int i = 0; i < m_closingSurfac
> > foreach nicer
>
> That's debatable. I personally find Q_FOREACH to be an eyesore.
I mis-spoke, I meant the C++11 ranged for is nicer.
Gerry Boland (gerboland) wrote : | # |
> On 09/02/2017 14:17, Gerry Boland wrote:
> > === modified file 'src/modules/
> > What is going on here? What is this mouse & touch counting stuff for? Can't
> these things could be done in the client, and avoid the test code in the
> shell?
>
> That would be lovely. Any suggestions?
Well I see the fake MirClient:
I don't mind if the code isn't perfect first time, I understand that shortcuts need to be made for brevity. If you mention that limitations in the description and justify why, then I'll be happy and can review with that in mind. But if not, I will point them out and ask why.
Gerry Boland (gerboland) wrote : | # |
=== added file 'src/modules/
+ MirBufferStream* buffer_stream = mir_window_
+ // TODO sometimes buffer_stream is nullptr
+ // (Only observed when creating a lot of clients at once)
Just FYI, this is a deprecated method. The null thing is weird, I'd suggest logging a bug but if it is to be deprecated anyway, not worth the trouble.
+ for (int i = 0; i < m_windows.count(); ++i) {
+ MirWindow *window = m_windows[i];
ranged for a little nicer! It's not an eyesore IMO
=== added file 'src/modules/
+ MirClientEvent(
+ : QEvent(type), window(window), mirEvent(event) {
+ mirEvent = mir_event_
you're setting mirEvent twice afaics.
Daniel d'Andrada (dandrader) wrote : | # |
On 10/02/2017 11:53, Gerry Boland wrote:
> === added file 'src/modules/
> + MirBufferStream* buffer_stream = mir_window_
> + // TODO sometimes buffer_stream is nullptr
> + // (Only observed when creating a lot of clients at once)
> Just FYI, this is a deprecated method. The null thing is weird, I'd suggest logging a bug but if it is to be deprecated anyway, not worth the trouble.
That's copy-pasted code from alan_g in miral.
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:599
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
PASSED: Continuous integration, rev:600
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:601
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:602
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:603
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:604
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Unity8 CI Bot (unity8-ci-bot) wrote : | # |
FAILED: Continuous integration, rev:605
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Daniel d'Andrada (dandrader) wrote : | # |
On 09/02/2017 14:17, Gerry Boland wrote:
> Review: Needs Fixing
>
> === modified file 'src/common/
> + virtual void modify(const miral::Window &window, miral::
> This is opening large functionality to the shell, which makes me suspicious. Digging I see it only used by MirSurface:
>
> I dislike that, as shell should not be updating MirAL's information on surface min/max/inc limits, instead it should be the client (like it will happen in reality).
>
> Can you redo the min/max/inc limit setting to use the client api instead, and remove this change?
Done.
> === modified file 'src/modules/
> + taskController.
> + procInfo = fakeTaskControl
> reset too, for consistency
>
Can't do that. fakeTaskControl
> === modified file 'src/modules/
> + SessionInterface *findSession(const mir::scene:
> + Application* findApplication
> so these you've made public, but are also just for test use. Do comment about that fact then, just to make it clear.
ApplicationMana
SessionManager is gone and its responsibilities split between
TaskController (most of it), SurfaceManager (just a little bit) and
ApplicationManager (another tiny piece).
Made findApplication
outside earlier in the development but not anymore).
> Also, we need to avoid exposing mirserver apis and use MirAL's api instead. So use miral::Application instead of std::shared_
findSession() is needed as explained above.
> + void onSessionStarti
> is this fixing a bug? If so, would be good to separate that bug fix into a separate MP with a test.
No. Again, it's because of the removal of SessionManager.
> === modified file 'src/modules/
> + Q_PROPERTY(int width READ width NOTIFY widthChanged)
> + Q_PROPERTY(int height READ height NOTIFY heightChanged)
> why? size() gives this info out, and a single change signal too. You know I disapprove of this.
Because test code uses it. Easier to copy/paste that from the mock
Unity.Application than to change test code.
Anyway, removed.
> + // Whether there's a MirSurfaceItem with active focus displaying this surface.
> + // This information is useful in shell tests
> + Q_PROPERTY(bool activeFocus READ activeFocus NOTIFY activeFocusChanged)
> +
> + // Whether the MirSurface is exposed (true) or occluded (false)
> + // This information is useful in shell tests
> + Q_PROPERTY(bool exposed READ exposed NOTIFY exposedChanged)
> Can you expose the client API for these? Wiring it through shell, you're missing out on testing the Mir->client communication.
Done.
> + // Used only by shell tests
> + Q_INVOKA...
Daniel d'Andrada (dandrader) wrote : | # |
On 10/02/2017 11:35, Gerry Boland wrote:
>> On 09/02/2017 14:17, Gerry Boland wrote:
>>> === modified file 'src/modules/
>>> What is going on here? What is this mouse & touch counting stuff for? Can't
>> these things could be done in the client, and avoid the test code in the
>> shell?
>>
>> That would be lovely. Any suggestions?
> Well I see the fake MirClient:
Done.
Daniel d'Andrada (dandrader) wrote : | # |
On 09/02/2017 16:26, Gerry Boland wrote:
> Can you also split the SessionManager-
Done:
https:/
Daniel d'Andrada (dandrader) wrote : | # |
On 09/02/2017 15:20, Gerry Boland wrote:
> Instead of exporting the whole of MirServer through the QPA, would be cleaner if you could just expose the bare minimum api needed for the test bits
Would it be ok if Unity.Application module got its hands on MirServer
via other means than Qt's NativeInterface? Is the problem that MirServer
is on the NativeInterface and so shell code could access it?
I'm a bit lost here. Not sure where you wanna get to and why. The
internal mir client code is really plain mir and miral has no part in it.
Daniel d'Andrada (dandrader) wrote : | # |
On 09/02/2017 14:23, Gerry Boland wrote:
> === modified file 'src/platforms/
> -MirServerInteg
> +MirServerInteg
> Why?? This prevents Mir from processing any command line args. You really need to justify this reversal.
Yes, I meant to ask about it but ended up forgetting to do so due to the
sea of code and multitude of weeks that took to me make these branches.
The problem is, if I recall correctly, that Mir is getting in the way
when qtmir is used in uqmlscene (make tryFoo) and qmltestrunner (make
testFoo). That was the simplest solution. Please advise.
- 596. By Albert Astals Cid
-
We're at provides 26 already
- 597. By Iain Lane
-
Releasing 0.5.1+17.
04.20170206- 0ubuntu2 - 598. By Alan Griffiths
-
Iteration 0 of miral::
PersistDisplayC onfig. This does nothing yet (and breaks nothing in the process). This MP creates a place (miral-prototypes) to build prototype miral features and sketches out what will need to be implemented for PersistDisplayC onfig. (LP: #1644189) Approved by: Nick Dedekind, Unity8 CI Bot
- 599. By Nick Dedekind
-
Added Extended Display Information Data (EDID) parsing.
Approved by: Gerry Boland, Unity8 CI Bot
- 600. By Gerry Boland
-
ScreenModel: Only expose windows on displays that are turned on
It seems the GL context Mir gives us for a display that is turned off is invalid. But there is no point rendering to a display that is turned off anyway. (LP: #1521403, #1638611, #1656250)
Approved by: Daniel d'Andrada, Unity8 CI Bot
- 601. By Gerry Boland
-
Restore lost LTTng tracepoints, and delete unused ones (LP: #1658084)
Approved by: Daniel d'Andrada, Unity8 CI Bot
- 602. By CI Train Bot Account
-
We're at provides 26 already (LP: #1662608)
Approved by: Gerry Boland
- 603. By Albert Astals Cid
-
Check we provide the same unity-applicati
on-impl that we require Approved by: Gerry Boland, Lukáš Tinkl, Unity8 CI Bot
- 604. By Alan Griffiths
-
Identify the code that depends directly on mirserver-dev headers
Approved by: Lukáš Tinkl, Unity8 CI Bot
- 605. By Daniel d'Andrada
-
Resolve mir cursor names using mir symbols instead of plain strings
Since those names under the API symbols change regularly and should be considered opaque. (LP: #1662827)
Approved by: Albert Astals Cid, Unity8 CI Bot
- 606. By CI Train Bot Account
-
Releasing 0.5.1+17.
04.20170215. 1-0ubuntu1
Daniel d'Andrada (dandrader) wrote : | # |
On 10/02/2017 11:53, Gerry Boland wrote:
> + for (int i = 0; i < m_windows.count(); ++i) {
> + MirWindow *window = m_windows[i];
> ranged for a little nicer! It's not an eyesore IMO
Done.
- 607. By Daniel d'Andrada
-
Some qtmir::Session fixes
- Emit Session:
:focusedChanged when adding an already focused window
- When session dies, besides killing all its surfaces, also kill its closing surfaces - 608. By Daniel d'Andrada
-
Make TaskController absorb SessionManager
So that we can later on provide fake, internal, mir clients for tests
just by replacing the TaskController with a fake implementation. - 609. By Daniel d'Andrada
-
Don't pass command line arguments to Mir
Those are application specific, as qtmir can be used by several different
executables (unity8, uqmlscene, qmltestrunner), each taking its own set of
comamnd line args.Those executables (uqmlscene, qmltestrunner in particular) will quit when
seeing Mir arguments and vice-versa (Mir quits when seeing unrecognized args) - 610. By Daniel d'Andrada
-
Fake applications using internal mir clients when UNITY_TESTING is defined
Unmerged revisions
- 610. By Daniel d'Andrada
-
Fake applications using internal mir clients when UNITY_TESTING is defined
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2017-02-02 09:17:48 +0000 |
3 | +++ CMakeLists.txt 2017-02-14 10:17:32 +0000 |
4 | @@ -23,8 +23,9 @@ |
5 | # add custom cmake modules |
6 | set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules) |
7 | |
8 | -# Instruct CMake to run moc automatically when needed. |
9 | +# Instruct CMake to run moc and rcc automatically when needed. |
10 | set(CMAKE_AUTOMOC ON) |
11 | +set(CMAKE_AUTORCC ON) |
12 | |
13 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -Wall -Wextra -Werror") |
14 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -fno-strict-aliasing -Werror -Wextra") |
15 | @@ -90,7 +91,7 @@ |
16 | pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt) |
17 | pkg_check_modules(QTDBUSTEST libqtdbustest-1 REQUIRED) |
18 | pkg_check_modules(QTDBUSMOCK libqtdbusmock-1 REQUIRED) |
19 | -pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=26) |
20 | +pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=27) |
21 | pkg_check_modules(CGMANAGER libcgmanager REQUIRED) |
22 | pkg_check_modules(CONTENT_HUB libcontent-hub>=0.2 REQUIRED) |
23 | |
24 | |
25 | === modified file 'debian/control' |
26 | --- debian/control 2017-02-02 09:17:48 +0000 |
27 | +++ debian/control 2017-02-14 10:17:32 +0000 |
28 | @@ -25,7 +25,7 @@ |
29 | libubuntu-app-launch2-dev (>= 0.9), |
30 | libubuntu-application-api-dev (>= 2.1.0), |
31 | libudev-dev, |
32 | - libunity-api-dev (>= 8.2), |
33 | + libunity-api-dev (>= 8.3), |
34 | liburl-dispatcher1-dev, |
35 | libxkbcommon-dev, |
36 | libxrender-dev, |
37 | @@ -102,7 +102,7 @@ |
38 | Conflicts: libqtmir, |
39 | libunity-mir1, |
40 | Provides: unity-application-impl, |
41 | - unity-application-impl-23, |
42 | + unity-application-impl-27, |
43 | Description: Qt plugin for Unity specific Mir APIs |
44 | QtMir provides Qt/QML bindings for Mir features that are exposed through the |
45 | qtmir-desktop or qtmir-android QPA plugin such as Application management |
46 | |
47 | === modified file 'debian/gles-patches/convert-to-gles.patch' |
48 | --- debian/gles-patches/convert-to-gles.patch 2016-12-01 11:45:31 +0000 |
49 | +++ debian/gles-patches/convert-to-gles.patch 2017-02-14 10:17:32 +0000 |
50 | @@ -84,7 +84,7 @@ |
51 | -Conflicts: libqtmir, |
52 | - libunity-mir1, |
53 | -Provides: unity-application-impl, |
54 | -- unity-application-impl-23, |
55 | +- unity-application-impl-27, |
56 | -Description: Qt plugin for Unity specific Mir APIs |
57 | - QtMir provides Qt/QML bindings for Mir features that are exposed through the |
58 | - qtmir-desktop or qtmir-android QPA plugin such as Application management |
59 | |
60 | === modified file 'src/common/debughelpers.cpp' |
61 | --- src/common/debughelpers.cpp 2017-01-18 21:24:15 +0000 |
62 | +++ src/common/debughelpers.cpp 2017-02-14 10:17:32 +0000 |
63 | @@ -1,5 +1,5 @@ |
64 | /* |
65 | - * Copyright (C) 2013-2015 Canonical, Ltd. |
66 | + * Copyright (C) 2013-2017 Canonical, Ltd. |
67 | * |
68 | * This program is free software: you can redistribute it and/or modify it under |
69 | * the terms of the GNU Lesser General Public License version 3, as published by |
70 | @@ -371,3 +371,49 @@ |
71 | return "???"; |
72 | } |
73 | } |
74 | + |
75 | +const char* mirEventTypeToStr(MirEventType t) |
76 | +{ |
77 | + switch (t) { |
78 | + case mir_event_type_key: |
79 | + return "key"; |
80 | + case mir_event_type_motion: |
81 | + return "motion"; |
82 | + case mir_event_type_window: |
83 | + return "window"; |
84 | + case mir_event_type_resize: |
85 | + return "resize"; |
86 | + case mir_event_type_prompt_session_state_change: |
87 | + return "prompt_session_state_change"; |
88 | + case mir_event_type_orientation: |
89 | + return "orientation"; |
90 | + case mir_event_type_close_window: |
91 | + return "close_window"; |
92 | + case mir_event_type_input: |
93 | + return "input"; |
94 | + case mir_event_type_keymap: |
95 | + return "keymap"; |
96 | + case mir_event_type_window_output: |
97 | + return "window_output"; |
98 | + case mir_event_type_input_device_state: |
99 | + return "input_device_state"; |
100 | + case mir_event_type_window_placement: |
101 | + return "window_placement"; |
102 | + default: |
103 | + return "????"; |
104 | + } |
105 | + Q_UNREACHABLE(); |
106 | +} |
107 | + |
108 | +const char *mirLifecycleStateToStr(MirLifecycleState value) |
109 | +{ |
110 | + switch (value) { |
111 | + case mir_lifecycle_state_will_suspend: |
112 | + return "will_suspend"; |
113 | + case mir_lifecycle_state_resumed: |
114 | + return "resumed"; |
115 | + case mir_lifecycle_connection_lost: |
116 | + return "connection_lost"; |
117 | + } |
118 | + Q_UNREACHABLE(); |
119 | +} |
120 | |
121 | === modified file 'src/common/debughelpers.h' |
122 | --- src/common/debughelpers.h 2017-01-18 21:24:15 +0000 |
123 | +++ src/common/debughelpers.h 2017-02-14 10:17:32 +0000 |
124 | @@ -1,5 +1,5 @@ |
125 | /* |
126 | - * Copyright (C) 2013-2015 Canonical, Ltd. |
127 | + * Copyright (C) 2013-2017 Canonical, Ltd. |
128 | * |
129 | * This program is free software: you can redistribute it and/or modify it under |
130 | * the terms of the GNU Lesser General Public License version 3, as published by |
131 | @@ -28,11 +28,13 @@ |
132 | QString touchEventToString(const QTouchEvent *ev); |
133 | |
134 | QString mirSurfaceAttribAndValueToString(MirWindowAttrib attrib, int value); |
135 | +const char* mirEventTypeToStr(MirEventType t); |
136 | const char *mirSurfaceTypeToStr(int value); |
137 | const char *mirSurfaceStateToStr(int value); |
138 | const char *mirSurfaceFocusStateToStr(int value); |
139 | const char *mirSurfaceVisibilityToStr(int value); |
140 | const char *mirMotionActionToStr(int value); |
141 | +const char *mirLifecycleStateToStr(MirLifecycleState value); |
142 | |
143 | const char *applicationStateToStr(int state); |
144 | |
145 | |
146 | === modified file 'src/common/windowcontrollerinterface.h' |
147 | --- src/common/windowcontrollerinterface.h 2016-11-03 20:17:46 +0000 |
148 | +++ src/common/windowcontrollerinterface.h 2017-02-14 10:17:32 +0000 |
149 | @@ -1,5 +1,5 @@ |
150 | /* |
151 | - * Copyright (C) 2016 Canonical, Ltd. |
152 | + * Copyright (C) 2016-2017 Canonical, Ltd. |
153 | * |
154 | * This program is free software: you can redistribute it and/or modify it under |
155 | * the terms of the GNU Lesser General Public License version 3, as published by |
156 | @@ -18,6 +18,7 @@ |
157 | #define WINDOWCONTROLLERINTERFACE_H |
158 | |
159 | #include <miral/window.h> |
160 | +#include <miral/window_specification.h> |
161 | |
162 | #include <mir_toolkit/event.h> |
163 | |
164 | |
165 | === modified file 'src/modules/Unity/Application/CMakeLists.txt' |
166 | --- src/modules/Unity/Application/CMakeLists.txt 2016-11-15 17:54:03 +0000 |
167 | +++ src/modules/Unity/Application/CMakeLists.txt 2017-02-14 10:17:32 +0000 |
168 | @@ -1,6 +1,7 @@ |
169 | include_directories( |
170 | ${CMAKE_SOURCE_DIR}/src/platforms/mirserver |
171 | ${CMAKE_SOURCE_DIR}/src/common |
172 | + fake |
173 | ) |
174 | |
175 | include_directories( |
176 | @@ -35,17 +36,23 @@ |
177 | ../../../common/abstractdbusservicemonitor.cpp |
178 | ../../../common/debughelpers.cpp |
179 | dbusfocusinfo.cpp |
180 | + fake/faketaskcontroller.cpp |
181 | + fake/fakeapplicationinfo.cpp |
182 | + fake/fakemaliit.cpp |
183 | + fake/fakemirclient.cpp |
184 | + fake/fakeprompt.cpp |
185 | plugin.cpp |
186 | mirsurface.cpp |
187 | mirsurfaceinterface.h |
188 | mirsurfaceitem.cpp |
189 | mirsurfacelistmodel.cpp |
190 | + mirtestsingleton.cpp |
191 | mirbuffersgtexture.cpp |
192 | proc_info.cpp |
193 | session.cpp |
194 | - sessionmanager.cpp |
195 | sharedwakelock.cpp |
196 | surfacemanager.cpp |
197 | + taskcontroller.cpp |
198 | upstart/applicationinfo.cpp |
199 | upstart/taskcontroller.cpp |
200 | timer.cpp |
201 | @@ -66,6 +73,7 @@ |
202 | applicationinfo.h |
203 | taskcontroller.h |
204 | settings_interface.h |
205 | + resources/surfaces.qrc |
206 | ) |
207 | |
208 | add_library(unityapplicationplugin SHARED |
209 | |
210 | === modified file 'src/modules/Unity/Application/application.cpp' |
211 | --- src/modules/Unity/Application/application.cpp 2017-02-02 09:36:07 +0000 |
212 | +++ src/modules/Unity/Application/application.cpp 2017-02-14 10:17:32 +0000 |
213 | @@ -392,7 +392,7 @@ |
214 | if (m_processState == ProcessRunning) { |
215 | suspend(); |
216 | } else { |
217 | - // we can't suspend it since we have no information on the app process |
218 | + DEBUG_MSG << "() Can't suspend since we have no information on the app process"; |
219 | Q_ASSERT(m_processState == ProcessUnknown); |
220 | } |
221 | break; |
222 | |
223 | === modified file 'src/modules/Unity/Application/application.h' |
224 | --- src/modules/Unity/Application/application.h 2016-11-15 17:54:03 +0000 |
225 | +++ src/modules/Unity/Application/application.h 2017-02-14 10:17:32 +0000 |
226 | @@ -184,7 +184,6 @@ |
227 | ProxySurfaceListModel *m_proxyPromptSurfaceList; |
228 | |
229 | friend class ApplicationManager; |
230 | - friend class SessionManager; |
231 | friend class Session; |
232 | }; |
233 | |
234 | |
235 | === modified file 'src/modules/Unity/Application/application_manager.cpp' |
236 | --- src/modules/Unity/Application/application_manager.cpp 2017-02-02 09:36:07 +0000 |
237 | +++ src/modules/Unity/Application/application_manager.cpp 2017-02-14 10:17:32 +0000 |
238 | @@ -1,5 +1,5 @@ |
239 | /* |
240 | - * Copyright (C) 2013-2016 Canonical, Ltd. |
241 | + * Copyright (C) 2013-2017 Canonical, Ltd. |
242 | * |
243 | * This program is free software: you can redistribute it and/or modify it under |
244 | * the terms of the GNU Lesser General Public License version 3, as published by |
245 | @@ -24,12 +24,12 @@ |
246 | #include "sharedwakelock.h" |
247 | #include "proc_info.h" |
248 | #include "upstart/taskcontroller.h" |
249 | +#include "faketaskcontroller.h" |
250 | #include "tracepoints.h" // generated from tracepoints.tp |
251 | #include "settings.h" |
252 | |
253 | // mirserver |
254 | #include "nativeinterface.h" |
255 | -#include "sessionauthorizer.h" |
256 | #include "logging.h" |
257 | |
258 | //miral |
259 | @@ -73,28 +73,6 @@ |
260 | return appId; |
261 | } |
262 | |
263 | -void connectToSessionAuthorizer(ApplicationManager *manager, SessionAuthorizer *authorizer) |
264 | -{ |
265 | - QObject::connect(authorizer, &SessionAuthorizer::requestAuthorizationForSession, |
266 | - manager, &ApplicationManager::authorizeSession, Qt::BlockingQueuedConnection); |
267 | -} |
268 | - |
269 | -void connectToTaskController(ApplicationManager *manager, TaskController *controller) |
270 | -{ |
271 | - QObject::connect(controller, &TaskController::processStarting, |
272 | - manager, &ApplicationManager::onProcessStarting); |
273 | - QObject::connect(controller, &TaskController::processStopped, |
274 | - manager, &ApplicationManager::onProcessStopped); |
275 | - QObject::connect(controller, &TaskController::processSuspended, |
276 | - manager, &ApplicationManager::onProcessSuspended); |
277 | - QObject::connect(controller, &TaskController::processFailed, |
278 | - manager, &ApplicationManager::onProcessFailed); |
279 | - QObject::connect(controller, &TaskController::focusRequested, |
280 | - manager, &ApplicationManager::onFocusRequested); |
281 | - QObject::connect(controller, &TaskController::resumeRequested, |
282 | - manager, &ApplicationManager::onResumeRequested); |
283 | -} |
284 | - |
285 | } // namespace |
286 | |
287 | ApplicationManager* ApplicationManager::create() |
288 | @@ -107,10 +85,17 @@ |
289 | return nullptr; |
290 | } |
291 | |
292 | - SessionAuthorizer *sessionAuthorizer = static_cast<SessionAuthorizer*>(nativeInterface->nativeResourceForIntegration("SessionAuthorizer")); |
293 | + QSharedPointer<TaskController> taskController; |
294 | + QSharedPointer<ProcInfo> procInfo; |
295 | + if (qgetenv("UNITY_TESTING") == "1") { |
296 | + auto *fakeTaskController = new FakeTaskController(); |
297 | + taskController.reset(fakeTaskController); |
298 | + procInfo = fakeTaskController->procInfo(); |
299 | + } else { |
300 | + taskController.reset(new upstart::TaskController()); |
301 | + procInfo.reset(new ProcInfo()); |
302 | + } |
303 | |
304 | - QSharedPointer<TaskController> taskController(new upstart::TaskController()); |
305 | - QSharedPointer<ProcInfo> procInfo(new ProcInfo()); |
306 | QSharedPointer<SharedWakelock> sharedWakelock(new SharedWakelock); |
307 | QSharedPointer<Settings> settings(new Settings()); |
308 | |
309 | @@ -126,9 +111,6 @@ |
310 | settings |
311 | ); |
312 | |
313 | - connectToSessionAuthorizer(appManager, sessionAuthorizer); |
314 | - connectToTaskController(appManager, taskController.data()); |
315 | - |
316 | // Emit signal to notify Upstart that Mir is ready to receive client connections |
317 | // see http://upstart.ubuntu.com/cookbook/#expect-stop |
318 | // FIXME: should not be qtmir's job, instead should notify the user of this library |
319 | @@ -166,6 +148,23 @@ |
320 | { |
321 | qCDebug(QTMIR_APPLICATIONS) << "ApplicationManager::ApplicationManager (this=%p)" << this; |
322 | setObjectName(QStringLiteral("qtmir::ApplicationManager")); |
323 | + |
324 | + QObject::connect(m_taskController.data(), &TaskController::processStarting, |
325 | + this, &ApplicationManager::onProcessStarting); |
326 | + QObject::connect(m_taskController.data(), &TaskController::processStopped, |
327 | + this, &ApplicationManager::onProcessStopped); |
328 | + QObject::connect(m_taskController.data(), &TaskController::processSuspended, |
329 | + this, &ApplicationManager::onProcessSuspended); |
330 | + QObject::connect(m_taskController.data(), &TaskController::processFailed, |
331 | + this, &ApplicationManager::onProcessFailed); |
332 | + QObject::connect(m_taskController.data(), &TaskController::focusRequested, |
333 | + this, &ApplicationManager::onFocusRequested); |
334 | + QObject::connect(m_taskController.data(), &TaskController::resumeRequested, |
335 | + this, &ApplicationManager::onResumeRequested); |
336 | + QObject::connect(m_taskController.data(), &TaskController::authorizationRequestedForSession, |
337 | + this, &ApplicationManager::authorizeSession); |
338 | + QObject::connect(m_taskController.data(), &TaskController::sessionStarting, |
339 | + this, &ApplicationManager::onSessionStarting); |
340 | } |
341 | |
342 | ApplicationManager::~ApplicationManager() |
343 | @@ -580,14 +579,14 @@ |
344 | |
345 | auto qtmirSurface = static_cast<qtmir::MirSurfaceInterface*>(surface); |
346 | |
347 | - return findApplicationWithPid(miral::pid_of(qtmirSurface->session()->session())); |
348 | + return findApplicationWithPid(PidFetcher::pidOf(qtmirSurface->session()->session())); |
349 | } |
350 | |
351 | Application* ApplicationManager::findApplicationWithSession(const std::shared_ptr<ms::Session> &session) |
352 | { |
353 | if (!session) |
354 | return nullptr; |
355 | - return findApplicationWithPid(miral::pid_of(session)); |
356 | + return findApplicationWithPid(PidFetcher::pidOf(session)); |
357 | } |
358 | |
359 | Application* ApplicationManager::findApplicationWithPid(const pid_t pid) const |
360 | @@ -596,7 +595,7 @@ |
361 | return nullptr; |
362 | |
363 | for (Application *app : m_applications) { |
364 | - if (app->m_pid == pid) { |
365 | + if (app->pid() == pid) { |
366 | return app; |
367 | } |
368 | } |
369 | @@ -665,7 +664,6 @@ |
370 | application->deleteLater(); |
371 | }); |
372 | |
373 | - |
374 | beginInsertRows(QModelIndex(), m_applications.count(), m_applications.count()); |
375 | m_applications.append(application); |
376 | endInsertRows(); |
377 | @@ -785,4 +783,18 @@ |
378 | return nullptr; |
379 | } |
380 | |
381 | + |
382 | +void ApplicationManager::onSessionStarting(SessionInterface *qmlSession) |
383 | +{ |
384 | + Application* application = findApplicationWithSession(qmlSession->session()); |
385 | + if (application && application->state() != Application::Running) { |
386 | + application->setSession(qmlSession); |
387 | + } |
388 | +} |
389 | + |
390 | +SessionInterface *ApplicationManager::findSession(const mir::scene::Session* session) const |
391 | +{ |
392 | + return m_taskController->findSession(session); |
393 | +} |
394 | + |
395 | } // namespace qtmir |
396 | |
397 | === modified file 'src/modules/Unity/Application/application_manager.h' |
398 | --- src/modules/Unity/Application/application_manager.h 2017-02-02 09:36:07 +0000 |
399 | +++ src/modules/Unity/Application/application_manager.h 2017-02-14 10:17:32 +0000 |
400 | @@ -94,6 +94,8 @@ |
401 | const QList<Application*> &list() const { return m_applications; } |
402 | qtmir::Application* findApplicationWithPid(const pid_t pid) const; |
403 | |
404 | + SessionInterface *findSession(const mir::scene::Session* session) const; |
405 | + |
406 | public Q_SLOTS: |
407 | void authorizeSession(const pid_t pid, bool &authorized); |
408 | |
409 | @@ -103,6 +105,7 @@ |
410 | void onProcessFailed(const QString& appId, TaskController::Error error); |
411 | void onFocusRequested(const QString& appId); |
412 | void onResumeRequested(const QString& appId); |
413 | + void onSessionStarting(SessionInterface *session); |
414 | |
415 | Q_SIGNALS: |
416 | void emptyChanged(); |
417 | @@ -138,7 +141,6 @@ |
418 | |
419 | friend class Application; |
420 | friend class DBusWindowStack; |
421 | - friend class SessionManager; |
422 | }; |
423 | |
424 | } // namespace qtmir |
425 | |
426 | === added directory 'src/modules/Unity/Application/fake' |
427 | === added file 'src/modules/Unity/Application/fake/fakeapplicationinfo.cpp' |
428 | --- src/modules/Unity/Application/fake/fakeapplicationinfo.cpp 1970-01-01 00:00:00 +0000 |
429 | +++ src/modules/Unity/Application/fake/fakeapplicationinfo.cpp 2017-02-14 10:17:32 +0000 |
430 | @@ -0,0 +1,26 @@ |
431 | +/* |
432 | + * Copyright (C) 2016 Canonical, Ltd. |
433 | + * |
434 | + * This program is free software: you can redistribute it and/or modify it under |
435 | + * the terms of the GNU Lesser General Public License version 3, as published by |
436 | + * the Free Software Foundation. |
437 | + * |
438 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
439 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
440 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
441 | + * Lesser General Public License for more details. |
442 | + * |
443 | + * You should have received a copy of the GNU Lesser General Public License |
444 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
445 | + * |
446 | + */ |
447 | + |
448 | +#include "fakeapplicationinfo.h" |
449 | + |
450 | +using namespace qtmir; |
451 | + |
452 | +void FakeApplicationInfo::setIconId(const QString &iconId) |
453 | +{ |
454 | + m_icon = QString("qrc:///Unity/Application/icons/%1@18.png") |
455 | + .arg(iconId); |
456 | +} |
457 | |
458 | === added file 'src/modules/Unity/Application/fake/fakeapplicationinfo.h' |
459 | --- src/modules/Unity/Application/fake/fakeapplicationinfo.h 1970-01-01 00:00:00 +0000 |
460 | +++ src/modules/Unity/Application/fake/fakeapplicationinfo.h 2017-02-14 10:17:32 +0000 |
461 | @@ -0,0 +1,93 @@ |
462 | +/* |
463 | + * Copyright (C) 2016 Canonical, Ltd. |
464 | + * |
465 | + * This program is free software: you can redistribute it and/or modify it under |
466 | + * the terms of the GNU Lesser General Public License version 3, as published by |
467 | + * the Free Software Foundation. |
468 | + * |
469 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
470 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
471 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
472 | + * Lesser General Public License for more details. |
473 | + * |
474 | + * You should have received a copy of the GNU Lesser General Public License |
475 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
476 | + * |
477 | + */ |
478 | + |
479 | +#ifndef QTMIR_FAKE_APPLICATION_INFO_H |
480 | +#define QTMIR_FAKE_APPLICATION_INFO_H |
481 | + |
482 | +#include "applicationinfo.h" |
483 | + |
484 | +#include <mir_toolkit/common.h> |
485 | + |
486 | +namespace qtmir { |
487 | + |
488 | +class FakeApplicationInfo : public ApplicationInfo |
489 | +{ |
490 | + Q_OBJECT |
491 | +public: |
492 | + FakeApplicationInfo(const QString &appId) { m_appId = appId; } |
493 | + |
494 | + QString appId() const override { return m_appId; } |
495 | + |
496 | + QString name() const override { return m_name; } |
497 | + void setName(const QString &name) { m_name = name; } |
498 | + |
499 | + QString comment() const override { return m_comment; } |
500 | + |
501 | + QUrl icon() const override { return m_icon; } |
502 | + |
503 | + QString splashTitle() const override { return m_splashTitle; } |
504 | + QUrl splashImage() const override { return m_splashImage; } |
505 | + bool splashShowHeader() const override { return m_splashShowHeader; } |
506 | + QString splashColor() const override { return m_splashColor; } |
507 | + QString splashColorHeader() const override { return m_splashColorHeader; } |
508 | + QString splashColorFooter() const override { return m_splashColorFooter; } |
509 | + Qt::ScreenOrientations supportedOrientations() const override { return m_supportedOrientations; } |
510 | + bool rotatesWindowContents() const override { return m_rotatesWindowContents; } |
511 | + |
512 | + void setIsTouchApp(bool value) { m_isTouchApp = value; } |
513 | + bool isTouchApp() const override { return m_isTouchApp; } |
514 | + |
515 | + void setScreenshotId(const QString &screenshotId) { m_screenshotId = screenshotId; } |
516 | + QString screenshotId() const { return m_screenshotId; } |
517 | + |
518 | + void setIconId(const QString &iconId); |
519 | + void setSupportedOrientations(Qt::ScreenOrientations orientations) { m_supportedOrientations = orientations; } |
520 | + void setRotatesWindowContents(bool value) { m_rotatesWindowContents = value; } |
521 | + |
522 | + void setInitialWindowState(MirWindowState value) { m_initialWindowState = value; } |
523 | + MirWindowState initialWindowState() const { return m_initialWindowState; } |
524 | + |
525 | + // Window type to be used when creating top-level windows for this application |
526 | + void setWindowType(MirWindowType value) { m_windowType = value; } |
527 | + MirWindowType windowType() const { return m_windowType; } |
528 | + |
529 | +private: |
530 | + QString m_appId; |
531 | + QString m_name; |
532 | + QString m_comment; |
533 | + QUrl m_icon; |
534 | + QString m_splashTitle; |
535 | + QUrl m_splashImage; |
536 | + bool m_splashShowHeader; |
537 | + QString m_splashColor; |
538 | + QString m_splashColorHeader; |
539 | + QString m_splashColorFooter; |
540 | + Qt::ScreenOrientations m_supportedOrientations{Qt::PortraitOrientation | |
541 | + Qt::LandscapeOrientation | |
542 | + Qt::InvertedPortraitOrientation | |
543 | + Qt::InvertedLandscapeOrientation}; |
544 | + bool m_rotatesWindowContents{false}; |
545 | + bool m_isTouchApp{true}; |
546 | + |
547 | + QString m_screenshotId; |
548 | + MirWindowState m_initialWindowState{mir_window_state_restored}; |
549 | + MirWindowType m_windowType{mir_window_type_normal}; |
550 | +}; |
551 | + |
552 | +} // namespace qtmir |
553 | + |
554 | +#endif // QTMIR_FAKE_APPLICATION_INFO_H |
555 | |
556 | === added file 'src/modules/Unity/Application/fake/fakemaliit.cpp' |
557 | --- src/modules/Unity/Application/fake/fakemaliit.cpp 1970-01-01 00:00:00 +0000 |
558 | +++ src/modules/Unity/Application/fake/fakemaliit.cpp 2017-02-14 10:17:32 +0000 |
559 | @@ -0,0 +1,76 @@ |
560 | +/* |
561 | + * Copyright (C) 2017 Canonical, Ltd. |
562 | + * |
563 | + * This program is free software: you can redistribute it and/or modify it under |
564 | + * the terms of the GNU Lesser General Public License version 3, as published by |
565 | + * the Free Software Foundation. |
566 | + * |
567 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
568 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
569 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
570 | + * Lesser General Public License for more details. |
571 | + * |
572 | + * You should have received a copy of the GNU Lesser General Public License |
573 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
574 | + * |
575 | + */ |
576 | + |
577 | +#include "fakemaliit.h" |
578 | + |
579 | +// Qt |
580 | +#include <QPainter> |
581 | + |
582 | +// mir |
583 | +#include <mir_toolkit/mir_buffer_stream.h> |
584 | + |
585 | +using namespace qtmir; |
586 | + |
587 | +/************************************************************************************************** |
588 | + * FakeMaliitLauncher |
589 | + *************************************************************************************************/ |
590 | + |
591 | +FakeMaliitLauncher::FakeMaliitLauncher(QSharedPointer<FakeApplicationInfo> appInfo, pid_t pid, QObject *parent) |
592 | + : FakeMirClientLauncher(appInfo, pid, parent) |
593 | +{ |
594 | +} |
595 | + |
596 | +MirClient *FakeMaliitLauncher::createClient() |
597 | +{ |
598 | + return new Maliit(m_appInfo, m_connection); |
599 | +} |
600 | + |
601 | +/************************************************************************************************** |
602 | + * Maliit |
603 | + *************************************************************************************************/ |
604 | + |
605 | +Maliit::Maliit(QSharedPointer<FakeApplicationInfo> appInfo, miral::toolkit::Connection conn) |
606 | + : MirClient(appInfo, conn) |
607 | +{ |
608 | +} |
609 | + |
610 | +QSize Maliit::update(MirWindow *window) |
611 | +{ |
612 | + MirBufferStream* buffer_stream = mir_window_get_buffer_stream(window); |
613 | + |
614 | + // TODO sometimes buffer_stream is nullptr |
615 | + // (Only observed when creating a lot of clients at once) |
616 | + if (!buffer_stream) |
617 | + return QSize(); |
618 | + |
619 | + MirGraphicsRegion region; |
620 | + mir_buffer_stream_get_graphics_region(buffer_stream, ®ion); |
621 | + |
622 | + Q_ASSERT(!m_screenshot.isNull()); |
623 | + |
624 | + QImage windowImage((uchar*)region.vaddr, region.width, region.height, QImage::Format_RGB32); |
625 | + { |
626 | + QPainter painter(&windowImage); |
627 | + |
628 | + painter.fillRect(0, 0, windowImage.width(), windowImage.height()*0.6, Qt::transparent); |
629 | + painter.drawImage(QRectF(0, windowImage.height()*0.6, windowImage.width(), windowImage.height()*0.4), m_screenshot); |
630 | + } |
631 | + |
632 | + mir_buffer_stream_swap_buffers_sync(buffer_stream); |
633 | + |
634 | + return windowImage.size(); |
635 | +} |
636 | |
637 | === added file 'src/modules/Unity/Application/fake/fakemaliit.h' |
638 | --- src/modules/Unity/Application/fake/fakemaliit.h 1970-01-01 00:00:00 +0000 |
639 | +++ src/modules/Unity/Application/fake/fakemaliit.h 2017-02-14 10:17:32 +0000 |
640 | @@ -0,0 +1,47 @@ |
641 | +/* |
642 | + * Copyright (C) 2017 Canonical, Ltd. |
643 | + * |
644 | + * This program is free software: you can redistribute it and/or modify it under |
645 | + * the terms of the GNU Lesser General Public License version 3, as published by |
646 | + * the Free Software Foundation. |
647 | + * |
648 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
649 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
650 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
651 | + * Lesser General Public License for more details. |
652 | + * |
653 | + * You should have received a copy of the GNU Lesser General Public License |
654 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
655 | + * |
656 | + */ |
657 | + |
658 | +#ifndef QTMIR_FAKE_MALIIT_H |
659 | +#define QTMIR_FAKE_MALIIT_H |
660 | + |
661 | +#include "fakemirclient.h" |
662 | + |
663 | +namespace qtmir { |
664 | + |
665 | +class Maliit : public MirClient |
666 | +{ |
667 | + Q_OBJECT |
668 | + |
669 | +public: |
670 | + Maliit(QSharedPointer<FakeApplicationInfo> appInfo, miral::toolkit::Connection); |
671 | + |
672 | +private: |
673 | + QSize update(MirWindow *window) override; |
674 | +}; |
675 | + |
676 | +class FakeMaliitLauncher : public FakeMirClientLauncher |
677 | +{ |
678 | + Q_OBJECT |
679 | +public: |
680 | + FakeMaliitLauncher(QSharedPointer<FakeApplicationInfo> appInfo, pid_t pid, QObject *parent = nullptr); |
681 | +private: |
682 | + MirClient *createClient() override; |
683 | +}; |
684 | + |
685 | +} // namespace qtmir |
686 | + |
687 | +#endif // QTMIR_FAKE_MALIIT_H |
688 | |
689 | === added file 'src/modules/Unity/Application/fake/fakemirclient.cpp' |
690 | --- src/modules/Unity/Application/fake/fakemirclient.cpp 1970-01-01 00:00:00 +0000 |
691 | +++ src/modules/Unity/Application/fake/fakemirclient.cpp 2017-02-14 10:17:32 +0000 |
692 | @@ -0,0 +1,685 @@ |
693 | +/* |
694 | + * Copyright (C) 2017 Canonical, Ltd. |
695 | + * |
696 | + * This program is free software: you can redistribute it and/or modify it under |
697 | + * the terms of the GNU Lesser General Public License version 3, as published by |
698 | + * the Free Software Foundation. |
699 | + * |
700 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
701 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
702 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
703 | + * Lesser General Public License for more details. |
704 | + * |
705 | + * You should have received a copy of the GNU Lesser General Public License |
706 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
707 | + * |
708 | + */ |
709 | + |
710 | +#include "fakemirclient.h" |
711 | + |
712 | +// src/common |
713 | +#include <debughelpers.h> |
714 | + |
715 | +#include <miral/toolkit/persistent_id.h> |
716 | +#include <miral/toolkit/window_spec.h> |
717 | + |
718 | +// std |
719 | +#include <atomic> |
720 | +#include <chrono> |
721 | +#include <mutex> |
722 | +#include <thread> |
723 | + |
724 | +// Qt |
725 | +#include <qpa/qplatformnativeinterface.h> |
726 | +#include <QGuiApplication> |
727 | +#include <QCoreApplication> |
728 | +#include <QEventLoop> |
729 | +#include <QPainter> |
730 | + |
731 | +// mir |
732 | +#include <mir/main_loop.h> |
733 | +#include <mir_toolkit/mir_buffer_stream.h> |
734 | + |
735 | +// qpa mirserver |
736 | +#include "logging.h" |
737 | + |
738 | +#include <QDebug> |
739 | + |
740 | +using namespace qtmir; |
741 | +using namespace miral::toolkit; |
742 | +using namespace std::chrono_literals; |
743 | + |
744 | +#define DEBUG_MSG qCDebug(QTMIR_FAKECLIENTS).nospace() << "MirClient["<< m_appInfo->appId() <<"]::" << __func__ |
745 | +#define CRITICAL_MSG qCCritical(QTMIR_FAKECLIENTS).nospace() << "MirClient["<< m_appInfo->appId() <<"]::" << __func__ |
746 | + |
747 | +class MirClientEvent : public QEvent |
748 | +{ |
749 | +public: |
750 | + MirClientEvent(MirWindow* window, const MirEvent *event, QEvent::Type type) |
751 | + : QEvent(type), window(window), mirEvent(event) { |
752 | + mirEvent = mir_event_ref(event); |
753 | + } |
754 | + ~MirClientEvent() |
755 | + { |
756 | + mir_event_unref(mirEvent); |
757 | + } |
758 | + |
759 | + MirWindow* window; |
760 | + const MirEvent *mirEvent; |
761 | +}; |
762 | + |
763 | +namespace { |
764 | +void lifecycleEventCallback(MirConnection* /*connection*/, MirLifecycleState state, void* context) |
765 | +{ |
766 | + static_cast<MirClient*>(context)->lifecycleEvent(state); |
767 | +} |
768 | + |
769 | +int mirClientEventType{0}; |
770 | +void windowEventHandler(MirWindow* window, MirEvent const* event, void* context) |
771 | +{ |
772 | + if (mirClientEventType == 0) { |
773 | + mirClientEventType = QEvent::registerEventType(); |
774 | + } |
775 | + auto client = static_cast<MirClient*>(context); |
776 | + QEvent *qtEvent = new MirClientEvent(window, event, static_cast<QEvent::Type>(mirClientEventType)); |
777 | + QCoreApplication::postEvent(client, qtEvent); |
778 | +} |
779 | + |
780 | +} // anonymous namespace |
781 | + |
782 | + |
783 | +/************************************************************************************************** |
784 | + * FakeMirClientLauncher |
785 | + *************************************************************************************************/ |
786 | + |
787 | +FakeMirClientLauncher::FakeMirClientLauncher(QSharedPointer<FakeApplicationInfo> appInfo, pid_t pid, QObject *parent) |
788 | + : QThread(parent) |
789 | + , m_pid(pid) |
790 | + , m_appInfo(appInfo) |
791 | +{ |
792 | + connect(this, &QThread::finished, this, [this]{ m_fd = mir::Fd(); }); |
793 | +} |
794 | + |
795 | +void FakeMirClientLauncher::launch() |
796 | +{ |
797 | + auto nativeInterface = QGuiApplication::platformNativeInterface(); |
798 | + m_server = static_cast<mir::Server*>(nativeInterface->nativeResourceForIntegration("MirServer")); |
799 | + |
800 | + m_server->the_main_loop()->enqueue(this, [this] { launchFromMirServerThread(); }); |
801 | +} |
802 | + |
803 | +void FakeMirClientLauncher::launchFromMirServerThread() |
804 | +{ |
805 | + std::condition_variable condition; |
806 | + |
807 | + m_fd = m_server->open_client_socket([this, &condition](std::shared_ptr<mir::frontend::Session> const& fSession) |
808 | + { |
809 | + std::lock_guard<decltype(m_mutex)> lock_guard{m_mutex}; |
810 | + m_session = std::dynamic_pointer_cast<mir::scene::Session>(fSession); |
811 | + condition.notify_one(); |
812 | + }); |
813 | + |
814 | + char connect_string[64] = {0}; |
815 | + sprintf(connect_string, "fd://%d", m_fd.operator int()); |
816 | + |
817 | + m_connection = Connection{mir_connect_sync(connect_string, m_appInfo->appId().toLatin1().data())}; |
818 | + |
819 | + { |
820 | + std::unique_lock<decltype(m_mutex)> lock{m_mutex}; |
821 | + condition.wait(lock, [&] { return !!m_session.lock(); }); |
822 | + } |
823 | + |
824 | + start(); |
825 | +} |
826 | + |
827 | +std::shared_ptr<mir::scene::Session> FakeMirClientLauncher::session() |
828 | +{ |
829 | + auto sharedPtr = m_session.lock(); |
830 | + return sharedPtr; |
831 | +} |
832 | + |
833 | +MirClient *FakeMirClientLauncher::createClient() |
834 | +{ |
835 | + return new MirClient(m_appInfo, m_connection); |
836 | +} |
837 | + |
838 | +void FakeMirClientLauncher::run() |
839 | +{ |
840 | + { |
841 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
842 | + |
843 | + m_client = createClient(); |
844 | + connect(m_client, &MirClient::willSuspend, this, &FakeMirClientLauncher::willSuspend); |
845 | + connect(m_client, &MirClient::resumed, this, &FakeMirClientLauncher::resumed); |
846 | + connect(m_client, &MirClient::windowCreated, this, &FakeMirClientLauncher::addWindowAttributes); |
847 | + connect(m_client, &MirClient::windowAttributeChanged, this, &FakeMirClientLauncher::updateWindowAttribute); |
848 | + connect(m_client, &MirClient::windowClosed, this, &FakeMirClientLauncher::removeWindowAttributes); |
849 | + connect(m_client, &MirClient::touchPressed, this, &FakeMirClientLauncher::incrementTouchPressCount); |
850 | + connect(m_client, &MirClient::touchReleased, this, &FakeMirClientLauncher::incrementTouchReleaseCount); |
851 | + connect(m_client, &MirClient::mousePressed, this, &FakeMirClientLauncher::incrementMousePressCount); |
852 | + connect(m_client, &MirClient::mouseReleased, this, &FakeMirClientLauncher::incrementMouseReleaseCount); |
853 | + |
854 | + if (!m_manualWindowCreation) { |
855 | + // wait a bit so that the splash screen has some time to shine |
856 | + msleep(350); |
857 | + |
858 | + m_client->createWindow(); |
859 | + } |
860 | + |
861 | + // keep only one reference, in MirClient |
862 | + m_connection.reset(); |
863 | + } |
864 | + |
865 | + |
866 | + qCDebug(QTMIR_FAKECLIENTS).nospace() << "FakeMirClientLauncher::run[" << m_appInfo->appId() << "] entered loop."; |
867 | + exec(); |
868 | + qCDebug(QTMIR_FAKECLIENTS).nospace() << "FakeMirClientLauncher::run[" << m_appInfo->appId() << "] exited loop."; |
869 | + |
870 | + { |
871 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
872 | + |
873 | + delete m_client; |
874 | + m_client = nullptr; |
875 | + } |
876 | +} |
877 | + |
878 | +void FakeMirClientLauncher::createWindow() |
879 | +{ |
880 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
881 | + QMetaObject::invokeMethod(m_client, "createWindow", Qt::AutoConnection); |
882 | +} |
883 | + |
884 | +void FakeMirClientLauncher::killWindow(const QString &persistentId) |
885 | +{ |
886 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
887 | + QMetaObject::invokeMethod(m_client, "killWindow", Qt::AutoConnection, Q_ARG(QString, persistentId)); |
888 | +} |
889 | + |
890 | +void FakeMirClientLauncher::setWindowInputBounds(const QString &persistentId, QRect rect) |
891 | +{ |
892 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
893 | + QMetaObject::invokeMethod(m_client, "setWindowInputBounds", Qt::AutoConnection, |
894 | + Q_ARG(QString, persistentId), |
895 | + Q_ARG(QRect, rect)); |
896 | +} |
897 | + |
898 | +void FakeMirClientLauncher::setWindowMinimumWidth(const QString &persistentId, int value) |
899 | +{ |
900 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
901 | + QMetaObject::invokeMethod(m_client, "setWindowMinimumWidth", Qt::AutoConnection, |
902 | + Q_ARG(QString, persistentId), Q_ARG(int, value)); |
903 | +} |
904 | + |
905 | +void FakeMirClientLauncher::setWindowMaximumWidth(const QString &persistentId, int value) |
906 | +{ |
907 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
908 | + QMetaObject::invokeMethod(m_client, "setWindowMaximumWidth", Qt::AutoConnection, |
909 | + Q_ARG(QString, persistentId), Q_ARG(int, value)); |
910 | +} |
911 | + |
912 | +void FakeMirClientLauncher::setWindowMinimumHeight(const QString &persistentId, int value) |
913 | +{ |
914 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
915 | + QMetaObject::invokeMethod(m_client, "setWindowMinimumHeight", Qt::AutoConnection, |
916 | + Q_ARG(QString, persistentId), Q_ARG(int, value)); |
917 | +} |
918 | + |
919 | +void FakeMirClientLauncher::setWindowMaximumHeight(const QString &persistentId, int value) |
920 | +{ |
921 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
922 | + QMetaObject::invokeMethod(m_client, "setWindowMaximumHeight", Qt::AutoConnection, |
923 | + Q_ARG(QString, persistentId), Q_ARG(int, value)); |
924 | +} |
925 | + |
926 | +void FakeMirClientLauncher::setWindowWidthIncrement(const QString &persistentId, int value) |
927 | +{ |
928 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
929 | + QMetaObject::invokeMethod(m_client, "setWindowWidthIncrement", Qt::AutoConnection, |
930 | + Q_ARG(QString, persistentId), Q_ARG(int, value)); |
931 | +} |
932 | + |
933 | +void FakeMirClientLauncher::setWindowHeightIncrement(const QString &persistentId, int value) |
934 | +{ |
935 | + std::lock_guard<std::mutex> lock_guard{m_mutex}; |
936 | + QMetaObject::invokeMethod(m_client, "setWindowHeightIncrement", Qt::AutoConnection, |
937 | + Q_ARG(QString, persistentId), Q_ARG(int, value)); |
938 | +} |
939 | + |
940 | +void FakeMirClientLauncher::kill() |
941 | +{ |
942 | + m_killed = true; |
943 | + quit(); |
944 | +} |
945 | + |
946 | +const WindowAttributes *FakeMirClientLauncher::windowAttributes(const QString &persistentId) const |
947 | +{ |
948 | + auto iterator = m_windowAttributes.find(persistentId); |
949 | + if (iterator == m_windowAttributes.end()) { |
950 | + return nullptr; |
951 | + } else { |
952 | + return &(iterator.value()); |
953 | + } |
954 | +} |
955 | + |
956 | +void FakeMirClientLauncher::addWindowAttributes(QString persistentId, WindowAttributes windowAttributes) |
957 | +{ |
958 | + Q_ASSERT(!m_windowAttributes.contains(persistentId)); |
959 | + m_windowAttributes[persistentId] = windowAttributes; |
960 | +} |
961 | + |
962 | +void FakeMirClientLauncher::updateWindowAttribute(QString persistentId, MirWindowAttrib attribute, int value) |
963 | +{ |
964 | + Q_ASSERT(m_windowAttributes.contains(persistentId)); |
965 | + |
966 | + WindowAttributes &windowAttribs = m_windowAttributes[persistentId]; |
967 | + |
968 | + switch (attribute) { |
969 | + case mir_window_attrib_focus: |
970 | + windowAttribs.focusState = static_cast<MirWindowFocusState>(value); |
971 | + break; |
972 | + case mir_window_attrib_visibility: |
973 | + windowAttribs.visibility = static_cast<MirWindowVisibility>(value); |
974 | + break; |
975 | + default: |
976 | + // NOOP |
977 | + break; |
978 | + }; |
979 | +} |
980 | + |
981 | +void FakeMirClientLauncher::incrementTouchPressCount(QString persistentId) |
982 | +{ |
983 | + Q_ASSERT(m_windowAttributes.contains(persistentId)); |
984 | + WindowAttributes &windowAttribs = m_windowAttributes[persistentId]; |
985 | + ++windowAttribs.touchPressCount; |
986 | +} |
987 | + |
988 | +void FakeMirClientLauncher::incrementTouchReleaseCount(QString persistentId) |
989 | +{ |
990 | + Q_ASSERT(m_windowAttributes.contains(persistentId)); |
991 | + WindowAttributes &windowAttribs = m_windowAttributes[persistentId]; |
992 | + ++windowAttribs.touchReleaseCount; |
993 | +} |
994 | + |
995 | +void FakeMirClientLauncher::incrementMousePressCount(QString persistentId) |
996 | +{ |
997 | + Q_ASSERT(m_windowAttributes.contains(persistentId)); |
998 | + WindowAttributes &windowAttribs = m_windowAttributes[persistentId]; |
999 | + ++windowAttribs.mousePressCount; |
1000 | +} |
1001 | + |
1002 | +void FakeMirClientLauncher::incrementMouseReleaseCount(QString persistentId) |
1003 | +{ |
1004 | + Q_ASSERT(m_windowAttributes.contains(persistentId)); |
1005 | + WindowAttributes &windowAttribs = m_windowAttributes[persistentId]; |
1006 | + ++windowAttribs.mouseReleaseCount; |
1007 | +} |
1008 | + |
1009 | +void FakeMirClientLauncher::removeWindowAttributes(QString persistentId) |
1010 | +{ |
1011 | + Q_ASSERT(m_windowAttributes.contains(persistentId)); |
1012 | + m_windowAttributes.remove(persistentId); |
1013 | +} |
1014 | + |
1015 | +/************************************************************************************************** |
1016 | + * MirClient |
1017 | + *************************************************************************************************/ |
1018 | + |
1019 | +MirClient::MirClient(QSharedPointer<FakeApplicationInfo> appInfo, miral::toolkit::Connection connection) |
1020 | + : m_connection(connection) |
1021 | + , m_appInfo(appInfo) |
1022 | +{ |
1023 | + QString screenshotFileName; |
1024 | + if (m_appInfo->screenshotId().endsWith(".svg") || m_appInfo->screenshotId().endsWith(".png")) { |
1025 | + screenshotFileName = QString(":/Unity/Application/screenshots/%2") |
1026 | + .arg(m_appInfo->screenshotId()); |
1027 | + } else { |
1028 | + screenshotFileName = QString(":/Unity/Application/screenshots/%2@12.png") |
1029 | + .arg(m_appInfo->screenshotId()); |
1030 | + } |
1031 | + |
1032 | + m_screenshot = QImage(screenshotFileName); |
1033 | + |
1034 | + mir_connection_set_lifecycle_event_callback(connection, &lifecycleEventCallback, this); |
1035 | +} |
1036 | + |
1037 | +QSize MirClient::update(MirWindow* window) |
1038 | +{ |
1039 | + MirBufferStream* buffer_stream = mir_window_get_buffer_stream(window); |
1040 | + |
1041 | + // TODO sometimes buffer_stream is nullptr |
1042 | + // (Only observed when creating a lot of clients at once) |
1043 | + if (!buffer_stream) |
1044 | + return QSize(); |
1045 | + |
1046 | + MirGraphicsRegion region; |
1047 | + mir_buffer_stream_get_graphics_region(buffer_stream, ®ion); |
1048 | + |
1049 | + QImage windowImage((uchar*)region.vaddr, region.width, region.height, QImage::Format_RGB32); |
1050 | + { |
1051 | + QPainter painter(&windowImage); |
1052 | + if (m_screenshot.isNull()) { |
1053 | + painter.fillRect(0, 0, windowImage.width(), windowImage.height(), Qt::magenta); |
1054 | + } else { |
1055 | + painter.drawImage(QRectF(0, 0, windowImage.width(), windowImage.height()), m_screenshot); |
1056 | + } |
1057 | + } |
1058 | + |
1059 | + mir_buffer_stream_swap_buffers_sync(buffer_stream); |
1060 | + |
1061 | + return windowImage.size(); |
1062 | +} |
1063 | + |
1064 | +void MirClient::resizeEvent(MirWindow* window, MirResizeEvent const *event) |
1065 | +{ |
1066 | + // TODO redraw until we get a frame with the size announced in this event |
1067 | + |
1068 | + QSize targetSize(mir_resize_event_get_width(event), mir_resize_event_get_height(event)); |
1069 | + |
1070 | + QSize size = update(window); |
1071 | + |
1072 | + int attempts = 1; |
1073 | + while (size != targetSize && attempts < 5) { |
1074 | + size = update(window); |
1075 | + ++attempts; |
1076 | + } |
1077 | +} |
1078 | + |
1079 | +void MirClient::attributeChangeEvent(MirWindow *window, MirWindowEvent const *event) |
1080 | +{ |
1081 | + MirWindowAttrib attribute = mir_window_event_get_attribute(event); |
1082 | + int value = mir_window_event_get_attribute_value(event); |
1083 | + |
1084 | + Q_EMIT windowAttributeChanged(idForWindow(window), attribute, value); |
1085 | +} |
1086 | + |
1087 | +void MirClient::inputEvent(MirWindow* window, const MirInputEvent *event) |
1088 | +{ |
1089 | + switch (mir_input_event_get_type(event)) { |
1090 | + case mir_input_event_type_touch: |
1091 | + touchEvent(window, mir_input_event_get_touch_event(event)); |
1092 | + break; |
1093 | + case mir_input_event_type_pointer: |
1094 | + pointerEvent(window, mir_input_event_get_pointer_event(event)); |
1095 | + break; |
1096 | + default: |
1097 | + // don't care |
1098 | + break; |
1099 | + } |
1100 | +} |
1101 | + |
1102 | +void MirClient::touchEvent(MirWindow* window, const MirTouchEvent *event) |
1103 | +{ |
1104 | + |
1105 | + // Don't care about multi-touch |
1106 | + switch (mir_touch_event_action(event, 0)) { |
1107 | + case mir_touch_action_up: |
1108 | + Q_EMIT touchReleased(idForWindow(window)); |
1109 | + break; |
1110 | + case mir_touch_action_down: |
1111 | + Q_EMIT touchPressed(idForWindow(window)); |
1112 | + break; |
1113 | + default: |
1114 | + // don't care |
1115 | + break; |
1116 | + } |
1117 | +} |
1118 | + |
1119 | +void MirClient::pointerEvent(MirWindow* window, const MirPointerEvent *event) |
1120 | +{ |
1121 | + bool isPressed = mir_pointer_event_button_state(event, mir_pointer_button_primary); |
1122 | + |
1123 | + if (isPressed && !m_primaryButtonPressed) { |
1124 | + Q_EMIT mousePressed(idForWindow(window)); |
1125 | + } else if (!isPressed && m_primaryButtonPressed) { |
1126 | + Q_EMIT mouseReleased(idForWindow(window)); |
1127 | + } |
1128 | + |
1129 | + m_primaryButtonPressed = isPressed; |
1130 | +} |
1131 | + |
1132 | +void MirClient::windowEvent(MirWindow* window, MirEvent const* mirEvent) |
1133 | +{ |
1134 | + switch (mir_event_get_type(mirEvent)) |
1135 | + { |
1136 | + case mir_event_type_input: |
1137 | + inputEvent(window, mir_event_get_input_event(mirEvent)); |
1138 | + break; |
1139 | + case mir_event_type_resize: |
1140 | + resizeEvent(window, mir_event_get_resize_event(mirEvent)); |
1141 | + break; |
1142 | + case mir_event_type_window: |
1143 | + attributeChangeEvent(window, mir_event_get_window_event(mirEvent)); |
1144 | + break; |
1145 | + case mir_event_type_window_output: |
1146 | + break; |
1147 | + case mir_event_type_orientation: |
1148 | + break; |
1149 | + case mir_event_type_close_window: |
1150 | + closeWindow(window); |
1151 | + break; |
1152 | + default: |
1153 | + qDebug() << "MirClient::windowEvent unhandled event type: " << mirEventTypeToStr(mir_event_get_type(mirEvent)); |
1154 | + } |
1155 | +} |
1156 | + |
1157 | +void MirClient::customEvent(QEvent* event) |
1158 | +{ |
1159 | + auto mirClientEvent = static_cast<MirClientEvent*>(event); |
1160 | + windowEvent(mirClientEvent->window, mirClientEvent->mirEvent); |
1161 | +} |
1162 | + |
1163 | +void MirClient::createWindow() |
1164 | +{ |
1165 | + ++m_windowCounter; |
1166 | + |
1167 | + QString name = QString("%1 %2") |
1168 | + .arg(m_appInfo->name()) |
1169 | + .arg(m_windowCounter); |
1170 | + |
1171 | + MirWindowSpec *spec = mir_create_window_spec(m_connection); |
1172 | + mir_window_spec_set_type(spec, m_appInfo->windowType()); |
1173 | + mir_window_spec_set_width(spec, 640); |
1174 | + mir_window_spec_set_height(spec, 480); |
1175 | + mir_window_spec_set_pixel_format(spec, mir_pixel_format_argb_8888); |
1176 | + mir_window_spec_set_buffer_usage(spec, mir_buffer_usage_software); |
1177 | + mir_window_spec_set_name(spec, name.toLatin1().data()); |
1178 | + mir_window_spec_set_event_handler(spec, &windowEventHandler, this /*context*/); |
1179 | + mir_window_spec_set_state(spec, m_appInfo->initialWindowState()); |
1180 | + |
1181 | + miral::toolkit::Window window{ mir_create_window_sync(spec) }; |
1182 | + m_windows.append(window); |
1183 | + |
1184 | + mir_window_spec_release(spec); |
1185 | + spec = nullptr; |
1186 | + |
1187 | + Q_EMIT windowCreated(idForWindow(window), WindowAttributes(window)); |
1188 | + |
1189 | + // draw the first frame |
1190 | + update(window); |
1191 | +} |
1192 | + |
1193 | +void MirClient::killWindow(const QString &requestedId) |
1194 | +{ |
1195 | + for (int i = 0; i < m_windows.count(); ++i) { |
1196 | + MirWindow *window = m_windows[i]; |
1197 | + if (idForWindow(window) == requestedId) { |
1198 | + window = nullptr; |
1199 | + m_windows.removeAt(i); |
1200 | + } |
1201 | + } |
1202 | +} |
1203 | + |
1204 | +QString MirClient::idForWindow(MirWindow* window) |
1205 | +{ |
1206 | + if (m_surfaceIds.contains(window)) { |
1207 | + return m_surfaceIds[window]; |
1208 | + } else { |
1209 | + QString id(PersistentId(window).c_str()); |
1210 | + m_surfaceIds[window] = id; |
1211 | + return id; |
1212 | + } |
1213 | +} |
1214 | + |
1215 | +void MirClient::closeWindow(MirWindow *mirWindow) |
1216 | +{ |
1217 | + DEBUG_MSG << "(" << mirWindow << ")"; |
1218 | + |
1219 | + bool found = false; |
1220 | + for (int i = 0; i < m_windows.count() && !found; ++i) { |
1221 | + if (m_windows[i] == mirWindow) { |
1222 | + found = true; |
1223 | + DEBUG_MSG << "(" << mirWindow << ") - window removed"; |
1224 | + m_windows.remove(i); |
1225 | + } |
1226 | + } |
1227 | + |
1228 | + if (m_windows.isEmpty()) { |
1229 | + DEBUG_MSG << "(" << mirWindow << ") - quitting"; |
1230 | + QThread::currentThread()->quit(); |
1231 | + } |
1232 | +} |
1233 | + |
1234 | +MirWindow *MirClient::findWindow(const QString &requestedId) |
1235 | +{ |
1236 | + for (int i = 0; i < m_windows.count(); ++i) { |
1237 | + MirWindow *window = m_windows[i]; |
1238 | + |
1239 | + if (idForWindow(window) == requestedId) { |
1240 | + return window; |
1241 | + } |
1242 | + } |
1243 | + |
1244 | + return nullptr; |
1245 | +} |
1246 | + |
1247 | +void MirClient::setWindowInputBounds(const QString &persistentId, QRect rect) |
1248 | +{ |
1249 | + MirWindow *window = findWindow(persistentId); |
1250 | + if (!window) { |
1251 | + CRITICAL_MSG << "(" << persistentId << ", " << rect << ") - did not find window"; |
1252 | + return; |
1253 | + } |
1254 | + |
1255 | + DEBUG_MSG << "(" << persistentId << ", " << rect << ")"; |
1256 | + |
1257 | + MirWindowSpec* spec = mir_create_window_spec(m_connection); |
1258 | + |
1259 | + { |
1260 | + MirRectangle mirRect; |
1261 | + mirRect.left = rect.x(); |
1262 | + mirRect.top = rect.y(); |
1263 | + mirRect.width = rect.width(); |
1264 | + mirRect.height = rect.height(); |
1265 | + |
1266 | + mir_window_spec_set_input_shape(spec, &mirRect, 1 /*n_rects*/); |
1267 | + } |
1268 | + |
1269 | + mir_window_apply_spec(window, spec); |
1270 | + mir_window_spec_release(spec); |
1271 | +} |
1272 | + |
1273 | +void MirClient::setWindowMinimumWidth(const QString &persistentId, int value) |
1274 | +{ |
1275 | + MirWindow *window = findWindow(persistentId); |
1276 | + if (!window) { |
1277 | + CRITICAL_MSG << "(" << persistentId << ", " << value << ") - did not find window"; |
1278 | + return; |
1279 | + } |
1280 | + |
1281 | + DEBUG_MSG << "(" << persistentId << ", " << value << ")"; |
1282 | + |
1283 | + MirWindowSpec* spec = mir_create_window_spec(m_connection); |
1284 | + mir_window_spec_set_min_width(spec, value); |
1285 | + mir_window_apply_spec(window, spec); |
1286 | + mir_window_spec_release(spec); |
1287 | +} |
1288 | + |
1289 | +void MirClient::setWindowMaximumWidth(const QString &persistentId, int value) |
1290 | +{ |
1291 | + MirWindow *window = findWindow(persistentId); |
1292 | + if (!window) { |
1293 | + CRITICAL_MSG << "(" << persistentId << ", " << value << ") - did not find window"; |
1294 | + return; |
1295 | + } |
1296 | + |
1297 | + DEBUG_MSG << "(" << persistentId << ", " << value << ")"; |
1298 | + |
1299 | + MirWindowSpec* spec = mir_create_window_spec(m_connection); |
1300 | + mir_window_spec_set_max_width(spec, value); |
1301 | + mir_window_apply_spec(window, spec); |
1302 | + mir_window_spec_release(spec); |
1303 | +} |
1304 | + |
1305 | +void MirClient::setWindowMinimumHeight(const QString &persistentId, int value) |
1306 | +{ |
1307 | + MirWindow *window = findWindow(persistentId); |
1308 | + if (!window) { |
1309 | + CRITICAL_MSG << "(" << persistentId << ", " << value << ") - did not find window"; |
1310 | + return; |
1311 | + } |
1312 | + |
1313 | + DEBUG_MSG << "(" << persistentId << ", " << value << ")"; |
1314 | + |
1315 | + MirWindowSpec* spec = mir_create_window_spec(m_connection); |
1316 | + mir_window_spec_set_min_height(spec, value); |
1317 | + mir_window_apply_spec(window, spec); |
1318 | + mir_window_spec_release(spec); |
1319 | +} |
1320 | + |
1321 | +void MirClient::setWindowMaximumHeight(const QString &persistentId, int value) |
1322 | +{ |
1323 | + MirWindow *window = findWindow(persistentId); |
1324 | + if (!window) { |
1325 | + CRITICAL_MSG << "(" << persistentId << ", " << value << ") - did not find window"; |
1326 | + return; |
1327 | + } |
1328 | + |
1329 | + DEBUG_MSG << "(" << persistentId << ", " << value << ")"; |
1330 | + |
1331 | + MirWindowSpec* spec = mir_create_window_spec(m_connection); |
1332 | + mir_window_spec_set_max_height(spec, value); |
1333 | + mir_window_apply_spec(window, spec); |
1334 | + mir_window_spec_release(spec); |
1335 | +} |
1336 | + |
1337 | +void MirClient::setWindowWidthIncrement(const QString &persistentId, int value) |
1338 | +{ |
1339 | + MirWindow *window = findWindow(persistentId); |
1340 | + if (!window) { |
1341 | + CRITICAL_MSG << "(" << persistentId << ", " << value << ") - did not find window"; |
1342 | + return; |
1343 | + } |
1344 | + |
1345 | + DEBUG_MSG << "(" << persistentId << ", " << value << ")"; |
1346 | + |
1347 | + MirWindowSpec* spec = mir_create_window_spec(m_connection); |
1348 | + mir_window_spec_set_width_increment(spec, value); |
1349 | + mir_window_apply_spec(window, spec); |
1350 | + mir_window_spec_release(spec); |
1351 | +} |
1352 | + |
1353 | +void MirClient::setWindowHeightIncrement(const QString &persistentId, int value) |
1354 | +{ |
1355 | + MirWindow *window = findWindow(persistentId); |
1356 | + if (!window) { |
1357 | + CRITICAL_MSG << "(" << persistentId << ", " << value << ") - did not find window"; |
1358 | + return; |
1359 | + } |
1360 | + |
1361 | + DEBUG_MSG << "(" << persistentId << ", " << value << ")"; |
1362 | + |
1363 | + MirWindowSpec* spec = mir_create_window_spec(m_connection); |
1364 | + mir_window_spec_set_height_increment(spec, value); |
1365 | + mir_window_apply_spec(window, spec); |
1366 | + mir_window_spec_release(spec); |
1367 | +} |
1368 | + |
1369 | +void MirClient::lifecycleEvent(MirLifecycleState state) |
1370 | +{ |
1371 | + DEBUG_MSG << "(" << mirLifecycleStateToStr(state) << ")"; |
1372 | + if (state == mir_lifecycle_state_will_suspend) { |
1373 | + Q_EMIT willSuspend(); |
1374 | + } else if (state == mir_lifecycle_state_resumed) { |
1375 | + Q_EMIT resumed(); |
1376 | + } |
1377 | +} |
1378 | |
1379 | === added file 'src/modules/Unity/Application/fake/fakemirclient.h' |
1380 | --- src/modules/Unity/Application/fake/fakemirclient.h 1970-01-01 00:00:00 +0000 |
1381 | +++ src/modules/Unity/Application/fake/fakemirclient.h 2017-02-14 10:17:32 +0000 |
1382 | @@ -0,0 +1,177 @@ |
1383 | +/* |
1384 | + * Copyright (C) 2017 Canonical, Ltd. |
1385 | + * |
1386 | + * This program is free software: you can redistribute it and/or modify it under |
1387 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1388 | + * the Free Software Foundation. |
1389 | + * |
1390 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1391 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1392 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1393 | + * Lesser General Public License for more details. |
1394 | + * |
1395 | + * You should have received a copy of the GNU Lesser General Public License |
1396 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1397 | + * |
1398 | + */ |
1399 | + |
1400 | +#ifndef QTMIR_FAKE_MIR_CLIENT_H |
1401 | +#define QTMIR_FAKE_MIR_CLIENT_H |
1402 | + |
1403 | +#include <QObject> |
1404 | +#include <QSharedPointer> |
1405 | +#include <QThread> |
1406 | + |
1407 | +#include <miral/toolkit/connection.h> |
1408 | +#include <miral/toolkit/window.h> |
1409 | + |
1410 | +// Qt |
1411 | +#include <QImage> |
1412 | +#include <QMap> |
1413 | + |
1414 | +// mir |
1415 | +#include <mir/fd.h> |
1416 | +#include <mir/scene/session.h> |
1417 | +#include <mir/server.h> |
1418 | +#include <mir_toolkit/client_types.h> |
1419 | + |
1420 | +// std |
1421 | +#include <condition_variable> |
1422 | + |
1423 | +// local |
1424 | +#include "fakeapplicationinfo.h" |
1425 | +#include "windowattributes.h" |
1426 | + |
1427 | +namespace qtmir { |
1428 | + |
1429 | +// lives in a separate thread |
1430 | +class MirClient : public QObject |
1431 | +{ |
1432 | + Q_OBJECT |
1433 | + |
1434 | +public: |
1435 | + MirClient(QSharedPointer<FakeApplicationInfo> appInfo, miral::toolkit::Connection); |
1436 | + |
1437 | + void customEvent(QEvent* event) override; |
1438 | + |
1439 | +Q_SIGNALS: |
1440 | + void willSuspend(); |
1441 | + void resumed(); |
1442 | + |
1443 | + void windowCreated(QString persistentId, qtmir::WindowAttributes windowAttributes); |
1444 | + void windowAttributeChanged(QString persistentId, MirWindowAttrib attribute, int value); |
1445 | + void touchPressed(QString persistentId); |
1446 | + void touchReleased(QString persistentId); |
1447 | + void mousePressed(QString persistentId); |
1448 | + void mouseReleased(QString persistentId); |
1449 | + void windowClosed(QString persistentId); |
1450 | + |
1451 | +public Q_SLOTS: |
1452 | + void windowEvent(MirWindow* window, MirEvent const* event); |
1453 | + void createWindow(); |
1454 | + void killWindow(const QString &persistentId); |
1455 | + void setWindowInputBounds(const QString &persistentId, QRect rect); |
1456 | + void setWindowMinimumWidth(const QString &persistentId, int value); |
1457 | + void setWindowMaximumWidth(const QString &persistentId, int value); |
1458 | + void setWindowMinimumHeight(const QString &persistentId, int value); |
1459 | + void setWindowMaximumHeight(const QString &persistentId, int value); |
1460 | + void setWindowWidthIncrement(const QString &persistentId, int value); |
1461 | + void setWindowHeightIncrement(const QString &persistentId, int value); |
1462 | + |
1463 | + void lifecycleEvent(MirLifecycleState state); |
1464 | + |
1465 | +private: |
1466 | + virtual QSize update(MirWindow *window); |
1467 | + void closeWindow(MirWindow *window); |
1468 | + void resizeEvent(MirWindow *window, MirResizeEvent const*); |
1469 | + void attributeChangeEvent(MirWindow *window, MirWindowEvent const *event); |
1470 | + void inputEvent(MirWindow* window, const MirInputEvent *); |
1471 | + void touchEvent(MirWindow* window, const MirTouchEvent *); |
1472 | + void pointerEvent(MirWindow* window, const MirPointerEvent *); |
1473 | + MirWindow *findWindow(const QString &persistentId); |
1474 | + QString idForWindow(MirWindow*); |
1475 | + |
1476 | + int m_windowCounter{0}; |
1477 | + QMap<MirWindow*, QString> m_surfaceIds; // works around bug LP#1661704 |
1478 | + |
1479 | + bool m_primaryButtonPressed{false}; |
1480 | + |
1481 | +protected: |
1482 | + miral::toolkit::Connection m_connection; |
1483 | + QVector<miral::toolkit::Window> m_windows; |
1484 | + QImage m_screenshot; |
1485 | + QSharedPointer<FakeApplicationInfo> m_appInfo; |
1486 | +}; |
1487 | + |
1488 | +// lives in Qt's main/gui thread |
1489 | +class FakeMirClientLauncher : public QThread |
1490 | +{ |
1491 | + Q_OBJECT |
1492 | +public: |
1493 | + FakeMirClientLauncher(QSharedPointer<FakeApplicationInfo> appInfo, pid_t pid, QObject *parent = nullptr); |
1494 | + |
1495 | + void launch(); |
1496 | + |
1497 | + std::shared_ptr<mir::scene::Session> session(); |
1498 | + pid_t pid() const { return m_pid; } |
1499 | + QSharedPointer<FakeApplicationInfo> appInfo() const { return m_appInfo; } |
1500 | + |
1501 | + void createWindow(); |
1502 | + void killWindow(const QString &persistentId); |
1503 | + void createPromptWindow(); |
1504 | + void setWindowInputBounds(const QString &persistentId, QRect rect); |
1505 | + void setWindowMinimumWidth(const QString &persistentId, int value); |
1506 | + void setWindowMaximumWidth(const QString &persistentId, int value); |
1507 | + void setWindowMinimumHeight(const QString &persistentId, int value); |
1508 | + void setWindowMaximumHeight(const QString &persistentId, int value); |
1509 | + void setWindowWidthIncrement(const QString &persistentId, int value); |
1510 | + void setWindowHeightIncrement(const QString &persistentId, int value); |
1511 | + void setManualWindowCreation(bool value) { m_manualWindowCreation = value; } |
1512 | + |
1513 | + const WindowAttributes *windowAttributes(const QString &persistentId) const; |
1514 | + |
1515 | + void kill(); |
1516 | + bool killed() const { return m_killed; } |
1517 | + |
1518 | +Q_SIGNALS: |
1519 | + void willSuspend(); |
1520 | + void resumed(); |
1521 | + |
1522 | +protected: |
1523 | + void run() override; |
1524 | + |
1525 | +private Q_SLOTS: |
1526 | + void addWindowAttributes(QString persistendId, WindowAttributes windowAttributes); |
1527 | + void updateWindowAttribute(QString persistentId, MirWindowAttrib attribute, int value); |
1528 | + void incrementTouchPressCount(QString persistentId); |
1529 | + void incrementTouchReleaseCount(QString persistentId); |
1530 | + void incrementMousePressCount(QString persistentId); |
1531 | + void incrementMouseReleaseCount(QString persistentId); |
1532 | + void removeWindowAttributes(QString persistendId); |
1533 | + |
1534 | +private: |
1535 | + // called from the fake mir client thread |
1536 | + virtual MirClient *createClient(); |
1537 | + |
1538 | + // Called from mir server thread |
1539 | + void launchFromMirServerThread(); |
1540 | + |
1541 | + mir::Server *m_server{nullptr}; |
1542 | + std::weak_ptr<mir::scene::Session> m_session; |
1543 | + std::mutex mutable m_mutex; |
1544 | + mir::Fd m_fd; // gotta hold on to it otherwise connection will close |
1545 | + pid_t m_pid; |
1546 | + MirClient *m_client{nullptr}; |
1547 | + bool m_manualWindowCreation{false}; |
1548 | + bool m_killed{false}; |
1549 | + |
1550 | + // Key is persistent window id |
1551 | + QMap<QString, WindowAttributes> m_windowAttributes; |
1552 | +protected: |
1553 | + QSharedPointer<FakeApplicationInfo> m_appInfo; |
1554 | + miral::toolkit::Connection m_connection; |
1555 | +}; |
1556 | + |
1557 | +} // namespace qtmir |
1558 | + |
1559 | +#endif // QTMIR_FAKE_MIR_CLIENT_H |
1560 | |
1561 | === added file 'src/modules/Unity/Application/fake/fakeprompt.cpp' |
1562 | --- src/modules/Unity/Application/fake/fakeprompt.cpp 1970-01-01 00:00:00 +0000 |
1563 | +++ src/modules/Unity/Application/fake/fakeprompt.cpp 2017-02-14 10:17:32 +0000 |
1564 | @@ -0,0 +1,320 @@ |
1565 | +/* |
1566 | + * Copyright (C) 2017 Canonical, Ltd. |
1567 | + * |
1568 | + * This program is free software: you can redistribute it and/or modify it under |
1569 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1570 | + * the Free Software Foundation. |
1571 | + * |
1572 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1573 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1574 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1575 | + * Lesser General Public License for more details. |
1576 | + * |
1577 | + * You should have received a copy of the GNU Lesser General Public License |
1578 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1579 | + * |
1580 | + */ |
1581 | + |
1582 | +#include "fakeprompt.h" |
1583 | + |
1584 | +// Qt |
1585 | +#include <qpa/qplatformnativeinterface.h> |
1586 | +#include <QDebug> |
1587 | +#include <QGuiApplication> |
1588 | +#include <QPainter> |
1589 | + |
1590 | +// mir |
1591 | +#include <mir/main_loop.h> |
1592 | + |
1593 | +#include <unistd.h> // for getpid() |
1594 | + |
1595 | +// mir |
1596 | +#include <mir_toolkit/mir_buffer_stream.h> |
1597 | +#include <mir_toolkit/mir_prompt_session.h> |
1598 | + |
1599 | +// miral |
1600 | +#include <miral/toolkit/window_spec.h> |
1601 | + |
1602 | +using namespace qtmir; |
1603 | +using namespace miral::toolkit; |
1604 | + |
1605 | +namespace { |
1606 | + |
1607 | +class MirClientEvent : public QEvent |
1608 | +{ |
1609 | +public: |
1610 | + MirClientEvent(MirWindow* window, const MirEvent *event, QEvent::Type type) |
1611 | + : QEvent(type), window(window), mirEvent(event) { |
1612 | + mirEvent = mir_event_ref(event); |
1613 | + } |
1614 | + ~MirClientEvent() |
1615 | + { |
1616 | + mir_event_unref(mirEvent); |
1617 | + } |
1618 | + |
1619 | + MirWindow* window; |
1620 | + const MirEvent *mirEvent; |
1621 | +}; |
1622 | + |
1623 | +int mirClientEventType{0}; |
1624 | +void windowEventHandler(MirWindow* window, MirEvent const* event, void* context) |
1625 | +{ |
1626 | + if (mirClientEventType == 0) { |
1627 | + mirClientEventType = QEvent::registerEventType(); |
1628 | + } |
1629 | + auto client = static_cast<QObject*>(context); |
1630 | + QEvent *qtEvent = new MirClientEvent(window, event, static_cast<QEvent::Type>(mirClientEventType)); |
1631 | + QCoreApplication::postEvent(client, qtEvent); |
1632 | +} |
1633 | + |
1634 | +void mirPromptSessionStateChangeCallback(MirPromptSession* /*promptSession*/, MirPromptSessionState /*state*/, void* /*context*/) |
1635 | +{ |
1636 | +} |
1637 | + |
1638 | +void mirClientFdCallback(MirPromptSession* /*promptSession*/, size_t count, int const* fds, void* context) |
1639 | +{ |
1640 | + Q_UNUSED(count); // in case of release builds, as Q_ASSERT won't be compiled |
1641 | + Q_ASSERT(count == 1); |
1642 | + |
1643 | + auto fakePromptHelper = static_cast<FakePromptHelper*>(context); |
1644 | + QMetaObject::invokeMethod(fakePromptHelper->launcher(), "notifyPromptProviderFdReady", Qt::AutoConnection, Q_ARG(int, fds[0])); |
1645 | +} |
1646 | + |
1647 | +} // anonymous namespace |
1648 | + |
1649 | +/************************************************************************************************** |
1650 | + * FakePromptHelperLauncher |
1651 | + *************************************************************************************************/ |
1652 | + |
1653 | +FakePromptHelperLauncher::FakePromptHelperLauncher(pid_t pid, QObject *parent) |
1654 | + : QThread(parent) |
1655 | + , m_pid(pid) |
1656 | +{ |
1657 | + m_targetApplicationPid = getpid(); // shell's own pid, since we're only running in-process mir clients |
1658 | + m_sessionName = QString("prompt-helper-%1").arg((qintptr)this); |
1659 | + connect(this, &QThread::finished, this, [this]{ m_fd = mir::Fd(); deleteLater(); }); |
1660 | +} |
1661 | + |
1662 | +void FakePromptHelperLauncher::launch() |
1663 | +{ |
1664 | + auto nativeInterface = QGuiApplication::platformNativeInterface(); |
1665 | + m_server = static_cast<mir::Server*>(nativeInterface->nativeResourceForIntegration("MirServer")); |
1666 | + |
1667 | + m_server->the_main_loop()->enqueue(this, [this] { launchFromMirServerThread(); }); |
1668 | +} |
1669 | + |
1670 | +void FakePromptHelperLauncher::launchFromMirServerThread() |
1671 | +{ |
1672 | + m_fd = m_server->open_prompt_socket(); |
1673 | + |
1674 | + char connectString[64] = {0}; |
1675 | + sprintf(connectString, "fd://%d", m_fd.operator int()); |
1676 | + |
1677 | + m_connection = Connection{mir_connect_sync(connectString, m_sessionName.toLatin1().data())}; |
1678 | + |
1679 | + start(); |
1680 | +} |
1681 | + |
1682 | +void FakePromptHelperLauncher::run() |
1683 | +{ |
1684 | + FakePromptHelper *promptHelper; |
1685 | + { |
1686 | + std::lock_guard<std::mutex> lockGuard{m_mutex}; |
1687 | + |
1688 | + promptHelper = new FakePromptHelper(m_targetApplicationPid, m_connection, this); |
1689 | + |
1690 | + // keep only one reference, in MirClient |
1691 | + m_connection.reset(); |
1692 | + } |
1693 | + |
1694 | + exec(); |
1695 | + |
1696 | + { |
1697 | + std::lock_guard<std::mutex> lockGuard{m_mutex}; |
1698 | + |
1699 | + delete promptHelper; |
1700 | + promptHelper = nullptr; |
1701 | + } |
1702 | +} |
1703 | + |
1704 | +void FakePromptHelperLauncher::notifyPromptProviderFdReady(int fd) |
1705 | +{ |
1706 | + Q_EMIT promptProviderFdReady(fd); |
1707 | +} |
1708 | + |
1709 | +void FakePromptHelperLauncher::setProvider(FakePromptProviderLauncher *providerLauncher) |
1710 | +{ |
1711 | + Q_ASSERT(m_providerLauncher == nullptr); |
1712 | + |
1713 | + m_providerLauncher = providerLauncher; |
1714 | + |
1715 | + connect(m_providerLauncher, &QThread::finished, this, [this]() { |
1716 | + m_providerLauncher->deleteLater(); |
1717 | + m_providerLauncher = nullptr; |
1718 | + quit(); |
1719 | + }); |
1720 | +} |
1721 | + |
1722 | +/************************************************************************************************** |
1723 | + * FakePromptHelper |
1724 | + *************************************************************************************************/ |
1725 | + |
1726 | +FakePromptHelper::FakePromptHelper(pid_t targetApplicationPid, miral::toolkit::Connection connection, QObject *launcher) |
1727 | + : m_connection(connection) |
1728 | + , m_launcher(launcher) |
1729 | +{ |
1730 | + m_promptSession = mir_connection_create_prompt_session_sync(m_connection, targetApplicationPid, |
1731 | + &mirPromptSessionStateChangeCallback, this); |
1732 | + |
1733 | + mir_prompt_session_new_fds_for_prompt_providers(m_promptSession, 1 /* no_of_fds */, &mirClientFdCallback, this); |
1734 | +} |
1735 | + |
1736 | +FakePromptHelper::~FakePromptHelper() |
1737 | +{ |
1738 | + mir_prompt_session_release_sync(m_promptSession); |
1739 | +} |
1740 | + |
1741 | +/************************************************************************************************** |
1742 | + * FakePromptProviderLauncher |
1743 | + *************************************************************************************************/ |
1744 | + |
1745 | +FakePromptProviderLauncher::FakePromptProviderLauncher(pid_t pid, int fd, QObject *parent) |
1746 | + : QThread(parent) |
1747 | + , m_fd(fd) |
1748 | + , m_pid(pid) |
1749 | +{ |
1750 | + m_sessionName = QString("prompt-provider-%1").arg((qintptr)this); |
1751 | + connect(this, &QThread::finished, this, [this]{ m_fd = mir::Fd(); }); |
1752 | +} |
1753 | + |
1754 | +void FakePromptProviderLauncher::launch() |
1755 | +{ |
1756 | + start(); |
1757 | +} |
1758 | + |
1759 | +void FakePromptProviderLauncher::run() |
1760 | +{ |
1761 | + { |
1762 | + char connectString[64] = {0}; |
1763 | + sprintf(connectString, "fd://%d", m_fd.operator int()); |
1764 | + m_connection = Connection{mir_connect_sync(connectString, m_sessionName.toLatin1().data())}; |
1765 | + } |
1766 | + |
1767 | + { |
1768 | + std::lock_guard<std::mutex> lockGuard{m_mutex}; |
1769 | + |
1770 | + m_promptProvider = new FakePromptProvider(m_connection); |
1771 | + |
1772 | + // keep only one reference, in MirClient |
1773 | + m_connection.reset(); |
1774 | + } |
1775 | + |
1776 | + exec(); |
1777 | + |
1778 | + { |
1779 | + std::lock_guard<std::mutex> lockGuard{m_mutex}; |
1780 | + |
1781 | + delete m_promptProvider; |
1782 | + m_promptProvider = nullptr; |
1783 | + } |
1784 | +} |
1785 | + |
1786 | +/************************************************************************************************** |
1787 | + * FakePromptProvider |
1788 | + *************************************************************************************************/ |
1789 | + |
1790 | +FakePromptProvider::FakePromptProvider(miral::toolkit::Connection connection) |
1791 | + : m_connection(connection) |
1792 | +{ |
1793 | + createWindow(); |
1794 | + update(m_windows[0]); |
1795 | +} |
1796 | + |
1797 | +void FakePromptProvider::update(MirWindow* window) |
1798 | +{ |
1799 | + MirBufferStream* buffer_stream = mir_window_get_buffer_stream(window); |
1800 | + |
1801 | + // TODO sometimes buffer_stream is nullptr |
1802 | + // (Only observed when creating a lot of clients at once) |
1803 | + if (!buffer_stream) |
1804 | + return; |
1805 | + |
1806 | + MirGraphicsRegion region; |
1807 | + mir_buffer_stream_get_graphics_region(buffer_stream, ®ion); |
1808 | + |
1809 | + QImage windowImage((uchar*)region.vaddr, region.width, region.height, QImage::Format_RGB32); |
1810 | + { |
1811 | + QRect windowRect(0, 0, windowImage.width(), windowImage.height()); |
1812 | + |
1813 | + QPainter painter(&windowImage); |
1814 | + painter.setBrush(QBrush(QColor(183,25,118))); |
1815 | + painter.drawRect(windowRect); |
1816 | + |
1817 | + painter.setPen(QPen(QColor(0,0,0))); |
1818 | + painter.drawText(windowRect, Qt::AlignCenter, QString("Prompt\nWindow")); |
1819 | + } |
1820 | + |
1821 | + mir_buffer_stream_swap_buffers_sync(buffer_stream); |
1822 | +} |
1823 | + |
1824 | +void FakePromptProvider::windowEvent(MirWindow* window, MirEvent const* mirEvent) |
1825 | +{ |
1826 | + switch (mir_event_get_type(mirEvent)) |
1827 | + { |
1828 | + case mir_event_type_input: |
1829 | + break; |
1830 | + case mir_event_type_resize: |
1831 | + update(window); |
1832 | + break; |
1833 | + case mir_event_type_window: |
1834 | + break; |
1835 | + case mir_event_type_window_output: |
1836 | + break; |
1837 | + case mir_event_type_orientation: |
1838 | + break; |
1839 | + case mir_event_type_close_window: |
1840 | + closeWindow(window); |
1841 | + break; |
1842 | + default: |
1843 | + qDebug() << "FakePromptProvider::windowEvent unhandled event type: %d" << static_cast<int>(mir_event_get_type(mirEvent)); |
1844 | + } |
1845 | +} |
1846 | + |
1847 | +void FakePromptProvider::customEvent(QEvent* event) |
1848 | +{ |
1849 | + auto mirClientEvent = static_cast<MirClientEvent*>(event); |
1850 | + windowEvent(mirClientEvent->window, mirClientEvent->mirEvent); |
1851 | +} |
1852 | + |
1853 | +void FakePromptProvider::createWindow() |
1854 | +{ |
1855 | + ++m_windowCounter; |
1856 | + |
1857 | + QString name = QString("%1 %2") |
1858 | + .arg("prompt provider") |
1859 | + .arg(m_windowCounter); |
1860 | + |
1861 | + auto const spec = WindowSpec::for_normal_surface( |
1862 | + m_connection, 640, 480, mir_pixel_format_xrgb_8888) |
1863 | + .set_buffer_usage(mir_buffer_usage_software) |
1864 | + .set_type(mir_window_type_normal) |
1865 | + .set_name(name.toLatin1().data()) |
1866 | + .set_event_handler(&windowEventHandler, this /*context*/); |
1867 | + |
1868 | + m_windows.append(spec.create_surface()); |
1869 | +} |
1870 | + |
1871 | +void FakePromptProvider::closeWindow(MirWindow *mirWindow) |
1872 | +{ |
1873 | + bool found = false; |
1874 | + for (int i = 0; i < m_windows.count() && !found; ++i) { |
1875 | + if (m_windows[i] == mirWindow) { |
1876 | + found = true; |
1877 | + m_windows.remove(i); |
1878 | + } |
1879 | + } |
1880 | + |
1881 | + if (m_windows.isEmpty()) { |
1882 | + QThread::currentThread()->quit(); |
1883 | + } |
1884 | +} |
1885 | |
1886 | === added file 'src/modules/Unity/Application/fake/fakeprompt.h' |
1887 | --- src/modules/Unity/Application/fake/fakeprompt.h 1970-01-01 00:00:00 +0000 |
1888 | +++ src/modules/Unity/Application/fake/fakeprompt.h 2017-02-14 10:17:32 +0000 |
1889 | @@ -0,0 +1,155 @@ |
1890 | +/* |
1891 | + * Copyright (C) 2017 Canonical, Ltd. |
1892 | + * |
1893 | + * This program is free software: you can redistribute it and/or modify it under |
1894 | + * the terms of the GNU Lesser General Public License version 3, as published by |
1895 | + * the Free Software Foundation. |
1896 | + * |
1897 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
1898 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
1899 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1900 | + * Lesser General Public License for more details. |
1901 | + * |
1902 | + * You should have received a copy of the GNU Lesser General Public License |
1903 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
1904 | + * |
1905 | + */ |
1906 | + |
1907 | +#ifndef QTMIR_FAKE_PROMPT_H |
1908 | +#define QTMIR_FAKE_PROMPT_H |
1909 | + |
1910 | +#include <QObject> |
1911 | +#include <QSharedPointer> |
1912 | +#include <QThread> |
1913 | + |
1914 | +#include <miral/toolkit/connection.h> |
1915 | +#include <miral/toolkit/window.h> |
1916 | + |
1917 | +// Qt |
1918 | +#include <QImage> |
1919 | + |
1920 | +// mir |
1921 | +#include <mir/fd.h> |
1922 | +#include <mir/scene/session.h> |
1923 | +#include <mir/server.h> |
1924 | +#include <mir_toolkit/client_types.h> |
1925 | + |
1926 | +// std |
1927 | +#include <condition_variable> |
1928 | + |
1929 | +// local |
1930 | +#include "fakeapplicationinfo.h" |
1931 | + |
1932 | +namespace qtmir { |
1933 | + |
1934 | +// lives in a separate thread |
1935 | +class FakePromptProvider : public QObject |
1936 | +{ |
1937 | + Q_OBJECT |
1938 | + |
1939 | +public: |
1940 | + FakePromptProvider(miral::toolkit::Connection); |
1941 | + |
1942 | + void customEvent(QEvent* event) override; |
1943 | + |
1944 | +public Q_SLOTS: |
1945 | + void windowEvent(MirWindow* window, MirEvent const* event); |
1946 | + void createWindow(); |
1947 | + |
1948 | +private Q_SLOTS: |
1949 | + void update(MirWindow *window); |
1950 | + |
1951 | +private: |
1952 | + void closeWindow(MirWindow *window); |
1953 | + |
1954 | + miral::toolkit::Connection m_connection; |
1955 | + QVector<miral::toolkit::Window> m_windows; |
1956 | + |
1957 | + int m_windowCounter{0}; |
1958 | +}; |
1959 | + |
1960 | +class FakePromptProviderLauncher : public QThread |
1961 | +{ |
1962 | + Q_OBJECT |
1963 | + |
1964 | +public: |
1965 | + FakePromptProviderLauncher(pid_t pid, int fd, QObject *parent = nullptr); |
1966 | + |
1967 | + pid_t pid() const { return m_pid; } |
1968 | + QString sessionName() const { return m_sessionName; } |
1969 | + void launch(); |
1970 | + |
1971 | +protected: |
1972 | + void run() override; |
1973 | + |
1974 | +private: |
1975 | + std::mutex mutable m_mutex; |
1976 | + miral::toolkit::Connection m_connection; |
1977 | + mir::Fd m_fd; // gotta hold on to it otherwise connection will close |
1978 | + pid_t m_pid; |
1979 | + |
1980 | + FakePromptProvider *m_promptProvider{nullptr}; |
1981 | + QString m_sessionName; |
1982 | +}; |
1983 | + |
1984 | +// lives in a separate thread |
1985 | +class FakePromptHelper : public QObject |
1986 | +{ |
1987 | + Q_OBJECT |
1988 | + |
1989 | +public: |
1990 | + FakePromptHelper(pid_t targetApplicationPid, miral::toolkit::Connection, QObject *launcher); |
1991 | + virtual ~FakePromptHelper(); |
1992 | + |
1993 | + QObject *launcher() const { return m_launcher; } |
1994 | + |
1995 | +private: |
1996 | + miral::toolkit::Connection m_connection; |
1997 | + MirPromptSession *m_promptSession{nullptr}; |
1998 | + QObject *m_launcher; |
1999 | +}; |
2000 | + |
2001 | +// lives in Qt's main/gui thread |
2002 | +class FakePromptHelperLauncher : public QThread |
2003 | +{ |
2004 | + Q_OBJECT |
2005 | +public: |
2006 | + FakePromptHelperLauncher(pid_t pid, QObject *parent = nullptr); |
2007 | + |
2008 | + void launch(); |
2009 | + |
2010 | + pid_t pid() const { return m_pid; } |
2011 | + |
2012 | + QString sessionName() const { return m_sessionName; } |
2013 | + |
2014 | + void setProvider(FakePromptProviderLauncher *providerLauncher); |
2015 | + FakePromptProviderLauncher *provider() const { return m_providerLauncher; } |
2016 | + |
2017 | +public Q_SLOTS: |
2018 | + void notifyPromptProviderFdReady(int fd); |
2019 | + |
2020 | +Q_SIGNALS: |
2021 | + void promptProviderFdReady(int fd); |
2022 | + |
2023 | +protected: |
2024 | + void run() override; |
2025 | + |
2026 | +private: |
2027 | + // Called from mir server thread |
2028 | + void launchFromMirServerThread(); |
2029 | + |
2030 | + mir::Server *m_server{nullptr}; |
2031 | + std::mutex mutable m_mutex; |
2032 | + miral::toolkit::Connection m_connection; |
2033 | + mir::Fd m_fd; // gotta hold on to it otherwise connection will close |
2034 | + pid_t m_pid; |
2035 | + QString m_sessionName; |
2036 | + |
2037 | + FakePromptProviderLauncher *m_providerLauncher{nullptr}; |
2038 | + |
2039 | + pid_t m_targetApplicationPid; |
2040 | +}; |
2041 | + |
2042 | +} // namespace qtmir |
2043 | + |
2044 | +#endif // QTMIR_FAKE_PROMPT_H |
2045 | |
2046 | === added file 'src/modules/Unity/Application/fake/faketaskcontroller.cpp' |
2047 | --- src/modules/Unity/Application/fake/faketaskcontroller.cpp 1970-01-01 00:00:00 +0000 |
2048 | +++ src/modules/Unity/Application/fake/faketaskcontroller.cpp 2017-02-14 10:17:32 +0000 |
2049 | @@ -0,0 +1,683 @@ |
2050 | +/* |
2051 | + * Copyright (C) 2017 Canonical, Ltd. |
2052 | + * |
2053 | + * This program is free software: you can redistribute it and/or modify it under |
2054 | + * the terms of the GNU Lesser General Public License version 3, as published by |
2055 | + * the Free Software Foundation. |
2056 | + * |
2057 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
2058 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
2059 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2060 | + * Lesser General Public License for more details. |
2061 | + * |
2062 | + * You should have received a copy of the GNU Lesser General Public License |
2063 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2064 | + * |
2065 | + */ |
2066 | + |
2067 | +// local |
2068 | +#include "faketaskcontroller.h" |
2069 | +#include "fakemaliit.h" |
2070 | +#include "fakemirclient.h" |
2071 | +#include "fakeprompt.h" |
2072 | +#include "session.h" |
2073 | +#include "mirsurface.h" |
2074 | +#include "windowattributes.h" |
2075 | + |
2076 | +// mirserver |
2077 | +#include <sessionauthorizer.h> |
2078 | + |
2079 | +// qt |
2080 | +#include <QGuiApplication> |
2081 | +#include <QTimer> |
2082 | +#include <qpa/qplatformnativeinterface.h> |
2083 | + |
2084 | +// QPA mirserver |
2085 | +#include <logging.h> |
2086 | +#include <promptsession.h> |
2087 | + |
2088 | +#include <QDebug> |
2089 | +#include <QMutexLocker> |
2090 | + |
2091 | +#define DEBUG_MSG qCDebug(QTMIR_SESSIONS).nospace() << "FakeTaskController::" << __func__ |
2092 | +#define WARNING_MSG qCWarning(QTMIR_SESSIONS).nospace() << "FakeTaskController::" << __func__ |
2093 | + |
2094 | +using namespace qtmir; |
2095 | +namespace unityapi = unity::shell::application; |
2096 | + |
2097 | + |
2098 | +FakeTaskController *FakeTaskController::m_instance = nullptr; |
2099 | + |
2100 | +FakeTaskController::FakeTaskController() |
2101 | + : TaskController() |
2102 | + , m_maliitAppInfo(new FakeApplicationInfo("maliit-server")) |
2103 | + , m_procInfo(new FakeProcInfo) |
2104 | +{ |
2105 | + Q_ASSERT(m_instance == nullptr); |
2106 | + m_instance = this; |
2107 | + |
2108 | + createAvailableApplications(); |
2109 | + |
2110 | + m_maliitAppInfo->setName("Maliit IM Server"); |
2111 | + m_maliitAppInfo->setScreenshotId("vkb_portrait.png"); |
2112 | + m_maliitAppInfo->setWindowType(mir_window_type_inputmethod); |
2113 | + m_maliitAppInfo->setInitialWindowState(mir_window_state_hidden); |
2114 | + |
2115 | + m_procInfo->taskController = this; |
2116 | + |
2117 | + qRegisterMetaType<qtmir::WindowAttributes>(); |
2118 | +} |
2119 | + |
2120 | +FakeTaskController::~FakeTaskController() |
2121 | +{ |
2122 | + Q_ASSERT(m_instance != nullptr); |
2123 | + m_instance = nullptr; |
2124 | +} |
2125 | + |
2126 | +void FakeTaskController::createAvailableApplications() |
2127 | +{ |
2128 | + FakeApplicationInfo *application; |
2129 | + |
2130 | + application = new FakeApplicationInfo("unity8-dash"); |
2131 | + application->setName("Unity 8 Mock Dash"); |
2132 | + application->setScreenshotId("unity8-dash"); |
2133 | + application->setIconId("dash"); |
2134 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2135 | + |
2136 | + application = new FakeApplicationInfo("dialer-app"); |
2137 | + application->setName("Dialer"); |
2138 | + application->setScreenshotId("dialer"); |
2139 | + application->setIconId("dialer-app"); |
2140 | + application->setSupportedOrientations(Qt::PortraitOrientation |
2141 | + | Qt::InvertedPortraitOrientation); |
2142 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2143 | + |
2144 | + application = new FakeApplicationInfo("camera-app"); |
2145 | + application->setName("Camera"); |
2146 | + application->setScreenshotId("camera"); |
2147 | + application->setIconId("camera"); |
2148 | + application->setInitialWindowState(mir_window_state_fullscreen); |
2149 | + application->setSupportedOrientations(Qt::PortraitOrientation |
2150 | + | Qt::LandscapeOrientation |
2151 | + | Qt::InvertedPortraitOrientation |
2152 | + | Qt::InvertedLandscapeOrientation); |
2153 | + application->setRotatesWindowContents(true); |
2154 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2155 | + |
2156 | + application = new FakeApplicationInfo("camera-app2"); |
2157 | + application->setName("Camera2"); |
2158 | + application->setScreenshotId("camera"); |
2159 | + application->setIconId("camera"); |
2160 | + application->setSupportedOrientations(Qt::PortraitOrientation |
2161 | + | Qt::LandscapeOrientation |
2162 | + | Qt::InvertedPortraitOrientation |
2163 | + | Qt::InvertedLandscapeOrientation); |
2164 | + application->setRotatesWindowContents(true); |
2165 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2166 | + |
2167 | + application = new FakeApplicationInfo("gallery-app"); |
2168 | + application->setName("Gallery"); |
2169 | + application->setScreenshotId("gallery"); |
2170 | + application->setIconId("gallery"); |
2171 | + //application->setShellChrome(Mir::LowChrome); |
2172 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2173 | + |
2174 | + application = new FakeApplicationInfo("facebook-webapp"); |
2175 | + application->setName("Facebook"); |
2176 | + application->setScreenshotId("facebook"); |
2177 | + application->setIconId("facebook"); |
2178 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2179 | + |
2180 | + application = new FakeApplicationInfo("webbrowser-app"); |
2181 | + //application->setShellChrome(Mir::LowChrome); |
2182 | + application->setName("Browser"); |
2183 | + application->setScreenshotId("browser"); |
2184 | + application->setIconId("browser"); |
2185 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2186 | + |
2187 | + application = new FakeApplicationInfo("twitter-webapp"); |
2188 | + application->setName("Twitter"); |
2189 | + application->setScreenshotId("twitter"); |
2190 | + application->setIconId("twitter"); |
2191 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2192 | + |
2193 | + application = new FakeApplicationInfo("map"); |
2194 | + application->setName("Map"); |
2195 | + application->setIconId("map"); |
2196 | + application->setScreenshotId("map"); |
2197 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2198 | + |
2199 | + application = new FakeApplicationInfo("gmail-webapp"); |
2200 | + application->setName("GMail"); |
2201 | + application->setIconId("gmail"); |
2202 | + application->setScreenshotId("gmail-webapp.svg"); |
2203 | + application->setSupportedOrientations(Qt::PortraitOrientation |
2204 | + | Qt::LandscapeOrientation |
2205 | + | Qt::InvertedPortraitOrientation |
2206 | + | Qt::InvertedLandscapeOrientation); |
2207 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2208 | + |
2209 | + application = new FakeApplicationInfo("music-app"); |
2210 | + application->setName("Music"); |
2211 | + application->setIconId("soundcloud"); |
2212 | + application->setScreenshotId("music"); |
2213 | + application->setSupportedOrientations(Qt::PortraitOrientation |
2214 | + | Qt::LandscapeOrientation |
2215 | + | Qt::InvertedPortraitOrientation |
2216 | + | Qt::InvertedLandscapeOrientation); |
2217 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2218 | + |
2219 | + application = new FakeApplicationInfo("ubuntu-weather-app"); |
2220 | + application->setName("Weather"); |
2221 | + application->setIconId("weather"); |
2222 | + application->setScreenshotId("ubuntu-weather-app.svg"); |
2223 | + application->setSupportedOrientations(Qt::LandscapeOrientation |
2224 | + | Qt::InvertedLandscapeOrientation); |
2225 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2226 | + |
2227 | + application = new FakeApplicationInfo("notes-app"); |
2228 | + application->setName("Notepad"); |
2229 | + application->setIconId("notepad"); |
2230 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2231 | + |
2232 | + application = new FakeApplicationInfo("calendar-app"); |
2233 | + application->setName("Calendar"); |
2234 | + application->setIconId("calendar"); |
2235 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2236 | + |
2237 | + application = new FakeApplicationInfo("evernote"); |
2238 | + application->setName("Evernote"); |
2239 | + application->setIconId("evernote"); |
2240 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2241 | + |
2242 | + application = new FakeApplicationInfo("pinterest"); |
2243 | + application->setName("Pinterest"); |
2244 | + application->setIconId("pinterest"); |
2245 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2246 | + |
2247 | + application = new FakeApplicationInfo("soundcloud"); |
2248 | + application->setName("SoundCloud"); |
2249 | + application->setIconId("soundcloud"); |
2250 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2251 | + |
2252 | + application = new FakeApplicationInfo("wikipedia"); |
2253 | + application->setName("Wikipedia"); |
2254 | + application->setIconId("wikipedia"); |
2255 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2256 | + |
2257 | + application = new FakeApplicationInfo("youtube"); |
2258 | + application->setName("YouTube"); |
2259 | + application->setIconId("youtube"); |
2260 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2261 | + |
2262 | + application = new FakeApplicationInfo("libreoffice"); |
2263 | + application->setName("LibreOffice"); |
2264 | + application->setIconId("libreoffice"); |
2265 | + application->setScreenshotId("libreoffice"); |
2266 | + application->setIsTouchApp(false); |
2267 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2268 | + |
2269 | + application = new FakeApplicationInfo("primary-oriented-app"); |
2270 | + application->setName("Primary Oriented"); |
2271 | + application->setSupportedOrientations(Qt::PrimaryOrientation); |
2272 | + m_availableApplications.append(QSharedPointer<FakeApplicationInfo>(application)); |
2273 | +} |
2274 | + |
2275 | +bool FakeTaskController::appIdHasProcessId(const QString& appId, pid_t pid) |
2276 | +{ |
2277 | + if (m_runningClients.contains(appId)) { |
2278 | + return m_runningClients[appId]->pid() == pid; |
2279 | + } else { |
2280 | + return false; |
2281 | + } |
2282 | +} |
2283 | + |
2284 | +bool FakeTaskController::stop(const QString& appId) |
2285 | +{ |
2286 | + QMutexLocker locker(&m_mutex); |
2287 | + |
2288 | + DEBUG_MSG << "(" << appId << ")"; |
2289 | + |
2290 | + if (m_runningClients.contains(appId)) { |
2291 | + m_runningClients[appId]->quit(); |
2292 | + return true; |
2293 | + } else { |
2294 | + return false; |
2295 | + } |
2296 | +} |
2297 | + |
2298 | +bool FakeTaskController::start(const QString& appId, const QStringList& arguments) |
2299 | +{ |
2300 | + Q_UNUSED(arguments); |
2301 | + QMutexLocker locker(&m_mutex); |
2302 | + |
2303 | + auto appInfo = qSharedPointerCast<FakeApplicationInfo>(getInfoForApp(appId)); |
2304 | + if (!appInfo) { |
2305 | + return false; |
2306 | + } |
2307 | + |
2308 | + auto *fakeMirClientLauncher = new FakeMirClientLauncher(appInfo, generatePid()); |
2309 | + m_runningClients[appId] = fakeMirClientLauncher; |
2310 | + |
2311 | + fakeMirClientLauncher->setManualWindowCreation(m_manualSurfaceCreation); |
2312 | + |
2313 | + connect(fakeMirClientLauncher, &QThread::finished, this, [this, fakeMirClientLauncher]() { |
2314 | + QString appId = fakeMirClientLauncher->appInfo()->appId(); |
2315 | + Q_ASSERT(m_runningClients.contains(appId)); |
2316 | + m_runningClients.remove(appId); |
2317 | + if (fakeMirClientLauncher->killed()) { |
2318 | + Q_EMIT processFailed(appId, Error::APPLICATION_CRASHED); |
2319 | + } |
2320 | + Q_EMIT processStopped(appId); |
2321 | + delete fakeMirClientLauncher; |
2322 | + }); |
2323 | + |
2324 | + m_appIdLatestLaunch = appId; |
2325 | + fakeMirClientLauncher->launch(); |
2326 | + |
2327 | + // Do it separately, on the next event loop iteration, with a clean call stack. |
2328 | + QMetaObject::invokeMethod(this, "processStarting", Qt::QueuedConnection, Q_ARG(QString, appId)); |
2329 | + |
2330 | + return true; |
2331 | +} |
2332 | + |
2333 | +bool FakeTaskController::suspend(const QString& appId) |
2334 | +{ |
2335 | + QTimer::singleShot(300, [this, appId] { Q_EMIT processSuspended(appId); }); |
2336 | + return true; |
2337 | +} |
2338 | + |
2339 | +bool FakeTaskController::resume(const QString& appId) |
2340 | +{ |
2341 | + Q_UNUSED(appId); |
2342 | + return true; |
2343 | +} |
2344 | + |
2345 | +QSharedPointer<ApplicationInfo> FakeTaskController::getInfoForApp(const QString &appId) const |
2346 | +{ |
2347 | + for (int i = 0; i < m_availableApplications.count(); ++i) { |
2348 | + auto appInfo = m_availableApplications[i]; |
2349 | + if (appInfo->appId() == appId) { |
2350 | + return appInfo; |
2351 | + } |
2352 | + } |
2353 | + |
2354 | + return QSharedPointer<ApplicationInfo>(); |
2355 | +} |
2356 | + |
2357 | +QStringList FakeTaskController::availableApplications() |
2358 | +{ |
2359 | + QStringList result; |
2360 | + for (int i = 0; i < m_availableApplications.count(); ++i) { |
2361 | + result << m_availableApplications[i]->appId(); |
2362 | + } |
2363 | + return result; |
2364 | +} |
2365 | + |
2366 | +pid_t FakeTaskController::pidOf_impl(const miral::Application &application) |
2367 | +{ |
2368 | + QMutexLocker locker(&m_mutex); |
2369 | + |
2370 | + const std::shared_ptr<mir::scene::Session> &session = application; |
2371 | + |
2372 | + { |
2373 | + auto clientList = m_runningClients.values(); |
2374 | + for (int i = 0; i < clientList.count(); ++i) { |
2375 | + auto *client = clientList[i]; |
2376 | + if (client->session() == session) { |
2377 | + return client->pid(); |
2378 | + } |
2379 | + } |
2380 | + } |
2381 | + { |
2382 | + auto promptList = m_runningPromptHelpers.values(); |
2383 | + for (int i = 0; i < promptList.count(); ++i) { |
2384 | + auto *promptHelper = promptList[i]; |
2385 | + if (promptHelper->sessionName() == session->name().c_str()) { |
2386 | + return promptHelper->pid(); |
2387 | + } |
2388 | + auto *provider = promptHelper->provider(); |
2389 | + if (provider && provider->sessionName() == session->name().c_str()) { |
2390 | + return provider->pid(); |
2391 | + } |
2392 | + } |
2393 | + } |
2394 | + |
2395 | + if (m_maliitLauncher && m_maliitLauncher->session() == session) { |
2396 | + return m_maliitLauncher->pid(); |
2397 | + } |
2398 | + |
2399 | + qFatal("FakeTaskController::pidOf_impl() - Did not find the requested session!"); |
2400 | +} |
2401 | + |
2402 | +pid_t FakeTaskController::generatePid() |
2403 | +{ |
2404 | + pid_t pid = m_nextPid; |
2405 | + m_nextPid = nextFreePid(nextPid(pid), pid); |
2406 | + return pid; |
2407 | +} |
2408 | + |
2409 | +pid_t FakeTaskController::nextPid(pid_t pid) const |
2410 | +{ |
2411 | + if (pid == m_maxPid) { |
2412 | + return 1; |
2413 | + } else { |
2414 | + return pid + 1; |
2415 | + } |
2416 | +} |
2417 | + |
2418 | +pid_t FakeTaskController::nextFreePid(pid_t candidatePid, const pid_t latestPid) |
2419 | +{ |
2420 | + pid_t firstCandidatePid = candidatePid; |
2421 | + |
2422 | + while (isPidInUse(candidatePid) || candidatePid == latestPid) { |
2423 | + candidatePid = nextPid(candidatePid); |
2424 | + |
2425 | + if (candidatePid == firstCandidatePid) { |
2426 | + qFatal("TopLevelWindowModel: run out of pids."); |
2427 | + } |
2428 | + } |
2429 | + |
2430 | + return candidatePid; |
2431 | +} |
2432 | + |
2433 | +bool FakeTaskController::isPidInUse(pid_t pid) const |
2434 | +{ |
2435 | + { |
2436 | + auto clientList = m_runningClients.values(); |
2437 | + for (int i = 0; i < clientList.count(); ++i) { |
2438 | + auto *client = clientList[i]; |
2439 | + if (client->pid() == pid) { |
2440 | + return true; |
2441 | + } |
2442 | + } |
2443 | + } |
2444 | + { |
2445 | + auto promptList = m_runningPromptHelpers.values(); |
2446 | + for (int i = 0; i < promptList.count(); ++i) { |
2447 | + auto *prompt = promptList[i]; |
2448 | + if (prompt->pid() == pid) { |
2449 | + return true; |
2450 | + } |
2451 | + } |
2452 | + } |
2453 | + return false; |
2454 | +} |
2455 | + |
2456 | +void FakeTaskController::onAuthorizationForSessionRequested(const pid_t &, bool &authorized) |
2457 | +{ |
2458 | + // replace shell's own pid (because you know, we're running only internal clients) with a fake one |
2459 | + // from the session we most recently started (some assumptions going on, but should hold during tests). |
2460 | + |
2461 | + if (m_runningClients.contains(m_appIdLatestLaunch)) { |
2462 | + Q_EMIT authorizationRequestedForSession(m_runningClients[m_appIdLatestLaunch]->pid(), authorized); |
2463 | + } else { |
2464 | + Q_ASSERT(m_maliitLauncher && m_maliitAppInfo->appId() == m_appIdLatestLaunch); |
2465 | + Q_EMIT authorizationRequestedForSession(m_maliitLauncher->pid(), authorized); |
2466 | + } |
2467 | +} |
2468 | + |
2469 | +void FakeTaskController::createSurface(const QString &appId) |
2470 | +{ |
2471 | + QMutexLocker locker(&m_mutex); |
2472 | + |
2473 | + DEBUG_MSG << "(" << appId << ")"; |
2474 | + if (m_runningClients.contains(appId)) { |
2475 | + m_runningClients[appId]->createWindow(); |
2476 | + } else { |
2477 | + qFatal("FakeTaskController::createSurface(%s) - no running client.", qPrintable(appId)); |
2478 | + } |
2479 | +} |
2480 | + |
2481 | +void FakeTaskController::killSurface(const QString & appId, unityapi::MirSurfaceInterface* surface) |
2482 | +{ |
2483 | + QMutexLocker locker(&m_mutex); |
2484 | + DEBUG_MSG << "("<< appId <<","<< surface <<")"; |
2485 | + |
2486 | + if (m_runningClients.contains(appId)) { |
2487 | + m_runningClients[appId]->killWindow(surface->persistentId()); |
2488 | + } |
2489 | +} |
2490 | + |
2491 | +void FakeTaskController::createPromptSurface(const QString &appId) |
2492 | +{ |
2493 | + QMutexLocker locker(&m_mutex); |
2494 | + |
2495 | + if (!m_runningClients.contains(appId)) { |
2496 | + return; |
2497 | + } |
2498 | + |
2499 | + m_appIdLatestPromptSurface = appId; |
2500 | + if (m_runningPromptHelpers.contains(appId)) { |
2501 | + // TODO |
2502 | + } else { |
2503 | + auto *promptHelperLauncher = new FakePromptHelperLauncher(generatePid(), this); |
2504 | + |
2505 | + connect(promptHelperLauncher, &FakePromptHelperLauncher::promptProviderFdReady, this, |
2506 | + [this, promptHelperLauncher, appId](int fd) { |
2507 | + launchPromptProvider(promptHelperLauncher, fd); |
2508 | + }); |
2509 | + |
2510 | + connect(promptHelperLauncher, &QThread::finished, this, |
2511 | + [this, promptHelperLauncher, appId]() { |
2512 | + m_runningPromptHelpers.remove(appId); |
2513 | + promptHelperLauncher->deleteLater(); |
2514 | + }); |
2515 | + |
2516 | + m_runningPromptHelpers[appId] = promptHelperLauncher; |
2517 | + promptHelperLauncher->launch(); |
2518 | + } |
2519 | +} |
2520 | + |
2521 | +void FakeTaskController::onPromptSessionStarting(const qtmir::PromptSession &promptSession) |
2522 | +{ |
2523 | + DEBUG_MSG << " - promptSession=" << promptSession.get(); |
2524 | + |
2525 | + Q_ASSERT(!m_appIdLatestPromptSurface.isEmpty()); |
2526 | + Q_ASSERT(m_runningClients.contains(m_appIdLatestPromptSurface)); |
2527 | + |
2528 | + std::shared_ptr<mir::scene::Session> appSession = m_runningClients[m_appIdLatestPromptSurface]->session(); |
2529 | + SessionInterface *qmlAppSession = findSession(appSession.get()); |
2530 | + if (qmlAppSession) { |
2531 | + m_mirPromptToSessionHash[promptSession.get()] = qmlAppSession; |
2532 | + qmlAppSession->appendPromptSession(promptSession); |
2533 | + } else { |
2534 | + DEBUG_MSG << " - could not find app session for prompt session"; |
2535 | + } |
2536 | +} |
2537 | + |
2538 | +void FakeTaskController::launchPromptProvider(FakePromptHelperLauncher *promptHelperLauncher, int fd) |
2539 | +{ |
2540 | + auto *providerLauncher = new FakePromptProviderLauncher(generatePid(), fd); |
2541 | + promptHelperLauncher->setProvider(providerLauncher); |
2542 | + providerLauncher->launch(); |
2543 | +} |
2544 | + |
2545 | +void FakeTaskController::createInputMethodSurface() |
2546 | +{ |
2547 | + QMutexLocker locker(&m_mutex); |
2548 | + |
2549 | + if (m_maliitLauncher) { |
2550 | + // already created |
2551 | + return; |
2552 | + } |
2553 | + |
2554 | + m_maliitLauncher.reset(new FakeMaliitLauncher(m_maliitAppInfo, generatePid())); |
2555 | + |
2556 | + connect(m_maliitLauncher.data(), &QThread::finished, this, [this]() { |
2557 | + delete m_maliitLauncher.take(); |
2558 | + }); |
2559 | + |
2560 | + m_appIdLatestLaunch = m_maliitAppInfo->appId(); |
2561 | + m_maliitLauncher->launch(); |
2562 | +} |
2563 | + |
2564 | +void FakeTaskController::stopInputMethod() |
2565 | +{ |
2566 | + QMutexLocker locker(&m_mutex); |
2567 | + |
2568 | + if (m_maliitLauncher) { |
2569 | + m_maliitLauncher->quit(); |
2570 | + } |
2571 | +} |
2572 | + |
2573 | +bool FakeTaskController::isInputMethodRunning() |
2574 | +{ |
2575 | + return !m_maliitLauncher.isNull(); |
2576 | +} |
2577 | + |
2578 | +QSharedPointer<ProcInfo> FakeTaskController::procInfo() |
2579 | +{ |
2580 | + return m_procInfo; |
2581 | +} |
2582 | + |
2583 | +std::unique_ptr<ProcInfo::CommandLine> FakeTaskController::commandLine(pid_t pid) |
2584 | +{ |
2585 | + if (m_maliitLauncher && m_maliitLauncher->pid() == pid) { |
2586 | + return std::unique_ptr<ProcInfo::CommandLine>(new ProcInfo::CommandLine{"maliit-server"}); |
2587 | + } else { |
2588 | + return std::unique_ptr<ProcInfo::CommandLine>(new ProcInfo::CommandLine{"foo"}); |
2589 | + } |
2590 | +} |
2591 | + |
2592 | +void FakeTaskController::setSurfaceInputBounds(unityapi::MirSurfaceInterface *surfaceInterface, QRect rect) |
2593 | +{ |
2594 | + auto surface = static_cast<MirSurface*>(surfaceInterface); |
2595 | + |
2596 | + DEBUG_MSG << "(" << surface << ", " << rect << ")"; |
2597 | + |
2598 | + pid_t pid = pidOf_impl(surface->session()->session()); |
2599 | + FakeMirClientLauncher *clientLauncher = findClientWithPid(pid); |
2600 | + clientLauncher->setWindowInputBounds(surface->persistentId(), rect); |
2601 | +} |
2602 | + |
2603 | +FakeMirClientLauncher *FakeTaskController::findClientWithPid(pid_t pid) |
2604 | +{ |
2605 | + QList<FakeMirClientLauncher*> clientList = m_runningClients.values(); |
2606 | + for (int i = 0; i < clientList.size(); ++i) { |
2607 | + auto client = clientList[i]; |
2608 | + if (client->pid() == pid) { |
2609 | + return client; |
2610 | + } |
2611 | + } |
2612 | + |
2613 | + if (m_maliitLauncher && m_maliitLauncher->pid() == pid) { |
2614 | + return m_maliitLauncher.data(); |
2615 | + } |
2616 | + |
2617 | + return nullptr; |
2618 | +} |
2619 | + |
2620 | +void FakeTaskController::setManualSurfaceCreation(bool value) |
2621 | +{ |
2622 | + if (value != m_manualSurfaceCreation) { |
2623 | + m_manualSurfaceCreation = value; |
2624 | + Q_EMIT manualSurfaceCreationChanged(); |
2625 | + } |
2626 | +} |
2627 | + |
2628 | +void FakeTaskController::killApplication(const QString &appId) |
2629 | +{ |
2630 | + QMutexLocker locker(&m_mutex); |
2631 | + |
2632 | + DEBUG_MSG << "(" << appId << ")"; |
2633 | + |
2634 | + if (m_runningClients.contains(appId)) { |
2635 | + m_runningClients[appId]->kill(); |
2636 | + } |
2637 | +} |
2638 | + |
2639 | +bool FakeTaskController::isRunning(const QString &appId) |
2640 | +{ |
2641 | + return m_runningClients.contains(appId); |
2642 | +} |
2643 | + |
2644 | +void FakeTaskController::killPrompts() |
2645 | +{ |
2646 | + auto promptList = m_runningPromptHelpers.values(); |
2647 | + for (int i = 0; i < promptList.count(); ++i) { |
2648 | + auto *prompt = promptList[i]; |
2649 | + if (prompt->provider()) { |
2650 | + prompt->provider()->quit(); |
2651 | + } |
2652 | + } |
2653 | +} |
2654 | + |
2655 | +bool FakeTaskController::promptsRunning() |
2656 | +{ |
2657 | + return !m_runningPromptHelpers.isEmpty(); |
2658 | +} |
2659 | + |
2660 | +void FakeTaskController::setSurfaceMinimumWidth(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
2661 | +{ |
2662 | + if (m_runningClients.contains(appId)) { |
2663 | + m_runningClients[appId]->setWindowMinimumWidth(surface->persistentId(), value); |
2664 | + } |
2665 | +} |
2666 | + |
2667 | +void FakeTaskController::setSurfaceMaximumWidth(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
2668 | +{ |
2669 | + if (m_runningClients.contains(appId)) { |
2670 | + m_runningClients[appId]->setWindowMaximumWidth(surface->persistentId(), value); |
2671 | + } |
2672 | +} |
2673 | + |
2674 | +void FakeTaskController::setSurfaceMinimumHeight(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
2675 | +{ |
2676 | + if (m_runningClients.contains(appId)) { |
2677 | + m_runningClients[appId]->setWindowMinimumHeight(surface->persistentId(), value); |
2678 | + } |
2679 | +} |
2680 | + |
2681 | +void FakeTaskController::setSurfaceMaximumHeight(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
2682 | +{ |
2683 | + if (m_runningClients.contains(appId)) { |
2684 | + m_runningClients[appId]->setWindowMaximumHeight(surface->persistentId(), value); |
2685 | + } |
2686 | +} |
2687 | + |
2688 | +void FakeTaskController::setSurfaceWidthIncrement(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
2689 | +{ |
2690 | + if (m_runningClients.contains(appId)) { |
2691 | + m_runningClients[appId]->setWindowWidthIncrement(surface->persistentId(), value); |
2692 | + } |
2693 | +} |
2694 | + |
2695 | +void FakeTaskController::setSurfaceHeightIncrement(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
2696 | +{ |
2697 | + if (m_runningClients.contains(appId)) { |
2698 | + m_runningClients[appId]->setWindowHeightIncrement(surface->persistentId(), value); |
2699 | + } |
2700 | +} |
2701 | + |
2702 | +const WindowAttributes *FakeTaskController::windowAttributes(const QString &appId, unity::shell::application::MirSurfaceInterface *surface) |
2703 | +{ |
2704 | + if (m_runningClients.contains(appId)) { |
2705 | + return m_runningClients[appId]->windowAttributes(surface->persistentId()); |
2706 | + } else { |
2707 | + return nullptr; |
2708 | + } |
2709 | +} |
2710 | + |
2711 | +const WindowAttributes *FakeTaskController::windowAttributes(unity::shell::application::MirSurfaceInterface *surface) |
2712 | +{ |
2713 | + const WindowAttributes *winAttribs = nullptr; |
2714 | + |
2715 | + { |
2716 | + auto clientList = m_runningClients.values(); |
2717 | + for (int i = 0; winAttribs == nullptr && i < clientList.count(); ++i) { |
2718 | + winAttribs = clientList[i]->windowAttributes(surface->persistentId()); |
2719 | + } |
2720 | + } |
2721 | + |
2722 | + if (winAttribs == nullptr && m_maliitLauncher) { |
2723 | + winAttribs = m_maliitLauncher->windowAttributes(surface->persistentId()); |
2724 | + } |
2725 | + |
2726 | + return winAttribs; |
2727 | +} |
2728 | + |
2729 | +std::unique_ptr<ProcInfo::CommandLine> FakeProcInfo::commandLine(pid_t pid) |
2730 | +{ |
2731 | + return taskController->commandLine(pid); |
2732 | +} |
2733 | |
2734 | === added file 'src/modules/Unity/Application/fake/faketaskcontroller.h' |
2735 | --- src/modules/Unity/Application/fake/faketaskcontroller.h 1970-01-01 00:00:00 +0000 |
2736 | +++ src/modules/Unity/Application/fake/faketaskcontroller.h 2017-02-14 10:17:32 +0000 |
2737 | @@ -0,0 +1,157 @@ |
2738 | +/* |
2739 | + * Copyright (C) 2017 Canonical, Ltd. |
2740 | + * |
2741 | + * This program is free software: you can redistribute it and/or modify it under |
2742 | + * the terms of the GNU Lesser General Public License version 3, as published by |
2743 | + * the Free Software Foundation. |
2744 | + * |
2745 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
2746 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
2747 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2748 | + * Lesser General Public License for more details. |
2749 | + * |
2750 | + * You should have received a copy of the GNU Lesser General Public License |
2751 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2752 | + * |
2753 | + */ |
2754 | + |
2755 | +#ifndef QTMIR_FAKE_TASK_CONTROLLER_H |
2756 | +#define QTMIR_FAKE_TASK_CONTROLLER_H |
2757 | + |
2758 | +#include "taskcontroller.h" |
2759 | +#include "proc_info.h" |
2760 | + |
2761 | +#include "fakeapplicationinfo.h" |
2762 | + |
2763 | +#include <QMap> |
2764 | +#include <QMutex> |
2765 | +#include <QScopedPointer> |
2766 | +#include <QSharedPointer> |
2767 | +#include <QVector> |
2768 | + |
2769 | +namespace qtmir { |
2770 | + |
2771 | +class FakeMirClientLauncher; |
2772 | +class FakePromptHelperLauncher; |
2773 | +class WindowAttributes; |
2774 | + |
2775 | +class FakeTaskController; |
2776 | + |
2777 | +class FakeProcInfo : public ProcInfo { |
2778 | +public: |
2779 | + std::unique_ptr<CommandLine> commandLine(pid_t pid) override; |
2780 | + FakeTaskController *taskController; |
2781 | +}; |
2782 | + |
2783 | +class FakeTaskController : public qtmir::TaskController |
2784 | +{ |
2785 | + Q_OBJECT |
2786 | +public: |
2787 | + FakeTaskController(); |
2788 | + ~FakeTaskController(); |
2789 | + |
2790 | + static FakeTaskController *instance() { return m_instance; } |
2791 | + |
2792 | + bool appIdHasProcessId(const QString& appId, pid_t pid) override; |
2793 | + |
2794 | + bool stop(const QString& appId) override; |
2795 | + bool start(const QString& appId, const QStringList& arguments) override; |
2796 | + |
2797 | + bool suspend(const QString& appId) override; |
2798 | + bool resume(const QString& appId) override; |
2799 | + |
2800 | + QSharedPointer<qtmir::ApplicationInfo> getInfoForApp(const QString &appId) const override; |
2801 | + |
2802 | + QStringList availableApplications(); |
2803 | + void createSurface(const QString &appId); |
2804 | + void killSurface(const QString &appId, unity::shell::application::MirSurfaceInterface*); |
2805 | + void createPromptSurface(const QString &appId); |
2806 | + |
2807 | + void killApplication(const QString &appId); |
2808 | + |
2809 | + void createInputMethodSurface(); |
2810 | + void stopInputMethod(); |
2811 | + bool isInputMethodRunning(); |
2812 | + void setSurfaceInputBounds(unity::shell::application::MirSurfaceInterface*, QRect); |
2813 | + |
2814 | + QSharedPointer<ProcInfo> procInfo(); |
2815 | + |
2816 | + std::unique_ptr<ProcInfo::CommandLine> commandLine(pid_t pid); |
2817 | + |
2818 | + bool manualSurfaceCreation() const { return m_manualSurfaceCreation; }; |
2819 | + void setManualSurfaceCreation(bool value); |
2820 | + |
2821 | + bool isRunning(const QString &appId); |
2822 | + |
2823 | + void killPrompts(); |
2824 | + bool promptsRunning(); |
2825 | + |
2826 | + void setSurfaceMinimumWidth(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
2827 | + void setSurfaceMaximumWidth(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
2828 | + void setSurfaceMinimumHeight(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
2829 | + void setSurfaceMaximumHeight(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
2830 | + void setSurfaceWidthIncrement(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
2831 | + void setSurfaceHeightIncrement(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
2832 | + |
2833 | + // returns the window attributes as seem on the client side |
2834 | + const WindowAttributes *windowAttributes(const QString &appId, unity::shell::application::MirSurfaceInterface*); |
2835 | + const WindowAttributes *windowAttributes(unity::shell::application::MirSurfaceInterface *surface); |
2836 | + |
2837 | +Q_SIGNALS: |
2838 | + void manualSurfaceCreationChanged(); |
2839 | + |
2840 | +private Q_SLOTS: |
2841 | + void onAuthorizationForSessionRequested(const pid_t &pid, bool &authorized) override; |
2842 | + void onPromptSessionStarting(const PromptSession& promptSession) override; |
2843 | + |
2844 | +private: |
2845 | + // From PidFetcher |
2846 | + // NB: Can be called from either Qt gui or from some mir thread. Hence need for mutex. |
2847 | + pid_t pidOf_impl(const miral::Application &application) override; |
2848 | + |
2849 | + FakeApplicationInfo *findAppInfo(const QString &appId); |
2850 | + |
2851 | + void createAvailableApplications(); |
2852 | + |
2853 | + FakeMirClientLauncher *findClientWithPid(pid_t pid); |
2854 | + |
2855 | + pid_t generatePid(); |
2856 | + pid_t nextPid(pid_t pid) const; |
2857 | + pid_t nextFreePid(pid_t candidatePid, const pid_t latestPid); |
2858 | + bool isPidInUse(pid_t) const; |
2859 | + |
2860 | + void launchPromptProvider(FakePromptHelperLauncher*, int fd); |
2861 | + |
2862 | + // some arbitrary starting point and limit |
2863 | + pid_t m_nextPid{123}; |
2864 | + static const pid_t m_maxPid{10000}; |
2865 | + |
2866 | + |
2867 | + QVector< QSharedPointer<FakeApplicationInfo> > m_availableApplications; |
2868 | + |
2869 | + // maps an appId to its running mir client |
2870 | + QMap<QString, FakeMirClientLauncher*> m_runningClients; |
2871 | + QString m_appIdLatestLaunch; |
2872 | + |
2873 | + // maps an appId to its running prompt helper session |
2874 | + QMap<QString, FakePromptHelperLauncher*> m_runningPromptHelpers; |
2875 | + |
2876 | + QString m_appIdLatestPromptSurface; |
2877 | + |
2878 | + // Because of pidOf_impl() |
2879 | + QMutex m_mutex; |
2880 | + |
2881 | + QSharedPointer<FakeApplicationInfo> m_maliitAppInfo; |
2882 | + QScopedPointer<FakeMirClientLauncher> m_maliitLauncher; |
2883 | + |
2884 | + QSharedPointer<FakeProcInfo> m_procInfo; |
2885 | + |
2886 | + static FakeTaskController *m_instance; |
2887 | + |
2888 | + bool m_manualSurfaceCreation{false}; |
2889 | +}; |
2890 | + |
2891 | +} // namespace qtmir |
2892 | + |
2893 | +#endif // QTMIR_FAKE_TASK_CONTROLLER_H |
2894 | + |
2895 | |
2896 | === added file 'src/modules/Unity/Application/fake/windowattributes.h' |
2897 | --- src/modules/Unity/Application/fake/windowattributes.h 1970-01-01 00:00:00 +0000 |
2898 | +++ src/modules/Unity/Application/fake/windowattributes.h 2017-02-14 10:17:32 +0000 |
2899 | @@ -0,0 +1,47 @@ |
2900 | +/* |
2901 | + * Copyright (C) 2017 Canonical, Ltd. |
2902 | + * |
2903 | + * This program is free software: you can redistribute it and/or modify it under |
2904 | + * the terms of the GNU Lesser General Public License version 3, as published by |
2905 | + * the Free Software Foundation. |
2906 | + * |
2907 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
2908 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
2909 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2910 | + * Lesser General Public License for more details. |
2911 | + * |
2912 | + * You should have received a copy of the GNU Lesser General Public License |
2913 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2914 | + * |
2915 | + */ |
2916 | + |
2917 | +#ifndef QTMIR_WINDOW_ATTRIBUTES |
2918 | +#define QTMIR_WINDOW_ATTRIBUTES |
2919 | + |
2920 | +#include <mir_toolkit/mir_window.h> |
2921 | + |
2922 | +namespace qtmir { |
2923 | + |
2924 | +class WindowAttributes { |
2925 | +public: |
2926 | + WindowAttributes() {} |
2927 | + |
2928 | + WindowAttributes(MirWindow *mirWindow) { |
2929 | + visibility = mir_window_get_visibility(mirWindow); |
2930 | + focusState = mir_window_get_focus_state(mirWindow); |
2931 | + } |
2932 | + |
2933 | + MirWindowVisibility visibility; |
2934 | + MirWindowFocusState focusState; |
2935 | + |
2936 | + int touchPressCount{0}; |
2937 | + int touchReleaseCount{0}; |
2938 | + int mousePressCount{0}; |
2939 | + int mouseReleaseCount{0}; |
2940 | +}; |
2941 | + |
2942 | +} // namespace qtmir |
2943 | + |
2944 | +Q_DECLARE_METATYPE(qtmir::WindowAttributes) |
2945 | + |
2946 | +#endif // QTMIR_WINDOW_ATTRIBUTES |
2947 | |
2948 | === added file 'src/modules/Unity/Application/mirtestsingleton.cpp' |
2949 | --- src/modules/Unity/Application/mirtestsingleton.cpp 1970-01-01 00:00:00 +0000 |
2950 | +++ src/modules/Unity/Application/mirtestsingleton.cpp 2017-02-14 10:17:32 +0000 |
2951 | @@ -0,0 +1,211 @@ |
2952 | +/* |
2953 | + * Copyright (C) 2017 Canonical, Ltd. |
2954 | + * |
2955 | + * This program is free software: you can redistribute it and/or modify it under |
2956 | + * the terms of the GNU Lesser General Public License version 3, as published by |
2957 | + * the Free Software Foundation. |
2958 | + * |
2959 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
2960 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
2961 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
2962 | + * Lesser General Public License for more details. |
2963 | + * |
2964 | + * You should have received a copy of the GNU Lesser General Public License |
2965 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
2966 | + */ |
2967 | + |
2968 | +#include "mirtestsingleton.h" |
2969 | + |
2970 | +#include "application.h" |
2971 | +#include "faketaskcontroller.h" |
2972 | +#include "mirsurface.h" |
2973 | +#include "windowattributes.h" |
2974 | + |
2975 | +using namespace qtmir; |
2976 | + |
2977 | +MirTest *MirTest::m_instance = nullptr; |
2978 | + |
2979 | +MirTest::MirTest() |
2980 | +{ |
2981 | + Q_ASSERT(m_instance == nullptr); |
2982 | + m_instance = this; |
2983 | + |
2984 | + connect(FakeTaskController::instance(), &FakeTaskController::manualSurfaceCreationChanged, |
2985 | + this, &MirTest::manualSurfaceCreationChanged); |
2986 | +} |
2987 | + |
2988 | +MirTest::~MirTest() |
2989 | +{ |
2990 | + Q_ASSERT(m_instance != nullptr); |
2991 | + m_instance = nullptr; |
2992 | +} |
2993 | + |
2994 | +void MirTest::createInputMethodSurface() |
2995 | +{ |
2996 | + FakeTaskController::instance()->createInputMethodSurface(); |
2997 | +} |
2998 | + |
2999 | +void MirTest::stopInputMethod() |
3000 | +{ |
3001 | + FakeTaskController::instance()->stopInputMethod(); |
3002 | +} |
3003 | + |
3004 | +bool MirTest::isInputMethodRunning() |
3005 | +{ |
3006 | + return FakeTaskController::instance()->isInputMethodRunning(); |
3007 | +} |
3008 | + |
3009 | +void MirTest::setSurfaceInputBounds(unity::shell::application::MirSurfaceInterface* surface, QRect rect) |
3010 | +{ |
3011 | + FakeTaskController::instance()->setSurfaceInputBounds(surface, rect); |
3012 | +} |
3013 | + |
3014 | +void MirTest::createSurface(const QString &appId) |
3015 | +{ |
3016 | + FakeTaskController::instance()->createSurface(appId); |
3017 | +} |
3018 | + |
3019 | +void MirTest::createPromptSurface(const QString &appId) |
3020 | +{ |
3021 | + FakeTaskController::instance()->createPromptSurface(appId); |
3022 | +} |
3023 | + |
3024 | +bool MirTest::manualSurfaceCreation() const |
3025 | +{ |
3026 | + return FakeTaskController::instance()->manualSurfaceCreation(); |
3027 | +} |
3028 | + |
3029 | +void MirTest::setManualSurfaceCreation(bool value) |
3030 | +{ |
3031 | + FakeTaskController::instance()->setManualSurfaceCreation(value); |
3032 | +} |
3033 | + |
3034 | +void MirTest::killSurface(const QString &appId, unity::shell::application::MirSurfaceInterface *surface) |
3035 | +{ |
3036 | + FakeTaskController::instance()->killSurface(appId, surface); |
3037 | +} |
3038 | + |
3039 | +void MirTest::killApplication(const QString &appId) |
3040 | +{ |
3041 | + FakeTaskController::instance()->killApplication(appId); |
3042 | +} |
3043 | + |
3044 | +auto MirTest::internalState(unity::shell::application::ApplicationInfoInterface *applicationInterface) -> ApplicationInternalState |
3045 | +{ |
3046 | + auto application = static_cast<Application*>(applicationInterface); |
3047 | + switch (application->internalState()) { |
3048 | + case Application::InternalState::Starting: |
3049 | + if (application->session() == nullptr) { |
3050 | + return StartingNoSession; |
3051 | + } else { |
3052 | + return StartingWithSession; |
3053 | + } |
3054 | + case Application::InternalState::Running: |
3055 | + return Running; |
3056 | + case Application::InternalState::RunningInBackground: |
3057 | + return RunningInBackground; |
3058 | + case Application::InternalState::SuspendingWaitSession: |
3059 | + return SuspendingWaitSession; |
3060 | + case Application::InternalState::SuspendingWaitProcess: |
3061 | + return SuspendingWaitProcess; |
3062 | + case Application::InternalState::Suspended: |
3063 | + return Suspended; |
3064 | + case Application::InternalState::Closing: |
3065 | + return Closing; |
3066 | + case Application::InternalState::StoppedResumable: |
3067 | + return StoppedResumable; |
3068 | + case Application::InternalState::Stopped: |
3069 | + return Stopped; |
3070 | + } |
3071 | + Q_UNREACHABLE(); |
3072 | +} |
3073 | + |
3074 | +QStringList MirTest::availableApplications() |
3075 | +{ |
3076 | + return FakeTaskController::instance()->availableApplications(); |
3077 | +} |
3078 | + |
3079 | +bool MirTest::isApplicationRunning(const QString &appId) |
3080 | +{ |
3081 | + return FakeTaskController::instance()->isRunning(appId); |
3082 | +} |
3083 | + |
3084 | +void MirTest::killPrompts() |
3085 | +{ |
3086 | + FakeTaskController::instance()->killPrompts(); |
3087 | +} |
3088 | + |
3089 | +bool MirTest::promptsRunning() |
3090 | +{ |
3091 | + return FakeTaskController::instance()->promptsRunning(); |
3092 | +} |
3093 | + |
3094 | +void MirTest::setSurfaceMinimumWidth(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
3095 | +{ |
3096 | + FakeTaskController::instance()->setSurfaceMinimumWidth(appId, surface, value); |
3097 | +} |
3098 | + |
3099 | +void MirTest::setSurfaceMaximumWidth(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
3100 | +{ |
3101 | + FakeTaskController::instance()->setSurfaceMaximumWidth(appId, surface, value); |
3102 | +} |
3103 | + |
3104 | +void MirTest::setSurfaceMinimumHeight(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
3105 | +{ |
3106 | + FakeTaskController::instance()->setSurfaceMinimumHeight(appId, surface, value); |
3107 | +} |
3108 | + |
3109 | +void MirTest::setSurfaceMaximumHeight(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
3110 | +{ |
3111 | + FakeTaskController::instance()->setSurfaceMaximumHeight(appId, surface, value); |
3112 | +} |
3113 | + |
3114 | +void MirTest::setSurfaceWidthIncrement(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
3115 | +{ |
3116 | + FakeTaskController::instance()->setSurfaceWidthIncrement(appId, surface, value); |
3117 | +} |
3118 | + |
3119 | +void MirTest::setSurfaceHeightIncrement(const QString &appId, unity::shell::application::MirSurfaceInterface *surface, int value) |
3120 | +{ |
3121 | + FakeTaskController::instance()->setSurfaceHeightIncrement(appId, surface, value); |
3122 | +} |
3123 | + |
3124 | +bool MirTest::surfaceFocused(const QString &appId, unity::shell::application::MirSurfaceInterface *surface) |
3125 | +{ |
3126 | + const WindowAttributes *windowAttribs = FakeTaskController::instance()->windowAttributes(appId, surface); |
3127 | + Q_ASSERT(windowAttribs); |
3128 | + return windowAttribs->focusState == mir_window_focus_state_focused; |
3129 | +} |
3130 | + |
3131 | +bool MirTest::surfaceExposed(const QString &appId, unity::shell::application::MirSurfaceInterface *surface) |
3132 | +{ |
3133 | + const WindowAttributes *windowAttribs = FakeTaskController::instance()->windowAttributes(appId, surface); |
3134 | + Q_ASSERT(windowAttribs); |
3135 | + return windowAttribs->visibility == mir_window_visibility_exposed; |
3136 | +} |
3137 | + |
3138 | +bool MirTest::hasActiveFocus(unity::shell::application::MirSurfaceInterface *surfaceInterface) |
3139 | +{ |
3140 | + auto surface = static_cast<MirSurface*>(surfaceInterface); |
3141 | + return surface->activeFocus(); |
3142 | +} |
3143 | + |
3144 | +int MirTest::touchPressCount(unity::shell::application::MirSurfaceInterface *surface) |
3145 | +{ |
3146 | + return FakeTaskController::instance()->windowAttributes(surface)->touchPressCount; |
3147 | +} |
3148 | + |
3149 | +int MirTest::touchReleaseCount(unity::shell::application::MirSurfaceInterface *surface) |
3150 | +{ |
3151 | + return FakeTaskController::instance()->windowAttributes(surface)->touchReleaseCount; |
3152 | +} |
3153 | + |
3154 | +int MirTest::mousePressCount(unity::shell::application::MirSurfaceInterface *surface) |
3155 | +{ |
3156 | + return FakeTaskController::instance()->windowAttributes(surface)->mousePressCount; |
3157 | +} |
3158 | + |
3159 | +int MirTest::mouseReleaseCount(unity::shell::application::MirSurfaceInterface *surface) |
3160 | +{ |
3161 | + return FakeTaskController::instance()->windowAttributes(surface)->mouseReleaseCount; |
3162 | +} |
3163 | |
3164 | === added file 'src/modules/Unity/Application/mirtestsingleton.h' |
3165 | --- src/modules/Unity/Application/mirtestsingleton.h 1970-01-01 00:00:00 +0000 |
3166 | +++ src/modules/Unity/Application/mirtestsingleton.h 2017-02-14 10:17:32 +0000 |
3167 | @@ -0,0 +1,116 @@ |
3168 | +/* |
3169 | + * Copyright (C) 2017 Canonical, Ltd. |
3170 | + * |
3171 | + * This program is free software: you can redistribute it and/or modify it under |
3172 | + * the terms of the GNU Lesser General Public License version 3, as published by |
3173 | + * the Free Software Foundation. |
3174 | + * |
3175 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
3176 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
3177 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
3178 | + * Lesser General Public License for more details. |
3179 | + * |
3180 | + * You should have received a copy of the GNU Lesser General Public License |
3181 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
3182 | + */ |
3183 | + |
3184 | +#ifndef QTMIR_MIRTEST_H |
3185 | +#define QTMIR_MIRTEST_H |
3186 | + |
3187 | +#include <QObject> |
3188 | +#include <QRect> |
3189 | + |
3190 | +namespace unity { |
3191 | + namespace shell { |
3192 | + namespace application { |
3193 | + class ApplicationInfoInterface; |
3194 | + class MirSurfaceInterface; |
3195 | + } |
3196 | + } |
3197 | +} |
3198 | + |
3199 | +namespace qtmir { |
3200 | + |
3201 | +/* |
3202 | + Various tidbits useful for shell tests |
3203 | + */ |
3204 | +class MirTest : public QObject { |
3205 | + Q_OBJECT |
3206 | + |
3207 | + Q_PROPERTY(bool manualSurfaceCreation READ manualSurfaceCreation WRITE setManualSurfaceCreation NOTIFY manualSurfaceCreationChanged) |
3208 | + Q_PROPERTY(QStringList availableApplications READ availableApplications NOTIFY availableApplicationsChanged) |
3209 | + |
3210 | +public: |
3211 | + |
3212 | + enum ApplicationInternalState { |
3213 | + StartingNoSession, |
3214 | + StartingWithSession, |
3215 | + Running, |
3216 | + RunningInBackground, |
3217 | + SuspendingWaitSession, |
3218 | + SuspendingWaitProcess, |
3219 | + Suspended, |
3220 | + Closing, |
3221 | + StoppedResumable, |
3222 | + Stopped |
3223 | + }; |
3224 | + Q_ENUM(ApplicationInternalState) |
3225 | + |
3226 | + |
3227 | + MirTest(); |
3228 | + virtual ~MirTest(); |
3229 | + |
3230 | + static MirTest *instance() { return m_instance; } |
3231 | + |
3232 | + Q_INVOKABLE void createInputMethodSurface(); |
3233 | + Q_INVOKABLE void stopInputMethod(); |
3234 | + Q_INVOKABLE bool isInputMethodRunning(); |
3235 | + |
3236 | + Q_INVOKABLE void setSurfaceInputBounds(unity::shell::application::MirSurfaceInterface*, QRect); |
3237 | + |
3238 | + Q_INVOKABLE void createSurface(const QString &appId); |
3239 | + |
3240 | + Q_INVOKABLE void createPromptSurface(const QString &appId); |
3241 | + Q_INVOKABLE void killPrompts(); |
3242 | + Q_INVOKABLE bool promptsRunning(); |
3243 | + |
3244 | + bool manualSurfaceCreation() const; |
3245 | + void setManualSurfaceCreation(bool); |
3246 | + |
3247 | + QStringList availableApplications(); |
3248 | + |
3249 | + Q_INVOKABLE void setSurfaceMinimumWidth(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
3250 | + Q_INVOKABLE void setSurfaceMaximumWidth(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
3251 | + Q_INVOKABLE void setSurfaceMinimumHeight(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
3252 | + Q_INVOKABLE void setSurfaceMaximumHeight(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
3253 | + Q_INVOKABLE void setSurfaceWidthIncrement(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
3254 | + Q_INVOKABLE void setSurfaceHeightIncrement(const QString &appId, unity::shell::application::MirSurfaceInterface*, int value); |
3255 | + |
3256 | + Q_INVOKABLE bool hasActiveFocus(unity::shell::application::MirSurfaceInterface*); // server-side information |
3257 | + |
3258 | + Q_INVOKABLE bool surfaceFocused(const QString &appId, unity::shell::application::MirSurfaceInterface*); |
3259 | + Q_INVOKABLE bool surfaceExposed(const QString &appId, unity::shell::application::MirSurfaceInterface*); |
3260 | + Q_INVOKABLE int touchPressCount(unity::shell::application::MirSurfaceInterface*); |
3261 | + Q_INVOKABLE int touchReleaseCount(unity::shell::application::MirSurfaceInterface*); |
3262 | + Q_INVOKABLE int mousePressCount(unity::shell::application::MirSurfaceInterface*); |
3263 | + Q_INVOKABLE int mouseReleaseCount(unity::shell::application::MirSurfaceInterface*); |
3264 | + |
3265 | + Q_INVOKABLE void killSurface(const QString &appId, unity::shell::application::MirSurfaceInterface*); |
3266 | + Q_INVOKABLE void killApplication(const QString &appId); |
3267 | + |
3268 | + Q_INVOKABLE ApplicationInternalState internalState(unity::shell::application::ApplicationInfoInterface *application); |
3269 | + |
3270 | + // Tells whether the application process (in this case, thread) is still running. |
3271 | + Q_INVOKABLE bool isApplicationRunning(const QString &appId); |
3272 | + |
3273 | +Q_SIGNALS: |
3274 | + void manualSurfaceCreationChanged(); |
3275 | + void availableApplicationsChanged(); |
3276 | + |
3277 | +private: |
3278 | + static MirTest *m_instance; |
3279 | +}; |
3280 | + |
3281 | +} // namespace qtmir |
3282 | + |
3283 | +#endif // QTMIR_MIRTEST_H |
3284 | |
3285 | === modified file 'src/modules/Unity/Application/plugin.cpp' |
3286 | --- src/modules/Unity/Application/plugin.cpp 2017-01-18 21:24:15 +0000 |
3287 | +++ src/modules/Unity/Application/plugin.cpp 2017-02-14 10:17:32 +0000 |
3288 | @@ -1,5 +1,5 @@ |
3289 | /* |
3290 | - * Copyright (C) 2013-2016 Canonical, Ltd. |
3291 | + * Copyright (C) 2013-2017 Canonical, Ltd. |
3292 | * |
3293 | * This program is free software: you can redistribute it and/or modify it under |
3294 | * the terms of the GNU Lesser General Public License version 3, as published by |
3295 | @@ -23,6 +23,7 @@ |
3296 | #include "mirsurfaceinterface.h" |
3297 | #include "mirsurfaceitem.h" |
3298 | #include "mirsurfacelistmodel.h" |
3299 | +#include "mirtestsingleton.h" |
3300 | #include "windowmodel.h" |
3301 | #include "surfacemanager.h" |
3302 | |
3303 | @@ -49,6 +50,11 @@ |
3304 | QObject* mirSingleton(QQmlEngine* /*engine*/, QJSEngine* /*scriptEngine*/) { |
3305 | return qtmir::Mir::instance(); |
3306 | } |
3307 | + |
3308 | +QObject* mirTestSingleton(QQmlEngine* /*engine*/, QJSEngine* /*scriptEngine*/) { |
3309 | + qtmir::ApplicationManager::singleton(); // make sure ApplicationManager (and hence TaskController) is created first |
3310 | + return new MirTest(); |
3311 | +} |
3312 | } // anonymous namespace |
3313 | |
3314 | class UnityApplicationPlugin : public QQmlExtensionPlugin { |
3315 | @@ -82,6 +88,10 @@ |
3316 | qmlRegisterType<qtmir::SurfaceManager>(uri, 0, 1, "SurfaceManager"); |
3317 | |
3318 | qmlRegisterType<qtmir::WindowModel>(uri, 0, 1, "WindowModel"); |
3319 | + |
3320 | + if (qgetenv("UNITY_TESTING") == "1") { |
3321 | + qmlRegisterSingletonType<qtmir::MirTest>(uri, 0, 1, "MirTest", mirTestSingleton); |
3322 | + } |
3323 | } |
3324 | |
3325 | virtual void initializeEngine(QQmlEngine *engine, const char *uri) |
3326 | |
3327 | === added directory 'src/modules/Unity/Application/resources' |
3328 | === added directory 'src/modules/Unity/Application/resources/icons' |
3329 | === added file 'src/modules/Unity/Application/resources/icons/browser@18.png' |
3330 | Binary files src/modules/Unity/Application/resources/icons/browser@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/browser@18.png 2017-02-14 10:17:32 +0000 differ |
3331 | === added file 'src/modules/Unity/Application/resources/icons/calendar@18.png' |
3332 | Binary files src/modules/Unity/Application/resources/icons/calendar@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/calendar@18.png 2017-02-14 10:17:32 +0000 differ |
3333 | === added file 'src/modules/Unity/Application/resources/icons/camera@18.png' |
3334 | Binary files src/modules/Unity/Application/resources/icons/camera@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/camera@18.png 2017-02-14 10:17:32 +0000 differ |
3335 | === added file 'src/modules/Unity/Application/resources/icons/contacts-app@18.png' |
3336 | Binary files src/modules/Unity/Application/resources/icons/contacts-app@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/contacts-app@18.png 2017-02-14 10:17:32 +0000 differ |
3337 | === added file 'src/modules/Unity/Application/resources/icons/dash@18.png' |
3338 | Binary files src/modules/Unity/Application/resources/icons/dash@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/dash@18.png 2017-02-14 10:17:32 +0000 differ |
3339 | === added file 'src/modules/Unity/Application/resources/icons/dialer-app@18.png' |
3340 | Binary files src/modules/Unity/Application/resources/icons/dialer-app@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/dialer-app@18.png 2017-02-14 10:17:32 +0000 differ |
3341 | === added file 'src/modules/Unity/Application/resources/icons/evernote@18.png' |
3342 | Binary files src/modules/Unity/Application/resources/icons/evernote@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/evernote@18.png 2017-02-14 10:17:32 +0000 differ |
3343 | === added file 'src/modules/Unity/Application/resources/icons/facebook@18.png' |
3344 | Binary files src/modules/Unity/Application/resources/icons/facebook@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/facebook@18.png 2017-02-14 10:17:32 +0000 differ |
3345 | === added file 'src/modules/Unity/Application/resources/icons/gallery@18.png' |
3346 | Binary files src/modules/Unity/Application/resources/icons/gallery@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/gallery@18.png 2017-02-14 10:17:32 +0000 differ |
3347 | === added file 'src/modules/Unity/Application/resources/icons/gmail@18.png' |
3348 | Binary files src/modules/Unity/Application/resources/icons/gmail@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/gmail@18.png 2017-02-14 10:17:32 +0000 differ |
3349 | === added file 'src/modules/Unity/Application/resources/icons/libreoffice@18.png' |
3350 | Binary files src/modules/Unity/Application/resources/icons/libreoffice@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/libreoffice@18.png 2017-02-14 10:17:32 +0000 differ |
3351 | === added file 'src/modules/Unity/Application/resources/icons/map@18.png' |
3352 | Binary files src/modules/Unity/Application/resources/icons/map@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/map@18.png 2017-02-14 10:17:32 +0000 differ |
3353 | === added file 'src/modules/Unity/Application/resources/icons/messages-app@18.png' |
3354 | Binary files src/modules/Unity/Application/resources/icons/messages-app@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/messages-app@18.png 2017-02-14 10:17:32 +0000 differ |
3355 | === added file 'src/modules/Unity/Application/resources/icons/notepad@18.png' |
3356 | Binary files src/modules/Unity/Application/resources/icons/notepad@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/notepad@18.png 2017-02-14 10:17:32 +0000 differ |
3357 | === added file 'src/modules/Unity/Application/resources/icons/pinterest@18.png' |
3358 | Binary files src/modules/Unity/Application/resources/icons/pinterest@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/pinterest@18.png 2017-02-14 10:17:32 +0000 differ |
3359 | === added file 'src/modules/Unity/Application/resources/icons/soundcloud@18.png' |
3360 | Binary files src/modules/Unity/Application/resources/icons/soundcloud@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/soundcloud@18.png 2017-02-14 10:17:32 +0000 differ |
3361 | === added file 'src/modules/Unity/Application/resources/icons/system-settings@18.png' |
3362 | Binary files src/modules/Unity/Application/resources/icons/system-settings@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/system-settings@18.png 2017-02-14 10:17:32 +0000 differ |
3363 | === added file 'src/modules/Unity/Application/resources/icons/twitter@18.png' |
3364 | Binary files src/modules/Unity/Application/resources/icons/twitter@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/twitter@18.png 2017-02-14 10:17:32 +0000 differ |
3365 | === added file 'src/modules/Unity/Application/resources/icons/weather@18.png' |
3366 | Binary files src/modules/Unity/Application/resources/icons/weather@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/weather@18.png 2017-02-14 10:17:32 +0000 differ |
3367 | === added file 'src/modules/Unity/Application/resources/icons/wikipedia@18.png' |
3368 | Binary files src/modules/Unity/Application/resources/icons/wikipedia@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/wikipedia@18.png 2017-02-14 10:17:32 +0000 differ |
3369 | === added file 'src/modules/Unity/Application/resources/icons/youtube@18.png' |
3370 | Binary files src/modules/Unity/Application/resources/icons/youtube@18.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/icons/youtube@18.png 2017-02-14 10:17:32 +0000 differ |
3371 | === added directory 'src/modules/Unity/Application/resources/screenshots' |
3372 | === added file 'src/modules/Unity/Application/resources/screenshots/browser@12.png' |
3373 | Binary files src/modules/Unity/Application/resources/screenshots/browser@12.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/browser@12.png 2017-02-14 10:17:32 +0000 differ |
3374 | === added file 'src/modules/Unity/Application/resources/screenshots/camera@12.png' |
3375 | Binary files src/modules/Unity/Application/resources/screenshots/camera@12.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/camera@12.png 2017-02-14 10:17:32 +0000 differ |
3376 | === added file 'src/modules/Unity/Application/resources/screenshots/dialer@12.png' |
3377 | Binary files src/modules/Unity/Application/resources/screenshots/dialer@12.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/dialer@12.png 2017-02-14 10:17:32 +0000 differ |
3378 | === added file 'src/modules/Unity/Application/resources/screenshots/facebook@12.png' |
3379 | Binary files src/modules/Unity/Application/resources/screenshots/facebook@12.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/facebook@12.png 2017-02-14 10:17:32 +0000 differ |
3380 | === added file 'src/modules/Unity/Application/resources/screenshots/gallery@12.png' |
3381 | Binary files src/modules/Unity/Application/resources/screenshots/gallery@12.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/gallery@12.png 2017-02-14 10:17:32 +0000 differ |
3382 | === added file 'src/modules/Unity/Application/resources/screenshots/gmail-webapp.svg' |
3383 | --- src/modules/Unity/Application/resources/screenshots/gmail-webapp.svg 1970-01-01 00:00:00 +0000 |
3384 | +++ src/modules/Unity/Application/resources/screenshots/gmail-webapp.svg 2017-02-14 10:17:32 +0000 |
3385 | @@ -0,0 +1,343 @@ |
3386 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
3387 | +<!-- Created with Inkscape (http://www.inkscape.org/) --> |
3388 | + |
3389 | +<svg |
3390 | + xmlns:dc="http://purl.org/dc/elements/1.1/" |
3391 | + xmlns:cc="http://creativecommons.org/ns#" |
3392 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
3393 | + xmlns:svg="http://www.w3.org/2000/svg" |
3394 | + xmlns="http://www.w3.org/2000/svg" |
3395 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
3396 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
3397 | + width="768" |
3398 | + height="1280" |
3399 | + id="svg2" |
3400 | + version="1.1" |
3401 | + inkscape:version="0.48.5 r10040" |
3402 | + sodipodi:docname="gmail-webapp.svg"> |
3403 | + <defs |
3404 | + id="defs4" /> |
3405 | + <sodipodi:namedview |
3406 | + id="base" |
3407 | + pagecolor="#ffffff" |
3408 | + bordercolor="#666666" |
3409 | + borderopacity="1.0" |
3410 | + inkscape:pageopacity="0.0" |
3411 | + inkscape:pageshadow="2" |
3412 | + inkscape:zoom="0.49497475" |
3413 | + inkscape:cx="117.33439" |
3414 | + inkscape:cy="668.80479" |
3415 | + inkscape:document-units="px" |
3416 | + inkscape:current-layer="layer1" |
3417 | + showgrid="false" |
3418 | + inkscape:window-width="1920" |
3419 | + inkscape:window-height="1056" |
3420 | + inkscape:window-x="0" |
3421 | + inkscape:window-y="24" |
3422 | + inkscape:window-maximized="1" /> |
3423 | + <metadata |
3424 | + id="metadata7"> |
3425 | + <rdf:RDF> |
3426 | + <cc:Work |
3427 | + rdf:about=""> |
3428 | + <dc:format>image/svg+xml</dc:format> |
3429 | + <dc:type |
3430 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
3431 | + <dc:title></dc:title> |
3432 | + </cc:Work> |
3433 | + </rdf:RDF> |
3434 | + </metadata> |
3435 | + <g |
3436 | + inkscape:label="Layer 1" |
3437 | + inkscape:groupmode="layer" |
3438 | + id="layer1" |
3439 | + transform="translate(0,227.63782)"> |
3440 | + <rect |
3441 | + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" |
3442 | + id="rect2985" |
3443 | + width="769.73627" |
3444 | + height="1276.8328" |
3445 | + x="-2.0203052" |
3446 | + y="3.1671834" |
3447 | + transform="translate(0,-227.63782)" /> |
3448 | + <rect |
3449 | + style="fill:#e6e6e6;fill-opacity:1;stroke:none;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" |
3450 | + id="rect3797" |
3451 | + width="773.77686" |
3452 | + height="129.29953" |
3453 | + x="-6.0609155" |
3454 | + y="-0.87342685" |
3455 | + transform="translate(0,-227.63782)" /> |
3456 | + <text |
3457 | + xml:space="preserve" |
3458 | + style="font-size:72px;font-style:normal;font-weight:500;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Medium;font-stretch:normal;font-variant:normal" |
3459 | + x="20.203053" |
3460 | + y="-139.61781" |
3461 | + id="text3755" |
3462 | + sodipodi:linespacing="125%"><tspan |
3463 | + sodipodi:role="line" |
3464 | + id="tspan3757" |
3465 | + x="20.203053" |
3466 | + y="-139.61781">GMail</tspan></text> |
3467 | + <text |
3468 | + xml:space="preserve" |
3469 | + style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3470 | + x="14.142137" |
3471 | + y="-28.501045" |
3472 | + id="text3759" |
3473 | + sodipodi:linespacing="125%"><tspan |
3474 | + sodipodi:role="line" |
3475 | + id="tspan3761" |
3476 | + x="14.142137" |
3477 | + y="-28.501045">Inbox</tspan></text> |
3478 | + <path |
3479 | + sodipodi:type="arc" |
3480 | + style="fill:#8effff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" |
3481 | + id="path3765" |
3482 | + sodipodi:cx="107.07617" |
3483 | + sodipodi:cy="337.52768" |
3484 | + sodipodi:rx="64.649765" |
3485 | + sodipodi:ry="61.619305" |
3486 | + d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" |
3487 | + transform="translate(-28.284271,-251.88148)" /> |
3488 | + <path |
3489 | + style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" |
3490 | + d="m 14.142136,237.52257 729.330134,0" |
3491 | + id="path3769" |
3492 | + inkscape:connector-curvature="0" |
3493 | + transform="translate(0,-227.63782)" /> |
3494 | + <text |
3495 | + xml:space="preserve" |
3496 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3497 | + x="167.68533" |
3498 | + y="78.575127" |
3499 | + id="text3771" |
3500 | + sodipodi:linespacing="125%"><tspan |
3501 | + sodipodi:role="line" |
3502 | + id="tspan3773" |
3503 | + x="167.68533" |
3504 | + y="78.575127">Lorem ipsum</tspan></text> |
3505 | + <text |
3506 | + xml:space="preserve" |
3507 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3508 | + x="167.68532" |
3509 | + y="131.10306" |
3510 | + id="text3775" |
3511 | + sodipodi:linespacing="125%"><tspan |
3512 | + sodipodi:role="line" |
3513 | + id="tspan3777" |
3514 | + x="167.68532" |
3515 | + y="131.10306" |
3516 | + style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> |
3517 | + <path |
3518 | + style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" |
3519 | + d="m 13.13199,165.44825 729.33013,0" |
3520 | + id="path3769-2" |
3521 | + inkscape:connector-curvature="0" /> |
3522 | + <path |
3523 | + sodipodi:type="arc" |
3524 | + style="fill:#8eff58;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" |
3525 | + id="path3765-3" |
3526 | + sodipodi:cx="107.07617" |
3527 | + sodipodi:cy="337.52768" |
3528 | + sodipodi:rx="64.649765" |
3529 | + sodipodi:ry="61.619305" |
3530 | + d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" |
3531 | + transform="translate(-26.263969,-93.102383)" /> |
3532 | + <text |
3533 | + xml:space="preserve" |
3534 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3535 | + x="169.70564" |
3536 | + y="237.35422" |
3537 | + id="text3771-9" |
3538 | + sodipodi:linespacing="125%"><tspan |
3539 | + sodipodi:role="line" |
3540 | + id="tspan3773-7" |
3541 | + x="169.70564" |
3542 | + y="237.35422">Lorem ipsum</tspan></text> |
3543 | + <text |
3544 | + xml:space="preserve" |
3545 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3546 | + x="169.70561" |
3547 | + y="289.88217" |
3548 | + id="text3775-1" |
3549 | + sodipodi:linespacing="125%"><tspan |
3550 | + sodipodi:role="line" |
3551 | + id="tspan3777-1" |
3552 | + x="169.70561" |
3553 | + y="289.88217" |
3554 | + style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> |
3555 | + <path |
3556 | + style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" |
3557 | + d="m 15.152292,324.22735 729.330128,0" |
3558 | + id="path3769-2-6" |
3559 | + inkscape:connector-curvature="0" /> |
3560 | + <path |
3561 | + sodipodi:type="arc" |
3562 | + style="fill:#8effff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" |
3563 | + id="path3765-7" |
3564 | + sodipodi:cx="107.07617" |
3565 | + sodipodi:cy="337.52768" |
3566 | + sodipodi:rx="64.649765" |
3567 | + sodipodi:ry="61.619305" |
3568 | + d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" |
3569 | + transform="translate(-28.284274,64.481414)" /> |
3570 | + <text |
3571 | + xml:space="preserve" |
3572 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3573 | + x="167.68533" |
3574 | + y="394.93799" |
3575 | + id="text3771-92" |
3576 | + sodipodi:linespacing="125%"><tspan |
3577 | + sodipodi:role="line" |
3578 | + id="tspan3773-0" |
3579 | + x="167.68533" |
3580 | + y="394.93799">Lorem ipsum</tspan></text> |
3581 | + <text |
3582 | + xml:space="preserve" |
3583 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3584 | + x="167.68532" |
3585 | + y="447.46594" |
3586 | + id="text3775-9" |
3587 | + sodipodi:linespacing="125%"><tspan |
3588 | + sodipodi:role="line" |
3589 | + id="tspan3777-8" |
3590 | + x="167.68532" |
3591 | + y="447.46594" |
3592 | + style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> |
3593 | + <path |
3594 | + style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" |
3595 | + d="m 13.131986,481.81114 729.330124,0" |
3596 | + id="path3769-2-3" |
3597 | + inkscape:connector-curvature="0" /> |
3598 | + <path |
3599 | + sodipodi:type="arc" |
3600 | + style="fill:#8ea2ff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" |
3601 | + id="path3765-2" |
3602 | + sodipodi:cx="107.07617" |
3603 | + sodipodi:cy="337.52768" |
3604 | + sodipodi:rx="64.649765" |
3605 | + sodipodi:ry="61.619305" |
3606 | + d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" |
3607 | + transform="translate(-26.263969,226.10582)" /> |
3608 | + <text |
3609 | + xml:space="preserve" |
3610 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3611 | + x="169.70564" |
3612 | + y="556.56238" |
3613 | + id="text3771-1" |
3614 | + sodipodi:linespacing="125%"><tspan |
3615 | + sodipodi:role="line" |
3616 | + id="tspan3773-1" |
3617 | + x="169.70564" |
3618 | + y="556.56238">Lorem ipsum</tspan></text> |
3619 | + <text |
3620 | + xml:space="preserve" |
3621 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3622 | + x="169.70563" |
3623 | + y="609.09033" |
3624 | + id="text3775-8" |
3625 | + sodipodi:linespacing="125%"><tspan |
3626 | + sodipodi:role="line" |
3627 | + id="tspan3777-85" |
3628 | + x="169.70563" |
3629 | + y="609.09033" |
3630 | + style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> |
3631 | + <path |
3632 | + style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" |
3633 | + d="m 15.152292,643.43555 729.330128,0" |
3634 | + id="path3769-2-1" |
3635 | + inkscape:connector-curvature="0" /> |
3636 | + <path |
3637 | + sodipodi:type="arc" |
3638 | + style="fill:#8effff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" |
3639 | + id="path3765-8" |
3640 | + sodipodi:cx="107.07617" |
3641 | + sodipodi:cy="337.52768" |
3642 | + sodipodi:rx="64.649765" |
3643 | + sodipodi:ry="61.619305" |
3644 | + d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" |
3645 | + transform="translate(-24.243664,391.77084)" /> |
3646 | + <text |
3647 | + xml:space="preserve" |
3648 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3649 | + x="171.72594" |
3650 | + y="722.22742" |
3651 | + id="text3771-7" |
3652 | + sodipodi:linespacing="125%"><tspan |
3653 | + sodipodi:role="line" |
3654 | + id="tspan3773-6" |
3655 | + x="171.72594" |
3656 | + y="722.22742">Lorem ipsum</tspan></text> |
3657 | + <text |
3658 | + xml:space="preserve" |
3659 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3660 | + x="171.72592" |
3661 | + y="774.75537" |
3662 | + id="text3775-5" |
3663 | + sodipodi:linespacing="125%"><tspan |
3664 | + sodipodi:role="line" |
3665 | + id="tspan3777-2" |
3666 | + x="171.72592" |
3667 | + y="774.75537" |
3668 | + style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> |
3669 | + <path |
3670 | + style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" |
3671 | + d="m 17.172597,809.10057 729.330133,0" |
3672 | + id="path3769-2-13" |
3673 | + inkscape:connector-curvature="0" /> |
3674 | + <path |
3675 | + sodipodi:type="arc" |
3676 | + style="fill:#e44738;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" |
3677 | + id="path3765-9" |
3678 | + sodipodi:cx="107.07617" |
3679 | + sodipodi:cy="337.52768" |
3680 | + sodipodi:rx="64.649765" |
3681 | + sodipodi:ry="61.619305" |
3682 | + d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z" |
3683 | + transform="translate(-24.243664,557.43585)" /> |
3684 | + <text |
3685 | + xml:space="preserve" |
3686 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3687 | + x="171.72594" |
3688 | + y="887.89246" |
3689 | + id="text3771-2" |
3690 | + sodipodi:linespacing="125%"><tspan |
3691 | + sodipodi:role="line" |
3692 | + id="tspan3773-8" |
3693 | + x="171.72594" |
3694 | + y="887.89246">Lorem ipsum</tspan></text> |
3695 | + <text |
3696 | + xml:space="preserve" |
3697 | + style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu" |
3698 | + x="171.72592" |
3699 | + y="940.42041" |
3700 | + id="text3775-3" |
3701 | + sodipodi:linespacing="125%"><tspan |
3702 | + sodipodi:role="line" |
3703 | + id="tspan3777-7" |
3704 | + x="171.72592" |
3705 | + y="940.42041" |
3706 | + style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text> |
3707 | + <path |
3708 | + style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" |
3709 | + d="m 17.172597,974.76558 729.330123,0" |
3710 | + id="path3769-2-9" |
3711 | + inkscape:connector-curvature="0" /> |
3712 | + <path |
3713 | + sodipodi:type="arc" |
3714 | + style="fill:none;stroke:#000000;stroke-width:8;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" |
3715 | + id="path3929" |
3716 | + sodipodi:cx="590.93921" |
3717 | + sodipodi:cy="-119.06127" |
3718 | + sodipodi:rx="33.335033" |
3719 | + sodipodi:ry="33.335033" |
3720 | + d="m 624.27424,-119.06127 a 33.335033,33.335033 0 1 1 -66.67006,0 33.335033,33.335033 0 1 1 66.67006,0 z" |
3721 | + transform="matrix(0.85096826,0,0,0.85096826,175.43863,-68.81729)" /> |
3722 | + <path |
3723 | + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:3.40387297;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" |
3724 | + d="m 692.92249,-145.20602 20.63059,24.06901 12.03451,-13.75372 -20.63059,-17.19215" |
3725 | + id="path3931" |
3726 | + inkscape:connector-curvature="0" /> |
3727 | + </g> |
3728 | +</svg> |
3729 | |
3730 | === added file 'src/modules/Unity/Application/resources/screenshots/libreoffice@12.png' |
3731 | Binary files src/modules/Unity/Application/resources/screenshots/libreoffice@12.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/libreoffice@12.png 2017-02-14 10:17:32 +0000 differ |
3732 | === added file 'src/modules/Unity/Application/resources/screenshots/map@12.png' |
3733 | Binary files src/modules/Unity/Application/resources/screenshots/map@12.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/map@12.png 2017-02-14 10:17:32 +0000 differ |
3734 | === added file 'src/modules/Unity/Application/resources/screenshots/music@12.png' |
3735 | Binary files src/modules/Unity/Application/resources/screenshots/music@12.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/music@12.png 2017-02-14 10:17:32 +0000 differ |
3736 | === added file 'src/modules/Unity/Application/resources/screenshots/twitter@12.png' |
3737 | Binary files src/modules/Unity/Application/resources/screenshots/twitter@12.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/twitter@12.png 2017-02-14 10:17:32 +0000 differ |
3738 | === added file 'src/modules/Unity/Application/resources/screenshots/ubuntu-weather-app.svg' |
3739 | --- src/modules/Unity/Application/resources/screenshots/ubuntu-weather-app.svg 1970-01-01 00:00:00 +0000 |
3740 | +++ src/modules/Unity/Application/resources/screenshots/ubuntu-weather-app.svg 2017-02-14 10:17:32 +0000 |
3741 | @@ -0,0 +1,201 @@ |
3742 | +<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
3743 | +<!-- Created with Inkscape (http://www.inkscape.org/) --> |
3744 | + |
3745 | +<svg |
3746 | + xmlns:dc="http://purl.org/dc/elements/1.1/" |
3747 | + xmlns:cc="http://creativecommons.org/ns#" |
3748 | + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
3749 | + xmlns:svg="http://www.w3.org/2000/svg" |
3750 | + xmlns="http://www.w3.org/2000/svg" |
3751 | + xmlns:xlink="http://www.w3.org/1999/xlink" |
3752 | + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" |
3753 | + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" |
3754 | + width="829" |
3755 | + height="480" |
3756 | + id="svg2740" |
3757 | + sodipodi:version="0.32" |
3758 | + inkscape:version="0.48.5 r10040" |
3759 | + version="1.0" |
3760 | + sodipodi:docname="ubuntu-weather-app.svg" |
3761 | + inkscape:output_extension="org.inkscape.output.svg.inkscape"> |
3762 | + <defs |
3763 | + id="defs2742"> |
3764 | + <linearGradient |
3765 | + id="linearGradient3824"> |
3766 | + <stop |
3767 | + style="stop-color:#e6e6e6;stop-opacity:1;" |
3768 | + offset="0" |
3769 | + id="stop3826" /> |
3770 | + <stop |
3771 | + style="stop-color:#23abff;stop-opacity:1;" |
3772 | + offset="1" |
3773 | + id="stop3828" /> |
3774 | + </linearGradient> |
3775 | + <linearGradient |
3776 | + inkscape:collect="always" |
3777 | + xlink:href="#linearGradient3824" |
3778 | + id="linearGradient3830" |
3779 | + x1="348.55862" |
3780 | + y1="343.23914" |
3781 | + x2="348.55862" |
3782 | + y2="-17.422215" |
3783 | + gradientUnits="userSpaceOnUse" /> |
3784 | + </defs> |
3785 | + <sodipodi:namedview |
3786 | + id="base" |
3787 | + pagecolor="#ffffff" |
3788 | + bordercolor="#666666" |
3789 | + borderopacity="1.0" |
3790 | + gridtolerance="10000" |
3791 | + guidetolerance="10" |
3792 | + objecttolerance="10" |
3793 | + inkscape:pageopacity="0.0" |
3794 | + inkscape:pageshadow="2" |
3795 | + inkscape:zoom="0.82625984" |
3796 | + inkscape:cx="331.28234" |
3797 | + inkscape:cy="125.54212" |
3798 | + inkscape:document-units="px" |
3799 | + inkscape:current-layer="layer1" |
3800 | + showgrid="false" |
3801 | + inkscape:window-width="1145" |
3802 | + inkscape:window-height="847" |
3803 | + inkscape:window-x="268" |
3804 | + inkscape:window-y="63" |
3805 | + inkscape:window-maximized="0" /> |
3806 | + <metadata |
3807 | + id="metadata2745"> |
3808 | + <rdf:RDF> |
3809 | + <cc:Work |
3810 | + rdf:about=""> |
3811 | + <dc:format>image/svg+xml</dc:format> |
3812 | + <dc:type |
3813 | + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> |
3814 | + </cc:Work> |
3815 | + </rdf:RDF> |
3816 | + </metadata> |
3817 | + <g |
3818 | + inkscape:label="Layer 1" |
3819 | + inkscape:groupmode="layer" |
3820 | + id="layer1" |
3821 | + transform="translate(-321.13452,-104.68346)"> |
3822 | + <rect |
3823 | + style="fill:url(#linearGradient3830);fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" |
3824 | + id="rect2990" |
3825 | + width="832.66785" |
3826 | + height="480.47839" |
3827 | + x="-1.210273" |
3828 | + y="0.73188055" |
3829 | + transform="translate(321.13452,104.68346)" /> |
3830 | + <path |
3831 | + d="m 310.66382,132.06057 c -1.82703,2.0443 -22.21039,-18.38308 -24.89334,-17.37811 -2.68295,1.00497 -6.73783,33.64192 -9.57527,34.01165 -2.83744,0.36973 -7.71546,-33.08881 -10.48084,-33.88783 -2.76539,-0.79903 -18.7793,19.34152 -21.17964,17.82892 -2.40034,-1.51259 5.69972,-26.09808 4.36486,-28.67057 -1.33487,-2.57249 -31.86305,-3.78032 -32.49182,-6.6501 -0.62876,-2.86978 27.66855,-10.399376 27.90248,-13.241764 0.23394,-2.842387 -18.99828,-18.90215 -17.89698,-21.393798 1.10131,-2.491647 26.85456,8.177399 28.59429,5.99159 1.73972,-2.185809 -3.39182,-29.683489 -0.75169,-30.507098 2.64013,-0.823608 18.50306,18.485327 21.32153,18.392972 2.81847,-0.09235 11.30312,-24.287685 14.18258,-23.722317 2.87947,0.565368 1.44329,25.667631 3.67226,27.34365 2.22897,1.676019 24.27161,-6.28288 25.90675,-4.004945 1.63514,2.277936 -12.63923,24.445025 -11.77955,27.07291 0.85968,2.627885 27.01183,5.1355 26.65457,7.852474 -0.35726,2.716973 -32.69913,3.875594 -34.04684,6.507203 -1.3477,2.631613 12.32368,32.410863 10.49665,34.455163 z" |
3832 | + id="path11949" |
3833 | + inkscape:flatsided="false" |
3834 | + inkscape:randomized="-0.092" |
3835 | + inkscape:rounded="0.1" |
3836 | + sodipodi:arg1="0.79570711" |
3837 | + sodipodi:arg2="1.144773" |
3838 | + sodipodi:cx="275.15002" |
3839 | + sodipodi:cy="88.090233" |
3840 | + sodipodi:r1="57.019234" |
3841 | + sodipodi:r2="32.818508" |
3842 | + sodipodi:sides="9" |
3843 | + sodipodi:type="star" |
3844 | + style="fill:#f5ff12;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible" |
3845 | + transform="matrix(2.527571,0,0,2.527571,85.214779,60.619097)" /> |
3846 | + <path |
3847 | + d="m 194.51692,77.283737 c 0,20.659371 -17.86424,37.407103 -39.90091,37.407103 -22.03666,0 -39.90091,-16.747732 -39.90091,-37.407103 0,-20.659371 17.86425,-37.4071 39.90091,-37.4071 22.03667,0 39.90091,16.747729 39.90091,37.4071 z" |
3848 | + id="path11951" |
3849 | + sodipodi:cx="154.61601" |
3850 | + sodipodi:cy="77.283737" |
3851 | + sodipodi:rx="39.900909" |
3852 | + sodipodi:ry="37.407101" |
3853 | + sodipodi:type="arc" |
3854 | + style="fill:#f5ff12;fill-opacity:1;fill-rule:nonzero;stroke:#f5ff12;stroke-width:10.27388287;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" |
3855 | + transform="matrix(2.4568175,0,0,2.1990879,404.91256,120.05076)" /> |
3856 | + <path |
3857 | + transform="matrix(3.2663208,0,0,3.4016021,515.92101,-254.59331)" |
3858 | + style="fill:#6798e9;fill-opacity:1;fill-rule:nonzero;stroke:#6798e9;stroke-width:7.30059433;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:0.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" |
3859 | + sodipodi:type="inkscape:offset" |
3860 | + inkscape:radius="0" |
3861 | + inkscape:original="M 110.53125 144.96875 C 100.76599 144.96875 92.384060 150.03292 88.281250 157.34375 C 86.642607 156.42892 84.835190 155.87500 82.906250 155.87500 C 77.073071 155.87500 72.219030 160.56753 70.718750 166.93750 C 68.157973 165.92533 65.180470 165.31250 62.000000 165.31250 C 52.458571 165.31250 44.718750 170.53296 44.718750 176.96875 C 44.718749 182.77816 51.066430 187.55402 59.312500 188.43750 C 58.942922 189.06456 58.656250 189.68551 58.656250 190.34375 C 58.656248 196.50568 75.538140 201.53125 96.343750 201.53125 C 117.14936 201.53125 134.03126 196.50568 134.03125 190.34375 C 134.03125 189.92916 133.77393 189.55916 133.62500 189.15625 C 134.53629 189.38287 135.43860 189.62500 136.43750 189.62500 C 142.00333 189.62501 146.53125 185.84318 146.53125 181.18750 C 146.53125 176.53182 142.00332 172.75000 136.43750 172.75000 C 135.75542 172.75000 135.17544 172.98560 134.53125 173.09375 C 135.09454 171.23218 135.46875 169.33268 135.46875 167.31250 C 135.46875 154.98864 124.31330 144.96875 110.53125 144.96875 z " |
3862 | + id="path11953" |
3863 | + d="m 110.53125,144.96875 c -9.76526,0 -18.14719,5.06417 -22.25,12.375 -1.638643,-0.91483 -3.44606,-1.46875 -5.375,-1.46875 -5.833179,0 -10.68722,4.69253 -12.1875,11.0625 -2.560777,-1.01217 -5.53828,-1.625 -8.71875,-1.625 -9.541429,0 -17.28125,5.22046 -17.28125,11.65625 -10e-7,5.80941 6.34768,10.58527 14.59375,11.46875 -0.369578,0.62706 -0.65625,1.24801 -0.65625,1.90625 -2e-6,6.16193 16.88189,11.1875 37.6875,11.1875 20.80561,0 37.68751,-5.02557 37.6875,-11.1875 0,-0.41459 -0.25732,-0.78459 -0.40625,-1.1875 0.91129,0.22662 1.8136,0.46875 2.8125,0.46875 5.56583,1e-5 10.09375,-3.78182 10.09375,-8.4375 0,-4.65568 -4.52793,-8.4375 -10.09375,-8.4375 -0.68208,0 -1.26206,0.2356 -1.90625,0.34375 0.56329,-1.86157 0.9375,-3.76107 0.9375,-5.78125 0,-12.32386 -11.15545,-22.34375 -24.9375,-22.34375 z" /> |
3864 | + <path |
3865 | + inkscape:connector-curvature="0" |
3866 | + style="fill:#386195;fill-opacity:1;fill-rule:nonzero;stroke:#386195;stroke-width:24.07697487;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:0.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" |
3867 | + id="path11963" |
3868 | + d="m 975.70833,305.75079 c -17.87875,0 -33.1897,9.10731 -40.70137,22.18913 -3.00012,-1.63696 -6.34124,-2.6392 -9.87286,-2.6392 -10.67967,0 -19.5639,8.39604 -22.31073,19.7943 -4.6884,-1.81117 -10.09942,-2.93251 -15.92242,-2.93251 -17.46892,0 -31.65122,9.35352 -31.65122,20.86955 0,10.39528 11.61748,18.9466 26.71485,20.52749 -0.67665,1.12204 -1.20995,2.24338 -1.20995,3.42121 0,11.02604 30.92124,19.98985 69.01327,19.98985 38.09195,0 69.0132,-8.96381 69.0132,-19.98985 0,-0.74183 -0.5017,-1.42952 -0.7743,-2.15046 1.6684,0.40556 3.3496,0.83088 5.1784,0.83088 10.1902,0 18.439,-6.7716 18.439,-15.10234 0,-8.33078 -8.2488,-15.05348 -18.439,-15.05348 -1.2488,0 -2.3535,0.39297 -3.5329,0.58647 1.0312,-3.33102 1.7422,-6.7466 1.7422,-10.36143 0,-22.05212 -20.4533,-39.97961 -45.68617,-39.97961 z" /> |
3869 | + <path |
3870 | + inkscape:connector-curvature="0" |
3871 | + style="fill:#6798e9;fill-opacity:1;fill-rule:nonzero;stroke:#6798e9;stroke-width:15.64964962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.20000005;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" |
3872 | + sodipodi:nodetypes="cccc" |
3873 | + id="path11965" |
3874 | + d="m 717.80594,482.73655 c -32.27924,28.4432 5.62151,52.69793 20.03284,13.63938 l 11.08203,-36.22961 -31.11487,22.59023 z" /> |
3875 | + <path |
3876 | + inkscape:connector-curvature="0" |
3877 | + style="fill:#6798e9;fill-opacity:1;fill-rule:nonzero;stroke:#6798e9;stroke-width:15.64964962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.20000005;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible" |
3878 | + sodipodi:nodetypes="cccc" |
3879 | + id="path11967" |
3880 | + d="m 799.47,485.76116 c -32.27925,28.4432 5.62151,52.69792 20.03284,13.63937 l 11.08202,-36.2296 -31.11486,22.59023 z" /> |
3881 | + <text |
3882 | + xml:space="preserve" |
3883 | + style="font-size:32px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold" |
3884 | + x="68.985565" |
3885 | + y="92.712631" |
3886 | + id="text2992" |
3887 | + sodipodi:linespacing="125%" |
3888 | + transform="translate(321.13452,104.68346)"><tspan |
3889 | + sodipodi:role="line" |
3890 | + id="tspan2994" |
3891 | + x="68.985565" |
3892 | + y="92.712631" /></text> |
3893 | + <text |
3894 | + xml:space="preserve" |
3895 | + style="font-size:10px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold" |
3896 | + x="-202.1156" |
3897 | + y="155.64684" |
3898 | + id="text2996" |
3899 | + sodipodi:linespacing="125%" |
3900 | + transform="translate(321.13452,104.68346)"><tspan |
3901 | + sodipodi:role="line" |
3902 | + id="tspan2998" |
3903 | + x="-202.1156" |
3904 | + y="155.64684" /></text> |
3905 | + <text |
3906 | + xml:space="preserve" |
3907 | + style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold" |
3908 | + x="342.91943" |
3909 | + y="155.03653" |
3910 | + id="text3000" |
3911 | + sodipodi:linespacing="125%"><tspan |
3912 | + sodipodi:role="line" |
3913 | + id="tspan3002" |
3914 | + x="342.91943" |
3915 | + y="155.03653" |
3916 | + style="font-size:32px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Medium">Wheather App</tspan></text> |
3917 | + <text |
3918 | + xml:space="preserve" |
3919 | + style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold" |
3920 | + x="460.31592" |
3921 | + y="358.3624" |
3922 | + id="text3004" |
3923 | + sodipodi:linespacing="125%"><tspan |
3924 | + sodipodi:role="line" |
3925 | + id="tspan3006" |
3926 | + x="460.31592" |
3927 | + y="358.3624" |
3928 | + style="font-size:48px;fill:#ff0000;-inkscape-font-specification:Ubuntu;font-family:Ubuntu;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal">22C</tspan></text> |
3929 | + <text |
3930 | + xml:space="preserve" |
3931 | + style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold" |
3932 | + x="460.19751" |
3933 | + y="412.14325" |
3934 | + id="text3004-0" |
3935 | + sodipodi:linespacing="125%"><tspan |
3936 | + sodipodi:role="line" |
3937 | + id="tspan3006-4" |
3938 | + x="460.19751" |
3939 | + y="412.14325" |
3940 | + style="font-size:48px;fill:#0000ff;-inkscape-font-specification:Ubuntu Medium;font-family:Ubuntu;font-weight:500;font-style:normal;font-stretch:normal;font-variant:normal">14C</tspan></text> |
3941 | + </g> |
3942 | +</svg> |
3943 | |
3944 | === added file 'src/modules/Unity/Application/resources/screenshots/unity8-dash@12.png' |
3945 | Binary files src/modules/Unity/Application/resources/screenshots/unity8-dash@12.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/unity8-dash@12.png 2017-02-14 10:17:32 +0000 differ |
3946 | === added file 'src/modules/Unity/Application/resources/screenshots/vkb_portrait.png' |
3947 | Binary files src/modules/Unity/Application/resources/screenshots/vkb_portrait.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/screenshots/vkb_portrait.png 2017-02-14 10:17:32 +0000 differ |
3948 | === added file 'src/modules/Unity/Application/resources/surfaces.qrc' |
3949 | --- src/modules/Unity/Application/resources/surfaces.qrc 1970-01-01 00:00:00 +0000 |
3950 | +++ src/modules/Unity/Application/resources/surfaces.qrc 2017-02-14 10:17:32 +0000 |
3951 | @@ -0,0 +1,39 @@ |
3952 | +<RCC> |
3953 | + <qresource prefix="/Unity/Application"> |
3954 | + <file>vkb_portrait.png</file> |
3955 | + <file>screenshots/browser@12.png</file> |
3956 | + <file>screenshots/camera@12.png</file> |
3957 | + <file>screenshots/dialer@12.png</file> |
3958 | + <file>screenshots/facebook@12.png</file> |
3959 | + <file>screenshots/gallery@12.png</file> |
3960 | + <file>screenshots/gmail-webapp.svg</file> |
3961 | + <file>screenshots/map@12.png</file> |
3962 | + <file>screenshots/music@12.png</file> |
3963 | + <file>screenshots/twitter@12.png</file> |
3964 | + <file>screenshots/ubuntu-weather-app.svg</file> |
3965 | + <file>screenshots/unity8-dash@12.png</file> |
3966 | + <file>screenshots/vkb_portrait.png</file> |
3967 | + <file>screenshots/libreoffice@12.png</file> |
3968 | + <file>icons/browser@18.png</file> |
3969 | + <file>icons/calendar@18.png</file> |
3970 | + <file>icons/camera@18.png</file> |
3971 | + <file>icons/contacts-app@18.png</file> |
3972 | + <file>icons/dash@18.png</file> |
3973 | + <file>icons/dialer-app@18.png</file> |
3974 | + <file>icons/evernote@18.png</file> |
3975 | + <file>icons/facebook@18.png</file> |
3976 | + <file>icons/gallery@18.png</file> |
3977 | + <file>icons/gmail@18.png</file> |
3978 | + <file>icons/libreoffice@18.png</file> |
3979 | + <file>icons/map@18.png</file> |
3980 | + <file>icons/messages-app@18.png</file> |
3981 | + <file>icons/notepad@18.png</file> |
3982 | + <file>icons/pinterest@18.png</file> |
3983 | + <file>icons/soundcloud@18.png</file> |
3984 | + <file>icons/system-settings@18.png</file> |
3985 | + <file>icons/twitter@18.png</file> |
3986 | + <file>icons/weather@18.png</file> |
3987 | + <file>icons/wikipedia@18.png</file> |
3988 | + <file>icons/youtube@18.png</file> |
3989 | + </qresource> |
3990 | +</RCC> |
3991 | |
3992 | === added file 'src/modules/Unity/Application/resources/vkb_portrait.png' |
3993 | Binary files src/modules/Unity/Application/resources/vkb_portrait.png 1970-01-01 00:00:00 +0000 and src/modules/Unity/Application/resources/vkb_portrait.png 2017-02-14 10:17:32 +0000 differ |
3994 | === modified file 'src/modules/Unity/Application/session.cpp' |
3995 | --- src/modules/Unity/Application/session.cpp 2016-11-03 20:17:46 +0000 |
3996 | +++ src/modules/Unity/Application/session.cpp 2017-02-14 10:17:32 +0000 |
3997 | @@ -1,5 +1,5 @@ |
3998 | /* |
3999 | - * Copyright (C) 2014-2016 Canonical, Ltd. |
4000 | + * Copyright (C) 2014-2017 Canonical, Ltd. |
4001 | * |
4002 | * This program is free software: you can redistribute it and/or modify it under |
4003 | * the terms of the GNU Lesser General Public License version 3, as published by |
4004 | @@ -215,6 +215,8 @@ |
4005 | { |
4006 | DEBUG_MSG << "(surface=" << newSurface << ")"; |
4007 | |
4008 | + const bool focusedBefore = focused(); |
4009 | + |
4010 | connect(newSurface, &MirSurfaceInterface::stateChanged, |
4011 | this, &Session::updateFullscreenProperty); |
4012 | |
4013 | @@ -244,6 +246,11 @@ |
4014 | setState(Running); |
4015 | } |
4016 | |
4017 | + const bool focusedNow = focused(); |
4018 | + if (focusedNow != focusedBefore) { |
4019 | + Q_EMIT focusedChanged(focused()); |
4020 | + } |
4021 | + |
4022 | updateFullscreenProperty(); |
4023 | } |
4024 | |
4025 | @@ -389,6 +396,11 @@ |
4026 | surface->setLive(false); |
4027 | } |
4028 | |
4029 | + for (int i = 0; i < m_closingSurfaces.count(); ++i) { |
4030 | + auto surface = static_cast<MirSurfaceInterface*>(m_closingSurfaces[i]); |
4031 | + surface->setLive(false); |
4032 | + } |
4033 | + |
4034 | deleteIfZombieAndEmpty(); |
4035 | } |
4036 | } |
4037 | |
4038 | === modified file 'src/modules/Unity/Application/session_interface.h' |
4039 | --- src/modules/Unity/Application/session_interface.h 2016-11-03 20:17:46 +0000 |
4040 | +++ src/modules/Unity/Application/session_interface.h 2017-02-14 10:17:32 +0000 |
4041 | @@ -99,7 +99,7 @@ |
4042 | |
4043 | virtual pid_t pid() const = 0; |
4044 | |
4045 | - // For SessionManager use |
4046 | + // For TaskController use |
4047 | |
4048 | virtual void addChildSession(SessionInterface* session) = 0; |
4049 | virtual void insertChildSession(uint index, SessionInterface* session) = 0; |
4050 | |
4051 | === removed file 'src/modules/Unity/Application/sessionmanager.cpp' |
4052 | --- src/modules/Unity/Application/sessionmanager.cpp 2016-11-03 20:17:46 +0000 |
4053 | +++ src/modules/Unity/Application/sessionmanager.cpp 1970-01-01 00:00:00 +0000 |
4054 | @@ -1,200 +0,0 @@ |
4055 | -/* |
4056 | - * Copyright (C) 2014-2016 Canonical, Ltd. |
4057 | - * |
4058 | - * This program is free software: you can redistribute it and/or modify it under |
4059 | - * the terms of the GNU Lesser General Public License version 3, as published by |
4060 | - * the Free Software Foundation. |
4061 | - * |
4062 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
4063 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4064 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4065 | - * Lesser General Public License for more details. |
4066 | - * |
4067 | - * You should have received a copy of the GNU Lesser General Public License |
4068 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4069 | - */ |
4070 | - |
4071 | -// Qt |
4072 | -#include <QGuiApplication> |
4073 | - |
4074 | -// local |
4075 | -#include "application_manager.h" |
4076 | -#include "debughelpers.h" |
4077 | -#include "sessionmanager.h" |
4078 | - |
4079 | -// QPA mirserver |
4080 | -#include "appnotifier.h" |
4081 | -#include "logging.h" |
4082 | -#include "nativeinterface.h" |
4083 | -#include "promptsessionlistener.h" |
4084 | -#include "promptsession.h" |
4085 | - |
4086 | - |
4087 | -namespace qtmir { |
4088 | - |
4089 | -SessionManager *SessionManager::the_session_manager = nullptr; |
4090 | - |
4091 | - |
4092 | -void connectToAppNotifier(SessionManager *manager, AppNotifier *appNotifier) |
4093 | -{ |
4094 | - QObject::connect(appNotifier, &AppNotifier::appAdded, |
4095 | - manager, &SessionManager::onSessionStarting); |
4096 | - QObject::connect(appNotifier, &AppNotifier::appRemoved, |
4097 | - manager, &SessionManager::onSessionStopping); |
4098 | -} |
4099 | - |
4100 | -void connectToPromptSessionListener(SessionManager * manager, PromptSessionListener * listener) |
4101 | -{ |
4102 | - QObject::connect(listener, &PromptSessionListener::promptSessionStarting, |
4103 | - manager, &SessionManager::onPromptSessionStarting); |
4104 | - QObject::connect(listener, &PromptSessionListener::promptSessionStopping, |
4105 | - manager, &SessionManager::onPromptSessionStopping); |
4106 | - QObject::connect(listener, &PromptSessionListener::promptProviderAdded, |
4107 | - manager, &SessionManager::onPromptProviderAdded); |
4108 | - QObject::connect(listener, &PromptSessionListener::promptProviderRemoved, |
4109 | - manager, &SessionManager::onPromptProviderRemoved); |
4110 | -} |
4111 | - |
4112 | -SessionManager* SessionManager::singleton() |
4113 | -{ |
4114 | - if (!the_session_manager) { |
4115 | - |
4116 | - NativeInterface *nativeInterface = dynamic_cast<NativeInterface*>(QGuiApplication::platformNativeInterface()); |
4117 | - |
4118 | - if (!nativeInterface) { |
4119 | - qCritical("ERROR: Unity.Application QML plugin requires use of the 'mirserver' QPA plugin"); |
4120 | - QGuiApplication::quit(); |
4121 | - return nullptr; |
4122 | - } |
4123 | - |
4124 | - auto appNotifier = static_cast<AppNotifier*>(nativeInterface->nativeResourceForIntegration("AppNotifier")); |
4125 | - PromptSessionListener *promptSessionListener = static_cast<PromptSessionListener*>(nativeInterface->nativeResourceForIntegration("PromptSessionListener")); |
4126 | - |
4127 | - the_session_manager = new SessionManager(nativeInterface->thePromptSessionManager(), ApplicationManager::singleton()); |
4128 | - |
4129 | - connectToAppNotifier(the_session_manager, appNotifier); |
4130 | - connectToPromptSessionListener(the_session_manager, promptSessionListener); |
4131 | - } |
4132 | - return the_session_manager; |
4133 | -} |
4134 | - |
4135 | -SessionManager::SessionManager( |
4136 | - const std::shared_ptr<qtmir::PromptSessionManager>& promptSessionManager, |
4137 | - ApplicationManager* applicationManager, |
4138 | - QObject *parent) |
4139 | - : SessionModel(parent) |
4140 | - , m_promptSessionManager(promptSessionManager) |
4141 | - , m_applicationManager(applicationManager) |
4142 | -{ |
4143 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::SessionManager - this=" << this; |
4144 | - setObjectName(QStringLiteral("qtmir::SessionManager")); |
4145 | -} |
4146 | - |
4147 | -SessionManager::~SessionManager() |
4148 | -{ |
4149 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::~SessionManager - this=" << this; |
4150 | -} |
4151 | - |
4152 | -SessionInterface *SessionManager::findSession(const mir::scene::Session* session) const |
4153 | -{ |
4154 | - if (!session) return nullptr; |
4155 | - |
4156 | - for (SessionInterface* child : list()) { |
4157 | - if (child->session().get() == session) |
4158 | - return child; |
4159 | - } |
4160 | - return nullptr; |
4161 | -} |
4162 | - |
4163 | -void SessionManager::onSessionStarting(const miral::ApplicationInfo &appInfo) |
4164 | -{ |
4165 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::onSessionStarting - sessionName=" << appInfo.name().c_str(); |
4166 | - |
4167 | - const auto &session = appInfo.application(); |
4168 | - Session* qmlSession = new Session(session, m_promptSessionManager); |
4169 | - insert(0, qmlSession); |
4170 | - |
4171 | - Application* application = m_applicationManager->findApplicationWithSession(session); |
4172 | - if (application && application->state() != Application::Running) { |
4173 | - application->setSession(qmlSession); |
4174 | - } |
4175 | - // need to remove if we've destroyed outside |
4176 | - connect(qmlSession, &Session::destroyed, this, [&](QObject *item) { |
4177 | - auto sessionToRemove = static_cast<Session*>(item); |
4178 | - remove(sessionToRemove); |
4179 | - }); |
4180 | - |
4181 | - Q_EMIT sessionStarting(qmlSession); |
4182 | -} |
4183 | - |
4184 | -void SessionManager::onSessionStopping(const miral::ApplicationInfo &appInfo) |
4185 | -{ |
4186 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::onSessionStopping - sessionName=" << appInfo.name().c_str(); |
4187 | - |
4188 | - SessionInterface* qmlSession = findSession(appInfo.application().get()); |
4189 | - if (!qmlSession) return; |
4190 | - |
4191 | - remove(qmlSession); |
4192 | - |
4193 | - qmlSession->setLive(false); |
4194 | - Q_EMIT sessionStopping(qmlSession); |
4195 | -} |
4196 | - |
4197 | -void SessionManager::onPromptSessionStarting(const qtmir::PromptSession &promptSession) |
4198 | -{ |
4199 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptSessionStarting - promptSession=" << promptSession.get(); |
4200 | - |
4201 | - std::shared_ptr<mir::scene::Session> appSession = m_promptSessionManager->applicationFor(promptSession); |
4202 | - SessionInterface *qmlAppSession = findSession(appSession.get()); |
4203 | - if (qmlAppSession) { |
4204 | - m_mirPromptToSessionHash[promptSession.get()] = qmlAppSession; |
4205 | - qmlAppSession->appendPromptSession(promptSession); |
4206 | - } else { |
4207 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptSessionStarting - could not find app session for prompt session"; |
4208 | - } |
4209 | -} |
4210 | - |
4211 | -void SessionManager::onPromptSessionStopping(const qtmir::PromptSession &promptSession) |
4212 | -{ |
4213 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptSessionStopping - promptSession=" << promptSession.get(); |
4214 | - |
4215 | - for (SessionInterface *qmlSession : this->list()) { |
4216 | - qmlSession->removePromptSession(promptSession); |
4217 | - } |
4218 | - m_mirPromptToSessionHash.remove(promptSession.get()); |
4219 | -} |
4220 | - |
4221 | -void SessionManager::onPromptProviderAdded(const qtmir::PromptSession &promptSession, |
4222 | - const std::shared_ptr<mir::scene::Session> &promptProvider) |
4223 | -{ |
4224 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptProviderAdded - promptSession=" << promptSession.get() << " promptProvider=" << promptProvider.get(); |
4225 | - |
4226 | - SessionInterface* qmlAppSession = m_mirPromptToSessionHash.value(promptSession.get(), nullptr); |
4227 | - if (!qmlAppSession) { |
4228 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptProviderAdded - could not find session item for app session"; |
4229 | - return; |
4230 | - } |
4231 | - |
4232 | - SessionInterface* qmlPromptProvider = findSession(promptProvider.get()); |
4233 | - if (!qmlPromptProvider) { |
4234 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptProviderAdded - could not find session item for provider session"; |
4235 | - return; |
4236 | - } |
4237 | - |
4238 | - qmlAppSession->addChildSession(qmlPromptProvider); |
4239 | -} |
4240 | - |
4241 | -void SessionManager::onPromptProviderRemoved(const qtmir::PromptSession &promptSession, |
4242 | - const std::shared_ptr<mir::scene::Session> &promptProvider) |
4243 | -{ |
4244 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptProviderRemoved - promptSession=" << promptSession.get() << " promptProvider=" << promptProvider.get(); |
4245 | - |
4246 | - SessionInterface* qmlPromptProvider = findSession(promptProvider.get()); |
4247 | - if (!qmlPromptProvider) { |
4248 | - qCDebug(QTMIR_SESSIONS) << "SessionManager::onPromptProviderAdded - could not find session item for provider session"; |
4249 | - return; |
4250 | - } |
4251 | - qmlPromptProvider->setLive(false); |
4252 | -} |
4253 | - |
4254 | -} // namespace qtmir |
4255 | |
4256 | === removed file 'src/modules/Unity/Application/sessionmanager.h' |
4257 | --- src/modules/Unity/Application/sessionmanager.h 2016-11-03 20:17:46 +0000 |
4258 | +++ src/modules/Unity/Application/sessionmanager.h 1970-01-01 00:00:00 +0000 |
4259 | @@ -1,90 +0,0 @@ |
4260 | -/* |
4261 | - * Copyright (C) 2014-2015 Canonical, Ltd. |
4262 | - * |
4263 | - * This program is free software: you can redistribute it and/or modify it under |
4264 | - * the terms of the GNU Lesser General Public License version 3, as published by |
4265 | - * the Free Software Foundation. |
4266 | - * |
4267 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
4268 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4269 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4270 | - * Lesser General Public License for more details. |
4271 | - * |
4272 | - * You should have received a copy of the GNU Lesser General Public License |
4273 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4274 | - */ |
4275 | - |
4276 | -#ifndef SESSIONMANAGER_H |
4277 | -#define SESSIONMANAGER_H |
4278 | - |
4279 | -// std |
4280 | -#include <memory> |
4281 | - |
4282 | -// Qt |
4283 | -#include <QHash> |
4284 | -#include <QSharedPointer> |
4285 | - |
4286 | -// Mir |
4287 | -#include <mir_toolkit/common.h> |
4288 | - |
4289 | -// miral |
4290 | -#include <miral/application_info.h> |
4291 | - |
4292 | -// local |
4293 | -#include "session.h" |
4294 | -#include "sessionmodel.h" |
4295 | - |
4296 | -namespace mir { |
4297 | - namespace scene { |
4298 | - class Session; |
4299 | - class PromptSession; |
4300 | - } |
4301 | -} |
4302 | - |
4303 | -namespace qtmir { |
4304 | - |
4305 | -class Application; |
4306 | -class ApplicationManager; |
4307 | - |
4308 | -class SessionManager : public SessionModel |
4309 | -{ |
4310 | - Q_OBJECT |
4311 | - |
4312 | -public: |
4313 | - explicit SessionManager( |
4314 | - const std::shared_ptr<PromptSessionManager>& promptSessionManager, |
4315 | - ApplicationManager* applicationManager, |
4316 | - QObject *parent = 0 |
4317 | - ); |
4318 | - ~SessionManager(); |
4319 | - |
4320 | - static SessionManager* singleton(); |
4321 | - |
4322 | - SessionInterface *findSession(const mir::scene::Session* session) const; |
4323 | - |
4324 | -Q_SIGNALS: |
4325 | - void sessionStarting(SessionInterface* session); |
4326 | - void sessionStopping(SessionInterface* session); |
4327 | - |
4328 | -public Q_SLOTS: |
4329 | - void onSessionStarting(const miral::ApplicationInfo &appInfo); |
4330 | - void onSessionStopping(const miral::ApplicationInfo &appInfo); |
4331 | - |
4332 | - void onPromptSessionStarting(const PromptSession& promptSession); |
4333 | - void onPromptSessionStopping(const PromptSession& promptSession); |
4334 | - void onPromptProviderAdded(const qtmir::PromptSession &promptSession, const std::shared_ptr<mir::scene::Session> &); |
4335 | - void onPromptProviderRemoved(const qtmir::PromptSession &promptSession, const std::shared_ptr<mir::scene::Session> &); |
4336 | - |
4337 | -protected: |
4338 | - |
4339 | -private: |
4340 | - const std::shared_ptr<PromptSessionManager> m_promptSessionManager; |
4341 | - ApplicationManager* m_applicationManager; |
4342 | - static SessionManager *the_session_manager; |
4343 | - |
4344 | - QHash<const mir::scene::PromptSession *, SessionInterface *> m_mirPromptToSessionHash; |
4345 | -}; |
4346 | - |
4347 | -} // namespace qtmir |
4348 | - |
4349 | -#endif // SESSIONMANAGER_H |
4350 | |
4351 | === modified file 'src/modules/Unity/Application/surfacemanager.cpp' |
4352 | --- src/modules/Unity/Application/surfacemanager.cpp 2017-02-02 09:17:48 +0000 |
4353 | +++ src/modules/Unity/Application/surfacemanager.cpp 2017-02-14 10:17:32 +0000 |
4354 | @@ -1,5 +1,5 @@ |
4355 | /* |
4356 | - * Copyright (C) 2016 Canonical, Ltd. |
4357 | + * Copyright (C) 2016,2017 Canonical, Ltd. |
4358 | * |
4359 | * This program is free software: you can redistribute it and/or modify it under |
4360 | * the terms of the GNU Lesser General Public License version 3, as published by |
4361 | @@ -17,7 +17,7 @@ |
4362 | #include "surfacemanager.h" |
4363 | |
4364 | #include "mirsurface.h" |
4365 | -#include "sessionmanager.h" |
4366 | +#include "application_manager.h" |
4367 | |
4368 | // mirserver |
4369 | #include "nativeinterface.h" |
4370 | @@ -54,8 +54,6 @@ |
4371 | |
4372 | auto windowModel = static_cast<WindowModelNotifier*>(nativeInterface->nativeResourceForIntegration("WindowModelNotifier")); |
4373 | connectToWindowModelNotifier(windowModel); |
4374 | - |
4375 | - m_sessionManager = SessionManager::singleton(); |
4376 | } |
4377 | |
4378 | void SurfaceManager::connectToWindowModelNotifier(WindowModelNotifier *notifier) |
4379 | @@ -99,7 +97,7 @@ |
4380 | } |
4381 | |
4382 | auto mirSession = window.windowInfo.window().application(); |
4383 | - SessionInterface* session = m_sessionManager->findSession(mirSession.get()); |
4384 | + SessionInterface* session = ApplicationManager::singleton()->findSession(mirSession.get()); |
4385 | |
4386 | MirSurface *parentSurface; |
4387 | { |
4388 | @@ -122,6 +120,7 @@ |
4389 | |
4390 | void SurfaceManager::onWindowRemoved(const miral::WindowInfo &windowInfo) |
4391 | { |
4392 | + DEBUG_MSG << "()"; |
4393 | MirSurface *surface = find(windowInfo); |
4394 | forgetMirSurface(windowInfo.window()); |
4395 | surface->setLive(false); |
4396 | |
4397 | === modified file 'src/modules/Unity/Application/surfacemanager.h' |
4398 | --- src/modules/Unity/Application/surfacemanager.h 2017-02-02 09:17:48 +0000 |
4399 | +++ src/modules/Unity/Application/surfacemanager.h 2017-02-14 10:17:32 +0000 |
4400 | @@ -1,5 +1,5 @@ |
4401 | /* |
4402 | - * Copyright (C) 2016 Canonical, Ltd. |
4403 | + * Copyright (C) 2016,2017 Canonical, Ltd. |
4404 | * |
4405 | * This program is free software: you can redistribute it and/or modify it under |
4406 | * the terms of the GNU Lesser General Public License version 3, as published by |
4407 | @@ -31,7 +31,6 @@ |
4408 | namespace qtmir { |
4409 | |
4410 | class MirSurface; |
4411 | -class SessionManager; |
4412 | class WindowControllerInterface; |
4413 | |
4414 | class SurfaceManager : public unity::shell::application::SurfaceManagerInterface |
4415 | @@ -66,7 +65,6 @@ |
4416 | QVector<MirSurface*> m_allSurfaces; |
4417 | |
4418 | WindowControllerInterface *m_windowController; |
4419 | - SessionManager* m_sessionManager; |
4420 | }; |
4421 | |
4422 | } // namespace qtmir |
4423 | |
4424 | === added file 'src/modules/Unity/Application/taskcontroller.cpp' |
4425 | --- src/modules/Unity/Application/taskcontroller.cpp 1970-01-01 00:00:00 +0000 |
4426 | +++ src/modules/Unity/Application/taskcontroller.cpp 2017-02-14 10:17:32 +0000 |
4427 | @@ -0,0 +1,196 @@ |
4428 | +/* |
4429 | + * Copyright (C) 2017 Canonical, Ltd. |
4430 | + * |
4431 | + * This program is free software: you can redistribute it and/or modify it under |
4432 | + * the terms of the GNU Lesser General Public License version 3, as published by |
4433 | + * the Free Software Foundation. |
4434 | + * |
4435 | + * This program is distributed in the hope that it will be useful, but WITHOUT |
4436 | + * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4437 | + * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4438 | + * Lesser General Public License for more details. |
4439 | + * |
4440 | + * You should have received a copy of the GNU Lesser General Public License |
4441 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4442 | + */ |
4443 | + |
4444 | +// local |
4445 | +#include "taskcontroller.h" |
4446 | +#include "session.h" |
4447 | + |
4448 | +#include <QGuiApplication> |
4449 | + |
4450 | +// QPA mirserver |
4451 | +#include "logging.h" |
4452 | +#include "nativeinterface.h" |
4453 | +#include "promptsessionlistener.h" |
4454 | +#include "promptsession.h" |
4455 | +#include <sessionauthorizer.h> |
4456 | + |
4457 | +// common |
4458 | +#include "appnotifier.h" |
4459 | + |
4460 | +#define DEBUG_MSG qCDebug(QTMIR_SESSIONS).nospace() << "TaskController::" << __func__ |
4461 | + |
4462 | +using namespace qtmir; |
4463 | + |
4464 | +void TaskController::connectToAppNotifier(AppNotifier *appNotifier) |
4465 | +{ |
4466 | + QObject::connect(appNotifier, &AppNotifier::appAdded, |
4467 | + this, &TaskController::onSessionStarting); |
4468 | + QObject::connect(appNotifier, &AppNotifier::appRemoved, |
4469 | + this, &TaskController::onSessionStopping); |
4470 | +} |
4471 | + |
4472 | +void TaskController::connectToPromptSessionListener(PromptSessionListener * listener) |
4473 | +{ |
4474 | + QObject::connect(listener, &PromptSessionListener::promptSessionStarting, |
4475 | + this, &TaskController::onPromptSessionStarting); |
4476 | + QObject::connect(listener, &PromptSessionListener::promptSessionStopping, |
4477 | + this, &TaskController::onPromptSessionStopping); |
4478 | + QObject::connect(listener, &PromptSessionListener::promptProviderAdded, |
4479 | + this, &TaskController::onPromptProviderAdded); |
4480 | + QObject::connect(listener, &PromptSessionListener::promptProviderRemoved, |
4481 | + this, &TaskController::onPromptProviderRemoved); |
4482 | +} |
4483 | + |
4484 | +TaskController::TaskController(QObject *parent) |
4485 | + : QObject(parent) |
4486 | +{ |
4487 | + Q_ASSERT(PidFetcher::m_instance == nullptr); |
4488 | + PidFetcher::m_instance = this; |
4489 | + |
4490 | + NativeInterface *nativeInterface = dynamic_cast<NativeInterface*>(QGuiApplication::platformNativeInterface()); |
4491 | + |
4492 | + if (!nativeInterface) { |
4493 | + qFatal("ERROR: Unity.Application QML plugin requires use of the 'mirserver' QPA plugin"); |
4494 | + } |
4495 | + |
4496 | + m_promptSessionManager = nativeInterface->thePromptSessionManager(); |
4497 | + |
4498 | + auto appNotifier = static_cast<AppNotifier*>(nativeInterface->nativeResourceForIntegration("AppNotifier")); |
4499 | + connectToAppNotifier(appNotifier); |
4500 | + |
4501 | + auto promptSessionListener = static_cast<PromptSessionListener*>(nativeInterface->nativeResourceForIntegration("PromptSessionListener")); |
4502 | + connectToPromptSessionListener(promptSessionListener); |
4503 | + |
4504 | + auto sessionAuthorizer = static_cast<SessionAuthorizer*>(nativeInterface->nativeResourceForIntegration("SessionAuthorizer")); |
4505 | + QObject::connect(sessionAuthorizer, &SessionAuthorizer::requestAuthorizationForSession, |
4506 | + this, &TaskController::onAuthorizationForSessionRequested, Qt::BlockingQueuedConnection); |
4507 | +} |
4508 | + |
4509 | +TaskController::TaskController(std::shared_ptr<PromptSessionManager> promptSessionManager, QObject *parent) |
4510 | + : QObject(parent) |
4511 | + , m_promptSessionManager(promptSessionManager) |
4512 | +{ |
4513 | + Q_ASSERT(PidFetcher::m_instance == nullptr); |
4514 | + PidFetcher::m_instance = this; |
4515 | +} |
4516 | + |
4517 | +TaskController::~TaskController() |
4518 | +{ |
4519 | + Q_ASSERT(PidFetcher::m_instance != nullptr); |
4520 | + PidFetcher::m_instance = nullptr; |
4521 | +} |
4522 | + |
4523 | +void TaskController::onSessionStarting(const miral::ApplicationInfo &appInfo) |
4524 | +{ |
4525 | + DEBUG_MSG << " - sessionName=" << appInfo.name().c_str(); |
4526 | + |
4527 | + const auto &session = appInfo.application(); |
4528 | + Session* qmlSession = new Session(session, m_promptSessionManager); |
4529 | + m_sessionList.prepend(qmlSession); |
4530 | + |
4531 | + // need to remove if we've destroyed outside |
4532 | + connect(qmlSession, &Session::destroyed, this, [&](QObject *item) { |
4533 | + auto sessionToRemove = static_cast<Session*>(item); |
4534 | + m_sessionList.removeAll(sessionToRemove); |
4535 | + }); |
4536 | + |
4537 | + Q_EMIT sessionStarting(qmlSession); |
4538 | +} |
4539 | + |
4540 | +void TaskController::onSessionStopping(const miral::ApplicationInfo &appInfo) |
4541 | +{ |
4542 | + DEBUG_MSG << " - sessionName=" << appInfo.name().c_str(); |
4543 | + |
4544 | + SessionInterface* qmlSession = findSession(appInfo.application().get()); |
4545 | + if (!qmlSession) return; |
4546 | + |
4547 | + m_sessionList.removeAll(qmlSession); |
4548 | + |
4549 | + qmlSession->setLive(false); |
4550 | +} |
4551 | + |
4552 | +void TaskController::onPromptSessionStarting(const qtmir::PromptSession &promptSession) |
4553 | +{ |
4554 | + DEBUG_MSG << " - promptSession=" << promptSession.get(); |
4555 | + |
4556 | + std::shared_ptr<mir::scene::Session> appSession = m_promptSessionManager->applicationFor(promptSession); |
4557 | + SessionInterface *qmlAppSession = findSession(appSession.get()); |
4558 | + if (qmlAppSession) { |
4559 | + m_mirPromptToSessionHash[promptSession.get()] = qmlAppSession; |
4560 | + qmlAppSession->appendPromptSession(promptSession); |
4561 | + } else { |
4562 | + DEBUG_MSG << " - could not find app session for prompt session"; |
4563 | + } |
4564 | +} |
4565 | + |
4566 | +void TaskController::onPromptSessionStopping(const qtmir::PromptSession &promptSession) |
4567 | +{ |
4568 | + DEBUG_MSG << " - promptSession=" << promptSession.get(); |
4569 | + |
4570 | + for (SessionInterface *qmlSession : m_sessionList) { |
4571 | + qmlSession->removePromptSession(promptSession); |
4572 | + } |
4573 | + m_mirPromptToSessionHash.remove(promptSession.get()); |
4574 | +} |
4575 | + |
4576 | +void TaskController::onPromptProviderAdded(const qtmir::PromptSession &promptSession, |
4577 | + const std::shared_ptr<mir::scene::Session> &promptProvider) |
4578 | +{ |
4579 | + DEBUG_MSG << " - promptSession=" << promptSession.get() << " promptProvider=" << promptProvider.get(); |
4580 | + |
4581 | + SessionInterface* qmlAppSession = m_mirPromptToSessionHash.value(promptSession.get(), nullptr); |
4582 | + if (!qmlAppSession) { |
4583 | + DEBUG_MSG << " - could not find session item for app session"; |
4584 | + return; |
4585 | + } |
4586 | + |
4587 | + SessionInterface* qmlPromptProvider = findSession(promptProvider.get()); |
4588 | + if (!qmlPromptProvider) { |
4589 | + DEBUG_MSG << " - could not find session item for provider session"; |
4590 | + return; |
4591 | + } |
4592 | + |
4593 | + qmlAppSession->addChildSession(qmlPromptProvider); |
4594 | +} |
4595 | + |
4596 | +void TaskController::onPromptProviderRemoved(const qtmir::PromptSession &promptSession, |
4597 | + const std::shared_ptr<mir::scene::Session> &promptProvider) |
4598 | +{ |
4599 | + DEBUG_MSG << " - promptSession=" << promptSession.get() << " promptProvider=" << promptProvider.get(); |
4600 | + |
4601 | + SessionInterface* qmlPromptProvider = findSession(promptProvider.get()); |
4602 | + if (!qmlPromptProvider) { |
4603 | + DEBUG_MSG << " - could not find session item for provider session"; |
4604 | + return; |
4605 | + } |
4606 | + qmlPromptProvider->setLive(false); |
4607 | +} |
4608 | + |
4609 | +SessionInterface *TaskController::findSession(const mir::scene::Session* session) const |
4610 | +{ |
4611 | + if (!session) return nullptr; |
4612 | + |
4613 | + Q_FOREACH(SessionInterface* child, m_sessionList) { |
4614 | + if (child->session().get() == session) |
4615 | + return child; |
4616 | + } |
4617 | + return nullptr; |
4618 | +} |
4619 | + |
4620 | +void TaskController::onAuthorizationForSessionRequested(const pid_t &pid, bool &authorized) |
4621 | +{ |
4622 | + Q_EMIT authorizationRequestedForSession(pid, authorized); |
4623 | +} |
4624 | |
4625 | === modified file 'src/modules/Unity/Application/taskcontroller.h' |
4626 | --- src/modules/Unity/Application/taskcontroller.h 2016-04-22 14:03:26 +0000 |
4627 | +++ src/modules/Unity/Application/taskcontroller.h 2017-02-14 10:17:32 +0000 |
4628 | @@ -1,5 +1,5 @@ |
4629 | /* |
4630 | - * Copyright (C) 2014-2015 Canonical, Ltd. |
4631 | + * Copyright (C) 2014-2017 Canonical, Ltd. |
4632 | * |
4633 | * This program is free software: you can redistribute it and/or modify it under |
4634 | * the terms of the GNU Lesser General Public License version 3, as published by |
4635 | @@ -23,12 +23,39 @@ |
4636 | #include <QString> |
4637 | #include <QStringList> |
4638 | |
4639 | +// miral |
4640 | +#include <miral/application.h> |
4641 | +#include <miral/application_info.h> |
4642 | + |
4643 | +// mirserver |
4644 | +#include "promptsessionmanager.h" |
4645 | +#include <pidfetcher.h> |
4646 | + |
4647 | +namespace mir { |
4648 | + namespace scene { |
4649 | + class Session; |
4650 | + class PromptSession; |
4651 | + } |
4652 | +} |
4653 | + |
4654 | +namespace unity { |
4655 | + namespace shell { |
4656 | + namespace application { |
4657 | + class MirSurfaceInterface; |
4658 | + } |
4659 | + } |
4660 | +} |
4661 | + |
4662 | +class PromptSessionListener; |
4663 | + |
4664 | namespace qtmir |
4665 | { |
4666 | |
4667 | +class AppNotifier; |
4668 | class ApplicationInfo; |
4669 | +class SessionInterface; |
4670 | |
4671 | -class TaskController : public QObject |
4672 | +class TaskController : public QObject, PidFetcher |
4673 | { |
4674 | Q_OBJECT |
4675 | |
4676 | @@ -39,8 +66,7 @@ |
4677 | APPLICATION_FAILED_TO_START |
4678 | }; |
4679 | |
4680 | - TaskController(const TaskController&) = delete; |
4681 | - virtual ~TaskController() = default; |
4682 | + virtual ~TaskController(); |
4683 | |
4684 | TaskController& operator=(const TaskController&) = delete; |
4685 | |
4686 | @@ -54,6 +80,14 @@ |
4687 | |
4688 | virtual QSharedPointer<qtmir::ApplicationInfo> getInfoForApp(const QString &appId) const = 0; |
4689 | |
4690 | + // needed for injecting fake info when running a fake TaskController for testing |
4691 | + // While this class is not the best fit for them, it's good the have them all under the same interface |
4692 | +private: |
4693 | + pid_t pidOf_impl(const miral::Application &application) override { return miral::pid_of(application); } |
4694 | +public: |
4695 | + |
4696 | + SessionInterface *findSession(const mir::scene::Session* session) const; |
4697 | + |
4698 | Q_SIGNALS: |
4699 | void processStarting(const QString &appId); |
4700 | void applicationStarted(const QString &appId); |
4701 | @@ -64,8 +98,32 @@ |
4702 | |
4703 | void processFailed(const QString &appId, TaskController::Error error); |
4704 | |
4705 | + void authorizationRequestedForSession(const pid_t &pid, bool &authorized); |
4706 | + |
4707 | + void sessionStarting(SessionInterface *session); |
4708 | + |
4709 | +public Q_SLOTS: |
4710 | + virtual void onSessionStarting(const miral::ApplicationInfo &appInfo); |
4711 | + virtual void onSessionStopping(const miral::ApplicationInfo &appInfo); |
4712 | + |
4713 | + virtual void onPromptSessionStarting(const PromptSession& promptSession); |
4714 | + virtual void onPromptSessionStopping(const PromptSession& promptSession); |
4715 | + virtual void onPromptProviderAdded(const qtmir::PromptSession &promptSession, const std::shared_ptr<mir::scene::Session> &); |
4716 | + virtual void onPromptProviderRemoved(const qtmir::PromptSession &promptSession, const std::shared_ptr<mir::scene::Session> &); |
4717 | + |
4718 | + virtual void onAuthorizationForSessionRequested(const pid_t &pid, bool &authorized); |
4719 | + |
4720 | protected: |
4721 | - TaskController() = default; |
4722 | + TaskController(QObject *parent = nullptr); |
4723 | + TaskController(std::shared_ptr<PromptSessionManager>, QObject *parent = nullptr); |
4724 | + |
4725 | + void connectToAppNotifier(AppNotifier *); |
4726 | + void connectToPromptSessionListener(PromptSessionListener *); |
4727 | + |
4728 | + std::shared_ptr<PromptSessionManager> m_promptSessionManager; |
4729 | + |
4730 | + QHash<const mir::scene::PromptSession *, SessionInterface *> m_mirPromptToSessionHash; |
4731 | + QList<SessionInterface*> m_sessionList; |
4732 | }; |
4733 | |
4734 | } // namespace qtmir |
4735 | |
4736 | === modified file 'src/platforms/mirserver/CMakeLists.txt' |
4737 | --- src/platforms/mirserver/CMakeLists.txt 2017-02-02 09:36:07 +0000 |
4738 | +++ src/platforms/mirserver/CMakeLists.txt 2017-02-14 10:17:32 +0000 |
4739 | @@ -61,6 +61,7 @@ |
4740 | shelluuid.cpp |
4741 | ubuntutheme.cpp |
4742 | clipboard.cpp |
4743 | + initialsurfacesizes.cpp |
4744 | openglcontextfactory.cpp openglcontextfactory.h |
4745 | initialsurfacesizes.cpp initialsurfacesizes.h |
4746 | mircursorimages.cpp |
4747 | @@ -70,6 +71,7 @@ |
4748 | promptsessionlistener.cpp |
4749 | mirserverstatuslistener.cpp |
4750 | screenscontroller.cpp |
4751 | + pidfetcher.cpp pidfetcher.h |
4752 | nativeinterface.cpp |
4753 | qtcompositor.cpp |
4754 | services.cpp |
4755 | |
4756 | === removed file 'src/platforms/mirserver/argvHelper.h' |
4757 | --- src/platforms/mirserver/argvHelper.h 2015-12-12 17:45:28 +0000 |
4758 | +++ src/platforms/mirserver/argvHelper.h 1970-01-01 00:00:00 +0000 |
4759 | @@ -1,52 +0,0 @@ |
4760 | -/* |
4761 | - * Copyright (C) 2015 Canonical, Ltd. |
4762 | - * |
4763 | - * This program is free software: you can redistribute it and/or modify it under |
4764 | - * the terms of the GNU Lesser General Public License version 3, as published by |
4765 | - * the Free Software Foundation. |
4766 | - * |
4767 | - * This program is distributed in the hope that it will be useful, but WITHOUT |
4768 | - * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, |
4769 | - * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
4770 | - * Lesser General Public License for more details. |
4771 | - * |
4772 | - * You should have received a copy of the GNU Lesser General Public License |
4773 | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
4774 | - */ |
4775 | - |
4776 | -#ifndef ARGVHELPER_P_H |
4777 | -#define ARGVHELPER_P_H |
4778 | - |
4779 | -#include <cassert> |
4780 | - |
4781 | -namespace qtmir { |
4782 | - |
4783 | -// Function to edit argv to strip out unmatched entries of targetArray, so both arrays have identical contents |
4784 | -// Note: Mir parses out arguments that it understands, but it also removes argv[0] (bug pad.lv/1511509) |
4785 | -// so need to ensure argv[0] is the binary name as usual. |
4786 | -void editArgvToMatch(int &argcToEdit, char** argvToEdit, int targetCount, const char* const targetArray[]) |
4787 | -{ |
4788 | - // Make copy of the argv array of pointers, as we will be editing the original |
4789 | - const size_t arraySize = (argcToEdit + 1) * sizeof(char*); |
4790 | - char** argvCopy = static_cast<char**>(malloc(arraySize)); |
4791 | - memcpy(argvCopy, argvToEdit, arraySize); |
4792 | - |
4793 | - int k=1; // index of argv we want to edit - note we'll leave argv[0] alone |
4794 | - for (int i=0; i<targetCount; i++) { // taking each argument Mir did not parse out |
4795 | - for (int j=1; j<argcToEdit; j++) { // find pointer to same argument in argvCopy (leave arg[0] out) |
4796 | - if (strcmp(targetArray[i], argvCopy[j]) == 0) { |
4797 | - argvToEdit[k] = const_cast<char*>(argvCopy[j]); // edit argv to position that argument to match argv2. |
4798 | - k++; |
4799 | - break; |
4800 | - } |
4801 | - } |
4802 | - } |
4803 | - assert(k == targetCount+1); |
4804 | - argvToEdit[k] = nullptr; |
4805 | - free(argvCopy); |
4806 | - argcToEdit = targetCount+1; // now argv and targetArray should have list the same strings. |
4807 | -} |
4808 | - |
4809 | -} // namespace qtmir |
4810 | - |
4811 | -#endif // ARGVHELPER_P_H |
4812 | |
4813 | === modified file 'src/platforms/mirserver/cursor.cpp' |
4814 | --- src/platforms/mirserver/cursor.cpp 2016-11-03 20:17:46 +0000 |
4815 | +++ src/platforms/mirserver/cursor.cpp 2017-02-14 10:17:32 +0000 |
4816 | @@ -1,5 +1,5 @@ |
4817 | /* |
4818 | - * Copyright (C) 2015 Canonical, Ltd. |
4819 | + * Copyright (C) 2015,2017 Canonical, Ltd. |
4820 | * |
4821 | * This program is free software: you can redistribute it and/or modify it under |
4822 | * the terms of the GNU Lesser General Public License version 3, as published by |
4823 | @@ -98,7 +98,7 @@ |
4824 | updateMousePointerCursorName(); |
4825 | } |
4826 | |
4827 | -bool Cursor::handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons, |
4828 | +bool Cursor::handleMouseEvent(ulong timestamp, QPointF movement, QPointF position, Qt::MouseButtons buttons, |
4829 | Qt::KeyboardModifiers modifiers) |
4830 | { |
4831 | QMutexLocker locker(&m_mutex); |
4832 | @@ -111,6 +111,7 @@ |
4833 | bool ok = QMetaObject::invokeMethod(m_mousePointer, "handleMouseEvent", Qt::AutoConnection, |
4834 | Q_ARG(ulong, timestamp), |
4835 | Q_ARG(QPointF, movement), |
4836 | + Q_ARG(QPointF, position), |
4837 | Q_ARG(Qt::MouseButtons, buttons), |
4838 | Q_ARG(Qt::KeyboardModifiers, modifiers)); |
4839 | |
4840 | @@ -136,7 +137,7 @@ |
4841 | Q_ARG(Qt::KeyboardModifiers, modifiers)); |
4842 | |
4843 | if (!ok) { |
4844 | - qCWarning(QTMIR_MIR_INPUT) << "Failed to invoke MousePointer::handleMouseEvent"; |
4845 | + qCWarning(QTMIR_MIR_INPUT) << "Failed to invoke MousePointer::handleWheelEvent"; |
4846 | } |
4847 | |
4848 | return ok; |
4849 | @@ -155,7 +156,7 @@ |
4850 | movement.setX(pos.x() - mouseScenePos.x()); |
4851 | movement.setY(pos.y() - mouseScenePos.y()); |
4852 | |
4853 | - m_mousePointer->handleMouseEvent(0 /*timestamp*/, movement, Qt::NoButton, Qt::NoModifier); |
4854 | + m_mousePointer->handleMouseEvent(0 /*timestamp*/, movement, pos, Qt::NoButton, Qt::NoModifier); |
4855 | } |
4856 | |
4857 | QPoint Cursor::pos() const |
4858 | |
4859 | === modified file 'src/platforms/mirserver/cursor.h' |
4860 | --- src/platforms/mirserver/cursor.h 2016-06-06 19:25:20 +0000 |
4861 | +++ src/platforms/mirserver/cursor.h 2017-02-14 10:17:32 +0000 |
4862 | @@ -1,5 +1,5 @@ |
4863 | /* |
4864 | - * Copyright (C) 2015 Canonical, Ltd. |
4865 | + * Copyright (C) 2015,2017 Canonical, Ltd. |
4866 | * |
4867 | * This program is free software: you can redistribute it and/or modify it under |
4868 | * the terms of the GNU Lesser General Public License version 3, as published by |
4869 | @@ -33,7 +33,7 @@ |
4870 | Cursor(); |
4871 | |
4872 | // Called form Mir input thread |
4873 | - bool handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons, |
4874 | + bool handleMouseEvent(ulong timestamp, QPointF movement, QPointF position, Qt::MouseButtons buttons, |
4875 | Qt::KeyboardModifiers modifiers); |
4876 | bool handleWheelEvent(ulong timestamp, QPoint angleDelta, Qt::KeyboardModifiers mods); |
4877 | |
4878 | |
4879 | === modified file 'src/platforms/mirserver/logging.cpp' |
4880 | --- src/platforms/mirserver/logging.cpp 2016-09-29 15:46:59 +0000 |
4881 | +++ src/platforms/mirserver/logging.cpp 2017-02-14 10:17:32 +0000 |
4882 | @@ -1,5 +1,5 @@ |
4883 | /* |
4884 | - * Copyright (C) 2016 Canonical, Ltd. |
4885 | + * Copyright (C) 2016,2017 Canonical, Ltd. |
4886 | * |
4887 | * This program is free software: you can redistribute it and/or modify it under |
4888 | * the terms of the GNU Lesser General Public License version 3, as published by |
4889 | @@ -26,3 +26,4 @@ |
4890 | Q_LOGGING_CATEGORY(QTMIR_SENSOR_MESSAGES, "qtmir.sensor") |
4891 | Q_LOGGING_CATEGORY(QTMIR_SCREENS, "qtmir.screens") |
4892 | Q_LOGGING_CATEGORY(QTMIR_DBUS, "qtmir.dbus", QtWarningMsg) |
4893 | +Q_LOGGING_CATEGORY(QTMIR_FAKECLIENTS, "qtmir.fakeclients", QtDebugMsg) |
4894 | |
4895 | === modified file 'src/platforms/mirserver/logging.h' |
4896 | --- src/platforms/mirserver/logging.h 2016-09-29 15:46:59 +0000 |
4897 | +++ src/platforms/mirserver/logging.h 2017-02-14 10:17:32 +0000 |
4898 | @@ -1,5 +1,5 @@ |
4899 | /* |
4900 | - * Copyright (C) 2013-2014 Canonical, Ltd. |
4901 | + * Copyright (C) 2013-2017 Canonical, Ltd. |
4902 | * |
4903 | * This program is free software: you can redistribute it and/or modify it under |
4904 | * the terms of the GNU Lesser General Public License version 3, as published by |
4905 | @@ -28,5 +28,6 @@ |
4906 | Q_DECLARE_LOGGING_CATEGORY(QTMIR_CLIPBOARD) |
4907 | Q_DECLARE_LOGGING_CATEGORY(QTMIR_SCREENS) |
4908 | Q_DECLARE_LOGGING_CATEGORY(QTMIR_DBUS) |
4909 | +Q_DECLARE_LOGGING_CATEGORY(QTMIR_FAKECLIENTS) |
4910 | |
4911 | #endif // UBUNTU_APPLICATION_PLUGIN_LOGGING_H |
4912 | |
4913 | === modified file 'src/platforms/mirserver/mirserverhooks.cpp' |
4914 | --- src/platforms/mirserver/mirserverhooks.cpp 2017-01-03 20:59:50 +0000 |
4915 | +++ src/platforms/mirserver/mirserverhooks.cpp 2017-02-14 10:17:32 +0000 |
4916 | @@ -1,5 +1,5 @@ |
4917 | /* |
4918 | - * Copyright © 2016 Canonical Ltd. |
4919 | + * Copyright © 2016-2017 Canonical Ltd. |
4920 | * |
4921 | * This program is free software: you can redistribute it and/or modify it |
4922 | * under the terms of the GNU General Public License version 3, |
4923 | @@ -77,6 +77,7 @@ |
4924 | std::weak_ptr<mir::shell::DisplayConfigurationController> m_mirDisplayConfigurationController; |
4925 | std::weak_ptr<mir::scene::PromptSessionManager> m_mirPromptSessionManager; |
4926 | std::weak_ptr<mir::input::InputDeviceHub> m_inputDeviceHub; |
4927 | + mir::Server *m_server{nullptr}; |
4928 | }; |
4929 | |
4930 | qtmir::MirServerHooks::MirServerHooks() : |
4931 | @@ -109,6 +110,8 @@ |
4932 | self->m_mirPromptSessionManager = server.the_prompt_session_manager(); |
4933 | self->m_inputDeviceHub = server.the_input_device_hub(); |
4934 | }); |
4935 | + |
4936 | + self->m_server = &server; |
4937 | } |
4938 | |
4939 | PromptSessionListener *qtmir::MirServerHooks::promptSessionListener() const |
4940 | @@ -143,6 +146,11 @@ |
4941 | throw std::logic_error("No input device hub available. Server not running?"); |
4942 | } |
4943 | |
4944 | +mir::Server *qtmir::MirServerHooks::server() const |
4945 | +{ |
4946 | + return self->m_server; |
4947 | +} |
4948 | + |
4949 | QSharedPointer<ScreensController> qtmir::MirServerHooks::createScreensController(QSharedPointer<ScreensModel> const &screensModel) const |
4950 | { |
4951 | return QSharedPointer<ScreensController>( |
4952 | |
4953 | === modified file 'src/platforms/mirserver/mirserverhooks.h' |
4954 | --- src/platforms/mirserver/mirserverhooks.h 2017-01-02 14:41:06 +0000 |
4955 | +++ src/platforms/mirserver/mirserverhooks.h 2017-02-14 10:17:32 +0000 |
4956 | @@ -1,5 +1,5 @@ |
4957 | /* |
4958 | - * Copyright © 2016 Canonical Ltd. |
4959 | + * Copyright © 2016-2017 Canonical Ltd. |
4960 | * |
4961 | * This program is free software: you can redistribute it and/or modify it |
4962 | * under the terms of the GNU General Public License version 3, |
4963 | @@ -44,6 +44,7 @@ |
4964 | std::shared_ptr<mir::scene::PromptSessionManager> thePromptSessionManager() const; |
4965 | std::shared_ptr<mir::graphics::Display> theMirDisplay() const; |
4966 | std::shared_ptr<mir::input::InputDeviceHub> theInputDeviceHub() const; |
4967 | + mir::Server *server() const; |
4968 | |
4969 | QSharedPointer<ScreensController> createScreensController(QSharedPointer<ScreensModel> const &screensModel) const; |
4970 | void createInputDeviceObserver(); |
4971 | |
4972 | === modified file 'src/platforms/mirserver/mirserverintegration.cpp' |
4973 | --- src/platforms/mirserver/mirserverintegration.cpp 2016-11-03 20:17:46 +0000 |
4974 | +++ src/platforms/mirserver/mirserverintegration.cpp 2017-02-14 10:17:32 +0000 |
4975 | @@ -50,11 +50,11 @@ |
4976 | namespace mg = mir::graphics; |
4977 | using qtmir::Clipboard; |
4978 | |
4979 | -MirServerIntegration::MirServerIntegration(int &argc, char **argv) |
4980 | +MirServerIntegration::MirServerIntegration() |
4981 | : m_accessibility(new QPlatformAccessibility()) |
4982 | , m_fontDb(new QGenericUnixFontDatabase()) |
4983 | , m_services(new Services) |
4984 | - , m_mirServer(new QMirServer(argc, argv)) |
4985 | + , m_mirServer(new QMirServer) |
4986 | , m_nativeInterface(nullptr) |
4987 | { |
4988 | // For access to sensors, qtmir uses qtubuntu-sensors. qtubuntu-sensors reads the |
4989 | |
4990 | === modified file 'src/platforms/mirserver/mirserverintegration.h' |
4991 | --- src/platforms/mirserver/mirserverintegration.h 2016-08-30 12:32:13 +0000 |
4992 | +++ src/platforms/mirserver/mirserverintegration.h 2017-02-14 10:17:32 +0000 |
4993 | @@ -27,7 +27,7 @@ |
4994 | class MirServerIntegration : public QPlatformIntegration |
4995 | { |
4996 | public: |
4997 | - MirServerIntegration(int &argc, char **argv); |
4998 | + MirServerIntegration(); |
4999 | ~MirServerIntegration(); |
5000 |
FAILED: Continuous integration, rev:596 /unity8- jenkins. ubuntu. com/job/ lp-qtmir- ci/485/ /unity8- jenkins. ubuntu. com/job/ build/4058/ console /unity8- jenkins. ubuntu. com/job/ build-0- fetch/4086 /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 3926/console /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=amd64, release= zesty/3926/ console /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 3926/console /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=armhf, release= zesty/3926/ console /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 3926/console /unity8- jenkins. ubuntu. com/job/ build-2- binpkg/ arch=i386, release= zesty/3926/ console
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /unity8- jenkins. ubuntu. com/job/ lp-qtmir- ci/485/ rebuild
https:/