Merge lp:~unity-team/unity8/dash-as-app into lp:unity8
- dash-as-app
- Merge into trunk
Status: | Merged | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Approved by: | Michał Sawicz | ||||||||||||||||||||
Approved revision: | 1110 | ||||||||||||||||||||
Merged at revision: | 1111 | ||||||||||||||||||||
Proposed branch: | lp:~unity-team/unity8/dash-as-app | ||||||||||||||||||||
Merge into: | lp:unity8 | ||||||||||||||||||||
Prerequisite: | lp:~mzanetti/unity8/drop-running-apps-from-dash | ||||||||||||||||||||
Diff against target: |
2983 lines (+1043/-783) 51 files modified
CMakeLists.txt (+1/-0) data/CMakeLists.txt (+5/-2) data/unity8-dash.conf (+22/-0) data/unity8-dash.desktop.in (+9/-0) data/unity8.conf (+1/-7) debian/unity8.install (+3/-0) plugins/Unity/CMakeLists.txt (+1/-0) plugins/Unity/DashCommunicator/CMakeLists.txt (+19/-0) plugins/Unity/DashCommunicator/dashcommunicator.cpp (+43/-0) plugins/Unity/DashCommunicator/dashcommunicator.h (+35/-0) plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp (+30/-0) plugins/Unity/DashCommunicator/dashcommunicatorservice.h (+38/-0) plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp (+39/-0) plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h (+39/-0) plugins/Unity/DashCommunicator/plugin.cpp (+31/-0) plugins/Unity/DashCommunicator/plugin.h (+34/-0) plugins/Unity/DashCommunicator/qmldir (+3/-0) plugins/Unity/Launcher/launchermodel.cpp (+5/-0) qml/Components/EdgeDemo.qml (+5/-6) qml/Dash/Dash.qml (+8/-0) qml/Dash/DashApplication.qml (+29/-0) qml/Dash/GenericScopeView.qml (+1/-1) qml/Dash/ScopeListView.qml (+0/-5) qml/Launcher/Launcher.qml (+2/-3) qml/Shell.qml (+26/-132) qml/Stages/PhoneStage.qml (+61/-28) qml/Stages/SpreadDelegate.qml (+6/-0) qml/Stages/TabletStage.qml (+85/-41) qml/Stages/TransformedSpreadDelegate.qml (+6/-5) qml/Stages/TransformedTabletSpreadDelegate.qml (+29/-1) src/CMakeLists.txt (+1/-0) src/Dash/CMakeLists.txt (+12/-0) src/Dash/main.cpp (+74/-0) tests/mocks/Unity/Application/ApplicationInfo.cpp (+0/-62) tests/mocks/Unity/Application/ApplicationInfo.h (+0/-10) tests/mocks/Unity/Application/ApplicationManager.cpp (+17/-147) tests/mocks/Unity/Application/ApplicationManager.h (+0/-16) tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp (+1/-1) tests/mocks/Unity/CMakeLists.txt (+1/-0) tests/mocks/Unity/DashCommunicator/CMakeLists.txt (+18/-0) tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp (+37/-0) tests/mocks/Unity/DashCommunicator/dashcommunicator.h (+39/-0) tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp (+33/-0) tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h (+36/-0) tests/mocks/Unity/DashCommunicator/plugin.cpp (+31/-0) tests/mocks/Unity/DashCommunicator/plugin.h (+34/-0) tests/mocks/Unity/DashCommunicator/qmldir (+3/-0) tests/qmltests/Dash/tst_Dash.qml (+19/-0) tests/qmltests/Stages/tst_PhoneStage.qml (+3/-2) tests/qmltests/tst_Shell.qml (+64/-277) tests/qmltests/tst_ShellWithPin.qml (+4/-37) |
||||||||||||||||||||
To merge this branch: | bzr merge lp:~unity-team/unity8/dash-as-app | ||||||||||||||||||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Michał Sawicz | Approve | ||
Daniel d'Andrada (community) | Approve | ||
Review via email: mp+228534@code.launchpad.net |
Commit message
Split the dash from the shell into a separate app
Description of the change
### Notes for reviewers ###
* It depends on QtCompositor (silo 6). Alternatively this and qtcomp rc can be installed through ppa:unity-
* Adds an upstart script to autolaunch and respawn the dash app.
* Introduces a new plugin DashCommunicator which consists of a server and a client part, to be used to communicate between shell and dash.
* Adds a mock plugin for the DashCommunicator plugin
* Drops a whole bunch of useless stuff from MockApplication
* Adds a fake unity8-dash app (screenshot) to MockApplication
* Drops some code and tests for stages in/out dragging, given the dash is a regular app now, the stages are always visible now.
* Updates/simplifies shell and dash tests for the split app scenario.
* Does some slight updates to the Stages to keep the Dash behind the current app when not in spread mode so a left edge flick still shows the dash behind the app.
### Still TODO ###
* Make autopilot work again
### Checklist ###
* 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, works fine for me, except launching apps from dash and AP (see TODO section)
* Did you make sure that your branch does not contain spurious tags?
Yes.
* If you changed the packaging (debian), did you subscribe the ubuntu-unity team to this MP?
I added the additional binary and upstart script to installs, to be reviewed.
* If you changed the UI, has there been a design review?
Vesa is on holiday atm. I tried to keep UI changes as minimal as possible to fulfill the design request of adding the dash into the spread. So should be good I hope.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1130
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
"""
Q_SIGNALS:
void setCurrentScope
"""
Naming signals like functions is never a good thing. I would make an effort to name it like a signal. "requestedScope
Daniel d'Andrada (dandrader) wrote : | # |
> """
> Q_SIGNALS:
> void setCurrentScope
> """
>
> Naming signals like functions is never a good thing. I would make an effort to
> name it like a signal. "requestedScope
> "setCurrentScop
That's in DashCommunicato
Daniel d'Andrada (dandrader) wrote : | # |
Jouni says nothing should happen when you do a right-edge drag and there's no app running. That is, when you have just the dash).
Daniel d'Andrada (dandrader) wrote : | # |
1 - long press power button
<shutdown dialog shows up>
2 - press "Restart"
Expected outcome:
The device reboots
Actual outcome:
You see the dash being restarted behind the dialog and that's it.
Daniel d'Andrada (dandrader) wrote : | # |
1 - Launch an app or two
2 - go to the spread
3 - reveal the launcher
4 - tap on the ubuntu/dash icon
expected outcome:
Dash is focused
actual outcome:
Nothing happens
Michael Zanetti (mzanetti) wrote : | # |
> Jouni says nothing should happen when you do a right-edge drag and there's no
> app running. That is, when you have just the dash).
This doesn't line up with an explicit request from Vesa to not have any difference on the behavior regardless of the amount of apps.
Daniel d'Andrada (dandrader) wrote : | # |
> 1 - long press power button
> <shutdown dialog shows up>
> 2 - press "Restart"
>
> Expected outcome:
> The device reboots
>
> Actual outcome:
> You see the dash being restarted behind the dialog and that's it.
Hold on on that as it might be a general qtcomp issue :(
Michael Zanetti (mzanetti) wrote : | # |
> """
> Q_SIGNALS:
> void setCurrentScope
> """
>
> Naming signals like functions is never a good thing. I would make an effort to
> name it like a signal. "requestedScope
> "setCurrentScop
fixed
Michael Zanetti (mzanetti) wrote : | # |
> """
> Q_SIGNALS:
> void setCurrentScope
> """
>
> Naming signals like functions is never a good thing. I would make an effort to
> name it like a signal. "requestedScope
> "setCurrentScop
fixed
Michael Zanetti (mzanetti) wrote : | # |
> 1 - Launch an app or two
> 2 - go to the spread
> 3 - reveal the launcher
> 4 - tap on the ubuntu/dash icon
>
> expected outcome:
> Dash is focused
>
> actual outcome:
> Nothing happens
Hmm, this works fine for me on the phone and in testShell. Is there any log output when this issue happens for you?
Daniel d'Andrada (dandrader) wrote : | # |
> > 1 - Launch an app or two
> > 2 - go to the spread
> > 3 - reveal the launcher
> > 4 - tap on the ubuntu/dash icon
> >
> > expected outcome:
> > Dash is focused
> >
> > actual outcome:
> > Nothing happens
>
> Hmm, this works fine for me on the phone and in testShell. Is there any log
> output when this issue happens for you?
It works if an app is the currently focused app but not if unity8-dash itself is the focused guy
- have some apps open
- go to dash
- right-edge to show spread
- left-edge to show launcher
- tap dash button
Daniel d'Andrada (dandrader) wrote : | # |
Did you add a 0 bytes qml/Dash/
It would be good to save some kilobytes by making unity8-dash@12.png 480 pixels wide like all other screenshots. Afterall they're used only in a rather small windows in the qml tests.
Daniel d'Andrada (dandrader) wrote : | # |
> Did you add a 0 bytes qml/Dash/
>
> It would be good to save some kilobytes by making unity8-dash@12.png 480
> pixels wide like all other screenshots. Afterall they're used only in a rather
> small windows in the qml tests.
Btw, you would have to rewrite history to fix that, as otherwise we would end up with two images in the bzr history (leading to slower "bzr branch" commands), defeating the idea.
Daniel d'Andrada (dandrader) wrote : | # |
1 - have the greeter on (like turn the display off and on)
2 - do a full left-edge drag
expected outcome:
greeter goes away for goo
actual outcome:
greeter goes back into place
Daniel d'Andrada (dandrader) wrote : | # |
+++ qml/Stages/
@@ -116,6 +117,8 @@ Item {
contentX: -shift
+ readonly property bool isActive: shiftedContentX > 0 || spreadDragArea.
+
// The flickable needs to fill the screen in order to get touch events all over.
// However, we don't want to the user to be able to scroll back all the way. For
// that, the beginning of the gesture starts with a negative value for contentX
In QML (unlike in C++) boolean properties are named simply "foo", not "isFoo". I would choose a less overloaded/generic term than "active" if possible. What's the difference between being "active" and being "interactive". I would add a comment explaining what it means to be "active" there.
Daniel d'Andrada (dandrader) wrote : | # |
> +++ qml/Stages/
> @@ -116,6 +117,8 @@ Item {
> contentWidth: spreadRow.width - shift
> contentX: -shift
>
> + readonly property bool isActive: shiftedContentX > 0 ||
> spreadDragArea.
> +
> // The flickable needs to fill the screen in order to get touch
> events all over.
> // However, we don't want to the user to be able to scroll back all
> the way. For
> // that, the beginning of the gesture starts with a negative value
> for contentX
>
>
> In QML (unlike in C++) boolean properties are named simply "foo", not "isFoo".
> I would choose a less overloaded/generic term than "active" if possible.
> What's the difference between being "active" and being "interactive". I would
> add a comment explaining what it means to be "active" there.
Which doesn't apply here as "Dash" is not an adjective.
+ readonly property bool isDash: model.appId == "unity8-dash"
Daniel d'Andrada (dandrader) wrote : | # |
In SpreadDelegate.qml:
+ if (model.appId == "unity8-dash") {
That messes up with encapsulation. You should declare it a as SpreadDelegate property and fill it up in PhoneStage instead.
Daniel d'Andrada (dandrader) wrote : | # |
+ onIsActiveChanged: print("spreadView isActive changed", isActive)
Debug stuff in TabletStage.
Michael Zanetti (mzanetti) wrote : | # |
> > Did you add a 0 bytes qml/Dash/
> >
> > It would be good to save some kilobytes by making unity8-dash@12.png 480
> > pixels wide like all other screenshots. Afterall they're used only in a
> rather
> > small windows in the qml tests.
>
> Btw, you would have to rewrite history to fix that, as otherwise we would end
> up with two images in the bzr history (leading to slower "bzr branch"
> commands), defeating the idea.
fixed
Michael Zanetti (mzanetti) wrote : | # |
> 1 - have the greeter on (like turn the display off and on)
> 2 - do a full left-edge drag
>
> expected outcome:
> greeter goes away for goo
>
> actual outcome:
> greeter goes back into place
fixed
Michael Zanetti (mzanetti) wrote : | # |
> +++ qml/Stages/
> @@ -116,6 +117,8 @@ Item {
> contentWidth: spreadRow.width - shift
> contentX: -shift
>
> + readonly property bool isActive: shiftedContentX > 0 ||
> spreadDragArea.
> +
> // The flickable needs to fill the screen in order to get touch
> events all over.
> // However, we don't want to the user to be able to scroll back all
> the way. For
> // that, the beginning of the gesture starts with a negative value
> for contentX
>
>
> In QML (unlike in C++) boolean properties are named simply "foo", not "isFoo".
> I would choose a less overloaded/generic term than "active" if possible.
> What's the difference between being "active" and being "interactive". I would
> add a comment explaining what it means to be "active" there.
I added a comment. I tend to agree that the "is*" is quite uncommon for qml, however, as you realized yourself just "active" is a bit overloaded and I think isActive describes best what's happening. I kept the name but added a comment what it does.
Michael Zanetti (mzanetti) wrote : | # |
> In SpreadDelegate.qml:
> + if (model.appId == "unity8-dash") {
>
> That messes up with encapsulation. You should declare it a as SpreadDelegate
> property and fill it up in PhoneStage instead.
Well, its a "Delegate" so imo fine that it accesses model.* stuff. Also, there's quite a lot of other places where we access model.* stuff, fir instance model.surface.
Maybe this file could be split at some point to be a SpreadDelegate handling the model.stuff and then move the SurfaceContainer into a separate file that doesn't know anything about the model any more. IMO out of scope of this MP though.
Michael Zanetti (mzanetti) wrote : | # |
> + onIsActiveChanged: print("spreadView isActive changed", isActive)
>
> Debug stuff in TabletStage.
fixed
Michael Zanetti (mzanetti) wrote : | # |
> > > 1 - Launch an app or two
> > > 2 - go to the spread
> > > 3 - reveal the launcher
> > > 4 - tap on the ubuntu/dash icon
> > >
> > > expected outcome:
> > > Dash is focused
> > >
> > > actual outcome:
> > > Nothing happens
> >
> > Hmm, this works fine for me on the phone and in testShell. Is there any log
> > output when this issue happens for you?
>
> It works if an app is the currently focused app but not if unity8-dash itself
> is the focused guy
>
> - have some apps open
> - go to dash
> - right-edge to show spread
> - left-edge to show launcher
> - tap dash button
Fixed in here for the MockApplication
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1131
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Daniel d'Andrada (dandrader) wrote : | # |
In PhoneStage:
+ // Hiding tiles when their progress is negative or reached the maximum
+ visible: (progress >= 0 && progress < 1.7) ||
+ (model.appId == "unity8-dash" && priv.focusedApp
s/model.appId == "unity8-
Daniel d'Andrada (dandrader) wrote : | # |
> > In SpreadDelegate.qml:
> > + if (model.appId == "unity8-dash") {
> >
> > That messes up with encapsulation. You should declare it a as SpreadDelegate
> > property and fill it up in PhoneStage instead.
>
> Well, its a "Delegate" so imo fine that it accesses model.* stuff. Also,
> there's quite a lot of other places where we access model.* stuff, fir
> instance model.surface.
Makes it cumbersome at best to write a tst_SpreadDelegate for instance. But ok, I'm already changing that in the app lifecycle patch I'm working on top of yours so I can change that line there as well.
Michael Zanetti (mzanetti) wrote : | # |
> In PhoneStage:
>
> + // Hiding tiles when their progress is negative or
> reached the maximum
> + visible: (progress >= 0 && progress < 1.7) ||
> + (model.appId == "unity8-dash" &&
> priv.focusedApp
>
> s/model.appId == "unity8-
fixed
Daniel d'Andrada (dandrader) wrote : | # |
Looking good.
Thanks!
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1130
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michał Sawicz (saviq) wrote : | # |
FWIW, run_on_device will get quite broken with this. We need a think whether we can fix it quickly or do we need to leave it for later.
Michał Sawicz (saviq) wrote : | # |
Failure in qmltests:
qml/Dash/
- 1109. By Daniel d'Andrada
-
Merge trunk
[ Gerry Boland ]
* Fix the run.sh script - pretend to be running with qtmir and emit
SIGSTOP at the right time
[ Ying-Chun Liu ]
* Implement Attribute UI. (LP: #1282460)
[ Albert Astals ]
* Hide search history popup as soon as you start typing As discussed
with Mike and Saviq
* Compile with for scopes-v3 unity-api
* PageHeader: Unfocus search field when search entry is selected
* Show search field if the search query changes
* Test: Add a condition for art.height being > 0 means stuff has
already been layouted a bit without it it can happen that we get 0
for everything at startup and tests still pass
* Remove leftover in test of an old headerless implementation
[ Michael Zanetti ]
* Drop Recent apps category from Dash (LP: #1281092)
* update launcher count emblems to match new spec (LP: #1338984)
[ Bill Filler ]
* disable predictive text for dash search field (LP: #1340409)
[ CI bot ]
* Resync trunk
[ Antti Kaijanmäki ]
* DefaultIndicatorPage: use Loader status to determine the visible
property. (LP: #1350555)
[ Michael Terry ]
* Check user's pin/password using PAM, instead of a plaintext keyfile.
New build dependency: libpam0g-dev for phone unlock with PAM (LP:
#1234983)
[ Ubuntu daily release ]
* New rebuild forced - 1110. By Daniel d'Andrada
-
Update DashCommunicator mock plugin
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1130
http://
Executed test runs:
UNSTABLE: http://
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Michał Sawicz (saviq) wrote : | # |
All tests passed locally now.
Michał Sawicz (saviq) wrote : | # |
* Did you perform an exploratory manual test run of the code change and any related functionality?
Yes. Extensive testing in silo 7.
* Did CI run pass? If not, please explain why.
No, ap failures fixed in the prerequisite branch and unrelated qmltests failures otherwise.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1110
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2014-06-11 15:36:51 +0000 | |||
3 | +++ CMakeLists.txt 2014-08-05 11:53:58 +0000 | |||
4 | @@ -96,6 +96,7 @@ | |||
5 | 96 | declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/) | 96 | declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/) |
6 | 97 | 97 | ||
7 | 98 | set(SHELL_APP unity8) | 98 | set(SHELL_APP unity8) |
8 | 99 | set(DASH_APP unity8-dash) | ||
9 | 99 | set(SCOPE_TOOL unity-scope-tool) | 100 | set(SCOPE_TOOL unity-scope-tool) |
10 | 100 | 101 | ||
11 | 101 | include_directories( | 102 | include_directories( |
12 | 102 | 103 | ||
13 | === modified file 'data/CMakeLists.txt' | |||
14 | --- data/CMakeLists.txt 2014-06-11 15:36:51 +0000 | |||
15 | +++ data/CMakeLists.txt 2014-08-05 11:53:58 +0000 | |||
16 | @@ -1,7 +1,10 @@ | |||
18 | 1 | # generate desktop file | 1 | # generate desktop files |
19 | 2 | configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY) | 2 | configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY) |
20 | 3 | configure_file(${DASH_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop @ONLY) | ||
21 | 3 | 4 | ||
22 | 4 | # install desktop files | 5 | # install desktop files |
24 | 5 | install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop | 6 | install(FILES |
25 | 7 | ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop | ||
26 | 8 | ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop | ||
27 | 6 | DESTINATION ${CMAKE_INSTALL_DATADIR}/applications | 9 | DESTINATION ${CMAKE_INSTALL_DATADIR}/applications |
28 | 7 | ) | 10 | ) |
29 | 8 | 11 | ||
30 | === added file 'data/unity8-dash.conf' | |||
31 | --- data/unity8-dash.conf 1970-01-01 00:00:00 +0000 | |||
32 | +++ data/unity8-dash.conf 2014-08-05 11:53:58 +0000 | |||
33 | @@ -0,0 +1,22 @@ | |||
34 | 1 | description "Unity Shell v8 Dash" | ||
35 | 2 | author "Michael Zanetti <michael.zanetti@canonical.com>" | ||
36 | 3 | |||
37 | 4 | emits scope-ui-starting | ||
38 | 5 | |||
39 | 6 | start on started unity8 | ||
40 | 7 | stop on stopping unity8 | ||
41 | 8 | |||
42 | 9 | kill timeout 120 | ||
43 | 10 | |||
44 | 11 | respawn | ||
45 | 12 | |||
46 | 13 | pre-start script | ||
47 | 14 | if [ -z "$UNITY_SCOPES_LIST" ]; then | ||
48 | 15 | # FIXME: remove once we have this in dconf | ||
49 | 16 | initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator" | ||
50 | 17 | fi | ||
51 | 18 | |||
52 | 19 | initctl emit scope-ui-starting | ||
53 | 20 | end script | ||
54 | 21 | |||
55 | 22 | exec ${BINARY:-unity8-dash} $ARGS --desktop_file_hint=/usr/share/applications/unity8-dash.desktop | ||
56 | 0 | 23 | ||
57 | === added file 'data/unity8-dash.desktop.in' | |||
58 | --- data/unity8-dash.desktop.in 1970-01-01 00:00:00 +0000 | |||
59 | +++ data/unity8-dash.desktop.in 2014-08-05 11:53:58 +0000 | |||
60 | @@ -0,0 +1,9 @@ | |||
61 | 1 | [Desktop Entry] | ||
62 | 2 | Type=Application | ||
63 | 3 | Name=Unity 8 Dash | ||
64 | 4 | Comment=The converged Unity shell dash | ||
65 | 5 | Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8-dash | ||
66 | 6 | Terminal=false | ||
67 | 7 | Icon=unity8 | ||
68 | 8 | NoDisplay=true | ||
69 | 9 | X-Ubuntu-Touch=true | ||
70 | 0 | 10 | ||
71 | === modified file 'data/unity8.conf' | |||
72 | --- data/unity8.conf 2014-07-18 16:40:56 +0000 | |||
73 | +++ data/unity8.conf 2014-08-05 11:53:58 +0000 | |||
74 | @@ -1,7 +1,7 @@ | |||
75 | 1 | description "Unity Shell v8" | 1 | description "Unity Shell v8" |
76 | 2 | author "Ricardo Mendoza <ricmm@ubuntu.com>" | 2 | author "Ricardo Mendoza <ricmm@ubuntu.com>" |
77 | 3 | 3 | ||
79 | 4 | emits scope-ui-starting indicator-services-start | 4 | emits indicator-services-start |
80 | 5 | 5 | ||
81 | 6 | start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=ubuntu-touch-surfaceflinger)) and started dbus | 6 | start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=ubuntu-touch-surfaceflinger)) and started dbus |
82 | 7 | stop on desktop-end | 7 | stop on desktop-end |
83 | @@ -34,11 +34,6 @@ | |||
84 | 34 | gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}" | 34 | gdbus call --session --dest org.freedesktop.DBus --object-path /org/freedesktop/DBus --method org.freedesktop.DBus.UpdateActivationEnvironment "@a{ss} {'MIR_SOCKET': '$MIR_SERVER_FILE'}" |
85 | 35 | fi | 35 | fi |
86 | 36 | 36 | ||
87 | 37 | if [ -z "$UNITY_SCOPES_LIST" ]; then | ||
88 | 38 | # FIXME: remove once we have this in dconf | ||
89 | 39 | initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator" | ||
90 | 40 | fi | ||
91 | 41 | |||
92 | 42 | # Remove the socket if still there | 37 | # Remove the socket if still there |
93 | 43 | if [ -S "$MIR_SERVER_FILE" ]; then | 38 | if [ -S "$MIR_SERVER_FILE" ]; then |
94 | 44 | rm "$MIR_SERVER_FILE" | 39 | rm "$MIR_SERVER_FILE" |
95 | @@ -46,7 +41,6 @@ | |||
96 | 46 | 41 | ||
97 | 47 | initctl set-env --global MIR_SERVER_PROMPT_FILE=1 | 42 | initctl set-env --global MIR_SERVER_PROMPT_FILE=1 |
98 | 48 | 43 | ||
99 | 49 | initctl emit scope-ui-starting | ||
100 | 50 | initctl emit --no-wait indicator-services-start | 44 | initctl emit --no-wait indicator-services-start |
101 | 51 | end script | 45 | end script |
102 | 52 | 46 | ||
103 | 53 | 47 | ||
104 | === modified file 'debian/unity8.install' | |||
105 | --- debian/unity8.install 2014-07-08 18:53:52 +0000 | |||
106 | +++ debian/unity8.install 2014-08-05 11:53:58 +0000 | |||
107 | @@ -1,6 +1,9 @@ | |||
108 | 1 | data/unity8.conf usr/share/upstart/sessions/ | 1 | data/unity8.conf usr/share/upstart/sessions/ |
109 | 2 | data/unity8-dash.conf usr/share/upstart/sessions/ | ||
110 | 2 | usr/bin/unity8 | 3 | usr/bin/unity8 |
111 | 4 | usr/bin/unity8-dash | ||
112 | 3 | usr/share/applications/unity8.desktop | 5 | usr/share/applications/unity8.desktop |
113 | 6 | usr/share/applications/unity8-dash.desktop | ||
114 | 4 | usr/share/unity8/Greeter | 7 | usr/share/unity8/Greeter |
115 | 5 | usr/share/unity8/Hud | 8 | usr/share/unity8/Hud |
116 | 6 | usr/share/unity8/Launcher | 9 | usr/share/unity8/Launcher |
117 | 7 | 10 | ||
118 | === modified file 'plugins/Unity/CMakeLists.txt' | |||
119 | --- plugins/Unity/CMakeLists.txt 2014-07-08 19:09:35 +0000 | |||
120 | +++ plugins/Unity/CMakeLists.txt 2014-08-05 11:53:58 +0000 | |||
121 | @@ -1,3 +1,4 @@ | |||
122 | 1 | add_subdirectory(Indicators) | 1 | add_subdirectory(Indicators) |
123 | 2 | add_subdirectory(Launcher) | 2 | add_subdirectory(Launcher) |
124 | 3 | add_subdirectory(Session) | 3 | add_subdirectory(Session) |
125 | 4 | add_subdirectory(DashCommunicator) | ||
126 | 4 | 5 | ||
127 | === added directory 'plugins/Unity/DashCommunicator' | |||
128 | === added file 'plugins/Unity/DashCommunicator/CMakeLists.txt' | |||
129 | --- plugins/Unity/DashCommunicator/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
130 | +++ plugins/Unity/DashCommunicator/CMakeLists.txt 2014-08-05 11:53:58 +0000 | |||
131 | @@ -0,0 +1,19 @@ | |||
132 | 1 | include_directories( | ||
133 | 2 | ${CMAKE_CURRENT_SOURCE_DIR} | ||
134 | 3 | ) | ||
135 | 4 | |||
136 | 5 | set(QMLDASHCOMMUNICATORPLUGIN_SRC | ||
137 | 6 | plugin.cpp | ||
138 | 7 | dbusdashcommunicatorservice.cpp | ||
139 | 8 | dashcommunicatorservice.cpp | ||
140 | 9 | dashcommunicator.cpp | ||
141 | 10 | ) | ||
142 | 11 | |||
143 | 12 | add_library(DashCommunicator-qml MODULE | ||
144 | 13 | ${QMLDASHCOMMUNICATORPLUGIN_SRC} | ||
145 | 14 | ) | ||
146 | 15 | |||
147 | 16 | qt5_use_modules(DashCommunicator-qml DBus Qml) | ||
148 | 17 | |||
149 | 18 | # export the qmldir and qmltypes files | ||
150 | 19 | add_unity8_plugin(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS DashCommunicator-qml) | ||
151 | 0 | 20 | ||
152 | === added file 'plugins/Unity/DashCommunicator/dashcommunicator.cpp' | |||
153 | --- plugins/Unity/DashCommunicator/dashcommunicator.cpp 1970-01-01 00:00:00 +0000 | |||
154 | +++ plugins/Unity/DashCommunicator/dashcommunicator.cpp 2014-08-05 11:53:58 +0000 | |||
155 | @@ -0,0 +1,43 @@ | |||
156 | 1 | /* | ||
157 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
158 | 3 | * | ||
159 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
160 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
161 | 6 | * the Free Software Foundation. | ||
162 | 7 | * | ||
163 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
164 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
165 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
166 | 11 | * Lesser General Public License for more details. | ||
167 | 12 | * | ||
168 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
169 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
170 | 15 | */ | ||
171 | 16 | |||
172 | 17 | #include "dashcommunicator.h" | ||
173 | 18 | |||
174 | 19 | #include <QObject> | ||
175 | 20 | #include <QDBusConnection> | ||
176 | 21 | #include <QDBusInterface> | ||
177 | 22 | #include <QDebug> | ||
178 | 23 | |||
179 | 24 | DashCommunicator::DashCommunicator(QObject *parent): | ||
180 | 25 | QObject(parent) | ||
181 | 26 | { | ||
182 | 27 | } | ||
183 | 28 | |||
184 | 29 | DashCommunicator::~DashCommunicator() | ||
185 | 30 | { | ||
186 | 31 | } | ||
187 | 32 | |||
188 | 33 | |||
189 | 34 | void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset) | ||
190 | 35 | { | ||
191 | 36 | QDBusConnection connection = QDBusConnection::sessionBus(); | ||
192 | 37 | QDBusInterface dashIface ("com.canonical.UnityDash", | ||
193 | 38 | "/com/canonical/UnityDash", | ||
194 | 39 | "", | ||
195 | 40 | connection); | ||
196 | 41 | |||
197 | 42 | dashIface.call("SetCurrentScope", scopeId, animate, reset); | ||
198 | 43 | } | ||
199 | 0 | 44 | ||
200 | === added file 'plugins/Unity/DashCommunicator/dashcommunicator.h' | |||
201 | --- plugins/Unity/DashCommunicator/dashcommunicator.h 1970-01-01 00:00:00 +0000 | |||
202 | +++ plugins/Unity/DashCommunicator/dashcommunicator.h 2014-08-05 11:53:58 +0000 | |||
203 | @@ -0,0 +1,35 @@ | |||
204 | 1 | /* | ||
205 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
206 | 3 | * | ||
207 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
208 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
209 | 6 | * the Free Software Foundation. | ||
210 | 7 | * | ||
211 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
212 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
213 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
214 | 11 | * Lesser General Public License for more details. | ||
215 | 12 | * | ||
216 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
217 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
218 | 15 | */ | ||
219 | 16 | |||
220 | 17 | #ifndef DASHCOMMUNICATOR_H | ||
221 | 18 | #define DASHCOMMUNICATOR_H | ||
222 | 19 | |||
223 | 20 | #include <QObject> | ||
224 | 21 | |||
225 | 22 | class DashCommunicator: public QObject | ||
226 | 23 | { | ||
227 | 24 | Q_OBJECT | ||
228 | 25 | Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator") | ||
229 | 26 | |||
230 | 27 | public: | ||
231 | 28 | DashCommunicator(QObject *parent = 0); | ||
232 | 29 | ~DashCommunicator(); | ||
233 | 30 | |||
234 | 31 | public Q_SLOTS: | ||
235 | 32 | void setCurrentScope(const QString &scopeId, bool animate, bool reset); | ||
236 | 33 | }; | ||
237 | 34 | |||
238 | 35 | #endif | ||
239 | 0 | 36 | ||
240 | === added file 'plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp' | |||
241 | --- plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp 1970-01-01 00:00:00 +0000 | |||
242 | +++ plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp 2014-08-05 11:53:58 +0000 | |||
243 | @@ -0,0 +1,30 @@ | |||
244 | 1 | /* | ||
245 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
246 | 3 | * | ||
247 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
248 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
249 | 6 | * the Free Software Foundation. | ||
250 | 7 | * | ||
251 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
252 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
253 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
254 | 11 | * Lesser General Public License for more details. | ||
255 | 12 | * | ||
256 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
257 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
258 | 15 | */ | ||
259 | 16 | |||
260 | 17 | #include "dashcommunicatorservice.h" | ||
261 | 18 | |||
262 | 19 | DashCommunicatorService::DashCommunicatorService(QObject *parent): | ||
263 | 20 | QObject(parent), | ||
264 | 21 | m_dbusService(new DBusDashCommunicatorService(this)) | ||
265 | 22 | { | ||
266 | 23 | connect(m_dbusService, &DBusDashCommunicatorService::setCurrentScopeRequested, this, &DashCommunicatorService::setCurrentScopeRequested); | ||
267 | 24 | } | ||
268 | 25 | |||
269 | 26 | |||
270 | 27 | DashCommunicatorService::~DashCommunicatorService() | ||
271 | 28 | { | ||
272 | 29 | |||
273 | 30 | } | ||
274 | 0 | 31 | ||
275 | === added file 'plugins/Unity/DashCommunicator/dashcommunicatorservice.h' | |||
276 | --- plugins/Unity/DashCommunicator/dashcommunicatorservice.h 1970-01-01 00:00:00 +0000 | |||
277 | +++ plugins/Unity/DashCommunicator/dashcommunicatorservice.h 2014-08-05 11:53:58 +0000 | |||
278 | @@ -0,0 +1,38 @@ | |||
279 | 1 | /* | ||
280 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
281 | 3 | * | ||
282 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
283 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
284 | 6 | * the Free Software Foundation. | ||
285 | 7 | * | ||
286 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
287 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
288 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
289 | 11 | * Lesser General Public License for more details. | ||
290 | 12 | * | ||
291 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
292 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
293 | 15 | */ | ||
294 | 16 | |||
295 | 17 | #ifndef DASHCOMMUNICATORSERVICE_H | ||
296 | 18 | #define DASHCOMMUNICATORSERVICE_H | ||
297 | 19 | |||
298 | 20 | #include "dbusdashcommunicatorservice.h" | ||
299 | 21 | |||
300 | 22 | #include <QObject> | ||
301 | 23 | |||
302 | 24 | class DashCommunicatorService: public QObject | ||
303 | 25 | { | ||
304 | 26 | Q_OBJECT | ||
305 | 27 | public: | ||
306 | 28 | DashCommunicatorService(QObject *parent = 0); | ||
307 | 29 | ~DashCommunicatorService(); | ||
308 | 30 | |||
309 | 31 | Q_SIGNALS: | ||
310 | 32 | void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset); | ||
311 | 33 | |||
312 | 34 | private: | ||
313 | 35 | DBusDashCommunicatorService *m_dbusService; | ||
314 | 36 | }; | ||
315 | 37 | |||
316 | 38 | #endif // DBUSUNITYSESSIONSERVICE_H | ||
317 | 0 | 39 | ||
318 | === added file 'plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp' | |||
319 | --- plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp 1970-01-01 00:00:00 +0000 | |||
320 | +++ plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp 2014-08-05 11:53:58 +0000 | |||
321 | @@ -0,0 +1,39 @@ | |||
322 | 1 | /* | ||
323 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
324 | 3 | * | ||
325 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
326 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
327 | 6 | * the Free Software Foundation. | ||
328 | 7 | * | ||
329 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
330 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
331 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
332 | 11 | * Lesser General Public License for more details. | ||
333 | 12 | * | ||
334 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
335 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
336 | 15 | */ | ||
337 | 16 | |||
338 | 17 | #include "dbusdashcommunicatorservice.h" | ||
339 | 18 | |||
340 | 19 | #include <QDBusConnection> | ||
341 | 20 | #include <QDBusInterface> | ||
342 | 21 | #include <QDebug> | ||
343 | 22 | |||
344 | 23 | DBusDashCommunicatorService::DBusDashCommunicatorService(QObject *parent): | ||
345 | 24 | QObject(parent) | ||
346 | 25 | { | ||
347 | 26 | QDBusConnection connection = QDBusConnection::sessionBus(); | ||
348 | 27 | |||
349 | 28 | connection.registerService("com.canonical.UnityDash"); | ||
350 | 29 | connection.registerObject("/com/canonical/UnityDash", this, QDBusConnection::ExportScriptableSlots); | ||
351 | 30 | } | ||
352 | 31 | |||
353 | 32 | DBusDashCommunicatorService::~DBusDashCommunicatorService() | ||
354 | 33 | { | ||
355 | 34 | } | ||
356 | 35 | |||
357 | 36 | void DBusDashCommunicatorService::SetCurrentScope(const QString &scopeId, bool animate, bool reset) | ||
358 | 37 | { | ||
359 | 38 | Q_EMIT setCurrentScopeRequested(scopeId, animate, reset); | ||
360 | 39 | } | ||
361 | 0 | 40 | ||
362 | === added file 'plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h' | |||
363 | --- plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h 1970-01-01 00:00:00 +0000 | |||
364 | +++ plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h 2014-08-05 11:53:58 +0000 | |||
365 | @@ -0,0 +1,39 @@ | |||
366 | 1 | /* | ||
367 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
368 | 3 | * | ||
369 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
370 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
371 | 6 | * the Free Software Foundation. | ||
372 | 7 | * | ||
373 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
374 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
375 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
376 | 11 | * Lesser General Public License for more details. | ||
377 | 12 | * | ||
378 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
379 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
380 | 15 | */ | ||
381 | 16 | |||
382 | 17 | #ifndef DBUSDASHCOMMUNICATORSERVICE_H | ||
383 | 18 | #define DBUSDASHCOMMUNICATORSERVICE_H | ||
384 | 19 | |||
385 | 20 | #include <QObject> | ||
386 | 21 | |||
387 | 22 | class DBusDashCommunicatorService: public QObject | ||
388 | 23 | { | ||
389 | 24 | Q_OBJECT | ||
390 | 25 | Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator") | ||
391 | 26 | |||
392 | 27 | public: | ||
393 | 28 | DBusDashCommunicatorService(QObject *parent = 0); | ||
394 | 29 | ~DBusDashCommunicatorService(); | ||
395 | 30 | |||
396 | 31 | Q_SIGNALS: | ||
397 | 32 | void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset); | ||
398 | 33 | |||
399 | 34 | public Q_SLOTS: | ||
400 | 35 | Q_SCRIPTABLE void SetCurrentScope(const QString &scopeId, bool animate, bool reset); | ||
401 | 36 | |||
402 | 37 | }; | ||
403 | 38 | |||
404 | 39 | #endif // DBUSUNITYSESSIONSERVICE_H | ||
405 | 0 | 40 | ||
406 | === added file 'plugins/Unity/DashCommunicator/plugin.cpp' | |||
407 | --- plugins/Unity/DashCommunicator/plugin.cpp 1970-01-01 00:00:00 +0000 | |||
408 | +++ plugins/Unity/DashCommunicator/plugin.cpp 2014-08-05 11:53:58 +0000 | |||
409 | @@ -0,0 +1,31 @@ | |||
410 | 1 | /* | ||
411 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
412 | 3 | * | ||
413 | 4 | * This program is free software; you can redistribute it and/or modify | ||
414 | 5 | * it under the terms of the GNU General Public License as published by | ||
415 | 6 | * the Free Software Foundation; version 3. | ||
416 | 7 | * | ||
417 | 8 | * This program is distributed in the hope that it will be useful, | ||
418 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
419 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
420 | 11 | * GNU General Public License for more details. | ||
421 | 12 | * | ||
422 | 13 | * You should have received a copy of the GNU General Public License | ||
423 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
424 | 15 | * | ||
425 | 16 | * Authors: Michael Zanetti <michael.zanetti@canonical.com> | ||
426 | 17 | */ | ||
427 | 18 | |||
428 | 19 | #include "plugin.h" | ||
429 | 20 | #include "dashcommunicator.h" | ||
430 | 21 | #include "dashcommunicatorservice.h" | ||
431 | 22 | |||
432 | 23 | #include <QDBusConnection> | ||
433 | 24 | #include <QtQml/qqml.h> | ||
434 | 25 | |||
435 | 26 | void DashCommunicatorPlugin::registerTypes(const char *uri) | ||
436 | 27 | { | ||
437 | 28 | Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator")); | ||
438 | 29 | qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService"); | ||
439 | 30 | qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator"); | ||
440 | 31 | } | ||
441 | 0 | 32 | ||
442 | === added file 'plugins/Unity/DashCommunicator/plugin.h' | |||
443 | --- plugins/Unity/DashCommunicator/plugin.h 1970-01-01 00:00:00 +0000 | |||
444 | +++ plugins/Unity/DashCommunicator/plugin.h 2014-08-05 11:53:58 +0000 | |||
445 | @@ -0,0 +1,34 @@ | |||
446 | 1 | /* | ||
447 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
448 | 3 | * | ||
449 | 4 | * This program is free software; you can redistribute it and/or modify | ||
450 | 5 | * it under the terms of the GNU General Public License as published by | ||
451 | 6 | * the Free Software Foundation; version 3. | ||
452 | 7 | * | ||
453 | 8 | * This program is distributed in the hope that it will be useful, | ||
454 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
455 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
456 | 11 | * GNU General Public License for more details. | ||
457 | 12 | * | ||
458 | 13 | * You should have received a copy of the GNU General Public License | ||
459 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
460 | 15 | * | ||
461 | 16 | * Authors: Michael Zanetti <michael.zanetti@canonical.com> | ||
462 | 17 | */ | ||
463 | 18 | |||
464 | 19 | #ifndef DASHCOMMUNICATOR_PLUGIN_H | ||
465 | 20 | #define DASHCOMMUNICATOR_PLUGIN_H | ||
466 | 21 | |||
467 | 22 | #include <QtQml/QQmlEngine> | ||
468 | 23 | #include <QtQml/QQmlExtensionPlugin> | ||
469 | 24 | |||
470 | 25 | class DashCommunicatorPlugin : public QQmlExtensionPlugin | ||
471 | 26 | { | ||
472 | 27 | Q_OBJECT | ||
473 | 28 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") | ||
474 | 29 | |||
475 | 30 | public: | ||
476 | 31 | void registerTypes(const char *uri); | ||
477 | 32 | }; | ||
478 | 33 | |||
479 | 34 | #endif | ||
480 | 0 | 35 | ||
481 | === added file 'plugins/Unity/DashCommunicator/qmldir' | |||
482 | --- plugins/Unity/DashCommunicator/qmldir 1970-01-01 00:00:00 +0000 | |||
483 | +++ plugins/Unity/DashCommunicator/qmldir 2014-08-05 11:53:58 +0000 | |||
484 | @@ -0,0 +1,3 @@ | |||
485 | 1 | module Unity.DashCommunicator | ||
486 | 2 | plugin DashCommunicator-qml | ||
487 | 3 | typeinfo DashCommunicator.qmltypes | ||
488 | 0 | 4 | ||
489 | === modified file 'plugins/Unity/Launcher/launchermodel.cpp' | |||
490 | --- plugins/Unity/Launcher/launchermodel.cpp 2014-07-25 11:29:56 +0000 | |||
491 | +++ plugins/Unity/Launcher/launchermodel.cpp 2014-08-05 11:53:58 +0000 | |||
492 | @@ -317,6 +317,11 @@ | |||
493 | 317 | return; | 317 | return; |
494 | 318 | } | 318 | } |
495 | 319 | 319 | ||
496 | 320 | if (app->appId() == "unity8-dash") { | ||
497 | 321 | // Not adding the dash app | ||
498 | 322 | return; | ||
499 | 323 | } | ||
500 | 324 | |||
501 | 320 | bool found = false; | 325 | bool found = false; |
502 | 321 | Q_FOREACH(LauncherItem *item, m_list) { | 326 | Q_FOREACH(LauncherItem *item, m_list) { |
503 | 322 | if (app->appId() == item->appId()) { | 327 | if (app->appId() == item->appId()) { |
504 | 323 | 328 | ||
505 | === modified file 'qml/Components/EdgeDemo.qml' | |||
506 | --- qml/Components/EdgeDemo.qml 2014-06-11 15:36:51 +0000 | |||
507 | +++ qml/Components/EdgeDemo.qml 2014-08-05 11:53:58 +0000 | |||
508 | @@ -22,7 +22,6 @@ | |||
509 | 22 | id: demo | 22 | id: demo |
510 | 23 | 23 | ||
511 | 24 | property Item greeter | 24 | property Item greeter |
512 | 25 | property Item dash | ||
513 | 26 | property Item launcher | 25 | property Item launcher |
514 | 27 | property Item indicators | 26 | property Item indicators |
515 | 28 | property Item underlay | 27 | property Item underlay |
516 | @@ -144,7 +143,7 @@ | |||
517 | 144 | "edge": "top", | 143 | "edge": "top", |
518 | 145 | "title": i18n.tr("Top edge"), | 144 | "title": i18n.tr("Top edge"), |
519 | 146 | "text": i18n.tr("Try swiping from the top edge to access the indicators"), | 145 | "text": i18n.tr("Try swiping from the top edge to access the indicators"), |
521 | 147 | "anchors.fill": demo.dash, | 146 | "anchors.fill": demo.underlay, |
522 | 148 | }); | 147 | }); |
523 | 149 | } | 148 | } |
524 | 150 | if (d.topEdgeDemo) { | 149 | if (d.topEdgeDemo) { |
525 | @@ -193,12 +192,12 @@ | |||
526 | 193 | function startLeftEdgeDemo() { | 192 | function startLeftEdgeDemo() { |
527 | 194 | demo.panelEnabled = false; | 193 | demo.panelEnabled = false; |
528 | 195 | demo.launcherEnabled = true; | 194 | demo.launcherEnabled = true; |
530 | 196 | if (demo.dash && demo.underlay) { | 195 | if (demo.underlay) { |
531 | 197 | d.leftEdgeDemo = d.overlay.createObject(demo.underlay, { | 196 | d.leftEdgeDemo = d.overlay.createObject(demo.underlay, { |
532 | 198 | "edge": "left", | 197 | "edge": "left", |
533 | 199 | "title": i18n.tr("Left edge"), | 198 | "title": i18n.tr("Left edge"), |
534 | 200 | "text": i18n.tr("Swipe from the left to reveal the launcher for quick access to apps"), | 199 | "text": i18n.tr("Swipe from the left to reveal the launcher for quick access to apps"), |
536 | 201 | "anchors.fill": demo.dash, | 200 | "anchors.fill": demo.underlay, |
537 | 202 | }); | 201 | }); |
538 | 203 | } | 202 | } |
539 | 204 | if (d.leftEdgeDemo) { | 203 | if (d.leftEdgeDemo) { |
540 | @@ -221,12 +220,12 @@ | |||
541 | 221 | 220 | ||
542 | 222 | function startFinalEdgeDemo() { | 221 | function startFinalEdgeDemo() { |
543 | 223 | demo.launcherEnabled = false; | 222 | demo.launcherEnabled = false; |
545 | 224 | if (demo.dash && demo.underlay) { | 223 | if (demo.underlay) { |
546 | 225 | d.finalEdgeDemo = d.overlay.createObject(demo.underlay, { | 224 | d.finalEdgeDemo = d.overlay.createObject(demo.underlay, { |
547 | 226 | "edge": "none", | 225 | "edge": "none", |
548 | 227 | "title": i18n.tr("Well done"), | 226 | "title": i18n.tr("Well done"), |
549 | 228 | "text": i18n.tr("You have now mastered the edge gestures and can start using the phone<br><br>Tap on the screen to start"), | 227 | "text": i18n.tr("You have now mastered the edge gestures and can start using the phone<br><br>Tap on the screen to start"), |
551 | 229 | "anchors.fill": demo.dash, | 228 | "anchors.fill": demo.underlay, |
552 | 230 | "showSkip": false, | 229 | "showSkip": false, |
553 | 231 | }); | 230 | }); |
554 | 232 | } | 231 | } |
555 | 233 | 232 | ||
556 | === modified file 'qml/Dash/Dash.qml' | |||
557 | --- qml/Dash/Dash.qml 2014-07-10 09:27:19 +0000 | |||
558 | +++ qml/Dash/Dash.qml 2014-08-05 11:53:58 +0000 | |||
559 | @@ -18,6 +18,7 @@ | |||
560 | 18 | import Ubuntu.Components 0.1 | 18 | import Ubuntu.Components 0.1 |
561 | 19 | import Unity 0.2 | 19 | import Unity 0.2 |
562 | 20 | import Utils 0.1 | 20 | import Utils 0.1 |
563 | 21 | import Unity.DashCommunicator 0.1 | ||
564 | 21 | import "../Components" | 22 | import "../Components" |
565 | 22 | 23 | ||
566 | 23 | Showable { | 24 | Showable { |
567 | @@ -29,6 +30,13 @@ | |||
568 | 29 | property string showScopeOnLoaded: "clickscope" | 30 | property string showScopeOnLoaded: "clickscope" |
569 | 30 | property real contentScale: 1.0 | 31 | property real contentScale: 1.0 |
570 | 31 | 32 | ||
571 | 33 | DashCommunicatorService { | ||
572 | 34 | objectName: "dashCommunicatorService" | ||
573 | 35 | onSetCurrentScopeRequested: { | ||
574 | 36 | dash.setCurrentScope(scopeId, animate, reset) | ||
575 | 37 | } | ||
576 | 38 | } | ||
577 | 39 | |||
578 | 32 | function setCurrentScope(scopeId, animate, reset) { | 40 | function setCurrentScope(scopeId, animate, reset) { |
579 | 33 | var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId) | 41 | var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId) |
580 | 34 | 42 | ||
581 | 35 | 43 | ||
582 | === added file 'qml/Dash/DashApplication.qml' | |||
583 | --- qml/Dash/DashApplication.qml 1970-01-01 00:00:00 +0000 | |||
584 | +++ qml/Dash/DashApplication.qml 2014-08-05 11:53:58 +0000 | |||
585 | @@ -0,0 +1,29 @@ | |||
586 | 1 | /* | ||
587 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
588 | 3 | * | ||
589 | 4 | * This program is free software; you can redistribute it and/or modify | ||
590 | 5 | * it under the terms of the GNU General Public License as published by | ||
591 | 6 | * the Free Software Foundation; version 3. | ||
592 | 7 | * | ||
593 | 8 | * This program is distributed in the hope that it will be useful, | ||
594 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
595 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
596 | 11 | * GNU General Public License for more details. | ||
597 | 12 | * | ||
598 | 13 | * You should have received a copy of the GNU General Public License | ||
599 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
600 | 15 | */ | ||
601 | 16 | |||
602 | 17 | import QtQuick 2.2 | ||
603 | 18 | import Ubuntu.Components 1.0 | ||
604 | 19 | |||
605 | 20 | MainView { | ||
606 | 21 | width: units.gu(40) | ||
607 | 22 | height: units.gu(71) | ||
608 | 23 | |||
609 | 24 | useDeprecatedToolbar: false | ||
610 | 25 | |||
611 | 26 | Dash { | ||
612 | 27 | anchors.fill: parent | ||
613 | 28 | } | ||
614 | 29 | } | ||
615 | 0 | 30 | ||
616 | === modified file 'qml/Dash/GenericScopeView.qml' | |||
617 | --- qml/Dash/GenericScopeView.qml 2014-07-25 11:49:28 +0000 | |||
618 | +++ qml/Dash/GenericScopeView.qml 2014-08-05 11:53:58 +0000 | |||
619 | @@ -46,7 +46,7 @@ | |||
620 | 46 | } | 46 | } |
621 | 47 | 47 | ||
622 | 48 | function activateApp(appId) { | 48 | function activateApp(appId) { |
624 | 49 | shell.activateApplication(appId); | 49 | Qt.openUrlExternally(appId); |
625 | 50 | } | 50 | } |
626 | 51 | 51 | ||
627 | 52 | function positionAtBeginning() { | 52 | function positionAtBeginning() { |
628 | 53 | 53 | ||
629 | === modified file 'qml/Dash/ScopeListView.qml' | |||
630 | --- qml/Dash/ScopeListView.qml 2014-06-11 15:36:51 +0000 | |||
631 | +++ qml/Dash/ScopeListView.qml 2014-08-05 11:53:58 +0000 | |||
632 | @@ -20,9 +20,4 @@ | |||
633 | 20 | ListViewWithPageHeader { | 20 | ListViewWithPageHeader { |
634 | 21 | maximumFlickVelocity: height * 10 | 21 | maximumFlickVelocity: height * 10 |
635 | 22 | flickDeceleration: height * 2 | 22 | flickDeceleration: height * 2 |
636 | 23 | |||
637 | 24 | Connections { | ||
638 | 25 | target: greeter | ||
639 | 26 | onShownChanged: if (greeter.shown) showHeader() | ||
640 | 27 | } | ||
641 | 28 | } | 23 | } |
642 | 29 | 24 | ||
643 | === added file 'qml/Dash/graphics/phone/screenshots/unity8-dash@12.png' | |||
644 | 30 | Binary files qml/Dash/graphics/phone/screenshots/unity8-dash@12.png 1970-01-01 00:00:00 +0000 and qml/Dash/graphics/phone/screenshots/unity8-dash@12.png 2014-08-05 11:53:58 +0000 differ | 25 | Binary files qml/Dash/graphics/phone/screenshots/unity8-dash@12.png 1970-01-01 00:00:00 +0000 and qml/Dash/graphics/phone/screenshots/unity8-dash@12.png 2014-08-05 11:53:58 +0000 differ |
645 | === modified file 'qml/Launcher/Launcher.qml' | |||
646 | --- qml/Launcher/Launcher.qml 2014-07-16 13:01:08 +0000 | |||
647 | +++ qml/Launcher/Launcher.qml 2014-08-05 11:53:58 +0000 | |||
648 | @@ -29,8 +29,7 @@ | |||
649 | 29 | property int dragAreaWidth: units.gu(1) | 29 | property int dragAreaWidth: units.gu(1) |
650 | 30 | property int minimizeDistance: units.gu(26) | 30 | property int minimizeDistance: units.gu(26) |
651 | 31 | property real progress: dragArea.dragging && dragArea.touchX > panelWidth ? | 31 | property real progress: dragArea.dragging && dragArea.touchX > panelWidth ? |
654 | 32 | (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : | 32 | (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : 0 |
653 | 33 | (dragArea.dragging ? 0.001 : 0) | ||
655 | 34 | 33 | ||
656 | 35 | readonly property bool shown: panel.x > -panel.width | 34 | readonly property bool shown: panel.x > -panel.width |
657 | 36 | 35 | ||
658 | @@ -245,7 +244,7 @@ | |||
659 | 245 | if (!dragging) { | 244 | if (!dragging) { |
660 | 246 | if (distance > panel.width / 2) { | 245 | if (distance > panel.width / 2) { |
661 | 247 | if (distance > minimizeDistance) { | 246 | if (distance > minimizeDistance) { |
663 | 248 | root.dash() | 247 | root.dash(); |
664 | 249 | } else { | 248 | } else { |
665 | 250 | root.switchToNextState("visible") | 249 | root.switchToNextState("visible") |
666 | 251 | } | 250 | } |
667 | 252 | 251 | ||
668 | === modified file 'qml/Shell.qml' | |||
669 | --- qml/Shell.qml 2014-07-29 23:36:16 +0000 | |||
670 | +++ qml/Shell.qml 2014-08-05 11:53:58 +0000 | |||
671 | @@ -25,7 +25,6 @@ | |||
672 | 25 | import LightDM 0.1 as LightDM | 25 | import LightDM 0.1 as LightDM |
673 | 26 | import Powerd 0.1 | 26 | import Powerd 0.1 |
674 | 27 | import SessionBroadcast 0.1 | 27 | import SessionBroadcast 0.1 |
675 | 28 | import "Dash" | ||
676 | 29 | import "Greeter" | 28 | import "Greeter" |
677 | 30 | import "Launcher" | 29 | import "Launcher" |
678 | 31 | import "Panel" | 30 | import "Panel" |
679 | @@ -34,6 +33,7 @@ | |||
680 | 34 | import "Stages" | 33 | import "Stages" |
681 | 35 | import Unity.Notifications 1.0 as NotificationBackend | 34 | import Unity.Notifications 1.0 as NotificationBackend |
682 | 36 | import Unity.Session 0.1 | 35 | import Unity.Session 0.1 |
683 | 36 | import Unity.DashCommunicator 0.1 | ||
684 | 37 | 37 | ||
685 | 38 | Item { | 38 | Item { |
686 | 39 | id: shell | 39 | id: shell |
687 | @@ -48,8 +48,6 @@ | |||
688 | 48 | property url background | 48 | property url background |
689 | 49 | readonly property real panelHeight: panel.panelHeight | 49 | readonly property real panelHeight: panel.panelHeight |
690 | 50 | 50 | ||
691 | 51 | property bool dashShown: dash.shown && dash.available && underlay.visible | ||
692 | 52 | |||
693 | 53 | property bool sideStageEnabled: shell.width >= units.gu(100) | 51 | property bool sideStageEnabled: shell.width >= units.gu(100) |
694 | 54 | readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId | 52 | readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId |
695 | 55 | 53 | ||
696 | @@ -59,7 +57,6 @@ | |||
697 | 59 | } else { | 57 | } else { |
698 | 60 | var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage; | 58 | var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage; |
699 | 61 | ApplicationManager.startApplication(appId, execFlags); | 59 | ApplicationManager.startApplication(appId, execFlags); |
700 | 62 | stages.show(); | ||
701 | 63 | } | 60 | } |
702 | 64 | } | 61 | } |
703 | 65 | 62 | ||
704 | @@ -86,6 +83,11 @@ | |||
705 | 86 | id: volumeControl | 83 | id: volumeControl |
706 | 87 | } | 84 | } |
707 | 88 | 85 | ||
708 | 86 | DashCommunicator { | ||
709 | 87 | id: dash | ||
710 | 88 | objectName: "dashCommunicator" | ||
711 | 89 | } | ||
712 | 90 | |||
713 | 89 | WindowKeysFilter { | 91 | WindowKeysFilter { |
714 | 90 | // Handle but do not filter out volume keys | 92 | // Handle but do not filter out volume keys |
715 | 91 | Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; } | 93 | Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; } |
716 | @@ -121,64 +123,12 @@ | |||
717 | 121 | visible: !fullyCovered | 123 | visible: !fullyCovered |
718 | 122 | 124 | ||
719 | 123 | Image { | 125 | Image { |
721 | 124 | anchors.fill: dash | 126 | anchors.fill: underlay |
722 | 125 | source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png" | 127 | source: shell.width > shell.height ? "Dash/graphics/paper_landscape.png" : "Dash/graphics/paper_portrait.png" |
723 | 126 | fillMode: Image.PreserveAspectCrop | 128 | fillMode: Image.PreserveAspectCrop |
724 | 127 | horizontalAlignment: Image.AlignRight | 129 | horizontalAlignment: Image.AlignRight |
725 | 128 | verticalAlignment: Image.AlignTop | 130 | verticalAlignment: Image.AlignTop |
726 | 129 | } | 131 | } |
727 | 130 | |||
728 | 131 | Dash { | ||
729 | 132 | id: dash | ||
730 | 133 | objectName: "dash" | ||
731 | 134 | |||
732 | 135 | available: !LightDM.Greeter.active | ||
733 | 136 | hides: [stages, launcher, panel.indicators] | ||
734 | 137 | shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0 && | ||
735 | 138 | !(panel.indicators.fullyOpened && !sideStageEnabled) | ||
736 | 139 | enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled | ||
737 | 140 | |||
738 | 141 | anchors { | ||
739 | 142 | fill: parent | ||
740 | 143 | topMargin: panel.panelHeight | ||
741 | 144 | } | ||
742 | 145 | |||
743 | 146 | contentScale: 1.0 - 0.2 * disappearingAnimationProgress | ||
744 | 147 | opacity: 1.0 - disappearingAnimationProgress | ||
745 | 148 | property real disappearingAnimationProgress: stages.showProgress | ||
746 | 149 | |||
747 | 150 | // FIXME: only necessary because stages.showProgress is not animated | ||
748 | 151 | Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }} | ||
749 | 152 | } | ||
750 | 153 | } | ||
751 | 154 | |||
752 | 155 | EdgeDragArea { | ||
753 | 156 | id: stagesDragArea | ||
754 | 157 | direction: Direction.Leftwards | ||
755 | 158 | |||
756 | 159 | anchors { top: parent.top; right: parent.right; bottom: parent.bottom } | ||
757 | 160 | width: shell.edgeSize | ||
758 | 161 | |||
759 | 162 | property real progress: stages.width | ||
760 | 163 | |||
761 | 164 | onTouchXChanged: { | ||
762 | 165 | if (status == DirectionalDragArea.Recognized) { | ||
763 | 166 | if (ApplicationManager.empty) { | ||
764 | 167 | progress = Math.max(stages.width - stagesDragArea.width + touchX, stages.width * .3); | ||
765 | 168 | } else { | ||
766 | 169 | progress = stages.width - stagesDragArea.width + touchX; | ||
767 | 170 | } | ||
768 | 171 | } | ||
769 | 172 | } | ||
770 | 173 | |||
771 | 174 | onDraggingChanged: { | ||
772 | 175 | if (!dragging) { | ||
773 | 176 | if (!ApplicationManager.empty && progress < stages.width - units.gu(10)) { | ||
774 | 177 | stages.show(); | ||
775 | 178 | } | ||
776 | 179 | stagesDragArea.progress = Qt.binding(function () { return stages.width; }); | ||
777 | 180 | } | ||
778 | 181 | } | ||
779 | 182 | } | 132 | } |
780 | 183 | 133 | ||
781 | 184 | Item { | 134 | Item { |
782 | @@ -186,55 +136,7 @@ | |||
783 | 186 | objectName: "stages" | 136 | objectName: "stages" |
784 | 187 | width: parent.width | 137 | width: parent.width |
785 | 188 | height: parent.height | 138 | height: parent.height |
835 | 189 | 139 | visible: !ApplicationManager.empty | |
787 | 190 | visible: !fullyHidden && !ApplicationManager.empty | ||
788 | 191 | |||
789 | 192 | x: { | ||
790 | 193 | if (shown) { | ||
791 | 194 | if (locked || greeter.fakeActiveForApp !== "") { | ||
792 | 195 | return 0; | ||
793 | 196 | } | ||
794 | 197 | return launcher.progress; | ||
795 | 198 | } else { | ||
796 | 199 | return stagesDragArea.progress | ||
797 | 200 | } | ||
798 | 201 | } | ||
799 | 202 | Behavior on x { SmoothedAnimation { velocity: 600; duration: UbuntuAnimation.FastDuration } } | ||
800 | 203 | |||
801 | 204 | property bool shown: false | ||
802 | 205 | onShownChanged: { | ||
803 | 206 | if (shown) { | ||
804 | 207 | if (ApplicationManager.count > 0) { | ||
805 | 208 | ApplicationManager.focusApplication(ApplicationManager.get(0).appId); | ||
806 | 209 | } | ||
807 | 210 | } else { | ||
808 | 211 | if (ApplicationManager.focusedApplicationId) { | ||
809 | 212 | ApplicationManager.updateScreenshot(ApplicationManager.focusedApplicationId); | ||
810 | 213 | ApplicationManager.unfocusCurrentApplication(); | ||
811 | 214 | } | ||
812 | 215 | } | ||
813 | 216 | } | ||
814 | 217 | |||
815 | 218 | // Avoid a silent "divide by zero -> NaN" situation during init as shell.width will be | ||
816 | 219 | // zero. That breaks the property binding and the function won't be reevaluated once | ||
817 | 220 | // shell.width is set, with the NaN result staying there for good. | ||
818 | 221 | property real showProgress: shell.width ? MathUtils.clamp(1 - x / shell.width, 0, 1) : 0 | ||
819 | 222 | |||
820 | 223 | property bool fullyShown: x == 0 | ||
821 | 224 | property bool fullyHidden: x == width | ||
822 | 225 | |||
823 | 226 | property bool locked: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.locked : false | ||
824 | 227 | |||
825 | 228 | // It might technically not be fullyShown but visually it just looks so. | ||
826 | 229 | property bool roughlyFullyShown: x >= 0 && x <= units.gu(1) | ||
827 | 230 | |||
828 | 231 | function show() { | ||
829 | 232 | shown = true; | ||
830 | 233 | } | ||
831 | 234 | |||
832 | 235 | function hide() { | ||
833 | 236 | shown = false; | ||
834 | 237 | } | ||
836 | 238 | 140 | ||
837 | 239 | Connections { | 141 | Connections { |
838 | 240 | target: ApplicationManager | 142 | target: ApplicationManager |
839 | @@ -243,7 +145,6 @@ | |||
840 | 243 | lockscreen.show(); | 145 | lockscreen.show(); |
841 | 244 | } | 146 | } |
842 | 245 | greeter.hide(); | 147 | greeter.hide(); |
843 | 246 | stages.show(); | ||
844 | 247 | } | 148 | } |
845 | 248 | 149 | ||
846 | 249 | onFocusedApplicationIdChanged: { | 150 | onFocusedApplicationIdChanged: { |
847 | @@ -254,18 +155,9 @@ | |||
848 | 254 | } | 155 | } |
849 | 255 | 156 | ||
850 | 256 | onApplicationAdded: { | 157 | onApplicationAdded: { |
852 | 257 | if (greeter.shown) { | 158 | if (greeter.shown && appId != "unity8-dash") { |
853 | 258 | greeter.hide(); | 159 | greeter.hide(); |
854 | 259 | } | 160 | } |
855 | 260 | if (!stages.shown) { | ||
856 | 261 | stages.show(); | ||
857 | 262 | } | ||
858 | 263 | } | ||
859 | 264 | |||
860 | 265 | onEmptyChanged: { | ||
861 | 266 | if (ApplicationManager.empty) { | ||
862 | 267 | stages.hide(); | ||
863 | 268 | } | ||
864 | 269 | } | 161 | } |
865 | 270 | } | 162 | } |
866 | 271 | 163 | ||
867 | @@ -294,14 +186,18 @@ | |||
868 | 294 | Binding { | 186 | Binding { |
869 | 295 | target: applicationsDisplayLoader.item | 187 | target: applicationsDisplayLoader.item |
870 | 296 | property: "interactive" | 188 | property: "interactive" |
873 | 297 | value: stages.roughlyFullyShown && !greeter.shown && !lockscreen.shown | 189 | value: !greeter.shown && !lockscreen.shown && panel.indicators.fullyClosed && launcher.progress == 0 |
872 | 298 | && panel.indicators.fullyClosed | ||
874 | 299 | } | 190 | } |
875 | 300 | Binding { | 191 | Binding { |
876 | 301 | target: applicationsDisplayLoader.item | 192 | target: applicationsDisplayLoader.item |
877 | 302 | property: "spreadEnabled" | 193 | property: "spreadEnabled" |
878 | 303 | value: greeter.fakeActiveForApp === "" // to support emergency dialer hack | 194 | value: greeter.fakeActiveForApp === "" // to support emergency dialer hack |
879 | 304 | } | 195 | } |
880 | 196 | Binding { | ||
881 | 197 | target: applicationsDisplayLoader.item | ||
882 | 198 | property: "inverseProgress" | ||
883 | 199 | value: launcher.progress | ||
884 | 200 | } | ||
885 | 305 | } | 201 | } |
886 | 306 | } | 202 | } |
887 | 307 | 203 | ||
888 | @@ -531,25 +427,20 @@ | |||
889 | 531 | 427 | ||
890 | 532 | var animate = !LightDM.Greeter.active && !stages.shown | 428 | var animate = !LightDM.Greeter.active && !stages.shown |
891 | 533 | dash.setCurrentScope("clickscope", animate, false) | 429 | dash.setCurrentScope("clickscope", animate, false) |
893 | 534 | stages.hide() | 430 | ApplicationManager.requestFocusApplication("unity8-dash") |
894 | 535 | } | 431 | } |
895 | 536 | 432 | ||
896 | 537 | function showDash() { | 433 | function showDash() { |
897 | 538 | if (LightDM.Greeter.active && !LightDM.Greeter.promptless) { | 434 | if (LightDM.Greeter.active && !LightDM.Greeter.promptless) { |
898 | 539 | return; | 435 | return; |
899 | 540 | } | 436 | } |
900 | 541 | |||
901 | 542 | if (!stages.locked) { | ||
902 | 543 | stages.hide(); | ||
903 | 544 | launcher.fadeOut(); | ||
904 | 545 | } else { | ||
905 | 546 | launcher.switchToNextState("visible"); | ||
906 | 547 | } | ||
907 | 548 | |||
908 | 549 | if (greeter.shown) { | 437 | if (greeter.shown) { |
909 | 550 | greeter.hideRight(); | 438 | greeter.hideRight(); |
910 | 551 | launcher.fadeOut(); | 439 | launcher.fadeOut(); |
911 | 552 | } | 440 | } |
912 | 441 | |||
913 | 442 | ApplicationManager.requestFocusApplication("unity8-dash") | ||
914 | 443 | launcher.fadeOut(); | ||
915 | 553 | } | 444 | } |
916 | 554 | 445 | ||
917 | 555 | Item { | 446 | Item { |
918 | @@ -574,8 +465,8 @@ | |||
919 | 574 | ApplicationManager.focusedApplicationId && | 465 | ApplicationManager.focusedApplicationId && |
920 | 575 | ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen | 466 | ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen |
921 | 576 | 467 | ||
924 | 577 | fullscreenMode: (stages.roughlyFullyShown && topmostApplicationIsFullscreen | 468 | fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0) |
925 | 578 | && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== "" | 469 | || greeter.fakeActiveForApp !== "" |
926 | 579 | } | 470 | } |
927 | 580 | 471 | ||
928 | 581 | Launcher { | 472 | Launcher { |
929 | @@ -592,7 +483,11 @@ | |||
930 | 592 | 483 | ||
931 | 593 | onShowDashHome: showHome() | 484 | onShowDashHome: showHome() |
932 | 594 | onDash: showDash() | 485 | onDash: showDash() |
934 | 595 | onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true) | 486 | onDashSwipeChanged: { |
935 | 487 | if (dashSwipe && ApplicationManager.focusedApplicationId !== "unity8-dash") { | ||
936 | 488 | dash.setCurrentScope("clickscope", false, true) | ||
937 | 489 | } | ||
938 | 490 | } | ||
939 | 596 | onLauncherApplicationSelected: { | 491 | onLauncherApplicationSelected: { |
940 | 597 | if (greeter.fakeActiveForApp !== "") { | 492 | if (greeter.fakeActiveForApp !== "") { |
941 | 598 | lockscreen.show() | 493 | lockscreen.show() |
942 | @@ -684,7 +579,6 @@ | |||
943 | 684 | z: alphaDisclaimerLabel.z + 10 | 579 | z: alphaDisclaimerLabel.z + 10 |
944 | 685 | greeter: greeter | 580 | greeter: greeter |
945 | 686 | launcher: launcher | 581 | launcher: launcher |
946 | 687 | dash: dash | ||
947 | 688 | indicators: panel.indicators | 582 | indicators: panel.indicators |
948 | 689 | underlay: underlay | 583 | underlay: underlay |
949 | 690 | } | 584 | } |
950 | 691 | 585 | ||
951 | === modified file 'qml/Stages/PhoneStage.qml' | |||
952 | --- qml/Stages/PhoneStage.qml 2014-07-22 15:16:32 +0000 | |||
953 | +++ qml/Stages/PhoneStage.qml 2014-08-05 11:53:58 +0000 | |||
954 | @@ -21,7 +21,7 @@ | |||
955 | 21 | import Utils 0.1 | 21 | import Utils 0.1 |
956 | 22 | import "../Components" | 22 | import "../Components" |
957 | 23 | 23 | ||
959 | 24 | Item { | 24 | Rectangle { |
960 | 25 | id: root | 25 | id: root |
961 | 26 | 26 | ||
962 | 27 | // Controls to be set from outside | 27 | // Controls to be set from outside |
963 | @@ -29,9 +29,9 @@ | |||
964 | 29 | property real maximizedAppTopMargin | 29 | property real maximizedAppTopMargin |
965 | 30 | property bool interactive | 30 | property bool interactive |
966 | 31 | property bool spreadEnabled: true // If false, animations and right edge will be disabled | 31 | property bool spreadEnabled: true // If false, animations and right edge will be disabled |
967 | 32 | property real inverseProgress: 0 // This is the progress for left edge drags, in pixels. | ||
968 | 32 | 33 | ||
971 | 33 | // State information propagated to the outside | 34 | color: "black" |
970 | 34 | readonly property bool locked: spreadView.phase == 2 | ||
972 | 35 | 35 | ||
973 | 36 | function select(appId) { | 36 | function select(appId) { |
974 | 37 | spreadView.snapTo(priv.indexOf(appId)); | 37 | spreadView.snapTo(priv.indexOf(appId)); |
975 | @@ -43,6 +43,16 @@ | |||
976 | 43 | spreadView.contentX = -spreadView.shift; | 43 | spreadView.contentX = -spreadView.shift; |
977 | 44 | } | 44 | } |
978 | 45 | 45 | ||
979 | 46 | onInverseProgressChanged: { | ||
980 | 47 | if (inverseProgress == 0 && priv.oldInverseProgress > 0) { | ||
981 | 48 | // left edge drag released. Minimum distance is given by design. | ||
982 | 49 | if (priv.oldInverseProgress > units.gu(22)) { | ||
983 | 50 | ApplicationManager.focusApplication("unity8-dash"); | ||
984 | 51 | } | ||
985 | 52 | } | ||
986 | 53 | priv.oldInverseProgress = inverseProgress; | ||
987 | 54 | } | ||
988 | 55 | |||
989 | 46 | Connections { | 56 | Connections { |
990 | 47 | target: ApplicationManager | 57 | target: ApplicationManager |
991 | 48 | 58 | ||
992 | @@ -50,7 +60,7 @@ | |||
993 | 50 | if (spreadView.phase > 0) { | 60 | if (spreadView.phase > 0) { |
994 | 51 | spreadView.snapTo(priv.indexOf(appId)); | 61 | spreadView.snapTo(priv.indexOf(appId)); |
995 | 52 | } else { | 62 | } else { |
997 | 53 | priv.switchToApp(appId); | 63 | ApplicationManager.focusApplication(appId); |
998 | 54 | } | 64 | } |
999 | 55 | } | 65 | } |
1000 | 56 | 66 | ||
1001 | @@ -60,7 +70,7 @@ | |||
1002 | 60 | } else { | 70 | } else { |
1003 | 61 | spreadView.phase = 0; | 71 | spreadView.phase = 0; |
1004 | 62 | spreadView.contentX = -spreadView.shift; | 72 | spreadView.contentX = -spreadView.shift; |
1006 | 63 | priv.switchToApp(appId); | 73 | ApplicationManager.focusApplication(appId); |
1007 | 64 | } | 74 | } |
1008 | 65 | } | 75 | } |
1009 | 66 | 76 | ||
1010 | @@ -79,15 +89,11 @@ | |||
1011 | 79 | 89 | ||
1012 | 80 | property string focusedAppId: ApplicationManager.focusedApplicationId | 90 | property string focusedAppId: ApplicationManager.focusedApplicationId |
1013 | 81 | property var focusedApplication: ApplicationManager.findApplication(focusedAppId) | 91 | property var focusedApplication: ApplicationManager.findApplication(focusedAppId) |
1023 | 82 | 92 | property var focusedAppDelegate: null | |
1024 | 83 | function switchToApp(appId) { | 93 | |
1025 | 84 | if (priv.focusedAppId) { | 94 | property real oldInverseProgress: 0 |
1026 | 85 | spreadView.focusChanging = true; | 95 | |
1027 | 86 | ApplicationManager.focusApplication(appId); | 96 | onFocusedAppIdChanged: focusedAppDelegate = spreadRepeater.itemAt(0); |
1019 | 87 | } else { | ||
1020 | 88 | ApplicationManager.focusApplication(appId); | ||
1021 | 89 | } | ||
1022 | 90 | } | ||
1028 | 91 | 97 | ||
1029 | 92 | function indexOf(appId) { | 98 | function indexOf(appId) { |
1030 | 93 | for (var i = 0; i < ApplicationManager.count; i++) { | 99 | for (var i = 0; i < ApplicationManager.count; i++) { |
1031 | @@ -100,14 +106,6 @@ | |||
1032 | 100 | 106 | ||
1033 | 101 | } | 107 | } |
1034 | 102 | 108 | ||
1035 | 103 | Rectangle { | ||
1036 | 104 | id: coverFlipBackground | ||
1037 | 105 | anchors.fill: parent | ||
1038 | 106 | color: "black" | ||
1039 | 107 | visible: spreadView.visible | ||
1040 | 108 | } | ||
1041 | 109 | |||
1042 | 110 | |||
1043 | 111 | Flickable { | 109 | Flickable { |
1044 | 112 | id: spreadView | 110 | id: spreadView |
1045 | 113 | objectName: "spreadView" | 111 | objectName: "spreadView" |
1046 | @@ -116,6 +114,10 @@ | |||
1047 | 116 | contentWidth: spreadRow.width - shift | 114 | contentWidth: spreadRow.width - shift |
1048 | 117 | contentX: -shift | 115 | contentX: -shift |
1049 | 118 | 116 | ||
1050 | 117 | // This indicates when the spreadView is active. That means, all the animations | ||
1051 | 118 | // are activated and tiles need to line up for the spread. | ||
1052 | 119 | readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging | ||
1053 | 120 | |||
1054 | 119 | // The flickable needs to fill the screen in order to get touch events all over. | 121 | // The flickable needs to fill the screen in order to get touch events all over. |
1055 | 120 | // However, we don't want to the user to be able to scroll back all the way. For | 122 | // However, we don't want to the user to be able to scroll back all the way. For |
1056 | 121 | // that, the beginning of the gesture starts with a negative value for contentX | 123 | // that, the beginning of the gesture starts with a negative value for contentX |
1057 | @@ -198,6 +200,12 @@ | |||
1058 | 198 | snapAnimation.start(); | 200 | snapAnimation.start(); |
1059 | 199 | } | 201 | } |
1060 | 200 | 202 | ||
1061 | 203 | // In case the ApplicationManager already holds an app when starting up we're missing animations | ||
1062 | 204 | // Make sure we end up in the same state | ||
1063 | 205 | Component.onCompleted: { | ||
1064 | 206 | spreadView.contentX = -spreadView.shift | ||
1065 | 207 | } | ||
1066 | 208 | |||
1067 | 201 | SequentialAnimation { | 209 | SequentialAnimation { |
1068 | 202 | id: snapAnimation | 210 | id: snapAnimation |
1069 | 203 | property int targetContentX: -spreadView.shift | 211 | property int targetContentX: -spreadView.shift |
1070 | @@ -260,14 +268,33 @@ | |||
1071 | 260 | && spreadView.shiftedContentX === 0 && root.interactive && index === 0 | 268 | && spreadView.shiftedContentX === 0 && root.interactive && index === 0 |
1072 | 261 | swipeToCloseEnabled: spreadView.interactive | 269 | swipeToCloseEnabled: spreadView.interactive |
1073 | 262 | maximizedAppTopMargin: root.maximizedAppTopMargin | 270 | maximizedAppTopMargin: root.maximizedAppTopMargin |
1078 | 263 | dropShadow: spreadView.shiftedContentX > 0 || spreadDragArea.status == DirectionalDragArea.Undecided | 271 | dropShadow: spreadView.active || |
1079 | 264 | 272 | priv.focusedAppDelegate.x !== 0 | |
1080 | 265 | z: behavioredIndex | 273 | |
1081 | 266 | x: index == 0 ? 0 : spreadView.width + (index - 1) * spreadView.tileDistance | 274 | readonly property bool isDash: model.appId == "unity8-dash" |
1082 | 275 | |||
1083 | 276 | z: isDash && !spreadView.active ? -1 : behavioredIndex | ||
1084 | 277 | |||
1085 | 278 | x: { | ||
1086 | 279 | // focused app is always positioned at 0 except when following left edge drag | ||
1087 | 280 | if (index == 0) { | ||
1088 | 281 | if (!isDash && root.inverseProgress > 0) { | ||
1089 | 282 | return root.inverseProgress; | ||
1090 | 283 | } | ||
1091 | 284 | return 0; | ||
1092 | 285 | } | ||
1093 | 286 | if (isDash && !spreadView.active && !spreadDragArea.dragging) { | ||
1094 | 287 | return 0; | ||
1095 | 288 | } | ||
1096 | 289 | |||
1097 | 290 | // Otherwise line up for the spread | ||
1098 | 291 | return spreadView.width + (index - 1) * spreadView.tileDistance; | ||
1099 | 292 | } | ||
1100 | 267 | property real behavioredIndex: index | 293 | property real behavioredIndex: index |
1101 | 268 | Behavior on behavioredIndex { | 294 | Behavior on behavioredIndex { |
1102 | 269 | enabled: spreadView.closingIndex >= 0 | 295 | enabled: spreadView.closingIndex >= 0 |
1103 | 270 | UbuntuNumberAnimation { | 296 | UbuntuNumberAnimation { |
1104 | 297 | id: appXAnimation | ||
1105 | 271 | onRunningChanged: { | 298 | onRunningChanged: { |
1106 | 272 | if (!running) { | 299 | if (!running) { |
1107 | 273 | spreadView.closingIndex = -1; | 300 | spreadView.closingIndex = -1; |
1108 | @@ -277,11 +304,13 @@ | |||
1109 | 277 | } | 304 | } |
1110 | 278 | 305 | ||
1111 | 279 | Behavior on x { | 306 | Behavior on x { |
1113 | 280 | enabled: spreadView.focusChanging && index == 0 && root.spreadEnabled | 307 | enabled: root.spreadEnabled && |
1114 | 308 | !spreadView.active && | ||
1115 | 309 | !snapAnimation.running | ||
1116 | 281 | UbuntuNumberAnimation { | 310 | UbuntuNumberAnimation { |
1117 | 282 | duration: UbuntuAnimation.FastDuration | 311 | duration: UbuntuAnimation.FastDuration |
1118 | 283 | onRunningChanged: { | 312 | onRunningChanged: { |
1120 | 284 | if (!running) { | 313 | if (!running && root.inverseProgress == 0) { |
1121 | 285 | spreadView.focusChanging = false; | 314 | spreadView.focusChanging = false; |
1122 | 286 | } | 315 | } |
1123 | 287 | } | 316 | } |
1124 | @@ -322,6 +351,10 @@ | |||
1125 | 322 | return progress; | 351 | return progress; |
1126 | 323 | } | 352 | } |
1127 | 324 | 353 | ||
1128 | 354 | // Hiding tiles when their progress is negative or reached the maximum | ||
1129 | 355 | visible: (progress >= 0 && progress < 1.7) || | ||
1130 | 356 | (isDash && priv.focusedAppDelegate.x !== 0) | ||
1131 | 357 | |||
1132 | 325 | EasingCurve { | 358 | EasingCurve { |
1133 | 326 | id: snappingCurve | 359 | id: snappingCurve |
1134 | 327 | type: EasingCurve.Linear | 360 | type: EasingCurve.Linear |
1135 | 328 | 361 | ||
1136 | === modified file 'qml/Stages/SpreadDelegate.qml' | |||
1137 | --- qml/Stages/SpreadDelegate.qml 2014-07-23 12:20:45 +0000 | |||
1138 | +++ qml/Stages/SpreadDelegate.qml 2014-08-05 11:53:58 +0000 | |||
1139 | @@ -37,6 +37,7 @@ | |||
1140 | 37 | 37 | ||
1141 | 38 | SurfaceContainer { | 38 | SurfaceContainer { |
1142 | 39 | id: surfaceContainer | 39 | id: surfaceContainer |
1143 | 40 | objectName: "surfaceContainer" | ||
1144 | 40 | anchors.fill: parent | 41 | anchors.fill: parent |
1145 | 41 | surface: model.surface | 42 | surface: model.surface |
1146 | 42 | property bool appHasCreatedASurface: false | 43 | property bool appHasCreatedASurface: false |
1147 | @@ -172,6 +173,11 @@ | |||
1148 | 172 | } | 173 | } |
1149 | 173 | 174 | ||
1150 | 174 | onDragEnd: { | 175 | onDragEnd: { |
1151 | 176 | if (model.appId == "unity8-dash") { | ||
1152 | 177 | animation.animate("center") | ||
1153 | 178 | return; | ||
1154 | 179 | } | ||
1155 | 180 | |||
1156 | 175 | // velocity and distance values specified by design prototype | 181 | // velocity and distance values specified by design prototype |
1157 | 176 | if ((dragVelocity < -units.gu(40) && distance < -units.gu(8)) || distance < -root.height / 2) { | 182 | if ((dragVelocity < -units.gu(40) && distance < -units.gu(8)) || distance < -root.height / 2) { |
1158 | 177 | animation.animate("up") | 183 | animation.animate("up") |
1159 | 178 | 184 | ||
1160 | === modified file 'qml/Stages/TabletStage.qml' | |||
1161 | --- qml/Stages/TabletStage.qml 2014-07-21 08:05:38 +0000 | |||
1162 | +++ qml/Stages/TabletStage.qml 2014-08-05 11:53:58 +0000 | |||
1163 | @@ -21,10 +21,11 @@ | |||
1164 | 21 | import Utils 0.1 | 21 | import Utils 0.1 |
1165 | 22 | import "../Components" | 22 | import "../Components" |
1166 | 23 | 23 | ||
1168 | 24 | Item { | 24 | Rectangle { |
1169 | 25 | id: root | 25 | id: root |
1170 | 26 | objectName: "stages" | 26 | objectName: "stages" |
1171 | 27 | anchors.fill: parent | 27 | anchors.fill: parent |
1172 | 28 | color: "black" | ||
1173 | 28 | 29 | ||
1174 | 29 | // Controls to be set from outside | 30 | // Controls to be set from outside |
1175 | 30 | property bool shown: false | 31 | property bool shown: false |
1176 | @@ -32,9 +33,17 @@ | |||
1177 | 32 | property int dragAreaWidth | 33 | property int dragAreaWidth |
1178 | 33 | property real maximizedAppTopMargin | 34 | property real maximizedAppTopMargin |
1179 | 34 | property bool interactive | 35 | property bool interactive |
1180 | 36 | property real inverseProgress: 0 // This is the progress for left edge drags, in pixels. | ||
1181 | 35 | 37 | ||
1184 | 36 | // State information propagated to the outside | 38 | onInverseProgressChanged: { |
1185 | 37 | readonly property bool locked: spreadView.phase == 2 | 39 | if (inverseProgress == 0 && priv.oldInverseProgress > 0) { |
1186 | 40 | // left edge drag released. Minimum distance is given by design. | ||
1187 | 41 | if (priv.oldInverseProgress > units.gu(22)) { | ||
1188 | 42 | ApplicationManager.focusApplication("unity8-dash"); | ||
1189 | 43 | } | ||
1190 | 44 | } | ||
1191 | 45 | priv.oldInverseProgress = inverseProgress; | ||
1192 | 46 | } | ||
1193 | 38 | 47 | ||
1194 | 39 | QtObject { | 48 | QtObject { |
1195 | 40 | id: priv | 49 | id: priv |
1196 | @@ -49,6 +58,8 @@ | |||
1197 | 49 | property string appId0 | 58 | property string appId0 |
1198 | 50 | property string appId1 | 59 | property string appId1 |
1199 | 51 | 60 | ||
1200 | 61 | property int oldInverseProgress: 0 | ||
1201 | 62 | |||
1202 | 52 | onFocusedAppIdChanged: { | 63 | onFocusedAppIdChanged: { |
1203 | 53 | if (priv.focusedAppId.length > 0) { | 64 | if (priv.focusedAppId.length > 0) { |
1204 | 54 | var focusedApp = ApplicationManager.findApplication(focusedAppId); | 65 | var focusedApp = ApplicationManager.findApplication(focusedAppId); |
1205 | @@ -107,16 +118,26 @@ | |||
1206 | 107 | } | 118 | } |
1207 | 108 | } | 119 | } |
1208 | 109 | 120 | ||
1209 | 121 | onApplicationAdded: { | ||
1210 | 122 | if (spreadView.phase == 2) { | ||
1211 | 123 | spreadView.snapTo(ApplicationManager.count - 1); | ||
1212 | 124 | } else { | ||
1213 | 125 | spreadView.phase = 0; | ||
1214 | 126 | spreadView.contentX = -spreadView.shift; | ||
1215 | 127 | ApplicationManager.focusApplication(appId); | ||
1216 | 128 | } | ||
1217 | 129 | } | ||
1218 | 130 | |||
1219 | 110 | onApplicationRemoved: { | 131 | onApplicationRemoved: { |
1220 | 111 | if (priv.mainStageAppId == appId) { | 132 | if (priv.mainStageAppId == appId) { |
1222 | 112 | priv.mainStageAppId = ""; | 133 | ApplicationManager.focusApplication("unity8-dash") |
1223 | 113 | } | 134 | } |
1224 | 114 | if (priv.sideStageAppId == appId) { | 135 | if (priv.sideStageAppId == appId) { |
1225 | 115 | priv.sideStageAppId = ""; | 136 | priv.sideStageAppId = ""; |
1226 | 116 | } | 137 | } |
1227 | 117 | if (ApplicationManager.count == 0) { | 138 | if (ApplicationManager.count == 0) { |
1228 | 118 | spreadView.phase = 0; | 139 | spreadView.phase = 0; |
1230 | 119 | spreadView.contentX = 0; | 140 | spreadView.contentX = -spreadView.shift; |
1231 | 120 | } | 141 | } |
1232 | 121 | } | 142 | } |
1233 | 122 | } | 143 | } |
1234 | @@ -124,13 +145,26 @@ | |||
1235 | 124 | Flickable { | 145 | Flickable { |
1236 | 125 | id: spreadView | 146 | id: spreadView |
1237 | 126 | anchors.fill: parent | 147 | anchors.fill: parent |
1238 | 127 | contentWidth: spreadRow.width | ||
1239 | 128 | interactive: (spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1) && draggedIndex == -1 | 148 | interactive: (spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1) && draggedIndex == -1 |
1240 | 149 | contentWidth: spreadRow.width - shift | ||
1241 | 150 | contentX: -shift | ||
1242 | 129 | 151 | ||
1243 | 130 | property int tileDistance: units.gu(20) | 152 | property int tileDistance: units.gu(20) |
1244 | 131 | property int sideStageWidth: units.gu(40) | 153 | property int sideStageWidth: units.gu(40) |
1245 | 132 | property bool sideStageVisible: priv.sideStageAppId | 154 | property bool sideStageVisible: priv.sideStageAppId |
1246 | 133 | 155 | ||
1247 | 156 | // This indicates when the spreadView is active. That means, all the animations | ||
1248 | 157 | // are activated and tiles need to line up for the spread. | ||
1249 | 158 | readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging | ||
1250 | 159 | |||
1251 | 160 | // The flickable needs to fill the screen in order to get touch events all over. | ||
1252 | 161 | // However, we don't want to the user to be able to scroll back all the way. For | ||
1253 | 162 | // that, the beginning of the gesture starts with a negative value for contentX | ||
1254 | 163 | // so the flickable wants to pull it into the view already. "shift" tunes the | ||
1255 | 164 | // distance where to "lock" the content. | ||
1256 | 165 | readonly property real shift: width / 2 | ||
1257 | 166 | readonly property real shiftedContentX: contentX + shift | ||
1258 | 167 | |||
1259 | 134 | // Phase of the animation: | 168 | // Phase of the animation: |
1260 | 135 | // 0: Starting from right edge, a new app (index 1) comes in from the right | 169 | // 0: Starting from right edge, a new app (index 1) comes in from the right |
1261 | 136 | // 1: The app has reached the first snap position. | 170 | // 1: The app has reached the first snap position. |
1262 | @@ -168,6 +202,12 @@ | |||
1263 | 168 | } | 202 | } |
1264 | 169 | } | 203 | } |
1265 | 170 | 204 | ||
1266 | 205 | // In case the ApplicationManager already holds an app when starting up we're missing animations | ||
1267 | 206 | // Make sure we end up in the same state | ||
1268 | 207 | Component.onCompleted: { | ||
1269 | 208 | spreadView.contentX = -spreadView.shift | ||
1270 | 209 | } | ||
1271 | 210 | |||
1272 | 171 | property int nextInStack: { | 211 | property int nextInStack: { |
1273 | 172 | switch (state) { | 212 | switch (state) { |
1274 | 173 | case "main": | 213 | case "main": |
1275 | @@ -224,31 +264,31 @@ | |||
1276 | 224 | return "empty"; | 264 | return "empty"; |
1277 | 225 | } | 265 | } |
1278 | 226 | 266 | ||
1281 | 227 | onContentXChanged: { | 267 | onShiftedContentXChanged: { |
1282 | 228 | if (spreadView.phase == 0 && spreadView.contentX > spreadView.width * spreadView.positionMarker2) { | 268 | if (spreadView.phase == 0 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker2) { |
1283 | 229 | spreadView.phase = 1; | 269 | spreadView.phase = 1; |
1285 | 230 | } else if (spreadView.phase == 1 && spreadView.contentX > spreadView.width * spreadView.positionMarker4) { | 270 | } else if (spreadView.phase == 1 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker4) { |
1286 | 231 | spreadView.phase = 2; | 271 | spreadView.phase = 2; |
1288 | 232 | } else if (spreadView.phase == 1 && spreadView.contentX < spreadView.width * spreadView.positionMarker2) { | 272 | } else if (spreadView.phase == 1 && spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) { |
1289 | 233 | spreadView.phase = 0; | 273 | spreadView.phase = 0; |
1290 | 234 | } | 274 | } |
1291 | 235 | } | 275 | } |
1292 | 236 | 276 | ||
1293 | 237 | function snap() { | 277 | function snap() { |
1296 | 238 | if (contentX < phase0Width) { | 278 | if (shiftedContentX < phase0Width) { |
1297 | 239 | snapAnimation.targetContentX = 0; | 279 | snapAnimation.targetContentX = -shift; |
1298 | 240 | snapAnimation.start(); | 280 | snapAnimation.start(); |
1300 | 241 | } else if (contentX < phase1Width) { | 281 | } else if (shiftedContentX < phase1Width) { |
1301 | 242 | snapTo(1); | 282 | snapTo(1); |
1302 | 243 | } else { | 283 | } else { |
1303 | 244 | // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation. | 284 | // Add 1 pixel to make sure we definitely hit positionMarker4 even with rounding errors of the animation. |
1305 | 245 | snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1; | 285 | snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1 - shift; |
1306 | 246 | snapAnimation.start(); | 286 | snapAnimation.start(); |
1307 | 247 | } | 287 | } |
1308 | 248 | } | 288 | } |
1309 | 249 | function snapTo(index) { | 289 | function snapTo(index) { |
1310 | 250 | spreadView.selectedIndex = index; | 290 | spreadView.selectedIndex = index; |
1312 | 251 | snapAnimation.targetContentX = 0; | 291 | snapAnimation.targetContentX = -shift; |
1313 | 252 | snapAnimation.start(); | 292 | snapAnimation.start(); |
1314 | 253 | } | 293 | } |
1315 | 254 | 294 | ||
1316 | @@ -261,12 +301,12 @@ | |||
1317 | 261 | return index; | 301 | return index; |
1318 | 262 | } | 302 | } |
1319 | 263 | 303 | ||
1322 | 264 | var isActive = app.appId == priv.mainStageAppId || app.appId == priv.sideStageAppId; | 304 | var active = app.appId == priv.mainStageAppId || app.appId == priv.sideStageAppId; |
1323 | 265 | if (isActive && app.stage == ApplicationInfoInterface.MainStage) { | 305 | if (active && app.stage == ApplicationInfoInterface.MainStage) { |
1324 | 266 | // if this app is active, and its the MainStage, always put it to index 0 | 306 | // if this app is active, and its the MainStage, always put it to index 0 |
1325 | 267 | return 0; | 307 | return 0; |
1326 | 268 | } | 308 | } |
1328 | 269 | if (isActive && app.stage == ApplicationInfoInterface.SideStage) { | 309 | if (active && app.stage == ApplicationInfoInterface.SideStage) { |
1329 | 270 | if (!priv.mainStageAppId) { | 310 | if (!priv.mainStageAppId) { |
1330 | 271 | // Only have SS apps running. Put the active one at 0 | 311 | // Only have SS apps running. Put the active one at 0 |
1331 | 272 | return 0; | 312 | return 0; |
1332 | @@ -309,7 +349,7 @@ | |||
1333 | 309 | 349 | ||
1334 | 310 | SequentialAnimation { | 350 | SequentialAnimation { |
1335 | 311 | id: snapAnimation | 351 | id: snapAnimation |
1337 | 312 | property int targetContentX: 0 | 352 | property int targetContentX: -spreadView.shift |
1338 | 313 | 353 | ||
1339 | 314 | UbuntuNumberAnimation { | 354 | UbuntuNumberAnimation { |
1340 | 315 | target: spreadView | 355 | target: spreadView |
1341 | @@ -325,15 +365,14 @@ | |||
1342 | 325 | spreadView.selectedIndex = -1; | 365 | spreadView.selectedIndex = -1; |
1343 | 326 | ApplicationManager.focusApplication(ApplicationManager.get(newIndex).appId); | 366 | ApplicationManager.focusApplication(ApplicationManager.get(newIndex).appId); |
1344 | 327 | spreadView.phase = 0; | 367 | spreadView.phase = 0; |
1346 | 328 | spreadView.contentX = 0; | 368 | spreadView.contentX = -spreadView.shift; |
1347 | 329 | } | 369 | } |
1348 | 330 | } | 370 | } |
1349 | 331 | } | 371 | } |
1350 | 332 | } | 372 | } |
1351 | 333 | 373 | ||
1353 | 334 | Rectangle { | 374 | Item { |
1354 | 335 | id: spreadRow | 375 | id: spreadRow |
1355 | 336 | color: "black" | ||
1356 | 337 | x: spreadView.contentX | 376 | x: spreadView.contentX |
1357 | 338 | height: root.height | 377 | height: root.height |
1358 | 339 | width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance) | 378 | width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance) |
1359 | @@ -380,7 +419,7 @@ | |||
1360 | 380 | MouseArea { | 419 | MouseArea { |
1361 | 381 | id: sideStageDragHandleMouseArea | 420 | id: sideStageDragHandleMouseArea |
1362 | 382 | anchors.fill: parent | 421 | anchors.fill: parent |
1364 | 383 | enabled: spreadView.contentX == 0 | 422 | enabled: spreadView.shiftedContentX == 0 |
1365 | 384 | property int startX | 423 | property int startX |
1366 | 385 | property var gesturePoints: new Array() | 424 | property var gesturePoints: new Array() |
1367 | 386 | 425 | ||
1368 | @@ -413,7 +452,7 @@ | |||
1369 | 413 | 452 | ||
1370 | 414 | onRunningChanged: { | 453 | onRunningChanged: { |
1371 | 415 | if (!running) { | 454 | if (!running) { |
1373 | 416 | sideStageDragHandle.dragging = false;; | 455 | sideStageDragHandle.dragging = false; |
1374 | 417 | } | 456 | } |
1375 | 418 | } | 457 | } |
1376 | 419 | } | 458 | } |
1377 | @@ -427,17 +466,26 @@ | |||
1378 | 427 | id: spreadTile | 466 | id: spreadTile |
1379 | 428 | height: spreadView.height | 467 | height: spreadView.height |
1380 | 429 | width: model.stage == ApplicationInfoInterface.MainStage ? spreadView.width : spreadView.sideStageWidth | 468 | width: model.stage == ApplicationInfoInterface.MainStage ? spreadView.width : spreadView.sideStageWidth |
1381 | 430 | x: spreadView.width | ||
1382 | 431 | z: spreadView.indexToZIndex(index) | ||
1383 | 432 | active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId | 469 | active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId |
1385 | 433 | zIndex: z | 470 | zIndex: spreadView.indexToZIndex(index) |
1386 | 434 | selected: spreadView.selectedIndex == index | 471 | selected: spreadView.selectedIndex == index |
1387 | 435 | otherSelected: spreadView.selectedIndex >= 0 && !selected | 472 | otherSelected: spreadView.selectedIndex >= 0 && !selected |
1388 | 436 | isInSideStage: priv.sideStageAppId == model.appId | 473 | isInSideStage: priv.sideStageAppId == model.appId |
1389 | 437 | interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive | 474 | interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive |
1390 | 438 | swipeToCloseEnabled: spreadView.interactive | 475 | swipeToCloseEnabled: spreadView.interactive |
1391 | 439 | maximizedAppTopMargin: root.maximizedAppTopMargin | 476 | maximizedAppTopMargin: root.maximizedAppTopMargin |
1393 | 440 | dropShadow: spreadView.contentX > 0 || spreadDragArea.status == DirectionalDragArea.Undecided | 477 | dragOffset: !isDash && model.appId == priv.mainStageAppId && root.inverseProgress > 0 ? root.inverseProgress : 0 |
1394 | 478 | |||
1395 | 479 | readonly property bool isDash: model.appId == "unity8-dash" | ||
1396 | 480 | |||
1397 | 481 | // FIXME: A regular binding doesn't update any more after closing an app. | ||
1398 | 482 | // Using a Binding for now. | ||
1399 | 483 | Binding { | ||
1400 | 484 | target: spreadTile | ||
1401 | 485 | property: "z" | ||
1402 | 486 | value: (!spreadView.active && isDash && !active) ? -1 : spreadTile.zIndex | ||
1403 | 487 | } | ||
1404 | 488 | x: spreadView.width | ||
1405 | 441 | 489 | ||
1406 | 442 | property real behavioredZIndex: zIndex | 490 | property real behavioredZIndex: zIndex |
1407 | 443 | Behavior on behavioredZIndex { | 491 | Behavior on behavioredZIndex { |
1408 | @@ -458,7 +506,7 @@ | |||
1409 | 458 | } | 506 | } |
1410 | 459 | 507 | ||
1411 | 460 | progress: { | 508 | progress: { |
1413 | 461 | var tileProgress = (spreadView.contentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width; | 509 | var tileProgress = (spreadView.shiftedContentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width; |
1414 | 462 | // Some tiles (nextInStack, active) need to move directly from the beginning, normalize progress to immediately start at 0 | 510 | // Some tiles (nextInStack, active) need to move directly from the beginning, normalize progress to immediately start at 0 |
1415 | 463 | if ((index == spreadView.nextInStack && spreadView.phase < 2) || (active && spreadView.phase < 1)) { | 511 | if ((index == spreadView.nextInStack && spreadView.phase < 2) || (active && spreadView.phase < 1)) { |
1416 | 464 | tileProgress += behavioredZIndex * spreadView.tileDistance / spreadView.width; | 512 | tileProgress += behavioredZIndex * spreadView.tileDistance / spreadView.width; |
1417 | @@ -481,11 +529,7 @@ | |||
1418 | 481 | 529 | ||
1419 | 482 | onClicked: { | 530 | onClicked: { |
1420 | 483 | if (spreadView.phase == 2) { | 531 | if (spreadView.phase == 2) { |
1426 | 484 | if (ApplicationManager.focusedApplicationId == ApplicationManager.get(index).appId) { | 532 | spreadView.snapTo(index); |
1422 | 485 | spreadView.snapTo(index); | ||
1423 | 486 | } else { | ||
1424 | 487 | ApplicationManager.requestFocusApplication(ApplicationManager.get(index).appId); | ||
1425 | 488 | } | ||
1427 | 489 | } | 533 | } |
1428 | 490 | } | 534 | } |
1429 | 491 | 535 | ||
1430 | @@ -518,12 +562,12 @@ | |||
1431 | 518 | onTouchXChanged: { | 562 | onTouchXChanged: { |
1432 | 519 | if (!dragging) { | 563 | if (!dragging) { |
1433 | 520 | spreadView.phase = 0; | 564 | spreadView.phase = 0; |
1435 | 521 | spreadView.contentX = 0; | 565 | spreadView.contentX = -spreadView.shift; |
1436 | 522 | } | 566 | } |
1437 | 523 | 567 | ||
1441 | 524 | if (attachedToView) { | 568 | if (dragging && attachedToView) { |
1442 | 525 | spreadView.contentX = -touchX + spreadDragArea.width; | 569 | spreadView.contentX = -touchX + spreadDragArea.width - spreadView.shift; |
1443 | 526 | if (spreadView.contentX > spreadView.phase0Width + spreadView.phase1Width / 2) { | 570 | if (spreadView.shiftedContentX > spreadView.phase0Width + spreadView.phase1Width / 2) { |
1444 | 527 | attachedToView = false; | 571 | attachedToView = false; |
1445 | 528 | spreadView.snap(); | 572 | spreadView.snap(); |
1446 | 529 | } | 573 | } |
1447 | @@ -548,14 +592,14 @@ | |||
1448 | 548 | var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints); | 592 | var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints); |
1449 | 549 | gesturePoints = []; | 593 | gesturePoints = []; |
1450 | 550 | 594 | ||
1452 | 551 | if (oneWayFlick && spreadView.contentX < spreadView.positionMarker1 * spreadView.width) { | 595 | if (oneWayFlick && spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) { |
1453 | 552 | // If it was a short one-way movement, do the Alt+Tab switch | 596 | // If it was a short one-way movement, do the Alt+Tab switch |
1454 | 553 | // no matter if we didn't cross positionMarker1 yet. | 597 | // no matter if we didn't cross positionMarker1 yet. |
1455 | 554 | spreadView.snapTo(spreadView.nextInStack); | 598 | spreadView.snapTo(spreadView.nextInStack); |
1456 | 555 | } else if (!dragging && attachedToView) { | 599 | } else if (!dragging && attachedToView) { |
1458 | 556 | if (spreadView.contentX < spreadView.width * spreadView.positionMarker1) { | 600 | if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker1) { |
1459 | 557 | spreadView.snap(); | 601 | spreadView.snap(); |
1461 | 558 | } else if (spreadView.contentX < spreadView.width * spreadView.positionMarker2) { | 602 | } else if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) { |
1462 | 559 | spreadView.snapTo(spreadView.nextInStack); | 603 | spreadView.snapTo(spreadView.nextInStack); |
1463 | 560 | } else { | 604 | } else { |
1464 | 561 | // otherwise snap to the closest snap position we can find | 605 | // otherwise snap to the closest snap position we can find |
1465 | 562 | 606 | ||
1466 | === modified file 'qml/Stages/TransformedSpreadDelegate.qml' | |||
1467 | --- qml/Stages/TransformedSpreadDelegate.qml 2014-07-21 08:13:44 +0000 | |||
1468 | +++ qml/Stages/TransformedSpreadDelegate.qml 2014-08-05 11:53:58 +0000 | |||
1469 | @@ -46,9 +46,6 @@ | |||
1470 | 46 | property real startDistance: units.gu(5) | 46 | property real startDistance: units.gu(5) |
1471 | 47 | property real endDistance: units.gu(.5) | 47 | property real endDistance: units.gu(.5) |
1472 | 48 | 48 | ||
1473 | 49 | // Hiding tiles when their progress is negative or reached the maximum | ||
1474 | 50 | visible: progress >= 0 && progress < 1.7 | ||
1475 | 51 | |||
1476 | 52 | onSelectedChanged: { | 49 | onSelectedChanged: { |
1477 | 53 | if (selected) { | 50 | if (selected) { |
1478 | 54 | priv.snapshot(); | 51 | priv.snapshot(); |
1479 | @@ -132,6 +129,10 @@ | |||
1480 | 132 | // the selected tile, which is animated from the snapshotted position to be fullscreen. | 129 | // the selected tile, which is animated from the snapshotted position to be fullscreen. |
1481 | 133 | 130 | ||
1482 | 134 | readonly property real xTranslate: { | 131 | readonly property real xTranslate: { |
1483 | 132 | if (!spreadView.active) { | ||
1484 | 133 | return 0; | ||
1485 | 134 | } | ||
1486 | 135 | |||
1487 | 135 | if (otherSelected) { | 136 | if (otherSelected) { |
1488 | 136 | if (spreadView.phase < 2 && index == 0) { | 137 | if (spreadView.phase < 2 && index == 0) { |
1489 | 137 | return linearAnimation(selectedProgress, 0, selectedXTranslate, | 138 | return linearAnimation(selectedProgress, 0, selectedXTranslate, |
1490 | @@ -183,7 +184,7 @@ | |||
1491 | 183 | } | 184 | } |
1492 | 184 | 185 | ||
1493 | 185 | readonly property real angle: { | 186 | readonly property real angle: { |
1495 | 186 | if (spreadView.focusChanging) { | 187 | if (!spreadView.active) { |
1496 | 187 | return 0; | 188 | return 0; |
1497 | 188 | } | 189 | } |
1498 | 189 | 190 | ||
1499 | @@ -216,7 +217,7 @@ | |||
1500 | 216 | } | 217 | } |
1501 | 217 | 218 | ||
1502 | 218 | readonly property real scale: { | 219 | readonly property real scale: { |
1504 | 219 | if (spreadView.focusChanging) { | 220 | if (!spreadView.active) { |
1505 | 220 | return 1; | 221 | return 1; |
1506 | 221 | } | 222 | } |
1507 | 222 | if (priv.otherSelected) { | 223 | if (priv.otherSelected) { |
1508 | 223 | 224 | ||
1509 | === modified file 'qml/Stages/TransformedTabletSpreadDelegate.qml' | |||
1510 | --- qml/Stages/TransformedTabletSpreadDelegate.qml 2014-07-21 08:17:07 +0000 | |||
1511 | +++ qml/Stages/TransformedTabletSpreadDelegate.qml 2014-08-05 11:53:58 +0000 | |||
1512 | @@ -47,6 +47,11 @@ | |||
1513 | 47 | 47 | ||
1514 | 48 | property bool isInSideStage: false | 48 | property bool isInSideStage: false |
1515 | 49 | 49 | ||
1516 | 50 | property int dragOffset: 0 | ||
1517 | 51 | |||
1518 | 52 | dropShadow: spreadView.active || | ||
1519 | 53 | (active && model.stage == ApplicationInfoInterface.MainStage && priv.xTranslate != 0) | ||
1520 | 54 | |||
1521 | 50 | onSelectedChanged: { | 55 | onSelectedChanged: { |
1522 | 51 | if (selected) { | 56 | if (selected) { |
1523 | 52 | priv.snapshot(); | 57 | priv.snapshot(); |
1524 | @@ -129,6 +134,16 @@ | |||
1525 | 129 | return helperEasingCurve.value * (endValue - startValue) + startValue; | 134 | return helperEasingCurve.value * (endValue - startValue) + startValue; |
1526 | 130 | } | 135 | } |
1527 | 131 | 136 | ||
1528 | 137 | Behavior on xTranslate { | ||
1529 | 138 | enabled: !spreadView.active && | ||
1530 | 139 | !snapAnimation.running && | ||
1531 | 140 | model.appId !== "unity8-dash" && | ||
1532 | 141 | !spreadView.sideStageDragging | ||
1533 | 142 | UbuntuNumberAnimation { | ||
1534 | 143 | duration: UbuntuAnimation.FastDuration | ||
1535 | 144 | } | ||
1536 | 145 | } | ||
1537 | 146 | |||
1538 | 132 | property real xTranslate: { | 147 | property real xTranslate: { |
1539 | 133 | var newTranslate = 0; | 148 | var newTranslate = 0; |
1540 | 134 | 149 | ||
1541 | @@ -155,7 +170,12 @@ | |||
1542 | 155 | if (spreadView.phase == 0 && shouldMoveAway) { | 170 | if (spreadView.phase == 0 && shouldMoveAway) { |
1543 | 156 | newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -units.gu(4), root.animatedProgress); | 171 | newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -units.gu(4), root.animatedProgress); |
1544 | 157 | } | 172 | } |
1546 | 158 | } | 173 | newTranslate += root.dragOffset; |
1547 | 174 | } | ||
1548 | 175 | if (!spreadView.active && model.appId == "unity8-dash" && !root.active) { | ||
1549 | 176 | newTranslate -= root.width; | ||
1550 | 177 | } | ||
1551 | 178 | |||
1552 | 159 | if (nextInStack && spreadView.phase == 0) { | 179 | if (nextInStack && spreadView.phase == 0) { |
1553 | 160 | if (model.stage == ApplicationInfoInterface.MainStage) { | 180 | if (model.stage == ApplicationInfoInterface.MainStage) { |
1554 | 161 | if (spreadView.sideStageVisible && root.progress > 0) { | 181 | if (spreadView.sideStageVisible && root.progress > 0) { |
1555 | @@ -205,6 +225,10 @@ | |||
1556 | 205 | } | 225 | } |
1557 | 206 | 226 | ||
1558 | 207 | property real scale: { | 227 | property real scale: { |
1559 | 228 | if (!spreadView.active) { | ||
1560 | 229 | return 1; | ||
1561 | 230 | } | ||
1562 | 231 | |||
1563 | 208 | if (otherSelected) { | 232 | if (otherSelected) { |
1564 | 209 | return selectedScale; | 233 | return selectedScale; |
1565 | 210 | } | 234 | } |
1566 | @@ -249,6 +273,10 @@ | |||
1567 | 249 | } | 273 | } |
1568 | 250 | 274 | ||
1569 | 251 | property real angle: { | 275 | property real angle: { |
1570 | 276 | if (!spreadView.active) { | ||
1571 | 277 | return 0; | ||
1572 | 278 | } | ||
1573 | 279 | |||
1574 | 252 | if (otherSelected) { | 280 | if (otherSelected) { |
1575 | 253 | return selectedAngle; | 281 | return selectedAngle; |
1576 | 254 | } | 282 | } |
1577 | 255 | 283 | ||
1578 | === modified file 'src/CMakeLists.txt' | |||
1579 | --- src/CMakeLists.txt 2014-07-03 20:28:32 +0000 | |||
1580 | +++ src/CMakeLists.txt 2014-08-05 11:53:58 +0000 | |||
1581 | @@ -35,3 +35,4 @@ | |||
1582 | 35 | ) | 35 | ) |
1583 | 36 | 36 | ||
1584 | 37 | add_subdirectory(Panel) | 37 | add_subdirectory(Panel) |
1585 | 38 | add_subdirectory(Dash) | ||
1586 | 38 | 39 | ||
1587 | === added directory 'src/Dash' | |||
1588 | === added file 'src/Dash/CMakeLists.txt' | |||
1589 | --- src/Dash/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
1590 | +++ src/Dash/CMakeLists.txt 2014-08-05 11:53:58 +0000 | |||
1591 | @@ -0,0 +1,12 @@ | |||
1592 | 1 | set(DASH_SRCS | ||
1593 | 2 | main.cpp | ||
1594 | 3 | ) | ||
1595 | 4 | |||
1596 | 5 | add_executable(unity8-dash ${DASH_SRCS}) | ||
1597 | 6 | |||
1598 | 7 | qt5_use_modules(unity8-dash Gui Qml Quick Test) | ||
1599 | 8 | |||
1600 | 9 | # install binaries | ||
1601 | 10 | install(TARGETS ${DASH_APP} | ||
1602 | 11 | RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} | ||
1603 | 12 | ) | ||
1604 | 0 | 13 | ||
1605 | === added file 'src/Dash/main.cpp' | |||
1606 | --- src/Dash/main.cpp 1970-01-01 00:00:00 +0000 | |||
1607 | +++ src/Dash/main.cpp 2014-08-05 11:53:58 +0000 | |||
1608 | @@ -0,0 +1,74 @@ | |||
1609 | 1 | /* | ||
1610 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
1611 | 3 | * | ||
1612 | 4 | * Authors: | ||
1613 | 5 | * Michael Zanetti <michael.zanetti@canonical.com> | ||
1614 | 6 | * | ||
1615 | 7 | * This program is free software; you can redistribute it and/or modify | ||
1616 | 8 | * it under the terms of the GNU General Public License as published by | ||
1617 | 9 | * the Free Software Foundation; version 3. | ||
1618 | 10 | * | ||
1619 | 11 | * This program is distributed in the hope that it will be useful, | ||
1620 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1621 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1622 | 14 | * GNU General Public License for more details. | ||
1623 | 15 | * | ||
1624 | 16 | * You should have received a copy of the GNU General Public License | ||
1625 | 17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1626 | 18 | */ | ||
1627 | 19 | |||
1628 | 20 | #include <QtQuick/QQuickView> | ||
1629 | 21 | #include <QtGui/QGuiApplication> | ||
1630 | 22 | #include <QtQml/QQmlEngine> | ||
1631 | 23 | #include <QtQml/QQmlContext> | ||
1632 | 24 | #include <QDebug> | ||
1633 | 25 | #include <QCommandLineParser> | ||
1634 | 26 | #include <QLibrary> | ||
1635 | 27 | |||
1636 | 28 | #include <paths.h> | ||
1637 | 29 | |||
1638 | 30 | int main(int argc, const char *argv[]) | ||
1639 | 31 | { | ||
1640 | 32 | QGuiApplication *application = new QGuiApplication(argc, (char**)argv); | ||
1641 | 33 | |||
1642 | 34 | QCommandLineParser parser; | ||
1643 | 35 | parser.setApplicationDescription("Description: Unity 8 Shell Dash"); | ||
1644 | 36 | parser.addHelpOption(); | ||
1645 | 37 | |||
1646 | 38 | QCommandLineOption testabilityOption("testability", | ||
1647 | 39 | "Load the testability driver (Alternatively export QT_LOAD_TESTABILITY"); | ||
1648 | 40 | parser.addOption(testabilityOption); | ||
1649 | 41 | |||
1650 | 42 | if (parser.isSet(testabilityOption) || getenv("QT_LOAD_TESTABILITY")) { | ||
1651 | 43 | QLibrary testLib(QLatin1String("qttestability")); | ||
1652 | 44 | if (testLib.load()) { | ||
1653 | 45 | typedef void (*TasInitialize)(void); | ||
1654 | 46 | TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init"); | ||
1655 | 47 | if (initFunction) { | ||
1656 | 48 | initFunction(); | ||
1657 | 49 | } else { | ||
1658 | 50 | qCritical("Library qttestability resolve failed!"); | ||
1659 | 51 | } | ||
1660 | 52 | } else { | ||
1661 | 53 | qCritical("Library qttestability load failed!"); | ||
1662 | 54 | } | ||
1663 | 55 | } | ||
1664 | 56 | |||
1665 | 57 | QQuickView* view = new QQuickView(); | ||
1666 | 58 | view->setResizeMode(QQuickView::SizeRootObjectToView); | ||
1667 | 59 | view->setTitle("Unity Dash"); | ||
1668 | 60 | |||
1669 | 61 | QUrl source(::qmlDirectory()+"Dash/DashApplication.qml"); | ||
1670 | 62 | prependImportPaths(view->engine(), ::overrideImportPaths()); | ||
1671 | 63 | appendImportPaths(view->engine(), ::fallbackImportPaths()); | ||
1672 | 64 | |||
1673 | 65 | view->setSource(source); | ||
1674 | 66 | view->show(); | ||
1675 | 67 | |||
1676 | 68 | int result = application->exec(); | ||
1677 | 69 | |||
1678 | 70 | delete view; | ||
1679 | 71 | delete application; | ||
1680 | 72 | |||
1681 | 73 | return result; | ||
1682 | 74 | } | ||
1683 | 0 | 75 | ||
1684 | === modified file 'tests/mocks/Unity/Application/ApplicationInfo.cpp' | |||
1685 | --- tests/mocks/Unity/Application/ApplicationInfo.cpp 2014-07-24 19:22:20 +0000 | |||
1686 | +++ tests/mocks/Unity/Application/ApplicationInfo.cpp 2014-08-05 11:53:58 +0000 | |||
1687 | @@ -31,8 +31,6 @@ | |||
1688 | 31 | , m_state(Starting) | 31 | , m_state(Starting) |
1689 | 32 | , m_focused(false) | 32 | , m_focused(false) |
1690 | 33 | , m_fullscreen(false) | 33 | , m_fullscreen(false) |
1691 | 34 | , m_windowItem(0) | ||
1692 | 35 | , m_windowComponent(0) | ||
1693 | 36 | , m_parentItem(0) | 34 | , m_parentItem(0) |
1694 | 37 | , m_surface(0) | 35 | , m_surface(0) |
1695 | 38 | { | 36 | { |
1696 | @@ -45,8 +43,6 @@ | |||
1697 | 45 | , m_state(Starting) | 43 | , m_state(Starting) |
1698 | 46 | , m_focused(false) | 44 | , m_focused(false) |
1699 | 47 | , m_fullscreen(false) | 45 | , m_fullscreen(false) |
1700 | 48 | , m_windowItem(0) | ||
1701 | 49 | , m_windowComponent(0) | ||
1702 | 50 | , m_parentItem(0) | 46 | , m_parentItem(0) |
1703 | 51 | , m_surface(0) | 47 | , m_surface(0) |
1704 | 52 | { | 48 | { |
1705 | @@ -61,12 +57,6 @@ | |||
1706 | 61 | } | 57 | } |
1707 | 62 | } | 58 | } |
1708 | 63 | 59 | ||
1709 | 64 | void ApplicationInfo::onWindowComponentStatusChanged(QQmlComponent::Status status) | ||
1710 | 65 | { | ||
1711 | 66 | if (status == QQmlComponent::Ready && !m_windowItem) | ||
1712 | 67 | doCreateWindowItem(); | ||
1713 | 68 | } | ||
1714 | 69 | |||
1715 | 70 | void ApplicationInfo::onStateChanged(State state) | 60 | void ApplicationInfo::onStateChanged(State state) |
1716 | 71 | { | 61 | { |
1717 | 72 | if (state == ApplicationInfo::Running) { | 62 | if (state == ApplicationInfo::Running) { |
1718 | @@ -108,55 +98,3 @@ | |||
1719 | 108 | Q_EMIT surfaceChanged(m_surface); | 98 | Q_EMIT surfaceChanged(m_surface); |
1720 | 109 | SurfaceManager::singleton()->registerSurface(m_surface); | 99 | SurfaceManager::singleton()->registerSurface(m_surface); |
1721 | 110 | } | 100 | } |
1722 | 111 | |||
1723 | 112 | void ApplicationInfo::createWindowComponent() | ||
1724 | 113 | { | ||
1725 | 114 | // The assumptions I make here really should hold. | ||
1726 | 115 | QQuickView *quickView = | ||
1727 | 116 | qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]); | ||
1728 | 117 | |||
1729 | 118 | QQmlEngine *engine = quickView->engine(); | ||
1730 | 119 | |||
1731 | 120 | m_windowComponent = new QQmlComponent(engine, this); | ||
1732 | 121 | m_windowComponent->setData(m_windowQml.toLatin1(), QUrl()); | ||
1733 | 122 | } | ||
1734 | 123 | |||
1735 | 124 | void ApplicationInfo::doCreateWindowItem() | ||
1736 | 125 | { | ||
1737 | 126 | m_windowItem = qobject_cast<QQuickItem *>(m_windowComponent->create()); | ||
1738 | 127 | m_windowItem->setParentItem(m_parentItem); | ||
1739 | 128 | } | ||
1740 | 129 | |||
1741 | 130 | void ApplicationInfo::createWindowItem() | ||
1742 | 131 | { | ||
1743 | 132 | if (!m_windowComponent) | ||
1744 | 133 | createWindowComponent(); | ||
1745 | 134 | |||
1746 | 135 | // only create the windowItem once the component is ready | ||
1747 | 136 | if (!m_windowComponent->isReady()) { | ||
1748 | 137 | connect(m_windowComponent, &QQmlComponent::statusChanged, | ||
1749 | 138 | this, &ApplicationInfo::onWindowComponentStatusChanged); | ||
1750 | 139 | } else { | ||
1751 | 140 | doCreateWindowItem(); | ||
1752 | 141 | } | ||
1753 | 142 | } | ||
1754 | 143 | |||
1755 | 144 | void ApplicationInfo::showWindow(QQuickItem *parent) | ||
1756 | 145 | { | ||
1757 | 146 | m_parentItem = parent; | ||
1758 | 147 | |||
1759 | 148 | if (!m_windowItem) | ||
1760 | 149 | createWindowItem(); | ||
1761 | 150 | |||
1762 | 151 | if (m_windowItem) { | ||
1763 | 152 | m_windowItem->setVisible(true); | ||
1764 | 153 | } | ||
1765 | 154 | } | ||
1766 | 155 | |||
1767 | 156 | void ApplicationInfo::hideWindow() | ||
1768 | 157 | { | ||
1769 | 158 | if (!m_windowItem) | ||
1770 | 159 | return; | ||
1771 | 160 | |||
1772 | 161 | m_windowItem->setVisible(false); | ||
1773 | 162 | } | ||
1774 | 163 | 101 | ||
1775 | === modified file 'tests/mocks/Unity/Application/ApplicationInfo.h' | |||
1776 | --- tests/mocks/Unity/Application/ApplicationInfo.h 2014-07-21 09:17:12 +0000 | |||
1777 | +++ tests/mocks/Unity/Application/ApplicationInfo.h 2014-08-05 11:53:58 +0000 | |||
1778 | @@ -88,22 +88,12 @@ | |||
1779 | 88 | Q_SIGNALS: | 88 | Q_SIGNALS: |
1780 | 89 | void surfaceChanged(MirSurfaceItem*); | 89 | void surfaceChanged(MirSurfaceItem*); |
1781 | 90 | 90 | ||
1782 | 91 | public: | ||
1783 | 92 | void showWindow(QQuickItem *parent); | ||
1784 | 93 | void hideWindow(); | ||
1785 | 94 | |||
1786 | 95 | private Q_SLOTS: | 91 | private Q_SLOTS: |
1787 | 96 | void onWindowComponentStatusChanged(QQmlComponent::Status status); | ||
1788 | 97 | void onStateChanged(State state); | 92 | void onStateChanged(State state); |
1789 | 98 | 93 | ||
1790 | 99 | void createSurface(); | 94 | void createSurface(); |
1791 | 100 | 95 | ||
1792 | 101 | private: | 96 | private: |
1793 | 102 | void createWindowItem(); | ||
1794 | 103 | void doCreateWindowItem(); | ||
1795 | 104 | void createWindowComponent(); | ||
1796 | 105 | QQuickItem *m_windowItem; | ||
1797 | 106 | QQmlComponent *m_windowComponent; | ||
1798 | 107 | QQuickItem *m_parentItem; | 97 | QQuickItem *m_parentItem; |
1799 | 108 | MirSurfaceItem* m_surface; | 98 | MirSurfaceItem* m_surface; |
1800 | 109 | }; | 99 | }; |
1801 | 110 | 100 | ||
1802 | === modified file 'tests/mocks/Unity/Application/ApplicationManager.cpp' | |||
1803 | --- tests/mocks/Unity/Application/ApplicationManager.cpp 2014-07-24 19:22:20 +0000 | |||
1804 | +++ tests/mocks/Unity/Application/ApplicationManager.cpp 2014-08-05 11:53:58 +0000 | |||
1805 | @@ -48,16 +48,14 @@ | |||
1806 | 48 | ApplicationManager::ApplicationManager(QObject *parent) | 48 | ApplicationManager::ApplicationManager(QObject *parent) |
1807 | 49 | : ApplicationManagerInterface(parent) | 49 | : ApplicationManagerInterface(parent) |
1808 | 50 | , m_suspended(false) | 50 | , m_suspended(false) |
1809 | 51 | , m_mainStageComponent(0) | ||
1810 | 52 | , m_mainStage(0) | ||
1811 | 53 | , m_sideStageComponent(0) | ||
1812 | 54 | , m_sideStage(0) | ||
1813 | 55 | , m_rightMargin(0) | ||
1814 | 56 | { | 51 | { |
1815 | 57 | m_roleNames.insert(RoleSurface, "surface"); | 52 | m_roleNames.insert(RoleSurface, "surface"); |
1816 | 58 | m_roleNames.insert(RoleFullscreen, "fullscreen"); | 53 | m_roleNames.insert(RoleFullscreen, "fullscreen"); |
1817 | 59 | 54 | ||
1818 | 60 | buildListOfAvailableApplications(); | 55 | buildListOfAvailableApplications(); |
1819 | 56 | |||
1820 | 57 | startApplication("unity8-dash"); | ||
1821 | 58 | focusApplication("unity8-dash"); | ||
1822 | 61 | } | 59 | } |
1823 | 62 | 60 | ||
1824 | 63 | ApplicationManager::~ApplicationManager() | 61 | ApplicationManager::~ApplicationManager() |
1825 | @@ -136,7 +134,6 @@ | |||
1826 | 136 | Q_EMIT applicationAdded(application->appId()); | 134 | Q_EMIT applicationAdded(application->appId()); |
1827 | 137 | Q_EMIT countChanged(); | 135 | Q_EMIT countChanged(); |
1828 | 138 | if (count() == 1) Q_EMIT emptyChanged(isEmpty()); // was empty but not anymore | 136 | if (count() == 1) Q_EMIT emptyChanged(isEmpty()); // was empty but not anymore |
1829 | 139 | Q_EMIT focusRequested(application->appId()); | ||
1830 | 140 | 137 | ||
1831 | 141 | connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() { | 138 | connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() { |
1832 | 142 | QModelIndex appIndex = findIndex(application); | 139 | QModelIndex appIndex = findIndex(application); |
1833 | @@ -222,6 +219,10 @@ | |||
1834 | 222 | 219 | ||
1835 | 223 | bool ApplicationManager::stopApplication(const QString &appId) | 220 | bool ApplicationManager::stopApplication(const QString &appId) |
1836 | 224 | { | 221 | { |
1837 | 222 | if (appId == "unity8-dash") { | ||
1838 | 223 | return false; | ||
1839 | 224 | } | ||
1840 | 225 | |||
1841 | 225 | ApplicationInfo *application = findApplication(appId); | 226 | ApplicationInfo *application = findApplication(appId); |
1842 | 226 | if (application == nullptr) | 227 | if (application == nullptr) |
1843 | 227 | return false; | 228 | return false; |
1844 | @@ -294,39 +295,25 @@ | |||
1845 | 294 | for (ApplicationInfo *app : m_runningApplications) { | 295 | for (ApplicationInfo *app : m_runningApplications) { |
1846 | 295 | if (app->focused() && app->stage() == ApplicationInfo::MainStage) { | 296 | if (app->focused() && app->stage() == ApplicationInfo::MainStage) { |
1847 | 296 | app->setFocused(false); | 297 | app->setFocused(false); |
1848 | 297 | app->hideWindow(); | ||
1849 | 298 | app->setState(ApplicationInfo::Suspended); | 298 | app->setState(ApplicationInfo::Suspended); |
1850 | 299 | } | 299 | } |
1851 | 300 | } | 300 | } |
1852 | 301 | 301 | ||
1853 | 302 | // focus this app | 302 | // focus this app |
1854 | 303 | application->setFocused(true); | 303 | application->setFocused(true); |
1855 | 304 | if (!m_mainStage) | ||
1856 | 305 | createMainStage(); | ||
1857 | 306 | application->setState(ApplicationInfo::Running); | 304 | application->setState(ApplicationInfo::Running); |
1858 | 307 | application->showWindow(m_mainStage); | ||
1859 | 308 | m_mainStage->setZ(-1000); | ||
1860 | 309 | if (m_sideStage) | ||
1861 | 310 | m_sideStage->setZ(-2000); | ||
1862 | 311 | } else if (application->stage() == ApplicationInfo::SideStage) { | 305 | } else if (application->stage() == ApplicationInfo::SideStage) { |
1863 | 312 | // unfocus currently focused sidestage app | 306 | // unfocus currently focused sidestage app |
1864 | 313 | for (ApplicationInfo *app : m_runningApplications) { | 307 | for (ApplicationInfo *app : m_runningApplications) { |
1865 | 314 | if (app->focused() && app->stage() == ApplicationInfo::SideStage) { | 308 | if (app->focused() && app->stage() == ApplicationInfo::SideStage) { |
1866 | 315 | app->setFocused(false); | 309 | app->setFocused(false); |
1867 | 316 | app->hideWindow(); | ||
1868 | 317 | app->setState(ApplicationInfo::Suspended); | 310 | app->setState(ApplicationInfo::Suspended); |
1869 | 318 | } | 311 | } |
1870 | 319 | } | 312 | } |
1871 | 320 | 313 | ||
1872 | 321 | // focus this app | 314 | // focus this app |
1873 | 322 | application->setFocused(true); | 315 | application->setFocused(true); |
1874 | 323 | if (!m_sideStage) | ||
1875 | 324 | createSideStage(); | ||
1876 | 325 | application->setState(ApplicationInfo::Running); | 316 | application->setState(ApplicationInfo::Running); |
1877 | 326 | application->showWindow(m_sideStage); | ||
1878 | 327 | m_sideStage->setZ(-1000); | ||
1879 | 328 | if (m_mainStage) | ||
1880 | 329 | m_mainStage->setZ(-2000); | ||
1881 | 330 | } | 317 | } |
1882 | 331 | 318 | ||
1883 | 332 | // move app to top of stack | 319 | // move app to top of stack |
1884 | @@ -337,18 +324,14 @@ | |||
1885 | 337 | 324 | ||
1886 | 338 | bool ApplicationManager::requestFocusApplication(const QString &appId) | 325 | bool ApplicationManager::requestFocusApplication(const QString &appId) |
1887 | 339 | { | 326 | { |
1893 | 340 | if (appId != focusedApplicationId()) { | 327 | QMetaObject::invokeMethod(this, "focusRequested", Qt::QueuedConnection, Q_ARG(QString, appId)); |
1894 | 341 | QMetaObject::invokeMethod(this, "focusRequested", Qt::QueuedConnection, Q_ARG(QString, appId)); | 328 | return true; |
1890 | 342 | return true; | ||
1891 | 343 | } | ||
1892 | 344 | return false; | ||
1895 | 345 | } | 329 | } |
1896 | 346 | 330 | ||
1897 | 347 | void ApplicationManager::unfocusCurrentApplication() | 331 | void ApplicationManager::unfocusCurrentApplication() |
1898 | 348 | { | 332 | { |
1899 | 349 | for (ApplicationInfo *app : m_runningApplications) { | 333 | for (ApplicationInfo *app : m_runningApplications) { |
1900 | 350 | if (app->focused()) { | 334 | if (app->focused()) { |
1901 | 351 | app->hideWindow(); | ||
1902 | 352 | app->setFocused(false); | 335 | app->setFocused(false); |
1903 | 353 | } | 336 | } |
1904 | 354 | } | 337 | } |
1905 | @@ -357,42 +340,6 @@ | |||
1906 | 357 | 340 | ||
1907 | 358 | void ApplicationManager::generateQmlStrings(ApplicationInfo *application) | 341 | void ApplicationManager::generateQmlStrings(ApplicationInfo *application) |
1908 | 359 | { | 342 | { |
1909 | 360 | // TODO: Is there a better way of solving this fullscreen vs. regular | ||
1910 | 361 | // application height? | ||
1911 | 362 | QString topMargin; | ||
1912 | 363 | if (application->fullscreen()) { | ||
1913 | 364 | topMargin.append("0"); | ||
1914 | 365 | } else { | ||
1915 | 366 | // Taken from Panel.panelHeight | ||
1916 | 367 | topMargin.append("units.gu(3) + units.dp(2)"); | ||
1917 | 368 | } | ||
1918 | 369 | |||
1919 | 370 | QString windowQml = QString( | ||
1920 | 371 | "import QtQuick 2.0\n" | ||
1921 | 372 | "Image {\n" | ||
1922 | 373 | " anchors.fill: parent\n" | ||
1923 | 374 | " anchors.topMargin: %1\n" | ||
1924 | 375 | " anchors.rightMargin: %2\n" | ||
1925 | 376 | " source: \"file://%3/Dash/graphics/phone/screenshots/%4.png\"\n" | ||
1926 | 377 | " smooth: true\n" | ||
1927 | 378 | " fillMode: Image.PreserveAspectCrop\n" | ||
1928 | 379 | "}").arg(topMargin) | ||
1929 | 380 | .arg(m_rightMargin) | ||
1930 | 381 | .arg(qmlDirectory()) | ||
1931 | 382 | .arg(application->icon().toString()); | ||
1932 | 383 | application->setWindowQml(windowQml); | ||
1933 | 384 | |||
1934 | 385 | QString imageQml = QString( | ||
1935 | 386 | "import QtQuick 2.0\n" | ||
1936 | 387 | "Image {\n" | ||
1937 | 388 | " anchors.fill: parent\n" | ||
1938 | 389 | " source: \"file://%1/Dash/graphics/phone/screenshots/%2.png\"\n" | ||
1939 | 390 | " smooth: true\n" | ||
1940 | 391 | " fillMode: Image.PreserveAspectCrop\n" | ||
1941 | 392 | "}").arg(qmlDirectory()) | ||
1942 | 393 | .arg(application->icon().toString()); | ||
1943 | 394 | application->setImageQml(imageQml); | ||
1944 | 395 | |||
1945 | 396 | application->setScreenshot(QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png").arg(qmlDirectory()) | 343 | application->setScreenshot(QString("file://%1/Dash/graphics/phone/screenshots/%2@12.png").arg(qmlDirectory()) |
1946 | 397 | .arg(application->icon().toString())); | 344 | .arg(application->icon().toString())); |
1947 | 398 | } | 345 | } |
1948 | @@ -402,6 +349,14 @@ | |||
1949 | 402 | ApplicationInfo *application; | 349 | ApplicationInfo *application; |
1950 | 403 | 350 | ||
1951 | 404 | application = new ApplicationInfo(this); | 351 | application = new ApplicationInfo(this); |
1952 | 352 | application->setAppId("unity8-dash"); | ||
1953 | 353 | application->setName("Unity 8 Mock Dash"); | ||
1954 | 354 | application->setIcon(QUrl("unity8-dash")); | ||
1955 | 355 | application->setStage(ApplicationInfo::MainStage); | ||
1956 | 356 | generateQmlStrings(application); | ||
1957 | 357 | m_availableApplications.append(application); | ||
1958 | 358 | |||
1959 | 359 | application = new ApplicationInfo(this); | ||
1960 | 405 | application->setAppId("dialer-app"); | 360 | application->setAppId("dialer-app"); |
1961 | 406 | application->setName("Dialer"); | 361 | application->setName("Dialer"); |
1962 | 407 | application->setIcon(QUrl("dialer")); | 362 | application->setIcon(QUrl("dialer")); |
1963 | @@ -521,78 +476,6 @@ | |||
1964 | 521 | m_availableApplications.append(application); | 476 | m_availableApplications.append(application); |
1965 | 522 | } | 477 | } |
1966 | 523 | 478 | ||
1967 | 524 | void ApplicationManager::createMainStageComponent() | ||
1968 | 525 | { | ||
1969 | 526 | // The assumptions I make here really should hold. | ||
1970 | 527 | QQuickView *quickView = | ||
1971 | 528 | qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]); | ||
1972 | 529 | |||
1973 | 530 | QQmlEngine *engine = quickView->engine(); | ||
1974 | 531 | |||
1975 | 532 | m_mainStageComponent = new QQmlComponent(engine, this); | ||
1976 | 533 | QString mainStageQml = | ||
1977 | 534 | "import QtQuick 2.0\n" | ||
1978 | 535 | "Rectangle {\n" | ||
1979 | 536 | " anchors.fill: parent\n" | ||
1980 | 537 | " color: 'black'\n" | ||
1981 | 538 | " z: -2000\n" | ||
1982 | 539 | "}\n"; | ||
1983 | 540 | m_mainStageComponent->setData(mainStageQml.toLatin1(), QUrl()); | ||
1984 | 541 | } | ||
1985 | 542 | |||
1986 | 543 | void ApplicationManager::createMainStage() | ||
1987 | 544 | { | ||
1988 | 545 | if (!m_mainStageComponent) | ||
1989 | 546 | createMainStageComponent(); | ||
1990 | 547 | |||
1991 | 548 | // The assumptions I make here really should hold. | ||
1992 | 549 | QQuickView *quickView = | ||
1993 | 550 | qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]); | ||
1994 | 551 | |||
1995 | 552 | QQuickItem *shell = quickView->rootObject(); | ||
1996 | 553 | |||
1997 | 554 | m_mainStage = qobject_cast<QQuickItem *>(m_mainStageComponent->create()); | ||
1998 | 555 | m_mainStage->setParentItem(shell); | ||
1999 | 556 | } | ||
2000 | 557 | |||
2001 | 558 | void ApplicationManager::createSideStageComponent() | ||
2002 | 559 | { | ||
2003 | 560 | // The assumptions I make here really should hold. | ||
2004 | 561 | QQuickView *quickView = | ||
2005 | 562 | qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]); | ||
2006 | 563 | |||
2007 | 564 | QQmlEngine *engine = quickView->engine(); | ||
2008 | 565 | |||
2009 | 566 | m_sideStageComponent = new QQmlComponent(engine, this); | ||
2010 | 567 | QString sideStageQml = | ||
2011 | 568 | "import QtQuick 2.0\n" | ||
2012 | 569 | "import Ubuntu.Components 0.1\n" | ||
2013 | 570 | "Item {\n" | ||
2014 | 571 | " width: units.gu(40)\n" // from SideStage in Shell.qml | ||
2015 | 572 | " anchors.top: parent.top\n" | ||
2016 | 573 | " anchors.bottom: parent.bottom\n" | ||
2017 | 574 | " anchors.right: parent.right\n" | ||
2018 | 575 | " z: -1000\n" | ||
2019 | 576 | "}\n"; | ||
2020 | 577 | m_sideStageComponent->setData(sideStageQml.toLatin1(), QUrl()); | ||
2021 | 578 | } | ||
2022 | 579 | |||
2023 | 580 | void ApplicationManager::createSideStage() | ||
2024 | 581 | { | ||
2025 | 582 | if (!m_sideStageComponent) | ||
2026 | 583 | createSideStageComponent(); | ||
2027 | 584 | |||
2028 | 585 | // The assumptions I make here really should hold. | ||
2029 | 586 | QQuickView *quickView = | ||
2030 | 587 | qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]); | ||
2031 | 588 | |||
2032 | 589 | QQuickItem *shell = quickView->rootObject(); | ||
2033 | 590 | |||
2034 | 591 | m_sideStage = qobject_cast<QQuickItem *>(m_sideStageComponent->create()); | ||
2035 | 592 | m_sideStage->setParentItem(shell); | ||
2036 | 593 | m_sideStage->setFlag(QQuickItem::ItemHasContents, false); | ||
2037 | 594 | } | ||
2038 | 595 | |||
2039 | 596 | QStringList ApplicationManager::availableApplications() | 479 | QStringList ApplicationManager::availableApplications() |
2040 | 597 | { | 480 | { |
2041 | 598 | QStringList appIds; | 481 | QStringList appIds; |
2042 | @@ -602,19 +485,6 @@ | |||
2043 | 602 | return appIds; | 485 | return appIds; |
2044 | 603 | } | 486 | } |
2045 | 604 | 487 | ||
2046 | 605 | int ApplicationManager::rightMargin() const | ||
2047 | 606 | { | ||
2048 | 607 | return m_rightMargin; | ||
2049 | 608 | } | ||
2050 | 609 | |||
2051 | 610 | void ApplicationManager::setRightMargin(int rightMargin) | ||
2052 | 611 | { | ||
2053 | 612 | m_rightMargin = rightMargin; | ||
2054 | 613 | Q_FOREACH(ApplicationInfo *app, m_availableApplications) { | ||
2055 | 614 | generateQmlStrings(app); | ||
2056 | 615 | } | ||
2057 | 616 | } | ||
2058 | 617 | |||
2059 | 618 | bool ApplicationManager::isEmpty() const | 488 | bool ApplicationManager::isEmpty() const |
2060 | 619 | { | 489 | { |
2061 | 620 | return m_runningApplications.isEmpty(); | 490 | return m_runningApplications.isEmpty(); |
2062 | 621 | 491 | ||
2063 | === modified file 'tests/mocks/Unity/Application/ApplicationManager.h' | |||
2064 | --- tests/mocks/Unity/Application/ApplicationManager.h 2014-07-24 19:22:20 +0000 | |||
2065 | +++ tests/mocks/Unity/Application/ApplicationManager.h 2014-08-05 11:53:58 +0000 | |||
2066 | @@ -44,10 +44,6 @@ | |||
2067 | 44 | 44 | ||
2068 | 45 | Q_PROPERTY(bool fake READ fake CONSTANT) | 45 | Q_PROPERTY(bool fake READ fake CONSTANT) |
2069 | 46 | 46 | ||
2070 | 47 | // Only for testing | ||
2071 | 48 | // This can be used to place some controls to right, like make tryPhoneStage for example | ||
2072 | 49 | Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin) | ||
2073 | 50 | |||
2074 | 51 | public: | 47 | public: |
2075 | 52 | ApplicationManager(QObject *parent = NULL); | 48 | ApplicationManager(QObject *parent = NULL); |
2076 | 53 | virtual ~ApplicationManager(); | 49 | virtual ~ApplicationManager(); |
2077 | @@ -108,8 +104,6 @@ | |||
2078 | 108 | 104 | ||
2079 | 109 | // Only for testing | 105 | // Only for testing |
2080 | 110 | Q_INVOKABLE QStringList availableApplications(); | 106 | Q_INVOKABLE QStringList availableApplications(); |
2081 | 111 | int rightMargin() const; | ||
2082 | 112 | void setRightMargin(int rightMargin); | ||
2083 | 113 | 107 | ||
2084 | 114 | QModelIndex findIndex(ApplicationInfo* application); | 108 | QModelIndex findIndex(ApplicationInfo* application); |
2085 | 115 | 109 | ||
2086 | @@ -126,19 +120,9 @@ | |||
2087 | 126 | void showApplicationWindow(ApplicationInfo *application); | 120 | void showApplicationWindow(ApplicationInfo *application); |
2088 | 127 | void buildListOfAvailableApplications(); | 121 | void buildListOfAvailableApplications(); |
2089 | 128 | void generateQmlStrings(ApplicationInfo *application); | 122 | void generateQmlStrings(ApplicationInfo *application); |
2090 | 129 | void createMainStageComponent(); | ||
2091 | 130 | void createMainStage(); | ||
2092 | 131 | void createSideStageComponent(); | ||
2093 | 132 | void createSideStage(); | ||
2094 | 133 | bool m_suspended; | 123 | bool m_suspended; |
2095 | 134 | QList<ApplicationInfo*> m_runningApplications; | 124 | QList<ApplicationInfo*> m_runningApplications; |
2096 | 135 | QList<ApplicationInfo*> m_availableApplications; | 125 | QList<ApplicationInfo*> m_availableApplications; |
2097 | 136 | QQmlComponent *m_mainStageComponent; | ||
2098 | 137 | QQuickItem *m_mainStage; | ||
2099 | 138 | QQmlComponent *m_sideStageComponent; | ||
2100 | 139 | QQuickItem *m_sideStage; | ||
2101 | 140 | |||
2102 | 141 | int m_rightMargin; | ||
2103 | 142 | 126 | ||
2104 | 143 | static ApplicationManager *the_application_manager; | 127 | static ApplicationManager *the_application_manager; |
2105 | 144 | }; | 128 | }; |
2106 | 145 | 129 | ||
2107 | === modified file 'tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp' | |||
2108 | --- tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp 2014-04-02 15:33:33 +0000 | |||
2109 | +++ tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp 2014-08-05 11:53:58 +0000 | |||
2110 | @@ -64,7 +64,7 @@ | |||
2111 | 64 | Q_FOREACH (QWindow *win, unity->allWindows()) { | 64 | Q_FOREACH (QWindow *win, unity->allWindows()) { |
2112 | 65 | QQuickWindow *quickWin = qobject_cast<QQuickWindow*>(win); | 65 | QQuickWindow *quickWin = qobject_cast<QQuickWindow*>(win); |
2113 | 66 | if (quickWin) { | 66 | if (quickWin) { |
2115 | 67 | image = image.scaledToWidth(quickWin->width() - m_appManager->rightMargin()); | 67 | image = image.scaledToWidth(quickWin->width()); |
2116 | 68 | break; | 68 | break; |
2117 | 69 | } | 69 | } |
2118 | 70 | } | 70 | } |
2119 | 71 | 71 | ||
2120 | === modified file 'tests/mocks/Unity/CMakeLists.txt' | |||
2121 | --- tests/mocks/Unity/CMakeLists.txt 2014-07-25 13:25:45 +0000 | |||
2122 | +++ tests/mocks/Unity/CMakeLists.txt 2014-08-05 11:53:58 +0000 | |||
2123 | @@ -2,6 +2,7 @@ | |||
2124 | 2 | add_subdirectory(Indicators) | 2 | add_subdirectory(Indicators) |
2125 | 3 | add_subdirectory(Launcher) | 3 | add_subdirectory(Launcher) |
2126 | 4 | add_subdirectory(Notifications) | 4 | add_subdirectory(Notifications) |
2127 | 5 | add_subdirectory(DashCommunicator) | ||
2128 | 5 | 6 | ||
2129 | 6 | pkg_search_module(DEE dee-1.0 REQUIRED) | 7 | pkg_search_module(DEE dee-1.0 REQUIRED) |
2130 | 7 | pkg_search_module(GOBJECT gobject-2.0 REQUIRED) | 8 | pkg_search_module(GOBJECT gobject-2.0 REQUIRED) |
2131 | 8 | 9 | ||
2132 | === added directory 'tests/mocks/Unity/DashCommunicator' | |||
2133 | === added file 'tests/mocks/Unity/DashCommunicator/CMakeLists.txt' | |||
2134 | --- tests/mocks/Unity/DashCommunicator/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
2135 | +++ tests/mocks/Unity/DashCommunicator/CMakeLists.txt 2014-08-05 11:53:58 +0000 | |||
2136 | @@ -0,0 +1,18 @@ | |||
2137 | 1 | include_directories( | ||
2138 | 2 | ${CMAKE_CURRENT_SOURCE_DIR} | ||
2139 | 3 | ) | ||
2140 | 4 | |||
2141 | 5 | set(QMLDASHCOMMUNICATORPLUGIN_SRC | ||
2142 | 6 | plugin.cpp | ||
2143 | 7 | dashcommunicatorservice.cpp | ||
2144 | 8 | dashcommunicator.cpp | ||
2145 | 9 | ) | ||
2146 | 10 | |||
2147 | 11 | add_library(MockDashCommunicator-qml MODULE | ||
2148 | 12 | ${QMLDASHCOMMUNICATORPLUGIN_SRC} | ||
2149 | 13 | ) | ||
2150 | 14 | |||
2151 | 15 | qt5_use_modules(MockDashCommunicator-qml DBus Qml) | ||
2152 | 16 | |||
2153 | 17 | # export the qmldir and qmltypes files | ||
2154 | 18 | add_unity8_mock(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS MockDashCommunicator-qml) | ||
2155 | 0 | 19 | ||
2156 | === added file 'tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp' | |||
2157 | --- tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp 1970-01-01 00:00:00 +0000 | |||
2158 | +++ tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp 2014-08-05 11:53:58 +0000 | |||
2159 | @@ -0,0 +1,37 @@ | |||
2160 | 1 | /* | ||
2161 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
2162 | 3 | * | ||
2163 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2164 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2165 | 6 | * the Free Software Foundation. | ||
2166 | 7 | * | ||
2167 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2168 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2169 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2170 | 11 | * Lesser General Public License for more details. | ||
2171 | 12 | * | ||
2172 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2173 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2174 | 15 | */ | ||
2175 | 16 | |||
2176 | 17 | #include "dashcommunicator.h" | ||
2177 | 18 | |||
2178 | 19 | #include <QObject> | ||
2179 | 20 | #include <QDBusConnection> | ||
2180 | 21 | #include <QDBusInterface> | ||
2181 | 22 | #include <QDebug> | ||
2182 | 23 | |||
2183 | 24 | DashCommunicator::DashCommunicator(QObject *parent): | ||
2184 | 25 | QObject(parent) | ||
2185 | 26 | { | ||
2186 | 27 | } | ||
2187 | 28 | |||
2188 | 29 | DashCommunicator::~DashCommunicator() | ||
2189 | 30 | { | ||
2190 | 31 | } | ||
2191 | 32 | |||
2192 | 33 | |||
2193 | 34 | void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset) | ||
2194 | 35 | { | ||
2195 | 36 | Q_EMIT setCurrentScopeCalled(scopeId, animate, reset); | ||
2196 | 37 | } | ||
2197 | 0 | 38 | ||
2198 | === added file 'tests/mocks/Unity/DashCommunicator/dashcommunicator.h' | |||
2199 | --- tests/mocks/Unity/DashCommunicator/dashcommunicator.h 1970-01-01 00:00:00 +0000 | |||
2200 | +++ tests/mocks/Unity/DashCommunicator/dashcommunicator.h 2014-08-05 11:53:58 +0000 | |||
2201 | @@ -0,0 +1,39 @@ | |||
2202 | 1 | /* | ||
2203 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
2204 | 3 | * | ||
2205 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2206 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2207 | 6 | * the Free Software Foundation. | ||
2208 | 7 | * | ||
2209 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2210 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2211 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2212 | 11 | * Lesser General Public License for more details. | ||
2213 | 12 | * | ||
2214 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2215 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2216 | 15 | */ | ||
2217 | 16 | |||
2218 | 17 | #ifndef DASHCOMMUNICATOR_H | ||
2219 | 18 | #define DASHCOMMUNICATOR_H | ||
2220 | 19 | |||
2221 | 20 | #include <QObject> | ||
2222 | 21 | |||
2223 | 22 | class DashCommunicator: public QObject | ||
2224 | 23 | { | ||
2225 | 24 | Q_OBJECT | ||
2226 | 25 | Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator") | ||
2227 | 26 | |||
2228 | 27 | public: | ||
2229 | 28 | DashCommunicator(QObject *parent = 0); | ||
2230 | 29 | ~DashCommunicator(); | ||
2231 | 30 | |||
2232 | 31 | public Q_SLOTS: | ||
2233 | 32 | void setCurrentScope(const QString &scopeId, bool animate, bool reset); | ||
2234 | 33 | |||
2235 | 34 | Q_SIGNALS: | ||
2236 | 35 | // This mock just emits calls back to the QML api for the plugin to verify calls | ||
2237 | 36 | void setCurrentScopeCalled(const QString &scopeId, bool animate, bool reset); | ||
2238 | 37 | }; | ||
2239 | 38 | |||
2240 | 39 | #endif | ||
2241 | 0 | 40 | ||
2242 | === added file 'tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp' | |||
2243 | --- tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp 1970-01-01 00:00:00 +0000 | |||
2244 | +++ tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp 2014-08-05 11:53:58 +0000 | |||
2245 | @@ -0,0 +1,33 @@ | |||
2246 | 1 | /* | ||
2247 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
2248 | 3 | * | ||
2249 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2250 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2251 | 6 | * the Free Software Foundation. | ||
2252 | 7 | * | ||
2253 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2254 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2255 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2256 | 11 | * Lesser General Public License for more details. | ||
2257 | 12 | * | ||
2258 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2259 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2260 | 15 | */ | ||
2261 | 16 | |||
2262 | 17 | #include "dashcommunicatorservice.h" | ||
2263 | 18 | |||
2264 | 19 | DashCommunicatorService::DashCommunicatorService(QObject *parent): | ||
2265 | 20 | QObject(parent) | ||
2266 | 21 | { | ||
2267 | 22 | } | ||
2268 | 23 | |||
2269 | 24 | |||
2270 | 25 | DashCommunicatorService::~DashCommunicatorService() | ||
2271 | 26 | { | ||
2272 | 27 | |||
2273 | 28 | } | ||
2274 | 29 | |||
2275 | 30 | void DashCommunicatorService::mockSetCurrentScope(const QString &scopeId, bool animate, bool reset) | ||
2276 | 31 | { | ||
2277 | 32 | Q_EMIT setCurrentScopeRequested(scopeId, animate, reset); | ||
2278 | 33 | } | ||
2279 | 0 | 34 | ||
2280 | === added file 'tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h' | |||
2281 | --- tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h 1970-01-01 00:00:00 +0000 | |||
2282 | +++ tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h 2014-08-05 11:53:58 +0000 | |||
2283 | @@ -0,0 +1,36 @@ | |||
2284 | 1 | /* | ||
2285 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
2286 | 3 | * | ||
2287 | 4 | * This program is free software: you can redistribute it and/or modify it under | ||
2288 | 5 | * the terms of the GNU Lesser General Public License version 3, as published by | ||
2289 | 6 | * the Free Software Foundation. | ||
2290 | 7 | * | ||
2291 | 8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
2292 | 9 | * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY, | ||
2293 | 10 | * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
2294 | 11 | * Lesser General Public License for more details. | ||
2295 | 12 | * | ||
2296 | 13 | * You should have received a copy of the GNU Lesser General Public License | ||
2297 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2298 | 15 | */ | ||
2299 | 16 | |||
2300 | 17 | #ifndef DASHCOMMUNICATORSERVICE_H | ||
2301 | 18 | #define DASHCOMMUNICATORSERVICE_H | ||
2302 | 19 | |||
2303 | 20 | #include <QObject> | ||
2304 | 21 | |||
2305 | 22 | class DashCommunicatorService: public QObject | ||
2306 | 23 | { | ||
2307 | 24 | Q_OBJECT | ||
2308 | 25 | public: | ||
2309 | 26 | DashCommunicatorService(QObject *parent = 0); | ||
2310 | 27 | ~DashCommunicatorService(); | ||
2311 | 28 | |||
2312 | 29 | Q_SIGNALS: | ||
2313 | 30 | void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset); | ||
2314 | 31 | |||
2315 | 32 | public Q_SLOTS: | ||
2316 | 33 | void mockSetCurrentScope(const QString &scopeId, bool animate, bool reset); | ||
2317 | 34 | }; | ||
2318 | 35 | |||
2319 | 36 | #endif // DBUSUNITYSESSIONSERVICE_H | ||
2320 | 0 | 37 | ||
2321 | === added file 'tests/mocks/Unity/DashCommunicator/plugin.cpp' | |||
2322 | --- tests/mocks/Unity/DashCommunicator/plugin.cpp 1970-01-01 00:00:00 +0000 | |||
2323 | +++ tests/mocks/Unity/DashCommunicator/plugin.cpp 2014-08-05 11:53:58 +0000 | |||
2324 | @@ -0,0 +1,31 @@ | |||
2325 | 1 | /* | ||
2326 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
2327 | 3 | * | ||
2328 | 4 | * This program is free software; you can redistribute it and/or modify | ||
2329 | 5 | * it under the terms of the GNU General Public License as published by | ||
2330 | 6 | * the Free Software Foundation; version 3. | ||
2331 | 7 | * | ||
2332 | 8 | * This program is distributed in the hope that it will be useful, | ||
2333 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2334 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2335 | 11 | * GNU General Public License for more details. | ||
2336 | 12 | * | ||
2337 | 13 | * You should have received a copy of the GNU General Public License | ||
2338 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2339 | 15 | * | ||
2340 | 16 | * Authors: Michael Zanetti <michael.zanetti@canonical.com> | ||
2341 | 17 | */ | ||
2342 | 18 | |||
2343 | 19 | #include "plugin.h" | ||
2344 | 20 | #include "dashcommunicator.h" | ||
2345 | 21 | #include "dashcommunicatorservice.h" | ||
2346 | 22 | |||
2347 | 23 | #include <QDBusConnection> | ||
2348 | 24 | #include <QtQml/qqml.h> | ||
2349 | 25 | |||
2350 | 26 | void DashCommunicatorPlugin::registerTypes(const char *uri) | ||
2351 | 27 | { | ||
2352 | 28 | Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator")); | ||
2353 | 29 | qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService"); | ||
2354 | 30 | qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator"); | ||
2355 | 31 | } | ||
2356 | 0 | 32 | ||
2357 | === added file 'tests/mocks/Unity/DashCommunicator/plugin.h' | |||
2358 | --- tests/mocks/Unity/DashCommunicator/plugin.h 1970-01-01 00:00:00 +0000 | |||
2359 | +++ tests/mocks/Unity/DashCommunicator/plugin.h 2014-08-05 11:53:58 +0000 | |||
2360 | @@ -0,0 +1,34 @@ | |||
2361 | 1 | /* | ||
2362 | 2 | * Copyright (C) 2014 Canonical, Ltd. | ||
2363 | 3 | * | ||
2364 | 4 | * This program is free software; you can redistribute it and/or modify | ||
2365 | 5 | * it under the terms of the GNU General Public License as published by | ||
2366 | 6 | * the Free Software Foundation; version 3. | ||
2367 | 7 | * | ||
2368 | 8 | * This program is distributed in the hope that it will be useful, | ||
2369 | 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
2370 | 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
2371 | 11 | * GNU General Public License for more details. | ||
2372 | 12 | * | ||
2373 | 13 | * You should have received a copy of the GNU General Public License | ||
2374 | 14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2375 | 15 | * | ||
2376 | 16 | * Authors: Michael Zanetti <michael.zanetti@canonical.com> | ||
2377 | 17 | */ | ||
2378 | 18 | |||
2379 | 19 | #ifndef DASHCOMMUNICATOR_PLUGIN_H | ||
2380 | 20 | #define DASHCOMMUNICATOR_PLUGIN_H | ||
2381 | 21 | |||
2382 | 22 | #include <QtQml/QQmlEngine> | ||
2383 | 23 | #include <QtQml/QQmlExtensionPlugin> | ||
2384 | 24 | |||
2385 | 25 | class DashCommunicatorPlugin : public QQmlExtensionPlugin | ||
2386 | 26 | { | ||
2387 | 27 | Q_OBJECT | ||
2388 | 28 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface") | ||
2389 | 29 | |||
2390 | 30 | public: | ||
2391 | 31 | void registerTypes(const char *uri); | ||
2392 | 32 | }; | ||
2393 | 33 | |||
2394 | 34 | #endif | ||
2395 | 0 | 35 | ||
2396 | === added file 'tests/mocks/Unity/DashCommunicator/qmldir' | |||
2397 | --- tests/mocks/Unity/DashCommunicator/qmldir 1970-01-01 00:00:00 +0000 | |||
2398 | +++ tests/mocks/Unity/DashCommunicator/qmldir 2014-08-05 11:53:58 +0000 | |||
2399 | @@ -0,0 +1,3 @@ | |||
2400 | 1 | module Unity.DashCommunicator | ||
2401 | 2 | plugin MockDashCommunicator-qml | ||
2402 | 3 | typeinfo DashCommunicator.qmltypes | ||
2403 | 0 | 4 | ||
2404 | === modified file 'tests/qmltests/Dash/tst_Dash.qml' | |||
2405 | --- tests/qmltests/Dash/tst_Dash.qml 2014-07-11 11:45:45 +0000 | |||
2406 | +++ tests/qmltests/Dash/tst_Dash.qml 2014-08-05 11:53:58 +0000 | |||
2407 | @@ -59,6 +59,7 @@ | |||
2408 | 59 | verify(dashContentList != undefined); | 59 | verify(dashContentList != undefined); |
2409 | 60 | tryCompare(dashContentList, "count", 0); | 60 | tryCompare(dashContentList, "count", 0); |
2410 | 61 | scopes.load(); | 61 | scopes.load(); |
2411 | 62 | tryCompare(dashContentList, "currentIndex", 0); | ||
2412 | 62 | } | 63 | } |
2413 | 63 | 64 | ||
2414 | 64 | function get_scope_data() { | 65 | function get_scope_data() { |
2415 | @@ -91,5 +92,23 @@ | |||
2416 | 91 | verify(dashContentList != undefined); | 92 | verify(dashContentList != undefined); |
2417 | 92 | tryCompare(dashContentList, "currentIndex", data.visualIndex); | 93 | tryCompare(dashContentList, "currentIndex", data.visualIndex); |
2418 | 93 | } | 94 | } |
2419 | 95 | |||
2420 | 96 | function test_setCurrentScope() { | ||
2421 | 97 | var dashContentList = findChild(dash, "dashContentList"); | ||
2422 | 98 | var startX = dash.width - units.gu(1); | ||
2423 | 99 | var startY = dash.height / 2; | ||
2424 | 100 | var stopX = units.gu(1) | ||
2425 | 101 | var stopY = startY; | ||
2426 | 102 | var retry = 0; | ||
2427 | 103 | while (dashContentList.currentIndex != 2 && retry <= 5) { | ||
2428 | 104 | mouseFlick(dash, startX, startY, stopX, stopY) | ||
2429 | 105 | waitForRendering(dashContentList) | ||
2430 | 106 | retry++; | ||
2431 | 107 | } | ||
2432 | 108 | compare(dashContentList.currentIndex, 2); | ||
2433 | 109 | var dashCommunicatorService = findInvisibleChild(dash, "dashCommunicatorService"); | ||
2434 | 110 | dashCommunicatorService.mockSetCurrentScope("clickscope", true, true); | ||
2435 | 111 | tryCompare(dashContentList, "currentIndex", 1) | ||
2436 | 112 | } | ||
2437 | 94 | } | 113 | } |
2438 | 95 | } | 114 | } |
2439 | 96 | 115 | ||
2440 | === modified file 'tests/qmltests/Stages/tst_PhoneStage.qml' | |||
2441 | --- tests/qmltests/Stages/tst_PhoneStage.qml 2014-07-24 21:56:42 +0000 | |||
2442 | +++ tests/qmltests/Stages/tst_PhoneStage.qml 2014-08-05 11:53:58 +0000 | |||
2443 | @@ -231,9 +231,10 @@ | |||
2444 | 231 | } | 231 | } |
2445 | 232 | 232 | ||
2446 | 233 | function cleanup() { | 233 | function cleanup() { |
2448 | 234 | while (ApplicationManager.count > 0) { | 234 | while (ApplicationManager.count > 1) { |
2449 | 235 | var oldCount = ApplicationManager.count; | 235 | var oldCount = ApplicationManager.count; |
2451 | 236 | ApplicationManager.stopApplication(ApplicationManager.get(0).appId) | 236 | var closingIndex = ApplicationManager.focusedApplicationId == "unity8-dash" ? 1 : 0 |
2452 | 237 | ApplicationManager.stopApplication(ApplicationManager.get(closingIndex).appId) | ||
2453 | 237 | tryCompare(ApplicationManager, "count", oldCount - 1) | 238 | tryCompare(ApplicationManager, "count", oldCount - 1) |
2454 | 238 | } | 239 | } |
2455 | 239 | } | 240 | } |
2456 | 240 | 241 | ||
2457 | === modified file 'tests/qmltests/tst_Shell.qml' | |||
2458 | --- tests/qmltests/tst_Shell.qml 2014-07-28 12:48:29 +0000 | |||
2459 | +++ tests/qmltests/tst_Shell.qml 2014-08-05 11:53:58 +0000 | |||
2460 | @@ -56,49 +56,20 @@ | |||
2461 | 56 | signalName: "sessionStarted" | 56 | signalName: "sessionStarted" |
2462 | 57 | } | 57 | } |
2463 | 58 | 58 | ||
2464 | 59 | SignalSpy { | ||
2465 | 60 | id: dashCommunicatorSpy | ||
2466 | 61 | signalName: "setCurrentScopeCalled" | ||
2467 | 62 | } | ||
2468 | 63 | |||
2469 | 59 | UT.UnityTestCase { | 64 | UT.UnityTestCase { |
2470 | 60 | name: "Shell" | 65 | name: "Shell" |
2471 | 61 | when: windowShown | 66 | when: windowShown |
2472 | 62 | 67 | ||
2473 | 63 | function initTestCase() { | 68 | function initTestCase() { |
2474 | 64 | var ok = false; | ||
2475 | 65 | var attempts = 0; | ||
2476 | 66 | var maxAttempts = 1000; | ||
2477 | 67 | |||
2478 | 68 | // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in | ||
2479 | 69 | // tests may fail because the desired child item wasn't loaded yet. | ||
2480 | 70 | // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests. | ||
2481 | 71 | // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded | ||
2482 | 72 | // (all items instantiated, etc), I resort to checking the existence of some key items until | ||
2483 | 73 | // repeatedly until they're all there. | ||
2484 | 74 | do { | ||
2485 | 75 | var dashContentList = findChild(shell, "dashContentList"); | ||
2486 | 76 | waitForRendering(dashContentList); | ||
2487 | 77 | var homeLoader = findChild(dashContentList, "clickscope loader"); | ||
2488 | 78 | ok = homeLoader !== null | ||
2489 | 79 | && homeLoader.item !== undefined; | ||
2490 | 80 | |||
2491 | 81 | var greeter = findChild(shell, "greeter"); | ||
2492 | 82 | ok &= greeter !== null; | ||
2493 | 83 | |||
2494 | 84 | var launcherPanel = findChild(shell, "launcherPanel"); | ||
2495 | 85 | ok &= launcherPanel !== null; | ||
2496 | 86 | |||
2497 | 87 | attempts++; | ||
2498 | 88 | if (!ok) { | ||
2499 | 89 | console.log("Attempt " + attempts + " failed. Waiting a bit before trying again."); | ||
2500 | 90 | // wait a bit before retrying | ||
2501 | 91 | wait(100); | ||
2502 | 92 | } else { | ||
2503 | 93 | console.log("All seem fine after " + attempts + " attempts."); | ||
2504 | 94 | } | ||
2505 | 95 | } while (!ok && attempts <= maxAttempts); | ||
2506 | 96 | |||
2507 | 97 | verify(ok); | ||
2508 | 98 | |||
2509 | 99 | swipeAwayGreeter(); | 69 | swipeAwayGreeter(); |
2510 | 100 | 70 | ||
2511 | 101 | sessionSpy.target = findChild(shell, "greeter") | 71 | sessionSpy.target = findChild(shell, "greeter") |
2512 | 72 | dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator"); | ||
2513 | 102 | } | 73 | } |
2514 | 103 | 74 | ||
2515 | 104 | function cleanup() { | 75 | function cleanup() { |
2516 | @@ -111,56 +82,16 @@ | |||
2517 | 111 | // kill all (fake) running apps | 82 | // kill all (fake) running apps |
2518 | 112 | killApps(ApplicationManager); | 83 | killApps(ApplicationManager); |
2519 | 113 | 84 | ||
2526 | 114 | var dashContent = findChild(shell, "dashContent"); | 85 | waitForUIToSettle(); |
2521 | 115 | dashContent.closePreview(); | ||
2522 | 116 | |||
2523 | 117 | var dashHome = findChild(shell, "clickscope loader"); | ||
2524 | 118 | swipeUntilScopeViewIsReached(dashHome); | ||
2525 | 119 | |||
2527 | 120 | hideIndicators(); | 86 | hideIndicators(); |
2528 | 121 | } | 87 | } |
2529 | 122 | 88 | ||
2534 | 123 | function killApps(apps) { | 89 | function killApps() { |
2535 | 124 | if (!apps) return; | 90 | while (ApplicationManager.count > 1) { |
2536 | 125 | while (apps.count > 0) { | 91 | var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0 |
2537 | 126 | ApplicationManager.stopApplication(apps.get(0).appId); | 92 | ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId); |
2538 | 127 | } | 93 | } |
2575 | 128 | compare(ApplicationManager.count, 0) | 94 | compare(ApplicationManager.count, 1) |
2540 | 129 | } | ||
2541 | 130 | |||
2542 | 131 | /* | ||
2543 | 132 | Test the effect of a right-edge drag on the dash in 3 situations: | ||
2544 | 133 | 1 - when no application has been launched yet | ||
2545 | 134 | 2 - when there's a minimized application | ||
2546 | 135 | 3 - after the last running application has been closed/stopped | ||
2547 | 136 | |||
2548 | 137 | The behavior of Dash on 3 should be the same as on 1. | ||
2549 | 138 | */ | ||
2550 | 139 | function test_rightEdgeDrag() { | ||
2551 | 140 | checkRightEdgeDragWithNoRunningApps(); | ||
2552 | 141 | |||
2553 | 142 | dragLauncherIntoView(); | ||
2554 | 143 | |||
2555 | 144 | // Launch an app from the launcher | ||
2556 | 145 | tapOnAppIconInLauncher(); | ||
2557 | 146 | waitUntilApplicationWindowIsFullyVisible(); | ||
2558 | 147 | |||
2559 | 148 | // Minimize the application we just launched | ||
2560 | 149 | swipeFromLeftEdge(units.gu(27)); | ||
2561 | 150 | |||
2562 | 151 | waitForUIToSettle(); | ||
2563 | 152 | |||
2564 | 153 | checkRightEdgeDragWithMinimizedApp(); | ||
2565 | 154 | |||
2566 | 155 | // Minimize that application once again | ||
2567 | 156 | swipeFromLeftEdge(units.gu(27)); | ||
2568 | 157 | |||
2569 | 158 | // Right edge behavior should now be the same as before that app, | ||
2570 | 159 | // was launched. Manually cleanup beforehand to get to initial | ||
2571 | 160 | // state. | ||
2572 | 161 | cleanup(); | ||
2573 | 162 | waitForUIToSettle(); | ||
2574 | 163 | checkRightEdgeDragWithNoRunningApps(); | ||
2576 | 164 | } | 95 | } |
2577 | 165 | 96 | ||
2578 | 166 | function test_leftEdgeDrag_data() { | 97 | function test_leftEdgeDrag_data() { |
2579 | @@ -183,7 +114,7 @@ | |||
2580 | 183 | 114 | ||
2581 | 184 | swipeFromLeftEdge(data.swipeLength); | 115 | swipeFromLeftEdge(data.swipeLength); |
2582 | 185 | if (data.appHides) | 116 | if (data.appHides) |
2584 | 186 | waitUntilApplicationWindowIsFullyHidden(); | 117 | waitUntilDashIsFocused(); |
2585 | 187 | else | 118 | else |
2586 | 188 | waitUntilApplicationWindowIsFullyVisible(); | 119 | waitUntilApplicationWindowIsFullyVisible(); |
2587 | 189 | } | 120 | } |
2588 | @@ -240,99 +171,17 @@ | |||
2589 | 240 | } | 171 | } |
2590 | 241 | 172 | ||
2591 | 242 | /* | 173 | /* |
2592 | 243 | Perform a right-edge drag when the Dash is being show and there are | ||
2593 | 244 | no running/minimized apps to be restored. | ||
2594 | 245 | |||
2595 | 246 | The expected behavior is that an animation should be played to hint the | ||
2596 | 247 | user that his right-edge drag gesture has been successfully recognized | ||
2597 | 248 | but there is no application to be brought to foreground. | ||
2598 | 249 | */ | ||
2599 | 250 | function checkRightEdgeDragWithNoRunningApps() { | ||
2600 | 251 | var touchX = shell.width - (shell.edgeSize / 2); | ||
2601 | 252 | var touchY = shell.height / 2; | ||
2602 | 253 | |||
2603 | 254 | var dash = findChild(shell, "dash"); | ||
2604 | 255 | // check that dash has normal scale and opacity | ||
2605 | 256 | tryCompare(dash, "contentScale", 1.0); | ||
2606 | 257 | tryCompare(dash, "opacity", 1.0); | ||
2607 | 258 | |||
2608 | 259 | touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY, | ||
2609 | 260 | true /* beginTouch */, false /* endTouch */, units.gu(10), 50); | ||
2610 | 261 | |||
2611 | 262 | // check that Dash has been scaled down and had its opacity reduced | ||
2612 | 263 | tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true); | ||
2613 | 264 | tryCompareFunction(function() { return dash.opacity <= 0.5; }, true); | ||
2614 | 265 | |||
2615 | 266 | touchRelease(shell, shell.width * 0.1, touchY); | ||
2616 | 267 | |||
2617 | 268 | // and now everything should have gone back to normal | ||
2618 | 269 | tryCompare(dash, "contentScale", 1.0); | ||
2619 | 270 | tryCompare(dash, "opacity", 1.0); | ||
2620 | 271 | } | ||
2621 | 272 | |||
2622 | 273 | /* | ||
2623 | 274 | Perform a right-edge drag when the Dash is being show and there is | ||
2624 | 275 | a running/minimized app to be restored. | ||
2625 | 276 | |||
2626 | 277 | The expected behavior is that the dash should fade away and ultimately be | ||
2627 | 278 | made invisible once the gesture is finished as the restored app will now | ||
2628 | 279 | be on foreground. | ||
2629 | 280 | */ | ||
2630 | 281 | function checkRightEdgeDragWithMinimizedApp() { | ||
2631 | 282 | var touchX = shell.width - (shell.edgeSize / 2); | ||
2632 | 283 | var touchY = shell.height / 2; | ||
2633 | 284 | |||
2634 | 285 | var dash = findChild(shell, "dash"); | ||
2635 | 286 | // check that dash has normal scale and opacity | ||
2636 | 287 | tryCompare(dash, "contentScale", 1.0); | ||
2637 | 288 | tryCompare(dash, "opacity", 1.0); | ||
2638 | 289 | |||
2639 | 290 | touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY, | ||
2640 | 291 | true /* beginTouch */, false /* endTouch */, units.gu(10), 50); | ||
2641 | 292 | |||
2642 | 293 | // check that Dash has been scaled down and had its opacity reduced | ||
2643 | 294 | tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true); | ||
2644 | 295 | tryCompareFunction(function() { return dash.opacity <= 0.5; }, true); | ||
2645 | 296 | |||
2646 | 297 | touchRelease(shell, shell.width * 0.1, touchY); | ||
2647 | 298 | |||
2648 | 299 | // dash should have gone away, now that the app is on foreground | ||
2649 | 300 | tryCompare(dash, "visible", false); | ||
2650 | 301 | } | ||
2651 | 302 | |||
2652 | 303 | /* | ||
2653 | 304 | Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419 | 174 | Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419 |
2654 | 305 | 175 | ||
2657 | 306 | When the user minimizes an application (left-edge swipe) he should always end up in the "Running Apps" | 176 | When the user minimizes an application (left-edge swipe) he should always end up in the |
2658 | 307 | category of the "Applications" scope view. | 177 | "Applications" scope view. |
2659 | 308 | 178 | ||
2660 | 309 | Steps: | 179 | Steps: |
2664 | 310 | - go to apps lens | 180 | - reveal launcher and launch an app that covers the dash |
2662 | 311 | - scroll to the bottom | ||
2663 | 312 | - reveal launcher and launch an app | ||
2665 | 313 | - perform long left edge swipe to go minimize the app and go back to the dash. | 181 | - perform long left edge swipe to go minimize the app and go back to the dash. |
2669 | 314 | 182 | - verify the setCurrentScope() D-Bus call to the dash has been called for the correct scope id. | |
2667 | 315 | Expected Results | ||
2668 | 316 | - apps lens shown | ||
2670 | 317 | */ | 183 | */ |
2671 | 318 | function test_minimizingAppTakesToDashApps() { | 184 | function test_minimizingAppTakesToDashApps() { |
2672 | 319 | var dashApps = findChild(shell, "clickscope"); | ||
2673 | 320 | swipeUntilScopeViewIsReached(dashApps); | ||
2674 | 321 | |||
2675 | 322 | // swipe finger up until the running/recent apps section (which we assume | ||
2676 | 323 | // it's the first one) is as far from view as possible. | ||
2677 | 324 | // We also assume that DashApps is tall enough that it's scrollable | ||
2678 | 325 | var appsCategoryListView = findChild(dashApps, "categoryListView"); | ||
2679 | 326 | while (!appsCategoryListView.atYEnd) { | ||
2680 | 327 | swipeUpFromCenter(); | ||
2681 | 328 | tryCompare(appsCategoryListView, "moving", false); | ||
2682 | 329 | } | ||
2683 | 330 | |||
2684 | 331 | // Switch away from the Applications scope. | ||
2685 | 332 | swipeRightFromCenter(); | ||
2686 | 333 | waitUntilItemStopsMoving(dashApps); | ||
2687 | 334 | verify(!itemIsOnScreen(dashApps)); | ||
2688 | 335 | |||
2689 | 336 | dragLauncherIntoView(); | 185 | dragLauncherIntoView(); |
2690 | 337 | 186 | ||
2691 | 338 | // Launch an app from the launcher | 187 | // Launch an app from the launcher |
2692 | @@ -340,19 +189,16 @@ | |||
2693 | 340 | 189 | ||
2694 | 341 | waitUntilApplicationWindowIsFullyVisible(); | 190 | waitUntilApplicationWindowIsFullyVisible(); |
2695 | 342 | 191 | ||
2699 | 343 | // Dragging launcher into view with a little bit of gap (units.gu(1)) should switch to Apps scope | 192 | verify(ApplicationManager.focusedApplicationId !== "unity8-dash") |
2697 | 344 | dragLauncherIntoView(); | ||
2698 | 345 | verify(itemIsOnScreen(dashApps)); | ||
2700 | 346 | 193 | ||
2701 | 194 | dashCommunicatorSpy.clear(); | ||
2702 | 347 | // Minimize the application we just launched | 195 | // Minimize the application we just launched |
2703 | 348 | swipeFromLeftEdge(units.gu(27)); | 196 | swipeFromLeftEdge(units.gu(27)); |
2704 | 349 | 197 | ||
2709 | 350 | // Wait for the whole UI to settle down | 198 | tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash"); |
2706 | 351 | waitUntilApplicationWindowIsFullyHidden(); | ||
2707 | 352 | waitUntilItemStopsMoving(dashApps); | ||
2708 | 353 | tryCompare(appsCategoryListView, "moving", false); | ||
2710 | 354 | 199 | ||
2712 | 355 | verify(itemIsOnScreen(dashApps)); | 200 | compare(dashCommunicatorSpy.count, 1); |
2713 | 201 | compare(dashCommunicatorSpy.signalArguments[0][0], "clickscope"); | ||
2714 | 356 | } | 202 | } |
2715 | 357 | 203 | ||
2716 | 358 | function test_showInputMethod() { | 204 | function test_showInputMethod() { |
2717 | @@ -409,9 +255,14 @@ | |||
2718 | 409 | 255 | ||
2719 | 410 | // Wait for the whole UI to settle down | 256 | // Wait for the whole UI to settle down |
2720 | 411 | function waitForUIToSettle() { | 257 | function waitForUIToSettle() { |
2724 | 412 | waitUntilApplicationWindowIsFullyHidden(); | 258 | var launcher = findChild(shell, "launcherPanel") |
2725 | 413 | var dashContentList = findChild(shell, "dashContentList"); | 259 | tryCompareFunction(function() {return launcher.x === 0 || launcher.x === -launcher.width;}, true); |
2726 | 414 | tryCompare(dashContentList, "moving", false); | 260 | if (launcher.x === 0) { |
2727 | 261 | mouseClick(shell, shell.width / 2, shell.height / 2) | ||
2728 | 262 | } | ||
2729 | 263 | tryCompare(launcher, "x", -launcher.width) | ||
2730 | 264 | |||
2731 | 265 | waitForRendering(shell) | ||
2732 | 415 | } | 266 | } |
2733 | 416 | 267 | ||
2734 | 417 | function dragToCloseIndicatorsPanel() { | 268 | function dragToCloseIndicatorsPanel() { |
2735 | @@ -468,24 +319,13 @@ | |||
2736 | 468 | } | 319 | } |
2737 | 469 | 320 | ||
2738 | 470 | function waitUntilApplicationWindowIsFullyVisible() { | 321 | function waitUntilApplicationWindowIsFullyVisible() { |
2757 | 471 | var underlay = findChild(shell, "underlay"); | 322 | var appDelegate = findChild(shell, "appDelegate0") |
2758 | 472 | tryCompare(underlay, "visible", false); | 323 | var surfaceContainer = findChild(appDelegate, "surfaceContainer"); |
2759 | 473 | } | 324 | tryCompareFunction(function() { return surfaceContainer.surface !== null; }, true); |
2760 | 474 | 325 | } | |
2761 | 475 | function waitUntilApplicationWindowIsFullyHidden() { | 326 | |
2762 | 476 | var stages = findChild(shell, "stages"); | 327 | function waitUntilDashIsFocused() { |
2763 | 477 | tryCompare(stages, "fullyHidden", true); | 328 | tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash"); |
2746 | 478 | } | ||
2747 | 479 | |||
2748 | 480 | function swipeUntilScopeViewIsReached(scopeView) { | ||
2749 | 481 | while (!itemIsOnScreen(scopeView)) { | ||
2750 | 482 | if (itemIsToLeftOfScreen(scopeView)) { | ||
2751 | 483 | swipeRightFromCenter(); | ||
2752 | 484 | } else { | ||
2753 | 485 | swipeLeftFromCenter(); | ||
2754 | 486 | } | ||
2755 | 487 | waitUntilItemStopsMoving(scopeView); | ||
2756 | 488 | } | ||
2764 | 489 | } | 329 | } |
2765 | 490 | 330 | ||
2766 | 491 | function swipeFromLeftEdge(swipeLength) { | 331 | function swipeFromLeftEdge(swipeLength) { |
2767 | @@ -494,24 +334,6 @@ | |||
2768 | 494 | touchFlick(shell, touchStartX, touchStartY, swipeLength, touchStartY); | 334 | touchFlick(shell, touchStartX, touchStartY, swipeLength, touchStartY); |
2769 | 495 | } | 335 | } |
2770 | 496 | 336 | ||
2771 | 497 | function swipeLeftFromCenter() { | ||
2772 | 498 | var touchStartX = shell.width * 3 / 4; | ||
2773 | 499 | var touchStartY = shell.height / 2; | ||
2774 | 500 | touchFlick(shell, touchStartX, touchStartY, 0, touchStartY); | ||
2775 | 501 | } | ||
2776 | 502 | |||
2777 | 503 | function swipeRightFromCenter() { | ||
2778 | 504 | var touchStartX = shell.width * 3 / 4; | ||
2779 | 505 | var touchStartY = shell.height / 2; | ||
2780 | 506 | touchFlick(shell, touchStartX, touchStartY, shell.width, touchStartY); | ||
2781 | 507 | } | ||
2782 | 508 | |||
2783 | 509 | function swipeUpFromCenter() { | ||
2784 | 510 | var touchStartX = shell.width / 2; | ||
2785 | 511 | var touchStartY = shell.height / 2; | ||
2786 | 512 | touchFlick(shell, touchStartX, touchStartY, touchStartX, 0); | ||
2787 | 513 | } | ||
2788 | 514 | |||
2789 | 515 | function itemIsOnScreen(item) { | 337 | function itemIsOnScreen(item) { |
2790 | 516 | var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height); | 338 | var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height); |
2791 | 517 | 339 | ||
2792 | @@ -521,64 +343,6 @@ | |||
2793 | 521 | && itemRectInShell.y + itemRectInShell.height <= shell.height; | 343 | && itemRectInShell.y + itemRectInShell.height <= shell.height; |
2794 | 522 | } | 344 | } |
2795 | 523 | 345 | ||
2796 | 524 | function itemIsToLeftOfScreen(item) { | ||
2797 | 525 | var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height); | ||
2798 | 526 | return itemRectInShell.x < 0; | ||
2799 | 527 | } | ||
2800 | 528 | |||
2801 | 529 | function waitUntilItemStopsMoving(item) { | ||
2802 | 530 | var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height); | ||
2803 | 531 | var previousX = itemRectInShell.x; | ||
2804 | 532 | var previousY = itemRectInShell.y; | ||
2805 | 533 | var isStill = false; | ||
2806 | 534 | |||
2807 | 535 | do { | ||
2808 | 536 | wait(100); | ||
2809 | 537 | itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height); | ||
2810 | 538 | if (itemRectInShell.x == previousX && itemRectInShell.y == previousY) { | ||
2811 | 539 | isStill = true; | ||
2812 | 540 | } else { | ||
2813 | 541 | previousX = itemRectInShell.x; | ||
2814 | 542 | previousY = itemRectInShell.y; | ||
2815 | 543 | } | ||
2816 | 544 | } while (!isStill); | ||
2817 | 545 | } | ||
2818 | 546 | |||
2819 | 547 | function test_DashShown_data() { | ||
2820 | 548 | return [ | ||
2821 | 549 | {tag: "in focus", greeter: false, app: false, launcher: false, indicators: false, expectedShown: true}, | ||
2822 | 550 | {tag: "under greeter", greeter: true, app: false, launcher: false, indicators: false, expectedShown: false}, | ||
2823 | 551 | {tag: "under app", greeter: false, app: true, launcher: false, indicators: false, expectedShown: false}, | ||
2824 | 552 | {tag: "under launcher", greeter: false, app: false, launcher: true, indicators: false, expectedShown: true}, | ||
2825 | 553 | {tag: "under indicators", greeter: false, app: false, launcher: false, indicators: true, expectedShown: false}, | ||
2826 | 554 | ] | ||
2827 | 555 | } | ||
2828 | 556 | |||
2829 | 557 | function test_DashShown(data) { | ||
2830 | 558 | if (data.greeter) { | ||
2831 | 559 | // Swipe the greeter in | ||
2832 | 560 | var greeter = findChild(shell, "greeter"); | ||
2833 | 561 | Powerd.displayPowerStateChange(Powerd.Off, 0); | ||
2834 | 562 | tryCompare(greeter, "showProgress", 1); | ||
2835 | 563 | } | ||
2836 | 564 | |||
2837 | 565 | if (data.app) { | ||
2838 | 566 | dragLauncherIntoView(); | ||
2839 | 567 | tapOnAppIconInLauncher(); | ||
2840 | 568 | } | ||
2841 | 569 | |||
2842 | 570 | if (data.launcher) { | ||
2843 | 571 | dragLauncherIntoView(); | ||
2844 | 572 | } | ||
2845 | 573 | |||
2846 | 574 | if (data.indicators) { | ||
2847 | 575 | showIndicators(); | ||
2848 | 576 | } | ||
2849 | 577 | |||
2850 | 578 | var dash = findChild(shell, "dash"); | ||
2851 | 579 | tryCompare(dash, "shown", data.expectedShown); | ||
2852 | 580 | } | ||
2853 | 581 | |||
2854 | 582 | function test_focusRequestedHidesGreeter() { | 346 | function test_focusRequestedHidesGreeter() { |
2855 | 583 | var greeter = findChild(shell, "greeter"); | 347 | var greeter = findChild(shell, "greeter"); |
2856 | 584 | 348 | ||
2857 | @@ -587,10 +351,9 @@ | |||
2858 | 587 | tryCompareFunction(function() { return app.surface != null }, true); | 351 | tryCompareFunction(function() { return app.surface != null }, true); |
2859 | 588 | 352 | ||
2860 | 589 | // Minimize the application we just launched | 353 | // Minimize the application we just launched |
2862 | 590 | swipeFromLeftEdge(units.gu(27)); | 354 | swipeFromLeftEdge(units.gu(26) + 1); |
2863 | 591 | 355 | ||
2866 | 592 | // Wait for the whole UI to settle down | 356 | waitUntilDashIsFocused(); |
2865 | 593 | waitUntilApplicationWindowIsFullyHidden(); | ||
2867 | 594 | 357 | ||
2868 | 595 | greeter.show(); | 358 | greeter.show(); |
2869 | 596 | tryCompare(greeter, "showProgress", 1); | 359 | tryCompare(greeter, "showProgress", 1); |
2870 | @@ -606,8 +369,9 @@ | |||
2871 | 606 | 369 | ||
2872 | 607 | showIndicators(); | 370 | showIndicators(); |
2873 | 608 | 371 | ||
2874 | 372 | var oldCount = ApplicationManager.count; | ||
2875 | 609 | ApplicationManager.startApplication("camera-app"); | 373 | ApplicationManager.startApplication("camera-app"); |
2877 | 610 | tryCompare(ApplicationManager, "count", 1); | 374 | tryCompare(ApplicationManager, "count", oldCount + 1); |
2878 | 611 | 375 | ||
2879 | 612 | tryCompare(indicators, "fullyClosed", true); | 376 | tryCompare(indicators, "fullyClosed", true); |
2880 | 613 | } | 377 | } |
2881 | @@ -616,6 +380,7 @@ | |||
2882 | 616 | function test_showGreeterDBusCall() { | 380 | function test_showGreeterDBusCall() { |
2883 | 617 | var greeter = findChild(shell, "greeter") | 381 | var greeter = findChild(shell, "greeter") |
2884 | 618 | tryCompare(greeter, "showProgress", 0) | 382 | tryCompare(greeter, "showProgress", 0) |
2885 | 383 | waitForRendering(greeter); | ||
2886 | 619 | LightDM.Greeter.showGreeter() | 384 | LightDM.Greeter.showGreeter() |
2887 | 620 | tryCompare(greeter, "showProgress", 1) | 385 | tryCompare(greeter, "showProgress", 1) |
2888 | 621 | } | 386 | } |
2889 | @@ -624,6 +389,7 @@ | |||
2890 | 624 | sessionSpy.clear() | 389 | sessionSpy.clear() |
2891 | 625 | 390 | ||
2892 | 626 | var greeter = findChild(shell, "greeter") | 391 | var greeter = findChild(shell, "greeter") |
2893 | 392 | waitForRendering(greeter) | ||
2894 | 627 | greeter.show() | 393 | greeter.show() |
2895 | 628 | tryCompare(greeter, "showProgress", 1) | 394 | tryCompare(greeter, "showProgress", 1) |
2896 | 629 | 395 | ||
2897 | @@ -644,5 +410,26 @@ | |||
2898 | 644 | ApplicationManager.requestFocusApplication("gallery-app"); | 410 | ApplicationManager.requestFocusApplication("gallery-app"); |
2899 | 645 | tryCompare(panel, "fullscreenMode", false); | 411 | tryCompare(panel, "fullscreenMode", false); |
2900 | 646 | } | 412 | } |
2901 | 413 | |||
2902 | 414 | function test_leftEdgeDragFullscreen() { | ||
2903 | 415 | var panel = findChild(shell, "panel"); | ||
2904 | 416 | tryCompare(panel, "fullscreenMode", false) | ||
2905 | 417 | |||
2906 | 418 | ApplicationManager.startApplication("camera-app"); | ||
2907 | 419 | tryCompare(panel, "fullscreenMode", true) | ||
2908 | 420 | |||
2909 | 421 | var touchStartX = 2; | ||
2910 | 422 | var touchStartY = shell.height / 2; | ||
2911 | 423 | |||
2912 | 424 | touchFlick(shell, touchStartX, touchStartY, units.gu(2), touchStartY, true, false); | ||
2913 | 425 | |||
2914 | 426 | compare(panel.fullscreenMode, true); | ||
2915 | 427 | |||
2916 | 428 | touchFlick(shell, units.gu(2), touchStartY, units.gu(10), touchStartY, false, false); | ||
2917 | 429 | |||
2918 | 430 | tryCompare(panel, "fullscreenMode", false); | ||
2919 | 431 | |||
2920 | 432 | touchRelease(shell); | ||
2921 | 433 | } | ||
2922 | 647 | } | 434 | } |
2923 | 648 | } | 435 | } |
2924 | 649 | 436 | ||
2925 | === modified file 'tests/qmltests/tst_ShellWithPin.qml' | |||
2926 | --- tests/qmltests/tst_ShellWithPin.qml 2014-07-15 18:26:25 +0000 | |||
2927 | +++ tests/qmltests/tst_ShellWithPin.qml 2014-08-05 11:53:58 +0000 | |||
2928 | @@ -58,40 +58,6 @@ | |||
2929 | 58 | when: windowShown | 58 | when: windowShown |
2930 | 59 | 59 | ||
2931 | 60 | function initTestCase() { | 60 | function initTestCase() { |
2932 | 61 | var ok = false; | ||
2933 | 62 | var attempts = 0; | ||
2934 | 63 | var maxAttempts = 1000; | ||
2935 | 64 | |||
2936 | 65 | // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in | ||
2937 | 66 | // tests may fail because the desired child item wasn't loaded yet. | ||
2938 | 67 | // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests. | ||
2939 | 68 | // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded | ||
2940 | 69 | // (all items instantiated, etc), I resort to checking the existence of some key items until | ||
2941 | 70 | // repeatedly until they're all there. | ||
2942 | 71 | do { | ||
2943 | 72 | var dashContentList = findChild(shell, "dashContentList"); | ||
2944 | 73 | waitForRendering(dashContentList); | ||
2945 | 74 | var homeLoader = findChild(dashContentList, "clickscope loader"); | ||
2946 | 75 | ok = homeLoader !== null | ||
2947 | 76 | && homeLoader.item !== undefined; | ||
2948 | 77 | |||
2949 | 78 | var greeter = findChild(shell, "greeter"); | ||
2950 | 79 | ok &= greeter !== null; | ||
2951 | 80 | |||
2952 | 81 | var launcherPanel = findChild(shell, "launcherPanel"); | ||
2953 | 82 | ok &= launcherPanel !== null; | ||
2954 | 83 | |||
2955 | 84 | attempts++; | ||
2956 | 85 | if (!ok) { | ||
2957 | 86 | console.log("Attempt " + attempts + " failed. Waiting a bit before trying again."); | ||
2958 | 87 | // wait a bit before retrying | ||
2959 | 88 | wait(100); | ||
2960 | 89 | } else { | ||
2961 | 90 | console.log("All seem fine after " + attempts + " attempts."); | ||
2962 | 91 | } | ||
2963 | 92 | } while (!ok && attempts <= maxAttempts); | ||
2964 | 93 | |||
2965 | 94 | verify(ok); | ||
2966 | 95 | 61 | ||
2967 | 96 | sessionSpy.target = findChild(shell, "greeter") | 62 | sessionSpy.target = findChild(shell, "greeter") |
2968 | 97 | } | 63 | } |
2969 | @@ -110,10 +76,11 @@ | |||
2970 | 110 | } | 76 | } |
2971 | 111 | 77 | ||
2972 | 112 | function killApps() { | 78 | function killApps() { |
2975 | 113 | while (ApplicationManager.count > 0) { | 79 | while (ApplicationManager.count > 1) { |
2976 | 114 | ApplicationManager.stopApplication(ApplicationManager.get(0).appId) | 80 | var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0 |
2977 | 81 | ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId); | ||
2978 | 115 | } | 82 | } |
2980 | 116 | compare(ApplicationManager.count, 0) | 83 | compare(ApplicationManager.count, 1) |
2981 | 117 | } | 84 | } |
2982 | 118 | 85 | ||
2983 | 119 | function swipeAwayGreeter() { | 86 | function swipeAwayGreeter() { |
FAILED: Continuous integration, rev:1127 jenkins. qa.ubuntu. com/job/ unity8- ci/3642/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- utopic- touch/2593/ console jenkins. qa.ubuntu. com/job/ unity-phablet- qmluitests- utopic/ 644/console jenkins. qa.ubuntu. com/job/ unity8- utopic- amd64-ci/ 736/console jenkins. qa.ubuntu. com/job/ unity8- utopic- armhf-ci/ 736/console jenkins. qa.ubuntu. com/job/ unity8- utopic- i386-ci/ 736/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- utopic- armhf/3836/ console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity8- ci/3642/ rebuild
http://