Merge lp:~unity-team/unity8/shellRotation into lp:unity8

Proposed by Daniel d'Andrada on 2015-04-16
Status: Merged
Approved by: Michael Zanetti on 2015-06-02
Approved revision: 1681
Merged at revision: 1804
Proposed branch: lp:~unity-team/unity8/shellRotation
Merge into: lp:unity8
Prerequisite: lp:~dandrader/unity8/unityCommandLineParser
Diff against target: 6915 lines (+4326/-608)
78 files modified
CMakeLists.txt (+3/-0)
data/unity8-dash.desktop.in (+1/-0)
debian/changelog (+6/-0)
debian/control (+5/-4)
debian/unity8.install (+3/-0)
plugins/Greeter/Unity/Launcher/CMakeLists.txt (+1/-1)
plugins/Unity/Launcher/CMakeLists.txt (+1/-1)
plugins/Utils/CMakeLists.txt (+1/-0)
plugins/Utils/plugin.cpp (+4/-1)
plugins/Utils/windowscreenshotprovider.cpp (+59/-0)
plugins/Utils/windowscreenshotprovider.h (+31/-0)
qml/CMakeLists.txt (+1/-0)
qml/Components/WindowScreenshot.qml (+35/-0)
qml/Dash/DashApplication.qml (+3/-3)
qml/Dash/graphics/phone/screenshots/gmail-webapp.svg (+343/-0)
qml/Dash/graphics/phone/screenshots/ubuntu-weather-app.svg (+201/-0)
qml/DeviceConfiguration.qml (+81/-0)
qml/Greeter/Greeter.qml (+2/-0)
qml/Greeter/NarrowView.qml (+1/-0)
qml/Greeter/WideView.qml (+1/-0)
qml/OrientedShell.qml (+185/-0)
qml/Panel/Panel.qml (+9/-0)
qml/Rotation/HalfLoopRotationAnimation.qml (+46/-0)
qml/Rotation/ImmediateRotationAction.qml (+45/-0)
qml/Rotation/NinetyRotationAnimation.qml (+90/-0)
qml/Rotation/RotationStates.qml (+278/-0)
qml/Shell.qml (+112/-49)
qml/Stages/ApplicationWindow.qml (+53/-18)
qml/Stages/DesktopStage.qml (+23/-0)
qml/Stages/OrientationChangeAnimation.qml (+241/-0)
qml/Stages/PhoneStage.qml (+137/-38)
qml/Stages/SessionContainer.qml (+2/-8)
qml/Stages/SpreadDelegate.qml (+265/-24)
qml/Stages/SurfaceContainer.qml (+2/-2)
qml/Stages/TabletStage.qml (+149/-19)
qml/Stages/TransformedSpreadDelegate.qml (+50/-6)
qml/Stages/TransformedTabletSpreadDelegate.qml (+5/-2)
run.sh (+1/-1)
src/ApplicationArguments.cpp (+22/-0)
src/ApplicationArguments.h (+7/-11)
src/CMakeLists.txt (+6/-7)
src/Dash/CMakeLists.txt (+7/-1)
src/Dash/main.cpp (+12/-6)
src/UnityCommandLineParser.cpp (+5/-0)
src/UnityCommandLineParser.h (+2/-0)
src/main.cpp (+18/-8)
tests/mocks/Unity/Application/ApplicationInfo.cpp (+45/-4)
tests/mocks/Unity/Application/ApplicationInfo.h (+9/-1)
tests/mocks/Unity/Application/ApplicationManager.cpp (+39/-2)
tests/mocks/Unity/Application/CMakeLists.txt (+1/-2)
tests/mocks/Unity/Application/MirSurfaceItem.cpp (+12/-29)
tests/mocks/Unity/Application/MirSurfaceItem.h (+29/-29)
tests/mocks/Unity/Application/MirSurfaceItem.qml (+12/-14)
tests/mocks/Unity/Application/SurfaceManager.cpp (+4/-34)
tests/mocks/Unity/Application/SurfaceManager.h (+2/-5)
tests/mocks/Unity/Application/UbuntuKeyboardInfo.cpp (+33/-1)
tests/mocks/Unity/Application/UbuntuKeyboardInfo.h (+11/-5)
tests/mocks/Unity/Application/VirtualKeyboard.cpp (+44/-0)
tests/mocks/Unity/Application/VirtualKeyboard.h (+42/-0)
tests/mocks/Unity/Application/VirtualKeyboard.qml (+7/-1)
tests/mocks/Unity/Launcher/MockLauncherModel.cpp (+3/-1)
tests/mocks/Utils/CMakeLists.txt (+1/-0)
tests/mocks/Utils/plugin.cpp (+3/-0)
tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt (+1/-1)
tests/plugins/Unity/Launcher/CMakeLists.txt (+0/-1)
tests/plugins/Unity/Launcher/launchermodeltest.cpp (+3/-1)
tests/qmltests/CMakeLists.txt (+1/-0)
tests/qmltests/Panel/tst_IndicatorsMenu.qml (+0/-2)
tests/qmltests/Panel/tst_Panel.qml (+0/-2)
tests/qmltests/Stages/tst_ApplicationWindow.qml (+14/-23)
tests/qmltests/Stages/tst_PhoneStage.qml (+5/-58)
tests/qmltests/Stages/tst_SessionContainer.qml (+1/-64)
tests/qmltests/Stages/tst_SpreadDelegate.qml (+173/-38)
tests/qmltests/Stages/tst_TabletStage.qml (+51/-0)
tests/qmltests/tst_OrientedShell.qml (+1151/-0)
tests/qmltests/tst_Shell.qml (+15/-69)
tests/qmltests/tst_ShellWithPin.qml (+6/-10)
tests/utils/modules/Unity/Test/UnityTestCase.qml (+53/-1)
To merge this branch: bzr merge lp:~unity-team/unity8/shellRotation
Reviewer Review Type Date Requested Status
Michael Zanetti (community) 2015-04-16 Approve on 2015-06-02
PS Jenkins bot continuous-integration 2015-04-16 Needs Fixing on 2015-05-21
Nick Dedekind (community) Abstain on 2015-05-12
Review via email: mp+256497@code.launchpad.net

This proposal supersedes a proposal from 2015-02-03.

Commit Message

Shell rotation

New dependency: libandroid-properties-dev
Updated dependencies: libunity-api-dev (>= 7.97), unity-application-impl-6

Description of the Change

* Are there any related MPs required for this MP to build/function as expected? Please list.
It's all in this PPA: https://launchpad.net/~unity-team/+archive/ubuntu/demo-stuff

https://code.launchpad.net/~dandrader/qtmir/supportedOrientations/+merge/242213
https://code.launchpad.net/~dandrader/qtubuntu/shellRotation/+merge/242215
https://code.launchpad.net/~phablet-team/ubuntu-keyboard/shellRotation/+merge/248399
https://code.launchpad.net/~dandrader/unity-api/shellRotation/+merge/242212

* Did you perform an exploratory manual test run of your code change and any related functionality?
Yes

* 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?
Not applicable

* If you changed the UI, has there been a design review?
Not sure, I guess they seen it by now. At least it's following the design spec for that.

To post a comment you must log in.
Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

Text conflict in tests/mocks/Unity/Application/ApplicationManager.h
Text conflict in tests/qmltests/tst_Shell.qml
2 conflicts encountered.

Michael Zanetti (mzanetti) wrote : Posted in a previous version of this proposal

1202 + d.transitioning = true;

I don't really like the fact that all the rotation animations reach out of context and operate on another object's "d" object. Can we make that more readable?

review: Needs Fixing
Michael Zanetti (mzanetti) wrote : Posted in a previous version of this proposal

1627 + * Copyright (C) 2013-2014 Canonical, Ltd.

You probably want to do another round of updating those headers to 2015

review: Needs Fixing
Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 05/03/15 08:22, Michael Zanetti wrote:
> Review: Needs Fixing
>
> 1202 + d.transitioning = true;
>
> I don't really like the fact that all the rotation animations reach out of context and operate on another object's "d" object. Can we make that more readable?
Done.

Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 05/03/15 08:45, Michael Zanetti wrote:
> Review: Needs Fixing
>
> 1627 + * Copyright (C) 2013-2014 Canonical, Ltd.
>
> You probably want to do another round of updating those headers to 2015
Done.

Michael Zanetti (mzanetti) wrote : Posted in a previous version of this proposal

please don't rebase this branch any more. there are branches building on top of that which throw > 30 conflicts each time you rebase... thanks.

Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 09/03/15 08:54, Michael Zanetti wrote:
> please don't rebase this branch any more. there are branches building on top of that which throw > 30 conflicts each time you rebase... thanks.
Oh, that sucks. I thought bzr would be smarter than that. Sorry.

Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

Text conflict in src/main.cpp
Text conflict in tests/qmltests/tst_Shell.qml
Contents conflict in tests/qmltests/tst_TabletShell.qml

Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 19/03/2015 05:14, Albert Astals Cid wrote:
> Text conflict in src/main.cpp
> Text conflict in tests/qmltests/tst_Shell.qml
> Contents conflict in tests/qmltests/tst_TabletShell.qml
Fixed.

Albert Astals Cid (aacid) wrote : Posted in a previous version of this proposal

Text conflict in plugins/Utils/plugin.cpp
Text conflict in qml/Shell.qml
Text conflict in qml/Stages/SurfaceContainer.qml
Text conflict in src/main.cpp
Conflict adding file tests/mocks/Unity/Application/MirSurfaceItem.cpp. Moved existing file to tests/mocks/Unity/Application/MirSurfaceItem.cpp.moved.
Conflict adding file tests/mocks/Unity/Application/MirSurfaceItem.h. Moved existing file to tests/mocks/Unity/Application/MirSurfaceItem.h.moved.
Text conflict in tests/qmltests/tst_Shell.qml
7 conflicts encountered.ly phase:adding file 0/89492

Daniel d'Andrada (dandrader) wrote : Posted in a previous version of this proposal

On 14/04/15 04:21, Albert Astals Cid wrote:
> Text conflict in plugins/Utils/plugin.cpp
> Text conflict in qml/Shell.qml
> Text conflict in qml/Stages/SurfaceContainer.qml
> Text conflict in src/main.cpp
> Conflict adding file tests/mocks/Unity/Application/MirSurfaceItem.cpp. Moved existing file to tests/mocks/Unity/Application/MirSurfaceItem.cpp.moved.
> Conflict adding file tests/mocks/Unity/Application/MirSurfaceItem.h. Moved existing file to tests/mocks/Unity/Application/MirSurfaceItem.h.moved.
> Text conflict in tests/qmltests/tst_Shell.qml
> 7 conflicts encountered.ly phase:adding file 0/89492
>
Fixed. Thanks for spotting that.

lp:~unity-team/unity8/shellRotation updated on 2015-04-20
1668. By Daniel d'Andrada on 2015-04-20

Fix bad merge (add UnityCommandLineParser::deviceName back)

Michael Zanetti (mzanetti) wrote :

2970+ // break binding
2971+ appWindowWithShadow.orientationAngle = appWindowWithShadow.orientationAngle;

This looks a bit odd... Wouldn't it be better to not use a binding in the first place - or - if using a binding, not breaking it? Seems like it makes things weird to use if bindings are broken randomly.

review: Needs Information
Michael Zanetti (mzanetti) wrote :

Visual glitch:

* Open a bunch of apps in portrait
* focus an app that supports landscape
* rotate to landscape
* use right edge to switch to another app
* rotate to portrait
* ender spread

=> the landscape app's size doesn't match the others. During the movement in the spread it should be scaled so that all surfaces have the same size when stacked up on the left edge. There is already a mechanism in place that does this for fullscreen vs non-fullscreen apps. You can probably reuse that somehow.

review: Needs Fixing
Michael Zanetti (mzanetti) wrote :

hmm... the dialer app breaks in landscape. We probably need to patch that to lock to portrait.

Michael Zanetti (mzanetti) wrote :

Another visual glitch:

* open an app supporting landscape and rotate to landscape
* press the power button
* press the power button again

=> the lock screen shows up squeezed to landscape and then it rotates. I guess in this case we should skip the rotation animation.

Michael Zanetti (mzanetti) wrote :

* open some apps supporting landscape but keep them in portrait before putting them to background
* now rotate the device to landscape
* use the right edge to switch to some other app

=> it'll animate to front, leaving some empty space where the panel has been before. then it'll resize in a jump to adjust to the new panel position and only after that it starts the rotation animation. Could we skip the intermediate resize jump somehow?

I think there would be two possibilities here. a) smoothly scale to the new panel location during the animation out of the spread or b) don't adjust to the new panel location before the rotation animation has started.

lp:~unity-team/unity8/shellRotation updated on 2015-04-22
1669. By Daniel d'Andrada on 2015-04-22

Refactor TransformedSpreadDelegate scaling logic into something I can understand

lp:~unity-team/unity8/shellRotation updated on 2015-04-22
1670. By Daniel d'Andrada on 2015-04-22

Ensure that windows in the spread stack perfectly on the left of the spread

Daniel d'Andrada (dandrader) wrote :

> Visual glitch:
>
> * Open a bunch of apps in portrait
> * focus an app that supports landscape
> * rotate to landscape
> * use right edge to switch to another app
> * rotate to portrait
> * ender spread
>
> => the landscape app's size doesn't match the others. During the movement in
> the spread it should be scaled so that all surfaces have the same size when
> stacked up on the left edge. There is already a mechanism in place that does
> this for fullscreen vs non-fullscreen apps. You can probably reuse that
> somehow.

Fixed.

Albert Astals Cid (aacid) wrote :

Text conflict in debian/control
Text conflict in tests/plugins/Unity/Launcher/CMakeLists.txt
2 conflicts encountered.

lp:~unity-team/unity8/shellRotation updated on 2015-04-23
1671. By Daniel d'Andrada on 2015-04-23

Merge trunk

[ Albert Astals Cid ]
* Compile with Qt 5.5 (LP: #1437238)
* Different way of top aligning labels when the other one in the row
  is multiline (LP: #1442085)
* make pot_file
[ Andrea Cimitan ]
* Set sourceSize for DashBackground.qml Image
[ CI Train Bot ]
* New rebuild forced.
* Resync trunk. added: po/sk.po
[ Daniel d'Andrada ]
* Move handling of command line options to a separate class
* Refactor tst_PhysicalKeysMapper.qml
[ Leo Arias ]
* For autopilot tests, use the device simulation scenarios from the
  toolkit.
[ Leonardo Arias Fonseca ]
* For autopilot tests, use the device simulation scenarios from the
  toolkit.
[ Michael Zanetti ]
* Make sure dnd mode is ended properly when drag gesture is cancelled
  (LP: #1444949)
[ Michał Sawicz ]
* Fix flake8 warnings (LP: #1444170)
* Move mock indicator service to unity8-fake-env, as it's a binary-
  dependent package.
[ Nick Dedekind ]
* Use asynchronous dbus requests for property updates. (LP: #1436982)

Daniel d'Andrada (dandrader) wrote :

On 23/04/15 04:11, Albert Astals Cid wrote:
> Text conflict in debian/control
> Text conflict in tests/plugins/Unity/Launcher/CMakeLists.txt
> 2 conflicts encountered.

Fixed.

lp:~unity-team/unity8/shellRotation updated on 2015-04-23
1672. By Daniel d'Andrada on 2015-04-23

Fix the positioning of the application window screenshot

Daniel d'Andrada (dandrader) wrote :

On 20/04/15 14:14, Michael Zanetti wrote:
> * open some apps supporting landscape but keep them in portrait before putting them to background
> * now rotate the device to landscape
> * use the right edge to switch to some other app
>
> => it'll animate to front, leaving some empty space where the panel has been before. then it'll resize in a jump to adjust to the new panel position and only after that it starts the rotation animation. [...]
Fixed.

lp:~unity-team/unity8/shellRotation updated on 2015-04-23
1673. By Michael Zanetti on 2015-04-23

[ CI Train Bot ]
* New rebuild forced.
[ Daniel d'Andrada ]
* Tapping home key shows unity8-dash home added:
  plugins/Utils/ElapsedTimer.h plugins/Utils/HomeKeyWatcher.cpp
  plugins/Utils/HomeKeyWatcher.h plugins/Utils/Timer.cpp
  plugins/Utils/Timer.h tests/plugins/Utils/homekeywatchertest.cpp
[ Michał Sawicz ]
* Tapping home key shows unity8-dash home added:
  plugins/Utils/ElapsedTimer.h plugins/Utils/HomeKeyWatcher.cpp
  plugins/Utils/HomeKeyWatcher.h plugins/Utils/Timer.cpp
  plugins/Utils/Timer.h tests/plugins/Utils/homekeywatchertest.cpp

1674. By Michael Zanetti on 2015-04-23

fix bad merge

lp:~unity-team/unity8/shellRotation updated on 2015-04-24
1675. By Daniel d'Andrada on 2015-04-24

Don't animate rotation when greeter is shown or while display is off

Daniel d'Andrada (dandrader) wrote :

> Another visual glitch:
>
> * open an app supporting landscape and rotate to landscape
> * press the power button
> * press the power button again
>
> => the lock screen shows up squeezed to landscape and then it rotates. I guess
> in this case we should skip the rotation animation.

Done.

Daniel d'Andrada (dandrader) wrote :

> 2970+ // break binding
> 2971+ appWindowWithShadow.orientationAngle =
> appWindowWithShadow.orientationAngle;
>
> This looks a bit odd... Wouldn't it be better to not use a binding in the
> first place - or - if using a binding, not breaking it? Seems like it makes
> things weird to use if bindings are broken randomly.

No. That's the main point of this state, keepSceneRotationState. It's supposed to *keep* the current orientation angle. I wouldn't say it's broken randomly. It's broken when entering a specific state.

Michael Zanetti (mzanetti) wrote :

I've beeen giving it a test on the N7 during my flight yesterday. There are two things:

a) http://i.imgur.com/6I4ao1U.png

To repro open some main and side stage apps, focus a rotatable main stage app, rotate to portrait, go to spread, select a side stage app. It should rotate to landscape I'd say.

Also not really sure what should happen if you're on portrait and nextInStack is a side stage app... That's an open design question I guess. If you have an idea on that, let me know, otherwise, let's leave it as is. Getting rotation on phone seems more important than having pixel-perfect spread/sidestage/rotation combo on the tablet.

b) in the spread, side stage and main stage items have different heights. I had a chat with design... We can probably leave it as is until we have a real tablet product.

review: Needs Information
Daniel d'Andrada (dandrader) wrote :

On 27/04/15 07:59, Michael Zanetti wrote:
> Review: Needs Information
>
> I've beeen giving it a test on the N7 during my flight yesterday. There are two things:
>
> a) http://i.imgur.com/6I4ao1U.png
>
> To repro open some main and side stage apps, focus a rotatable main stage app, rotate to portrait, go to spread, select a side stage app. It should rotate to landscape I'd say.
>
> Also not really sure what should happen if you're on portrait and nextInStack is a side stage app... That's an open design question I guess. If you have an idea on that, let me know, otherwise, let's leave it as is. Getting rotation on phone seems more important than having pixel-perfect spread/sidestage/rotation combo on the tablet.

This was the best compromise I could get.

Rotating to landscape but staying in in side stage size wouldn't look
any better. Imagine you then minimize the side stage, rotate the device
back to landscape and then show the side stage again. You would get a
landscape side stage that would rotate to portrait. Pretty horrible. Not
to mention the extra complexity involved. To avoid that we could
pre-rotate the sidestage app back to portrait behind the scenes but
there are 3 problems with that: 1 - resizing two surfaces at roughly the
same time crashes mir (or qtmir maybe). I don't wanna be blocked on that
bug. 2 - We would have to keep the side stage app running behind the
scenes for a bit to be able to resize it. 3 - more code complexity and
work for something we really have no design for and the whole thing
could pretty easily get scrapped on the next design.

> b) in the spread, side stage and main stage items have different heights. I had a chat with design... We can probably leave it as is until we have a real tablet product.
>

Yes, please! It's very likely that this is an existing problem with the
current tablet code.

Michael Zanetti (mzanetti) wrote :

> > Visual glitch:
> >
> > * Open a bunch of apps in portrait
> > * focus an app that supports landscape
> > * rotate to landscape
> > * use right edge to switch to another app
> > * rotate to portrait
> > * ender spread
> >
> > => the landscape app's size doesn't match the others. During the movement in
> > the spread it should be scaled so that all surfaces have the same size when
> > stacked up on the left edge. There is already a mechanism in place that does
> > this for fullscreen vs non-fullscreen apps. You can probably reuse that
> > somehow.
>
> Fixed.

I can still see this: http://i.imgur.com/nKXeq6Z.png

See how the landscape contacts app is smaller than the other (portrait) apps.

review: Needs Fixing
Michał Sawicz (saviq) wrote :

W dniu 28.04.2015 o 18:56, Michael Zanetti pisze:
> See how the landscape contacts app is smaller than the other (portrait) apps.

That highlighted one more issue - screenshots should be saved with
current orientation :)

lp:~unity-team/unity8/shellRotation updated on 2015-04-28
1676. By Daniel d'Andrada on 2015-04-28

Make all items in the spread have the very same size when stacked on the left side

Daniel d'Andrada (dandrader) wrote :

> > > Visual glitch:
> > >
> > > * Open a bunch of apps in portrait
> > > * focus an app that supports landscape
> > > * rotate to landscape
> > > * use right edge to switch to another app
> > > * rotate to portrait
> > > * ender spread
> > >
> > > => the landscape app's size doesn't match the others. During the movement
> in
> > > the spread it should be scaled so that all surfaces have the same size
> when
> > > stacked up on the left edge. There is already a mechanism in place that
> does
> > > this for fullscreen vs non-fullscreen apps. You can probably reuse that
> > > somehow.
> >
> > Fixed.
>
> I can still see this: http://i.imgur.com/nKXeq6Z.png
>
> See how the landscape contacts app is smaller than the other (portrait) apps.

Fixed.

Albert Astals Cid (aacid) wrote :

Yesterday at some point we got http://imgur.com/j9utzlX

I'll try to see if I can reproduce it.

Daniel d'Andrada (dandrader) wrote :

Whatever bug still remains, it can't be a show stopper and therefore could be dealt with later. The merging of this branch is long overdue.

Michael Zanetti (mzanetti) wrote :

> Whatever bug still remains, it can't be a show stopper and therefore could be
> dealt with later. The merging of this branch is long overdue.

I think the fact that the dialer app breaks is a showstopper. You didn't address that yet, did you? Besides, landing is frozen atm.

Daniel d'Andrada (dandrader) wrote :

On 29/04/15 09:50, Michael Zanetti wrote:
>> Whatever bug still remains, it can't be a show stopper and therefore could be
>> dealt with later. The merging of this branch is long overdue.
> I think the fact that the dialer app breaks is a showstopper. You didn't address that yet, did you? Besides, landing is frozen atm.
You mean that the dialer app looks bad in landscape? It's app to them to
provide the supported orientations in their desktop file

Albert Astals Cid (aacid) wrote :

Text conflict in qml/Stages/PhoneStage.qml
Text conflict in qml/Stages/TabletStage.qml
2 conflicts encountered.

Nick Dedekind (nick-dedekind) wrote :

I'm pretty sure u8 shouldn't be depending on libandroid-properties; that doesn't sound right. Perhaps this should be resolved in qtubuntu somehow?

review: Needs Information
lp:~unity-team/unity8/shellRotation updated on 2015-05-11
1677. By Daniel d'Andrada on 2015-05-11

Merge trunk

[ Albert Astals Cid ]
* Make runtests fake a test error if make fails
* Make the test more stable
* Use dbus-test-runner instead of dbus-launch
* DirectionalDragArea: improvements & API grooming (LP: #1417920)
* Fix EdgeDragEvaluator when a drag can happen both ways
  (Direction.Horizontal)
[ Josh Arenson ]
* Remove panelHeight property as it is unused.
[ Leo Arias ]
* Initial clean up of the autopilot tests set up. Removed the touch
  device from the test case. Moved the restart of unity to a fixture.
  Removed the unused DragMixin. Updated the setUpClass to use
  process_helpers. Removed the workaround for bug #1238417, already
  fixed. Use the toolkit helper to set the testability environment
  variable. Fixed the indicators base class that was restarting unity
  twice. (LP: #1238417, #1447206)
* Use the base class from the toolkit in autopilot tests.
[ Michael Zanetti ]
* emit application-stop when we're going down (LP: #1326513)
[ Michał Sawicz ]
* UNITY_SCOPES_LIST is no more
[ handsome_feng<email address hidden> ]
* When click the favorite scope in Dash Manager , it just return to
  the corresponding scope page. (LP: #1447056)

1678. By Daniel d'Andrada on 2015-05-11

Improve test code

Daniel d'Andrada (dandrader) wrote :

On 11/05/15 04:23, Albert Astals Cid wrote:
> Text conflict in qml/Stages/PhoneStage.qml
> Text conflict in qml/Stages/TabletStage.qml
> 2 conflicts encountered.
Fixed

Michael Zanetti (mzanetti) wrote :

> I'm pretty sure u8 shouldn't be depending on libandroid-properties; that
> doesn't sound right. Perhaps this should be resolved in qtubuntu somehow?

This is a fair point. At this point I probably wouldn't open that can of worms any more. The device detection is very likely to be expanded a lot in the near future. I'd say we clean this up when the bigger picture gets more visible.

Nick Dedekind (nick-dedekind) wrote :

windowgeometry command line option doesn't seem to work in either u8 or dash (does in trunk).
As I haven't really been over the MP; if it's not supposed to work any more, then the option should be removed. At the moment it's just opening a small window, which needs to be resized every time.

review: Needs Fixing
Nick Dedekind (nick-dedekind) wrote :

file:///home/nick/Work/phablet/rotation/unity8/qml/Dash/DashApplication.qml:23: TypeError: Property 'hasGeometry' of object ApplicationArguments(0x7ffd3c47e400) is not a function

Seems you removed the ApplicationArguments::hasGemoetry function.

lp:~unity-team/unity8/shellRotation updated on 2015-05-12
1679. By Daniel d'Andrada on 2015-05-12

Make -windowgeometry work again

Daniel d'Andrada (dandrader) wrote :

On 12/05/15 05:38, Nick Dedekind wrote:
> Review: Needs Fixing
>
> windowgeometry command line option doesn't seem to work in either u8 or dash (does in trunk).
> As I haven't really been over the MP; if it's not supposed to work any more, then the option should be removed. At the moment it's just opening a small window, which needs to be resized every time.
Fixed

Daniel d'Andrada (dandrader) wrote :

On 12/05/15 06:20, Nick Dedekind wrote:
> file:///home/nick/Work/phablet/rotation/unity8/qml/Dash/DashApplication.qml:23: TypeError: Property 'hasGeometry' of object ApplicationArguments(0x7ffd3c47e400) is not a function
>
> Seems you removed the ApplicationArguments::hasGemoetry function.

Yeah, not using this approach anymore.

review: Abstain
Albert Astals Cid (aacid) wrote :

Text conflict in qml/Stages/PhoneStage.qml
Text conflict in qml/Stages/TabletStage.qml
2 conflicts encountered.

lp:~unity-team/unity8/shellRotation updated on 2015-05-21
1680. By Daniel d'Andrada on 2015-05-21

Merge trunk

[ Albert Astals Cid ]
* Add overrides to override functions
* Implement "rating-edit" preview widget (LP: #1318144)
* Make the DashContent::test_mainNavigation test more stable (LP:
  #1450809)
* Use art height as implicitHeight when the header is overlayed and
  there's no summary
[ CI Train Bot ]
* New rebuild forced.
* Resync trunk.
[ Daniel d'Andrada ]
* Introducing FloatingFlickable
* Make Ubuntu.Gestures components install TouchRegistry by themselves
[ Michael Terry ]
* Fix a possible crash in our PAM threading code. (LP: #1425362) (LP:
  #1425362)
* Fix the lockscreen becoming unresponsive after testing an app on the
  device from QtCreator. (LP: #1435364)
[ Nick Dedekind ]
* Fixed desktop stage app focus.
* Fixed issue in laggy indicator autpilot tests (LP: #1446846)
[ Albert Astals Cid ]
* Workarounds for concierge mode.
[ CI Train Bot ]
* New rebuild forced.
* Resync trunk.

1681. By Daniel d'Andrada on 2015-05-21

Fix build regarding unity-api and add screenshot provider to the mock Utils plugin

Daniel d'Andrada (dandrader) wrote :

On 21/05/2015 09:03, Albert Astals Cid wrote:
> Text conflict in qml/Stages/PhoneStage.qml
> Text conflict in qml/Stages/TabletStage.qml
> 2 conflicts encountered.
>

Fixed.

Michael Zanetti (mzanetti) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2015-03-12 13:59:07 +0000
3+++ CMakeLists.txt 2015-05-21 17:30:56 +0000
4@@ -56,6 +56,8 @@
5 find_package(Qt5Concurrent 5.2 REQUIRED)
6 find_package(Qt5Sql 5.2 REQUIRED)
7
8+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=6)
9+
10 # Standard install paths
11 include(GNUInstallDirs)
12
13@@ -111,6 +113,7 @@
14 include_directories(
15 ${CMAKE_SOURCE_DIR}/include
16 ${CMAKE_BINARY_DIR}/include
17+ ${APPLICATION_API_INCLUDE_DIRS}
18 )
19
20 # add subdirectories to build
21
22=== modified file 'data/unity8-dash.desktop.in'
23--- data/unity8-dash.desktop.in 2014-09-04 13:23:09 +0000
24+++ data/unity8-dash.desktop.in 2015-05-21 17:30:56 +0000
25@@ -7,3 +7,4 @@
26 Icon=
27 NoDisplay=true
28 X-Ubuntu-Touch=true
29+X-Ubuntu-Supported-Orientations=primary
30
31=== modified file 'debian/changelog'
32--- debian/changelog 2015-05-18 23:04:39 +0000
33+++ debian/changelog 2015-05-21 17:30:56 +0000
34@@ -1,3 +1,9 @@
35+unity8 (8.10-0ubuntu1) UNRELEASED; urgency=medium
36+
37+ * Implement full-shell rotation (LP: #1210199)
38+
39+ -- Michał Sawicz <michal.sawicz@canonical.com> Wed, 15 Apr 2015 14:47:17 +0200
40+
41 unity8 (8.02+15.10.20150518.1-0ubuntu1) wily; urgency=medium
42
43 [ Albert Astals Cid ]
44
45=== modified file 'debian/control'
46--- debian/control 2015-04-22 14:43:17 +0000
47+++ debian/control 2015-05-21 17:30:56 +0000
48@@ -12,6 +12,7 @@
49 # append :native to g++-4.9 so we don't try to run armhf g++
50 # on an x86 CPU for eaxmple, when cross-compiling.
51 g++-4.9:native,
52+ libandroid-properties-dev,
53 graphviz,
54 gsettings-ubuntu-schemas (>= 0.0.2+14.10.20140815),
55 libconnectivity-qt1-dev,
56@@ -27,7 +28,7 @@
57 libqmenumodel-dev (>= 0.2.9),
58 libqt5xmlpatterns5-dev,
59 libsystemsettings-dev,
60- libunity-api-dev (>= 7.96),
61+ libunity-api-dev (>= 7.97),
62 libusermetricsoutput1-dev,
63 libxcb1-dev,
64 pkg-config,
65@@ -94,7 +95,7 @@
66 qml-module-qtquick-xmllistmodel,
67 qml-module-qtsysteminfo,
68 qtdeclarative5-gsettings1.0,
69- qtdeclarative5-qtmir-plugin (>= 0.4.4),
70+ qtdeclarative5-qtmir-plugin (>= 0.4.5),
71 qtdeclarative5-ubuntu-telephony0.1,
72 qtdeclarative5-ubuntu-web-plugin,
73 ubuntu-system-settings,
74@@ -124,7 +125,7 @@
75 qtdeclarative5-ubuntu-ui-toolkit-plugin (>= 1.1.1239) | qtdeclarative5-ubuntu-ui-toolkit-plugin-gles (>= 1.1.1239),
76 qtdeclarative5-unity-notifications-plugin (>= 0.1.2) | unity-notifications-impl,
77 ubuntu-thumbnailer-impl-0,
78- unity-application-impl-4,
79+ unity-application-impl-6,
80 unity-notifications-impl-3,
81 unity-plugin-scopes | unity-scopes-impl,
82 unity-scopes-impl-6,
83@@ -168,7 +169,7 @@
84 Depends: ${misc:Depends},
85 ${shlibs:Depends},
86 Provides: unity-application-impl,
87- unity-application-impl-4,
88+ unity-application-impl-6,
89 Replaces: unity8-autopilot (<< 8.02+15.04.20150422-0ubuntu1)
90 Description: Fake environment for running Unity 8 shell
91 Provides fake implementations of some QML modules used by Unity 8 shell
92
93=== modified file 'debian/unity8.install'
94--- debian/unity8.install 2015-04-21 15:22:53 +0000
95+++ debian/unity8.install 2015-05-21 17:30:56 +0000
96@@ -8,6 +8,9 @@
97 usr/share/unity8/Greeter
98 usr/share/unity8/Launcher
99 usr/share/unity8/Panel
100+usr/share/unity8/Rotation
101+usr/share/unity8/DeviceConfiguration.qml
102+usr/share/unity8/OrientedShell.qml
103 usr/share/unity8/Shell.qml
104 usr/share/unity8/Stages
105 usr/share/unity8/Tutorial
106
107=== modified file 'plugins/Greeter/Unity/Launcher/CMakeLists.txt'
108--- plugins/Greeter/Unity/Launcher/CMakeLists.txt 2015-04-22 14:45:11 +0000
109+++ plugins/Greeter/Unity/Launcher/CMakeLists.txt 2015-05-21 17:30:56 +0000
110@@ -1,5 +1,5 @@
111 pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=6)
112-pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5)
113+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=6)
114 pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
115
116 add_definitions(-DSM_BUSNAME=systemBus)
117
118=== modified file 'plugins/Unity/Launcher/CMakeLists.txt'
119--- plugins/Unity/Launcher/CMakeLists.txt 2015-04-13 09:33:28 +0000
120+++ plugins/Unity/Launcher/CMakeLists.txt 2015-05-21 17:30:56 +0000
121@@ -1,5 +1,5 @@
122 pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=6)
123-pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5)
124+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=6)
125 pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
126
127 add_definitions(-DSM_BUSNAME=systemBus)
128
129=== modified file 'plugins/Utils/CMakeLists.txt'
130--- plugins/Utils/CMakeLists.txt 2015-04-22 10:40:54 +0000
131+++ plugins/Utils/CMakeLists.txt 2015-05-21 17:30:56 +0000
132@@ -18,6 +18,7 @@
133 Timer.cpp
134 unitymenumodelpaths.cpp
135 windowkeysfilter.cpp
136+ windowscreenshotprovider.cpp
137 easingcurve.cpp
138 windowstatestorage.cpp
139 plugin.cpp
140
141=== modified file 'plugins/Utils/plugin.cpp'
142--- plugins/Utils/plugin.cpp 2015-04-22 10:40:54 +0000
143+++ plugins/Utils/plugin.cpp 2015-05-21 17:30:56 +0000
144@@ -23,6 +23,7 @@
145 #include "plugin.h"
146
147 // local
148+#include "easingcurve.h"
149 #include "HomeKeyWatcher.h"
150 #include "inputwatcher.h"
151 #include "qlimitproxymodelqml.h"
152@@ -31,7 +32,7 @@
153 #include "timeformatter.h"
154 #include "unitymenumodelpaths.h"
155 #include "windowkeysfilter.h"
156-#include "easingcurve.h"
157+#include "windowscreenshotprovider.h"
158 #include "windowstatestorage.h"
159 #include "constants.h"
160
161@@ -70,4 +71,6 @@
162 void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
163 {
164 QQmlExtensionPlugin::initializeEngine(engine, uri);
165+
166+ engine->addImageProvider(QLatin1String("window"), new WindowScreenshotProvider);
167 }
168
169=== added file 'plugins/Utils/windowscreenshotprovider.cpp'
170--- plugins/Utils/windowscreenshotprovider.cpp 1970-01-01 00:00:00 +0000
171+++ plugins/Utils/windowscreenshotprovider.cpp 2015-05-21 17:30:56 +0000
172@@ -0,0 +1,59 @@
173+/*
174+ * Copyright (C) 2015 Canonical, Ltd.
175+ *
176+ * This program is free software; you can redistribute it and/or modify
177+ * it under the terms of the GNU General Public License as published by
178+ * the Free Software Foundation; version 3.
179+ *
180+ * This program is distributed in the hope that it will be useful,
181+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
182+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
183+ * GNU General Public License for more details.
184+ *
185+ * You should have received a copy of the GNU General Public License
186+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
187+ */
188+
189+#include "windowscreenshotprovider.h"
190+
191+#include <QGuiApplication>
192+#include <QQuickWindow>
193+
194+WindowScreenshotProvider::WindowScreenshotProvider()
195+ : QQuickImageProvider(QQmlImageProviderBase::Image, 0)
196+{
197+}
198+
199+// A very simple implementation where we assume that there's only one window and that it's a
200+// QQuickWindow. Thus the id parameter is irrelevant.
201+//
202+// Idea: Make the id contain the objectName of the QQuickWindow once we care about a multi-display
203+// compositor?
204+// Strictly speaking that could be the actual QWindow::winId(), but that's mostly a
205+// meaningless arbitrary number.
206+QImage WindowScreenshotProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
207+{
208+ Q_UNUSED(id);
209+ Q_UNUSED(requestedSize);
210+
211+ QWindowList windows = QGuiApplication::topLevelWindows();
212+
213+ if (windows.count() != 1) {
214+ size->rwidth() = 0;
215+ size->rheight() = 0;
216+ return QImage();
217+ }
218+
219+ QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(windows[0]);
220+
221+ if (!quickWindow) {
222+ size->rwidth() = 0;
223+ size->rheight() = 0;
224+ return QImage();
225+ }
226+
227+ QImage image = quickWindow->grabWindow();
228+ size->rwidth() = image.width();
229+ size->rheight() = image.height();
230+ return image;
231+}
232
233=== added file 'plugins/Utils/windowscreenshotprovider.h'
234--- plugins/Utils/windowscreenshotprovider.h 1970-01-01 00:00:00 +0000
235+++ plugins/Utils/windowscreenshotprovider.h 2015-05-21 17:30:56 +0000
236@@ -0,0 +1,31 @@
237+/*
238+ * Copyright (C) 2015 Canonical, Ltd.
239+ *
240+ * This program is free software; you can redistribute it and/or modify
241+ * it under the terms of the GNU General Public License as published by
242+ * the Free Software Foundation; version 3.
243+ *
244+ * This program is distributed in the hope that it will be useful,
245+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
246+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
247+ * GNU General Public License for more details.
248+ *
249+ * You should have received a copy of the GNU General Public License
250+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
251+ */
252+
253+#ifndef WINDOW_SCREENSHOT_PROVIDER_H_
254+#define WINDOW_SCREENSHOT_PROVIDER_H_
255+
256+#include <QQuickImageProvider>
257+
258+class WindowScreenshotProvider : public QQuickImageProvider
259+{
260+public:
261+ WindowScreenshotProvider();
262+
263+ // id is ignored for now
264+ QImage requestImage(const QString &id, QSize *size, const QSize &requestedSize) override;
265+};
266+
267+#endif // WINDOW_SCREENSHOT_PROVIDER_H_
268
269=== modified file 'qml/CMakeLists.txt'
270--- qml/CMakeLists.txt 2014-12-16 16:49:49 +0000
271+++ qml/CMakeLists.txt 2015-05-21 17:30:56 +0000
272@@ -13,6 +13,7 @@
273 Notifications
274 Panel
275 Stages
276+ Rotation
277 Tutorial
278 Wizard
279 )
280
281=== added file 'qml/Components/WindowScreenshot.qml'
282--- qml/Components/WindowScreenshot.qml 1970-01-01 00:00:00 +0000
283+++ qml/Components/WindowScreenshot.qml 2015-05-21 17:30:56 +0000
284@@ -0,0 +1,35 @@
285+/*
286+ * Copyright (C) 2015 Canonical, Ltd.
287+ *
288+ * This program is free software; you can redistribute it and/or modify
289+ * it under the terms of the GNU General Public License as published by
290+ * the Free Software Foundation; version 3.
291+ *
292+ * This program is distributed in the hope that it will be useful,
293+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
294+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
295+ * GNU General Public License for more details.
296+ *
297+ * You should have received a copy of the GNU General Public License
298+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
299+ */
300+
301+import QtQuick 2.2
302+
303+Item {
304+ id: root
305+
306+ function take() {
307+ var timeNow = new Date().getTime();
308+ image.source = "image://window/" + timeNow;
309+ }
310+
311+ // Unload the image to free up memory
312+ function discard() {
313+ image.source = "";
314+ }
315+
316+ Image {
317+ id: image
318+ }
319+}
320
321=== modified file 'qml/Dash/DashApplication.qml'
322--- qml/Dash/DashApplication.qml 2014-09-18 21:22:37 +0000
323+++ qml/Dash/DashApplication.qml 2015-05-21 17:30:56 +0000
324@@ -1,5 +1,5 @@
325 /*
326- * Copyright (C) 2014 Canonical, Ltd.
327+ * Copyright (C) 2014,2015 Canonical, Ltd.
328 *
329 * This program is free software; you can redistribute it and/or modify
330 * it under the terms of the GNU General Public License as published by
331@@ -19,8 +19,8 @@
332 import Ubuntu.Thumbnailer 0.1 // Register support for image://thumbnailer/ and image://albumart/
333
334 MainView {
335- width: applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
336- height: applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(68)
337+ implicitWidth: units.gu(40)
338+ implicitHeight: units.gu(68)
339
340 useDeprecatedToolbar: false
341
342
343=== added file 'qml/Dash/graphics/phone/screenshots/gmail-webapp.svg'
344--- qml/Dash/graphics/phone/screenshots/gmail-webapp.svg 1970-01-01 00:00:00 +0000
345+++ qml/Dash/graphics/phone/screenshots/gmail-webapp.svg 2015-05-21 17:30:56 +0000
346@@ -0,0 +1,343 @@
347+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
348+<!-- Created with Inkscape (http://www.inkscape.org/) -->
349+
350+<svg
351+ xmlns:dc="http://purl.org/dc/elements/1.1/"
352+ xmlns:cc="http://creativecommons.org/ns#"
353+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
354+ xmlns:svg="http://www.w3.org/2000/svg"
355+ xmlns="http://www.w3.org/2000/svg"
356+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
357+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
358+ width="768"
359+ height="1280"
360+ id="svg2"
361+ version="1.1"
362+ inkscape:version="0.48.5 r10040"
363+ sodipodi:docname="gmail-webapp.svg">
364+ <defs
365+ id="defs4" />
366+ <sodipodi:namedview
367+ id="base"
368+ pagecolor="#ffffff"
369+ bordercolor="#666666"
370+ borderopacity="1.0"
371+ inkscape:pageopacity="0.0"
372+ inkscape:pageshadow="2"
373+ inkscape:zoom="0.49497475"
374+ inkscape:cx="117.33439"
375+ inkscape:cy="668.80479"
376+ inkscape:document-units="px"
377+ inkscape:current-layer="layer1"
378+ showgrid="false"
379+ inkscape:window-width="1920"
380+ inkscape:window-height="1056"
381+ inkscape:window-x="0"
382+ inkscape:window-y="24"
383+ inkscape:window-maximized="1" />
384+ <metadata
385+ id="metadata7">
386+ <rdf:RDF>
387+ <cc:Work
388+ rdf:about="">
389+ <dc:format>image/svg+xml</dc:format>
390+ <dc:type
391+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
392+ <dc:title></dc:title>
393+ </cc:Work>
394+ </rdf:RDF>
395+ </metadata>
396+ <g
397+ inkscape:label="Layer 1"
398+ inkscape:groupmode="layer"
399+ id="layer1"
400+ transform="translate(0,227.63782)">
401+ <rect
402+ style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
403+ id="rect2985"
404+ width="769.73627"
405+ height="1276.8328"
406+ x="-2.0203052"
407+ y="3.1671834"
408+ transform="translate(0,-227.63782)" />
409+ <rect
410+ style="fill:#e6e6e6;fill-opacity:1;stroke:none;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
411+ id="rect3797"
412+ width="773.77686"
413+ height="129.29953"
414+ x="-6.0609155"
415+ y="-0.87342685"
416+ transform="translate(0,-227.63782)" />
417+ <text
418+ xml:space="preserve"
419+ style="font-size:72px;font-style:normal;font-weight:500;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Medium;font-stretch:normal;font-variant:normal"
420+ x="20.203053"
421+ y="-139.61781"
422+ id="text3755"
423+ sodipodi:linespacing="125%"><tspan
424+ sodipodi:role="line"
425+ id="tspan3757"
426+ x="20.203053"
427+ y="-139.61781">GMail</tspan></text>
428+ <text
429+ xml:space="preserve"
430+ style="font-size:72px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
431+ x="14.142137"
432+ y="-28.501045"
433+ id="text3759"
434+ sodipodi:linespacing="125%"><tspan
435+ sodipodi:role="line"
436+ id="tspan3761"
437+ x="14.142137"
438+ y="-28.501045">Inbox</tspan></text>
439+ <path
440+ sodipodi:type="arc"
441+ style="fill:#8effff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
442+ id="path3765"
443+ sodipodi:cx="107.07617"
444+ sodipodi:cy="337.52768"
445+ sodipodi:rx="64.649765"
446+ sodipodi:ry="61.619305"
447+ d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z"
448+ transform="translate(-28.284271,-251.88148)" />
449+ <path
450+ style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
451+ d="m 14.142136,237.52257 729.330134,0"
452+ id="path3769"
453+ inkscape:connector-curvature="0"
454+ transform="translate(0,-227.63782)" />
455+ <text
456+ xml:space="preserve"
457+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
458+ x="167.68533"
459+ y="78.575127"
460+ id="text3771"
461+ sodipodi:linespacing="125%"><tspan
462+ sodipodi:role="line"
463+ id="tspan3773"
464+ x="167.68533"
465+ y="78.575127">Lorem ipsum</tspan></text>
466+ <text
467+ xml:space="preserve"
468+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
469+ x="167.68532"
470+ y="131.10306"
471+ id="text3775"
472+ sodipodi:linespacing="125%"><tspan
473+ sodipodi:role="line"
474+ id="tspan3777"
475+ x="167.68532"
476+ y="131.10306"
477+ style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text>
478+ <path
479+ style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
480+ d="m 13.13199,165.44825 729.33013,0"
481+ id="path3769-2"
482+ inkscape:connector-curvature="0" />
483+ <path
484+ sodipodi:type="arc"
485+ style="fill:#8eff58;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
486+ id="path3765-3"
487+ sodipodi:cx="107.07617"
488+ sodipodi:cy="337.52768"
489+ sodipodi:rx="64.649765"
490+ sodipodi:ry="61.619305"
491+ d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z"
492+ transform="translate(-26.263969,-93.102383)" />
493+ <text
494+ xml:space="preserve"
495+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
496+ x="169.70564"
497+ y="237.35422"
498+ id="text3771-9"
499+ sodipodi:linespacing="125%"><tspan
500+ sodipodi:role="line"
501+ id="tspan3773-7"
502+ x="169.70564"
503+ y="237.35422">Lorem ipsum</tspan></text>
504+ <text
505+ xml:space="preserve"
506+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
507+ x="169.70561"
508+ y="289.88217"
509+ id="text3775-1"
510+ sodipodi:linespacing="125%"><tspan
511+ sodipodi:role="line"
512+ id="tspan3777-1"
513+ x="169.70561"
514+ y="289.88217"
515+ style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text>
516+ <path
517+ style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
518+ d="m 15.152292,324.22735 729.330128,0"
519+ id="path3769-2-6"
520+ inkscape:connector-curvature="0" />
521+ <path
522+ sodipodi:type="arc"
523+ style="fill:#8effff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
524+ id="path3765-7"
525+ sodipodi:cx="107.07617"
526+ sodipodi:cy="337.52768"
527+ sodipodi:rx="64.649765"
528+ sodipodi:ry="61.619305"
529+ d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z"
530+ transform="translate(-28.284274,64.481414)" />
531+ <text
532+ xml:space="preserve"
533+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
534+ x="167.68533"
535+ y="394.93799"
536+ id="text3771-92"
537+ sodipodi:linespacing="125%"><tspan
538+ sodipodi:role="line"
539+ id="tspan3773-0"
540+ x="167.68533"
541+ y="394.93799">Lorem ipsum</tspan></text>
542+ <text
543+ xml:space="preserve"
544+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
545+ x="167.68532"
546+ y="447.46594"
547+ id="text3775-9"
548+ sodipodi:linespacing="125%"><tspan
549+ sodipodi:role="line"
550+ id="tspan3777-8"
551+ x="167.68532"
552+ y="447.46594"
553+ style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text>
554+ <path
555+ style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
556+ d="m 13.131986,481.81114 729.330124,0"
557+ id="path3769-2-3"
558+ inkscape:connector-curvature="0" />
559+ <path
560+ sodipodi:type="arc"
561+ style="fill:#8ea2ff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
562+ id="path3765-2"
563+ sodipodi:cx="107.07617"
564+ sodipodi:cy="337.52768"
565+ sodipodi:rx="64.649765"
566+ sodipodi:ry="61.619305"
567+ d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z"
568+ transform="translate(-26.263969,226.10582)" />
569+ <text
570+ xml:space="preserve"
571+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
572+ x="169.70564"
573+ y="556.56238"
574+ id="text3771-1"
575+ sodipodi:linespacing="125%"><tspan
576+ sodipodi:role="line"
577+ id="tspan3773-1"
578+ x="169.70564"
579+ y="556.56238">Lorem ipsum</tspan></text>
580+ <text
581+ xml:space="preserve"
582+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
583+ x="169.70563"
584+ y="609.09033"
585+ id="text3775-8"
586+ sodipodi:linespacing="125%"><tspan
587+ sodipodi:role="line"
588+ id="tspan3777-85"
589+ x="169.70563"
590+ y="609.09033"
591+ style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text>
592+ <path
593+ style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
594+ d="m 15.152292,643.43555 729.330128,0"
595+ id="path3769-2-1"
596+ inkscape:connector-curvature="0" />
597+ <path
598+ sodipodi:type="arc"
599+ style="fill:#8effff;fill-opacity:1;stroke:#000000;stroke-width:0.69999999;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
600+ id="path3765-8"
601+ sodipodi:cx="107.07617"
602+ sodipodi:cy="337.52768"
603+ sodipodi:rx="64.649765"
604+ sodipodi:ry="61.619305"
605+ d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z"
606+ transform="translate(-24.243664,391.77084)" />
607+ <text
608+ xml:space="preserve"
609+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
610+ x="171.72594"
611+ y="722.22742"
612+ id="text3771-7"
613+ sodipodi:linespacing="125%"><tspan
614+ sodipodi:role="line"
615+ id="tspan3773-6"
616+ x="171.72594"
617+ y="722.22742">Lorem ipsum</tspan></text>
618+ <text
619+ xml:space="preserve"
620+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
621+ x="171.72592"
622+ y="774.75537"
623+ id="text3775-5"
624+ sodipodi:linespacing="125%"><tspan
625+ sodipodi:role="line"
626+ id="tspan3777-2"
627+ x="171.72592"
628+ y="774.75537"
629+ style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text>
630+ <path
631+ style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
632+ d="m 17.172597,809.10057 729.330133,0"
633+ id="path3769-2-13"
634+ inkscape:connector-curvature="0" />
635+ <path
636+ sodipodi:type="arc"
637+ style="fill:#e44738;fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
638+ id="path3765-9"
639+ sodipodi:cx="107.07617"
640+ sodipodi:cy="337.52768"
641+ sodipodi:rx="64.649765"
642+ sodipodi:ry="61.619305"
643+ d="m 171.72594,337.52768 a 64.649765,61.619305 0 1 1 -129.299533,0 64.649765,61.619305 0 1 1 129.299533,0 z"
644+ transform="translate(-24.243664,557.43585)" />
645+ <text
646+ xml:space="preserve"
647+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
648+ x="171.72594"
649+ y="887.89246"
650+ id="text3771-2"
651+ sodipodi:linespacing="125%"><tspan
652+ sodipodi:role="line"
653+ id="tspan3773-8"
654+ x="171.72594"
655+ y="887.89246">Lorem ipsum</tspan></text>
656+ <text
657+ xml:space="preserve"
658+ style="font-size:64px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Ubuntu;-inkscape-font-specification:Ubuntu"
659+ x="171.72592"
660+ y="940.42041"
661+ id="text3775-3"
662+ sodipodi:linespacing="125%"><tspan
663+ sodipodi:role="line"
664+ id="tspan3777-7"
665+ x="171.72592"
666+ y="940.42041"
667+ style="font-size:48px;fill:#b3b3b3">bla bla bla bla bla bla bla ...</tspan></text>
668+ <path
669+ style="fill:none;stroke:#000000;stroke-width:4;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
670+ d="m 17.172597,974.76558 729.330123,0"
671+ id="path3769-2-9"
672+ inkscape:connector-curvature="0" />
673+ <path
674+ sodipodi:type="arc"
675+ style="fill:none;stroke:#000000;stroke-width:8;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
676+ id="path3929"
677+ sodipodi:cx="590.93921"
678+ sodipodi:cy="-119.06127"
679+ sodipodi:rx="33.335033"
680+ sodipodi:ry="33.335033"
681+ d="m 624.27424,-119.06127 a 33.335033,33.335033 0 1 1 -66.67006,0 33.335033,33.335033 0 1 1 66.67006,0 z"
682+ transform="matrix(0.85096826,0,0,0.85096826,175.43863,-68.81729)" />
683+ <path
684+ style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:3.40387297;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
685+ d="m 692.92249,-145.20602 20.63059,24.06901 12.03451,-13.75372 -20.63059,-17.19215"
686+ id="path3931"
687+ inkscape:connector-curvature="0" />
688+ </g>
689+</svg>
690
691=== removed file 'qml/Dash/graphics/phone/screenshots/settings@12.png'
692Binary files qml/Dash/graphics/phone/screenshots/settings@12.png 2013-06-20 13:42:39 +0000 and qml/Dash/graphics/phone/screenshots/settings@12.png 1970-01-01 00:00:00 +0000 differ
693=== added file 'qml/Dash/graphics/phone/screenshots/ubuntu-weather-app.svg'
694--- qml/Dash/graphics/phone/screenshots/ubuntu-weather-app.svg 1970-01-01 00:00:00 +0000
695+++ qml/Dash/graphics/phone/screenshots/ubuntu-weather-app.svg 2015-05-21 17:30:56 +0000
696@@ -0,0 +1,201 @@
697+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
698+<!-- Created with Inkscape (http://www.inkscape.org/) -->
699+
700+<svg
701+ xmlns:dc="http://purl.org/dc/elements/1.1/"
702+ xmlns:cc="http://creativecommons.org/ns#"
703+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
704+ xmlns:svg="http://www.w3.org/2000/svg"
705+ xmlns="http://www.w3.org/2000/svg"
706+ xmlns:xlink="http://www.w3.org/1999/xlink"
707+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
708+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
709+ width="829"
710+ height="480"
711+ id="svg2740"
712+ sodipodi:version="0.32"
713+ inkscape:version="0.48.5 r10040"
714+ version="1.0"
715+ sodipodi:docname="ubuntu-weather-app.svg"
716+ inkscape:output_extension="org.inkscape.output.svg.inkscape">
717+ <defs
718+ id="defs2742">
719+ <linearGradient
720+ id="linearGradient3824">
721+ <stop
722+ style="stop-color:#e6e6e6;stop-opacity:1;"
723+ offset="0"
724+ id="stop3826" />
725+ <stop
726+ style="stop-color:#23abff;stop-opacity:1;"
727+ offset="1"
728+ id="stop3828" />
729+ </linearGradient>
730+ <linearGradient
731+ inkscape:collect="always"
732+ xlink:href="#linearGradient3824"
733+ id="linearGradient3830"
734+ x1="348.55862"
735+ y1="343.23914"
736+ x2="348.55862"
737+ y2="-17.422215"
738+ gradientUnits="userSpaceOnUse" />
739+ </defs>
740+ <sodipodi:namedview
741+ id="base"
742+ pagecolor="#ffffff"
743+ bordercolor="#666666"
744+ borderopacity="1.0"
745+ gridtolerance="10000"
746+ guidetolerance="10"
747+ objecttolerance="10"
748+ inkscape:pageopacity="0.0"
749+ inkscape:pageshadow="2"
750+ inkscape:zoom="0.82625984"
751+ inkscape:cx="331.28234"
752+ inkscape:cy="125.54212"
753+ inkscape:document-units="px"
754+ inkscape:current-layer="layer1"
755+ showgrid="false"
756+ inkscape:window-width="1145"
757+ inkscape:window-height="847"
758+ inkscape:window-x="268"
759+ inkscape:window-y="63"
760+ inkscape:window-maximized="0" />
761+ <metadata
762+ id="metadata2745">
763+ <rdf:RDF>
764+ <cc:Work
765+ rdf:about="">
766+ <dc:format>image/svg+xml</dc:format>
767+ <dc:type
768+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
769+ </cc:Work>
770+ </rdf:RDF>
771+ </metadata>
772+ <g
773+ inkscape:label="Layer 1"
774+ inkscape:groupmode="layer"
775+ id="layer1"
776+ transform="translate(-321.13452,-104.68346)">
777+ <rect
778+ style="fill:url(#linearGradient3830);fill-opacity:1;stroke:#000000;stroke-width:0.69999999000000002;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
779+ id="rect2990"
780+ width="832.66785"
781+ height="480.47839"
782+ x="-1.210273"
783+ y="0.73188055"
784+ transform="translate(321.13452,104.68346)" />
785+ <path
786+ d="m 310.66382,132.06057 c -1.82703,2.0443 -22.21039,-18.38308 -24.89334,-17.37811 -2.68295,1.00497 -6.73783,33.64192 -9.57527,34.01165 -2.83744,0.36973 -7.71546,-33.08881 -10.48084,-33.88783 -2.76539,-0.79903 -18.7793,19.34152 -21.17964,17.82892 -2.40034,-1.51259 5.69972,-26.09808 4.36486,-28.67057 -1.33487,-2.57249 -31.86305,-3.78032 -32.49182,-6.6501 -0.62876,-2.86978 27.66855,-10.399376 27.90248,-13.241764 0.23394,-2.842387 -18.99828,-18.90215 -17.89698,-21.393798 1.10131,-2.491647 26.85456,8.177399 28.59429,5.99159 1.73972,-2.185809 -3.39182,-29.683489 -0.75169,-30.507098 2.64013,-0.823608 18.50306,18.485327 21.32153,18.392972 2.81847,-0.09235 11.30312,-24.287685 14.18258,-23.722317 2.87947,0.565368 1.44329,25.667631 3.67226,27.34365 2.22897,1.676019 24.27161,-6.28288 25.90675,-4.004945 1.63514,2.277936 -12.63923,24.445025 -11.77955,27.07291 0.85968,2.627885 27.01183,5.1355 26.65457,7.852474 -0.35726,2.716973 -32.69913,3.875594 -34.04684,6.507203 -1.3477,2.631613 12.32368,32.410863 10.49665,34.455163 z"
787+ id="path11949"
788+ inkscape:flatsided="false"
789+ inkscape:randomized="-0.092"
790+ inkscape:rounded="0.1"
791+ sodipodi:arg1="0.79570711"
792+ sodipodi:arg2="1.144773"
793+ sodipodi:cx="275.15002"
794+ sodipodi:cy="88.090233"
795+ sodipodi:r1="57.019234"
796+ sodipodi:r2="32.818508"
797+ sodipodi:sides="9"
798+ sodipodi:type="star"
799+ style="fill:#f5ff12;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.2;marker:none;visibility:visible;display:inline;overflow:visible"
800+ transform="matrix(2.527571,0,0,2.527571,85.214779,60.619097)" />
801+ <path
802+ d="m 194.51692,77.283737 c 0,20.659371 -17.86424,37.407103 -39.90091,37.407103 -22.03666,0 -39.90091,-16.747732 -39.90091,-37.407103 0,-20.659371 17.86425,-37.4071 39.90091,-37.4071 22.03667,0 39.90091,16.747729 39.90091,37.4071 z"
803+ id="path11951"
804+ sodipodi:cx="154.61601"
805+ sodipodi:cy="77.283737"
806+ sodipodi:rx="39.900909"
807+ sodipodi:ry="37.407101"
808+ sodipodi:type="arc"
809+ style="fill:#f5ff12;fill-opacity:1;fill-rule:nonzero;stroke:#f5ff12;stroke-width:10.27388287;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:0.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
810+ transform="matrix(2.4568175,0,0,2.1990879,404.91256,120.05076)" />
811+ <path
812+ transform="matrix(3.2663208,0,0,3.4016021,515.92101,-254.59331)"
813+ style="fill:#6798e9;fill-opacity:1;fill-rule:nonzero;stroke:#6798e9;stroke-width:7.30059433;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:0.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
814+ sodipodi:type="inkscape:offset"
815+ inkscape:radius="0"
816+ inkscape:original="M 110.53125 144.96875 C 100.76599 144.96875 92.384060 150.03292 88.281250 157.34375 C 86.642607 156.42892 84.835190 155.87500 82.906250 155.87500 C 77.073071 155.87500 72.219030 160.56753 70.718750 166.93750 C 68.157973 165.92533 65.180470 165.31250 62.000000 165.31250 C 52.458571 165.31250 44.718750 170.53296 44.718750 176.96875 C 44.718749 182.77816 51.066430 187.55402 59.312500 188.43750 C 58.942922 189.06456 58.656250 189.68551 58.656250 190.34375 C 58.656248 196.50568 75.538140 201.53125 96.343750 201.53125 C 117.14936 201.53125 134.03126 196.50568 134.03125 190.34375 C 134.03125 189.92916 133.77393 189.55916 133.62500 189.15625 C 134.53629 189.38287 135.43860 189.62500 136.43750 189.62500 C 142.00333 189.62501 146.53125 185.84318 146.53125 181.18750 C 146.53125 176.53182 142.00332 172.75000 136.43750 172.75000 C 135.75542 172.75000 135.17544 172.98560 134.53125 173.09375 C 135.09454 171.23218 135.46875 169.33268 135.46875 167.31250 C 135.46875 154.98864 124.31330 144.96875 110.53125 144.96875 z "
817+ id="path11953"
818+ d="m 110.53125,144.96875 c -9.76526,0 -18.14719,5.06417 -22.25,12.375 -1.638643,-0.91483 -3.44606,-1.46875 -5.375,-1.46875 -5.833179,0 -10.68722,4.69253 -12.1875,11.0625 -2.560777,-1.01217 -5.53828,-1.625 -8.71875,-1.625 -9.541429,0 -17.28125,5.22046 -17.28125,11.65625 -10e-7,5.80941 6.34768,10.58527 14.59375,11.46875 -0.369578,0.62706 -0.65625,1.24801 -0.65625,1.90625 -2e-6,6.16193 16.88189,11.1875 37.6875,11.1875 20.80561,0 37.68751,-5.02557 37.6875,-11.1875 0,-0.41459 -0.25732,-0.78459 -0.40625,-1.1875 0.91129,0.22662 1.8136,0.46875 2.8125,0.46875 5.56583,1e-5 10.09375,-3.78182 10.09375,-8.4375 0,-4.65568 -4.52793,-8.4375 -10.09375,-8.4375 -0.68208,0 -1.26206,0.2356 -1.90625,0.34375 0.56329,-1.86157 0.9375,-3.76107 0.9375,-5.78125 0,-12.32386 -11.15545,-22.34375 -24.9375,-22.34375 z" />
819+ <path
820+ inkscape:connector-curvature="0"
821+ style="fill:#386195;fill-opacity:1;fill-rule:nonzero;stroke:#386195;stroke-width:24.07697487;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:0.5;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
822+ id="path11963"
823+ d="m 975.70833,305.75079 c -17.87875,0 -33.1897,9.10731 -40.70137,22.18913 -3.00012,-1.63696 -6.34124,-2.6392 -9.87286,-2.6392 -10.67967,0 -19.5639,8.39604 -22.31073,19.7943 -4.6884,-1.81117 -10.09942,-2.93251 -15.92242,-2.93251 -17.46892,0 -31.65122,9.35352 -31.65122,20.86955 0,10.39528 11.61748,18.9466 26.71485,20.52749 -0.67665,1.12204 -1.20995,2.24338 -1.20995,3.42121 0,11.02604 30.92124,19.98985 69.01327,19.98985 38.09195,0 69.0132,-8.96381 69.0132,-19.98985 0,-0.74183 -0.5017,-1.42952 -0.7743,-2.15046 1.6684,0.40556 3.3496,0.83088 5.1784,0.83088 10.1902,0 18.439,-6.7716 18.439,-15.10234 0,-8.33078 -8.2488,-15.05348 -18.439,-15.05348 -1.2488,0 -2.3535,0.39297 -3.5329,0.58647 1.0312,-3.33102 1.7422,-6.7466 1.7422,-10.36143 0,-22.05212 -20.4533,-39.97961 -45.68617,-39.97961 z" />
824+ <path
825+ inkscape:connector-curvature="0"
826+ style="fill:#6798e9;fill-opacity:1;fill-rule:nonzero;stroke:#6798e9;stroke-width:15.64964962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.20000005;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
827+ sodipodi:nodetypes="cccc"
828+ id="path11965"
829+ d="m 717.80594,482.73655 c -32.27924,28.4432 5.62151,52.69793 20.03284,13.63938 l 11.08203,-36.22961 -31.11487,22.59023 z" />
830+ <path
831+ inkscape:connector-curvature="0"
832+ style="fill:#6798e9;fill-opacity:1;fill-rule:nonzero;stroke:#6798e9;stroke-width:15.64964962;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:3.20000005;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible"
833+ sodipodi:nodetypes="cccc"
834+ id="path11967"
835+ d="m 799.47,485.76116 c -32.27925,28.4432 5.62151,52.69792 20.03284,13.63937 l 11.08202,-36.2296 -31.11486,22.59023 z" />
836+ <text
837+ xml:space="preserve"
838+ style="font-size:32px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
839+ x="68.985565"
840+ y="92.712631"
841+ id="text2992"
842+ sodipodi:linespacing="125%"
843+ transform="translate(321.13452,104.68346)"><tspan
844+ sodipodi:role="line"
845+ id="tspan2994"
846+ x="68.985565"
847+ y="92.712631" /></text>
848+ <text
849+ xml:space="preserve"
850+ style="font-size:10px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
851+ x="-202.1156"
852+ y="155.64684"
853+ id="text2996"
854+ sodipodi:linespacing="125%"
855+ transform="translate(321.13452,104.68346)"><tspan
856+ sodipodi:role="line"
857+ id="tspan2998"
858+ x="-202.1156"
859+ y="155.64684" /></text>
860+ <text
861+ xml:space="preserve"
862+ style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
863+ x="342.91943"
864+ y="155.03653"
865+ id="text3000"
866+ sodipodi:linespacing="125%"><tspan
867+ sodipodi:role="line"
868+ id="tspan3002"
869+ x="342.91943"
870+ y="155.03653"
871+ style="font-size:32px;font-style:normal;font-variant:normal;font-weight:500;font-stretch:normal;font-family:Ubuntu;-inkscape-font-specification:Ubuntu Medium">Wheather App</tspan></text>
872+ <text
873+ xml:space="preserve"
874+ style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
875+ x="460.31592"
876+ y="358.3624"
877+ id="text3004"
878+ sodipodi:linespacing="125%"><tspan
879+ sodipodi:role="line"
880+ id="tspan3006"
881+ x="460.31592"
882+ y="358.3624"
883+ style="font-size:48px;fill:#ff0000;-inkscape-font-specification:Ubuntu;font-family:Ubuntu;font-weight:normal;font-style:normal;font-stretch:normal;font-variant:normal">22C</tspan></text>
884+ <text
885+ xml:space="preserve"
886+ style="font-size:24px;font-style:normal;font-weight:bold;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#0000ff;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans Bold"
887+ x="460.19751"
888+ y="412.14325"
889+ id="text3004-0"
890+ sodipodi:linespacing="125%"><tspan
891+ sodipodi:role="line"
892+ id="tspan3006-4"
893+ x="460.19751"
894+ y="412.14325"
895+ style="font-size:48px;fill:#0000ff;-inkscape-font-specification:Ubuntu Medium;font-family:Ubuntu;font-weight:500;font-style:normal;font-stretch:normal;font-variant:normal">14C</tspan></text>
896+ </g>
897+</svg>
898
899=== added file 'qml/DeviceConfiguration.qml'
900--- qml/DeviceConfiguration.qml 1970-01-01 00:00:00 +0000
901+++ qml/DeviceConfiguration.qml 2015-05-21 17:30:56 +0000
902@@ -0,0 +1,81 @@
903+/*
904+ * Copyright (C) 2015 Canonical, Ltd.
905+ *
906+ * This program is free software; you can redistribute it and/or modify
907+ * it under the terms of the GNU General Public License as published by
908+ * the Free Software Foundation; version 3.
909+ *
910+ * This program is distributed in the hope that it will be useful,
911+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
912+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
913+ * GNU General Public License for more details.
914+ *
915+ * You should have received a copy of the GNU General Public License
916+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
917+ */
918+
919+import QtQuick 2.0
920+
921+StateGroup {
922+ id: root
923+
924+ readonly property int useNativeOrientation: -1
925+
926+ property int primaryOrientation: useNativeOrientation
927+
928+ property int supportedOrientations: Qt.PortraitOrientation
929+ | Qt.InvertedPortraitOrientation
930+ | Qt.LandscapeOrientation
931+ | Qt.InvertedLandscapeOrientation
932+
933+ // Supported values so far:
934+ // "phone", "tablet" or "desktop"
935+ property string category: "phone"
936+
937+
938+ property alias name: root.state
939+
940+ states: [
941+ State {
942+ name: "mako"
943+ PropertyChanges {
944+ target: root
945+ supportedOrientations: Qt.PortraitOrientation
946+ | Qt.LandscapeOrientation
947+ | Qt.InvertedLandscapeOrientation
948+ }
949+ },
950+ State {
951+ name: "krillin"
952+ PropertyChanges {
953+ target: root
954+ supportedOrientations: Qt.PortraitOrientation
955+ | Qt.LandscapeOrientation
956+ | Qt.InvertedLandscapeOrientation
957+ }
958+ },
959+ State {
960+ name: "manta"
961+ PropertyChanges {
962+ target: root
963+ category: "tablet"
964+ }
965+ },
966+ State {
967+ name: "flo"
968+ PropertyChanges {
969+ target: root
970+ primaryOrientation: Qt.InvertedLandscapeOrientation
971+ category: "tablet"
972+ }
973+ },
974+ State {
975+ name: "desktop"
976+ PropertyChanges {
977+ target: root
978+ category: "desktop"
979+ }
980+ }
981+ ]
982+
983+}
984
985=== modified file 'qml/Greeter/Greeter.qml'
986--- qml/Greeter/Greeter.qml 2015-04-27 13:52:24 +0000
987+++ qml/Greeter/Greeter.qml 2015-05-21 17:30:56 +0000
988@@ -52,6 +52,8 @@
989 property int failedLoginsDelayAttempts: 7 // number of failed logins
990 property real failedLoginsDelayMinutes: 5 // minutes of forced waiting
991
992+ readonly property bool animating: loader.item ? loader.item.animating : false
993+
994 signal tease()
995 signal sessionStarted()
996 signal emergencyCall()
997
998=== modified file 'qml/Greeter/NarrowView.qml'
999--- qml/Greeter/NarrowView.qml 2015-02-23 15:43:41 +0000
1000+++ qml/Greeter/NarrowView.qml 2015-05-21 17:30:56 +0000
1001@@ -33,6 +33,7 @@
1002 property alias infographicModel: coverPage.infographicModel
1003 readonly property bool fullyShown: coverPage.showProgress === 1 || lockscreen.shown
1004 readonly property bool required: coverPage.required || lockscreen.required
1005+ readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running
1006
1007 signal selected(int index) // unused
1008 signal responded(string response)
1009
1010=== modified file 'qml/Greeter/WideView.qml'
1011--- qml/Greeter/WideView.qml 2015-02-23 15:43:41 +0000
1012+++ qml/Greeter/WideView.qml 2015-05-21 17:30:56 +0000
1013@@ -32,6 +32,7 @@
1014 property alias infographicModel: coverPage.infographicModel
1015 readonly property bool fullyShown: coverPage.showProgress === 1
1016 readonly property bool required: coverPage.required
1017+ readonly property bool animating: coverPage.showAnimation.running || coverPage.hideAnimation.running
1018
1019 // so that it can be replaced in tests with a mock object
1020 property var inputMethod: Qt.inputMethod
1021
1022=== added file 'qml/OrientedShell.qml'
1023--- qml/OrientedShell.qml 1970-01-01 00:00:00 +0000
1024+++ qml/OrientedShell.qml 2015-05-21 17:30:56 +0000
1025@@ -0,0 +1,185 @@
1026+/*
1027+ * Copyright (C) 2015 Canonical, Ltd.
1028+ *
1029+ * This program is free software; you can redistribute it and/or modify
1030+ * it under the terms of the GNU General Public License as published by
1031+ * the Free Software Foundation; version 3.
1032+ *
1033+ * This program is distributed in the hope that it will be useful,
1034+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1035+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1036+ * GNU General Public License for more details.
1037+ *
1038+ * You should have received a copy of the GNU General Public License
1039+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1040+ */
1041+
1042+import QtQuick 2.0
1043+import QtQuick.Window 2.0
1044+import Unity.Session 0.1
1045+import GSettings 1.0
1046+import "Components"
1047+import "Rotation"
1048+
1049+Rectangle {
1050+ id: root
1051+ color: "black"
1052+
1053+ implicitWidth: units.gu(40)
1054+ implicitHeight: units.gu(71)
1055+
1056+ // NB: native and primary orientations here don't map exactly to their QScreen counterparts
1057+ readonly property int nativeOrientation: width > height ? Qt.LandscapeOrientation : Qt.PortraitOrientation
1058+
1059+ readonly property int primaryOrientation:
1060+ deviceConfiguration.primaryOrientation == deviceConfiguration.useNativeOrientation
1061+ ? nativeOrientation : deviceConfiguration.primaryOrientation
1062+
1063+ DeviceConfiguration {
1064+ id: deviceConfiguration
1065+ name: applicationArguments.deviceName
1066+ }
1067+
1068+ // to be overwritten by tests
1069+ property var usageModeSettings: GSettings { schema.id: "com.canonical.Unity8" }
1070+ property int physicalOrientation: Screen.orientation
1071+ property bool orientationLocked: OrientationLock.enabled
1072+ property var orientationLock: OrientationLock
1073+
1074+ property int orientation
1075+ onPhysicalOrientationChanged: {
1076+ if (!orientationLocked) {
1077+ orientation = physicalOrientation;
1078+ }
1079+ }
1080+ onOrientationLockedChanged: {
1081+ if (orientationLocked) {
1082+ orientationLock.savedOrientation = physicalOrientation;
1083+ } else {
1084+ orientation = physicalOrientation;
1085+ }
1086+ }
1087+ Component.onCompleted: {
1088+ if (orientationLocked) {
1089+ orientation = orientationLock.savedOrientation;
1090+ }
1091+ }
1092+
1093+ readonly property int supportedOrientations: shell.supportedOrientations
1094+ & deviceConfiguration.supportedOrientations
1095+ property int acceptedOrientationAngle: {
1096+ if (orientation & supportedOrientations) {
1097+ return Screen.angleBetween(nativeOrientation, orientation);
1098+ } else if (shell.orientation & supportedOrientations) {
1099+ // stay where we are
1100+ return shell.orientationAngle;
1101+ } else if (angleToOrientation(shell.mainAppWindowOrientationAngle) & supportedOrientations) {
1102+ return shell.mainAppWindowOrientationAngle;
1103+ } else {
1104+ // rotate to some supported orientation as we can't stay where we currently are
1105+ // TODO: Choose the closest to the current one
1106+ if (supportedOrientations & Qt.PortraitOrientation) {
1107+ return Screen.angleBetween(nativeOrientation, Qt.PortraitOrientation);
1108+ } else if (supportedOrientations & Qt.LandcscapeOrientation) {
1109+ return Screen.angleBetween(nativeOrientation, Qt.LandscapeOrientation);
1110+ } else if (supportedOrientations & Qt.InvertedPortraitOrientation) {
1111+ return Screen.angleBetween(nativeOrientation, Qt.InvertedPortraitOrientation);
1112+ } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) {
1113+ return Screen.angleBetween(nativeOrientation, Qt.InvertedLandscapeOrientation);
1114+ } else {
1115+ // if all fails, fallback to primary orientation
1116+ return Screen.angleBetween(nativeOrientation, primaryOrientation);
1117+ }
1118+ }
1119+ }
1120+
1121+ function angleToOrientation(angle) {
1122+ switch (angle) {
1123+ case 0:
1124+ return nativeOrientation;
1125+ break;
1126+ case 90:
1127+ return nativeOrientation === Qt.PortraitOrientation ? Qt.InvertedLandscapeOrientation
1128+ : Qt.PortraitOrientation;
1129+ break;
1130+ case 180:
1131+ return nativeOrientation === Qt.PortraitOrientation ? Qt.InvertedPortraitOrientation
1132+ : Qt.InvertedLandscapeOrientation;
1133+ break;
1134+ case 270:
1135+ return nativeOrientation === Qt.PortraitOrientation ? Qt.LandscapeOrientation
1136+ : Qt.InvertedPortraitOrientation;
1137+ break;
1138+ default:
1139+ console.warn("angleToOrientation: Invalid orientation angle: " + angle);
1140+ return primaryOrientation;
1141+ }
1142+ }
1143+
1144+ RotationStates {
1145+ id: rotationStates
1146+ objectName: "rotationStates"
1147+ orientedShell: root
1148+ shell: shell
1149+ shellCover: shellCover
1150+ windowScreenshot: windowScreenshot
1151+ }
1152+
1153+ Shell {
1154+ id: shell
1155+ objectName: "shell"
1156+ width: root.width
1157+ height: root.height
1158+ orientation: root.angleToOrientation(orientationAngle)
1159+ primaryOrientation: root.primaryOrientation
1160+ nativeOrientation: root.nativeOrientation
1161+ nativeWidth: root.width
1162+ nativeHeight: root.height
1163+
1164+ // TODO: Factor in the connected input devices (eg: physical keyboard, mouse, touchscreen),
1165+ // what's the output device (eg: big TV, desktop monitor, phone display), etc.
1166+ usageScenario: {
1167+ if (root.usageModeSettings.usageMode === "Windowed") {
1168+ return "desktop";
1169+ } else if (root.usageModeSettings.usageMode === "Staged"
1170+ && deviceConfiguration.category === "desktop") {
1171+ return "tablet";
1172+ } else {
1173+ return deviceConfiguration.category;
1174+ }
1175+ }
1176+
1177+ property real transformRotationAngle
1178+ property real transformOriginX
1179+ property real transformOriginY
1180+
1181+ transform: Rotation {
1182+ origin.x: shell.transformOriginX; origin.y: shell.transformOriginY; axis { x: 0; y: 0; z: 1 }
1183+ angle: shell.transformRotationAngle
1184+ }
1185+ }
1186+
1187+ Rectangle {
1188+ id: shellCover
1189+ color: "black"
1190+ anchors.fill: parent
1191+ visible: false
1192+ }
1193+
1194+ WindowScreenshot {
1195+ id: windowScreenshot
1196+ visible: false
1197+ width: root.width
1198+ height: root.height
1199+
1200+ property real transformRotationAngle
1201+ property real transformOriginX
1202+ property real transformOriginY
1203+
1204+ transform: Rotation {
1205+ origin.x: windowScreenshot.transformOriginX; origin.y: windowScreenshot.transformOriginY;
1206+ axis { x: 0; y: 0; z: 1 }
1207+ angle: windowScreenshot.transformRotationAngle
1208+ }
1209+ }
1210+}
1211
1212=== modified file 'qml/Panel/Panel.qml'
1213--- qml/Panel/Panel.qml 2015-04-02 15:08:05 +0000
1214+++ qml/Panel/Panel.qml 2015-05-21 17:30:56 +0000
1215@@ -27,6 +27,9 @@
1216 property alias indicators: __indicators
1217 property alias callHint: __callHint
1218 property bool fullscreenMode: false
1219+ property real indicatorAreaShowProgress: 1.0
1220+
1221+ opacity: fullscreenMode && indicators.fullyClosed ? 0.0 : 1.0
1222
1223 Rectangle {
1224 id: darkenedArea
1225@@ -58,6 +61,12 @@
1226 NumberAnimation { duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing }
1227 }
1228
1229+ transform: Translate {
1230+ y: indicators.state === "initial"
1231+ ? (1.0 - indicatorAreaShowProgress) * -d.indicatorHeight
1232+ : 0
1233+ }
1234+
1235 BorderImage {
1236 id: dropShadow
1237 anchors {
1238
1239=== added directory 'qml/Rotation'
1240=== added file 'qml/Rotation/HalfLoopRotationAnimation.qml'
1241--- qml/Rotation/HalfLoopRotationAnimation.qml 1970-01-01 00:00:00 +0000
1242+++ qml/Rotation/HalfLoopRotationAnimation.qml 2015-05-21 17:30:56 +0000
1243@@ -0,0 +1,46 @@
1244+/*
1245+ * Copyright (C) 2015 Canonical, Ltd.
1246+ *
1247+ * This program is free software; you can redistribute it and/or modify
1248+ * it under the terms of the GNU General Public License as published by
1249+ * the Free Software Foundation; version 3.
1250+ *
1251+ * This program is distributed in the hope that it will be useful,
1252+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1253+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1254+ * GNU General Public License for more details.
1255+ *
1256+ * You should have received a copy of the GNU General Public License
1257+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1258+ */
1259+
1260+import QtQuick 2.3
1261+
1262+SequentialAnimation {
1263+ id: root
1264+
1265+ // set from outside
1266+ property int fromAngle
1267+ property int toAngle
1268+ property var info
1269+ property var shell
1270+
1271+ readonly property bool flipShellDimensions: toAngle == 90 || toAngle == 270
1272+
1273+ ScriptAction { script: {
1274+ info.transitioning = true;
1275+ shell.orientationAngle = root.toAngle;
1276+ shell.x = (orientedShell.width - shell.width) / 2
1277+ shell.y = (orientedShell.height - shell.height) / 2;
1278+ shell.transformOriginX = shell.width / 2;
1279+ shell.transformOriginY = shell.height / 2;
1280+ shell.updateFocusedAppOrientation();
1281+ } }
1282+ NumberAnimation {
1283+ target: shell
1284+ property: "transformRotationAngle"
1285+ from: root.fromAngle; to: root.toAngle
1286+ duration: rotationDuration; easing.type: rotationEasing
1287+ }
1288+ ScriptAction { script: { info.transitioning = false; } }
1289+}
1290
1291=== added file 'qml/Rotation/ImmediateRotationAction.qml'
1292--- qml/Rotation/ImmediateRotationAction.qml 1970-01-01 00:00:00 +0000
1293+++ qml/Rotation/ImmediateRotationAction.qml 2015-05-21 17:30:56 +0000
1294@@ -0,0 +1,45 @@
1295+/*
1296+ * Copyright (C) 2015 Canonical, Ltd.
1297+ *
1298+ * This program is free software; you can redistribute it and/or modify
1299+ * it under the terms of the GNU General Public License as published by
1300+ * the Free Software Foundation; version 3.
1301+ *
1302+ * This program is distributed in the hope that it will be useful,
1303+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1304+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1305+ * GNU General Public License for more details.
1306+ *
1307+ * You should have received a copy of the GNU General Public License
1308+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1309+ */
1310+
1311+import QtQuick 2.3
1312+
1313+ScriptAction {
1314+ property var info
1315+ property var shell
1316+
1317+ script: {
1318+ info.transitioning = true;
1319+ shell.orientationAngle = info.requestedOrientationAngle;
1320+ shell.transformRotationAngle = info.requestedOrientationAngle;
1321+
1322+ // Making bindings as orientedShell's dimensions might wiggle during startup.
1323+ if (info.requestedOrientationAngle === 90 || info.requestedOrientationAngle === 270) {
1324+ shell.width = Qt.binding(function() { return orientedShell.height; });
1325+ shell.height = Qt.binding(function() { return orientedShell.width; });
1326+ } else {
1327+ shell.width = Qt.binding(function() { return orientedShell.width; });
1328+ shell.height = Qt.binding(function() { return orientedShell.height; });
1329+ }
1330+
1331+ shell.x = Qt.binding(function() { return (orientedShell.width - shell.width) / 2; });
1332+ shell.y = Qt.binding(function() { return (orientedShell.height - shell.height) / 2; });
1333+ shell.transformOriginX = Qt.binding(function() { return shell.width / 2; });
1334+ shell.transformOriginY = Qt.binding(function() { return shell.height / 2; });
1335+
1336+ shell.updateFocusedAppOrientation();
1337+ info.transitioning = false;
1338+ }
1339+}
1340
1341=== added file 'qml/Rotation/NinetyRotationAnimation.qml'
1342--- qml/Rotation/NinetyRotationAnimation.qml 1970-01-01 00:00:00 +0000
1343+++ qml/Rotation/NinetyRotationAnimation.qml 2015-05-21 17:30:56 +0000
1344@@ -0,0 +1,90 @@
1345+/*
1346+ * Copyright (C) 2015 Canonical, Ltd.
1347+ *
1348+ * This program is free software; you can redistribute it and/or modify
1349+ * it under the terms of the GNU General Public License as published by
1350+ * the Free Software Foundation; version 3.
1351+ *
1352+ * This program is distributed in the hope that it will be useful,
1353+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1354+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1355+ * GNU General Public License for more details.
1356+ *
1357+ * You should have received a copy of the GNU General Public License
1358+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1359+ */
1360+
1361+import QtQuick 2.3
1362+
1363+SequentialAnimation {
1364+ id: root
1365+
1366+ property int fromAngle
1367+ property int toAngle
1368+ property var info
1369+ property var shell
1370+
1371+ readonly property real fromY: fromAngle === 0 || fromAngle === 90 ? 0 : orientedShell.height - orientedShell.width;
1372+ readonly property real toY: toAngle === 0 || toAngle === 90 ? 0 : orientedShell.height - orientedShell.width;
1373+ readonly property bool flipShellDimensions: toAngle == 90 || toAngle == 270
1374+
1375+ ScriptAction { script: {
1376+ info.transitioning = true;
1377+ windowScreenshot.take();
1378+ windowScreenshot.visible = true;
1379+ shell.orientationAngle = root.toAngle;
1380+ shell.x = 0;
1381+ shell.width = flipShellDimensions ? orientedShell.height : orientedShell.width;
1382+ shell.height = flipShellDimensions ? orientedShell.width : orientedShell.height;
1383+ shell.transformOriginX = orientedShell.width / 2;
1384+ shell.transformOriginY = orientedShell.width / 2;
1385+ shell.updateFocusedAppOrientation();
1386+ shellCover.visible = true;
1387+
1388+ windowScreenshot.transformOriginX = orientedShell.width / 2;
1389+ if (fromAngle == 180 || fromAngle == 270) {
1390+ windowScreenshot.transformOriginY = orientedShell.height - (orientedShell.width / 2);
1391+ } else {
1392+ windowScreenshot.transformOriginY = orientedShell.width / 2;
1393+ }
1394+ } }
1395+ ParallelAnimation {
1396+ NumberAnimation {
1397+ target: shellCover; property: "opacity"; from: 1; to: 0;
1398+ duration: rotationDuration; easing.type: rotationEasing
1399+ }
1400+ RotationAnimation {
1401+ target: shell; property: "transformRotationAngle";
1402+ from: root.fromAngle; to: root.toAngle
1403+ direction: RotationAnimation.Shortest
1404+ duration: rotationDuration; easing.type: rotationEasing
1405+ }
1406+ NumberAnimation {
1407+ target: shell; property: "y"
1408+ from: root.fromY; to: root.toY
1409+ duration: rotationDuration; easing.type: rotationEasing
1410+ }
1411+
1412+ NumberAnimation {
1413+ target: windowScreenshot; property: "opacity"; from: 1; to: 0;
1414+ duration: rotationDuration; easing.type: rotationEasing
1415+ }
1416+ RotationAnimation {
1417+ target: windowScreenshot; property: "transformRotationAngle";
1418+ from: 0; to: root.toAngle - root.fromAngle
1419+ direction: RotationAnimation.Shortest
1420+ duration: rotationDuration; easing.type: rotationEasing
1421+ }
1422+ NumberAnimation {
1423+ target: windowScreenshot; property: "y"
1424+ from: 0; to: root.toY - root.fromY
1425+ duration: rotationDuration; easing.type: rotationEasing
1426+ }
1427+ }
1428+ ScriptAction { script: {
1429+ windowScreenshot.visible = false;
1430+ windowScreenshot.discard();
1431+ shellCover.visible = false;
1432+ info.transitioning = false;
1433+ } }
1434+}
1435
1436=== added file 'qml/Rotation/RotationStates.qml'
1437--- qml/Rotation/RotationStates.qml 1970-01-01 00:00:00 +0000
1438+++ qml/Rotation/RotationStates.qml 2015-05-21 17:30:56 +0000
1439@@ -0,0 +1,278 @@
1440+/*
1441+ * Copyright (C) 2015 Canonical, Ltd.
1442+ *
1443+ * This program is free software; you can redistribute it and/or modify
1444+ * it under the terms of the GNU General Public License as published by
1445+ * the Free Software Foundation; version 3.
1446+ *
1447+ * This program is distributed in the hope that it will be useful,
1448+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1449+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1450+ * GNU General Public License for more details.
1451+ *
1452+ * You should have received a copy of the GNU General Public License
1453+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1454+ */
1455+
1456+import QtQuick 2.0
1457+import Ubuntu.Components 1.1
1458+import Powerd 0.1
1459+
1460+// Why the state machine is done that way:
1461+// We cannot use regular PropertyChanges{} inside the State elements as steps in the
1462+// transition animations must take place in a well defined order.
1463+// Which means that we also cannot jump to a new state in the middle of a transition
1464+// as that would make hell brake loose.
1465+StateGroup {
1466+ id: root
1467+
1468+ // to be set from the outside
1469+ property Item orientedShell
1470+ property Item shell
1471+ property Item shellCover
1472+ property Item windowScreenshot
1473+
1474+ property int rotationDuration: 450
1475+ property int rotationEasing: Easing.InOutCubic
1476+ // Those values are good for debugging/development
1477+ //property int rotationDuration: 3000
1478+ //property int rotationEasing: Easing.Linear
1479+
1480+ state: "0"
1481+ states: [
1482+ State { name: "0" },
1483+ State { name: "90" },
1484+ State { name: "180" },
1485+ State { name: "270" }
1486+ ]
1487+
1488+ property QtObject d: QtObject {
1489+ id: d
1490+
1491+ property bool startingUp: true
1492+ property var finishStartUpTimer: Timer {
1493+ interval: 500
1494+ onTriggered: d.startingUp = false
1495+ }
1496+ Component.onCompleted: {
1497+ finishStartUpTimer.start();
1498+ }
1499+
1500+ property bool transitioning: false
1501+ onTransitioningChanged: {
1502+ d.tryUpdateState();
1503+ }
1504+
1505+ readonly property int requestedOrientationAngle: root.orientedShell.acceptedOrientationAngle
1506+
1507+ // Avoiding a direct call to tryUpdateState() as the state change might trigger an immediate
1508+ // change to Shell.orientationAngle which, in its turn, causes a reevaluation of
1509+ // requestedOrientationAngle (ie., OrientedShell.acceptedOrientationAngle). A reentrant evaluation
1510+ // of a binding is detected by QML as a binding loop and QML will deny the reevalutation, which
1511+ // will leave us in a bogus state.
1512+ //
1513+ // To avoid this mess we update the state in the next event loop iteration, ensuring a clean
1514+ // call stack.
1515+ onRequestedOrientationAngleChanged: {
1516+ stateUpdateTimer.start();
1517+ }
1518+ property Timer stateUpdateTimer: Timer {
1519+ id: stateUpdateTimer
1520+ interval: 1
1521+ onTriggered: { d.tryUpdateState(); }
1522+ }
1523+
1524+ function tryUpdateState() {
1525+ if (d.transitioning || (!d.startingUp && !root.shell.orientationChangesEnabled)) {
1526+ return;
1527+ }
1528+
1529+ var requestedState = d.requestedOrientationAngle.toString();
1530+ if (requestedState !== root.state) {
1531+ d.resolveAnimationType();
1532+ root.state = requestedState;
1533+ }
1534+ }
1535+
1536+ property Connections shellConnections: Connections {
1537+ target: root.shell
1538+ onOrientationChangesEnabledChanged: {
1539+ d.tryUpdateState();
1540+ }
1541+ }
1542+
1543+ property var shellBeingResized: Binding {
1544+ target: root.shell
1545+ property: "beingResized"
1546+ value: d.transitioning
1547+ }
1548+
1549+ readonly property int fullAnimation: 0
1550+ readonly property int indicatorsBarAnimation: 1
1551+ readonly property int noAnimation: 2
1552+
1553+ property int animationType
1554+
1555+ // animationType update *must* take place *before* the state update.
1556+ // If animationType and state were updated through bindings, as with normal qml code,
1557+ // there would be no guarantee in the order of the binding updates, which could then
1558+ // cause the wrong transitions to be chosen for the state changes.
1559+ function resolveAnimationType() {
1560+ if (d.startingUp) {
1561+ // During start up, inital property values are still settling while we're still
1562+ // to render the very first frame
1563+ d.animationType = d.noAnimation;
1564+ } else if (Powerd.status === Powerd.Off) {
1565+ // There's no point in animating if the user can't see it (display is off).
1566+ d.animationType = d.noAnimation;
1567+ } else if (root.shell.showingGreeter) {
1568+ // A rotating greeter looks weird.
1569+ d.animationType = d.noAnimation;
1570+ } else {
1571+ if (!root.shell.mainApp) {
1572+ // shouldn't happen but, anyway
1573+ d.animationType = d.fullAnimation;
1574+ return;
1575+ }
1576+
1577+ if (root.shell.mainApp.rotatesWindowContents) {
1578+ // The application will animate its own GUI, so we don't have to do anything ourselves.
1579+ d.animationType = d.noAnimation;
1580+ } else if (root.shell.mainAppWindowOrientationAngle == d.requestedOrientationAngle) {
1581+ // The app window is already on its final orientation angle.
1582+ // So we just animate the indicators bar
1583+ // TODO: what if the app is fullscreen?
1584+ d.animationType = d.indicatorsBarAnimation;
1585+ } else {
1586+ d.animationType = d.fullAnimation;
1587+ }
1588+ }
1589+ }
1590+
1591+ // When an application switch takes place, d.requestedOrientationAngle and
1592+ // root.shell.mainAppWindowOrientationAngle get updated separately, at different moments.
1593+ // So, when one of those properties change, we shouldn't make a decision straight away
1594+ // as the other might be stale and about to be changed. So let's give it a bit of time for
1595+ // them to get properly updated.
1596+ // This approach is indeed a bit hacky.
1597+ property bool appWindowOrientationAngleNeedsUpdateUnstable:
1598+ root.shell.orientationAngle === d.requestedOrientationAngle
1599+ && root.shell.mainApp
1600+ && root.shell.mainAppWindowOrientationAngle !== root.shell.orientationAngle
1601+ && !d.transitioning
1602+ onAppWindowOrientationAngleNeedsUpdateUnstableChanged: {
1603+ stableTimer.restart();
1604+ }
1605+ property Timer stableTimer: Timer {
1606+ interval: 200
1607+ onTriggered: {
1608+ if (d.appWindowOrientationAngleNeedsUpdateUnstable) {
1609+ shell.updateFocusedAppOrientationAnimated();
1610+ }
1611+ }
1612+ }
1613+ }
1614+
1615+ transitions: [
1616+ Transition {
1617+ from: "90"; to: "0"
1618+ enabled: d.animationType == d.fullAnimation
1619+ NinetyRotationAnimation { fromAngle: 90; toAngle: 0
1620+ info: d; shell: root.shell }
1621+ },
1622+ Transition {
1623+ from: "0"; to: "90"
1624+ enabled: d.animationType == d.fullAnimation
1625+ NinetyRotationAnimation { fromAngle: 0; toAngle: 90
1626+ info: d; shell: root.shell }
1627+ },
1628+ Transition {
1629+ from: "0"; to: "270"
1630+ enabled: d.animationType == d.fullAnimation
1631+ NinetyRotationAnimation { fromAngle: 0; toAngle: 270
1632+ info: d; shell: root.shell }
1633+ },
1634+ Transition {
1635+ from: "270"; to: "0"
1636+ enabled: d.animationType == d.fullAnimation
1637+ NinetyRotationAnimation { fromAngle: 270; toAngle: 0
1638+ info: d; shell: root.shell }
1639+ },
1640+ Transition {
1641+ from: "90"; to: "180"
1642+ enabled: d.animationType == d.fullAnimation
1643+ NinetyRotationAnimation { fromAngle: 90; toAngle: 180
1644+ info: d; shell: root.shell }
1645+ },
1646+ Transition {
1647+ from: "180"; to: "90"
1648+ enabled: d.animationType == d.fullAnimation
1649+ NinetyRotationAnimation { fromAngle: 180; toAngle: 90
1650+ info: d; shell: root.shell }
1651+ },
1652+ Transition {
1653+ from: "180"; to: "270"
1654+ enabled: d.animationType == d.fullAnimation
1655+ NinetyRotationAnimation { fromAngle: 180; toAngle: 270
1656+ info: d; shell: root.shell }
1657+ },
1658+ Transition {
1659+ from: "270"; to: "180"
1660+ enabled: d.animationType == d.fullAnimation
1661+ NinetyRotationAnimation { fromAngle: 270; toAngle: 180
1662+ info: d; shell: root.shell }
1663+ },
1664+ Transition {
1665+ from: "0"; to: "180"
1666+ enabled: d.animationType == d.fullAnimation
1667+ HalfLoopRotationAnimation { fromAngle: 0; toAngle: 180
1668+ info: d; shell: root.shell }
1669+ },
1670+ Transition {
1671+ from: "180"; to: "0"
1672+ enabled: d.animationType == d.fullAnimation
1673+ HalfLoopRotationAnimation { fromAngle: 180; toAngle: 0
1674+ info: d; shell: root.shell }
1675+ },
1676+ Transition {
1677+ from: "90"; to: "270"
1678+ enabled: d.animationType == d.fullAnimation
1679+ HalfLoopRotationAnimation { fromAngle: 90; toAngle: 270
1680+ info: d; shell: root.shell }
1681+ },
1682+ Transition {
1683+ from: "270"; to: "90"
1684+ enabled: d.animationType == d.fullAnimation
1685+ HalfLoopRotationAnimation { fromAngle: 270; toAngle: 90
1686+ info: d; shell: root.shell }
1687+ },
1688+ Transition {
1689+ objectName: "immediateTransition"
1690+ enabled: d.animationType == d.noAnimation
1691+ ImmediateRotationAction { info: d; shell: root.shell }
1692+ },
1693+ Transition {
1694+ enabled: d.animationType == d.indicatorsBarAnimation
1695+ SequentialAnimation {
1696+ ScriptAction { script: {
1697+ d.transitioning = true;
1698+ } }
1699+ NumberAnimation {
1700+ duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing
1701+ target: root.shell; property: "indicatorAreaShowProgress"
1702+ from: 1.0; to: 0.0
1703+ }
1704+ ImmediateRotationAction { info: d; shell: root.shell }
1705+ NumberAnimation {
1706+ duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing
1707+ target: root.shell; property: "indicatorAreaShowProgress"
1708+ from: 0.0; to: 1.0
1709+ }
1710+ ScriptAction { script: {
1711+ d.transitioning = false;
1712+ }}
1713+ }
1714+ }
1715+ ]
1716+
1717+}
1718
1719=== modified file 'qml/Shell.qml'
1720--- qml/Shell.qml 2015-05-18 23:03:25 +0000
1721+++ qml/Shell.qml 2015-05-21 17:30:56 +0000
1722@@ -1,5 +1,5 @@
1723 /*
1724- * Copyright (C) 2013 Canonical, Ltd.
1725+ * Copyright (C) 2013-2015 Canonical, Ltd.
1726 *
1727 * This program is free software; you can redistribute it and/or modify
1728 * it under the terms of the GNU General Public License as published by
1729@@ -45,39 +45,69 @@
1730 Item {
1731 id: shell
1732
1733+ // to be set from outside
1734+ property int orientationAngle: 0
1735+ property int orientation
1736+ property int primaryOrientation
1737+ property int nativeOrientation
1738+ property real nativeWidth
1739+ property real nativeHeight
1740+ property alias indicatorAreaShowProgress: panel.indicatorAreaShowProgress
1741+ property bool beingResized
1742+ property string usageScenario: "phone" // supported values: "phone", "tablet" or "desktop"
1743+ function updateFocusedAppOrientation() {
1744+ applicationsDisplayLoader.item.updateFocusedAppOrientation();
1745+ }
1746+ function updateFocusedAppOrientationAnimated() {
1747+ applicationsDisplayLoader.item.updateFocusedAppOrientationAnimated();
1748+ }
1749+
1750+ // to be read from outside
1751+ readonly property int mainAppWindowOrientationAngle:
1752+ applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainAppWindowOrientationAngle : 0
1753+
1754+ readonly property bool orientationChangesEnabled: panel.indicators.fullyClosed
1755+ && (applicationsDisplayLoader.item && applicationsDisplayLoader.item.orientationChangesEnabled)
1756+ && !greeter.animating
1757+
1758+ readonly property bool showingGreeter: greeter.shown
1759+
1760+ property bool startingUp: true
1761+ Timer { id: finishStartUpTimer; interval: 500; onTriggered: startingUp = false }
1762+
1763+ property int supportedOrientations: {
1764+ if (startingUp) {
1765+ // Ensure we don't rotate during start up
1766+ return Qt.PrimaryOrientation;
1767+ } else if (greeter.shown) {
1768+ return Qt.PrimaryOrientation;
1769+ } else if (mainApp) {
1770+ return mainApp.supportedOrientations;
1771+ } else {
1772+ // we just don't care
1773+ return Qt.PortraitOrientation
1774+ | Qt.LandscapeOrientation
1775+ | Qt.InvertedPortraitOrientation
1776+ | Qt.InvertedLandscapeOrientation;
1777+ }
1778+ }
1779+
1780+ // For autopilot consumption
1781+ readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
1782+
1783+ // internal props from here onwards
1784+ readonly property var mainApp:
1785+ applicationsDisplayLoader.item ? applicationsDisplayLoader.item.mainApp : null
1786+
1787 // Disable everything while greeter is waiting, so that the user can't swipe
1788 // the greeter or launcher until we know whether the session is locked.
1789 enabled: !greeter.waiting
1790
1791- // this is only here to select the width / height of the window if not running fullscreen
1792- property bool tablet: false
1793- width: tablet ? units.gu(160) : applicationArguments.hasGeometry() ? applicationArguments.width() : units.gu(40)
1794- height: tablet ? units.gu(100) : applicationArguments.hasGeometry() ? applicationArguments.height() : units.gu(71)
1795-
1796 property real edgeSize: units.gu(2)
1797 property url defaultBackground: Qt.resolvedUrl(shell.width >= units.gu(60) ? "graphics/tablet_background.jpg" : "graphics/phone_background.jpg")
1798 property url background: asImageTester.status == Image.Ready ? asImageTester.source
1799 : gsImageTester.status == Image.Ready ? gsImageTester.source : defaultBackground
1800
1801- property bool sideStageEnabled: shell.width >= units.gu(100)
1802- readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
1803-
1804- property int orientation
1805- readonly property int deviceOrientationAngle: Screen.angleBetween(Screen.primaryOrientation, Screen.orientation)
1806- onDeviceOrientationAngleChanged: {
1807- if (!OrientationLock.enabled) {
1808- orientation = Screen.orientation;
1809- }
1810- }
1811- readonly property bool orientationLockEnabled: OrientationLock.enabled
1812- onOrientationLockEnabledChanged: {
1813- if (orientationLockEnabled) {
1814- OrientationLock.savedOrientation = Screen.orientation;
1815- } else {
1816- orientation = Screen.orientation;
1817- }
1818- }
1819-
1820 // This is _only_ used to expose the property to autopilot tests
1821 readonly property string testShellMode: shellMode
1822
1823@@ -85,7 +115,8 @@
1824 if (ApplicationManager.findApplication(appId)) {
1825 ApplicationManager.requestFocusApplication(appId);
1826 } else {
1827- var execFlags = shell.sideStageEnabled ? ApplicationManager.NoFlag : ApplicationManager.ForceMainStage;
1828+ var execFlags = shell.usageScenario === "phone" ? ApplicationManager.ForceMainStage
1829+ : ApplicationManager.NoFlag;
1830 ApplicationManager.startApplication(appId, execFlags);
1831 }
1832 }
1833@@ -122,11 +153,6 @@
1834 sourceSize.width: 0
1835 }
1836
1837- GSettings {
1838- id: usageModeSettings
1839- schema.id: "com.canonical.Unity8"
1840- }
1841-
1842 Binding {
1843 target: LauncherModel
1844 property: "applicationManager"
1845@@ -138,9 +164,7 @@
1846 if (ApplicationManager.count > 0) {
1847 ApplicationManager.focusApplication(ApplicationManager.get(0).appId);
1848 }
1849- if (orientationLockEnabled) {
1850- orientation = OrientationLock.savedOrientation;
1851- }
1852+ finishStartUpTimer.start();
1853 }
1854
1855 VolumeControl {
1856@@ -233,9 +257,19 @@
1857 // theoretical attack where user enters lockedApp mode, then makes
1858 // the screen larger (maybe connects to monitor) and tries to enter
1859 // tablet mode.
1860- property bool tabletMode: shell.sideStageEnabled && !greeter.hasLockedApp
1861- source: usageModeSettings.usageMode === "Windowed" ? "Stages/DesktopStage.qml"
1862- : tabletMode ? "Stages/TabletStage.qml" : "Stages/PhoneStage.qml"
1863+
1864+ property string usageScenario: shell.usageScenario === "phone" || greeter.hasLockedApp
1865+ ? "phone"
1866+ : shell.usageScenario
1867+ source: {
1868+ if (applicationsDisplayLoader.usageScenario === "phone") {
1869+ return "Stages/PhoneStage.qml";
1870+ } else if (applicationsDisplayLoader.usageScenario === "tablet") {
1871+ return "Stages/TabletStage.qml";
1872+ } else {
1873+ return "Stages/DesktopStage.qml";
1874+ }
1875+ }
1876
1877 property bool interactive: tutorial.spreadEnabled
1878 && !greeter.shown
1879@@ -278,7 +312,12 @@
1880 }
1881 Binding {
1882 target: applicationsDisplayLoader.item
1883- property: "orientation"
1884+ property: "shellOrientationAngle"
1885+ value: shell.orientationAngle
1886+ }
1887+ Binding {
1888+ target: applicationsDisplayLoader.item
1889+ property: "shellOrientation"
1890 value: shell.orientation
1891 }
1892 Binding {
1893@@ -286,6 +325,31 @@
1894 property: "background"
1895 value: shell.background
1896 }
1897+ Binding {
1898+ target: applicationsDisplayLoader.item
1899+ property: "shellPrimaryOrientation"
1900+ value: shell.primaryOrientation
1901+ }
1902+ Binding {
1903+ target: applicationsDisplayLoader.item
1904+ property: "nativeOrientation"
1905+ value: shell.nativeOrientation
1906+ }
1907+ Binding {
1908+ target: applicationsDisplayLoader.item
1909+ property: "nativeWidth"
1910+ value: shell.nativeWidth
1911+ }
1912+ Binding {
1913+ target: applicationsDisplayLoader.item
1914+ property: "nativeHeight"
1915+ value: shell.nativeHeight
1916+ }
1917+ Binding {
1918+ target: applicationsDisplayLoader.item
1919+ property: "beingResized"
1920+ value: shell.beingResized
1921+ }
1922 }
1923
1924 Tutorial {
1925@@ -355,7 +419,7 @@
1926 objectName: "greeter"
1927
1928 hides: [launcher, panel.indicators]
1929- tabletMode: shell.sideStageEnabled
1930+ tabletMode: shell.usageScenario !== "phone"
1931 launcherOffset: launcher.progress
1932 forcedUnlock: tutorial.running
1933 background: shell.background
1934@@ -482,20 +546,18 @@
1935 expandedPanelHeight: units.gu(7)
1936
1937 indicatorsModel: Indicators.IndicatorsModel {
1938- // TODO: This should be sourced by device type (e.g. "desktop", "tablet", "phone"...)
1939- profile: indicatorProfile
1940- Component.onCompleted: load()
1941+ // tablet and phone both use the same profile
1942+ profile: shell.usageScenario === "desktop" ? "desktop" : "phone"
1943+ Component.onCompleted: load();
1944 }
1945 }
1946+
1947 callHint {
1948 greeterShown: greeter.shown
1949 }
1950
1951- property bool topmostApplicationIsFullscreen:
1952- ApplicationManager.focusedApplicationId &&
1953- ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).fullscreen
1954-
1955- fullscreenMode: (topmostApplicationIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
1956+ property bool mainAppIsFullscreen: shell.mainApp && shell.mainApp.fullscreen
1957+ fullscreenMode: (mainAppIsFullscreen && !LightDM.Greeter.active && launcher.progress == 0)
1958 || greeter.hasLockedApp
1959 }
1960
1961@@ -513,7 +575,7 @@
1962 available: tutorial.launcherEnabled
1963 && (!greeter.locked || AccountsService.enableLauncherWhileLocked)
1964 && !greeter.hasLockedApp
1965- inverted: usageModeSettings.usageMode === "Staged"
1966+ inverted: shell.usageScenario !== "desktop"
1967 shadeBackground: !tutorial.running
1968
1969 onShowDashHome: showHome()
1970@@ -555,7 +617,7 @@
1971 Rectangle {
1972 id: modalNotificationBackground
1973
1974- visible: notifications.useModal && (notifications.state == "narrow")
1975+ visible: notifications.useModal
1976 color: "#000000"
1977 anchors.fill: parent
1978 opacity: 0.9
1979@@ -600,6 +662,7 @@
1980
1981 Dialogs {
1982 id: dialogs
1983+ objectName: "dialogs"
1984 anchors.fill: parent
1985 z: overlay.z + 10
1986 onPowerOffClicked: {
1987
1988=== modified file 'qml/Stages/ApplicationWindow.qml'
1989--- qml/Stages/ApplicationWindow.qml 2015-02-26 22:35:53 +0000
1990+++ qml/Stages/ApplicationWindow.qml 2015-05-21 17:30:56 +0000
1991@@ -1,5 +1,5 @@
1992 /*
1993- * Copyright 2014 Canonical Ltd.
1994+ * Copyright 2014-2015 Canonical Ltd.
1995 *
1996 * This program is free software; you can redistribute it and/or modify
1997 * it under the terms of the GNU Lesser General Public License as published by
1998@@ -24,10 +24,11 @@
1999 // to be read from outside
2000 readonly property bool fullscreen: application ? application.fullscreen : false
2001 property alias interactive: sessionContainer.interactive
2002+ property bool orientationChangesEnabled: d.supportsSurfaceResize ? d.surfaceOldEnoughToBeResized : true
2003
2004 // to be set from outside
2005 property QtObject application
2006- property int orientation
2007+ property int surfaceOrientationAngle
2008
2009 QtObject {
2010 id: d
2011@@ -62,6 +63,15 @@
2012 // Remove this when possible
2013 property bool surfaceInitialized: false
2014
2015+ property bool supportsSurfaceResize:
2016+ application &&
2017+ ((application.supportedOrientations & Qt.PortraitOrientation)
2018+ || (application.supportedOrientations & Qt.InvertedPortraitOrientation))
2019+ &&
2020+ ((application.supportedOrientations & Qt.LandscapeOrientation)
2021+ || (application.supportedOrientations & Qt.InvertedLandscapeOrientation))
2022+
2023+ property bool surfaceOldEnoughToBeResized: false
2024 }
2025
2026 Timer {
2027@@ -70,6 +80,12 @@
2028 onTriggered: { if (sessionContainer.surface) {d.surfaceInitialized = true;} }
2029 }
2030
2031+ Timer {
2032+ id: surfaceIsOldTimer
2033+ interval: 1000
2034+ onTriggered: { if (stateGroup.state === "surface") { d.surfaceOldEnoughToBeResized = true; } }
2035+ }
2036+
2037 Image {
2038 id: screenshotImage
2039 objectName: "screenshotImage"
2040@@ -113,7 +129,8 @@
2041 // A fake application might not even have a session property.
2042 session: application && application.session ? application.session : null
2043 anchors.fill: parent
2044- orientation: root.orientation
2045+
2046+ surfaceOrientationAngle: application && application.rotatesWindowContents ? root.surfaceOrientationAngle : 0
2047
2048 onSurfaceChanged: {
2049 if (sessionContainer.surface) {
2050@@ -179,15 +196,21 @@
2051 UbuntuNumberAnimation { target: sessionContainer.surfaceContainer; property: "opacity";
2052 from: 0.0; to: 1.0
2053 duration: UbuntuAnimation.BriskDuration }
2054- PropertyAction { target: splashLoader; property: "active"; value: false }
2055+ ScriptAction { script: {
2056+ splashLoader.active = false;
2057+ surfaceIsOldTimer.start();
2058+ } }
2059 }
2060 },
2061 Transition {
2062 from: "surface"; to: "splashScreen"
2063 SequentialAnimation {
2064- PropertyAction { target: splashLoader; property: "active"; value: true }
2065- PropertyAction { target: sessionContainer.surfaceContainer
2066- property: "visible"; value: true }
2067+ ScriptAction { script: {
2068+ surfaceIsOldTimer.stop();
2069+ d.surfaceOldEnoughToBeResized = false;
2070+ splashLoader.active = true;
2071+ sessionContainer.surfaceContainer.visible = true;
2072+ } }
2073 UbuntuNumberAnimation { target: splashLoader; property: "opacity";
2074 from: 0.0; to: 1.0
2075 duration: UbuntuAnimation.BriskDuration }
2076@@ -198,14 +221,18 @@
2077 Transition {
2078 from: "surface"; to: "screenshot"
2079 SequentialAnimation {
2080- PropertyAction { target: screenshotImage
2081- property: "visible"; value: true }
2082+ ScriptAction { script: {
2083+ surfaceIsOldTimer.stop();
2084+ d.surfaceOldEnoughToBeResized = false;
2085+ screenshotImage.visible = true;
2086+ } }
2087 UbuntuNumberAnimation { target: screenshotImage; property: "opacity";
2088 from: 0.0; to: 1.0
2089 duration: UbuntuAnimation.BriskDuration }
2090- PropertyAction { target: sessionContainer.surfaceContainer
2091- property: "visible"; value: false }
2092- ScriptAction { script: { if (sessionContainer.session) { sessionContainer.session.release(); } } }
2093+ ScriptAction { script: {
2094+ sessionContainer.surfaceContainer.visible = false;
2095+ if (sessionContainer.session) { sessionContainer.session.release(); }
2096+ } }
2097 }
2098 },
2099 Transition {
2100@@ -216,8 +243,11 @@
2101 UbuntuNumberAnimation { target: screenshotImage; property: "opacity";
2102 from: 1.0; to: 0.0
2103 duration: UbuntuAnimation.BriskDuration }
2104- PropertyAction { target: screenshotImage; property: "visible"; value: false }
2105- PropertyAction { target: screenshotImage; property: "source"; value: "" }
2106+ ScriptAction { script: {
2107+ screenshotImage.visible = false;
2108+ screenshotImage.source = "";
2109+ surfaceIsOldTimer.start();
2110+ } }
2111 }
2112 },
2113 Transition {
2114@@ -233,10 +263,12 @@
2115 },
2116 Transition {
2117 from: "surface"; to: "void"
2118- SequentialAnimation {
2119- PropertyAction { target: sessionContainer.surfaceContainer; property: "visible"; value: false }
2120- ScriptAction { script: { if (sessionContainer.session) { sessionContainer.session.release(); } } }
2121- }
2122+ ScriptAction { script: {
2123+ surfaceIsOldTimer.stop();
2124+ d.surfaceOldEnoughToBeResized = false;
2125+ sessionContainer.surfaceContainer.visible = false;
2126+ if (sessionContainer.session) { sessionContainer.session.release(); }
2127+ } }
2128 },
2129 Transition {
2130 from: "void"; to: "surface"
2131@@ -246,6 +278,9 @@
2132 UbuntuNumberAnimation { target: sessionContainer.surfaceContainer; property: "opacity";
2133 from: 0.0; to: 1.0
2134 duration: UbuntuAnimation.BriskDuration }
2135+ ScriptAction { script: {
2136+ surfaceIsOldTimer.start();
2137+ } }
2138 }
2139 }
2140 ]
2141
2142=== modified file 'qml/Stages/DesktopStage.qml'
2143--- qml/Stages/DesktopStage.qml 2015-05-01 14:09:58 +0000
2144+++ qml/Stages/DesktopStage.qml 2015-05-21 17:30:56 +0000
2145@@ -26,6 +26,29 @@
2146
2147 anchors.fill: parent
2148
2149+ // Controls to be set from outside
2150+ property int dragAreaWidth // just to comply with the interface shared between stages
2151+ property real maximizedAppTopMargin
2152+ property bool interactive
2153+ property bool spreadEnabled // just to comply with the interface shared between stages
2154+ property real inverseProgress: 0 // just to comply with the interface shared between stages
2155+ property int shellOrientationAngle: 0
2156+ property int shellOrientation
2157+ property int shellPrimaryOrientation
2158+ property int nativeOrientation
2159+ property bool beingResized: false
2160+
2161+ // functions to be called from outside
2162+ function updateFocusedAppOrientation() { /* TODO */ }
2163+ function updateFocusedAppOrientationAnimated() { /* TODO */}
2164+
2165+ // To be read from outside
2166+ readonly property var mainApp: ApplicationManager.focusedApplicationId
2167+ ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId)
2168+ : null
2169+ property int mainAppWindowOrientationAngle: 0
2170+ readonly property bool orientationChangesEnabled: false
2171+
2172 property alias background: wallpaper.source
2173
2174 CrossFadeImage {
2175
2176=== added file 'qml/Stages/OrientationChangeAnimation.qml'
2177--- qml/Stages/OrientationChangeAnimation.qml 1970-01-01 00:00:00 +0000
2178+++ qml/Stages/OrientationChangeAnimation.qml 2015-05-21 17:30:56 +0000
2179@@ -0,0 +1,241 @@
2180+/*
2181+ * Copyright 2015 Canonical Ltd.
2182+ *
2183+ * This program is free software; you can redistribute it and/or modify
2184+ * it under the terms of the GNU Lesser General Public License as published by
2185+ * the Free Software Foundation; version 3.
2186+ *
2187+ * This program is distributed in the hope that it will be useful,
2188+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2189+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2190+ * GNU Lesser General Public License for more details.
2191+ *
2192+ * You should have received a copy of the GNU Lesser General Public License
2193+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2194+ */
2195+
2196+import QtQuick 2.3
2197+
2198+QtObject {
2199+ id: root
2200+
2201+ // to be set from outside
2202+ property Item spreadDelegate
2203+ property Item background
2204+ property Item window
2205+ property Item screenshot
2206+
2207+ function start() {
2208+ if (window.orientationAngle === 0) {
2209+ if (spreadDelegate.shellOrientationAngle === 90) {
2210+ chosenAnimation = simple90Animation;
2211+ } else if (spreadDelegate.shellOrientationAngle === 180) {
2212+ chosenAnimation = halfLoopAnimation;
2213+ } else if (spreadDelegate.shellOrientationAngle === 270) {
2214+ chosenAnimation = moving90Animation;
2215+ } else {
2216+ chosenAnimation = null;
2217+ }
2218+ } else if (window.orientationAngle === 90) {
2219+ if (spreadDelegate.shellOrientationAngle === 0) {
2220+ chosenAnimation = simple90Animation;
2221+ } else if (spreadDelegate.shellOrientationAngle === 180) {
2222+ chosenAnimation = moving90Animation;
2223+ } else if (spreadDelegate.shellOrientationAngle === 270) {
2224+ chosenAnimation = halfLoopAnimation;
2225+ } else {
2226+ chosenAnimation = null;
2227+ }
2228+ } else if (window.orientationAngle === 180) {
2229+ if (spreadDelegate.shellOrientationAngle === 0) {
2230+ chosenAnimation = halfLoopAnimation;
2231+ } else if (spreadDelegate.shellOrientationAngle === 90) {
2232+ chosenAnimation = moving90Animation;
2233+ } else if (spreadDelegate.shellOrientationAngle === 270) {
2234+ chosenAnimation = simple90Animation;
2235+ } else {
2236+ chosenAnimation = null;
2237+ }
2238+ } else if (window.orientationAngle === 270) {
2239+ if (spreadDelegate.shellOrientationAngle === 0) {
2240+ chosenAnimation = moving90Animation;
2241+ } else if (spreadDelegate.shellOrientationAngle === 90) {
2242+ chosenAnimation = halfLoopAnimation;
2243+ } else if (spreadDelegate.shellOrientationAngle === 180) {
2244+ chosenAnimation = simple90Animation;
2245+ } else {
2246+ chosenAnimation = null;
2247+ }
2248+ }
2249+
2250+ if (chosenAnimation)
2251+ chosenAnimation.start();
2252+ }
2253+
2254+ // to be read from outside
2255+ property bool running: chosenAnimation ? chosenAnimation.running : false
2256+
2257+ property int duration: 450
2258+ property int easingType: Easing.InOutCubic
2259+
2260+ property int shortestDimension: spreadDelegate.width < spreadDelegate.height
2261+ ? spreadDelegate.width : spreadDelegate.height
2262+ property int longestDimension: spreadDelegate.width > spreadDelegate.height
2263+ ? spreadDelegate.width : spreadDelegate.height
2264+ property string longestAxis: spreadDelegate.width > spreadDelegate.height ? "x" : "y"
2265+
2266+ property QtObject chosenAnimation
2267+
2268+ function setup90Animation() {
2269+ background.visible = true;
2270+
2271+ screenshot.width = window.width;
2272+ screenshot.height = window.height;
2273+ screenshot.window.anchors.topMargin = window.window.anchors.topMargin;
2274+ screenshot.take();
2275+ screenshot.transformOriginX = root.shortestDimension / 2;
2276+ screenshot.transformOriginY = root.shortestDimension / 2;
2277+ screenshot.visible = true;
2278+
2279+ window.rotation = 0;
2280+ window.width = spreadDelegate.width;
2281+ window.height = spreadDelegate.height;
2282+ window.transformOriginX = root.shortestDimension / 2;
2283+ window.transformOriginY = root.shortestDimension / 2;
2284+ }
2285+
2286+ function tearDown90Animation() {
2287+ window.orientationAngle = spreadDelegate.shellOrientationAngle;
2288+ screenshot.discard();
2289+ screenshot.visible = false;
2290+ background.visible = false;
2291+ }
2292+
2293+ property QtObject simple90Animation: SequentialAnimation {
2294+ id: simple90Animation
2295+
2296+ ScriptAction { script: setup90Animation() }
2297+ ParallelAnimation {
2298+ RotationAnimation {
2299+ target: root.window
2300+ duration: root.duration
2301+ easing.type: root.easingType
2302+ from: window.orientationAngle - spreadDelegate.shellOrientationAngle
2303+ to: 0
2304+ property: "transformRotationAngle"
2305+ }
2306+ RotationAnimation {
2307+ target: root.screenshot
2308+ duration: root.duration
2309+ easing.type: root.easingType
2310+ from: window.orientationAngle - spreadDelegate.shellOrientationAngle
2311+ to: 0
2312+ property: "transformRotationAngle"
2313+ }
2314+ NumberAnimation {
2315+ target: root.screenshot
2316+ duration: root.duration
2317+ easing.type: root.easingType
2318+ property: "opacity"
2319+ from: 1.0
2320+ to: 0.0
2321+ }
2322+ NumberAnimation {
2323+ target: root.window
2324+ duration: root.duration
2325+ easing.type: root.easingType
2326+ property: "opacity"
2327+ from: 0.0
2328+ to: 1.0
2329+ }
2330+ }
2331+ ScriptAction { script: tearDown90Animation() }
2332+ }
2333+
2334+ property QtObject moving90Animation: SequentialAnimation {
2335+ id: moving90Animation
2336+
2337+ ScriptAction { script: setup90Animation() }
2338+ ParallelAnimation {
2339+ RotationAnimation {
2340+ target: root.window
2341+ duration: root.duration
2342+ easing.type: root.easingType
2343+ direction: RotationAnimation.Shortest
2344+ from: window.orientationAngle - spreadDelegate.shellOrientationAngle
2345+ to: 0
2346+ property: "transformRotationAngle"
2347+ }
2348+ RotationAnimation {
2349+ target: root.screenshot
2350+ duration: root.duration
2351+ easing.type: root.easingType
2352+ direction: RotationAnimation.Shortest
2353+ from: window.orientationAngle - spreadDelegate.shellOrientationAngle
2354+ to: 0
2355+ property: "transformRotationAngle"
2356+ }
2357+ NumberAnimation {
2358+ target: root.screenshot
2359+ duration: root.duration
2360+ easing.type: root.easingType
2361+ property: "opacity"
2362+ from: 1.0
2363+ to: 0.0
2364+ }
2365+ NumberAnimation {
2366+ target: root.window
2367+ duration: root.duration
2368+ easing.type: root.easingType
2369+ property: "opacity"
2370+ from: 0.0
2371+ to: 1.0
2372+ }
2373+ NumberAnimation {
2374+ target: root.window
2375+ duration: root.duration
2376+ easing.type: root.easingType
2377+ property: root.longestAxis
2378+ from: root.longestDimension - root.shortestDimension
2379+ to: 0
2380+ }
2381+ NumberAnimation {
2382+ target: root.screenshot
2383+ duration: root.duration
2384+ easing.type: root.easingType
2385+ property: root.longestAxis
2386+ from: root.longestDimension - root.shortestDimension
2387+ to: 0
2388+ }
2389+ }
2390+ ScriptAction { script: tearDown90Animation() }
2391+ }
2392+
2393+ property QtObject halfLoopAnimation: SequentialAnimation {
2394+ id: halfLoopAnimation
2395+
2396+ ScriptAction { script: {
2397+ background.visible = true;
2398+
2399+ window.rotation = 0;
2400+ window.width = spreadDelegate.width;
2401+ window.height = spreadDelegate.height;
2402+ window.transformOriginX = window.width / 2
2403+ window.transformOriginY = window.height / 2
2404+ } }
2405+ ParallelAnimation {
2406+ RotationAnimation {
2407+ target: root.window
2408+ duration: root.duration
2409+ easing.type: root.easingType
2410+ from: window.orientationAngle - spreadDelegate.shellOrientationAngle
2411+ to: 0
2412+ property: "transformRotationAngle"
2413+ }
2414+ }
2415+ ScriptAction { script: {
2416+ window.orientationAngle = spreadDelegate.shellOrientationAngle;
2417+ background.visible = false;
2418+ } }
2419+ }
2420+}
2421
2422=== modified file 'qml/Stages/PhoneStage.qml'
2423--- qml/Stages/PhoneStage.qml 2015-05-18 23:03:25 +0000
2424+++ qml/Stages/PhoneStage.qml 2015-05-21 17:30:56 +0000
2425@@ -1,5 +1,5 @@
2426 /*
2427- * Copyright (C) 2014 Canonical, Ltd.
2428+ * Copyright (C) 2014-2015 Canonical, Ltd.
2429 *
2430 * This program is free software; you can redistribute it and/or modify
2431 * it under the terms of the GNU General Public License as published by
2432@@ -31,12 +31,64 @@
2433 property bool interactive
2434 property bool spreadEnabled: true // If false, animations and right edge will be disabled
2435 property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
2436- property int orientation: Qt.PortraitOrientation
2437 property QtObject applicationManager: ApplicationManager
2438 property bool focusFirstApp: true // If false, focused app will appear on right edge like other apps
2439 property bool altTabEnabled: true
2440 property real startScale: 1.1
2441 property real endScale: 0.7
2442+ property int shellOrientationAngle: 0
2443+ property int shellOrientation
2444+ property int shellPrimaryOrientation
2445+ property int nativeOrientation
2446+ property real nativeWidth
2447+ property real nativeHeight
2448+ property bool beingResized: false
2449+ onBeingResizedChanged: {
2450+ if (beingResized) {
2451+ // Brace yourselves for impact!
2452+ spreadView.selectedIndex = -1;
2453+ spreadView.phase = 0;
2454+ spreadView.contentX = -spreadView.shift;
2455+ }
2456+ }
2457+ function updateFocusedAppOrientation() {
2458+ if (spreadRepeater.count > 0) {
2459+ spreadRepeater.itemAt(0).matchShellOrientation();
2460+ }
2461+
2462+ for (var i = 1; i < spreadRepeater.count; ++i) {
2463+
2464+ var spreadDelegate = spreadRepeater.itemAt(i);
2465+
2466+ var delta = spreadDelegate.appWindowOrientationAngle - root.shellOrientationAngle;
2467+ if (delta < 0) { delta += 360; }
2468+ delta = delta % 360;
2469+
2470+ var supportedOrientations = spreadDelegate.application.supportedOrientations;
2471+ if (supportedOrientations === Qt.PrimaryOrientation) {
2472+ supportedOrientations = spreadDelegate.shellPrimaryOrientation;
2473+ }
2474+
2475+ if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) {
2476+ spreadDelegate.matchShellOrientation();
2477+ }
2478+ }
2479+ }
2480+ function updateFocusedAppOrientationAnimated() {
2481+ if (spreadRepeater.count > 0) {
2482+ spreadRepeater.itemAt(0).animateToShellOrientation();
2483+ }
2484+ }
2485+
2486+ // To be read from outside
2487+ readonly property var mainApp: applicationManager.focusedApplicationId
2488+ ? applicationManager.findApplication(applicationManager.focusedApplicationId)
2489+ : null
2490+ property int mainAppWindowOrientationAngle: 0
2491+ readonly property bool orientationChangesEnabled: priv.focusedAppOrientationChangesEnabled
2492+ && !priv.focusedAppDelegateIsDislocated
2493+ && !(priv.focusedAppDelegate && priv.focusedAppDelegate.xBehavior.running)
2494+ && spreadView.phase === 0
2495
2496 // How far left the stage has been dragged
2497 readonly property real dragProgress: spreadRepeater.count > 0 ? -spreadRepeater.itemAt(0).xTranslate : 0
2498@@ -54,12 +106,6 @@
2499 spreadView.snapTo(priv.indexOf(appId));
2500 }
2501
2502- onWidthChanged: {
2503- spreadView.selectedIndex = -1;
2504- spreadView.phase = 0;
2505- spreadView.contentX = -spreadView.shift;
2506- }
2507-
2508 onInverseProgressChanged: {
2509 // This can't be a simple binding because that would be triggered after this handler
2510 // while we need it active before doing the anition left/right
2511@@ -73,6 +119,20 @@
2512 priv.oldInverseProgress = inverseProgress;
2513 }
2514
2515+ // <FIXME-contentX> See rationale in the next comment with this tag
2516+ onWidthChanged: {
2517+ if (!root.beingResized) {
2518+ // we're being resized without a warning (ie, the corresponding property wasn't set
2519+ root.beingResized = true;
2520+ beingResizedTimer.start();
2521+ }
2522+ }
2523+ Timer {
2524+ id: beingResizedTimer
2525+ interval: 100
2526+ onTriggered: { root.beingResized = false; }
2527+ }
2528+
2529 Connections {
2530 target: applicationManager
2531
2532@@ -115,8 +175,9 @@
2533 QtObject {
2534 id: priv
2535
2536+ property string focusedAppId: root.applicationManager.focusedApplicationId
2537+ property bool focusedAppOrientationChangesEnabled: false
2538 readonly property int firstSpreadIndex: root.focusFirstApp ? 1 : 0
2539- property string focusedAppId: applicationManager.focusedApplicationId
2540 readonly property var focusedAppDelegate: {
2541 var index = indexOf(focusedAppId);
2542 return index >= 0 && index < spreadRepeater.count ? spreadRepeater.itemAt(index) : null
2543@@ -131,15 +192,27 @@
2544 }
2545 }
2546
2547+ property bool focusedAppDelegateIsDislocated: focusedAppDelegate && focusedAppDelegate.x !== 0
2548+
2549 function indexOf(appId) {
2550- for (var i = 0; i < applicationManager.count; i++) {
2551- if (applicationManager.get(i).appId == appId) {
2552+ for (var i = 0; i < root.applicationManager.count; i++) {
2553+ if (root.applicationManager.get(i).appId == appId) {
2554 return i;
2555 }
2556 }
2557 return -1;
2558 }
2559
2560+ // Is more stable than "spreadView.shiftedContentX === 0" as it filters out noise caused by
2561+ // Flickable.contentX changing due to resizes.
2562+ property bool fullyShowingFocusedApp: true
2563+ }
2564+ Timer {
2565+ id: fullyShowingFocusedAppUpdateTimer
2566+ interval: 100
2567+ onTriggered: {
2568+ priv.fullyShowingFocusedApp = spreadView.shiftedContentX === 0;
2569+ }
2570 }
2571
2572 Flickable {
2573@@ -187,9 +260,25 @@
2574 property int draggedDelegateCount: 0
2575 property int closingIndex: -1
2576
2577- property bool focusChanging: false
2578+ // <FIXME-contentX> Workaround Flickable's behavior of bringing contentX back between valid boundaries
2579+ // when resized. The proper way to fix this is refactoring PhoneStage so that it doesn't
2580+ // rely on having Flickable.contentX keeping an out-of-bounds value when it's set programatically
2581+ // (as opposed to having contentX reaching an out-of-bounds value through dragging, which will trigger
2582+ // the Flickable.boundsBehavior upon release).
2583+ onContentXChanged: { forceItToRemainStillIfBeingResized(); }
2584+ onShiftChanged: { forceItToRemainStillIfBeingResized(); }
2585+ function forceItToRemainStillIfBeingResized() {
2586+ if (root.beingResized && contentX != -spreadView.shift) {
2587+ contentX = -spreadView.shift;
2588+ }
2589+ }
2590
2591 onShiftedContentXChanged: {
2592+ if (root.beingResized) {
2593+ // Flickabe.contentX wiggles during resizes. Don't react to it.
2594+ return;
2595+ }
2596+
2597 switch (phase) {
2598 case 0:
2599 if (shiftedContentX > width * positionMarker2) {
2600@@ -204,6 +293,7 @@
2601 }
2602 break;
2603 }
2604+ fullyShowingFocusedAppUpdateTimer.restart();
2605 }
2606
2607 function snap() {
2608@@ -228,7 +318,7 @@
2609 snapAnimation.start();
2610 return;
2611 }
2612- if (applicationManager.count <= index) {
2613+ if (root.applicationManager.count <= index) {
2614 // In case we're trying to snap to some non existing app, lets snap back to the first one
2615 index = 0;
2616 }
2617@@ -265,7 +355,7 @@
2618 ScriptAction {
2619 script: {
2620 if (spreadView.selectedIndex >= 0) {
2621- applicationManager.focusApplication(applicationManager.get(spreadView.selectedIndex).appId);
2622+ root.applicationManager.focusApplication(root.applicationManager.get(spreadView.selectedIndex).appId);
2623
2624 spreadView.selectedIndex = -1;
2625 spreadView.phase = 0;
2626@@ -280,7 +370,7 @@
2627 // This width controls how much the spread can be flicked left/right. It's composed of:
2628 // tileDistance * app count (with a minimum of 3 apps, in order to also allow moving 1 and 2 apps a bit)
2629 // + some constant value (still scales with the screen width) which looks good and somewhat fills the screen
2630- width: Math.max(3, applicationManager.count) * spreadView.tileDistance + (spreadView.width - spreadView.tileDistance) * 1.5
2631+ width: Math.max(3, root.applicationManager.count) * spreadView.tileDistance + (spreadView.width - spreadView.tileDistance) * 1.5
2632 height: parent.height
2633 Behavior on width {
2634 enabled: spreadView.closingIndex >= 0
2635@@ -303,7 +393,7 @@
2636 Repeater {
2637 id: spreadRepeater
2638 objectName: "spreadRepeater"
2639- model: applicationManager
2640+ model: root.applicationManager
2641 delegate: TransformedSpreadDelegate {
2642 id: appDelegate
2643 objectName: "appDelegate" + index
2644@@ -318,11 +408,10 @@
2645 selected: spreadView.selectedIndex == index
2646 otherSelected: spreadView.selectedIndex >= 0 && !selected
2647 interactive: !spreadView.interactive && spreadView.phase === 0
2648- && spreadView.shiftedContentX === 0 && root.interactive && isFocused
2649+ && priv.fullyShowingFocusedApp && root.interactive && isFocused
2650 swipeToCloseEnabled: spreadView.interactive && root.interactive && !snapAnimation.running
2651 maximizedAppTopMargin: root.maximizedAppTopMargin
2652- dropShadow: spreadView.active ||
2653- (priv.focusedAppDelegate && priv.focusedAppDelegate.x !== 0)
2654+ dropShadow: spreadView.active || priv.focusedAppDelegateIsDislocated
2655 focusFirstApp: root.focusFirstApp
2656
2657 readonly property bool isDash: model.appId == "unity8-dash"
2658@@ -345,7 +434,7 @@
2659 return spreadView.width + spreadIndex * spreadView.tileDistance;
2660 }
2661
2662- application: applicationManager.get(index)
2663+ application: root.applicationManager.get(index)
2664 closeable: !isDash
2665
2666 property real behavioredIndex: index
2667@@ -361,18 +450,16 @@
2668 }
2669 }
2670
2671+ property var xBehavior: xBehavior
2672 Behavior on x {
2673+ id: xBehavior
2674 enabled: root.spreadEnabled &&
2675 !spreadView.active &&
2676 !snapAnimation.running &&
2677- priv.animateX
2678+ priv.animateX &&
2679+ !root.beingResized
2680 UbuntuNumberAnimation {
2681 duration: UbuntuAnimation.BriskDuration
2682- onRunningChanged: {
2683- if (!running && root.inverseProgress == 0) {
2684- spreadView.focusChanging = false;
2685- }
2686- }
2687 }
2688 }
2689
2690@@ -412,22 +499,21 @@
2691 }
2692
2693 // Hiding tiles when their progress is negative or reached the maximum
2694- visible: (progress >= 0 && progress < 1.7) ||
2695- (isDash && priv.focusedAppDelegate.x !== 0)
2696-
2697- Binding {
2698- target: appDelegate
2699- property: "orientation"
2700- when: appDelegate.interactive
2701- value: root.orientation
2702- }
2703+ visible: (progress >= 0 && progress < 1.7)
2704+ || (isDash && priv.focusedAppDelegateIsDislocated)
2705+
2706+
2707+ shellOrientationAngle: root.shellOrientationAngle
2708+ shellOrientation: root.shellOrientation
2709+ shellPrimaryOrientation: root.shellPrimaryOrientation
2710+ nativeOrientation: root.nativeOrientation
2711
2712 onClicked: {
2713 if (root.altTabEnabled && spreadView.phase == 2) {
2714- if (applicationManager.focusedApplicationId == applicationManager.get(index).appId) {
2715+ if (root.applicationManager.focusedApplicationId == root.applicationManager.get(index).appId) {
2716 spreadView.snapTo(index);
2717 } else {
2718- applicationManager.requestFocusApplication(applicationManager.get(index).appId);
2719+ root.applicationManager.requestFocusApplication(root.applicationManager.get(index).appId);
2720 }
2721 }
2722 }
2723@@ -442,7 +528,20 @@
2724
2725 onClosed: {
2726 spreadView.closingIndex = index;
2727- applicationManager.stopApplication(applicationManager.get(index).appId);
2728+ root.applicationManager.stopApplication(root.applicationManager.get(index).appId);
2729+ }
2730+
2731+ Binding {
2732+ target: root
2733+ when: index == 0
2734+ property: "mainAppWindowOrientationAngle"
2735+ value: appWindowOrientationAngle
2736+ }
2737+ Binding {
2738+ target: priv
2739+ when: index == 0
2740+ property: "focusedAppOrientationChangesEnabled"
2741+ value: orientationChangesEnabled
2742 }
2743 }
2744 }
2745
2746=== modified file 'qml/Stages/SessionContainer.qml'
2747--- qml/Stages/SessionContainer.qml 2015-01-28 12:59:21 +0000
2748+++ qml/Stages/SessionContainer.qml 2015-05-21 17:30:56 +0000
2749@@ -1,5 +1,5 @@
2750 /*
2751- * Copyright 2014 Canonical Ltd.
2752+ * Copyright 2014-2015 Canonical Ltd.
2753 *
2754 * This program is free software; you can redistribute it and/or modify
2755 * it under the terms of the GNU Lesser General Public License as published by
2756@@ -24,14 +24,13 @@
2757 readonly property var childSessions: session ? session.childSessions : null
2758 readonly property alias surface: _surfaceContainer.surface
2759 property alias interactive: _surfaceContainer.interactive
2760- property int orientation
2761+ property alias surfaceOrientationAngle: _surfaceContainer.surfaceOrientationAngle
2762
2763 readonly property alias surfaceContainer: _surfaceContainer
2764 SurfaceContainer {
2765 id: _surfaceContainer
2766 anchors.fill: parent
2767 surface: session ? session.surface : null
2768- orientation: root.orientation
2769 }
2770
2771 Repeater {
2772@@ -72,11 +71,6 @@
2773 target: item; when: item
2774 property: "height"; value: root.height
2775 }
2776-
2777- Binding {
2778- target: item; when: item
2779- property: "orientation"; value: root.orientation
2780- }
2781 }
2782 }
2783
2784
2785=== modified file 'qml/Stages/SpreadDelegate.qml'
2786--- qml/Stages/SpreadDelegate.qml 2015-01-28 12:59:21 +0000
2787+++ qml/Stages/SpreadDelegate.qml 2015-05-21 17:30:56 +0000
2788@@ -1,5 +1,5 @@
2789 /*
2790- * Copyright 2014 Canonical Ltd.
2791+ * Copyright 2014-2015 Canonical Ltd.
2792 *
2793 * This program is free software; you can redistribute it and/or modify
2794 * it under the terms of the GNU Lesser General Public License as published by
2795@@ -18,6 +18,7 @@
2796 */
2797
2798 import QtQuick 2.0
2799+import QtQuick.Window 2.0
2800 import Ubuntu.Components 1.1
2801 import "../Components"
2802
2803@@ -28,6 +29,9 @@
2804 readonly property bool dragged: dragArea.moving
2805 signal clicked()
2806 signal closed()
2807+ readonly property alias appWindowOrientationAngle: appWindowWithShadow.orientationAngle
2808+ readonly property alias appWindowRotation: appWindowWithShadow.rotation
2809+ readonly property alias orientationChangesEnabled: appWindow.orientationChangesEnabled
2810
2811 // to be set from outside
2812 property bool interactive: true
2813@@ -36,10 +40,54 @@
2814 property alias swipeToCloseEnabled: dragArea.enabled
2815 property bool closeable
2816 property alias application: appWindow.application
2817- property int orientation
2818+ property int shellOrientationAngle
2819+ property int shellOrientation
2820+ property int shellPrimaryOrientation
2821+ property int nativeOrientation
2822+
2823+ function matchShellOrientation() {
2824+ if (!root.application)
2825+ return;
2826+ appWindowWithShadow.orientationAngle = root.shellOrientationAngle;
2827+ }
2828+
2829+ function animateToShellOrientation() {
2830+ if (!root.application)
2831+ return;
2832+
2833+ if (root.application.rotatesWindowContents) {
2834+ appWindowWithShadow.orientationAngle = root.shellOrientationAngle;
2835+ } else {
2836+ orientationChangeAnimation.start();
2837+ }
2838+ }
2839+
2840+ OrientationChangeAnimation {
2841+ id: orientationChangeAnimation
2842+ objectName: "orientationChangeAnimation"
2843+ spreadDelegate: root
2844+ background: background
2845+ window: appWindowWithShadow
2846+ screenshot: appWindowScreenshotWithShadow
2847+ }
2848+
2849+ QtObject {
2850+ id: priv
2851+ property bool startingUp: true
2852+ }
2853+
2854+ Component.onCompleted: { finishStartUpTimer.start(); }
2855+ Timer { id: finishStartUpTimer; interval: 400; onTriggered: priv.startingUp = false }
2856+
2857+ Rectangle {
2858+ id: background
2859+ color: "black"
2860+ anchors.fill: parent
2861+ visible: false
2862+ }
2863
2864 Item {
2865- objectName: "appWindowWithShadow"
2866+ objectName: "displacedAppWindowWithShadow"
2867
2868 readonly property real limit: root.height / 4
2869
2870@@ -52,27 +100,220 @@
2871 return k * (1 - Math.pow((k - 1) / k, distance))
2872 }
2873
2874- BorderImage {
2875- anchors {
2876- fill: appWindow
2877- margins: -units.gu(2)
2878- }
2879- source: "graphics/dropshadow2gu.sci"
2880- opacity: root.dropShadow ? .3 : 0
2881- Behavior on opacity { UbuntuNumberAnimation {} }
2882- }
2883-
2884- ApplicationWindow {
2885- id: appWindow
2886- objectName: application ? "appWindow_" + application.appId : "appWindow_null"
2887- focus: true
2888- anchors {
2889- fill: parent
2890- topMargin: appWindow.fullscreen ? 0 : maximizedAppTopMargin
2891- }
2892-
2893- interactive: root.interactive
2894- orientation: root.orientation
2895+ Item {
2896+ id: appWindowWithShadow
2897+ objectName: "appWindowWithShadow"
2898+
2899+ property int orientationAngle
2900+
2901+ property real transformRotationAngle: 0
2902+ property real transformOriginX
2903+ property real transformOriginY
2904+
2905+ property var window: appWindow
2906+
2907+ transform: Rotation {
2908+ origin.x: appWindowWithShadow.transformOriginX
2909+ origin.y: appWindowWithShadow.transformOriginY
2910+ axis { x: 0; y: 0; z: 1 }
2911+ angle: appWindowWithShadow.transformRotationAngle
2912+ }
2913+
2914+ state: {
2915+ if (priv.startingUp) {
2916+ return "startingUp";
2917+ } else if (root.application && root.application.rotatesWindowContents) {
2918+ return "counterRotate";
2919+ } else if (orientationChangeAnimation.running) {
2920+ return "animatingRotation";
2921+ } else {
2922+ return "keepSceneRotation";
2923+ }
2924+ }
2925+
2926+ // Ensures the given angle is in the form (0,90,180,270)
2927+ function normalizeAngle(angle) {
2928+ while (angle < 0) {
2929+ angle += 360;
2930+ }
2931+ return angle % 360;
2932+ }
2933+
2934+ states: [
2935+ // Sets the initial orientationAngle of the window, when it first slides into view
2936+ // (with the splash screen likely being displayed). At that point we just try to
2937+ // match shell's current orientation. We need a bit of time in this state as the
2938+ // information we need to decide orientationAngle may take a few cycles to
2939+ // be set.
2940+ State {
2941+ name: "startingUp"
2942+ PropertyChanges {
2943+ target: appWindowWithShadow
2944+ restoreEntryValues: false
2945+ orientationAngle: {
2946+ if (!root.application || root.application.rotatesWindowContents) {
2947+ return 0;
2948+ }
2949+ var supportedOrientations = root.application.supportedOrientations;
2950+
2951+ if (supportedOrientations === Qt.PrimaryOrientation) {
2952+ supportedOrientations = root.shellPrimaryOrientation;
2953+ }
2954+
2955+ // If it doesn't support shell's current orientation
2956+ // then simply pick some arbitraty one that it does support
2957+ var chosenOrientation = 0;
2958+ if (supportedOrientations & root.shellOrientation) {
2959+ chosenOrientation = root.shellOrientation;
2960+ } else if (supportedOrientations & Qt.PortraitOrientation) {
2961+ chosenOrientation = Qt.PortraitOrientation;
2962+ } else if (supportedOrientations & Qt.LandscapeOrientation) {
2963+ chosenOrientation = Qt.LandscapeOrientation;
2964+ } else if (supportedOrientations & Qt.InvertedPortraitOrientation) {
2965+ chosenOrientation = Qt.InvertedPortraitOrientation;
2966+ } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) {
2967+ chosenOrientation = Qt.InvertedLandscapeOrientation;
2968+ } else {
2969+ chosenOrientation = root.shellPrimaryOrientation;
2970+ }
2971+
2972+ return Screen.angleBetween(root.nativeOrientation, chosenOrientation);
2973+ }
2974+
2975+ rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle)
2976+ width: {
2977+ if (rotation == 0 || rotation == 180) {
2978+ return root.width;
2979+ } else {
2980+ return root.height;
2981+ }
2982+ }
2983+ height: {
2984+ if (rotation == 0 || rotation == 180)
2985+ return root.height;
2986+ else
2987+ return root.width;
2988+ }
2989+ }
2990+ },
2991+ // In this state we stick to our currently set orientationAngle, which may change only due
2992+ // to calls made to matchShellOrientation() or animateToShellOrientation()
2993+ State {
2994+ id: keepSceneRotationState
2995+ name: "keepSceneRotation"
2996+
2997+ StateChangeScript { script: {
2998+ // break binding
2999+ appWindowWithShadow.orientationAngle = appWindowWithShadow.orientationAngle;
3000+ } }
3001+ PropertyChanges {
3002+ target: appWindowWithShadow
3003+ restoreEntryValues: false
3004+ rotation: normalizeAngle(appWindowWithShadow.orientationAngle - root.shellOrientationAngle)
3005+ width: {
3006+ if (rotation == 0 || rotation == 180) {
3007+ return root.width;
3008+ } else {
3009+ return root.height;
3010+ }
3011+ }
3012+ height: {
3013+ if (rotation == 0 || rotation == 180)
3014+ return root.height;
3015+ else
3016+ return root.width;
3017+ }
3018+ }
3019+ },
3020+ // In this state we counteract any shell rotation so that the window, in scene coordinates,
3021+ // remains unrotated.
3022+ State {
3023+ name: "counterRotate"
3024+ StateChangeScript { script: {
3025+ // break binding
3026+ appWindowWithShadow.orientationAngle = appWindowWithShadow.orientationAngle;
3027+ } }
3028+ PropertyChanges {
3029+ target: appWindowWithShadow
3030+ width: root.shellOrientationAngle == 0 || root.shellOrientationAngle == 180 ? root.width : root.height
3031+ height: root.shellOrientationAngle == 0 || root.shellOrientationAngle == 180 ? root.height : root.width
3032+ rotation: normalizeAngle(-root.shellOrientationAngle)
3033+ }
3034+ PropertyChanges {
3035+ target: appWindow
3036+ surfaceOrientationAngle: orientationAngle
3037+ }
3038+ },
3039+ State {
3040+ name: "animatingRotation"
3041+ }
3042+ ]
3043+
3044+ x: (parent.width - width) / 2
3045+ y: (parent.height - height) / 2
3046+
3047+ BorderImage {
3048+ anchors {
3049+ fill: appWindow
3050+ margins: -units.gu(2)
3051+ }
3052+ source: "graphics/dropshadow2gu.sci"
3053+ opacity: root.dropShadow ? .3 : 0
3054+ Behavior on opacity { UbuntuNumberAnimation {} }
3055+ }
3056+
3057+ ApplicationWindow {
3058+ id: appWindow
3059+ objectName: application ? "appWindow_" + application.appId : "appWindow_null"
3060+ focus: true
3061+ anchors {
3062+ fill: parent
3063+ topMargin: appWindow.fullscreen || application.rotatesWindowContents
3064+ ? 0 : maximizedAppTopMargin
3065+ }
3066+
3067+ interactive: root.interactive
3068+ }
3069+ }
3070+ }
3071+
3072+ Item {
3073+ // mimics appWindowWithShadow. Do the positioning of screenshots of non-fullscreen
3074+ // app windows
3075+ id: appWindowScreenshotWithShadow
3076+ visible: false
3077+
3078+ property real transformRotationAngle: 0
3079+ property real transformOriginX
3080+ property real transformOriginY
3081+
3082+ transform: Rotation {
3083+ origin.x: appWindowScreenshotWithShadow.transformOriginX
3084+ origin.y: appWindowScreenshotWithShadow.transformOriginY
3085+ axis { x: 0; y: 0; z: 1 }
3086+ angle: appWindowScreenshotWithShadow.transformRotationAngle
3087+ }
3088+
3089+ property var window: appWindowScreenshot
3090+
3091+ function take() {
3092+ // Format: "image://application/$APP_ID/$CURRENT_TIME_MS"
3093+ // eg: "image://application/calculator-app/123456"
3094+ var timeMs = new Date().getTime();
3095+ appWindowScreenshot.source = "image://application/" + root.application.appId + "/" + timeMs;
3096+ }
3097+ function discard() {
3098+ appWindowScreenshot.source = "";
3099+ }
3100+
3101+ Image {
3102+ id: appWindowScreenshot
3103+ source: ""
3104+
3105+ anchors.fill: parent
3106+
3107+ sourceSize.width: width
3108+ sourceSize.height: height
3109 }
3110 }
3111
3112
3113=== modified file 'qml/Stages/SurfaceContainer.qml'
3114--- qml/Stages/SurfaceContainer.qml 2015-03-12 18:55:52 +0000
3115+++ qml/Stages/SurfaceContainer.qml 2015-05-21 17:30:56 +0000
3116@@ -24,8 +24,8 @@
3117 objectName: "surfaceContainer"
3118 property Item surface: null
3119 property bool hadSurface: false
3120- property int orientation
3121 property bool interactive
3122+ property int surfaceOrientationAngle: 0
3123
3124 onSurfaceChanged: {
3125 if (surface) {
3126@@ -39,10 +39,10 @@
3127 }
3128 }
3129 Binding { target: surface; property: "anchors.fill"; value: root }
3130- Binding { target: surface; property: "orientation"; value: root.orientation }
3131 Binding { target: surface; property: "z"; value: 1 }
3132 Binding { target: surface; property: "enabled"; value: root.interactive; when: surface }
3133 Binding { target: surface; property: "antialiasing"; value: !root.interactive; when: surface }
3134+ Binding { target: surface; property: "orientationAngle"; value: root.surfaceOrientationAngle; when: surface }
3135
3136 InputWatcher {
3137 target: root.surface
3138
3139=== modified file 'qml/Stages/TabletStage.qml'
3140--- qml/Stages/TabletStage.qml 2015-05-18 23:03:25 +0000
3141+++ qml/Stages/TabletStage.qml 2015-05-21 17:30:56 +0000
3142@@ -1,5 +1,5 @@
3143 /*
3144- * Copyright (C) 2014 Canonical, Ltd.
3145+ * Copyright (C) 2014-2015 Canonical, Ltd.
3146 *
3147 * This program is free software; you can redistribute it and/or modify
3148 * it under the terms of the GNU General Public License as published by
3149@@ -28,13 +28,79 @@
3150 color: "#111111"
3151
3152 // Controls to be set from outside
3153- property bool shown: false
3154- property bool moving: false
3155 property int dragAreaWidth
3156 property real maximizedAppTopMargin
3157 property bool interactive
3158+ property alias beingResized: spreadView.beingResized
3159+
3160+ property bool spreadEnabled: true // If false, animations and right edge will be disabled
3161+
3162 property real inverseProgress: 0 // This is the progress for left edge drags, in pixels.
3163- property int orientation: Qt.PortraitOrientation
3164+ property int shellOrientationAngle: 0
3165+ property int shellOrientation
3166+ property int shellPrimaryOrientation
3167+ property int nativeOrientation
3168+ property real nativeWidth
3169+ property real nativeHeight
3170+ function updateFocusedAppOrientation() {
3171+ var mainStageAppIndex = priv.indexOf(priv.mainStageAppId);
3172+ if (mainStageAppIndex >= 0 && mainStageAppIndex < spreadRepeater.count) {
3173+ spreadRepeater.itemAt(mainStageAppIndex).matchShellOrientation();
3174+ }
3175+
3176+ for (var i = 0; i < spreadRepeater.count; ++i) {
3177+
3178+ if (i === mainStageAppIndex) {
3179+ continue;
3180+ }
3181+
3182+ var spreadDelegate = spreadRepeater.itemAt(i);
3183+
3184+ var delta = spreadDelegate.appWindowOrientationAngle - root.shellOrientationAngle;
3185+ if (delta < 0) { delta += 360; }
3186+ delta = delta % 360;
3187+
3188+ var supportedOrientations = spreadDelegate.application.supportedOrientations;
3189+ if (supportedOrientations === Qt.PrimaryOrientation) {
3190+ supportedOrientations = spreadDelegate.shellPrimaryOrientation;
3191+ }
3192+
3193+ if (delta === 180 && (supportedOrientations & spreadDelegate.shellOrientation)) {
3194+ spreadDelegate.matchShellOrientation();
3195+ }
3196+ }
3197+ }
3198+ function updateFocusedAppOrientationAnimated() {
3199+ var mainStageAppIndex = priv.indexOf(priv.mainStageAppId);
3200+ if (mainStageAppIndex >= 0 && mainStageAppIndex < spreadRepeater.count) {
3201+ spreadRepeater.itemAt(mainStageAppIndex).animateToShellOrientation();
3202+ }
3203+
3204+ if (priv.sideStageAppId) {
3205+ var sideStageAppIndex = priv.indexOf(priv.sideStageAppId);
3206+ if (sideStageAppIndex >= 0 && sideStageAppIndex < spreadRepeater.count) {
3207+ spreadRepeater.itemAt(sideStageAppIndex).matchShellOrientation();
3208+ }
3209+ }
3210+ }
3211+
3212+ // To be read from outside
3213+ property var mainApp: null
3214+ property int mainAppWindowOrientationAngle: 0
3215+ readonly property bool orientationChangesEnabled: priv.mainAppOrientationChangesEnabled
3216+
3217+ onWidthChanged: {
3218+ spreadView.selectedIndex = -1;
3219+ spreadView.phase = 0;
3220+ spreadView.contentX = -spreadView.shift;
3221+ }
3222+
3223+ onShellOrientationChanged: {
3224+ if (shellOrientation == Qt.PortraitOrientation || shellOrientation == Qt.InvertedPortraitOrientation) {
3225+ ApplicationManager.focusApplication(priv.mainStageAppId);
3226+ priv.sideStageAppId = "";
3227+ }
3228+ }
3229
3230 onInverseProgressChanged: {
3231 // This can't be a simple binding because that would be triggered after this handler
3232@@ -59,6 +125,13 @@
3233 }
3234
3235 property string oldFocusedAppId: ""
3236+ property bool mainAppOrientationChangesEnabled: false
3237+
3238+ property real landscapeHeight: root.nativeOrientation == Qt.LandscapeOrientation ?
3239+ root.nativeHeight : root.nativeWidth
3240+
3241+ property bool shellIsLandscape: root.shellOrientation === Qt.LandscapeOrientation
3242+ || root.shellOrientation === Qt.InvertedLandscapeOrientation
3243
3244 property string mainStageAppId
3245 property string sideStageAppId
3246@@ -76,6 +149,7 @@
3247 priv.sideStageAppId = focusedAppId;
3248 } else {
3249 priv.mainStageAppId = focusedAppId;
3250+ root.mainApp = focusedApp;
3251 }
3252 }
3253
3254@@ -166,6 +240,7 @@
3255
3256 Flickable {
3257 id: spreadView
3258+ objectName: "spreadView"
3259 anchors.fill: parent
3260 interactive: (spreadDragArea.dragging || phase > 1) && draggedDelegateCount === 0
3261 contentWidth: spreadRow.width - shift
3262@@ -214,7 +289,25 @@
3263 property int draggedDelegateCount: 0
3264 property int closingIndex: -1
3265
3266+ // FIXME: Workaround Flickable's not keepping its contentX still when resized
3267+ onContentXChanged: { forceItToRemainStillIfBeingResized(); }
3268+ onShiftChanged: { forceItToRemainStillIfBeingResized(); }
3269+ function forceItToRemainStillIfBeingResized() {
3270+ if (root.beingResized && contentX != -shift) {
3271+ contentX = -shift;
3272+ }
3273+ }
3274+
3275 property bool animateX: true
3276+ property bool beingResized: false
3277+ onBeingResizedChanged: {
3278+ if (beingResized) {
3279+ // Brace yourselves for impact!
3280+ selectedIndex = -1;
3281+ phase = 0;
3282+ contentX = -shift;
3283+ }
3284+ }
3285
3286 property bool sideStageDragging: sideStageDragHandle.dragging
3287 property real sideStageDragProgress: sideStageDragHandle.progress
3288@@ -253,7 +346,6 @@
3289 case "overlay":
3290 return 1;
3291 }
3292- print("Unhandled nextInStack case! This shouldn't happen any more when the Dash is an app!");
3293 return -1;
3294 }
3295 property int nextZInStack: indexToZIndex(nextInStack)
3296@@ -289,6 +381,10 @@
3297 }
3298
3299 onShiftedContentXChanged: {
3300+ if (root.beingResized) {
3301+ // Flickabe.contentX wiggles during resizes. Don't react to it.
3302+ return;
3303+ }
3304 if (spreadView.phase == 0 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker2) {
3305 spreadView.phase = 1;
3306 } else if (spreadView.phase == 1 && spreadView.shiftedContentX > spreadView.width * spreadView.positionMarker4) {
3307@@ -398,8 +494,8 @@
3308 MouseArea {
3309 id: spreadRow
3310 x: spreadView.contentX
3311+ width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance)
3312 height: root.height
3313- width: spreadView.width + Math.max(spreadView.width, ApplicationManager.count * spreadView.tileDistance)
3314
3315 onClicked: {
3316 spreadView.snapTo(0);
3317@@ -408,8 +504,9 @@
3318 Rectangle {
3319 id: sideStageBackground
3320 color: "black"
3321- anchors.fill: parent
3322- anchors.leftMargin: spreadView.width - (1 - sideStageDragHandle.progress) * spreadView.sideStageWidth
3323+ width: spreadView.sideStageWidth * (1 - sideStageDragHandle.progress)
3324+ height: priv.landscapeHeight
3325+ x: spreadView.width - width
3326 z: spreadView.indexToZIndex(priv.indexOf(priv.sideStageAppId))
3327 opacity: spreadView.phase == 0 ? 1 : 0
3328 Behavior on opacity { UbuntuNumberAnimation {} }
3329@@ -417,8 +514,10 @@
3330
3331 Item {
3332 id: sideStageDragHandle
3333- anchors { top: parent.top; bottom: parent.bottom; left: parent.left; leftMargin: spreadView.width - spreadView.sideStageWidth - width }
3334+ anchors.right: sideStageBackground.left
3335+ anchors.top: sideStageBackground.top
3336 width: units.gu(2)
3337+ height: priv.landscapeHeight
3338 z: sideStageBackground.z
3339 opacity: spreadView.phase <= 0 && spreadView.sideStageVisible ? 1 : 0
3340 property real progress: 0
3341@@ -437,7 +536,6 @@
3342
3343 Image {
3344 anchors.centerIn: parent
3345- anchors.horizontalCenterOffset: parent.progress * spreadView.sideStageWidth - (width - parent.width) / 2
3346 width: sideStageDragHandleMouseArea.pressed ? parent.width * 2 : parent.width
3347 height: parent.height
3348 source: "graphics/sidestage_handle@20.png"
3349@@ -450,16 +548,19 @@
3350 enabled: spreadView.shiftedContentX == 0
3351 property int startX
3352 property var gesturePoints: new Array()
3353+ property real totalDiff
3354
3355 onPressed: {
3356 gesturePoints = [];
3357 startX = mouseX;
3358+ totalDiff = 0.0;
3359 sideStageDragHandle.progress = 0;
3360 sideStageDragHandle.dragging = true;
3361 }
3362 onMouseXChanged: {
3363+ totalDiff += mouseX - startX;
3364 if (priv.mainStageAppId) {
3365- sideStageDragHandle.progress = Math.max(0, (-startX + mouseX) / spreadView.sideStageWidth);
3366+ sideStageDragHandle.progress = Math.max(0, totalDiff / spreadView.sideStageWidth);
3367 }
3368 gesturePoints.push(mouseX);
3369 }
3370@@ -488,14 +589,27 @@
3371
3372 Repeater {
3373 id: spreadRepeater
3374+ objectName: "spreadRepeater"
3375 model: ApplicationManager
3376
3377 delegate: TransformedTabletSpreadDelegate {
3378 id: spreadTile
3379 objectName: model.appId ? "tabletSpreadDelegate_" + model.appId
3380 : "tabletSpreadDelegate_null";
3381- height: spreadView.height
3382- width: model.stage == ApplicationInfoInterface.MainStage ? spreadView.width : spreadView.sideStageWidth
3383+ width: {
3384+ if (wantsMainStage) {
3385+ return spreadView.width;
3386+ } else {
3387+ return spreadView.sideStageWidth;
3388+ }
3389+ }
3390+ height: {
3391+ if (wantsMainStage) {
3392+ return spreadView.height;
3393+ } else {
3394+ return priv.landscapeHeight;
3395+ }
3396+ }
3397 active: model.appId == priv.mainStageAppId || model.appId == priv.sideStageAppId
3398 zIndex: spreadView.indexToZIndex(index)
3399 selected: spreadView.selectedIndex == index
3400@@ -508,6 +622,8 @@
3401 application: ApplicationManager.get(index)
3402 closeable: !isDash
3403
3404+ readonly property bool wantsMainStage: model.stage == ApplicationInfoInterface.MainStage
3405+
3406 readonly property bool isDash: model.appId == "unity8-dash"
3407
3408 // FIXME: A regular binding doesn't update any more after closing an app.
3409@@ -559,12 +675,11 @@
3410 return progress;
3411 }
3412
3413- Binding {
3414- target: spreadTile
3415- property: "orientation"
3416- when: spreadTile.interactive
3417- value: root.orientation
3418- }
3419+ shellOrientationAngle: wantsMainStage ? root.shellOrientationAngle : 0
3420+ shellOrientation: wantsMainStage ? root.shellOrientation : Qt.PortraitOrientation
3421+ shellPrimaryOrientation: wantsMainStage ? root.shellPrimaryOrientation : Qt.PortraitOrientation
3422+ nativeOrientation: wantsMainStage ? root.nativeOrientation : Qt.PortraitOrientation
3423+
3424
3425 onClicked: {
3426 if (spreadView.phase == 2) {
3427@@ -585,6 +700,19 @@
3428 ApplicationManager.stopApplication(ApplicationManager.get(index).appId);
3429 }
3430
3431+ Binding {
3432+ target: root
3433+ when: model.appId == priv.mainStageAppId
3434+ property: "mainAppWindowOrientationAngle"
3435+ value: appWindowOrientationAngle
3436+ }
3437+ Binding {
3438+ target: priv
3439+ when: model.appId == priv.mainStageAppId
3440+ property: "mainAppOrientationChangesEnabled"
3441+ value: orientationChangesEnabled
3442+ }
3443+
3444 EasingCurve {
3445 id: snappingCurve
3446 type: EasingCurve.Linear
3447@@ -598,9 +726,11 @@
3448
3449 DirectionalDragArea {
3450 id: spreadDragArea
3451+ objectName: "spreadDragArea"
3452 anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
3453 width: root.dragAreaWidth
3454 direction: Direction.Leftwards
3455+ enabled: (spreadView.phase != 2 && root.spreadEnabled) || dragging
3456
3457 property var gesturePoints: new Array()
3458
3459
3460=== modified file 'qml/Stages/TransformedSpreadDelegate.qml'
3461--- qml/Stages/TransformedSpreadDelegate.qml 2015-01-06 14:46:52 +0000
3462+++ qml/Stages/TransformedSpreadDelegate.qml 2015-05-21 17:30:56 +0000
3463@@ -298,7 +298,6 @@
3464
3465 return easingCurve.value;
3466 }
3467-
3468 }
3469
3470 transform: [
3471@@ -307,16 +306,61 @@
3472 axis { x: 0; y: 1; z: 0 }
3473 angle: priv.angle
3474 },
3475+
3476+ // The next two transformations are to ensure that fullscreen and rotated
3477+ // windows all have the same size and position as an unrotated (0 degrees)
3478+ // non-fullscreen window when they're stacked on top of each other on the
3479+ // far left of the spread.
3480+ Translate {
3481+ y: !fullscreen && appWindowRotation === 180
3482+ ? priv.topMarginProgress * maximizedAppTopMargin
3483+ : 0
3484+ },
3485+ Scale {
3486+ origin {
3487+ x: appWindowRotation === 270 ? spreadView.width : 0
3488+ y: spreadView.height
3489+ }
3490+
3491+ xScale: {
3492+ switch (appWindowRotation) {
3493+ case 90:
3494+ case 270:
3495+ if (fullscreen) {
3496+ return 1;
3497+ } else {
3498+ return 1 + priv.topMarginProgress * maximizedAppTopMargin / spreadView.width;
3499+ }
3500+ break;
3501+ default:
3502+ return 1;
3503+ }
3504+ }
3505+
3506+ yScale: {
3507+ switch (appWindowRotation) {
3508+ case 0:
3509+ if (fullscreen) {
3510+ return 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height;
3511+ } else {
3512+ return 1;
3513+ }
3514+ break;
3515+ case 90:
3516+ case 270:
3517+ return 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height;
3518+ break;
3519+ default:
3520+ return 1;
3521+ }
3522+ }
3523+ },
3524+
3525 Scale {
3526 origin { x: 0; y: spreadView.height / 2 }
3527 xScale: priv.scale
3528 yScale: xScale
3529 },
3530- Scale {
3531- origin { x: 0; y: (spreadView.height * priv.scale) + maximizedAppTopMargin * 3 }
3532- xScale: 1
3533- yScale: fullscreen ? 1 - priv.topMarginProgress * maximizedAppTopMargin / spreadView.height : 1
3534- },
3535 Translate {
3536 x: priv.xTranslate
3537 }
3538
3539=== modified file 'qml/Stages/TransformedTabletSpreadDelegate.qml'
3540--- qml/Stages/TransformedTabletSpreadDelegate.qml 2015-02-02 16:23:34 +0000
3541+++ qml/Stages/TransformedTabletSpreadDelegate.qml 2015-05-21 17:30:56 +0000
3542@@ -50,7 +50,9 @@
3543 property int dragOffset: 0
3544
3545 dropShadow: spreadView.active ||
3546- (active && model.stage == ApplicationInfoInterface.MainStage && priv.xTranslate != 0)
3547+ (active
3548+ && (model.stage == ApplicationInfoInterface.MainStage || !priv.shellIsLandscape)
3549+ && priv.xTranslate != 0)
3550
3551 onSelectedChanged: {
3552 if (selected) {
3553@@ -139,7 +141,8 @@
3554 !snapAnimation.running &&
3555 model.appId !== "unity8-dash" &&
3556 !spreadView.sideStageDragging &&
3557- spreadView.animateX
3558+ spreadView.animateX &&
3559+ !spreadView.beingResized
3560 UbuntuNumberAnimation {
3561 duration: UbuntuAnimation.FastDuration
3562 }
3563
3564=== modified file 'run.sh'
3565--- run.sh 2015-03-11 08:07:31 +0000
3566+++ run.sh 2015-05-21 17:30:56 +0000
3567@@ -44,7 +44,7 @@
3568 export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/builddir/plugins/LightDM/liblightdm
3569 fi
3570
3571-QML_PHONE_SHELL_ARGS=""
3572+QML_PHONE_SHELL_ARGS="-windowgeometry=40gux68gu -devicename=mako"
3573 if $MOUSE_TOUCH; then
3574 QML_PHONE_SHELL_ARGS="$QML_PHONE_SHELL_ARGS -mousetouch"
3575 fi
3576
3577=== added file 'src/ApplicationArguments.cpp'
3578--- src/ApplicationArguments.cpp 1970-01-01 00:00:00 +0000
3579+++ src/ApplicationArguments.cpp 2015-05-21 17:30:56 +0000
3580@@ -0,0 +1,22 @@
3581+/*
3582+ * Copyright (C) 2015 Canonical, Ltd.
3583+ *
3584+ * This program is free software; you can redistribute it and/or modify
3585+ * it under the terms of the GNU General Public License as published by
3586+ * the Free Software Foundation; version 3.
3587+ *
3588+ * This program is distributed in the hope that it will be useful,
3589+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3590+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3591+ * GNU General Public License for more details.
3592+ *
3593+ * You should have received a copy of the GNU General Public License
3594+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3595+ */
3596+
3597+#include "ApplicationArguments.h"
3598+
3599+ApplicationArguments::ApplicationArguments(QObject *parent)
3600+ : QObject(parent)
3601+{
3602+}
3603
3604=== modified file 'src/ApplicationArguments.h'
3605--- src/ApplicationArguments.h 2015-04-15 15:20:24 +0000
3606+++ src/ApplicationArguments.h 2015-05-21 17:30:56 +0000
3607@@ -1,5 +1,5 @@
3608 /*
3609- * Copyright (C) 2013 Canonical, Ltd.
3610+ * Copyright (C) 2013,2015 Canonical, Ltd.
3611 *
3612 * This program is free software; you can redistribute it and/or modify
3613 * it under the terms of the GNU General Public License as published by
3614@@ -13,7 +13,6 @@
3615 * You should have received a copy of the GNU General Public License
3616 * along with this program. If not, see <http://www.gnu.org/licenses/>.
3617 *
3618- * Authored by: Nick Dedekind <nick.dedekind@canonical.com>
3619 */
3620
3621
3622@@ -22,23 +21,20 @@
3623
3624 #include <QObject>
3625 #include <QSize>
3626-#include <QStringList>
3627+#include <QString>
3628
3629 class ApplicationArguments : public QObject
3630 {
3631 Q_OBJECT
3632+ Q_PROPERTY(QString deviceName READ deviceName CONSTANT)
3633 public:
3634- // Not exposed to the app as setSize isn't invokable
3635- void setSize(const QSize &size) {
3636- m_size = size;
3637- }
3638+ ApplicationArguments(QObject *parent = nullptr);
3639
3640- Q_INVOKABLE bool hasGeometry() const { return m_size.isValid(); }
3641- Q_INVOKABLE int width() const { return m_size.width(); }
3642- Q_INVOKABLE int height() const { return m_size.height(); }
3643+ void setDeviceName(QString deviceName) { m_deviceName = deviceName; }
3644+ QString deviceName() const { return m_deviceName; }
3645
3646 private:
3647- QSize m_size;
3648+ QString m_deviceName;
3649 };
3650
3651 #endif // APPLICATION_ARGUMENTS_H
3652
3653=== modified file 'src/CMakeLists.txt'
3654--- src/CMakeLists.txt 2015-04-14 14:11:43 +0000
3655+++ src/CMakeLists.txt 2015-05-21 17:30:56 +0000
3656@@ -17,7 +17,7 @@
3657 )
3658
3659 add_executable(${SHELL_APP}
3660- ApplicationArguments.h
3661+ ApplicationArguments.cpp
3662 main.cpp
3663 MouseTouchAdaptor.cpp
3664 CachingNetworkManagerFactory.cpp
3665@@ -26,13 +26,12 @@
3666 )
3667
3668 qt5_use_modules(${SHELL_APP} Gui Qml Quick Test)
3669-pkg_check_modules(XCB REQUIRED xcb)
3670-
3671-if (NOT "${XCB_INCLUDE_DIRS}" STREQUAL "")
3672- set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${XCB_INCLUDE_DIRS})
3673-
3674- target_link_libraries(${SHELL_APP} ${XCB_LDFLAGS})
3675+
3676+pkg_check_modules(NEEDED_LIBS REQUIRED xcb libandroid-properties)
3677+if (NOT "${NEEDED_LIBS_INCLUDE_DIRS}" STREQUAL "")
3678+ set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${NEEDED_LIBS_INCLUDE_DIRS})
3679 endif()
3680+target_link_libraries(${SHELL_APP} ${NEEDED_LIBS_LDFLAGS})
3681
3682 target_link_libraries(${SHELL_APP} UbuntuGestures connectivity-qt1)
3683
3684
3685=== modified file 'src/Dash/CMakeLists.txt'
3686--- src/Dash/CMakeLists.txt 2014-10-27 09:40:01 +0000
3687+++ src/Dash/CMakeLists.txt 2015-05-21 17:30:56 +0000
3688@@ -1,6 +1,6 @@
3689 set(DASH_SRCS
3690 main.cpp
3691- ../ApplicationArguments.h
3692+ ../ApplicationArguments.cpp
3693 ../MouseTouchAdaptor.cpp
3694 ../CachingNetworkManagerFactory.cpp
3695 )
3696@@ -9,6 +9,12 @@
3697
3698 qt5_use_modules(unity8-dash Gui Qml Quick Test)
3699
3700+pkg_check_modules(NEEDED_LIBS REQUIRED xcb libandroid-properties)
3701+if (NOT "${NEEDED_LIBS_INCLUDE_DIRS}" STREQUAL "")
3702+ set_target_properties(unity8-dash PROPERTIES INCLUDE_DIRECTORIES ${NEEDED_LIBS_INCLUDE_DIRS})
3703+endif()
3704+target_link_libraries(unity8-dash ${NEEDED_LIBS_LDFLAGS})
3705+
3706 # For it to find libUbuntuGestures.so, needed by Ubuntu.Gestures QML module.
3707 set_target_properties(unity8-dash PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}")
3708
3709
3710=== modified file 'src/Dash/main.cpp'
3711--- src/Dash/main.cpp 2015-05-11 09:50:47 +0000
3712+++ src/Dash/main.cpp 2015-05-21 17:30:56 +0000
3713@@ -58,12 +58,6 @@
3714 parser.process(*application);
3715
3716 ApplicationArguments qmlArgs;
3717- if (parser.isSet(windowGeometryOption) &&
3718- parser.value(windowGeometryOption).split('x').size() == 2)
3719- {
3720- QStringList geom = parser.value(windowGeometryOption).split('x');
3721- qmlArgs.setSize(QSize(geom.at(0).toInt(), geom.at(1).toInt()));
3722- }
3723
3724 if (getenv("QT_LOAD_TESTABILITY")) {
3725 QLibrary testLib(QLatin1String("qttestability"));
3726@@ -85,6 +79,18 @@
3727
3728 QQuickView* view = new QQuickView();
3729 view->setResizeMode(QQuickView::SizeRootObjectToView);
3730+
3731+ if (parser.isSet(windowGeometryOption) &&
3732+ parser.value(windowGeometryOption).split('x').size() == 2)
3733+ {
3734+ QStringList geom = parser.value(windowGeometryOption).split('x');
3735+ QSize windowSize(geom.at(0).toInt(), geom.at(1).toInt());
3736+ if (windowSize.isValid()) {
3737+ view->setWidth(windowSize.width());
3738+ view->setHeight(windowSize.height());
3739+ }
3740+ }
3741+
3742 view->setTitle("Scopes");
3743 view->rootContext()->setContextProperty("applicationArguments", &qmlArgs);
3744
3745
3746=== modified file 'src/UnityCommandLineParser.cpp'
3747--- src/UnityCommandLineParser.cpp 2015-04-14 14:11:43 +0000
3748+++ src/UnityCommandLineParser.cpp 2015-05-21 17:30:56 +0000
3749@@ -49,6 +49,10 @@
3750 "DISCOURAGED: Please set QT_LOAD_TESTABILITY instead.\nLoad the testability driver");
3751 parser.addOption(testabilityOption);
3752
3753+ QCommandLineOption devicenameOption(QStringList() << "devicename",
3754+ "Specify the device name instead of letting Unity 8 find it out", "devicename", "");
3755+ parser.addOption(devicenameOption);
3756+
3757 QCommandLineOption modeOption("mode",
3758 "Whether to run greeter and/or shell [full-greeter, full-shell, greeter, shell]",
3759 "mode", "full-greeter");
3760@@ -73,6 +77,7 @@
3761 m_hasFrameless = parser.isSet(framelessOption);
3762 m_hasMouseToTouch = parser.isSet(mousetouchOption);
3763 m_hasFullscreen = parser.isSet(fullscreenOption);
3764+ m_deviceName = parser.value(devicenameOption);
3765 resolveMode(parser, modeOption);
3766 }
3767
3768
3769=== modified file 'src/UnityCommandLineParser.h'
3770--- src/UnityCommandLineParser.h 2015-04-14 14:11:43 +0000
3771+++ src/UnityCommandLineParser.h 2015-05-21 17:30:56 +0000
3772@@ -30,6 +30,7 @@
3773 bool hasFrameless() const { return m_hasFrameless; }
3774 bool hasMouseToTouch() const { return m_hasMouseToTouch; }
3775 bool hasFullscreen() const { return m_hasFullscreen; }
3776+ QString deviceName() const { return m_deviceName; }
3777 QString mode() const { return m_mode; }
3778 private:
3779
3780@@ -44,6 +45,7 @@
3781 bool m_hasFrameless;
3782 bool m_hasMouseToTouch;
3783 bool m_hasFullscreen;
3784+ QString m_deviceName;
3785 QString m_mode;
3786 };
3787
3788
3789=== modified file 'src/main.cpp'
3790--- src/main.cpp 2015-05-11 09:50:47 +0000
3791+++ src/main.cpp 2015-05-21 17:30:56 +0000
3792@@ -25,6 +25,9 @@
3793 #include <csignal>
3794 #include <libintl.h>
3795
3796+// libandroid-properties
3797+#include <hybris/properties/properties.h>
3798+
3799 // local
3800 #include <paths.h>
3801 #include "MouseTouchAdaptor.h"
3802@@ -47,13 +50,15 @@
3803
3804 UnityCommandLineParser parser(*application);
3805
3806- QString indicatorProfile = qgetenv("UNITY_INDICATOR_PROFILE");
3807- if (indicatorProfile.isEmpty()) {
3808- indicatorProfile = "phone";
3809- }
3810-
3811 ApplicationArguments qmlArgs;
3812- qmlArgs.setSize(parser.windowGeometry());
3813+
3814+ if (!parser.deviceName().isEmpty()) {
3815+ qmlArgs.setDeviceName(parser.deviceName());
3816+ } else {
3817+ char buffer[200];
3818+ property_get("ro.product.device", buffer /* value */, "desktop" /* default_value*/);
3819+ qmlArgs.setDeviceName(QString(buffer));
3820+ }
3821
3822 // The testability driver is only loaded by QApplication but not by QGuiApplication.
3823 // However, QApplication depends on QWidget which would add some unneeded overhead => Let's load the testability driver on our own.
3824@@ -79,9 +84,14 @@
3825 view->setResizeMode(QQuickView::SizeRootObjectToView);
3826 view->setColor("black");
3827 view->setTitle("Unity8 Shell");
3828+
3829+ if (parser.windowGeometry().isValid()) {
3830+ view->setWidth(parser.windowGeometry().width());
3831+ view->setHeight(parser.windowGeometry().height());
3832+ }
3833+
3834 view->engine()->setBaseUrl(QUrl::fromLocalFile(::qmlDirectory()));
3835 view->rootContext()->setContextProperty("applicationArguments", &qmlArgs);
3836- view->rootContext()->setContextProperty("indicatorProfile", indicatorProfile);
3837 view->rootContext()->setContextProperty("shellMode", parser.mode());
3838 if (parser.hasFrameless()) {
3839 view->setFlags(Qt::FramelessWindowHint);
3840@@ -94,7 +104,7 @@
3841 mouseTouchAdaptor = MouseTouchAdaptor::instance();
3842 }
3843
3844- QUrl source(::qmlDirectory()+"Shell.qml");
3845+ QUrl source(::qmlDirectory()+"OrientedShell.qml");
3846 prependImportPaths(view->engine(), ::overrideImportPaths());
3847 if (!isMirServer) {
3848 prependImportPaths(view->engine(), ::nonMirImportPaths());
3849
3850=== modified file 'tests/mocks/Unity/Application/ApplicationInfo.cpp'
3851--- tests/mocks/Unity/Application/ApplicationInfo.cpp 2014-08-28 23:16:07 +0000
3852+++ tests/mocks/Unity/Application/ApplicationInfo.cpp 2015-05-21 17:30:56 +0000
3853@@ -1,5 +1,5 @@
3854 /*
3855- * Copyright (C) 2013-2014 Canonical, Ltd.
3856+ * Copyright (C) 2013-2015 Canonical, Ltd.
3857 *
3858 * This program is free software; you can redistribute it and/or modify
3859 * it under the terms of the GNU General Public License as published by
3860@@ -34,6 +34,11 @@
3861 , m_focused(false)
3862 , m_fullscreen(false)
3863 , m_session(0)
3864+ , m_supportedOrientations(Qt::PortraitOrientation |
3865+ Qt::LandscapeOrientation |
3866+ Qt::InvertedPortraitOrientation |
3867+ Qt::InvertedLandscapeOrientation)
3868+ , m_rotatesWindowContents(false)
3869 , m_manualSurfaceCreation(false)
3870 {
3871 }
3872@@ -45,6 +50,11 @@
3873 , m_focused(false)
3874 , m_fullscreen(false)
3875 , m_session(0)
3876+ , m_supportedOrientations(Qt::PortraitOrientation |
3877+ Qt::LandscapeOrientation |
3878+ Qt::InvertedPortraitOrientation |
3879+ Qt::InvertedLandscapeOrientation)
3880+ , m_rotatesWindowContents(false)
3881 , m_manualSurfaceCreation(false)
3882 {
3883 }
3884@@ -99,9 +109,17 @@
3885
3886 void ApplicationInfo::setScreenshotId(const QString &screenshotId)
3887 {
3888- QString screenshotFileName = QString("%1/Dash/graphics/phone/screenshots/%2@12.png")
3889- .arg(qmlDirectory())
3890- .arg(screenshotId);
3891+ QString screenshotFileName;
3892+
3893+ if (screenshotId.endsWith(".svg")) {
3894+ screenshotFileName = QString("%1/Dash/graphics/phone/screenshots/%2")
3895+ .arg(qmlDirectory())
3896+ .arg(screenshotId);
3897+ } else {
3898+ screenshotFileName = QString("%1/Dash/graphics/phone/screenshots/%2@12.png")
3899+ .arg(qmlDirectory())
3900+ .arg(screenshotId);
3901+ }
3902
3903 if (screenshotFileName != m_screenshotFileName) {
3904 m_screenshotFileName = screenshotFileName;
3905@@ -145,6 +163,9 @@
3906
3907 if (!m_manualSurfaceCreation && m_state == ApplicationInfo::Running) {
3908 QTimer::singleShot(500, this, SLOT(createSession()));
3909+ } else if (m_state == ApplicationInfo::Stopped) {
3910+ delete m_session;
3911+ m_session = nullptr;
3912 }
3913 }
3914 }
3915@@ -172,3 +193,23 @@
3916 Q_EMIT manualSurfaceCreationChanged(value);
3917 }
3918 }
3919+
3920+Qt::ScreenOrientations ApplicationInfo::supportedOrientations() const
3921+{
3922+ return m_supportedOrientations;
3923+}
3924+
3925+void ApplicationInfo::setSupportedOrientations(Qt::ScreenOrientations orientations)
3926+{
3927+ m_supportedOrientations = orientations;
3928+}
3929+
3930+bool ApplicationInfo::rotatesWindowContents() const
3931+{
3932+ return m_rotatesWindowContents;
3933+}
3934+
3935+void ApplicationInfo::setRotatesWindowContents(bool value)
3936+{
3937+ m_rotatesWindowContents = value;
3938+}
3939
3940=== modified file 'tests/mocks/Unity/Application/ApplicationInfo.h'
3941--- tests/mocks/Unity/Application/ApplicationInfo.h 2014-09-15 19:05:32 +0000
3942+++ tests/mocks/Unity/Application/ApplicationInfo.h 2015-05-21 17:30:56 +0000
3943@@ -1,5 +1,5 @@
3944 /*
3945- * Copyright (C) 2013-2014 Canonical, Ltd.
3946+ * Copyright (C) 2013-2015 Canonical, Ltd.
3947 *
3948 * This program is free software; you can redistribute it and/or modify
3949 * it under the terms of the GNU General Public License as published by
3950@@ -80,6 +80,12 @@
3951 void setFullscreen(bool value);
3952 bool fullscreen() const { return m_fullscreen; }
3953
3954+ Qt::ScreenOrientations supportedOrientations() const override;
3955+ void setSupportedOrientations(Qt::ScreenOrientations orientations);
3956+
3957+ bool rotatesWindowContents() const override;
3958+ void setRotatesWindowContents(bool value);
3959+
3960 bool manualSurfaceCreation() const { return m_manualSurfaceCreation; }
3961 void setManualSurfaceCreation(bool value);
3962
3963@@ -108,6 +114,8 @@
3964 bool m_focused;
3965 bool m_fullscreen;
3966 Session* m_session;
3967+ Qt::ScreenOrientations m_supportedOrientations;
3968+ bool m_rotatesWindowContents;
3969
3970 bool m_manualSurfaceCreation;
3971 };
3972
3973=== modified file 'tests/mocks/Unity/Application/ApplicationManager.cpp'
3974--- tests/mocks/Unity/Application/ApplicationManager.cpp 2015-04-13 10:49:47 +0000
3975+++ tests/mocks/Unity/Application/ApplicationManager.cpp 2015-05-21 17:30:56 +0000
3976@@ -1,5 +1,5 @@
3977 /*
3978- * Copyright (C) 2013-2014 Canonical, Ltd.
3979+ * Copyright (C) 2013-2015 Canonical, Ltd.
3980 *
3981 * This program is free software; you can redistribute it and/or modify
3982 * it under the terms of the GNU General Public License as published by
3983@@ -348,6 +348,13 @@
3984
3985 void ApplicationManager::buildListOfAvailableApplications()
3986 {
3987+ /*
3988+ ATTENTION!
3989+ Be careful when changing application properties here as some qmltests
3990+ rely on them being the way it's specified here (e.g. that camera-app
3991+ is fullscreen, that twitter-webapp can rotate in all directions, etc)
3992+ */
3993+
3994 ApplicationInfo *application;
3995
3996 application = new ApplicationInfo(this);
3997@@ -355,6 +362,7 @@
3998 application->setName("Unity 8 Mock Dash");
3999 application->setScreenshotId("unity8-dash");
4000 application->setStage(ApplicationInfo::MainStage);
4001+ application->setSupportedOrientations(Qt::PrimaryOrientation);
4002 m_availableApplications.append(application);
4003
4004 application = new ApplicationInfo(this);
4005@@ -363,6 +371,8 @@
4006 application->setScreenshotId("dialer");
4007 application->setIconId("dialer-app");
4008 application->setStage(ApplicationInfo::SideStage);
4009+ application->setSupportedOrientations(Qt::PortraitOrientation
4010+ | Qt::InvertedPortraitOrientation);
4011 m_availableApplications.append(application);
4012
4013 application = new ApplicationInfo(this);
4014@@ -371,6 +381,11 @@
4015 application->setScreenshotId("camera");
4016 application->setIconId("camera");
4017 application->setFullscreen(true);
4018+ application->setSupportedOrientations(Qt::PortraitOrientation
4019+ | Qt::LandscapeOrientation
4020+ | Qt::InvertedPortraitOrientation
4021+ | Qt::InvertedLandscapeOrientation);
4022+ application->setRotatesWindowContents(true);
4023 m_availableApplications.append(application);
4024
4025 application = new ApplicationInfo(this);
4026@@ -416,13 +431,35 @@
4027 application->setAppId("gmail-webapp");
4028 application->setName("GMail");
4029 application->setIconId("gmail");
4030+ application->setScreenshotId("gmail-webapp.svg");
4031+ application->setFullscreen(false);
4032+ application->setStage(ApplicationInfo::MainStage);
4033+ application->setSupportedOrientations(Qt::PortraitOrientation
4034+ | Qt::LandscapeOrientation
4035+ | Qt::InvertedPortraitOrientation
4036+ | Qt::InvertedLandscapeOrientation);
4037+ m_availableApplications.append(application);
4038+
4039+ application = new ApplicationInfo(this);
4040+ application->setAppId("music-app");
4041+ application->setName("Music");
4042+ application->setIconId("soundcloud");
4043+ application->setScreenshotId("music");
4044+ application->setFullscreen(false);
4045+ application->setStage(ApplicationInfo::MainStage);
4046+ application->setSupportedOrientations(Qt::PortraitOrientation
4047+ | Qt::LandscapeOrientation
4048+ | Qt::InvertedPortraitOrientation
4049+ | Qt::InvertedLandscapeOrientation);
4050 m_availableApplications.append(application);
4051
4052 application = new ApplicationInfo(this);
4053 application->setAppId("ubuntu-weather-app");
4054 application->setName("Weather");
4055 application->setIconId("weather");
4056- application->setStage(ApplicationInfo::SideStage);
4057+ application->setScreenshotId("ubuntu-weather-app.svg");
4058+ application->setSupportedOrientations(Qt::LandscapeOrientation
4059+ | Qt::InvertedLandscapeOrientation);
4060 m_availableApplications.append(application);
4061
4062 application = new ApplicationInfo(this);
4063
4064=== modified file 'tests/mocks/Unity/Application/CMakeLists.txt'
4065--- tests/mocks/Unity/Application/CMakeLists.txt 2014-10-06 15:45:25 +0000
4066+++ tests/mocks/Unity/Application/CMakeLists.txt 2015-05-21 17:30:56 +0000
4067@@ -1,5 +1,3 @@
4068-pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5)
4069-
4070 set(FakeUnityApplicationQml_SOURCES
4071 plugin.cpp
4072 ApplicationInfo.cpp
4073@@ -14,6 +12,7 @@
4074 SurfaceManager.cpp
4075 SessionModel.h
4076 UbuntuKeyboardInfo.cpp
4077+ VirtualKeyboard.cpp
4078 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationInfoInterface.h
4079 ${APPLICATION_API_INCLUDEDIR}/unity/shell/application/ApplicationManagerInterface.h
4080 )
4081
4082=== modified file 'tests/mocks/Unity/Application/MirSurfaceItem.cpp'
4083--- tests/mocks/Unity/Application/MirSurfaceItem.cpp 2015-03-12 14:45:44 +0000
4084+++ tests/mocks/Unity/Application/MirSurfaceItem.cpp 2015-05-21 17:30:56 +0000
4085@@ -1,5 +1,5 @@
4086 /*
4087- * Copyright (C) 2014 Canonical, Ltd.
4088+ * Copyright (C) 2014-2015 Canonical, Ltd.
4089 *
4090 * This program is free software; you can redistribute it and/or modify
4091 * it under the terms of the GNU General Public License as published by
4092@@ -39,14 +39,12 @@
4093 , m_type(type)
4094 , m_state(state)
4095 , m_live(true)
4096- , m_orientation(Qt::PortraitOrientation)
4097+ , m_orientationAngle(Angle0)
4098+ , m_qmlItem(nullptr)
4099+ , m_screenshotUrl(screenshot)
4100 , m_touchPressCount(0)
4101 , m_touchReleaseCount(0)
4102- , m_qmlItem(nullptr)
4103- , m_screenshotUrl(screenshot)
4104 {
4105- qDebug() << "MirSurfaceItem::MirSurfaceItem() " << this->name();
4106-
4107 setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton |
4108 Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 |
4109 Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 |
4110@@ -55,9 +53,6 @@
4111
4112 QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
4113
4114- connect(this, &QQuickItem::focusChanged,
4115- this, &MirSurfaceItem::onFocusChanged);
4116-
4117 // The assumptions I make here really should hold.
4118 QQuickView *quickView =
4119 qobject_cast<QQuickView*>(QGuiApplication::topLevelWindows()[0]);
4120@@ -117,17 +112,17 @@
4121 }
4122 }
4123
4124-void MirSurfaceItem::setOrientation(const Qt::ScreenOrientation orientation)
4125+void MirSurfaceItem::setOrientationAngle(OrientationAngle angle)
4126 {
4127- if (m_orientation == orientation)
4128+ if (m_orientationAngle == angle)
4129 return;
4130
4131- m_orientation = orientation;
4132-
4133- QQmlProperty orientationProp(m_qmlItem, "orientation");
4134- orientationProp.write(QVariant::fromValue(orientation));
4135-
4136- Q_EMIT orientationChanged();
4137+ m_orientationAngle = angle;
4138+
4139+ QQmlProperty orientationProp(m_qmlItem, "orientationAngle");
4140+ orientationProp.write(QVariant::fromValue(m_orientationAngle));
4141+
4142+ Q_EMIT orientationAngleChanged(m_orientationAngle);
4143 }
4144
4145 void MirSurfaceItem::setSession(Session* session)
4146@@ -152,15 +147,6 @@
4147 }
4148 }
4149
4150-void MirSurfaceItem::onFocusChanged()
4151-{
4152- if (!hasFocus()) {
4153- // Causes a crash in tst_Shell.qml, inside the mock Unity.Application itself.
4154- // Didn't have time to debug yet.
4155- //Q_EMIT inputMethodDismissed();
4156- }
4157-}
4158-
4159 void MirSurfaceItem::setState(MirSurfaceItem::State newState)
4160 {
4161 if (newState != m_state) {
4162@@ -197,9 +183,6 @@
4163 if (event->touchPointStates() & Qt::TouchPointPressed) {
4164 ++m_touchPressCount;
4165 Q_EMIT touchPressCountChanged(m_touchPressCount);
4166- // Causes a crash in tst_Shell.qml, inside the mock Unity.Application itself.
4167- // Didn't have time to debug yet.
4168- // Q_EMIT inputMethodRequested();
4169 } else if (event->touchPointStates() & Qt::TouchPointReleased) {
4170 ++m_touchReleaseCount;
4171 Q_EMIT touchReleaseCountChanged(m_touchReleaseCount);
4172
4173=== modified file 'tests/mocks/Unity/Application/MirSurfaceItem.h'
4174--- tests/mocks/Unity/Application/MirSurfaceItem.h 2015-03-12 14:45:44 +0000
4175+++ tests/mocks/Unity/Application/MirSurfaceItem.h 2015-05-21 17:30:56 +0000
4176@@ -1,5 +1,5 @@
4177 /*
4178- * Copyright (C) 2014 Canonical, Ltd.
4179+ * Copyright (C) 2014-2015 Canonical, Ltd.
4180 *
4181 * This program is free software; you can redistribute it and/or modify
4182 * it under the terms of the GNU General Public License as published by
4183@@ -29,17 +29,18 @@
4184 Q_OBJECT
4185 Q_ENUMS(Type)
4186 Q_ENUMS(State)
4187+ Q_ENUMS(OrientationAngle)
4188
4189 Q_PROPERTY(Type type READ type NOTIFY typeChanged)
4190 Q_PROPERTY(State state READ state NOTIFY stateChanged)
4191 Q_PROPERTY(QString name READ name CONSTANT)
4192 Q_PROPERTY(bool live READ live NOTIFY liveChanged)
4193- Q_PROPERTY(Qt::ScreenOrientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged DESIGNABLE false)
4194-
4195- Q_PROPERTY(int touchPressCount READ touchPressCount WRITE setTouchPressCount NOTIFY touchPressCountChanged
4196- DESIGNABLE false)
4197- Q_PROPERTY(int touchReleaseCount READ touchReleaseCount WRITE setTouchReleaseCount NOTIFY touchReleaseCountChanged
4198- DESIGNABLE false)
4199+ Q_PROPERTY(OrientationAngle orientationAngle READ orientationAngle WRITE setOrientationAngle
4200+ NOTIFY orientationAngleChanged DESIGNABLE false)
4201+ Q_PROPERTY(int touchPressCount READ touchPressCount WRITE setTouchPressCount
4202+ NOTIFY touchPressCountChanged DESIGNABLE false)
4203+ Q_PROPERTY(int touchReleaseCount READ touchReleaseCount WRITE setTouchReleaseCount
4204+ NOTIFY touchReleaseCountChanged DESIGNABLE false)
4205
4206 public:
4207 enum Type {
4208@@ -62,6 +63,13 @@
4209 Fullscreen,
4210 };
4211
4212+ enum OrientationAngle {
4213+ Angle0 = 0,
4214+ Angle90 = 90,
4215+ Angle180 = 180,
4216+ Angle270 = 270
4217+ };
4218+
4219 ~MirSurfaceItem();
4220
4221 //getters
4222@@ -70,9 +78,9 @@
4223 State state() const { return m_state; }
4224 QString name() const { return m_name; }
4225 bool live() const { return m_live; }
4226- Qt::ScreenOrientation orientation() const { return m_orientation; }
4227+ OrientationAngle orientationAngle() const { return m_orientationAngle; }
4228
4229- void setOrientation(const Qt::ScreenOrientation orientation);
4230+ void setOrientationAngle(OrientationAngle angle);
4231
4232 void setSession(Session* item);
4233 void setScreenshot(const QUrl& screenshot);
4234@@ -91,29 +99,14 @@
4235 void typeChanged(Type);
4236 void stateChanged(State);
4237 void liveChanged(bool live);
4238- void orientationChanged();
4239+ void orientationAngleChanged(OrientationAngle angle);
4240 void touchPressCountChanged(int count);
4241 void touchReleaseCountChanged(int count);
4242
4243- void inputMethodRequested();
4244- void inputMethodDismissed();
4245-
4246 // internal mock use
4247 void deregister();
4248
4249 protected:
4250- void touchEvent(QTouchEvent * event) override;
4251-
4252- // becaue the default implementation ignores the events
4253- void mousePressEvent(QMouseEvent *) override {}
4254- void mouseMoveEvent(QMouseEvent *) override {}
4255- void mouseReleaseEvent(QMouseEvent *) override {}
4256-
4257-private Q_SLOTS:
4258- void onFocusChanged();
4259- void onComponentStatusChanged(QQmlComponent::Status status);
4260-
4261-private:
4262 explicit MirSurfaceItem(const QString& name,
4263 Type type,
4264 State state,
4265@@ -121,6 +114,12 @@
4266 const QString &qmlFilePath = QString(),
4267 QQuickItem *parent = 0);
4268
4269+ void touchEvent(QTouchEvent * event) override;
4270+
4271+private Q_SLOTS:
4272+ void onComponentStatusChanged(QQmlComponent::Status status);
4273+
4274+private:
4275 void createQmlContentItem();
4276 void printComponentErrors();
4277
4278@@ -129,19 +128,20 @@
4279 const Type m_type;
4280 State m_state;
4281 bool m_live;
4282- Qt::ScreenOrientation m_orientation;
4283- int m_touchPressCount;
4284- int m_touchReleaseCount;
4285+ OrientationAngle m_orientationAngle;
4286
4287 QQmlComponent *m_qmlContentComponent;
4288 QQuickItem *m_qmlItem;
4289 QUrl m_screenshotUrl;
4290
4291+ int m_touchPressCount;
4292+ int m_touchReleaseCount;
4293+
4294 friend class SurfaceManager;
4295 };
4296
4297 Q_DECLARE_METATYPE(MirSurfaceItem*)
4298 Q_DECLARE_METATYPE(QList<MirSurfaceItem*>)
4299-Q_DECLARE_METATYPE(Qt::ScreenOrientation)
4300+Q_DECLARE_METATYPE(MirSurfaceItem::OrientationAngle)
4301
4302 #endif // MIRSURFACEITEM_H
4303
4304=== modified file 'tests/mocks/Unity/Application/MirSurfaceItem.qml'
4305--- tests/mocks/Unity/Application/MirSurfaceItem.qml 2015-01-28 12:59:21 +0000
4306+++ tests/mocks/Unity/Application/MirSurfaceItem.qml 2015-05-21 17:30:56 +0000
4307@@ -1,5 +1,5 @@
4308 /*
4309- * Copyright 2014 Canonical Ltd.
4310+ * Copyright 2014-2015 Canonical Ltd.
4311 *
4312 * This program is free software; you can redistribute it and/or modify
4313 * it under the terms of the GNU Lesser General Public License as published by
4314@@ -23,19 +23,11 @@
4315 implicitWidth: units.gu(40)
4316 implicitHeight: units.gu(70)
4317
4318- rotation: {
4319- if (orientation == Qt.PortraitOrientation) return 0;
4320- else if (orientation == Qt.LandscapeOrientation) return 90;
4321- else if (orientation == Qt.InvertedPortraitOrientation) return 180;
4322- else return 270;
4323- }
4324- x: parent ? (parent.width - width) / 2 : 0
4325- y: parent ? (parent.height - height) / 2 : 0
4326- width: parent ? (rotation == 0 || rotation == 180 ? parent.width : parent.height) : implicitWidth
4327- height: parent ? (rotation == 0 || rotation == 180 ? parent.height : parent.width) : implicitHeight
4328+ width: parent ? parent.width : implicitWidth
4329+ height: parent ? parent.height : implicitHeight
4330
4331 property alias screenshotSource: screenshotImage.source
4332- property int orientation: Qt.PortraitOrientation
4333+ property int orientationAngle
4334
4335 Image {
4336 id: screenshotImage
4337@@ -50,6 +42,7 @@
4338 fontSizeMode: Text.Fit
4339 minimumPixelSize: 10
4340 verticalAlignment: Text.AlignVCenter
4341+ rotation: surfaceText.rotation
4342 x: surfaceText.x
4343 y: surfaceText.y
4344 width: surfaceText.width
4345@@ -59,12 +52,17 @@
4346 }
4347 Text {
4348 id: surfaceText
4349- anchors.fill: parent
4350- text: "SURFACE"
4351+ text: "SURFACE " + root.width + "," + root.height
4352 color: root.parent && root.parent.activeFocus ? "yellow" : "blue"
4353 font.bold: true
4354 fontSizeMode: Text.Fit
4355 minimumPixelSize: 10; font.pixelSize: 200
4356 verticalAlignment: Text.AlignVCenter
4357+
4358+ rotation: root.orientationAngle
4359+ x: (parent.width - width) / 2
4360+ y: (parent.height - height) / 2
4361+ width: (rotation == 0 || rotation == 180 ? parent.width : parent.height)
4362+ height:(rotation == 0 || rotation == 180 ? parent.height : parent.width)
4363 }
4364 }
4365
4366=== modified file 'tests/mocks/Unity/Application/SurfaceManager.cpp'
4367--- tests/mocks/Unity/Application/SurfaceManager.cpp 2014-08-29 14:50:49 +0000
4368+++ tests/mocks/Unity/Application/SurfaceManager.cpp 2015-05-21 17:30:56 +0000
4369@@ -16,8 +16,9 @@
4370
4371 #include "SurfaceManager.h"
4372
4373+#include "VirtualKeyboard.h"
4374+
4375 #include <paths.h>
4376-#include "MirSurfaceItem.h"
4377
4378 SurfaceManager *SurfaceManager::the_surface_manager = nullptr;
4379
4380@@ -40,10 +41,7 @@
4381 MirSurfaceItem::State state,
4382 const QUrl& screenshot)
4383 {
4384- MirSurfaceItem* surface = new MirSurfaceItem(name,
4385- type,
4386- state,
4387- screenshot);
4388+ MirSurfaceItem* surface = new MirSurfaceItem(name, type, state, screenshot);
4389 Q_EMIT surfaceCreated(surface);
4390 return surface;
4391 }
4392@@ -57,40 +55,12 @@
4393 surface->setLive(false);
4394 Q_EMIT surfaceDestroyed(surface);
4395 });
4396- connect(surface, &MirSurfaceItem::inputMethodRequested,
4397- this, &SurfaceManager::showInputMethod);
4398- connect(surface, &MirSurfaceItem::inputMethodDismissed,
4399- this, &SurfaceManager::hideInputMethod);
4400-}
4401-
4402-void SurfaceManager::showInputMethod()
4403-{
4404- inputMethodSurface()->setState(MirSurfaceItem::Restored);
4405-}
4406-
4407-void SurfaceManager::hideInputMethod()
4408-{
4409- if (m_virtualKeyboard) {
4410- m_virtualKeyboard->setState(MirSurfaceItem::Minimized);
4411- }
4412 }
4413
4414 MirSurfaceItem *SurfaceManager::inputMethodSurface()
4415 {
4416 if (!m_virtualKeyboard) {
4417-
4418- QString screenshotPath = QString("file://%1/Dash/graphics/phone/screenshots/vkb_portrait.png")
4419- .arg(qmlDirectory());
4420-
4421- QString qmlFilePath = QString("%1/Unity/Application/VirtualKeyboard.qml")
4422- .arg(mockPluginsDir());
4423-
4424- m_virtualKeyboard = new MirSurfaceItem(
4425- "input-method",
4426- MirSurfaceItem::InputMethod,
4427- MirSurfaceItem::Minimized,
4428- screenshotPath,
4429- qmlFilePath);
4430+ m_virtualKeyboard = new VirtualKeyboard;
4431 Q_EMIT surfaceCreated(m_virtualKeyboard);
4432 }
4433 return m_virtualKeyboard;
4434
4435=== modified file 'tests/mocks/Unity/Application/SurfaceManager.h'
4436--- tests/mocks/Unity/Application/SurfaceManager.h 2014-08-28 23:16:07 +0000
4437+++ tests/mocks/Unity/Application/SurfaceManager.h 2015-05-21 17:30:56 +0000
4438@@ -20,6 +20,7 @@
4439 #include <QObject>
4440
4441 #include "MirSurfaceItem.h"
4442+#include "VirtualKeyboard.h"
4443
4444 class SurfaceManager : public QObject
4445 {
4446@@ -45,13 +46,9 @@
4447 void surfaceCreated(MirSurfaceItem *surface);
4448 void surfaceDestroyed(MirSurfaceItem *surface);
4449
4450-private Q_SLOTS:
4451- void showInputMethod();
4452- void hideInputMethod();
4453-
4454 private:
4455 static SurfaceManager *the_surface_manager;
4456- MirSurfaceItem *m_virtualKeyboard;
4457+ VirtualKeyboard *m_virtualKeyboard;
4458 };
4459
4460 #endif // SURFACEMANAGER_H
4461
4462=== modified file 'tests/mocks/Unity/Application/UbuntuKeyboardInfo.cpp'
4463--- tests/mocks/Unity/Application/UbuntuKeyboardInfo.cpp 2014-10-02 08:50:52 +0000
4464+++ tests/mocks/Unity/Application/UbuntuKeyboardInfo.cpp 2015-05-21 17:30:56 +0000
4465@@ -1,5 +1,5 @@
4466 /*
4467- * Copyright (C) 2014 Canonical, Ltd.
4468+ * Copyright (C) 2014-2015 Canonical, Ltd.
4469 *
4470 * This program is free software: you can redistribute it and/or modify it under
4471 * the terms of the GNU Lesser General Public License version 3, as published by
4472@@ -26,3 +26,35 @@
4473 m_height(200)
4474 {
4475 }
4476+
4477+void UbuntuKeyboardInfo::setX(qreal value)
4478+{
4479+ if (value != m_x) {
4480+ m_x = value;
4481+ Q_EMIT xChanged(m_x);
4482+ }
4483+}
4484+
4485+void UbuntuKeyboardInfo::setY(qreal value)
4486+{
4487+ if (value != m_y) {
4488+ m_y = value;
4489+ Q_EMIT yChanged(m_y);
4490+ }
4491+}
4492+
4493+void UbuntuKeyboardInfo::setWidth(qreal value)
4494+{
4495+ if (value != m_width) {
4496+ m_width = value;
4497+ Q_EMIT widthChanged(m_width);
4498+ }
4499+}
4500+
4501+void UbuntuKeyboardInfo::setHeight(qreal value)
4502+{
4503+ if (value != m_height) {
4504+ m_height = value;
4505+ Q_EMIT heightChanged(m_height);
4506+ }
4507+}
4508
4509=== modified file 'tests/mocks/Unity/Application/UbuntuKeyboardInfo.h'
4510--- tests/mocks/Unity/Application/UbuntuKeyboardInfo.h 2014-10-02 08:50:52 +0000
4511+++ tests/mocks/Unity/Application/UbuntuKeyboardInfo.h 2015-05-21 17:30:56 +0000
4512@@ -1,5 +1,5 @@
4513 /*
4514- * Copyright (C) 2014 Canonical, Ltd.
4515+ * Copyright (C) 2014-2015 Canonical, Ltd.
4516 *
4517 * This program is free software: you can redistribute it and/or modify it under
4518 * the terms of the GNU Lesser General Public License version 3, as published by
4519@@ -22,10 +22,10 @@
4520
4521 class UbuntuKeyboardInfo : public QObject {
4522 Q_OBJECT
4523- Q_PROPERTY(qreal x READ x NOTIFY xChanged)
4524- Q_PROPERTY(qreal y READ y NOTIFY yChanged)
4525- Q_PROPERTY(qreal width READ width NOTIFY widthChanged)
4526- Q_PROPERTY(qreal height READ height NOTIFY heightChanged)
4527+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
4528+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
4529+ Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged)
4530+ Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged)
4531 public:
4532 UbuntuKeyboardInfo(QObject *parent = 0);
4533 virtual ~UbuntuKeyboardInfo() {}
4534@@ -34,6 +34,12 @@
4535 qreal width() const { return m_width; }
4536 qreal height() const { return m_height; }
4537
4538+ // Just in the fake implementation
4539+ void setX(qreal value);
4540+ void setY(qreal value);
4541+ void setWidth(qreal value);
4542+ void setHeight(qreal value);
4543+
4544 static UbuntuKeyboardInfo *singleton() {
4545 if (!m_instance) {
4546 m_instance = new UbuntuKeyboardInfo;
4547
4548=== added file 'tests/mocks/Unity/Application/VirtualKeyboard.cpp'
4549--- tests/mocks/Unity/Application/VirtualKeyboard.cpp 1970-01-01 00:00:00 +0000
4550+++ tests/mocks/Unity/Application/VirtualKeyboard.cpp 2015-05-21 17:30:56 +0000
4551@@ -0,0 +1,44 @@
4552+/*
4553+ * Copyright (C) 2015 Canonical, Ltd.
4554+ *
4555+ * This program is free software; you can redistribute it and/or modify
4556+ * it under the terms of the GNU General Public License as published by
4557+ * the Free Software Foundation; version 3.
4558+ *
4559+ * This program is distributed in the hope that it will be useful,
4560+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4561+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4562+ * GNU General Public License for more details.
4563+ *
4564+ * You should have received a copy of the GNU General Public License
4565+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4566+ */
4567+
4568+#include "VirtualKeyboard.h"
4569+
4570+#include <paths.h>
4571+
4572+#include <QString>
4573+
4574+#include <QDebug>
4575+
4576+VirtualKeyboard::VirtualKeyboard(QQuickItem *parent)
4577+ : MirSurfaceItem("input-method",
4578+ MirSurfaceItem::InputMethod,
4579+ MirSurfaceItem::Minimized,
4580+ QString("file://%1/Dash/graphics/phone/screenshots/vkb_portrait.png")
4581+ .arg(qmlDirectory()),
4582+ QString("%1/Unity/Application/VirtualKeyboard.qml")
4583+ .arg(mockPluginsDir()),
4584+ parent)
4585+{
4586+}
4587+
4588+VirtualKeyboard::~VirtualKeyboard()
4589+{
4590+}
4591+
4592+void VirtualKeyboard::touchEvent(QTouchEvent *event)
4593+{
4594+ event->setAccepted(false);
4595+}
4596
4597=== added file 'tests/mocks/Unity/Application/VirtualKeyboard.h'
4598--- tests/mocks/Unity/Application/VirtualKeyboard.h 1970-01-01 00:00:00 +0000
4599+++ tests/mocks/Unity/Application/VirtualKeyboard.h 2015-05-21 17:30:56 +0000
4600@@ -0,0 +1,42 @@
4601+/*
4602+ * Copyright (C) 2015 Canonical, Ltd.
4603+ *
4604+ * This program is free software; you can redistribute it and/or modify
4605+ * it under the terms of the GNU General Public License as published by
4606+ * the Free Software Foundation; version 3.
4607+ *
4608+ * This program is distributed in the hope that it will be useful,
4609+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4610+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4611+ * GNU General Public License for more details.
4612+ *
4613+ * You should have received a copy of the GNU General Public License
4614+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4615+ */
4616+
4617+#ifndef VIRTUALKEYBOARD_H
4618+#define VIRTUALKEYBOARD_H
4619+
4620+#include "MirSurfaceItem.h"
4621+#include "MirSurfaceItemModel.h"
4622+
4623+#include <QQuickItem>
4624+#include <QUrl>
4625+
4626+class Session;
4627+
4628+class VirtualKeyboard : public MirSurfaceItem
4629+{
4630+ Q_OBJECT
4631+public:
4632+ explicit VirtualKeyboard(QQuickItem *parent = 0);
4633+ ~VirtualKeyboard();
4634+
4635+protected:
4636+ void touchEvent(QTouchEvent * event) override;
4637+};
4638+
4639+Q_DECLARE_METATYPE(VirtualKeyboard*)
4640+Q_DECLARE_METATYPE(QList<VirtualKeyboard*>)
4641+
4642+#endif // VIRTUALKEYBOARD_H
4643
4644=== modified file 'tests/mocks/Unity/Application/VirtualKeyboard.qml'
4645--- tests/mocks/Unity/Application/VirtualKeyboard.qml 2014-08-19 13:26:00 +0000
4646+++ tests/mocks/Unity/Application/VirtualKeyboard.qml 2015-05-21 17:30:56 +0000
4647@@ -1,5 +1,5 @@
4648 /*
4649- * Copyright 2014 Canonical Ltd.
4650+ * Copyright 2014-2015 Canonical Ltd.
4651 *
4652 * This program is free software; you can redistribute it and/or modify
4653 * it under the terms of the GNU Lesser General Public License as published by
4654@@ -15,6 +15,7 @@
4655 */
4656
4657 import QtQuick 2.0
4658+import Unity.Application 0.1
4659
4660 Item {
4661 implicitWidth: units.gu(40)
4662@@ -37,4 +38,9 @@
4663 anchors.fill: parent
4664 }
4665 }
4666+
4667+ Binding { target: UbuntuKeyboardInfo; property: "x"; value: screenshotImage.x}
4668+ Binding { target: UbuntuKeyboardInfo; property: "y"; value: screenshotImage.y}
4669+ Binding { target: UbuntuKeyboardInfo; property: "width"; value: screenshotImage.width}
4670+ Binding { target: UbuntuKeyboardInfo; property: "height"; value: screenshotImage.height}
4671 }
4672
4673=== modified file 'tests/mocks/Unity/Launcher/MockLauncherModel.cpp'
4674--- tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2015-02-09 17:17:59 +0000
4675+++ tests/mocks/Unity/Launcher/MockLauncherModel.cpp 2015-05-21 17:30:56 +0000
4676@@ -1,5 +1,5 @@
4677 /*
4678- * Copyright 2013 Canonical Ltd.
4679+ * Copyright 2013,2015 Canonical Ltd.
4680 *
4681 * This program is free software; you can redistribute it and/or modify
4682 * it under the terms of the GNU Lesser General Public License as published by
4683@@ -35,6 +35,8 @@
4684 item->setProgress(50);
4685 item->setCountVisible(true);
4686 m_list.append(item);
4687+ item = new MockLauncherItem("music-app", "/usr/share/applications/music-app.desktop", "Music", "soundcloud", this);
4688+ m_list.append(item);
4689 item = new MockLauncherItem("facebook-webapp", "/usr/share/applications/facebook-webapp.desktop", "Facebook", "facebook", this);
4690 item->setProgress(150);
4691 m_list.append(item);
4692
4693=== modified file 'tests/mocks/Utils/CMakeLists.txt'
4694--- tests/mocks/Utils/CMakeLists.txt 2015-04-15 14:52:01 +0000
4695+++ tests/mocks/Utils/CMakeLists.txt 2015-05-21 17:30:56 +0000
4696@@ -16,6 +16,7 @@
4697 ${CMAKE_SOURCE_DIR}/plugins/Utils/timeformatter.cpp
4698 ${CMAKE_SOURCE_DIR}/plugins/Utils/unitymenumodelpaths.cpp
4699 ${CMAKE_SOURCE_DIR}/plugins/Utils/windowkeysfilter.cpp
4700+ ${CMAKE_SOURCE_DIR}/plugins/Utils/windowscreenshotprovider.cpp
4701 ${CMAKE_SOURCE_DIR}/plugins/Utils/easingcurve.cpp
4702 constants.cpp
4703 plugin.cpp
4704
4705=== modified file 'tests/mocks/Utils/plugin.cpp'
4706--- tests/mocks/Utils/plugin.cpp 2015-05-01 13:21:30 +0000
4707+++ tests/mocks/Utils/plugin.cpp 2015-05-21 17:30:56 +0000
4708@@ -34,6 +34,7 @@
4709 #include <timeformatter.h>
4710 #include <unitymenumodelpaths.h>
4711 #include <windowkeysfilter.h>
4712+#include <windowscreenshotprovider.h>
4713 #include <easingcurve.h>
4714
4715 static QObject *createWindowStateStorage(QQmlEngine *engine, QJSEngine *scriptEngine)
4716@@ -70,4 +71,6 @@
4717 void FakeUtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
4718 {
4719 QQmlExtensionPlugin::initializeEngine(engine, uri);
4720+
4721+ engine->addImageProvider(QLatin1String("window"), new WindowScreenshotProvider);
4722 }
4723
4724=== modified file 'tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt'
4725--- tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt 2015-02-11 13:43:17 +0000
4726+++ tests/plugins/Greeter/Unity/Launcher/CMakeLists.txt 2015-05-21 17:30:56 +0000
4727@@ -1,5 +1,5 @@
4728 pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=6)
4729-pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5)
4730+pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=6)
4731
4732 include_directories(
4733 ${CMAKE_CURRENT_SOURCE_DIR}
4734
4735=== modified file 'tests/plugins/Unity/Launcher/CMakeLists.txt'
4736--- tests/plugins/Unity/Launcher/CMakeLists.txt 2015-04-13 08:28:56 +0000
4737+++ tests/plugins/Unity/Launcher/CMakeLists.txt 2015-05-21 17:30:56 +0000
4738@@ -1,6 +1,5 @@
4739 pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
4740 pkg_check_modules(LAUNCHER_API REQUIRED unity-shell-launcher=6)
4741-pkg_check_modules(APPLICATION_API REQUIRED unity-shell-application=5)
4742
4743 include_directories(
4744 ${CMAKE_CURRENT_SOURCE_DIR}
4745
4746=== modified file 'tests/plugins/Unity/Launcher/launchermodeltest.cpp'
4747--- tests/plugins/Unity/Launcher/launchermodeltest.cpp 2015-04-30 09:31:51 +0000
4748+++ tests/plugins/Unity/Launcher/launchermodeltest.cpp 2015-05-21 17:30:56 +0000
4749@@ -1,5 +1,5 @@
4750 /*
4751- * Copyright 2013-2014 Canonical Ltd.
4752+ * Copyright 2013-2015 Canonical Ltd.
4753 *
4754 * This program is free software; you can redistribute it and/or modify
4755 * it under the terms of the GNU Lesser General Public License as published by
4756@@ -52,6 +52,8 @@
4757 QColor splashColor() const override { return QColor(0,0,0,0); }
4758 QColor splashColorHeader() const override { return QColor(0,0,0,0); }
4759 QColor splashColorFooter() const override { return QColor(0,0,0,0); }
4760+ Qt::ScreenOrientations supportedOrientations() const override { return Qt::PortraitOrientation; }
4761+ bool rotatesWindowContents() const override { return false; }
4762
4763 // Methods used for mocking (not in the interface)
4764 void setFocused(bool focused) { m_focused = focused; Q_EMIT focusedChanged(focused); }
4765
4766=== modified file 'tests/qmltests/CMakeLists.txt'
4767--- tests/qmltests/CMakeLists.txt 2015-05-18 23:04:19 +0000
4768+++ tests/qmltests/CMakeLists.txt 2015-05-21 17:30:56 +0000
4769@@ -19,6 +19,7 @@
4770 set(qmltest_DEFAULT_NO_ADD_TEST TRUE)
4771 set(qmltest_DEFAULT_PROPERTIES ENVIRONMENT "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/tests/mocks/libusermetrics:${CMAKE_BINARY_DIR}/tests/mocks/LightDM/liblightdm:${CMAKE_BINARY_DIR}/tests/mocks/QMenuModel")
4772
4773+add_qml_test(. OrientedShell)
4774 add_qml_test(. Shell)
4775 add_qml_test(. ShellWithPin)
4776 add_qml_test(Components Background)
4777
4778=== modified file 'tests/qmltests/Panel/tst_IndicatorsMenu.qml'
4779--- tests/qmltests/Panel/tst_IndicatorsMenu.qml 2014-11-25 12:53:03 +0000
4780+++ tests/qmltests/Panel/tst_IndicatorsMenu.qml 2015-05-21 17:30:56 +0000
4781@@ -28,8 +28,6 @@
4782 height: units.gu(71)
4783 color: "white"
4784
4785- property string indicatorProfile: "phone"
4786-
4787 RowLayout {
4788 anchors.fill: parent
4789 anchors.margins: units.gu(1)
4790
4791=== modified file 'tests/qmltests/Panel/tst_Panel.qml'
4792--- tests/qmltests/Panel/tst_Panel.qml 2015-04-02 15:08:05 +0000
4793+++ tests/qmltests/Panel/tst_Panel.qml 2015-05-21 17:30:56 +0000
4794@@ -29,8 +29,6 @@
4795 height: units.gu(71)
4796 color: "white"
4797
4798- property string indicatorProfile: "phone"
4799-
4800 RowLayout {
4801 anchors.fill: parent
4802 anchors.margins: units.gu(1)
4803
4804=== modified file 'tests/qmltests/Stages/tst_ApplicationWindow.qml'
4805--- tests/qmltests/Stages/tst_ApplicationWindow.qml 2015-01-28 12:59:21 +0000
4806+++ tests/qmltests/Stages/tst_ApplicationWindow.qml 2015-05-21 17:30:56 +0000
4807@@ -1,5 +1,5 @@
4808 /*
4809- * Copyright 2014 Canonical Ltd.
4810+ * Copyright 2014-2015 Canonical Ltd.
4811 *
4812 * This program is free software; you can redistribute it and/or modify
4813 * it under the terms of the GNU General Public License as published by
4814@@ -50,7 +50,7 @@
4815 ApplicationWindow {
4816 anchors.fill: parent
4817 application: fakeApplication
4818- orientation: Qt.PortraitOrientation
4819+ surfaceOrientationAngle: 0
4820 interactive: true
4821 focus: true
4822 }
4823@@ -210,15 +210,6 @@
4824 stateGroup = null;
4825 }
4826
4827- // wait until any transition animation has finished
4828- function waitUntilTransitionsEnd() {
4829- var transitions = stateGroup.transitions;
4830- for (var i = 0; i < transitions.length; ++i) {
4831- var transition = transitions[i];
4832- tryCompare(transition, "running", false, 2000);
4833- }
4834- }
4835-
4836 function init() {
4837 findInterestingApplicationWindowChildren();
4838 }
4839@@ -280,12 +271,12 @@
4840
4841 tryCompare(stateGroup, "state", "surface");
4842
4843- waitUntilTransitionsEnd();
4844+ waitUntilTransitionsEnd(stateGroup);
4845
4846 setApplicationState(appSuspended);
4847
4848 verify(stateGroup.state === "surface");
4849- waitUntilTransitionsEnd();
4850+ waitUntilTransitionsEnd(stateGroup);
4851 }
4852
4853 function test_killedAppShowsScreenshot() {
4854@@ -311,7 +302,7 @@
4855 initSession();
4856 setApplicationState(appRunning);
4857 tryCompare(stateGroup, "state", "surface");
4858- waitUntilTransitionsEnd();
4859+ waitUntilTransitionsEnd(stateGroup);
4860
4861 setApplicationState(appSuspended);
4862
4863@@ -319,19 +310,19 @@
4864 setApplicationState(appStopped);
4865
4866 tryCompare(stateGroup, "state", "screenshot");
4867- waitUntilTransitionsEnd();
4868+ waitUntilTransitionsEnd(stateGroup);
4869 tryCompare(fakeApplication, "session", null);
4870
4871 // and restart it
4872 setApplicationState(appStarting);
4873
4874- waitUntilTransitionsEnd();
4875+ waitUntilTransitionsEnd(stateGroup);
4876 verify(stateGroup.state === "screenshot");
4877 verify(fakeSession === null);
4878
4879 setApplicationState(appRunning);
4880
4881- waitUntilTransitionsEnd();
4882+ waitUntilTransitionsEnd(stateGroup);
4883 verify(stateGroup.state === "screenshot");
4884
4885 initSession();
4886@@ -344,7 +335,7 @@
4887 initSession();
4888 setApplicationState(appRunning);
4889 tryCompare(stateGroup, "state", "surface");
4890- waitUntilTransitionsEnd();
4891+ waitUntilTransitionsEnd(stateGroup);
4892
4893 // oh, it crashed...
4894 setApplicationState(appStopped);
4895@@ -357,18 +348,18 @@
4896 initSession();
4897 setApplicationState(appRunning);
4898 tryCompare(stateGroup, "state", "surface");
4899- waitUntilTransitionsEnd();
4900+ waitUntilTransitionsEnd(stateGroup);
4901 verify(fakeSession.surface !== null);
4902
4903 applicationWindowLoader.item.visible = false;
4904
4905- waitUntilTransitionsEnd();
4906+ waitUntilTransitionsEnd(stateGroup);
4907 verify(stateGroup.state === "surface");
4908 verify(fakeSession.surface !== null);
4909
4910 applicationWindowLoader.item.visible = true;
4911
4912- waitUntilTransitionsEnd();
4913+ waitUntilTransitionsEnd(stateGroup);
4914 verify(stateGroup.state === "surface");
4915 verify(fakeSession.surface !== null);
4916 }
4917@@ -379,7 +370,7 @@
4918
4919 tryCompare(stateGroup, "state", "surface");
4920
4921- waitUntilTransitionsEnd();
4922+ waitUntilTransitionsEnd(stateGroup);
4923
4924 var fakeSurface = fakeSession.surface;
4925 fakeSurface.touchPressCount = 0;
4926@@ -396,7 +387,7 @@
4927 initSession();
4928 setApplicationState(appRunning);
4929 tryCompare(stateGroup, "state", "surface");
4930- waitUntilTransitionsEnd();
4931+ waitUntilTransitionsEnd(stateGroup);
4932
4933 cleanupSession();
4934
4935
4936=== modified file 'tests/qmltests/Stages/tst_PhoneStage.qml'
4937--- tests/qmltests/Stages/tst_PhoneStage.qml 2015-04-10 21:16:37 +0000
4938+++ tests/qmltests/Stages/tst_PhoneStage.qml 2015-05-21 17:30:56 +0000
4939@@ -1,5 +1,5 @@
4940 /*
4941- * Copyright 2014 Canonical Ltd.
4942+ * Copyright 2014-2015 Canonical Ltd.
4943 *
4944 * This program is free software; you can redistribute it and/or modify
4945 * it under the terms of the GNU General Public License as published by
4946@@ -33,7 +33,9 @@
4947 dragAreaWidth: units.gu(2)
4948 maximizedAppTopMargin: units.gu(3) + units.dp(2)
4949 interactive: true
4950- orientation: Qt.PortraitOrientation
4951+ shellOrientation: Qt.PortraitOrientation
4952+ shellPrimaryOrientation: Qt.PortraitOrientation
4953+ nativeOrientation: Qt.PortraitOrientation
4954 }
4955
4956 Binding {
4957@@ -73,21 +75,6 @@
4958 ApplicationManager.get(appList.selectedAppIndex).setState(ApplicationInfoInterface.Stopped);
4959 }
4960 }
4961- Button {
4962- anchors { left: parent.left; right: parent.right }
4963- text: "Rotate device \u27F3"
4964- onClicked: {
4965- if (phoneStage.orientation == Qt.PortraitOrientation) {
4966- phoneStage.orientation = Qt.LandscapeOrientation;
4967- } else if (phoneStage.orientation == Qt.LandscapeOrientation) {
4968- phoneStage.orientation = Qt.InvertedPortraitOrientation;
4969- } else if (phoneStage.orientation == Qt.InvertedPortraitOrientation) {
4970- phoneStage.orientation = Qt.InvertedLandscapeOrientation;
4971- } else {
4972- phoneStage.orientation = Qt.PortraitOrientation;
4973- }
4974- }
4975- }
4976 }
4977 ListView {
4978 id: appList
4979@@ -283,46 +270,6 @@
4980 compare(ApplicationManager.focusedApplicationId, selectedApp.appId);
4981 }
4982
4983- function test_orientationChangeSentToFocusedApp() {
4984- phoneStage.orientation = Qt.PortraitOrientation;
4985- addApps(1);
4986-
4987- var spreadView = findChild(phoneStage, "spreadView");
4988- var app = findChild(spreadView, "appDelegate0");
4989- tryCompare(app, "orientation", Qt.PortraitOrientation);
4990-
4991- phoneStage.orientation = Qt.LandscapeOrientation;
4992- tryCompare(app, "orientation", Qt.LandscapeOrientation);
4993- }
4994-
4995- function test_orientationChangeNotSentToAppsWhileSpreadOpen() {
4996- phoneStage.orientation = Qt.PortraitOrientation;
4997- addApps(1);
4998-
4999- var spreadView = findChild(phoneStage, "spreadView");
5000- var app = findChild(spreadView, "appDelegate0");
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches