Merge lp:~unity-team/unity8/dash-as-app into lp:unity8

Proposed by Michael Zanetti
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
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-team/phone-right-edge

* 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 MockApplicationManager which isn't needed any more since QtCompositor. (The fake placing of surfaces behind the shell - as unity-mir did it.). This could/should have been gone earlier, but only became a visible issue with this branch. Those changes are isolated in commit 1099.

* Adds a fake unity8-dash app (screenshot) to MockApplicationManager which will always be there, simulating the running dash app.

* 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://code.launchpad.net/~unity-team/unity-scopes-shell/drop-appid-workaround/+merge/228427
https://code.launchpad.net/~dandrader/qtmir/fix_lp1350917/+merge/229585

 * 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.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

"""
Q_SIGNALS:
    void setCurrentScope(const QString &scopeId, bool animate, bool reset);
"""

Naming signals like functions is never a good thing. I would make an effort to name it like a signal. "requestedScopeAsCurrent" or even "setCurrentScopeCalled" would do it.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> """
> Q_SIGNALS:
> void setCurrentScope(const QString &scopeId, bool animate, bool reset);
> """
>
> Naming signals like functions is never a good thing. I would make an effort to
> name it like a signal. "requestedScopeAsCurrent" or even
> "setCurrentScopeCalled" would do it.

That's in DashCommunicatorService and DBusDashCommunicatorService, to be clear.

Revision history for this message
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).

review: Needs Fixing
Revision history for this message
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.

review: Needs Fixing
Revision history for this message
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

review: Needs Fixing
Revision history for this message
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.

Revision history for this message
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 :(

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

> """
> Q_SIGNALS:
> void setCurrentScope(const QString &scopeId, bool animate, bool reset);
> """
>
> Naming signals like functions is never a good thing. I would make an effort to
> name it like a signal. "requestedScopeAsCurrent" or even
> "setCurrentScopeCalled" would do it.

fixed

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

> """
> Q_SIGNALS:
> void setCurrentScope(const QString &scopeId, bool animate, bool reset);
> """
>
> Naming signals like functions is never a good thing. I would make an effort to
> name it like a signal. "requestedScopeAsCurrent" or even
> "setCurrentScopeCalled" would do it.

fixed

Revision history for this message
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?

Revision history for this message
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

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

Did you add a 0 bytes qml/Dash/graphics/phone/screenshots/dash.png?

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.

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

> Did you add a 0 bytes qml/Dash/graphics/phone/screenshots/dash.png?
>
> 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.

Revision history for this message
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

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

+++ qml/Stages/PhoneStage.qml 2014-07-27 01:55:40 +0000
@@ -116,6 +117,8 @@ Item {
         contentWidth: spreadRow.width - shift
         contentX: -shift

+ readonly property bool isActive: shiftedContentX > 0 || spreadDragArea.dragging
+
         // 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.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> +++ qml/Stages/PhoneStage.qml 2014-07-27 01:55:40 +0000
> @@ -116,6 +117,8 @@ Item {
> contentWidth: spreadRow.width - shift
> contentX: -shift
>
> + readonly property bool isActive: shiftedContentX > 0 ||
> spreadDragArea.dragging
> +
> // 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"

Revision history for this message
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.

review: Needs Fixing
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

+ onIsActiveChanged: print("spreadView isActive changed", isActive)

Debug stuff in TabletStage.

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

> > Did you add a 0 bytes qml/Dash/graphics/phone/screenshots/dash.png?
> >
> > 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

Revision history for this message
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

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

> +++ qml/Stages/PhoneStage.qml 2014-07-27 01:55:40 +0000
> @@ -116,6 +117,8 @@ Item {
> contentWidth: spreadRow.width - shift
> contentX: -shift
>
> + readonly property bool isActive: shiftedContentX > 0 ||
> spreadDragArea.dragging
> +
> // 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.

Revision history for this message
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.

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

> + onIsActiveChanged: print("spreadView isActive changed", isActive)
>
> Debug stuff in TabletStage.

fixed

Revision history for this message
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 MockApplicationManager and fixed for qtmir in https://code.launchpad.net/~mzanetti/qtmir/always-forward-focus-requests/+merge/228659

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
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.focusedAppDelegate.x !== 0)

s/model.appId == "unity8-dash"/isDash

review: Needs Fixing
Revision history for this message
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.

Revision history for this message
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.focusedAppDelegate.x !== 0)
>
> s/model.appId == "unity8-dash"/isDash

fixed

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

Looking good.
Thanks!

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
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.

Revision history for this message
Michał Sawicz (saviq) wrote :

Failure in qmltests:

qml/Dash/Dash.qml:35:9: Cannot assign to non-existent property "onSetCurrentScopeRequested"

review: Needs Fixing
lp:~unity-team/unity8/dash-as-app updated
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

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

All tests passed locally now.

review: Approve
Revision history for this message
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.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-06-11 15:36:51 +0000
+++ CMakeLists.txt 2014-08-05 11:53:58 +0000
@@ -96,6 +96,7 @@
96declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)96declare_autopilot_test(shell unity8.shell ${CMAKE_SOURCE_DIR}/tests/autopilot/)
9797
98set(SHELL_APP unity8)98set(SHELL_APP unity8)
99set(DASH_APP unity8-dash)
99set(SCOPE_TOOL unity-scope-tool)100set(SCOPE_TOOL unity-scope-tool)
100101
101include_directories(102include_directories(
102103
=== modified file 'data/CMakeLists.txt'
--- data/CMakeLists.txt 2014-06-11 15:36:51 +0000
+++ data/CMakeLists.txt 2014-08-05 11:53:58 +0000
@@ -1,7 +1,10 @@
1# generate desktop file1# generate desktop files
2configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY)2configure_file(${SHELL_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop @ONLY)
3configure_file(${DASH_APP}.desktop.in ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop @ONLY)
34
4# install desktop files5# install desktop files
5install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop6install(FILES
7 ${CMAKE_CURRENT_BINARY_DIR}/${SHELL_APP}.desktop
8 ${CMAKE_CURRENT_BINARY_DIR}/${DASH_APP}.desktop
6 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications9 DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
7 )10 )
811
=== added file 'data/unity8-dash.conf'
--- data/unity8-dash.conf 1970-01-01 00:00:00 +0000
+++ data/unity8-dash.conf 2014-08-05 11:53:58 +0000
@@ -0,0 +1,22 @@
1description "Unity Shell v8 Dash"
2author "Michael Zanetti <michael.zanetti@canonical.com>"
3
4emits scope-ui-starting
5
6start on started unity8
7stop on stopping unity8
8
9kill timeout 120
10
11respawn
12
13pre-start script
14 if [ -z "$UNITY_SCOPES_LIST" ]; then
15 # FIXME: remove once we have this in dconf
16 initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator"
17 fi
18
19 initctl emit scope-ui-starting
20end script
21
22exec ${BINARY:-unity8-dash} $ARGS --desktop_file_hint=/usr/share/applications/unity8-dash.desktop
023
=== added file 'data/unity8-dash.desktop.in'
--- data/unity8-dash.desktop.in 1970-01-01 00:00:00 +0000
+++ data/unity8-dash.desktop.in 2014-08-05 11:53:58 +0000
@@ -0,0 +1,9 @@
1[Desktop Entry]
2Type=Application
3Name=Unity 8 Dash
4Comment=The converged Unity shell dash
5Exec=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_BINDIR@/unity8-dash
6Terminal=false
7Icon=unity8
8NoDisplay=true
9X-Ubuntu-Touch=true
010
=== modified file 'data/unity8.conf'
--- data/unity8.conf 2014-07-18 16:40:56 +0000
+++ data/unity8.conf 2014-08-05 11:53:58 +0000
@@ -1,7 +1,7 @@
1description "Unity Shell v8"1description "Unity Shell v8"
2author "Ricardo Mendoza <ricmm@ubuntu.com>"2author "Ricardo Mendoza <ricmm@ubuntu.com>"
33
4emits scope-ui-starting indicator-services-start4emits indicator-services-start
55
6start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=ubuntu-touch-surfaceflinger)) and started dbus6start on ((xsession SESSION=ubuntu-touch) or (xsession SESSION=ubuntu-touch-surfaceflinger)) and started dbus
7stop on desktop-end7stop on desktop-end
@@ -34,11 +34,6 @@
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'}"
35 fi35 fi
3636
37 if [ -z "$UNITY_SCOPES_LIST" ]; then
38 # FIXME: remove once we have this in dconf
39 initctl set-env UNITY_SCOPES_LIST="scopes;clickscope;musicaggregator;videoaggregator"
40 fi
41
42 # Remove the socket if still there37 # Remove the socket if still there
43 if [ -S "$MIR_SERVER_FILE" ]; then38 if [ -S "$MIR_SERVER_FILE" ]; then
44 rm "$MIR_SERVER_FILE"39 rm "$MIR_SERVER_FILE"
@@ -46,7 +41,6 @@
4641
47 initctl set-env --global MIR_SERVER_PROMPT_FILE=142 initctl set-env --global MIR_SERVER_PROMPT_FILE=1
4843
49 initctl emit scope-ui-starting
50 initctl emit --no-wait indicator-services-start44 initctl emit --no-wait indicator-services-start
51end script45end script
5246
5347
=== modified file 'debian/unity8.install'
--- debian/unity8.install 2014-07-08 18:53:52 +0000
+++ debian/unity8.install 2014-08-05 11:53:58 +0000
@@ -1,6 +1,9 @@
1data/unity8.conf usr/share/upstart/sessions/1data/unity8.conf usr/share/upstart/sessions/
2data/unity8-dash.conf usr/share/upstart/sessions/
2usr/bin/unity83usr/bin/unity8
4usr/bin/unity8-dash
3usr/share/applications/unity8.desktop5usr/share/applications/unity8.desktop
6usr/share/applications/unity8-dash.desktop
4usr/share/unity8/Greeter7usr/share/unity8/Greeter
5usr/share/unity8/Hud8usr/share/unity8/Hud
6usr/share/unity8/Launcher9usr/share/unity8/Launcher
710
=== modified file 'plugins/Unity/CMakeLists.txt'
--- plugins/Unity/CMakeLists.txt 2014-07-08 19:09:35 +0000
+++ plugins/Unity/CMakeLists.txt 2014-08-05 11:53:58 +0000
@@ -1,3 +1,4 @@
1add_subdirectory(Indicators)1add_subdirectory(Indicators)
2add_subdirectory(Launcher)2add_subdirectory(Launcher)
3add_subdirectory(Session)3add_subdirectory(Session)
4add_subdirectory(DashCommunicator)
45
=== added directory 'plugins/Unity/DashCommunicator'
=== added file 'plugins/Unity/DashCommunicator/CMakeLists.txt'
--- plugins/Unity/DashCommunicator/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ plugins/Unity/DashCommunicator/CMakeLists.txt 2014-08-05 11:53:58 +0000
@@ -0,0 +1,19 @@
1include_directories(
2 ${CMAKE_CURRENT_SOURCE_DIR}
3)
4
5set(QMLDASHCOMMUNICATORPLUGIN_SRC
6 plugin.cpp
7 dbusdashcommunicatorservice.cpp
8 dashcommunicatorservice.cpp
9 dashcommunicator.cpp
10 )
11
12add_library(DashCommunicator-qml MODULE
13 ${QMLDASHCOMMUNICATORPLUGIN_SRC}
14 )
15
16qt5_use_modules(DashCommunicator-qml DBus Qml)
17
18# export the qmldir and qmltypes files
19add_unity8_plugin(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS DashCommunicator-qml)
020
=== added file 'plugins/Unity/DashCommunicator/dashcommunicator.cpp'
--- plugins/Unity/DashCommunicator/dashcommunicator.cpp 1970-01-01 00:00:00 +0000
+++ plugins/Unity/DashCommunicator/dashcommunicator.cpp 2014-08-05 11:53:58 +0000
@@ -0,0 +1,43 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "dashcommunicator.h"
18
19#include <QObject>
20#include <QDBusConnection>
21#include <QDBusInterface>
22#include <QDebug>
23
24DashCommunicator::DashCommunicator(QObject *parent):
25 QObject(parent)
26{
27}
28
29DashCommunicator::~DashCommunicator()
30{
31}
32
33
34void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset)
35{
36 QDBusConnection connection = QDBusConnection::sessionBus();
37 QDBusInterface dashIface ("com.canonical.UnityDash",
38 "/com/canonical/UnityDash",
39 "",
40 connection);
41
42 dashIface.call("SetCurrentScope", scopeId, animate, reset);
43}
044
=== added file 'plugins/Unity/DashCommunicator/dashcommunicator.h'
--- plugins/Unity/DashCommunicator/dashcommunicator.h 1970-01-01 00:00:00 +0000
+++ plugins/Unity/DashCommunicator/dashcommunicator.h 2014-08-05 11:53:58 +0000
@@ -0,0 +1,35 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef DASHCOMMUNICATOR_H
18#define DASHCOMMUNICATOR_H
19
20#include <QObject>
21
22class DashCommunicator: public QObject
23{
24 Q_OBJECT
25 Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26
27public:
28 DashCommunicator(QObject *parent = 0);
29 ~DashCommunicator();
30
31public Q_SLOTS:
32 void setCurrentScope(const QString &scopeId, bool animate, bool reset);
33};
34
35#endif
036
=== added file 'plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp'
--- plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp 1970-01-01 00:00:00 +0000
+++ plugins/Unity/DashCommunicator/dashcommunicatorservice.cpp 2014-08-05 11:53:58 +0000
@@ -0,0 +1,30 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "dashcommunicatorservice.h"
18
19DashCommunicatorService::DashCommunicatorService(QObject *parent):
20 QObject(parent),
21 m_dbusService(new DBusDashCommunicatorService(this))
22{
23 connect(m_dbusService, &DBusDashCommunicatorService::setCurrentScopeRequested, this, &DashCommunicatorService::setCurrentScopeRequested);
24}
25
26
27DashCommunicatorService::~DashCommunicatorService()
28{
29
30}
031
=== added file 'plugins/Unity/DashCommunicator/dashcommunicatorservice.h'
--- plugins/Unity/DashCommunicator/dashcommunicatorservice.h 1970-01-01 00:00:00 +0000
+++ plugins/Unity/DashCommunicator/dashcommunicatorservice.h 2014-08-05 11:53:58 +0000
@@ -0,0 +1,38 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef DASHCOMMUNICATORSERVICE_H
18#define DASHCOMMUNICATORSERVICE_H
19
20#include "dbusdashcommunicatorservice.h"
21
22#include <QObject>
23
24class DashCommunicatorService: public QObject
25{
26 Q_OBJECT
27public:
28 DashCommunicatorService(QObject *parent = 0);
29 ~DashCommunicatorService();
30
31Q_SIGNALS:
32 void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset);
33
34private:
35 DBusDashCommunicatorService *m_dbusService;
36};
37
38#endif // DBUSUNITYSESSIONSERVICE_H
039
=== added file 'plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp'
--- plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp 1970-01-01 00:00:00 +0000
+++ plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.cpp 2014-08-05 11:53:58 +0000
@@ -0,0 +1,39 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "dbusdashcommunicatorservice.h"
18
19#include <QDBusConnection>
20#include <QDBusInterface>
21#include <QDebug>
22
23DBusDashCommunicatorService::DBusDashCommunicatorService(QObject *parent):
24 QObject(parent)
25{
26 QDBusConnection connection = QDBusConnection::sessionBus();
27
28 connection.registerService("com.canonical.UnityDash");
29 connection.registerObject("/com/canonical/UnityDash", this, QDBusConnection::ExportScriptableSlots);
30}
31
32DBusDashCommunicatorService::~DBusDashCommunicatorService()
33{
34}
35
36void DBusDashCommunicatorService::SetCurrentScope(const QString &scopeId, bool animate, bool reset)
37{
38 Q_EMIT setCurrentScopeRequested(scopeId, animate, reset);
39}
040
=== added file 'plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h'
--- plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h 1970-01-01 00:00:00 +0000
+++ plugins/Unity/DashCommunicator/dbusdashcommunicatorservice.h 2014-08-05 11:53:58 +0000
@@ -0,0 +1,39 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef DBUSDASHCOMMUNICATORSERVICE_H
18#define DBUSDASHCOMMUNICATORSERVICE_H
19
20#include <QObject>
21
22class DBusDashCommunicatorService: public QObject
23{
24 Q_OBJECT
25 Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26
27public:
28 DBusDashCommunicatorService(QObject *parent = 0);
29 ~DBusDashCommunicatorService();
30
31Q_SIGNALS:
32 void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset);
33
34public Q_SLOTS:
35 Q_SCRIPTABLE void SetCurrentScope(const QString &scopeId, bool animate, bool reset);
36
37};
38
39#endif // DBUSUNITYSESSIONSERVICE_H
040
=== added file 'plugins/Unity/DashCommunicator/plugin.cpp'
--- plugins/Unity/DashCommunicator/plugin.cpp 1970-01-01 00:00:00 +0000
+++ plugins/Unity/DashCommunicator/plugin.cpp 2014-08-05 11:53:58 +0000
@@ -0,0 +1,31 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17 */
18
19#include "plugin.h"
20#include "dashcommunicator.h"
21#include "dashcommunicatorservice.h"
22
23#include <QDBusConnection>
24#include <QtQml/qqml.h>
25
26void DashCommunicatorPlugin::registerTypes(const char *uri)
27{
28 Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator"));
29 qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService");
30 qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator");
31}
032
=== added file 'plugins/Unity/DashCommunicator/plugin.h'
--- plugins/Unity/DashCommunicator/plugin.h 1970-01-01 00:00:00 +0000
+++ plugins/Unity/DashCommunicator/plugin.h 2014-08-05 11:53:58 +0000
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17 */
18
19#ifndef DASHCOMMUNICATOR_PLUGIN_H
20#define DASHCOMMUNICATOR_PLUGIN_H
21
22#include <QtQml/QQmlEngine>
23#include <QtQml/QQmlExtensionPlugin>
24
25class DashCommunicatorPlugin : public QQmlExtensionPlugin
26{
27 Q_OBJECT
28 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29
30public:
31 void registerTypes(const char *uri);
32};
33
34#endif
035
=== added file 'plugins/Unity/DashCommunicator/qmldir'
--- plugins/Unity/DashCommunicator/qmldir 1970-01-01 00:00:00 +0000
+++ plugins/Unity/DashCommunicator/qmldir 2014-08-05 11:53:58 +0000
@@ -0,0 +1,3 @@
1module Unity.DashCommunicator
2plugin DashCommunicator-qml
3typeinfo DashCommunicator.qmltypes
04
=== modified file 'plugins/Unity/Launcher/launchermodel.cpp'
--- plugins/Unity/Launcher/launchermodel.cpp 2014-07-25 11:29:56 +0000
+++ plugins/Unity/Launcher/launchermodel.cpp 2014-08-05 11:53:58 +0000
@@ -317,6 +317,11 @@
317 return;317 return;
318 }318 }
319319
320 if (app->appId() == "unity8-dash") {
321 // Not adding the dash app
322 return;
323 }
324
320 bool found = false;325 bool found = false;
321 Q_FOREACH(LauncherItem *item, m_list) {326 Q_FOREACH(LauncherItem *item, m_list) {
322 if (app->appId() == item->appId()) {327 if (app->appId() == item->appId()) {
323328
=== modified file 'qml/Components/EdgeDemo.qml'
--- qml/Components/EdgeDemo.qml 2014-06-11 15:36:51 +0000
+++ qml/Components/EdgeDemo.qml 2014-08-05 11:53:58 +0000
@@ -22,7 +22,6 @@
22 id: demo22 id: demo
2323
24 property Item greeter24 property Item greeter
25 property Item dash
26 property Item launcher25 property Item launcher
27 property Item indicators26 property Item indicators
28 property Item underlay27 property Item underlay
@@ -144,7 +143,7 @@
144 "edge": "top",143 "edge": "top",
145 "title": i18n.tr("Top edge"),144 "title": i18n.tr("Top edge"),
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"),
147 "anchors.fill": demo.dash,146 "anchors.fill": demo.underlay,
148 });147 });
149 }148 }
150 if (d.topEdgeDemo) {149 if (d.topEdgeDemo) {
@@ -193,12 +192,12 @@
193 function startLeftEdgeDemo() {192 function startLeftEdgeDemo() {
194 demo.panelEnabled = false;193 demo.panelEnabled = false;
195 demo.launcherEnabled = true;194 demo.launcherEnabled = true;
196 if (demo.dash && demo.underlay) {195 if (demo.underlay) {
197 d.leftEdgeDemo = d.overlay.createObject(demo.underlay, {196 d.leftEdgeDemo = d.overlay.createObject(demo.underlay, {
198 "edge": "left",197 "edge": "left",
199 "title": i18n.tr("Left edge"),198 "title": i18n.tr("Left edge"),
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"),
201 "anchors.fill": demo.dash,200 "anchors.fill": demo.underlay,
202 });201 });
203 }202 }
204 if (d.leftEdgeDemo) {203 if (d.leftEdgeDemo) {
@@ -221,12 +220,12 @@
221220
222 function startFinalEdgeDemo() {221 function startFinalEdgeDemo() {
223 demo.launcherEnabled = false;222 demo.launcherEnabled = false;
224 if (demo.dash && demo.underlay) {223 if (demo.underlay) {
225 d.finalEdgeDemo = d.overlay.createObject(demo.underlay, {224 d.finalEdgeDemo = d.overlay.createObject(demo.underlay, {
226 "edge": "none",225 "edge": "none",
227 "title": i18n.tr("Well done"),226 "title": i18n.tr("Well done"),
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"),
229 "anchors.fill": demo.dash,228 "anchors.fill": demo.underlay,
230 "showSkip": false,229 "showSkip": false,
231 });230 });
232 }231 }
233232
=== modified file 'qml/Dash/Dash.qml'
--- qml/Dash/Dash.qml 2014-07-10 09:27:19 +0000
+++ qml/Dash/Dash.qml 2014-08-05 11:53:58 +0000
@@ -18,6 +18,7 @@
18import Ubuntu.Components 0.118import Ubuntu.Components 0.1
19import Unity 0.219import Unity 0.2
20import Utils 0.120import Utils 0.1
21import Unity.DashCommunicator 0.1
21import "../Components"22import "../Components"
2223
23Showable {24Showable {
@@ -29,6 +30,13 @@
29 property string showScopeOnLoaded: "clickscope"30 property string showScopeOnLoaded: "clickscope"
30 property real contentScale: 1.031 property real contentScale: 1.0
3132
33 DashCommunicatorService {
34 objectName: "dashCommunicatorService"
35 onSetCurrentScopeRequested: {
36 dash.setCurrentScope(scopeId, animate, reset)
37 }
38 }
39
32 function setCurrentScope(scopeId, animate, reset) {40 function setCurrentScope(scopeId, animate, reset) {
33 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)41 var scopeIndex = filteredScopes.findFirst(Scopes.RoleId, scopeId)
3442
3543
=== added file 'qml/Dash/DashApplication.qml'
--- qml/Dash/DashApplication.qml 1970-01-01 00:00:00 +0000
+++ qml/Dash/DashApplication.qml 2014-08-05 11:53:58 +0000
@@ -0,0 +1,29 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17import QtQuick 2.2
18import Ubuntu.Components 1.0
19
20MainView {
21 width: units.gu(40)
22 height: units.gu(71)
23
24 useDeprecatedToolbar: false
25
26 Dash {
27 anchors.fill: parent
28 }
29}
030
=== modified file 'qml/Dash/GenericScopeView.qml'
--- qml/Dash/GenericScopeView.qml 2014-07-25 11:49:28 +0000
+++ qml/Dash/GenericScopeView.qml 2014-08-05 11:53:58 +0000
@@ -46,7 +46,7 @@
46 }46 }
4747
48 function activateApp(appId) {48 function activateApp(appId) {
49 shell.activateApplication(appId);49 Qt.openUrlExternally(appId);
50 }50 }
5151
52 function positionAtBeginning() {52 function positionAtBeginning() {
5353
=== modified file 'qml/Dash/ScopeListView.qml'
--- qml/Dash/ScopeListView.qml 2014-06-11 15:36:51 +0000
+++ qml/Dash/ScopeListView.qml 2014-08-05 11:53:58 +0000
@@ -20,9 +20,4 @@
20ListViewWithPageHeader {20ListViewWithPageHeader {
21 maximumFlickVelocity: height * 1021 maximumFlickVelocity: height * 10
22 flickDeceleration: height * 222 flickDeceleration: height * 2
23
24 Connections {
25 target: greeter
26 onShownChanged: if (greeter.shown) showHeader()
27 }
28}23}
2924
=== added file 'qml/Dash/graphics/phone/screenshots/unity8-dash@12.png'
30Binary 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 differ25Binary 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
=== modified file 'qml/Launcher/Launcher.qml'
--- qml/Launcher/Launcher.qml 2014-07-16 13:01:08 +0000
+++ qml/Launcher/Launcher.qml 2014-08-05 11:53:58 +0000
@@ -29,8 +29,7 @@
29 property int dragAreaWidth: units.gu(1)29 property int dragAreaWidth: units.gu(1)
30 property int minimizeDistance: units.gu(26)30 property int minimizeDistance: units.gu(26)
31 property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?31 property real progress: dragArea.dragging && dragArea.touchX > panelWidth ?
32 (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) :32 (width * (dragArea.touchX-panelWidth) / (width - panelWidth)) : 0
33 (dragArea.dragging ? 0.001 : 0)
3433
35 readonly property bool shown: panel.x > -panel.width34 readonly property bool shown: panel.x > -panel.width
3635
@@ -245,7 +244,7 @@
245 if (!dragging) {244 if (!dragging) {
246 if (distance > panel.width / 2) {245 if (distance > panel.width / 2) {
247 if (distance > minimizeDistance) {246 if (distance > minimizeDistance) {
248 root.dash()247 root.dash();
249 } else {248 } else {
250 root.switchToNextState("visible")249 root.switchToNextState("visible")
251 }250 }
252251
=== modified file 'qml/Shell.qml'
--- qml/Shell.qml 2014-07-29 23:36:16 +0000
+++ qml/Shell.qml 2014-08-05 11:53:58 +0000
@@ -25,7 +25,6 @@
25import LightDM 0.1 as LightDM25import LightDM 0.1 as LightDM
26import Powerd 0.126import Powerd 0.1
27import SessionBroadcast 0.127import SessionBroadcast 0.1
28import "Dash"
29import "Greeter"28import "Greeter"
30import "Launcher"29import "Launcher"
31import "Panel"30import "Panel"
@@ -34,6 +33,7 @@
34import "Stages"33import "Stages"
35import Unity.Notifications 1.0 as NotificationBackend34import Unity.Notifications 1.0 as NotificationBackend
36import Unity.Session 0.135import Unity.Session 0.1
36import Unity.DashCommunicator 0.1
3737
38Item {38Item {
39 id: shell39 id: shell
@@ -48,8 +48,6 @@
48 property url background48 property url background
49 readonly property real panelHeight: panel.panelHeight49 readonly property real panelHeight: panel.panelHeight
5050
51 property bool dashShown: dash.shown && dash.available && underlay.visible
52
53 property bool sideStageEnabled: shell.width >= units.gu(100)51 property bool sideStageEnabled: shell.width >= units.gu(100)
54 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId52 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
5553
@@ -59,7 +57,6 @@
59 } else {57 } else {
60 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;58 var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
61 ApplicationManager.startApplication(appId, execFlags);59 ApplicationManager.startApplication(appId, execFlags);
62 stages.show();
63 }60 }
64 }61 }
6562
@@ -86,6 +83,11 @@
86 id: volumeControl83 id: volumeControl
87 }84 }
8885
86 DashCommunicator {
87 id: dash
88 objectName: "dashCommunicator"
89 }
90
89 WindowKeysFilter {91 WindowKeysFilter {
90 // Handle but do not filter out volume keys92 // Handle but do not filter out volume keys
91 Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }93 Keys.onVolumeUpPressed: { volumeControl.volumeUp(); event.accepted = false; }
@@ -121,64 +123,12 @@
121 visible: !fullyCovered123 visible: !fullyCovered
122124
123 Image {125 Image {
124 anchors.fill: dash126 anchors.fill: underlay
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"
126 fillMode: Image.PreserveAspectCrop128 fillMode: Image.PreserveAspectCrop
127 horizontalAlignment: Image.AlignRight129 horizontalAlignment: Image.AlignRight
128 verticalAlignment: Image.AlignTop130 verticalAlignment: Image.AlignTop
129 }131 }
130
131 Dash {
132 id: dash
133 objectName: "dash"
134
135 available: !LightDM.Greeter.active
136 hides: [stages, launcher, panel.indicators]
137 shown: disappearingAnimationProgress !== 1.0 && greeterWrapper.showProgress !== 1.0 &&
138 !(panel.indicators.fullyOpened && !sideStageEnabled)
139 enabled: disappearingAnimationProgress === 0.0 && greeterWrapper.showProgress === 0.0 && edgeDemo.dashEnabled
140
141 anchors {
142 fill: parent
143 topMargin: panel.panelHeight
144 }
145
146 contentScale: 1.0 - 0.2 * disappearingAnimationProgress
147 opacity: 1.0 - disappearingAnimationProgress
148 property real disappearingAnimationProgress: stages.showProgress
149
150 // FIXME: only necessary because stages.showProgress is not animated
151 Behavior on disappearingAnimationProgress { SmoothedAnimation { velocity: 5 }}
152 }
153 }
154
155 EdgeDragArea {
156 id: stagesDragArea
157 direction: Direction.Leftwards
158
159 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
160 width: shell.edgeSize
161
162 property real progress: stages.width
163
164 onTouchXChanged: {
165 if (status == DirectionalDragArea.Recognized) {
166 if (ApplicationManager.empty) {
167 progress = Math.max(stages.width - stagesDragArea.width + touchX, stages.width * .3);
168 } else {
169 progress = stages.width - stagesDragArea.width + touchX;
170 }
171 }
172 }
173
174 onDraggingChanged: {
175 if (!dragging) {
176 if (!ApplicationManager.empty && progress < stages.width - units.gu(10)) {
177 stages.show();
178 }
179 stagesDragArea.progress = Qt.binding(function () { return stages.width; });
180 }
181 }
182 }132 }
183133
184 Item {134 Item {
@@ -186,55 +136,7 @@
186 objectName: "stages"136 objectName: "stages"
187 width: parent.width137 width: parent.width
188 height: parent.height138 height: parent.height
189139 visible: !ApplicationManager.empty
190 visible: !fullyHidden && !ApplicationManager.empty
191
192 x: {
193 if (shown) {
194 if (locked || greeter.fakeActiveForApp !== "") {
195 return 0;
196 }
197 return launcher.progress;
198 } else {
199 return stagesDragArea.progress
200 }
201 }
202 Behavior on x { SmoothedAnimation { velocity: 600; duration: UbuntuAnimation.FastDuration } }
203
204 property bool shown: false
205 onShownChanged: {
206 if (shown) {
207 if (ApplicationManager.count > 0) {
208 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
209 }
210 } else {
211 if (ApplicationManager.focusedApplicationId) {
212 ApplicationManager.updateScreenshot(ApplicationManager.focusedApplicationId);
213 ApplicationManager.unfocusCurrentApplication();
214 }
215 }
216 }
217
218 // Avoid a silent "divide by zero -> NaN" situation during init as shell.width will be
219 // zero. That breaks the property binding and the function won't be reevaluated once
220 // shell.width is set, with the NaN result staying there for good.
221 property real showProgress: shell.width ? MathUtils.clamp(1 - x / shell.width, 0, 1) : 0
222
223 property bool fullyShown: x == 0
224 property bool fullyHidden: x == width
225
226 property bool locked: applicationsDisplayLoader.item ? applicationsDisplayLoader.item.locked : false
227
228 // It might technically not be fullyShown but visually it just looks so.
229 property bool roughlyFullyShown: x >= 0 && x <= units.gu(1)
230
231 function show() {
232 shown = true;
233 }
234
235 function hide() {
236 shown = false;
237 }
238140
239 Connections {141 Connections {
240 target: ApplicationManager142 target: ApplicationManager
@@ -243,7 +145,6 @@
243 lockscreen.show();145 lockscreen.show();
244 }146 }
245 greeter.hide();147 greeter.hide();
246 stages.show();
247 }148 }
248149
249 onFocusedApplicationIdChanged: {150 onFocusedApplicationIdChanged: {
@@ -254,18 +155,9 @@
254 }155 }
255156
256 onApplicationAdded: {157 onApplicationAdded: {
257 if (greeter.shown) {158 if (greeter.shown && appId != "unity8-dash") {
258 greeter.hide();159 greeter.hide();
259 }160 }
260 if (!stages.shown) {
261 stages.show();
262 }
263 }
264
265 onEmptyChanged: {
266 if (ApplicationManager.empty) {
267 stages.hide();
268 }
269 }161 }
270 }162 }
271163
@@ -294,14 +186,18 @@
294 Binding {186 Binding {
295 target: applicationsDisplayLoader.item187 target: applicationsDisplayLoader.item
296 property: "interactive"188 property: "interactive"
297 value: stages.roughlyFullyShown && !greeter.shown && !lockscreen.shown189 value: !greeter.shown && !lockscreen.shown && panel.indicators.fullyClosed && launcher.progress == 0
298 && panel.indicators.fullyClosed
299 }190 }
300 Binding {191 Binding {
301 target: applicationsDisplayLoader.item192 target: applicationsDisplayLoader.item
302 property: "spreadEnabled"193 property: "spreadEnabled"
303 value: greeter.fakeActiveForApp === "" // to support emergency dialer hack194 value: greeter.fakeActiveForApp === "" // to support emergency dialer hack
304 }195 }
196 Binding {
197 target: applicationsDisplayLoader.item
198 property: "inverseProgress"
199 value: launcher.progress
200 }
305 }201 }
306 }202 }
307203
@@ -531,25 +427,20 @@
531427
532 var animate = !LightDM.Greeter.active && !stages.shown428 var animate = !LightDM.Greeter.active && !stages.shown
533 dash.setCurrentScope("clickscope", animate, false)429 dash.setCurrentScope("clickscope", animate, false)
534 stages.hide()430 ApplicationManager.requestFocusApplication("unity8-dash")
535 }431 }
536432
537 function showDash() {433 function showDash() {
538 if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {434 if (LightDM.Greeter.active && !LightDM.Greeter.promptless) {
539 return;435 return;
540 }436 }
541
542 if (!stages.locked) {
543 stages.hide();
544 launcher.fadeOut();
545 } else {
546 launcher.switchToNextState("visible");
547 }
548
549 if (greeter.shown) {437 if (greeter.shown) {
550 greeter.hideRight();438 greeter.hideRight();
551 launcher.fadeOut();439 launcher.fadeOut();
552 }440 }
441
442 ApplicationManager.requestFocusApplication("unity8-dash")
443 launcher.fadeOut();
553 }444 }
554445
555 Item {446 Item {
@@ -574,8 +465,8 @@
574 ApplicationManager.focusedApplicationId &&465 ApplicationManager.focusedApplicationId &&
575 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen466 ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
576467
577 fullscreenMode: (stages.roughlyFullyShown && topmostApplicationIsFullscreen468 fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
578 && !LightDM.Greeter.active) || greeter.fakeActiveForApp !== ""469 || greeter.fakeActiveForApp !== ""
579 }470 }
580471
581 Launcher {472 Launcher {
@@ -592,7 +483,11 @@
592483
593 onShowDashHome: showHome()484 onShowDashHome: showHome()
594 onDash: showDash()485 onDash: showDash()
595 onDashSwipeChanged: if (dashSwipe && stages.shown) dash.setCurrentScope("clickscope", false, true)486 onDashSwipeChanged: {
487 if (dashSwipe && ApplicationManager.focusedApplicationId !== "unity8-dash") {
488 dash.setCurrentScope("clickscope", false, true)
489 }
490 }
596 onLauncherApplicationSelected: {491 onLauncherApplicationSelected: {
597 if (greeter.fakeActiveForApp !== "") {492 if (greeter.fakeActiveForApp !== "") {
598 lockscreen.show()493 lockscreen.show()
@@ -684,7 +579,6 @@
684 z: alphaDisclaimerLabel.z + 10579 z: alphaDisclaimerLabel.z + 10
685 greeter: greeter580 greeter: greeter
686 launcher: launcher581 launcher: launcher
687 dash: dash
688 indicators: panel.indicators582 indicators: panel.indicators
689 underlay: underlay583 underlay: underlay
690 }584 }
691585
=== modified file 'qml/Stages/PhoneStage.qml'
--- qml/Stages/PhoneStage.qml 2014-07-22 15:16:32 +0000
+++ qml/Stages/PhoneStage.qml 2014-08-05 11:53:58 +0000
@@ -21,7 +21,7 @@
21import Utils 0.121import Utils 0.1
22import "../Components"22import "../Components"
2323
24Item {24Rectangle {
25 id: root25 id: root
2626
27 // Controls to be set from outside27 // Controls to be set from outside
@@ -29,9 +29,9 @@
29 property real maximizedAppTopMargin29 property real maximizedAppTopMargin
30 property bool interactive30 property bool interactive
31 property bool spreadEnabled: true // If false, animations and right edge will be disabled31 property bool spreadEnabled: true // If false, animations and right edge will be disabled
32 property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
3233
33 // State information propagated to the outside34 color: "black"
34 readonly property bool locked: spreadView.phase == 2
3535
36 function select(appId) {36 function select(appId) {
37 spreadView.snapTo(priv.indexOf(appId));37 spreadView.snapTo(priv.indexOf(appId));
@@ -43,6 +43,16 @@
43 spreadView.contentX = -spreadView.shift;43 spreadView.contentX = -spreadView.shift;
44 }44 }
4545
46 onInverseProgressChanged: {
47 if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
48 // left edge drag released. Minimum distance is given by design.
49 if (priv.oldInverseProgress > units.gu(22)) {
50 ApplicationManager.focusApplication("unity8-dash");
51 }
52 }
53 priv.oldInverseProgress = inverseProgress;
54 }
55
46 Connections {56 Connections {
47 target: ApplicationManager57 target: ApplicationManager
4858
@@ -50,7 +60,7 @@
50 if (spreadView.phase > 0) {60 if (spreadView.phase > 0) {
51 spreadView.snapTo(priv.indexOf(appId));61 spreadView.snapTo(priv.indexOf(appId));
52 } else {62 } else {
53 priv.switchToApp(appId);63 ApplicationManager.focusApplication(appId);
54 }64 }
55 }65 }
5666
@@ -60,7 +70,7 @@
60 } else {70 } else {
61 spreadView.phase = 0;71 spreadView.phase = 0;
62 spreadView.contentX = -spreadView.shift;72 spreadView.contentX = -spreadView.shift;
63 priv.switchToApp(appId);73 ApplicationManager.focusApplication(appId);
64 }74 }
65 }75 }
6676
@@ -79,15 +89,11 @@
7989
80 property string focusedAppId: ApplicationManager.focusedApplicationId90 property string focusedAppId: ApplicationManager.focusedApplicationId
81 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)91 property var focusedApplication: ApplicationManager.findApplication(focusedAppId)
8292 property var focusedAppDelegate: null
83 function switchToApp(appId) {93
84 if (priv.focusedAppId) {94 property real oldInverseProgress: 0
85 spreadView.focusChanging = true;95
86 ApplicationManager.focusApplication(appId);96 onFocusedAppIdChanged: focusedAppDelegate = spreadRepeater.itemAt(0);
87 } else {
88 ApplicationManager.focusApplication(appId);
89 }
90 }
9197
92 function indexOf(appId) {98 function indexOf(appId) {
93 for (var i = 0; i < ApplicationManager.count; i++) {99 for (var i = 0; i < ApplicationManager.count; i++) {
@@ -100,14 +106,6 @@
100106
101 }107 }
102108
103 Rectangle {
104 id: coverFlipBackground
105 anchors.fill: parent
106 color: "black"
107 visible: spreadView.visible
108 }
109
110
111 Flickable {109 Flickable {
112 id: spreadView110 id: spreadView
113 objectName: "spreadView"111 objectName: "spreadView"
@@ -116,6 +114,10 @@
116 contentWidth: spreadRow.width - shift114 contentWidth: spreadRow.width - shift
117 contentX: -shift115 contentX: -shift
118116
117 // This indicates when the spreadView is active. That means, all the animations
118 // are activated and tiles need to line up for the spread.
119 readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging
120
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.
120 // However, we don't want to the user to be able to scroll back all the way. For122 // However, we don't want to the user to be able to scroll back all the way. For
121 // that, the beginning of the gesture starts with a negative value for contentX123 // that, the beginning of the gesture starts with a negative value for contentX
@@ -198,6 +200,12 @@
198 snapAnimation.start();200 snapAnimation.start();
199 }201 }
200202
203 // In case the ApplicationManager already holds an app when starting up we're missing animations
204 // Make sure we end up in the same state
205 Component.onCompleted: {
206 spreadView.contentX = -spreadView.shift
207 }
208
201 SequentialAnimation {209 SequentialAnimation {
202 id: snapAnimation210 id: snapAnimation
203 property int targetContentX: -spreadView.shift211 property int targetContentX: -spreadView.shift
@@ -260,14 +268,33 @@
260 && spreadView.shiftedContentX === 0 && root.interactive && index === 0268 && spreadView.shiftedContentX === 0 && root.interactive && index === 0
261 swipeToCloseEnabled: spreadView.interactive269 swipeToCloseEnabled: spreadView.interactive
262 maximizedAppTopMargin: root.maximizedAppTopMargin270 maximizedAppTopMargin: root.maximizedAppTopMargin
263 dropShadow: spreadView.shiftedContentX > 0 || spreadDragArea.status == DirectionalDragArea.Undecided271 dropShadow: spreadView.active ||
264272 priv.focusedAppDelegate.x !== 0
265 z: behavioredIndex273
266 x: index == 0 ? 0 : spreadView.width + (index - 1) * spreadView.tileDistance274 readonly property bool isDash: model.appId == "unity8-dash"
275
276 z: isDash && !spreadView.active ? -1 : behavioredIndex
277
278 x: {
279 // focused app is always positioned at 0 except when following left edge drag
280 if (index == 0) {
281 if (!isDash && root.inverseProgress > 0) {
282 return root.inverseProgress;
283 }
284 return 0;
285 }
286 if (isDash && !spreadView.active && !spreadDragArea.dragging) {
287 return 0;
288 }
289
290 // Otherwise line up for the spread
291 return spreadView.width + (index - 1) * spreadView.tileDistance;
292 }
267 property real behavioredIndex: index293 property real behavioredIndex: index
268 Behavior on behavioredIndex {294 Behavior on behavioredIndex {
269 enabled: spreadView.closingIndex >= 0295 enabled: spreadView.closingIndex >= 0
270 UbuntuNumberAnimation {296 UbuntuNumberAnimation {
297 id: appXAnimation
271 onRunningChanged: {298 onRunningChanged: {
272 if (!running) {299 if (!running) {
273 spreadView.closingIndex = -1;300 spreadView.closingIndex = -1;
@@ -277,11 +304,13 @@
277 }304 }
278305
279 Behavior on x {306 Behavior on x {
280 enabled: spreadView.focusChanging && index == 0 && root.spreadEnabled307 enabled: root.spreadEnabled &&
308 !spreadView.active &&
309 !snapAnimation.running
281 UbuntuNumberAnimation {310 UbuntuNumberAnimation {
282 duration: UbuntuAnimation.FastDuration311 duration: UbuntuAnimation.FastDuration
283 onRunningChanged: {312 onRunningChanged: {
284 if (!running) {313 if (!running && root.inverseProgress == 0) {
285 spreadView.focusChanging = false;314 spreadView.focusChanging = false;
286 }315 }
287 }316 }
@@ -322,6 +351,10 @@
322 return progress;351 return progress;
323 }352 }
324353
354 // Hiding tiles when their progress is negative or reached the maximum
355 visible: (progress >= 0 && progress < 1.7) ||
356 (isDash && priv.focusedAppDelegate.x !== 0)
357
325 EasingCurve {358 EasingCurve {
326 id: snappingCurve359 id: snappingCurve
327 type: EasingCurve.Linear360 type: EasingCurve.Linear
328361
=== modified file 'qml/Stages/SpreadDelegate.qml'
--- qml/Stages/SpreadDelegate.qml 2014-07-23 12:20:45 +0000
+++ qml/Stages/SpreadDelegate.qml 2014-08-05 11:53:58 +0000
@@ -37,6 +37,7 @@
3737
38 SurfaceContainer {38 SurfaceContainer {
39 id: surfaceContainer39 id: surfaceContainer
40 objectName: "surfaceContainer"
40 anchors.fill: parent41 anchors.fill: parent
41 surface: model.surface42 surface: model.surface
42 property bool appHasCreatedASurface: false43 property bool appHasCreatedASurface: false
@@ -172,6 +173,11 @@
172 }173 }
173174
174 onDragEnd: {175 onDragEnd: {
176 if (model.appId == "unity8-dash") {
177 animation.animate("center")
178 return;
179 }
180
175 // velocity and distance values specified by design prototype181 // velocity and distance values specified by design prototype
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) {
177 animation.animate("up")183 animation.animate("up")
178184
=== modified file 'qml/Stages/TabletStage.qml'
--- qml/Stages/TabletStage.qml 2014-07-21 08:05:38 +0000
+++ qml/Stages/TabletStage.qml 2014-08-05 11:53:58 +0000
@@ -21,10 +21,11 @@
21import Utils 0.121import Utils 0.1
22import "../Components"22import "../Components"
2323
24Item {24Rectangle {
25 id: root25 id: root
26 objectName: "stages"26 objectName: "stages"
27 anchors.fill: parent27 anchors.fill: parent
28 color: "black"
2829
29 // Controls to be set from outside30 // Controls to be set from outside
30 property bool shown: false31 property bool shown: false
@@ -32,9 +33,17 @@
32 property int dragAreaWidth33 property int dragAreaWidth
33 property real maximizedAppTopMargin34 property real maximizedAppTopMargin
34 property bool interactive35 property bool interactive
36 property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
3537
36 // State information propagated to the outside38 onInverseProgressChanged: {
37 readonly property bool locked: spreadView.phase == 239 if (inverseProgress == 0 && priv.oldInverseProgress > 0) {
40 // left edge drag released. Minimum distance is given by design.
41 if (priv.oldInverseProgress > units.gu(22)) {
42 ApplicationManager.focusApplication("unity8-dash");
43 }
44 }
45 priv.oldInverseProgress = inverseProgress;
46 }
3847
39 QtObject {48 QtObject {
40 id: priv49 id: priv
@@ -49,6 +58,8 @@
49 property string appId058 property string appId0
50 property string appId159 property string appId1
5160
61 property int oldInverseProgress: 0
62
52 onFocusedAppIdChanged: {63 onFocusedAppIdChanged: {
53 if (priv.focusedAppId.length > 0) {64 if (priv.focusedAppId.length > 0) {
54 var focusedApp = ApplicationManager.findApplication(focusedAppId);65 var focusedApp = ApplicationManager.findApplication(focusedAppId);
@@ -107,16 +118,26 @@
107 }118 }
108 }119 }
109120
121 onApplicationAdded: {
122 if (spreadView.phase == 2) {
123 spreadView.snapTo(ApplicationManager.count - 1);
124 } else {
125 spreadView.phase = 0;
126 spreadView.contentX = -spreadView.shift;
127 ApplicationManager.focusApplication(appId);
128 }
129 }
130
110 onApplicationRemoved: {131 onApplicationRemoved: {
111 if (priv.mainStageAppId == appId) {132 if (priv.mainStageAppId == appId) {
112 priv.mainStageAppId = "";133 ApplicationManager.focusApplication("unity8-dash")
113 }134 }
114 if (priv.sideStageAppId == appId) {135 if (priv.sideStageAppId == appId) {
115 priv.sideStageAppId = "";136 priv.sideStageAppId = "";
116 }137 }
117 if (ApplicationManager.count == 0) {138 if (ApplicationManager.count == 0) {
118 spreadView.phase = 0;139 spreadView.phase = 0;
119 spreadView.contentX = 0;140 spreadView.contentX = -spreadView.shift;
120 }141 }
121 }142 }
122 }143 }
@@ -124,13 +145,26 @@
124 Flickable {145 Flickable {
125 id: spreadView146 id: spreadView
126 anchors.fill: parent147 anchors.fill: parent
127 contentWidth: spreadRow.width
128 interactive: (spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1) && draggedIndex == -1148 interactive: (spreadDragArea.status == DirectionalDragArea.Recognized || phase > 1) && draggedIndex == -1
149 contentWidth: spreadRow.width - shift
150 contentX: -shift
129151
130 property int tileDistance: units.gu(20)152 property int tileDistance: units.gu(20)
131 property int sideStageWidth: units.gu(40)153 property int sideStageWidth: units.gu(40)
132 property bool sideStageVisible: priv.sideStageAppId154 property bool sideStageVisible: priv.sideStageAppId
133155
156 // This indicates when the spreadView is active. That means, all the animations
157 // are activated and tiles need to line up for the spread.
158 readonly property bool active: shiftedContentX > 0 || spreadDragArea.dragging
159
160 // The flickable needs to fill the screen in order to get touch events all over.
161 // However, we don't want to the user to be able to scroll back all the way. For
162 // that, the beginning of the gesture starts with a negative value for contentX
163 // so the flickable wants to pull it into the view already. "shift" tunes the
164 // distance where to "lock" the content.
165 readonly property real shift: width / 2
166 readonly property real shiftedContentX: contentX + shift
167
134 // Phase of the animation:168 // Phase of the animation:
135 // 0: Starting from right edge, a new app (index 1) comes in from the right169 // 0: Starting from right edge, a new app (index 1) comes in from the right
136 // 1: The app has reached the first snap position.170 // 1: The app has reached the first snap position.
@@ -168,6 +202,12 @@
168 }202 }
169 }203 }
170204
205 // In case the ApplicationManager already holds an app when starting up we're missing animations
206 // Make sure we end up in the same state
207 Component.onCompleted: {
208 spreadView.contentX = -spreadView.shift
209 }
210
171 property int nextInStack: {211 property int nextInStack: {
172 switch (state) {212 switch (state) {
173 case "main":213 case "main":
@@ -224,31 +264,31 @@
224 return "empty";264 return "empty";
225 }265 }
226266
227 onContentXChanged: {267 onShiftedContentXChanged: {
228 if (spreadView.phase == 0 && spreadView.contentX > spreadView.width * spreadView.positionMarker2) {268 if (spreadView.phase == 0 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker2) {
229 spreadView.phase = 1;269 spreadView.phase = 1;
230 } else if (spreadView.phase == 1 && spreadView.contentX > spreadView.width * spreadView.positionMarker4) {270 } else if (spreadView.phase == 1 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker4) {
231 spreadView.phase = 2;271 spreadView.phase = 2;
232 } else if (spreadView.phase == 1 && spreadView.contentX < spreadView.width * spreadView.positionMarker2) {272 } else if (spreadView.phase == 1 && spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
233 spreadView.phase = 0;273 spreadView.phase = 0;
234 }274 }
235 }275 }
236276
237 function snap() {277 function snap() {
238 if (contentX < phase0Width) {278 if (shiftedContentX < phase0Width) {
239 snapAnimation.targetContentX = 0;279 snapAnimation.targetContentX = -shift;
240 snapAnimation.start();280 snapAnimation.start();
241 } else if (contentX < phase1Width) {281 } else if (shiftedContentX < phase1Width) {
242 snapTo(1);282 snapTo(1);
243 } else {283 } else {
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.
245 snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1;285 snapAnimation.targetContentX = spreadView.width * spreadView.positionMarker4 + 1 - shift;
246 snapAnimation.start();286 snapAnimation.start();
247 }287 }
248 }288 }
249 function snapTo(index) {289 function snapTo(index) {
250 spreadView.selectedIndex = index;290 spreadView.selectedIndex = index;
251 snapAnimation.targetContentX = 0;291 snapAnimation.targetContentX = -shift;
252 snapAnimation.start();292 snapAnimation.start();
253 }293 }
254294
@@ -261,12 +301,12 @@
261 return index;301 return index;
262 }302 }
263303
264 var isActive = app.appId == priv.mainStageAppId || app.appId == priv.sideStageAppId;304 var active = app.appId == priv.mainStageAppId || app.appId == priv.sideStageAppId;
265 if (isActive && app.stage == ApplicationInfoInterface.MainStage) {305 if (active && app.stage == ApplicationInfoInterface.MainStage) {
266 // if this app is active, and its the MainStage, always put it to index 0306 // if this app is active, and its the MainStage, always put it to index 0
267 return 0;307 return 0;
268 }308 }
269 if (isActive && app.stage == ApplicationInfoInterface.SideStage) {309 if (active && app.stage == ApplicationInfoInterface.SideStage) {
270 if (!priv.mainStageAppId) {310 if (!priv.mainStageAppId) {
271 // Only have SS apps running. Put the active one at 0311 // Only have SS apps running. Put the active one at 0
272 return 0;312 return 0;
@@ -309,7 +349,7 @@
309349
310 SequentialAnimation {350 SequentialAnimation {
311 id: snapAnimation351 id: snapAnimation
312 property int targetContentX: 0352 property int targetContentX: -spreadView.shift
313353
314 UbuntuNumberAnimation {354 UbuntuNumberAnimation {
315 target: spreadView355 target: spreadView
@@ -325,15 +365,14 @@
325 spreadView.selectedIndex = -1;365 spreadView.selectedIndex = -1;
326 ApplicationManager.focusApplication(ApplicationManager.get(newIndex).appId);366 ApplicationManager.focusApplication(ApplicationManager.get(newIndex).appId);
327 spreadView.phase = 0;367 spreadView.phase = 0;
328 spreadView.contentX = 0;368 spreadView.contentX = -spreadView.shift;
329 }369 }
330 }370 }
331 }371 }
332 }372 }
333373
334 Rectangle {374 Item {
335 id: spreadRow375 id: spreadRow
336 color: "black"
337 x: spreadView.contentX376 x: spreadView.contentX
338 height: root.height377 height: root.height
339 width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance)378 width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance)
@@ -380,7 +419,7 @@
380 MouseArea {419 MouseArea {
381 id: sideStageDragHandleMouseArea420 id: sideStageDragHandleMouseArea
382 anchors.fill: parent421 anchors.fill: parent
383 enabled: spreadView.contentX == 0422 enabled: spreadView.shiftedContentX == 0
384 property int startX423 property int startX
385 property var gesturePoints: new Array()424 property var gesturePoints: new Array()
386425
@@ -413,7 +452,7 @@
413452
414 onRunningChanged: {453 onRunningChanged: {
415 if (!running) {454 if (!running) {
416 sideStageDragHandle.dragging = false;;455 sideStageDragHandle.dragging = false;
417 }456 }
418 }457 }
419 }458 }
@@ -427,17 +466,26 @@
427 id: spreadTile466 id: spreadTile
428 height: spreadView.height467 height: spreadView.height
429 width: model.stage == ApplicationInfoInterface.MainStage ? spreadView.width : spreadView.sideStageWidth468 width: model.stage == ApplicationInfoInterface.MainStage ? spreadView.width : spreadView.sideStageWidth
430 x: spreadView.width
431 z: spreadView.indexToZIndex(index)
432 active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId469 active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId
433 zIndex: z470 zIndex: spreadView.indexToZIndex(index)
434 selected: spreadView.selectedIndex == index471 selected: spreadView.selectedIndex == index
435 otherSelected: spreadView.selectedIndex >= 0 && !selected472 otherSelected: spreadView.selectedIndex >= 0 && !selected
436 isInSideStage: priv.sideStageAppId == model.appId473 isInSideStage: priv.sideStageAppId == model.appId
437 interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive474 interactive: !spreadView.interactive && spreadView.phase === 0 && root.interactive
438 swipeToCloseEnabled: spreadView.interactive475 swipeToCloseEnabled: spreadView.interactive
439 maximizedAppTopMargin: root.maximizedAppTopMargin476 maximizedAppTopMargin: root.maximizedAppTopMargin
440 dropShadow: spreadView.contentX > 0 || spreadDragArea.status == DirectionalDragArea.Undecided477 dragOffset: !isDash && model.appId == priv.mainStageAppId && root.inverseProgress > 0 ? root.inverseProgress : 0
478
479 readonly property bool isDash: model.appId == "unity8-dash"
480
481 // FIXME: A regular binding doesn't update any more after closing an app.
482 // Using a Binding for now.
483 Binding {
484 target: spreadTile
485 property: "z"
486 value: (!spreadView.active && isDash && !active) ? -1 : spreadTile.zIndex
487 }
488 x: spreadView.width
441489
442 property real behavioredZIndex: zIndex490 property real behavioredZIndex: zIndex
443 Behavior on behavioredZIndex {491 Behavior on behavioredZIndex {
@@ -458,7 +506,7 @@
458 }506 }
459507
460 progress: {508 progress: {
461 var tileProgress = (spreadView.contentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width;509 var tileProgress = (spreadView.shiftedContentX - behavioredZIndex * spreadView.tileDistance) / spreadView.width;
462 // Some tiles (nextInStack, active) need to move directly from the beginning, normalize progress to immediately start at 0510 // Some tiles (nextInStack, active) need to move directly from the beginning, normalize progress to immediately start at 0
463 if ((index == spreadView.nextInStack && spreadView.phase < 2) || (active && spreadView.phase < 1)) {511 if ((index == spreadView.nextInStack && spreadView.phase < 2) || (active && spreadView.phase < 1)) {
464 tileProgress += behavioredZIndex * spreadView.tileDistance / spreadView.width;512 tileProgress += behavioredZIndex * spreadView.tileDistance / spreadView.width;
@@ -481,11 +529,7 @@
481529
482 onClicked: {530 onClicked: {
483 if (spreadView.phase == 2) {531 if (spreadView.phase == 2) {
484 if (ApplicationManager.focusedApplicationId == ApplicationManager.get(index).appId) {532 spreadView.snapTo(index);
485 spreadView.snapTo(index);
486 } else {
487 ApplicationManager.requestFocusApplication(ApplicationManager.get(index).appId);
488 }
489 }533 }
490 }534 }
491535
@@ -518,12 +562,12 @@
518 onTouchXChanged: {562 onTouchXChanged: {
519 if (!dragging) {563 if (!dragging) {
520 spreadView.phase = 0;564 spreadView.phase = 0;
521 spreadView.contentX = 0;565 spreadView.contentX = -spreadView.shift;
522 }566 }
523567
524 if (attachedToView) {568 if (dragging && attachedToView) {
525 spreadView.contentX = -touchX + spreadDragArea.width;569 spreadView.contentX = -touchX + spreadDragArea.width - spreadView.shift;
526 if (spreadView.contentX > spreadView.phase0Width + spreadView.phase1Width / 2) {570 if (spreadView.shiftedContentX > spreadView.phase0Width + spreadView.phase1Width / 2) {
527 attachedToView = false;571 attachedToView = false;
528 spreadView.snap();572 spreadView.snap();
529 }573 }
@@ -548,14 +592,14 @@
548 var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);592 var oneWayFlick = priv.evaluateOneWayFlick(gesturePoints);
549 gesturePoints = [];593 gesturePoints = [];
550594
551 if (oneWayFlick && spreadView.contentX < spreadView.positionMarker1 * spreadView.width) {595 if (oneWayFlick && spreadView.shiftedContentX < spreadView.positionMarker1 * spreadView.width) {
552 // If it was a short one-way movement, do the Alt+Tab switch596 // If it was a short one-way movement, do the Alt+Tab switch
553 // no matter if we didn't cross positionMarker1 yet.597 // no matter if we didn't cross positionMarker1 yet.
554 spreadView.snapTo(spreadView.nextInStack);598 spreadView.snapTo(spreadView.nextInStack);
555 } else if (!dragging && attachedToView) {599 } else if (!dragging && attachedToView) {
556 if (spreadView.contentX < spreadView.width * spreadView.positionMarker1) {600 if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker1) {
557 spreadView.snap();601 spreadView.snap();
558 } else if (spreadView.contentX < spreadView.width * spreadView.positionMarker2) {602 } else if (spreadView.shiftedContentX < spreadView.width * spreadView.positionMarker2) {
559 spreadView.snapTo(spreadView.nextInStack);603 spreadView.snapTo(spreadView.nextInStack);
560 } else {604 } else {
561 // otherwise snap to the closest snap position we can find605 // otherwise snap to the closest snap position we can find
562606
=== modified file 'qml/Stages/TransformedSpreadDelegate.qml'
--- qml/Stages/TransformedSpreadDelegate.qml 2014-07-21 08:13:44 +0000
+++ qml/Stages/TransformedSpreadDelegate.qml 2014-08-05 11:53:58 +0000
@@ -46,9 +46,6 @@
46 property real startDistance: units.gu(5)46 property real startDistance: units.gu(5)
47 property real endDistance: units.gu(.5)47 property real endDistance: units.gu(.5)
4848
49 // Hiding tiles when their progress is negative or reached the maximum
50 visible: progress >= 0 && progress < 1.7
51
52 onSelectedChanged: {49 onSelectedChanged: {
53 if (selected) {50 if (selected) {
54 priv.snapshot();51 priv.snapshot();
@@ -132,6 +129,10 @@
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.
133130
134 readonly property real xTranslate: {131 readonly property real xTranslate: {
132 if (!spreadView.active) {
133 return 0;
134 }
135
135 if (otherSelected) {136 if (otherSelected) {
136 if (spreadView.phase < 2 && index == 0) {137 if (spreadView.phase < 2 && index == 0) {
137 return linearAnimation(selectedProgress, 0, selectedXTranslate,138 return linearAnimation(selectedProgress, 0, selectedXTranslate,
@@ -183,7 +184,7 @@
183 }184 }
184185
185 readonly property real angle: {186 readonly property real angle: {
186 if (spreadView.focusChanging) {187 if (!spreadView.active) {
187 return 0;188 return 0;
188 }189 }
189190
@@ -216,7 +217,7 @@
216 }217 }
217218
218 readonly property real scale: {219 readonly property real scale: {
219 if (spreadView.focusChanging) {220 if (!spreadView.active) {
220 return 1;221 return 1;
221 }222 }
222 if (priv.otherSelected) {223 if (priv.otherSelected) {
223224
=== modified file 'qml/Stages/TransformedTabletSpreadDelegate.qml'
--- qml/Stages/TransformedTabletSpreadDelegate.qml 2014-07-21 08:17:07 +0000
+++ qml/Stages/TransformedTabletSpreadDelegate.qml 2014-08-05 11:53:58 +0000
@@ -47,6 +47,11 @@
4747
48 property bool isInSideStage: false48 property bool isInSideStage: false
4949
50 property int dragOffset: 0
51
52 dropShadow: spreadView.active ||
53 (active && model.stage == ApplicationInfoInterface.MainStage && priv.xTranslate != 0)
54
50 onSelectedChanged: {55 onSelectedChanged: {
51 if (selected) {56 if (selected) {
52 priv.snapshot();57 priv.snapshot();
@@ -129,6 +134,16 @@
129 return helperEasingCurve.value * (endValue - startValue) + startValue;134 return helperEasingCurve.value * (endValue - startValue) + startValue;
130 }135 }
131136
137 Behavior on xTranslate {
138 enabled: !spreadView.active &&
139 !snapAnimation.running &&
140 model.appId !== "unity8-dash" &&
141 !spreadView.sideStageDragging
142 UbuntuNumberAnimation {
143 duration: UbuntuAnimation.FastDuration
144 }
145 }
146
132 property real xTranslate: {147 property real xTranslate: {
133 var newTranslate = 0;148 var newTranslate = 0;
134149
@@ -155,7 +170,12 @@
155 if (spreadView.phase == 0 && shouldMoveAway) {170 if (spreadView.phase == 0 && shouldMoveAway) {
156 newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -units.gu(4), root.animatedProgress);171 newTranslate += linearAnimation(0, spreadView.positionMarker2, 0, -units.gu(4), root.animatedProgress);
157 }172 }
158 }173 newTranslate += root.dragOffset;
174 }
175 if (!spreadView.active && model.appId == "unity8-dash" && !root.active) {
176 newTranslate -= root.width;
177 }
178
159 if (nextInStack && spreadView.phase == 0) {179 if (nextInStack && spreadView.phase == 0) {
160 if (model.stage == ApplicationInfoInterface.MainStage) {180 if (model.stage == ApplicationInfoInterface.MainStage) {
161 if (spreadView.sideStageVisible && root.progress > 0) {181 if (spreadView.sideStageVisible && root.progress > 0) {
@@ -205,6 +225,10 @@
205 }225 }
206226
207 property real scale: {227 property real scale: {
228 if (!spreadView.active) {
229 return 1;
230 }
231
208 if (otherSelected) {232 if (otherSelected) {
209 return selectedScale;233 return selectedScale;
210 }234 }
@@ -249,6 +273,10 @@
249 }273 }
250274
251 property real angle: {275 property real angle: {
276 if (!spreadView.active) {
277 return 0;
278 }
279
252 if (otherSelected) {280 if (otherSelected) {
253 return selectedAngle;281 return selectedAngle;
254 }282 }
255283
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2014-07-03 20:28:32 +0000
+++ src/CMakeLists.txt 2014-08-05 11:53:58 +0000
@@ -35,3 +35,4 @@
35 )35 )
3636
37add_subdirectory(Panel)37add_subdirectory(Panel)
38add_subdirectory(Dash)
3839
=== added directory 'src/Dash'
=== added file 'src/Dash/CMakeLists.txt'
--- src/Dash/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ src/Dash/CMakeLists.txt 2014-08-05 11:53:58 +0000
@@ -0,0 +1,12 @@
1set(DASH_SRCS
2 main.cpp
3)
4
5add_executable(unity8-dash ${DASH_SRCS})
6
7qt5_use_modules(unity8-dash Gui Qml Quick Test)
8
9# install binaries
10install(TARGETS ${DASH_APP}
11 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
12)
013
=== added file 'src/Dash/main.cpp'
--- src/Dash/main.cpp 1970-01-01 00:00:00 +0000
+++ src/Dash/main.cpp 2014-08-05 11:53:58 +0000
@@ -0,0 +1,74 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * Authors:
5 * Michael Zanetti <michael.zanetti@canonical.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 3.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <QtQuick/QQuickView>
21#include <QtGui/QGuiApplication>
22#include <QtQml/QQmlEngine>
23#include <QtQml/QQmlContext>
24#include <QDebug>
25#include <QCommandLineParser>
26#include <QLibrary>
27
28#include <paths.h>
29
30int main(int argc, const char *argv[])
31{
32 QGuiApplication *application = new QGuiApplication(argc, (char**)argv);
33
34 QCommandLineParser parser;
35 parser.setApplicationDescription("Description: Unity 8 Shell Dash");
36 parser.addHelpOption();
37
38 QCommandLineOption testabilityOption("testability",
39 "Load the testability driver (Alternatively export QT_LOAD_TESTABILITY");
40 parser.addOption(testabilityOption);
41
42 if (parser.isSet(testabilityOption) || getenv("QT_LOAD_TESTABILITY")) {
43 QLibrary testLib(QLatin1String("qttestability"));
44 if (testLib.load()) {
45 typedef void (*TasInitialize)(void);
46 TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
47 if (initFunction) {
48 initFunction();
49 } else {
50 qCritical("Library qttestability resolve failed!");
51 }
52 } else {
53 qCritical("Library qttestability load failed!");
54 }
55 }
56
57 QQuickView* view = new QQuickView();
58 view->setResizeMode(QQuickView::SizeRootObjectToView);
59 view->setTitle("Unity Dash");
60
61 QUrl source(::qmlDirectory()+"Dash/DashApplication.qml");
62 prependImportPaths(view->engine(), ::overrideImportPaths());
63 appendImportPaths(view->engine(), ::fallbackImportPaths());
64
65 view->setSource(source);
66 view->show();
67
68 int result = application->exec();
69
70 delete view;
71 delete application;
72
73 return result;
74}
075
=== modified file 'tests/mocks/Unity/Application/ApplicationInfo.cpp'
--- tests/mocks/Unity/Application/ApplicationInfo.cpp 2014-07-24 19:22:20 +0000
+++ tests/mocks/Unity/Application/ApplicationInfo.cpp 2014-08-05 11:53:58 +0000
@@ -31,8 +31,6 @@
31 , m_state(Starting)31 , m_state(Starting)
32 , m_focused(false)32 , m_focused(false)
33 , m_fullscreen(false)33 , m_fullscreen(false)
34 , m_windowItem(0)
35 , m_windowComponent(0)
36 , m_parentItem(0)34 , m_parentItem(0)
37 , m_surface(0)35 , m_surface(0)
38{36{
@@ -45,8 +43,6 @@
45 , m_state(Starting)43 , m_state(Starting)
46 , m_focused(false)44 , m_focused(false)
47 , m_fullscreen(false)45 , m_fullscreen(false)
48 , m_windowItem(0)
49 , m_windowComponent(0)
50 , m_parentItem(0)46 , m_parentItem(0)
51 , m_surface(0)47 , m_surface(0)
52{48{
@@ -61,12 +57,6 @@
61 }57 }
62}58}
6359
64void ApplicationInfo::onWindowComponentStatusChanged(QQmlComponent::Status status)
65{
66 if (status == QQmlComponent::Ready && !m_windowItem)
67 doCreateWindowItem();
68}
69
70void ApplicationInfo::onStateChanged(State state)60void ApplicationInfo::onStateChanged(State state)
71{61{
72 if (state == ApplicationInfo::Running) {62 if (state == ApplicationInfo::Running) {
@@ -108,55 +98,3 @@
108 Q_EMIT surfaceChanged(m_surface);98 Q_EMIT surfaceChanged(m_surface);
109 SurfaceManager::singleton()->registerSurface(m_surface);99 SurfaceManager::singleton()->registerSurface(m_surface);
110}100}
111
112void ApplicationInfo::createWindowComponent()
113{
114 // The assumptions I make here really should hold.
115 QQuickView *quickView =
116 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
117
118 QQmlEngine *engine = quickView->engine();
119
120 m_windowComponent = new QQmlComponent(engine, this);
121 m_windowComponent->setData(m_windowQml.toLatin1(), QUrl());
122}
123
124void ApplicationInfo::doCreateWindowItem()
125{
126 m_windowItem = qobject_cast<QQuickItem *>(m_windowComponent->create());
127 m_windowItem->setParentItem(m_parentItem);
128}
129
130void ApplicationInfo::createWindowItem()
131{
132 if (!m_windowComponent)
133 createWindowComponent();
134
135 // only create the windowItem once the component is ready
136 if (!m_windowComponent->isReady()) {
137 connect(m_windowComponent, &QQmlComponent::statusChanged,
138 this, &ApplicationInfo::onWindowComponentStatusChanged);
139 } else {
140 doCreateWindowItem();
141 }
142}
143
144void ApplicationInfo::showWindow(QQuickItem *parent)
145{
146 m_parentItem = parent;
147
148 if (!m_windowItem)
149 createWindowItem();
150
151 if (m_windowItem) {
152 m_windowItem->setVisible(true);
153 }
154}
155
156void ApplicationInfo::hideWindow()
157{
158 if (!m_windowItem)
159 return;
160
161 m_windowItem->setVisible(false);
162}
163101
=== modified file 'tests/mocks/Unity/Application/ApplicationInfo.h'
--- tests/mocks/Unity/Application/ApplicationInfo.h 2014-07-21 09:17:12 +0000
+++ tests/mocks/Unity/Application/ApplicationInfo.h 2014-08-05 11:53:58 +0000
@@ -88,22 +88,12 @@
88Q_SIGNALS:88Q_SIGNALS:
89 void surfaceChanged(MirSurfaceItem*);89 void surfaceChanged(MirSurfaceItem*);
9090
91public:
92 void showWindow(QQuickItem *parent);
93 void hideWindow();
94
95private Q_SLOTS:91private Q_SLOTS:
96 void onWindowComponentStatusChanged(QQmlComponent::Status status);
97 void onStateChanged(State state);92 void onStateChanged(State state);
9893
99 void createSurface();94 void createSurface();
10095
101private:96private:
102 void createWindowItem();
103 void doCreateWindowItem();
104 void createWindowComponent();
105 QQuickItem *m_windowItem;
106 QQmlComponent *m_windowComponent;
107 QQuickItem *m_parentItem;97 QQuickItem *m_parentItem;
108 MirSurfaceItem* m_surface;98 MirSurfaceItem* m_surface;
109};99};
110100
=== modified file 'tests/mocks/Unity/Application/ApplicationManager.cpp'
--- tests/mocks/Unity/Application/ApplicationManager.cpp 2014-07-24 19:22:20 +0000
+++ tests/mocks/Unity/Application/ApplicationManager.cpp 2014-08-05 11:53:58 +0000
@@ -48,16 +48,14 @@
48ApplicationManager::ApplicationManager(QObject *parent)48ApplicationManager::ApplicationManager(QObject *parent)
49 : ApplicationManagerInterface(parent)49 : ApplicationManagerInterface(parent)
50 , m_suspended(false)50 , m_suspended(false)
51 , m_mainStageComponent(0)
52 , m_mainStage(0)
53 , m_sideStageComponent(0)
54 , m_sideStage(0)
55 , m_rightMargin(0)
56{51{
57 m_roleNames.insert(RoleSurface, "surface");52 m_roleNames.insert(RoleSurface, "surface");
58 m_roleNames.insert(RoleFullscreen, "fullscreen");53 m_roleNames.insert(RoleFullscreen, "fullscreen");
5954
60 buildListOfAvailableApplications();55 buildListOfAvailableApplications();
56
57 startApplication("unity8-dash");
58 focusApplication("unity8-dash");
61}59}
6260
63ApplicationManager::~ApplicationManager()61ApplicationManager::~ApplicationManager()
@@ -136,7 +134,6 @@
136 Q_EMIT applicationAdded(application->appId());134 Q_EMIT applicationAdded(application->appId());
137 Q_EMIT countChanged();135 Q_EMIT countChanged();
138 if (count() == 1) Q_EMIT emptyChanged(isEmpty()); // was empty but not anymore136 if (count() == 1) Q_EMIT emptyChanged(isEmpty()); // was empty but not anymore
139 Q_EMIT focusRequested(application->appId());
140137
141 connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() {138 connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() {
142 QModelIndex appIndex = findIndex(application);139 QModelIndex appIndex = findIndex(application);
@@ -222,6 +219,10 @@
222219
223bool ApplicationManager::stopApplication(const QString &appId)220bool ApplicationManager::stopApplication(const QString &appId)
224{221{
222 if (appId == "unity8-dash") {
223 return false;
224 }
225
225 ApplicationInfo *application = findApplication(appId);226 ApplicationInfo *application = findApplication(appId);
226 if (application == nullptr)227 if (application == nullptr)
227 return false;228 return false;
@@ -294,39 +295,25 @@
294 for (ApplicationInfo *app : m_runningApplications) {295 for (ApplicationInfo *app : m_runningApplications) {
295 if (app->focused() && app->stage() == ApplicationInfo::MainStage) {296 if (app->focused() && app->stage() == ApplicationInfo::MainStage) {
296 app->setFocused(false);297 app->setFocused(false);
297 app->hideWindow();
298 app->setState(ApplicationInfo::Suspended);298 app->setState(ApplicationInfo::Suspended);
299 }299 }
300 }300 }
301301
302 // focus this app302 // focus this app
303 application->setFocused(true);303 application->setFocused(true);
304 if (!m_mainStage)
305 createMainStage();
306 application->setState(ApplicationInfo::Running);304 application->setState(ApplicationInfo::Running);
307 application->showWindow(m_mainStage);
308 m_mainStage->setZ(-1000);
309 if (m_sideStage)
310 m_sideStage->setZ(-2000);
311 } else if (application->stage() == ApplicationInfo::SideStage) {305 } else if (application->stage() == ApplicationInfo::SideStage) {
312 // unfocus currently focused sidestage app306 // unfocus currently focused sidestage app
313 for (ApplicationInfo *app : m_runningApplications) {307 for (ApplicationInfo *app : m_runningApplications) {
314 if (app->focused() && app->stage() == ApplicationInfo::SideStage) {308 if (app->focused() && app->stage() == ApplicationInfo::SideStage) {
315 app->setFocused(false);309 app->setFocused(false);
316 app->hideWindow();
317 app->setState(ApplicationInfo::Suspended);310 app->setState(ApplicationInfo::Suspended);
318 }311 }
319 }312 }
320313
321 // focus this app314 // focus this app
322 application->setFocused(true);315 application->setFocused(true);
323 if (!m_sideStage)
324 createSideStage();
325 application->setState(ApplicationInfo::Running);316 application->setState(ApplicationInfo::Running);
326 application->showWindow(m_sideStage);
327 m_sideStage->setZ(-1000);
328 if (m_mainStage)
329 m_mainStage->setZ(-2000);
330 }317 }
331318
332 // move app to top of stack319 // move app to top of stack
@@ -337,18 +324,14 @@
337324
338bool ApplicationManager::requestFocusApplication(const QString &appId)325bool ApplicationManager::requestFocusApplication(const QString &appId)
339{326{
340 if (appId != focusedApplicationId()) {327 QMetaObject::invokeMethod(this, "focusRequested", Qt::QueuedConnection, Q_ARG(QString, appId));
341 QMetaObject::invokeMethod(this, "focusRequested", Qt::QueuedConnection, Q_ARG(QString, appId));328 return true;
342 return true;
343 }
344 return false;
345}329}
346330
347void ApplicationManager::unfocusCurrentApplication()331void ApplicationManager::unfocusCurrentApplication()
348{332{
349 for (ApplicationInfo *app : m_runningApplications) {333 for (ApplicationInfo *app : m_runningApplications) {
350 if (app->focused()) {334 if (app->focused()) {
351 app->hideWindow();
352 app->setFocused(false);335 app->setFocused(false);
353 }336 }
354 }337 }
@@ -357,42 +340,6 @@
357340
358void ApplicationManager::generateQmlStrings(ApplicationInfo *application)341void ApplicationManager::generateQmlStrings(ApplicationInfo *application)
359{342{
360 // TODO: Is there a better way of solving this fullscreen vs. regular
361 // application height?
362 QString topMargin;
363 if (application->fullscreen()) {
364 topMargin.append("0");
365 } else {
366 // Taken from Panel.panelHeight
367 topMargin.append("units.gu(3) + units.dp(2)");
368 }
369
370 QString windowQml = QString(
371 "import QtQuick 2.0\n"
372 "Image {\n"
373 " anchors.fill: parent\n"
374 " anchors.topMargin: %1\n"
375 " anchors.rightMargin: %2\n"
376 " source: \"file://%3/Dash/graphics/phone/screenshots/%4.png\"\n"
377 " smooth: true\n"
378 " fillMode: Image.PreserveAspectCrop\n"
379 "}").arg(topMargin)
380 .arg(m_rightMargin)
381 .arg(qmlDirectory())
382 .arg(application->icon().toString());
383 application->setWindowQml(windowQml);
384
385 QString imageQml = QString(
386 "import QtQuick 2.0\n"
387 "Image {\n"
388 " anchors.fill: parent\n"
389 " source: \"file://%1/Dash/graphics/phone/screenshots/%2.png\"\n"
390 " smooth: true\n"
391 " fillMode: Image.PreserveAspectCrop\n"
392 "}").arg(qmlDirectory())
393 .arg(application->icon().toString());
394 application->setImageQml(imageQml);
395
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())
397 .arg(application->icon().toString()));344 .arg(application->icon().toString()));
398}345}
@@ -402,6 +349,14 @@
402 ApplicationInfo *application;349 ApplicationInfo *application;
403350
404 application = new ApplicationInfo(this);351 application = new ApplicationInfo(this);
352 application->setAppId("unity8-dash");
353 application->setName("Unity 8 Mock Dash");
354 application->setIcon(QUrl("unity8-dash"));
355 application->setStage(ApplicationInfo::MainStage);
356 generateQmlStrings(application);
357 m_availableApplications.append(application);
358
359 application = new ApplicationInfo(this);
405 application->setAppId("dialer-app");360 application->setAppId("dialer-app");
406 application->setName("Dialer");361 application->setName("Dialer");
407 application->setIcon(QUrl("dialer"));362 application->setIcon(QUrl("dialer"));
@@ -521,78 +476,6 @@
521 m_availableApplications.append(application);476 m_availableApplications.append(application);
522}477}
523478
524void ApplicationManager::createMainStageComponent()
525{
526 // The assumptions I make here really should hold.
527 QQuickView *quickView =
528 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
529
530 QQmlEngine *engine = quickView->engine();
531
532 m_mainStageComponent = new QQmlComponent(engine, this);
533 QString mainStageQml =
534 "import QtQuick 2.0\n"
535 "Rectangle {\n"
536 " anchors.fill: parent\n"
537 " color: 'black'\n"
538 " z: -2000\n"
539 "}\n";
540 m_mainStageComponent->setData(mainStageQml.toLatin1(), QUrl());
541}
542
543void ApplicationManager::createMainStage()
544{
545 if (!m_mainStageComponent)
546 createMainStageComponent();
547
548 // The assumptions I make here really should hold.
549 QQuickView *quickView =
550 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
551
552 QQuickItem *shell = quickView->rootObject();
553
554 m_mainStage = qobject_cast<QQuickItem *>(m_mainStageComponent->create());
555 m_mainStage->setParentItem(shell);
556}
557
558void ApplicationManager::createSideStageComponent()
559{
560 // The assumptions I make here really should hold.
561 QQuickView *quickView =
562 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
563
564 QQmlEngine *engine = quickView->engine();
565
566 m_sideStageComponent = new QQmlComponent(engine, this);
567 QString sideStageQml =
568 "import QtQuick 2.0\n"
569 "import Ubuntu.Components 0.1\n"
570 "Item {\n"
571 " width: units.gu(40)\n" // from SideStage in Shell.qml
572 " anchors.top: parent.top\n"
573 " anchors.bottom: parent.bottom\n"
574 " anchors.right: parent.right\n"
575 " z: -1000\n"
576 "}\n";
577 m_sideStageComponent->setData(sideStageQml.toLatin1(), QUrl());
578}
579
580void ApplicationManager::createSideStage()
581{
582 if (!m_sideStageComponent)
583 createSideStageComponent();
584
585 // The assumptions I make here really should hold.
586 QQuickView *quickView =
587 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
588
589 QQuickItem *shell = quickView->rootObject();
590
591 m_sideStage = qobject_cast<QQuickItem *>(m_sideStageComponent->create());
592 m_sideStage->setParentItem(shell);
593 m_sideStage->setFlag(QQuickItem::ItemHasContents, false);
594}
595
596QStringList ApplicationManager::availableApplications()479QStringList ApplicationManager::availableApplications()
597{480{
598 QStringList appIds;481 QStringList appIds;
@@ -602,19 +485,6 @@
602 return appIds;485 return appIds;
603}486}
604487
605int ApplicationManager::rightMargin() const
606{
607 return m_rightMargin;
608}
609
610void ApplicationManager::setRightMargin(int rightMargin)
611{
612 m_rightMargin = rightMargin;
613 Q_FOREACH(ApplicationInfo *app, m_availableApplications) {
614 generateQmlStrings(app);
615 }
616}
617
618bool ApplicationManager::isEmpty() const488bool ApplicationManager::isEmpty() const
619{489{
620 return m_runningApplications.isEmpty();490 return m_runningApplications.isEmpty();
621491
=== modified file 'tests/mocks/Unity/Application/ApplicationManager.h'
--- tests/mocks/Unity/Application/ApplicationManager.h 2014-07-24 19:22:20 +0000
+++ tests/mocks/Unity/Application/ApplicationManager.h 2014-08-05 11:53:58 +0000
@@ -44,10 +44,6 @@
4444
45 Q_PROPERTY(bool fake READ fake CONSTANT)45 Q_PROPERTY(bool fake READ fake CONSTANT)
4646
47 // Only for testing
48 // This can be used to place some controls to right, like make tryPhoneStage for example
49 Q_PROPERTY(int rightMargin READ rightMargin WRITE setRightMargin)
50
51 public:47 public:
52 ApplicationManager(QObject *parent = NULL);48 ApplicationManager(QObject *parent = NULL);
53 virtual ~ApplicationManager();49 virtual ~ApplicationManager();
@@ -108,8 +104,6 @@
108104
109 // Only for testing105 // Only for testing
110 Q_INVOKABLE QStringList availableApplications();106 Q_INVOKABLE QStringList availableApplications();
111 int rightMargin() const;
112 void setRightMargin(int rightMargin);
113107
114 QModelIndex findIndex(ApplicationInfo* application);108 QModelIndex findIndex(ApplicationInfo* application);
115109
@@ -126,19 +120,9 @@
126 void showApplicationWindow(ApplicationInfo *application);120 void showApplicationWindow(ApplicationInfo *application);
127 void buildListOfAvailableApplications();121 void buildListOfAvailableApplications();
128 void generateQmlStrings(ApplicationInfo *application);122 void generateQmlStrings(ApplicationInfo *application);
129 void createMainStageComponent();
130 void createMainStage();
131 void createSideStageComponent();
132 void createSideStage();
133 bool m_suspended;123 bool m_suspended;
134 QList<ApplicationInfo*> m_runningApplications;124 QList<ApplicationInfo*> m_runningApplications;
135 QList<ApplicationInfo*> m_availableApplications;125 QList<ApplicationInfo*> m_availableApplications;
136 QQmlComponent *m_mainStageComponent;
137 QQuickItem *m_mainStage;
138 QQmlComponent *m_sideStageComponent;
139 QQuickItem *m_sideStage;
140
141 int m_rightMargin;
142126
143 static ApplicationManager *the_application_manager;127 static ApplicationManager *the_application_manager;
144};128};
145129
=== modified file 'tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp'
--- tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp 2014-04-02 15:33:33 +0000
+++ tests/mocks/Unity/Application/ApplicationScreenshotProvider.cpp 2014-08-05 11:53:58 +0000
@@ -64,7 +64,7 @@
64 Q_FOREACH (QWindow *win, unity->allWindows()) {64 Q_FOREACH (QWindow *win, unity->allWindows()) {
65 QQuickWindow *quickWin = qobject_cast<QQuickWindow*>(win);65 QQuickWindow *quickWin = qobject_cast<QQuickWindow*>(win);
66 if (quickWin) {66 if (quickWin) {
67 image = image.scaledToWidth(quickWin->width() - m_appManager->rightMargin());67 image = image.scaledToWidth(quickWin->width());
68 break;68 break;
69 }69 }
70 }70 }
7171
=== modified file 'tests/mocks/Unity/CMakeLists.txt'
--- tests/mocks/Unity/CMakeLists.txt 2014-07-25 13:25:45 +0000
+++ tests/mocks/Unity/CMakeLists.txt 2014-08-05 11:53:58 +0000
@@ -2,6 +2,7 @@
2add_subdirectory(Indicators)2add_subdirectory(Indicators)
3add_subdirectory(Launcher)3add_subdirectory(Launcher)
4add_subdirectory(Notifications)4add_subdirectory(Notifications)
5add_subdirectory(DashCommunicator)
56
6pkg_search_module(DEE dee-1.0 REQUIRED)7pkg_search_module(DEE dee-1.0 REQUIRED)
7pkg_search_module(GOBJECT gobject-2.0 REQUIRED)8pkg_search_module(GOBJECT gobject-2.0 REQUIRED)
89
=== added directory 'tests/mocks/Unity/DashCommunicator'
=== added file 'tests/mocks/Unity/DashCommunicator/CMakeLists.txt'
--- tests/mocks/Unity/DashCommunicator/CMakeLists.txt 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/DashCommunicator/CMakeLists.txt 2014-08-05 11:53:58 +0000
@@ -0,0 +1,18 @@
1include_directories(
2 ${CMAKE_CURRENT_SOURCE_DIR}
3)
4
5set(QMLDASHCOMMUNICATORPLUGIN_SRC
6 plugin.cpp
7 dashcommunicatorservice.cpp
8 dashcommunicator.cpp
9 )
10
11add_library(MockDashCommunicator-qml MODULE
12 ${QMLDASHCOMMUNICATORPLUGIN_SRC}
13 )
14
15qt5_use_modules(MockDashCommunicator-qml DBus Qml)
16
17# export the qmldir and qmltypes files
18add_unity8_mock(Unity.DashCommunicator 0.1 Unity/DashCommunicator TARGETS MockDashCommunicator-qml)
019
=== added file 'tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp'
--- tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/DashCommunicator/dashcommunicator.cpp 2014-08-05 11:53:58 +0000
@@ -0,0 +1,37 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "dashcommunicator.h"
18
19#include <QObject>
20#include <QDBusConnection>
21#include <QDBusInterface>
22#include <QDebug>
23
24DashCommunicator::DashCommunicator(QObject *parent):
25 QObject(parent)
26{
27}
28
29DashCommunicator::~DashCommunicator()
30{
31}
32
33
34void DashCommunicator::setCurrentScope(const QString &scopeId, bool animate, bool reset)
35{
36 Q_EMIT setCurrentScopeCalled(scopeId, animate, reset);
37}
038
=== added file 'tests/mocks/Unity/DashCommunicator/dashcommunicator.h'
--- tests/mocks/Unity/DashCommunicator/dashcommunicator.h 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/DashCommunicator/dashcommunicator.h 2014-08-05 11:53:58 +0000
@@ -0,0 +1,39 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef DASHCOMMUNICATOR_H
18#define DASHCOMMUNICATOR_H
19
20#include <QObject>
21
22class DashCommunicator: public QObject
23{
24 Q_OBJECT
25 Q_CLASSINFO("D-Bus Interface", "com.canonical.Unity.DashCommunicator")
26
27public:
28 DashCommunicator(QObject *parent = 0);
29 ~DashCommunicator();
30
31public Q_SLOTS:
32 void setCurrentScope(const QString &scopeId, bool animate, bool reset);
33
34Q_SIGNALS:
35 // This mock just emits calls back to the QML api for the plugin to verify calls
36 void setCurrentScopeCalled(const QString &scopeId, bool animate, bool reset);
37};
38
39#endif
040
=== added file 'tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp'
--- tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.cpp 2014-08-05 11:53:58 +0000
@@ -0,0 +1,33 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#include "dashcommunicatorservice.h"
18
19DashCommunicatorService::DashCommunicatorService(QObject *parent):
20 QObject(parent)
21{
22}
23
24
25DashCommunicatorService::~DashCommunicatorService()
26{
27
28}
29
30void DashCommunicatorService::mockSetCurrentScope(const QString &scopeId, bool animate, bool reset)
31{
32 Q_EMIT setCurrentScopeRequested(scopeId, animate, reset);
33}
034
=== added file 'tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h'
--- tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/DashCommunicator/dashcommunicatorservice.h 2014-08-05 11:53:58 +0000
@@ -0,0 +1,36 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Lesser General Public License version 3, as published by
6 * the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef DASHCOMMUNICATORSERVICE_H
18#define DASHCOMMUNICATORSERVICE_H
19
20#include <QObject>
21
22class DashCommunicatorService: public QObject
23{
24 Q_OBJECT
25public:
26 DashCommunicatorService(QObject *parent = 0);
27 ~DashCommunicatorService();
28
29Q_SIGNALS:
30 void setCurrentScopeRequested(const QString &scopeId, bool animate, bool reset);
31
32public Q_SLOTS:
33 void mockSetCurrentScope(const QString &scopeId, bool animate, bool reset);
34};
35
36#endif // DBUSUNITYSESSIONSERVICE_H
037
=== added file 'tests/mocks/Unity/DashCommunicator/plugin.cpp'
--- tests/mocks/Unity/DashCommunicator/plugin.cpp 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/DashCommunicator/plugin.cpp 2014-08-05 11:53:58 +0000
@@ -0,0 +1,31 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17 */
18
19#include "plugin.h"
20#include "dashcommunicator.h"
21#include "dashcommunicatorservice.h"
22
23#include <QDBusConnection>
24#include <QtQml/qqml.h>
25
26void DashCommunicatorPlugin::registerTypes(const char *uri)
27{
28 Q_ASSERT(uri == QStringLiteral("Unity.DashCommunicator"));
29 qmlRegisterType<DashCommunicatorService>(uri, 0, 1, "DashCommunicatorService");
30 qmlRegisterType<DashCommunicator>(uri, 0, 1, "DashCommunicator");
31}
032
=== added file 'tests/mocks/Unity/DashCommunicator/plugin.h'
--- tests/mocks/Unity/DashCommunicator/plugin.h 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/DashCommunicator/plugin.h 2014-08-05 11:53:58 +0000
@@ -0,0 +1,34 @@
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors: Michael Zanetti <michael.zanetti@canonical.com>
17 */
18
19#ifndef DASHCOMMUNICATOR_PLUGIN_H
20#define DASHCOMMUNICATOR_PLUGIN_H
21
22#include <QtQml/QQmlEngine>
23#include <QtQml/QQmlExtensionPlugin>
24
25class DashCommunicatorPlugin : public QQmlExtensionPlugin
26{
27 Q_OBJECT
28 Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
29
30public:
31 void registerTypes(const char *uri);
32};
33
34#endif
035
=== added file 'tests/mocks/Unity/DashCommunicator/qmldir'
--- tests/mocks/Unity/DashCommunicator/qmldir 1970-01-01 00:00:00 +0000
+++ tests/mocks/Unity/DashCommunicator/qmldir 2014-08-05 11:53:58 +0000
@@ -0,0 +1,3 @@
1module Unity.DashCommunicator
2plugin MockDashCommunicator-qml
3typeinfo DashCommunicator.qmltypes
04
=== modified file 'tests/qmltests/Dash/tst_Dash.qml'
--- tests/qmltests/Dash/tst_Dash.qml 2014-07-11 11:45:45 +0000
+++ tests/qmltests/Dash/tst_Dash.qml 2014-08-05 11:53:58 +0000
@@ -59,6 +59,7 @@
59 verify(dashContentList != undefined);59 verify(dashContentList != undefined);
60 tryCompare(dashContentList, "count", 0);60 tryCompare(dashContentList, "count", 0);
61 scopes.load();61 scopes.load();
62 tryCompare(dashContentList, "currentIndex", 0);
62 }63 }
6364
64 function get_scope_data() {65 function get_scope_data() {
@@ -91,5 +92,23 @@
91 verify(dashContentList != undefined);92 verify(dashContentList != undefined);
92 tryCompare(dashContentList, "currentIndex", data.visualIndex);93 tryCompare(dashContentList, "currentIndex", data.visualIndex);
93 }94 }
95
96 function test_setCurrentScope() {
97 var dashContentList = findChild(dash, "dashContentList");
98 var startX = dash.width - units.gu(1);
99 var startY = dash.height / 2;
100 var stopX = units.gu(1)
101 var stopY = startY;
102 var retry = 0;
103 while (dashContentList.currentIndex != 2 && retry <= 5) {
104 mouseFlick(dash, startX, startY, stopX, stopY)
105 waitForRendering(dashContentList)
106 retry++;
107 }
108 compare(dashContentList.currentIndex, 2);
109 var dashCommunicatorService = findInvisibleChild(dash, "dashCommunicatorService");
110 dashCommunicatorService.mockSetCurrentScope("clickscope", true, true);
111 tryCompare(dashContentList, "currentIndex", 1)
112 }
94 }113 }
95}114}
96115
=== modified file 'tests/qmltests/Stages/tst_PhoneStage.qml'
--- tests/qmltests/Stages/tst_PhoneStage.qml 2014-07-24 21:56:42 +0000
+++ tests/qmltests/Stages/tst_PhoneStage.qml 2014-08-05 11:53:58 +0000
@@ -231,9 +231,10 @@
231 }231 }
232232
233 function cleanup() {233 function cleanup() {
234 while (ApplicationManager.count > 0) {234 while (ApplicationManager.count > 1) {
235 var oldCount = ApplicationManager.count;235 var oldCount = ApplicationManager.count;
236 ApplicationManager.stopApplication(ApplicationManager.get(0).appId)236 var closingIndex = ApplicationManager.focusedApplicationId == "unity8-dash" ? 1 : 0
237 ApplicationManager.stopApplication(ApplicationManager.get(closingIndex).appId)
237 tryCompare(ApplicationManager, "count", oldCount - 1)238 tryCompare(ApplicationManager, "count", oldCount - 1)
238 }239 }
239 }240 }
240241
=== modified file 'tests/qmltests/tst_Shell.qml'
--- tests/qmltests/tst_Shell.qml 2014-07-28 12:48:29 +0000
+++ tests/qmltests/tst_Shell.qml 2014-08-05 11:53:58 +0000
@@ -56,49 +56,20 @@
56 signalName: "sessionStarted"56 signalName: "sessionStarted"
57 }57 }
5858
59 SignalSpy {
60 id: dashCommunicatorSpy
61 signalName: "setCurrentScopeCalled"
62 }
63
59 UT.UnityTestCase {64 UT.UnityTestCase {
60 name: "Shell"65 name: "Shell"
61 when: windowShown66 when: windowShown
6267
63 function initTestCase() {68 function initTestCase() {
64 var ok = false;
65 var attempts = 0;
66 var maxAttempts = 1000;
67
68 // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
69 // tests may fail because the desired child item wasn't loaded yet.
70 // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
71 // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
72 // (all items instantiated, etc), I resort to checking the existence of some key items until
73 // repeatedly until they're all there.
74 do {
75 var dashContentList = findChild(shell, "dashContentList");
76 waitForRendering(dashContentList);
77 var homeLoader = findChild(dashContentList, "clickscope loader");
78 ok = homeLoader !== null
79 && homeLoader.item !== undefined;
80
81 var greeter = findChild(shell, "greeter");
82 ok &= greeter !== null;
83
84 var launcherPanel = findChild(shell, "launcherPanel");
85 ok &= launcherPanel !== null;
86
87 attempts++;
88 if (!ok) {
89 console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
90 // wait a bit before retrying
91 wait(100);
92 } else {
93 console.log("All seem fine after " + attempts + " attempts.");
94 }
95 } while (!ok && attempts <= maxAttempts);
96
97 verify(ok);
98
99 swipeAwayGreeter();69 swipeAwayGreeter();
10070
101 sessionSpy.target = findChild(shell, "greeter")71 sessionSpy.target = findChild(shell, "greeter")
72 dashCommunicatorSpy.target = findInvisibleChild(shell, "dashCommunicator");
102 }73 }
10374
104 function cleanup() {75 function cleanup() {
@@ -111,56 +82,16 @@
111 // kill all (fake) running apps82 // kill all (fake) running apps
112 killApps(ApplicationManager);83 killApps(ApplicationManager);
11384
114 var dashContent = findChild(shell, "dashContent");85 waitForUIToSettle();
115 dashContent.closePreview();
116
117 var dashHome = findChild(shell, "clickscope loader");
118 swipeUntilScopeViewIsReached(dashHome);
119
120 hideIndicators();86 hideIndicators();
121 }87 }
12288
123 function killApps(apps) {89 function killApps() {
124 if (!apps) return;90 while (ApplicationManager.count > 1) {
125 while (apps.count > 0) {91 var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
126 ApplicationManager.stopApplication(apps.get(0).appId);92 ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
127 }93 }
128 compare(ApplicationManager.count, 0)94 compare(ApplicationManager.count, 1)
129 }
130
131 /*
132 Test the effect of a right-edge drag on the dash in 3 situations:
133 1 - when no application has been launched yet
134 2 - when there's a minimized application
135 3 - after the last running application has been closed/stopped
136
137 The behavior of Dash on 3 should be the same as on 1.
138 */
139 function test_rightEdgeDrag() {
140 checkRightEdgeDragWithNoRunningApps();
141
142 dragLauncherIntoView();
143
144 // Launch an app from the launcher
145 tapOnAppIconInLauncher();
146 waitUntilApplicationWindowIsFullyVisible();
147
148 // Minimize the application we just launched
149 swipeFromLeftEdge(units.gu(27));
150
151 waitForUIToSettle();
152
153 checkRightEdgeDragWithMinimizedApp();
154
155 // Minimize that application once again
156 swipeFromLeftEdge(units.gu(27));
157
158 // Right edge behavior should now be the same as before that app,
159 // was launched. Manually cleanup beforehand to get to initial
160 // state.
161 cleanup();
162 waitForUIToSettle();
163 checkRightEdgeDragWithNoRunningApps();
164 }95 }
16596
166 function test_leftEdgeDrag_data() {97 function test_leftEdgeDrag_data() {
@@ -183,7 +114,7 @@
183114
184 swipeFromLeftEdge(data.swipeLength);115 swipeFromLeftEdge(data.swipeLength);
185 if (data.appHides)116 if (data.appHides)
186 waitUntilApplicationWindowIsFullyHidden();117 waitUntilDashIsFocused();
187 else118 else
188 waitUntilApplicationWindowIsFullyVisible();119 waitUntilApplicationWindowIsFullyVisible();
189 }120 }
@@ -240,99 +171,17 @@
240 }171 }
241172
242 /*173 /*
243 Perform a right-edge drag when the Dash is being show and there are
244 no running/minimized apps to be restored.
245
246 The expected behavior is that an animation should be played to hint the
247 user that his right-edge drag gesture has been successfully recognized
248 but there is no application to be brought to foreground.
249 */
250 function checkRightEdgeDragWithNoRunningApps() {
251 var touchX = shell.width - (shell.edgeSize / 2);
252 var touchY = shell.height / 2;
253
254 var dash = findChild(shell, "dash");
255 // check that dash has normal scale and opacity
256 tryCompare(dash, "contentScale", 1.0);
257 tryCompare(dash, "opacity", 1.0);
258
259 touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
260 true /* beginTouch */, false /* endTouch */, units.gu(10), 50);
261
262 // check that Dash has been scaled down and had its opacity reduced
263 tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
264 tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
265
266 touchRelease(shell, shell.width * 0.1, touchY);
267
268 // and now everything should have gone back to normal
269 tryCompare(dash, "contentScale", 1.0);
270 tryCompare(dash, "opacity", 1.0);
271 }
272
273 /*
274 Perform a right-edge drag when the Dash is being show and there is
275 a running/minimized app to be restored.
276
277 The expected behavior is that the dash should fade away and ultimately be
278 made invisible once the gesture is finished as the restored app will now
279 be on foreground.
280 */
281 function checkRightEdgeDragWithMinimizedApp() {
282 var touchX = shell.width - (shell.edgeSize / 2);
283 var touchY = shell.height / 2;
284
285 var dash = findChild(shell, "dash");
286 // check that dash has normal scale and opacity
287 tryCompare(dash, "contentScale", 1.0);
288 tryCompare(dash, "opacity", 1.0);
289
290 touchFlick(shell, touchX, touchY, shell.width * 0.1, touchY,
291 true /* beginTouch */, false /* endTouch */, units.gu(10), 50);
292
293 // check that Dash has been scaled down and had its opacity reduced
294 tryCompareFunction(function() { return dash.contentScale <= 0.9; }, true);
295 tryCompareFunction(function() { return dash.opacity <= 0.5; }, true);
296
297 touchRelease(shell, shell.width * 0.1, touchY);
298
299 // dash should have gone away, now that the app is on foreground
300 tryCompare(dash, "visible", false);
301 }
302
303 /*
304 Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419174 Regression test for bug https://bugs.launchpad.net/touch-preview-images/+bug/1193419
305175
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
307 category of the "Applications" scope view.177 "Applications" scope view.
308178
309 Steps:179 Steps:
310 - go to apps lens180 - reveal launcher and launch an app that covers the dash
311 - scroll to the bottom
312 - reveal launcher and launch an app
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.
314182 - verify the setCurrentScope() D-Bus call to the dash has been called for the correct scope id.
315 Expected Results
316 - apps lens shown
317 */183 */
318 function test_minimizingAppTakesToDashApps() {184 function test_minimizingAppTakesToDashApps() {
319 var dashApps = findChild(shell, "clickscope");
320 swipeUntilScopeViewIsReached(dashApps);
321
322 // swipe finger up until the running/recent apps section (which we assume
323 // it's the first one) is as far from view as possible.
324 // We also assume that DashApps is tall enough that it's scrollable
325 var appsCategoryListView = findChild(dashApps, "categoryListView");
326 while (!appsCategoryListView.atYEnd) {
327 swipeUpFromCenter();
328 tryCompare(appsCategoryListView, "moving", false);
329 }
330
331 // Switch away from the Applications scope.
332 swipeRightFromCenter();
333 waitUntilItemStopsMoving(dashApps);
334 verify(!itemIsOnScreen(dashApps));
335
336 dragLauncherIntoView();185 dragLauncherIntoView();
337186
338 // Launch an app from the launcher187 // Launch an app from the launcher
@@ -340,19 +189,16 @@
340189
341 waitUntilApplicationWindowIsFullyVisible();190 waitUntilApplicationWindowIsFullyVisible();
342191
343 // Dragging launcher into view with a little bit of gap (units.gu(1)) should switch to Apps scope192 verify(ApplicationManager.focusedApplicationId !== "unity8-dash")
344 dragLauncherIntoView();
345 verify(itemIsOnScreen(dashApps));
346193
194 dashCommunicatorSpy.clear();
347 // Minimize the application we just launched195 // Minimize the application we just launched
348 swipeFromLeftEdge(units.gu(27));196 swipeFromLeftEdge(units.gu(27));
349197
350 // Wait for the whole UI to settle down198 tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
351 waitUntilApplicationWindowIsFullyHidden();
352 waitUntilItemStopsMoving(dashApps);
353 tryCompare(appsCategoryListView, "moving", false);
354199
355 verify(itemIsOnScreen(dashApps));200 compare(dashCommunicatorSpy.count, 1);
201 compare(dashCommunicatorSpy.signalArguments[0][0], "clickscope");
356 }202 }
357203
358 function test_showInputMethod() {204 function test_showInputMethod() {
@@ -409,9 +255,14 @@
409255
410 // Wait for the whole UI to settle down256 // Wait for the whole UI to settle down
411 function waitForUIToSettle() {257 function waitForUIToSettle() {
412 waitUntilApplicationWindowIsFullyHidden();258 var launcher = findChild(shell, "launcherPanel")
413 var dashContentList = findChild(shell, "dashContentList");259 tryCompareFunction(function() {return launcher.x === 0 || launcher.x === -launcher.width;}, true);
414 tryCompare(dashContentList, "moving", false);260 if (launcher.x === 0) {
261 mouseClick(shell, shell.width / 2, shell.height / 2)
262 }
263 tryCompare(launcher, "x", -launcher.width)
264
265 waitForRendering(shell)
415 }266 }
416267
417 function dragToCloseIndicatorsPanel() {268 function dragToCloseIndicatorsPanel() {
@@ -468,24 +319,13 @@
468 }319 }
469320
470 function waitUntilApplicationWindowIsFullyVisible() {321 function waitUntilApplicationWindowIsFullyVisible() {
471 var underlay = findChild(shell, "underlay");322 var appDelegate = findChild(shell, "appDelegate0")
472 tryCompare(underlay, "visible", false);323 var surfaceContainer = findChild(appDelegate, "surfaceContainer");
473 }324 tryCompareFunction(function() { return surfaceContainer.surface !== null; }, true);
474325 }
475 function waitUntilApplicationWindowIsFullyHidden() {326
476 var stages = findChild(shell, "stages");327 function waitUntilDashIsFocused() {
477 tryCompare(stages, "fullyHidden", true);328 tryCompare(ApplicationManager, "focusedApplicationId", "unity8-dash");
478 }
479
480 function swipeUntilScopeViewIsReached(scopeView) {
481 while (!itemIsOnScreen(scopeView)) {
482 if (itemIsToLeftOfScreen(scopeView)) {
483 swipeRightFromCenter();
484 } else {
485 swipeLeftFromCenter();
486 }
487 waitUntilItemStopsMoving(scopeView);
488 }
489 }329 }
490330
491 function swipeFromLeftEdge(swipeLength) {331 function swipeFromLeftEdge(swipeLength) {
@@ -494,24 +334,6 @@
494 touchFlick(shell, touchStartX, touchStartY, swipeLength, touchStartY);334 touchFlick(shell, touchStartX, touchStartY, swipeLength, touchStartY);
495 }335 }
496336
497 function swipeLeftFromCenter() {
498 var touchStartX = shell.width * 3 / 4;
499 var touchStartY = shell.height / 2;
500 touchFlick(shell, touchStartX, touchStartY, 0, touchStartY);
501 }
502
503 function swipeRightFromCenter() {
504 var touchStartX = shell.width * 3 / 4;
505 var touchStartY = shell.height / 2;
506 touchFlick(shell, touchStartX, touchStartY, shell.width, touchStartY);
507 }
508
509 function swipeUpFromCenter() {
510 var touchStartX = shell.width / 2;
511 var touchStartY = shell.height / 2;
512 touchFlick(shell, touchStartX, touchStartY, touchStartX, 0);
513 }
514
515 function itemIsOnScreen(item) {337 function itemIsOnScreen(item) {
516 var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);338 var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
517339
@@ -521,64 +343,6 @@
521 && itemRectInShell.y + itemRectInShell.height <= shell.height;343 && itemRectInShell.y + itemRectInShell.height <= shell.height;
522 }344 }
523345
524 function itemIsToLeftOfScreen(item) {
525 var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
526 return itemRectInShell.x < 0;
527 }
528
529 function waitUntilItemStopsMoving(item) {
530 var itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
531 var previousX = itemRectInShell.x;
532 var previousY = itemRectInShell.y;
533 var isStill = false;
534
535 do {
536 wait(100);
537 itemRectInShell = item.mapToItem(shell, 0, 0, item.width, item.height);
538 if (itemRectInShell.x == previousX && itemRectInShell.y == previousY) {
539 isStill = true;
540 } else {
541 previousX = itemRectInShell.x;
542 previousY = itemRectInShell.y;
543 }
544 } while (!isStill);
545 }
546
547 function test_DashShown_data() {
548 return [
549 {tag: "in focus", greeter: false, app: false, launcher: false, indicators: false, expectedShown: true},
550 {tag: "under greeter", greeter: true, app: false, launcher: false, indicators: false, expectedShown: false},
551 {tag: "under app", greeter: false, app: true, launcher: false, indicators: false, expectedShown: false},
552 {tag: "under launcher", greeter: false, app: false, launcher: true, indicators: false, expectedShown: true},
553 {tag: "under indicators", greeter: false, app: false, launcher: false, indicators: true, expectedShown: false},
554 ]
555 }
556
557 function test_DashShown(data) {
558 if (data.greeter) {
559 // Swipe the greeter in
560 var greeter = findChild(shell, "greeter");
561 Powerd.displayPowerStateChange(Powerd.Off, 0);
562 tryCompare(greeter, "showProgress", 1);
563 }
564
565 if (data.app) {
566 dragLauncherIntoView();
567 tapOnAppIconInLauncher();
568 }
569
570 if (data.launcher) {
571 dragLauncherIntoView();
572 }
573
574 if (data.indicators) {
575 showIndicators();
576 }
577
578 var dash = findChild(shell, "dash");
579 tryCompare(dash, "shown", data.expectedShown);
580 }
581
582 function test_focusRequestedHidesGreeter() {346 function test_focusRequestedHidesGreeter() {
583 var greeter = findChild(shell, "greeter");347 var greeter = findChild(shell, "greeter");
584348
@@ -587,10 +351,9 @@
587 tryCompareFunction(function() { return app.surface != null }, true);351 tryCompareFunction(function() { return app.surface != null }, true);
588352
589 // Minimize the application we just launched353 // Minimize the application we just launched
590 swipeFromLeftEdge(units.gu(27));354 swipeFromLeftEdge(units.gu(26) + 1);
591355
592 // Wait for the whole UI to settle down356 waitUntilDashIsFocused();
593 waitUntilApplicationWindowIsFullyHidden();
594357
595 greeter.show();358 greeter.show();
596 tryCompare(greeter, "showProgress", 1);359 tryCompare(greeter, "showProgress", 1);
@@ -606,8 +369,9 @@
606369
607 showIndicators();370 showIndicators();
608371
372 var oldCount = ApplicationManager.count;
609 ApplicationManager.startApplication("camera-app");373 ApplicationManager.startApplication("camera-app");
610 tryCompare(ApplicationManager, "count", 1);374 tryCompare(ApplicationManager, "count", oldCount + 1);
611375
612 tryCompare(indicators, "fullyClosed", true);376 tryCompare(indicators, "fullyClosed", true);
613 }377 }
@@ -616,6 +380,7 @@
616 function test_showGreeterDBusCall() {380 function test_showGreeterDBusCall() {
617 var greeter = findChild(shell, "greeter")381 var greeter = findChild(shell, "greeter")
618 tryCompare(greeter, "showProgress", 0)382 tryCompare(greeter, "showProgress", 0)
383 waitForRendering(greeter);
619 LightDM.Greeter.showGreeter()384 LightDM.Greeter.showGreeter()
620 tryCompare(greeter, "showProgress", 1)385 tryCompare(greeter, "showProgress", 1)
621 }386 }
@@ -624,6 +389,7 @@
624 sessionSpy.clear()389 sessionSpy.clear()
625390
626 var greeter = findChild(shell, "greeter")391 var greeter = findChild(shell, "greeter")
392 waitForRendering(greeter)
627 greeter.show()393 greeter.show()
628 tryCompare(greeter, "showProgress", 1)394 tryCompare(greeter, "showProgress", 1)
629395
@@ -644,5 +410,26 @@
644 ApplicationManager.requestFocusApplication("gallery-app");410 ApplicationManager.requestFocusApplication("gallery-app");
645 tryCompare(panel, "fullscreenMode", false);411 tryCompare(panel, "fullscreenMode", false);
646 }412 }
413
414 function test_leftEdgeDragFullscreen() {
415 var panel = findChild(shell, "panel");
416 tryCompare(panel, "fullscreenMode", false)
417
418 ApplicationManager.startApplication("camera-app");
419 tryCompare(panel, "fullscreenMode", true)
420
421 var touchStartX = 2;
422 var touchStartY = shell.height / 2;
423
424 touchFlick(shell, touchStartX, touchStartY, units.gu(2), touchStartY, true, false);
425
426 compare(panel.fullscreenMode, true);
427
428 touchFlick(shell, units.gu(2), touchStartY, units.gu(10), touchStartY, false, false);
429
430 tryCompare(panel, "fullscreenMode", false);
431
432 touchRelease(shell);
433 }
647 }434 }
648}435}
649436
=== modified file 'tests/qmltests/tst_ShellWithPin.qml'
--- tests/qmltests/tst_ShellWithPin.qml 2014-07-15 18:26:25 +0000
+++ tests/qmltests/tst_ShellWithPin.qml 2014-08-05 11:53:58 +0000
@@ -58,40 +58,6 @@
58 when: windowShown58 when: windowShown
5959
60 function initTestCase() {60 function initTestCase() {
61 var ok = false;
62 var attempts = 0;
63 var maxAttempts = 1000;
64
65 // Qt loads a qml scene asynchronously. So early on, some findChild() calls made in
66 // tests may fail because the desired child item wasn't loaded yet.
67 // Thus here we try to ensure the scene has been fully loaded before proceeding with the tests.
68 // As I couldn't find an API in QQuickView & friends to tell me that the scene is 100% loaded
69 // (all items instantiated, etc), I resort to checking the existence of some key items until
70 // repeatedly until they're all there.
71 do {
72 var dashContentList = findChild(shell, "dashContentList");
73 waitForRendering(dashContentList);
74 var homeLoader = findChild(dashContentList, "clickscope loader");
75 ok = homeLoader !== null
76 && homeLoader.item !== undefined;
77
78 var greeter = findChild(shell, "greeter");
79 ok &= greeter !== null;
80
81 var launcherPanel = findChild(shell, "launcherPanel");
82 ok &= launcherPanel !== null;
83
84 attempts++;
85 if (!ok) {
86 console.log("Attempt " + attempts + " failed. Waiting a bit before trying again.");
87 // wait a bit before retrying
88 wait(100);
89 } else {
90 console.log("All seem fine after " + attempts + " attempts.");
91 }
92 } while (!ok && attempts <= maxAttempts);
93
94 verify(ok);
9561
96 sessionSpy.target = findChild(shell, "greeter")62 sessionSpy.target = findChild(shell, "greeter")
97 }63 }
@@ -110,10 +76,11 @@
110 }76 }
11177
112 function killApps() {78 function killApps() {
113 while (ApplicationManager.count > 0) {79 while (ApplicationManager.count > 1) {
114 ApplicationManager.stopApplication(ApplicationManager.get(0).appId)80 var appIndex = ApplicationManager.get(0).appId == "unity8-dash" ? 1 : 0
81 ApplicationManager.stopApplication(ApplicationManager.get(appIndex).appId);
115 }82 }
116 compare(ApplicationManager.count, 0)83 compare(ApplicationManager.count, 1)
117 }84 }
11885
119 function swipeAwayGreeter() {86 function swipeAwayGreeter() {

Subscribers

People subscribed via source and target branches