Merge lp:~dandrader/unity8/mouseEdgePush into lp:unity8

Proposed by Daniel d'Andrada
Status: Superseded
Proposed branch: lp:~dandrader/unity8/mouseEdgePush
Merge into: lp:unity8
Prerequisite: lp:~dandrader/unity8/cursorStartup
Diff against target: 2832 lines (+1243/-372)
40 files modified
data/com.canonical.Unity8.gschema.xml (+16/-0)
plugins/Cursor/MousePointer.cpp (+2/-0)
plugins/Cursor/MousePointer.h (+4/-0)
plugins/Utils/EdgeBarrierSettings.qml (+66/-0)
plugins/Utils/qmldir (+1/-0)
qml/Components/EdgeBarrier.qml (+111/-0)
qml/Components/EdgeBarrierController.qml (+71/-0)
qml/Components/PanelState/PanelState.qml (+3/-2)
qml/Components/WindowControlButtons.qml (+76/-31)
qml/Components/graphics/window-close.svg (+14/-0)
qml/Components/graphics/window-maximize.svg (+12/-0)
qml/Components/graphics/window-minimize.svg (+13/-0)
qml/Launcher/Launcher.qml (+30/-32)
qml/Launcher/LauncherPanel.qml (+7/-0)
qml/Panel/Handle.qml (+2/-2)
qml/Panel/Indicators/client/IndicatorsClient.qml (+1/-1)
qml/Panel/IndicatorsMenu.qml (+11/-2)
qml/Panel/MenuContent.qml (+1/-1)
qml/Panel/Panel.qml (+68/-80)
qml/Panel/PanelBackground.qml (+0/-21)
qml/Shell.qml (+13/-0)
qml/Stages/ApplicationWindow.qml (+29/-3)
qml/Stages/DecoratedWindow.qml (+24/-16)
qml/Stages/DesktopSpread.qml (+5/-19)
qml/Stages/DesktopStage.qml (+107/-55)
qml/Stages/SessionContainer.qml (+25/-1)
qml/Stages/SurfaceContainer.qml (+56/-4)
qml/Stages/WindowDecoration.qml (+15/-10)
qml/Stages/WindowResizeArea.qml (+66/-21)
tests/mocks/Cursor/Cursor.qml (+2/-0)
tests/mocks/Unity/Application/MirSurface.cpp (+52/-0)
tests/mocks/Unity/Application/MirSurface.h (+16/-0)
tests/mocks/Utils/EdgeBarrierSettings.qml (+22/-0)
tests/mocks/Utils/qmldir (+1/-0)
tests/qmltests/EdgeBarrierControls.qml (+97/-0)
tests/qmltests/Launcher/tst_Launcher.qml (+15/-5)
tests/qmltests/Panel/tst_Panel.qml (+45/-11)
tests/qmltests/Stages/tst_DesktopStage.qml (+96/-31)
tests/qmltests/Stages/tst_WindowResizeArea.qml (+31/-12)
tests/qmltests/tst_Shell.qml (+17/-12)
To merge this branch: bzr merge lp:~dandrader/unity8/mouseEdgePush
Reviewer Review Type Date Requested Status
Michael Zanetti (community) Approve
PS Jenkins bot (community) continuous-integration Needs Fixing
Albert Astals Cid (community) merges fine Abstain
Review via email: mp+276306@code.launchpad.net

This proposal has been superseded by a proposal from 2015-11-24.

Commit message

Mouse has to push against edges to show launcher or apps spread

edge-barrier-sensitivity is the property that should show up in the System Settings GUI.

edge-barrier-min-push and edge-barrier-max-push are exposed in GSettings merely as a convenience so you can tweak those values without having to restart unity8. But they should NOT show up in system settings.

Description of the change

* Are there any related MPs required for this MP to build/function as expected? Please list.
No

* 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?
John Lea tried it out. Values for the edge barrier parameters are still preliminary. Proper values will come once we have configurable mouse pointer speed and, most importantly, mouse pointer acceleration.

The graphical effect is following the design specification.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2021
http://jenkins.qa.ubuntu.com/job/unity8-ci/6613/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/4954
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/28/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1325
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/28
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1220
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1221
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/27
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/27
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-mako/3977
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/4951
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/4951/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24761
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-mako/16/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/28
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/28/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24763

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6613/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

There's a few qmluitests that fail to compile

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

> There's a few qmluitests that fail to compile

Fixed.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2022
http://jenkins.qa.ubuntu.com/job/unity8-ci/6636/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/4992
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/51/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1348
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/51
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1243
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1244
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/50
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/50
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-mako/4010
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/4989
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/4989/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24855
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-mako/35/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/51
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/51/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24856

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6636/rebuild

review: Needs Fixing (continuous-integration)
lp:~dandrader/unity8/mouseEdgePush updated
2022. By Daniel d'Andrada

Use SDK 1.3 across all files Fixes: #1449628, #1503498, #1508363
Approved by: PS Jenkins bot

2023. By Andrea Cimitan

Updated all 1.3 UbuntuShape to use new APIs where possible
Approved by: Albert Astals Cid

2024. By Andrea Cimitan

Make zoomable and video playback widgets edge to edge
Approved by: Albert Astals Cid

2025. By Andrea Cimitan

Add sharing widget to zoomable image and video playback
Approved by: Albert Astals Cid, Pawel Stolowski

2026. By Albert Astals Cid

Make the scope settings list scroll to text visible area
 Fixes: #1499084
Approved by: Michael Terry

2027. By Albert Astals Cid

Move to importing QtQuick 2.4 & friends

This means we obviously require Qt 5.4 or greater, we had for a while
but make it official now
Approved by: Michael Terry

2028. By Albert Astals Cid

Add an Item that proxies for old and new audio roles Fixes: #1493851

2029. By Michael Zanetti

Fixes for the panel buttons

* Hide panel buttons when switching to staged mode
* properly save/restore window states, not just geometry Fixes: #1431566, #1443319, #1504269, #1510360
Approved by: Lukáš Tinkl

2030. By Michał Sawicz

Enable support for overriding application orientations based on device type Fixes: #1478637

2031. By Michael Terry

Handle lifecycle policy exceptions ourselves, instead of letting qtmir do it for us and allow non-Touch apps to opt-out of the Touch lifecycle.

This requires using the new isTouchApp unity-api property to ApplicationInfoInterface.

Now that qtmir won't decide policy for suspending exemptions anymore, we take over the interpretation of the lifecycleException GSettings key. Since the GSettings key for that was registered under the qtmir namespace (and there's no technical reason to migrate settings), I left the schema in qtmir itself. We merely consume it.

2032. By Michał Sawicz

Support server->client visibility change to stop rendering (lp:#1475678) Fixes: #1475678
Approved by: Daniel d'Andrada

2033. By Christopher Lee

Quick spelling fix in process control output.
Approved by: Albert Astals Cid

2034. By Albert Astals Cid

CroppedImageMinimumSourceSize: Fix 'Binding loop detected for property "imageAspectRatio"'

Approved by: Gerry Boland, Michał Sawicz

2035. By Michael Terry

Avoid showing the shutdown dialog when turning on the screen if your device is under heavy load.

Specifically, we actually watch the timestamp of input events as they come in to determine how long it's been. This means that if for whatever reason, processing of events get delayed, we don't misinterpret user input.

To test this, try running the following command and then turning the screen on and off again:
sudo cpulimit -l 1 -c 1 -p `ps ax | grep dbus-daemon | head -n 1 | awk '{print $1;}'`

Without this branch, you'll notice that at some point, you see the shutdown dialog in error. Because unity8 couldn't keep up with events and thought 2s passed between power-pressed and power-released events.

But if we watch the timestamps, we can avoid that particular fate. Fixes: #1508563
Approved by: Albert Astals Cid, Michael Zanetti

2036. By CI Train Bot Account

Releasing 8.11+16.04.20151104-0ubuntu1

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2023
http://jenkins.qa.ubuntu.com/job/unity8-ci/6640/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5007
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/55/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1352
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/55
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1247
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1248
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/54
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/54
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-mako/4020
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5004
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5004/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24888
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-mako/38/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/55
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/55/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24887

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6640/rebuild

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

FAILED: Continuous integration, rev:2026
http://jenkins.qa.ubuntu.com/job/unity8-ci/6648/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5021
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/63/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1360
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/63/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1255
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1256
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/62
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/62
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-mako/4032
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5018
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5018/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24919
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/63
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/63/artifact/work/output/*zip*/output.zip

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6648/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Albert Astals Cid (aacid) wrote :

Text conflict in tests/qmltests/Stages/tst_DesktopStage.qml
1 conflicts encountered.

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

Hmm... curious why we need 3 settings for this. Wouldn't one be enough? For instance, sensitivity, going from 0 to 100, which defines the grid units to be pushed... You probably do have a reason for this, what is it?

========

The shadow on the right edge looks very wrong. And I have a feeling it's too strong on the left edge too. You sure someone from design saw this? I know John didn't so far.

====
+ anchors.top: {
+ if (edge == Qt.LeftEdge || edge == Qt.RightEdge) {
+ return target.top;
+ } else {
+ return undefined;
+ }
+ }

writing this like this:

anchors.top: edge == Qt.LeftEdge || edge == Qt.RightEdge ? target.top : undefined

is quite a bit faster in evaluating. You should avoid adding JS blocks for bindings unless the other approach really ends up being unreadable.

======

+ // to be overwritten by tests
+ property bool _containsMouse: root.containsMouse

I'm starting to think you are mocking too much. Instead of all that logic with _containsMouse, wouldn't it be nicer to just use the standard containsMouse and in the test just do a mouseMove to fulfill that?

====

+ property real _defaultMinPushThreshold :
+ property real _minPushThreshold:
+ property real _maxPushThreshold:
+ property real _accumulatedPush:

instead of all those _properties everywhere, didn't we agree to put them into private objects instead?

====

I feel like EdgeBarrierSettings isn't needed at all. The tiny bit of logic could happen in EdgeBarrier.qml too, and for mocking the settings, we already have a fully mocked GSettings backend in tests/mocks/GSettings-1.0/ which you could reuse.

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

On 06/11/2015 09:48, Michael Zanetti wrote:
> Review: Needs Fixing
>
> Hmm... curious why we need 3 settings for this. Wouldn't one be enough? For instance, sensitivity, going from 0 to 100, which defines the grid units to be pushed... You probably do have a reason for this, what is it?
>

It's explained in the commit message

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

On 06/11/2015 09:48, Michael Zanetti wrote:
> + // to be overwritten by tests
> + property bool _containsMouse: root.containsMouse
>
> I'm starting to think you are mocking too much. Instead of all that logic with _containsMouse, wouldn't it be nicer to just use the standard containsMouse and in the test just do a mouseMove to fulfill that?

I've to mock this in order to *manually* test edge barriers. Can't do
otherwise. See EdgeBarrierControls. Run "make tryLauncher".

The automated tests do not overwrite this property and do the
mouseMove() just like you mentioned.

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

On 06/11/2015 09:48, Michael Zanetti wrote:
> I feel like EdgeBarrierSettings isn't needed at all. The tiny bit of logic could happen in EdgeBarrier.qml too, and for mocking the settings, we already have a fully mocked GSettings backend in tests/mocks/GSettings-1.0/ which you could reuse.

This is to avoid doing the same work several times. This settings stuff
is a singleton and thus is calculated/evaluated only once. Whereas you
can save several EdgeBarrier instances. So yes, we don't *need* to have
it separate, but it is more efficient that way.

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

On 06/11/2015 09:48, Michael Zanetti wrote:
> The shadow on the right edge looks very wrong. And I have a feeling it's too strong on the left edge too. You sure someone from design saw this? I know John didn't so far.

The right edge and left edge shadows are the very same, just mirrored.
John Lea saw that (as I commented on the merge description). It puzzles
me to heard you say he did not...
By "wrong" you mean they're too opaque? Let's talk over IRC

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

On 06/11/2015 08:09, Albert Astals Cid wrote:
> Text conflict in tests/qmltests/Stages/tst_DesktopStage.qml
> 1 conflicts encountered.
Fixed, thanks.

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

On 06/11/2015 09:48, Michael Zanetti wrote:
> + property real _defaultMinPushThreshold :
> + property real _minPushThreshold:
> + property real _maxPushThreshold:
> + property real _accumulatedPush:
>
> instead of all those _properties everywhere, didn't we agree to put them into private objects instead?

Done.

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

On 06/11/2015 09:48, Michael Zanetti wrote:
> writing this like this:
>
> anchors.top: edge == Qt.LeftEdge || edge == Qt.RightEdge ? target.top : undefined
>
> is quite a bit faster in evaluating. You should avoid adding JS blocks for bindings unless the other approach really ends up being unreadable.

Isn't that Javascript all the same, but just in a more concise notation?

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

On 06.11.2015 14:12, Daniel d'Andrada wrote:
> On 06/11/2015 09:48, Michael Zanetti wrote:
>> writing this like this:
>>
>> anchors.top: edge == Qt.LeftEdge || edge == Qt.RightEdge ? target.top : undefined
>>
>> is quite a bit faster in evaluating. You should avoid adding JS blocks for bindings unless the other approach really ends up being unreadable.
>
> Isn't that Javascript all the same, but just in a more concise notation?
>

From http://doc.qt.io/qt-5/qtquick-performance.html#javascript-code

"There are two types of bindings in QML: optimized and non-optimized
bindings.
...
Things to avoid in binding expressions to maximize optimizability:
...
* constructing closures or defining functions within the binding expression"

If I understand that correctly, adding {} already breaks some optimizations.

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

On 06/11/2015 11:30, Michael Zanetti wrote:
>
> On 06.11.2015 14:12, Daniel d'Andrada wrote:
>> On 06/11/2015 09:48, Michael Zanetti wrote:
>>> writing this like this:
>>>
>>> anchors.top: edge == Qt.LeftEdge || edge == Qt.RightEdge ? target.top : undefined
>>>
>>> is quite a bit faster in evaluating. You should avoid adding JS blocks for bindings unless the other approach really ends up being unreadable.
>> Isn't that Javascript all the same, but just in a more concise notation?
>>
> >From http://doc.qt.io/qt-5/qtquick-performance.html#javascript-code
>
> "There are two types of bindings in QML: optimized and non-optimized
> bindings.
> ...
> Things to avoid in binding expressions to maximize optimizability:
> ...
> * constructing closures or defining functions within the binding expression"
>
> If I understand that correctly, adding {} already breaks some optimizations.
>
>

I think "{}" is a way of making scope explicit, not defining a closure
nor an internal function.

But thanks for the link. Bookmarked it. And as I said in a previous
comment, I made the change anyway as it does make the code cleaner

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2027
http://jenkins.qa.ubuntu.com/job/unity8-ci/6667/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5061
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/82/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1379
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/82
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1274
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1275
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/81
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/81
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-mako/4057
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5064
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5064/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24984
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-mako/45/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/82
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/82/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24986

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6667/rebuild

review: Needs Fixing (continuous-integration)
lp:~dandrader/unity8/mouseEdgePush updated
2037. By Launchpad Translations on behalf of unity-team

Launchpad automatic translations update.

2038. By Launchpad Translations on behalf of unity-team

Launchpad automatic translations update.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2029
http://jenkins.qa.ubuntu.com/job/unity8-ci/6675/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5073
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/90/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1387
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/90
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1282
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1283
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/89
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/89
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-mako/4063
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5078
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5078/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24994
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-mako/47/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/90
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/90/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/24993

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6675/rebuild

review: Needs Fixing (continuous-integration)
lp:~dandrader/unity8/mouseEdgePush updated
2039. By Launchpad Translations on behalf of unity-team

Launchpad automatic translations update.

2040. By Michael Terry

Make a few DBus calls asynchronous, for a smoother UX.

The calls I've changed here are neither hugely important nor frequent calls. But every little bit helps.

- Made a few sync calls async.

- Made a few sync calls more obviously sync. We had several instances of asyncCall()'s return value -- a QDBusPendingReply -- being assigned to a QDBusReply variable, which makes it wait for the call to finish. In cases where it didn't make sense to rewrite logic to be async, I've merely changed the method to be call() instead of asyncCall() for clarity.

- I removed the API in our AccountsService plugin for even making sync calls. This won't stop future developers from from writing sync code, but might give them pause.

- I removed some test mocks for our AccountsService plugin interface and changed those tests to use our actual AS plugin against a mock AS server. In truth, this change was because I had a devil of a time crafting a fake reply that included a custom complex type. But it's a good change anyway. Exercises more of our code in tests and reduces duplicated interfaces.
Approved by: Albert Astals Cid

2041. By Daniel d'Andrada

Cursor: properly initialize hotspot position Fixes: #1510407
Approved by: Gerry Boland

2042. By Albert Astals Cid

 Warn we're using only the cache when not connected to the interwebs

Approved by: Michael Terry

2043. By Michael Zanetti

added icon for the dash Fixes: #1488146
Approved by: Albert Astals Cid, Lukáš Tinkl

2044. By Daniel d'Andrada

Update GSettings mock in tst_OrientedShell

Gets rid of the following warning:
OrientedShell.qml:76: Error: Cannot assign to non-existent property "disableHeight"
Approved by: Albert Astals Cid

2045. By Andrea Cimitan

Add sharing widget to zoomable image and video playback
Approved by: Albert Astals Cid, Pawel Stolowski

2046. By Lukáš Tinkl

Restore windows when activating from the spread, maintain a focus stack

Stop displaying the "grabbing" icon when we merely click to focus the app's decoration.

Provide keyboard shortcuts for common window operations
Approved by: Michael Zanetti

2047. By Michael Zanetti

prevent windows to be moved under the panel

If they happen to have a saved state which is under the panel
(might happen on alt+drag later), they will be moved below the panel
on close and reopen. This is how unity7 behaves in this regard. Fixes: #1438465
Approved by: Lukáš Tinkl

2048. By Michael Zanetti

use UbuntuNumberAnimations instead of linear ones for window state transitions Fixes: #1497097
Approved by: Lukáš Tinkl

2049. By Albert Astals Cid

Make cardWidth and cardHeight real

If they are var the properties depending on them get reevaluated even if they don't change
Approved by: Michael Zanetti

2050. By Michael Zanetti

update inputinfo api to the latest upstream snapshot

* Import latest update of api from gerrit.
* drop all the old mock code
* instead of mocking the whole api, add mocks for the backend only. This should simplify future updates and moving to upstream implementation a lot.
* update tests to use new mocking system
Approved by: Lukáš Tinkl

2051. By Michael Zanetti

Add a warning dialog when disconnecting the external monitor.

In case there are still legacy apps running, the dialog forces the user to reconnect the external monitor, or close all the legacy apps.
Approved by: Daniel d'Andrada

2052. By Albert Astals Cid

Reset instead of qFatal when removing things from the middle

This can be optimized but let's see how this behaves, at least we won't qFatal anymore :D Fixes: #1238979
Approved by: Andrea Cimitan

2053. By CI Train Bot Account

Releasing 8.11+16.04.20151112.1-0ubuntu1

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

Updated according to design spec.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2031
http://jenkins.qa.ubuntu.com/job/unity8-ci/6746/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5278
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/161/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1459
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/161
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1353
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1354
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/160
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/160
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4187
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5298
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5298/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25295
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/38/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/161
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/161/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25294

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6746/rebuild

review: Needs Fixing (continuous-integration)
lp:~dandrader/unity8/mouseEdgePush updated
2054. By CI Train Bot Account

Resync trunk.

Revision history for this message
Albert Astals Cid (aacid) wrote :

Text conflict in qml/Stages/DesktopStage.qml
Text conflict in tests/qmltests/Stages/tst_DesktopStage.qml
Text conflict in tests/qmltests/tst_Shell.qml
3 conflicts encountered.

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

> Text conflict in qml/Stages/DesktopStage.qml
> Text conflict in tests/qmltests/Stages/tst_DesktopStage.qml
> Text conflict in tests/qmltests/tst_Shell.qml
> 3 conflicts encountered.

Fixed.

Revision history for this message
Albert Astals Cid (aacid) :
review: Abstain (merges fine)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2055
http://jenkins.qa.ubuntu.com/job/unity8-ci/6757/
Executed test runs:
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5295/console
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/172/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1470
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/172
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1364
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1365
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/171
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/171
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4200/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5315
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5315/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25333
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/44/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/172
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/172/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25334

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6757/rebuild

review: Needs Fixing (continuous-integration)
lp:~dandrader/unity8/mouseEdgePush updated
2055. By Launchpad Translations on behalf of unity-team

Launchpad automatic translations update.

2056. By Launchpad Translations on behalf of unity-team

Launchpad automatic translations update.

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

The jenkins test failure seems a real one. also, trying to run this on my laptop I get:

file:///usr/share/unity8//OrientedShell.qml:176:5: Type Shell unavailable
         Shell {
         ^
file:///usr/share/unity8//Shell.qml:537:9: Type Launcher unavailable
             Launcher {
             ^
file:///usr/share/unity8//Launcher/Launcher.qml:211:5: Type EdgeBarrier unavailable
         EdgeBarrier {
         ^
file:///usr/share/unity8//Components/EdgeBarrier.qml:65:5: Type EdgeBarrierController unavailable
         EdgeBarrierController {
         ^
file:///usr/share/unity8//Components/EdgeBarrierController.qml: Type EdgeBarrierSettings unavailable
file:///usr/lib/x86_64-linux-gnu/unity8/qml/Utils/EdgeBarrierSettings.qml:33:23: Expected token `identifier'
         property QtObject private: QtObject {

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

> The jenkins test failure seems a real one. also, trying to run this on my
> laptop I get:
> [...]

Fixed.

Also fixed the problem in tst_Shell.qml

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

I'm still not 100% satisfied with the visuals. But I understand it's a lot of fiddling to tweak that further. I'm okay with doing that in a future branch. Let's land it.

All my other review comments have been addressed, so

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

yes

 * Did CI run pass? If not, please explain why.

not yet, but issue has been fixed, let's see if next run passes.

 * Did you make sure that the branch does not contain spurious tags?

yes

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

FAILED: Continuous integration, rev:2056
http://jenkins.qa.ubuntu.com/job/unity8-ci/6776/
Executed test runs:
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5326
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/191/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1489
    FAILURE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/191/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1383
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1384
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/190
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/190
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4225
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5346
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5346/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25410
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/57/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/191
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/191/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25409

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6776/rebuild

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

I'm afraid at least some of the autopilot failures are related to the changes here. At least they passed today already on another branch (e.g. https://code.launchpad.net/~cimi/unity8/new-shadows-1.3/+merge/271611)

Can you please check them

review: Needs Information
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

FAILED: Continuous integration, rev:2057
http://jenkins.qa.ubuntu.com/job/unity8-ci/6782/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5336
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/197/console
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1495
    UNSTABLE: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/197
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1389
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1390
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/196
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/196
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4231
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5356
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5356/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25419
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/59/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/197
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/197/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25418

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6782/rebuild

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

FAILED: Continuous integration, rev:2056
http://jenkins.qa.ubuntu.com/job/unity8-ci/6783/
Executed test runs:
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-vivid-touch/5337
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-xenial-touch/198/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity-phablet-qmluitests-vivid/1496
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-qmluitest-xenial-amd64/198
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-amd64-ci/1390
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-vivid-i386-ci/1391
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-amd64-ci/197
    SUCCESS: http://jenkins.qa.ubuntu.com/job/unity8-xenial-i386-ci/197
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-vivid-touch/4232
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5357
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-vivid-armhf/5357/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25420
    FAILURE: http://jenkins.qa.ubuntu.com/job/generic-deb-autopilot-runner-xenial-touch/60/console
    SUCCESS: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/198
        deb: http://jenkins.qa.ubuntu.com/job/generic-mediumtests-builder-xenial-armhf/198/artifact/work/output/*zip*/output.zip
    SUCCESS: http://s-jenkins.ubuntu-ci:8080/job/touch-flash-device/25421

Click here to trigger a rebuild:
http://s-jenkins.ubuntu-ci:8080/job/unity8-ci/6783/rebuild

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

ok... seems that was a stale run above. jenkins looks ok now.

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

yes

 * Did CI run pass? If not, please explain why.

on v+o it did, yes. x AP tests still busted.

 * Did you make sure that the branch does not contain spurious tags?

yes

review: Approve
lp:~dandrader/unity8/mouseEdgePush updated
2057. By Daniel d'Andrada

Merge lp:~dandrader/unity8/noStretchOnResize

2058. By Daniel d'Andrada

Merge lp:~lukas-kde/unity8/newWindowDecosAndPanel

2059. By Daniel d'Andrada

Mouse has to push against edges to show launcher or apps spread

edge-barrier-sensitivity is the property that should show up in the System Settings GUI.

edge-barrier-min-push and edge-barrier-max-push are exposed in GSettings merely as a
convenience so you can tweak those values without having to restart unity8. But they
should NOT show up in system settings.

2060. By Daniel d'Andrada

Merge lp:~lukas-kde/unity8/newWindowDecosAndPanel again

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'data/com.canonical.Unity8.gschema.xml'
2--- data/com.canonical.Unity8.gschema.xml 2015-08-19 21:45:40 +0000
3+++ data/com.canonical.Unity8.gschema.xml 2015-11-24 17:51:40 +0000
4@@ -11,6 +11,22 @@
5 <summary>The usage mode.</summary>
6 <description>The usage mode chosen will affect the Window Management behaviour.</description>
7 </key>
8+ <key type="y" name="edge-barrier-sensitivity">
9+ <default>35</default>
10+ <range min="1" max="100"/>
11+ <summary>Sensitivity of screen edge barriers for the mouse pointer.</summary>
12+ <description>Some UI actions like revealing the launcher or the applications spread are triggered by pushing the mouse pointer against a screen edge. This key defines how much you have to push in order to trigger the associated action.</description>
13+ </key>
14+ <key type="u" name="edge-barrier-min-push">
15+ <default>2</default>
16+ <summary>Minimum push needed to overcome edge barrier</summary>
17+ <description>How much you have to push (in grid units)the mouse against an edge barrier when sensibility is 100.</description>
18+ </key>
19+ <key type="u" name="edge-barrier-max-push">
20+ <default>60</default>
21+ <summary>Maximum push needed to overcome edge barrier</summary>
22+ <description>How much you have to push (in grid units) the mouse against an edge barrier when sensibility is 1.</description>
23+ </key>
24 </schema>
25
26 <schema path="/com/canonical/unity8/greeter/" id="com.canonical.Unity8.Greeter" gettext-domain="unity8">
27
28=== modified file 'plugins/Cursor/MousePointer.cpp'
29--- plugins/Cursor/MousePointer.cpp 2015-11-12 20:39:12 +0000
30+++ plugins/Cursor/MousePointer.cpp 2015-11-24 17:51:40 +0000
31@@ -44,8 +44,10 @@
32
33 qreal newX = x() + movement.x();
34 if (newX < 0) {
35+ Q_EMIT pushedLeftBoundary(qAbs(newX), buttons);
36 newX = 0;
37 } else if (newX > parentItem()->width()) {
38+ Q_EMIT pushedRightBoundary(newX - parentItem()->width(), buttons);
39 newX = parentItem()->width();
40 }
41 setX(newX);
42
43=== modified file 'plugins/Cursor/MousePointer.h'
44--- plugins/Cursor/MousePointer.h 2015-10-21 16:16:37 +0000
45+++ plugins/Cursor/MousePointer.h 2015-11-24 17:51:40 +0000
46@@ -42,6 +42,10 @@
47 void handleMouseEvent(ulong timestamp, QPointF movement, Qt::MouseButtons buttons,
48 Qt::KeyboardModifiers modifiers) override;
49
50+Q_SIGNALS:
51+ void pushedLeftBoundary(qreal amount, Qt::MouseButtons buttons);
52+ void pushedRightBoundary(qreal amount, Qt::MouseButtons buttons);
53+
54 protected:
55 void itemChange(ItemChange change, const ItemChangeData &value) override;
56
57
58=== added file 'plugins/Utils/EdgeBarrierSettings.qml'
59--- plugins/Utils/EdgeBarrierSettings.qml 1970-01-01 00:00:00 +0000
60+++ plugins/Utils/EdgeBarrierSettings.qml 2015-11-24 17:51:40 +0000
61@@ -0,0 +1,66 @@
62+/*
63+ * Copyright (C) 2015 Canonical, Ltd.
64+ *
65+ * This program is free software; you can redistribute it and/or modify
66+ * it under the terms of the GNU General Public License as published by
67+ * the Free Software Foundation; version 3.
68+ *
69+ * This program is distributed in the hope that it will be useful,
70+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
71+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
72+ * GNU General Public License for more details.
73+ *
74+ * You should have received a copy of the GNU General Public License
75+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
76+ */
77+
78+pragma Singleton
79+import QtQuick 2.4
80+import GSettings 1.0
81+
82+QtObject {
83+ id: root
84+
85+ // The only public property
86+ readonly property real pushThreshold:
87+ d.minPushThreshold + ((d.maxPushThreshold - d.minPushThreshold) * (1.0 - d.sensitivity))
88+
89+ onPushThresholdChanged: {
90+ // Avoid calling d.printSettings() directly as it would spam the console during initialization
91+ d.printSettingsTimer.start();
92+ }
93+
94+ property QtObject priv: QtObject {
95+ id: d
96+
97+ property Timer printSettingsTimer: Timer {
98+ interval: 1
99+ onTriggered: printSettings();
100+ }
101+ function printSettings() {
102+ console.log("EdgeBarrierSettings: min="+(minPushThreshold/units.gu(1))+"gu("+minPushThreshold+"px)"
103+ +", max="+(maxPushThreshold/units.gu(1))+"gu("+maxPushThreshold+"px)"
104+ +", sensitivity="+sensitivity
105+ +", threshold="+(pushThreshold/units.gu(1))+"gu("+pushThreshold+"px)"
106+ );
107+ }
108+
109+ property real defaultMinPushThreshold: units.gu(2)
110+ property real minPushThreshold: gsettings.edgeBarrierMinPush ? units.gu(gsettings.edgeBarrierMinPush) : defaultMinPushThreshold
111+ property real maxPushThreshold: {
112+ if (gsettings.edgeBarrierMaxPush && units.gu(gsettings.edgeBarrierMaxPush) > minPushThreshold) {
113+ return units.gu(gsettings.edgeBarrierMaxPush);
114+ } else if (minPushThreshold == defaultMinPushThreshold) {
115+ return units.gu(60);
116+ } else {
117+ return minPushThreshold * 10.0;
118+ }
119+ }
120+ // Value range is [0.0, 1.0]
121+ readonly property real sensitivity: gsettings.edgeBarrierSensitivity
122+ ? Math.min(Math.max(0, gsettings.edgeBarrierSensitivity), 100) / 100
123+ : 0.35
124+
125+ property var gsettings: GSettings { schema.id: "com.canonical.Unity8" }
126+ }
127+}
128
129=== modified file 'plugins/Utils/qmldir'
130--- plugins/Utils/qmldir 2014-08-14 11:43:32 +0000
131+++ plugins/Utils/qmldir 2015-11-24 17:51:40 +0000
132@@ -2,3 +2,4 @@
133 plugin Utils-qml
134 typeinfo Utils.qmltypes
135 Style 0.1 Style.js
136+singleton EdgeBarrierSettings 0.1 EdgeBarrierSettings.qml
137
138=== added file 'qml/Components/EdgeBarrier.qml'
139--- qml/Components/EdgeBarrier.qml 1970-01-01 00:00:00 +0000
140+++ qml/Components/EdgeBarrier.qml 2015-11-24 17:51:40 +0000
141@@ -0,0 +1,111 @@
142+/*
143+ * Copyright (C) 2015 Canonical, Ltd.
144+ *
145+ * This program is free software; you can redistribute it and/or modify
146+ * it under the terms of the GNU General Public License as published by
147+ * the Free Software Foundation; version 3.
148+ *
149+ * This program is distributed in the hope that it will be useful,
150+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
151+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152+ * GNU General Public License for more details.
153+ *
154+ * You should have received a copy of the GNU General Public License
155+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
156+ */
157+
158+import QtQuick 2.4
159+import Ubuntu.Components 1.3
160+
161+/*
162+ An edge barrier for the mouse pointer
163+
164+ The further you push against it, the stronger the visual hint. Until it's
165+ overcome, when passed() is emitted.
166+ */
167+Item {
168+ id: root
169+
170+ // Supported values are: Qt.LeftEdge, Qt.RightEdge
171+ property int edge: Qt.LeftEdge
172+
173+ property Item target: parent
174+ function push(amount) { controller.push(amount); }
175+ signal passed()
176+
177+ anchors.top: (edge == Qt.LeftEdge || edge == Qt.RightEdge) ? target.top : undefined
178+ anchors.bottom: (edge == Qt.LeftEdge || edge == Qt.RightEdge) ? target.bottom : undefined
179+ anchors.left: edge == Qt.LeftEdge ? target.left : undefined
180+ anchors.right: edge == Qt.RightEdge ? target.right : undefined
181+
182+ width: units.gu(0.5)
183+
184+ property Component material
185+
186+ Loader {
187+ id: materialContainer
188+
189+ sourceComponent: root.material
190+
191+ anchors.top: parent.top
192+ anchors.bottom: parent.bottom
193+ anchors.left: root.edge == Qt.LeftEdge ? root.left : undefined
194+ anchors.right: root.edge == Qt.RightEdge ? root.right : undefined
195+
196+ anchors.leftMargin: root.edge == Qt.LeftEdge ? -width * (1 - positionProgress) : 0
197+ anchors.rightMargin: root.edge == Qt.RightEdge ? -width * (1 - positionProgress) : 0
198+
199+ property real positionProgress
200+
201+ visible: positionProgress > 0
202+
203+ width: units.gu(2)
204+ }
205+
206+ EdgeBarrierController {
207+ id: controller
208+ objectName: "edgeBarrierController"
209+ anchors.fill: parent
210+ onPassed: root.passed();
211+ }
212+
213+ state: {
214+ if (controller.progress === 0.0) {
215+ return "";
216+ } else if (controller.progress < 1.0) {
217+ return "resisting";
218+ } else { // controller.progress == 1.0
219+ return "passed";
220+ }
221+ }
222+ states: [
223+ State {
224+ name: ""
225+ PropertyChanges { target: materialContainer; opacity: 0.0 }
226+ PropertyChanges { target: materialContainer; positionProgress: 0.0 }
227+ },
228+ State {
229+ name: "resisting"
230+ PropertyChanges { target: materialContainer; opacity: controller.progress }
231+ PropertyChanges { target: materialContainer; positionProgress: controller.progress }
232+ },
233+ State {
234+ name: "passed"
235+ PropertyChanges { target: materialContainer; opacity: 0.0 }
236+ PropertyChanges { target: materialContainer; positionProgress: 1.0 }
237+ }
238+ ]
239+ transitions: [
240+ Transition {
241+ from: "passed"; to: ""
242+ },
243+ Transition {
244+ from: "resisting"; to: ""
245+ UbuntuNumberAnimation { target: materialContainer; properties: "opacity,positionProgress" }
246+ },
247+ Transition {
248+ from: "resisting"; to: "passed"
249+ UbuntuNumberAnimation { target: materialContainer; property: "opacity" }
250+ }
251+ ]
252+}
253
254=== added file 'qml/Components/EdgeBarrierController.qml'
255--- qml/Components/EdgeBarrierController.qml 1970-01-01 00:00:00 +0000
256+++ qml/Components/EdgeBarrierController.qml 2015-11-24 17:51:40 +0000
257@@ -0,0 +1,71 @@
258+/*
259+ * Copyright (C) 2015 Canonical, Ltd.
260+ *
261+ * This program is free software; you can redistribute it and/or modify
262+ * it under the terms of the GNU General Public License as published by
263+ * the Free Software Foundation; version 3.
264+ *
265+ * This program is distributed in the hope that it will be useful,
266+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
267+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
268+ * GNU General Public License for more details.
269+ *
270+ * You should have received a copy of the GNU General Public License
271+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
272+ */
273+
274+import QtQuick 2.4
275+import Utils 0.1 // For EdgeBarrierSettings
276+
277+MouseArea {
278+ id: root
279+
280+ hoverEnabled: true
281+
282+ // Edge push progress
283+ // Value range is [0.0, 1.0]
284+ readonly property real progress: Math.min(Math.max(0.0, _accumulatedPush / EdgeBarrierSettings.pushThreshold), 1.0)
285+
286+ // Emitted when progress reaches 1.0
287+ // Should trigger the action associated with this edge
288+ signal passed()
289+
290+ function push(amount) {
291+ if (!root._containsMouse) {
292+ return;
293+ }
294+
295+ if (_accumulatedPush === EdgeBarrierSettings.pushThreshold) {
296+ // NO-OP
297+ return;
298+ }
299+
300+ if (_accumulatedPush + amount > EdgeBarrierSettings.pushThreshold) {
301+ _accumulatedPush = EdgeBarrierSettings.pushThreshold;
302+ } else {
303+ _accumulatedPush += amount;
304+ }
305+
306+ if (_accumulatedPush === EdgeBarrierSettings.pushThreshold) {
307+ passed();
308+ }
309+ }
310+
311+ onEnabledChanged: {
312+ if (!enabled) {
313+ // reset
314+ _accumulatedPush = 0;
315+ }
316+ }
317+
318+ // to be overwritten by tests
319+ property bool _containsMouse: root.containsMouse
320+ on_ContainsMouseChanged: {
321+ if (!_containsMouse) {
322+ // reset
323+ _accumulatedPush = 0;
324+ }
325+ }
326+
327+ property real _accumulatedPush: 0
328+}
329
330=== modified file 'qml/Components/PanelState/PanelState.qml'
331--- qml/Components/PanelState/PanelState.qml 2015-11-09 10:16:18 +0000
332+++ qml/Components/PanelState/PanelState.qml 2015-11-24 17:51:40 +0000
333@@ -22,10 +22,11 @@
334
335 property string title: ""
336 property bool buttonsVisible: false
337-
338- property int panelHeight: 0
339+ property bool dropShadow: false
340+ property int panelHeight: units.gu(3)
341
342 signal close()
343 signal minimize()
344 signal maximize()
345+ signal focusMaximizedApp()
346 }
347
348=== modified file 'qml/Components/WindowControlButtons.qml'
349--- qml/Components/WindowControlButtons.qml 2015-11-04 14:57:33 +0000
350+++ qml/Components/WindowControlButtons.qml 2015-11-24 17:51:40 +0000
351@@ -1,5 +1,5 @@
352 /*
353- * Copyright (C) 2014 Canonical, Ltd.
354+ * Copyright (C) 2014-2015 Canonical, Ltd.
355 *
356 * This program is free software; you can redistribute it and/or modify
357 * it under the terms of the GNU General Public License as published by
358@@ -12,8 +12,6 @@
359 *
360 * You should have received a copy of the GNU General Public License
361 * along with this program. If not, see <http://www.gnu.org/licenses/>.
362- *
363- * Authors: Michael Zanetti <michael.zanetti@canonical.com>
364 */
365
366 import QtQuick 2.4
367@@ -21,43 +19,90 @@
368
369 Row {
370 id: root
371- spacing: units.gu(0.5)
372+ spacing: units.gu(1)
373+
374+ // to be set from outside
375+ property bool active: false
376
377 signal close()
378 signal minimize()
379 signal maximize()
380
381- Rectangle {
382+ MouseArea {
383+ id: closeWindowButton
384 objectName: "closeWindowButton"
385- height: parent.height; width: height; radius: height / 2
386- gradient: Gradient {
387- GradientStop { color: "#F49073"; position: 0 }
388- GradientStop { color: "#DF4F1C"; position: 1 }
389- }
390- border.width: units.dp(.5)
391- border.color: "black"
392- MouseArea { anchors.fill: parent; onClicked: root.close() }
393+ hoverEnabled: true
394+ height: parent.height
395+ width: height
396+ onClicked: root.close()
397+
398+ Rectangle {
399+ anchors.centerIn: parent
400+ width: units.gu(2)
401+ height: units.gu(2)
402+ radius: height / 2
403+ color: "#ed3146"
404+ visible: parent.containsMouse
405+ }
406+ Icon {
407+ width: height
408+ height: parent.height *.5
409+ anchors.centerIn: parent
410+ source: "graphics/window-close.svg"
411+ color: root.active ? "white" : "#5d5d5d"
412+ keyColor: "black"
413+ }
414 }
415- Rectangle {
416+
417+ MouseArea {
418+ id: minimizeWindowButton
419 objectName: "minimizeWindowButton"
420- height: parent.height; width: height; radius: height / 2
421- gradient: Gradient {
422- GradientStop { color: "#92918C"; position: 0 }
423- GradientStop { color: "#5E5D58"; position: 1 }
424- }
425- border.width: units.dp(.5)
426- border.color: "black"
427- MouseArea { anchors.fill: parent; onClicked: root.minimize() }
428+ hoverEnabled: true
429+ height: parent.height
430+ width: height
431+ onClicked: root.minimize()
432+
433+ Rectangle {
434+ anchors.centerIn: parent
435+ width: units.gu(2)
436+ height: units.gu(2)
437+ radius: height / 2
438+ color: "#888888"
439+ visible: parent.containsMouse
440+ }
441+ Icon {
442+ width: height
443+ height: parent.height *.5
444+ anchors.centerIn: parent
445+ source: "graphics/window-minimize.svg"
446+ color: root.active ? "white" : "#5d5d5d"
447+ keyColor: "black"
448+ }
449 }
450- Rectangle {
451+
452+ MouseArea {
453+ id: maximizeWindowButton
454 objectName: "maximizeWindowButton"
455- height: parent.height; width: height; radius: height / 2
456- gradient: Gradient {
457- GradientStop { color: "#92918C"; position: 0 }
458- GradientStop { color: "#5E5D58"; position: 1 }
459- }
460- border.width: units.dp(.5)
461- border.color: "black"
462- MouseArea { anchors.fill: parent; onClicked: root.maximize() }
463+ hoverEnabled: true
464+ height: parent.height
465+ width: height
466+ onClicked: root.maximize()
467+
468+ Rectangle {
469+ anchors.centerIn: parent
470+ width: units.gu(2)
471+ height: units.gu(2)
472+ radius: height / 2
473+ color: "#888888"
474+ visible: parent.containsMouse
475+ }
476+ Icon {
477+ width: height
478+ height: parent.height *.5
479+ anchors.centerIn: parent
480+ source: "graphics/window-maximize.svg"
481+ color: root.active ? "white" : "#5d5d5d"
482+ keyColor: "black"
483+ }
484 }
485 }
486
487=== added file 'qml/Components/graphics/window-close.svg'
488--- qml/Components/graphics/window-close.svg 1970-01-01 00:00:00 +0000
489+++ qml/Components/graphics/window-close.svg 2015-11-24 17:51:40 +0000
490@@ -0,0 +1,14 @@
491+<?xml version="1.0" encoding="iso-8859-1"?>
492+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
493+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
494+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
495+ width="94.926px" height="94.926px" viewBox="0 0 94.926 94.926" style="enable-background:new 0 0 94.926 94.926;"
496+ xml:space="preserve">
497+<g>
498+ <path d="M55.931,47.463L94.306,9.09c0.826-0.827,0.826-2.167,0-2.994L88.833,0.62C88.436,0.224,87.896,0,87.335,0
499+ c-0.562,0-1.101,0.224-1.498,0.62L47.463,38.994L9.089,0.62c-0.795-0.795-2.202-0.794-2.995,0L0.622,6.096
500+ c-0.827,0.827-0.827,2.167,0,2.994l38.374,38.373L0.622,85.836c-0.827,0.827-0.827,2.167,0,2.994l5.473,5.476
501+ c0.397,0.396,0.936,0.62,1.498,0.62s1.1-0.224,1.497-0.62l38.374-38.374l38.374,38.374c0.397,0.396,0.937,0.62,1.498,0.62
502+ s1.101-0.224,1.498-0.62l5.473-5.476c0.826-0.827,0.826-2.167,0-2.994L55.931,47.463z"/>
503+</g>
504+</svg>
505
506=== added file 'qml/Components/graphics/window-maximize.svg'
507--- qml/Components/graphics/window-maximize.svg 1970-01-01 00:00:00 +0000
508+++ qml/Components/graphics/window-maximize.svg 2015-11-24 17:51:40 +0000
509@@ -0,0 +1,12 @@
510+<?xml version="1.0" encoding="iso-8859-1"?>
511+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
512+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
513+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
514+ width="459px" height="459px" viewBox="0 0 459 459" style="enable-background:new 0 0 459 459;" xml:space="preserve">
515+<g>
516+ <g id="check-box-outline-blank">
517+ <path d="M408,51v357H51V51H408 M408,0H51C22.95,0,0,22.95,0,51v357c0,28.05,22.95,51,51,51h357c28.05,0,51-22.95,51-51V51
518+ C459,22.95,436.05,0,408,0L408,0z"/>
519+ </g>
520+</g>
521+</svg>
522
523=== added file 'qml/Components/graphics/window-minimize.svg'
524--- qml/Components/graphics/window-minimize.svg 1970-01-01 00:00:00 +0000
525+++ qml/Components/graphics/window-minimize.svg 2015-11-24 17:51:40 +0000
526@@ -0,0 +1,13 @@
527+<?xml version="1.0" encoding="iso-8859-1"?>
528+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
529+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
530+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
531+ width="121.805px" height="121.804px" viewBox="0 0 121.805 121.804" style="enable-background:new 0 0 121.805 121.804;"
532+ xml:space="preserve">
533+<g>
534+ <g>
535+ <path d="M7.308,68.211h107.188c4.037,0,7.309-3.272,7.309-7.31c0-4.037-3.271-7.309-7.309-7.309H7.308
536+ C3.272,53.593,0,56.865,0,60.902C0,64.939,3.272,68.211,7.308,68.211z"/>
537+ </g>
538+</g>
539+</svg>
540
541=== modified file 'qml/Launcher/Launcher.qml'
542--- qml/Launcher/Launcher.qml 2015-11-04 14:57:33 +0000
543+++ qml/Launcher/Launcher.qml 2015-11-24 17:51:40 +0000
544@@ -1,5 +1,5 @@
545 /*
546- * Copyright (C) 2013-2014 Canonical, Ltd.
547+ * Copyright (C) 2013-2015 Canonical, Ltd.
548 *
549 * This program is free software; you can redistribute it and/or modify
550 * it under the terms of the GNU General Public License as published by
551@@ -84,6 +84,12 @@
552 }
553 }
554
555+ function pushEdge(amount) {
556+ if (root.state === "") {
557+ edgeBarrier.push(amount);
558+ }
559+ }
560+
561 Timer {
562 id: teaseTimer
563 interval: mode == "teasing" ? 200 : 300
564@@ -96,7 +102,7 @@
565 interval: 500
566 onTriggered: {
567 if (root.autohideEnabled) {
568- if (!panel.preventHiding && !hoverArea.containsMouse) {
569+ if (!panel.preventHiding) {
570 root.state = ""
571 } else {
572 dismissTimer.restart()
573@@ -176,7 +182,6 @@
574 root.switchToNextState("visible")
575 }
576 }
577-
578 }
579
580 MultiPointTouchArea {
581@@ -203,6 +208,28 @@
582 Behavior on opacity { NumberAnimation { duration: UbuntuAnimation.BriskDuration } }
583 }
584
585+ EdgeBarrier {
586+ id: edgeBarrier
587+ edge: Qt.LeftEdge
588+ target: parent
589+ enabled: root.available
590+ onPassed: { root.switchToNextState("visibleTemporary"); }
591+ material: Component {
592+ Item {
593+ Rectangle {
594+ width: parent.height
595+ height: parent.width
596+ rotation: -90
597+ anchors.centerIn: parent
598+ gradient: Gradient {
599+ GradientStop { position: 0.0; color: panel.color}
600+ GradientStop { position: 1.0; color: Qt.rgba(panel.r,panel.g,panel.b,0)}
601+ }
602+ }
603+ }
604+ }
605+ }
606+
607 LauncherPanel {
608 id: panel
609 objectName: "launcherPanel"
610@@ -248,33 +275,6 @@
611 }
612 }
613
614- // TODO: This should be replaced by some mechanism that reveals the launcher
615- // after a certain resistance has been overcome, like unity7 does. However,
616- // as we don't get relative mouse coordinates yet, this will do for now.
617- MouseArea {
618- id: hoverArea
619- anchors { fill: panel; rightMargin: -1 }
620- hoverEnabled: true
621- propagateComposedEvents: true
622- onContainsMouseChanged: {
623- if (containsMouse) {
624- root.switchToNextState("visibleTemporary");
625- } else {
626- dismissTimer.restart();
627- }
628- }
629- onPressed: mouse.accepted = false;
630-
631- // We need to eat touch events here in order to make sure that
632- // we don't trigger both, the dragArea and the hoverArea
633- MultiPointTouchArea {
634- anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
635- width: units.dp(1)
636- mouseEnabled: false
637- enabled: parent.enabled
638- }
639- }
640-
641 DirectionalDragArea {
642 id: dragArea
643 objectName: "launcherDragArea"
644@@ -322,7 +322,6 @@
645 target: panel
646 x: -root.x // so we never go past panelWidth, even when teased by tutorial
647 }
648- PropertyChanges { target: hoverArea; enabled: false }
649 },
650 State {
651 name: "visibleTemporary"
652@@ -331,7 +330,6 @@
653 target: root
654 autohideEnabled: true
655 }
656- PropertyChanges { target: hoverArea; enabled: true }
657 },
658 State {
659 name: "teasing"
660
661=== modified file 'qml/Launcher/LauncherPanel.qml'
662--- qml/Launcher/LauncherPanel.qml 2015-11-04 14:57:13 +0000
663+++ qml/Launcher/LauncherPanel.qml 2015-11-24 17:51:40 +0000
664@@ -33,6 +33,7 @@
665 property bool dragging: false
666 property bool moving: launcherListView.moving || launcherListView.flicking
667 property bool preventHiding: moving || dndArea.draggedIndex >= 0 || quickList.state === "open" || dndArea.pressed
668+ || mouseEventEater.containsMouse || dashItem.hovered
669 property int highlightIndex: -1
670
671 signal applicationSelected(string appId)
672@@ -44,6 +45,12 @@
673 }
674 }
675
676+ MouseArea {
677+ id: mouseEventEater
678+ anchors.fill: parent
679+ hoverEnabled: true
680+ }
681+
682 Column {
683 id: mainColumn
684 anchors {
685
686=== modified file 'qml/Panel/Handle.qml'
687--- qml/Panel/Handle.qml 2015-07-15 15:07:19 +0000
688+++ qml/Panel/Handle.qml 2015-11-24 17:51:40 +0000
689@@ -19,7 +19,7 @@
690
691 Rectangle {
692 id: handle
693- color: "#333333"
694+ color: "#5d5d5d"
695 height: units.gu(2)
696 property bool active: false
697
698@@ -35,7 +35,7 @@
699 id: dot
700 width: units.dp(3)
701 height: width
702- color: handle.active ? "#de4814" : "#717171"
703+ color: handle.active ? UbuntuColors.orange : "#717171"
704 radius: units.dp(1)
705 }
706 }
707
708=== modified file 'qml/Panel/Indicators/client/IndicatorsClient.qml'
709--- qml/Panel/Indicators/client/IndicatorsClient.qml 2015-07-15 15:07:19 +0000
710+++ qml/Panel/Indicators/client/IndicatorsClient.qml 2015-11-24 17:51:40 +0000
711@@ -22,7 +22,7 @@
712 import Ubuntu.Components.ListItems 1.3 as ListItem
713
714 Rectangle {
715- color: "black"
716+ color: "#333333"
717 id: root
718
719 Component.onCompleted: {
720
721=== modified file 'qml/Panel/IndicatorsMenu.qml'
722--- qml/Panel/IndicatorsMenu.qml 2015-09-02 07:42:27 +0000
723+++ qml/Panel/IndicatorsMenu.qml 2015-11-24 17:51:40 +0000
724@@ -38,7 +38,7 @@
725 property bool enableHint: true
726 property bool contentEnabled: true
727 property bool showOnClick: true
728- property color panelColor: "black"
729+ property color panelColor: "#333333"
730
731 signal showTapped(point position)
732
733@@ -110,12 +110,21 @@
734 height: units.gu(0.5)
735 gradient: Gradient {
736 GradientStop { position: 0.0; color: "transparent" }
737- GradientStop { position: 1.0; color: "black" }
738+ GradientStop { position: 1.0; color: "#333333" }
739 }
740 opacity: 0.3
741 }
742 }
743
744+ PanelSeparatorLine {
745+ id: indicatorOrangeLine
746+ anchors {
747+ bottom: handle.top
748+ left: handle.left
749+ right: handle.right
750+ }
751+ }
752+
753 Rectangle {
754 anchors.fill: bar
755 color: panelColor
756
757=== modified file 'qml/Panel/MenuContent.qml'
758--- qml/Panel/MenuContent.qml 2015-07-15 15:13:18 +0000
759+++ qml/Panel/MenuContent.qml 2015-11-24 17:51:40 +0000
760@@ -27,7 +27,7 @@
761
762 property QtObject indicatorsModel: null
763 property int currentMenuIndex: -1
764- color: "#221e1c" // FIXME not in palette yet
765+ color: "#333333" // FIXME not in palette yet
766
767 width: units.gu(40)
768 height: units.gu(42)
769
770=== modified file 'qml/Panel/Panel.qml'
771--- qml/Panel/Panel.qml 2015-11-09 10:16:18 +0000
772+++ qml/Panel/Panel.qml 2015-11-24 17:51:40 +0000
773@@ -30,23 +30,12 @@
774 property real indicatorAreaShowProgress: 1.0
775 property bool locked: false
776
777- opacity: fullscreenMode && indicators.fullyClosed ? 0.0 : 1.0
778-
779- Binding {
780- target: PanelState
781- property: "panelHeight"
782- value: root.panelHeight
783- }
784-
785 Rectangle {
786 id: darkenedArea
787 property real darkenedOpacity: 0.6
788 anchors {
789- top: parent.top
790+ fill: parent
791 topMargin: panelHeight
792- left: parent.left
793- right: parent.right
794- bottom: parent.bottom
795 }
796 color: "black"
797 opacity: indicators.unitProgress * darkenedOpacity
798@@ -59,16 +48,18 @@
799 }
800 }
801
802+ Binding {
803+ target: PanelState
804+ property: "panelHeight"
805+ value: indicators.minimizedPanelHeight
806+ }
807+
808 Item {
809 id: indicatorArea
810 objectName: "indicatorArea"
811
812 anchors.fill: parent
813
814- Behavior on anchors.topMargin {
815- NumberAnimation { duration: UbuntuAnimation.FastDuration; easing: UbuntuAnimation.StandardEasing }
816- }
817-
818 transform: Translate {
819 y: indicators.state === "initial"
820 ? (1.0 - indicatorAreaShowProgress) * -d.indicatorHeight
821@@ -76,7 +67,7 @@
822 }
823
824 BorderImage {
825- id: dropShadow
826+ id: indicatorsDropShadow
827 anchors {
828 fill: indicators
829 leftMargin: -units.gu(1)
830@@ -86,9 +77,19 @@
831 source: "graphics/rectangular_dropshadow.sci"
832 }
833
834+ BorderImage {
835+ id: panelDropShadow
836+ anchors {
837+ fill: indicatorAreaBackground
838+ bottomMargin: -units.gu(1)
839+ }
840+ visible: PanelState.dropShadow && !callHint.visible
841+ source: "graphics/rectangular_dropshadow.sci"
842+ }
843+
844 Rectangle {
845 id: indicatorAreaBackground
846- color: callHint.visible ? "green" : "black"
847+ color: callHint.visible ? "green" : "#333333"
848 anchors {
849 top: parent.top
850 left: parent.left
851@@ -99,30 +100,6 @@
852 Behavior on color { ColorAnimation { duration: UbuntuAnimation.FastDuration } }
853 }
854
855- PanelSeparatorLine {
856- id: orangeLine
857- anchors {
858- top: indicatorAreaBackground.bottom
859- left: parent.left
860- right: indicators.left
861- }
862- saturation: 1 - indicators.unitProgress
863-
864- // Don't let input event pass trough
865- MouseArea { anchors.fill: parent }
866- }
867-
868- Image {
869- anchors {
870- top: indicators.top
871- bottom: indicators.bottom
872- right: indicators.left
873- topMargin: indicatorArea.anchors.topMargin + indicators.minimizedPanelHeight
874- }
875- width: units.dp(2)
876- source: "graphics/VerticalDivider.png"
877- }
878-
879 MouseArea {
880 anchors {
881 top: parent.top
882@@ -130,7 +107,29 @@
883 right: indicators.left
884 }
885 height: indicators.minimizedPanelHeight
886- onClicked: { if (callHint.visible) { callHint.showLiveCall(); } }
887+ hoverEnabled: true
888+ onClicked: callHint.visible ? callHint.showLiveCall() : PanelState.focusMaximizedApp()
889+ onDoubleClicked: PanelState.maximize()
890+
891+ // WindowControlButtons inside the mouse area, otherwise QML doesn't grok nested hover events :/
892+ // cf. https://bugreports.qt.io/browse/QTBUG-32909
893+ WindowControlButtons {
894+ id: windowControlButtons
895+ objectName: "panelWindowControlButtons"
896+ anchors {
897+ left: parent.left
898+ top: parent.top
899+ leftMargin: units.gu(1)
900+ topMargin: units.gu(0.5)
901+ bottomMargin: units.gu(0.5)
902+ }
903+ height: indicators.minimizedPanelHeight - anchors.topMargin - anchors.bottomMargin
904+ visible: PanelState.buttonsVisible && parent.containsMouse && !root.locked && !callHint.visible
905+ active: PanelState.buttonsVisible
906+ onClose: PanelState.close()
907+ onMinimize: PanelState.minimize()
908+ onMaximize: PanelState.maximize()
909+ }
910 }
911
912 IndicatorsMenu {
913@@ -146,7 +145,7 @@
914 width: root.width - (windowControlButtons.visible ? windowControlButtons.width + titleLabel.width : 0)
915 minimizedPanelHeight: units.gu(3)
916 expandedPanelHeight: units.gu(7)
917- openedHeight: root.height - indicatorOrangeLine.height
918+ openedHeight: root.height
919
920 overFlowWidth: {
921 if (callHint.visible) {
922@@ -163,58 +162,34 @@
923 callHint.showLiveCall();
924 }
925 }
926-
927- hideDragHandle {
928- anchors.bottomMargin: -indicatorOrangeLine.height
929- }
930- }
931-
932- WindowControlButtons {
933- id: windowControlButtons
934- objectName: "panelWindowControlButtons"
935- anchors {
936- left: parent.left
937- top: parent.top
938- margins: units.gu(0.7)
939- }
940- height: indicators.minimizedPanelHeight - anchors.margins * 2
941- visible: PanelState.buttonsVisible && !root.locked
942- onClose: PanelState.close()
943- onMinimize: PanelState.minimize()
944- onMaximize: PanelState.maximize()
945 }
946
947 Label {
948 id: titleLabel
949 objectName: "windowDecorationTitle"
950 anchors {
951- left: windowControlButtons.right
952+ left: parent.left
953 top: parent.top
954- margins: units.gu(0.7)
955+ leftMargin: units.gu(1)
956+ topMargin: units.gu(0.5)
957+ bottomMargin: units.gu(0.5)
958 }
959- color: "#DFDBD2"
960- height: windowControlButtons.height
961- visible: windowControlButtons.visible
962+ color: PanelState.buttonsVisible ? "#ffffff" : "#5d5d5d"
963+ height: indicators.minimizedPanelHeight - anchors.topMargin - anchors.bottomMargin
964+ visible: !windowControlButtons.visible && !root.locked && !callHint.visible
965 verticalAlignment: Text.AlignVCenter
966- fontSize: "small"
967- font.bold: true
968+ fontSize: "medium"
969+ font.weight: Font.Normal
970 text: PanelState.title
971 }
972
973- PanelSeparatorLine {
974- id: indicatorOrangeLine
975- anchors {
976- top: indicators.bottom
977- left: indicators.left
978- right: indicators.right
979- }
980- }
981+ // TODO here would the Locally integrated menus come
982
983 ActiveCallHint {
984 id: __callHint
985 anchors {
986 top: parent.top
987- left: windowControlButtons.visible ? windowControlButtons.right : parent.left
988+ left: parent.left
989 }
990 height: indicators.minimizedPanelHeight
991 visible: active && indicators.state == "initial"
992@@ -224,7 +199,7 @@
993 QtObject {
994 id: d
995 objectName: "panelPriv"
996- readonly property real indicatorHeight: indicators.minimizedPanelHeight + indicatorOrangeLine.height
997+ readonly property real indicatorHeight: indicators.minimizedPanelHeight
998 }
999
1000 states: [
1001@@ -234,6 +209,7 @@
1002 PropertyChanges {
1003 target: indicatorArea;
1004 anchors.topMargin: 0
1005+ opacity: 1;
1006 }
1007 },
1008 State {
1009@@ -242,6 +218,7 @@
1010 PropertyChanges {
1011 target: indicatorArea;
1012 anchors.topMargin: indicators.state === "initial" ? -d.indicatorHeight : 0
1013+ opacity: indicators.fullyClosed ? 0.0 : 1.0
1014 }
1015 PropertyChanges {
1016 target: indicators.showDragHandle;
1017@@ -249,4 +226,15 @@
1018 }
1019 }
1020 ]
1021+
1022+ transitions: [
1023+ Transition {
1024+ to: "onscreen"
1025+ UbuntuNumberAnimation { target: indicatorArea; properties: "anchors.topMargin,opacity" }
1026+ },
1027+ Transition {
1028+ to: "offscreen"
1029+ UbuntuNumberAnimation { target: indicatorArea; properties: "anchors.topMargin,opacity" }
1030+ }
1031+ ]
1032 }
1033
1034=== removed file 'qml/Panel/PanelBackground.qml'
1035--- qml/Panel/PanelBackground.qml 2015-07-15 15:07:19 +0000
1036+++ qml/Panel/PanelBackground.qml 1970-01-01 00:00:00 +0000
1037@@ -1,21 +0,0 @@
1038-/*
1039- * Copyright (C) 2013 Canonical, Ltd.
1040- *
1041- * This program is free software; you can redistribute it and/or modify
1042- * it under the terms of the GNU General Public License as published by
1043- * the Free Software Foundation; version 3.
1044- *
1045- * This program is distributed in the hope that it will be useful,
1046- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1047- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1048- * GNU General Public License for more details.
1049- *
1050- * You should have received a copy of the GNU General Public License
1051- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1052- */
1053-
1054-import QtQuick 2.4
1055-
1056-Rectangle {
1057- color: "black"
1058-}
1059
1060=== modified file 'qml/Shell.qml'
1061--- qml/Shell.qml 2015-11-06 10:06:58 +0000
1062+++ qml/Shell.qml 2015-11-24 17:51:40 +0000
1063@@ -663,6 +663,19 @@
1064 id: cursor
1065 visible: shell.hasMouse
1066 z: screenGrabber.z + 1
1067+
1068+ onPushedLeftBoundary: {
1069+ if (buttons === Qt.NoButton) {
1070+ launcher.pushEdge(amount);
1071+ }
1072+ }
1073+
1074+ onPushedRightBoundary: {
1075+ if (buttons === Qt.NoButton && applicationsDisplayLoader.item
1076+ && applicationsDisplayLoader.item.pushRightEdge) {
1077+ applicationsDisplayLoader.item.pushRightEdge(amount);
1078+ }
1079+ }
1080 }
1081
1082 Rectangle {
1083
1084=== modified file 'qml/Stages/ApplicationWindow.qml'
1085--- qml/Stages/ApplicationWindow.qml 2015-10-26 09:59:50 +0000
1086+++ qml/Stages/ApplicationWindow.qml 2015-11-24 17:51:40 +0000
1087@@ -34,6 +34,8 @@
1088 property QtObject application
1089 property int surfaceOrientationAngle
1090 property alias resizeSurface: sessionContainer.resizeSurface
1091+ property int requestedWidth: -1
1092+ property int requestedHeight: -1
1093
1094 QtObject {
1095 id: d
1096@@ -54,7 +56,7 @@
1097 // Whether the Application had a surface before but lost it.
1098 property bool hadSurface: sessionContainer.surfaceContainer.hadSurface
1099
1100- property bool needToTakeScreenshot:
1101+ readonly property bool needToTakeScreenshot:
1102 ((sessionContainer.surface && d.surfaceInitialized) || d.hadSurface)
1103 && screenshotImage.status === Image.Null
1104 && d.applicationState === ApplicationInfoInterface.Stopped
1105@@ -69,7 +71,7 @@
1106 // Remove this when possible
1107 property bool surfaceInitialized: false
1108
1109- property bool supportsSurfaceResize:
1110+ readonly property bool supportsSurfaceResize:
1111 application &&
1112 ((application.supportedOrientations & Qt.PortraitOrientation)
1113 || (application.supportedOrientations & Qt.InvertedPortraitOrientation))
1114@@ -135,7 +137,9 @@
1115 id: sessionContainer
1116 // A fake application might not even have a session property.
1117 session: application && application.session ? application.session : null
1118- anchors.fill: parent
1119+
1120+ requestedWidth: root.requestedWidth
1121+ requestedHeight: root.requestedHeight
1122
1123 surfaceOrientationAngle: application && application.rotatesWindowContents ? root.surfaceOrientationAngle : 0
1124
1125@@ -150,6 +154,28 @@
1126 focus: true
1127 }
1128
1129+ // SessionContainer size drives ApplicationWindow size
1130+ Binding {
1131+ target: root; property: "width"
1132+ value: stateGroup.state === "surface" ? sessionContainer.width : root.requestedWidth
1133+ when: root.requestedWidth >= 0
1134+ }
1135+ Binding {
1136+ target: root; property: "height"
1137+ value: stateGroup.state === "surface" ? sessionContainer.height : root.requestedHeight
1138+ when: root.requestedHeight >= 0
1139+ }
1140+
1141+ // ApplicationWindow size drives SessionContainer size
1142+ Binding {
1143+ target: sessionContainer; property: "width"; value: root.width
1144+ when: root.requestedWidth < 0
1145+ }
1146+ Binding {
1147+ target: sessionContainer; property: "height"; value: root.height
1148+ when: root.requestedHeight < 0
1149+ }
1150+
1151 StateGroup {
1152 id: stateGroup
1153 objectName: "applicationWindowStateGroup"
1154
1155=== modified file 'qml/Stages/DecoratedWindow.qml'
1156--- qml/Stages/DecoratedWindow.qml 2015-11-06 13:48:29 +0000
1157+++ qml/Stages/DecoratedWindow.qml 2015-11-24 17:51:40 +0000
1158@@ -23,29 +23,27 @@
1159 FocusScope {
1160 id: root
1161
1162+ width: applicationWindow.width
1163+ height: (decorationShown ? decoration.height : 0) + applicationWindow.height
1164+
1165 property alias window: applicationWindow
1166 property alias application: applicationWindow.application
1167 property alias active: decoration.active
1168 property alias title: decoration.title
1169+ property alias fullscreen: applicationWindow.fullscreen
1170
1171- property bool decorationShown: true
1172+ readonly property bool decorationShown: !fullscreen
1173 property bool highlightShown: false
1174 property real shadowOpacity: 1
1175
1176+ property alias requestedWidth: applicationWindow.requestedWidth
1177+ property real requestedHeight
1178+
1179 signal close()
1180 signal maximize()
1181 signal minimize()
1182 signal decorationPressed()
1183
1184- BorderImage {
1185- anchors {
1186- fill: root
1187- margins: -units.gu(2)
1188- }
1189- source: "graphics/dropshadow2gu.sci"
1190- opacity: root.shadowOpacity * .3
1191- }
1192-
1193 Rectangle {
1194 id: selectionHighlight
1195 anchors.fill: parent
1196@@ -58,7 +56,17 @@
1197 anchors { left: selectionHighlight.left; right: selectionHighlight.right; bottom: selectionHighlight.bottom; }
1198 height: units.dp(2)
1199 color: UbuntuColors.orange
1200- visible: root.highlightShown
1201+ visible: highlightShown
1202+ }
1203+
1204+ BorderImage {
1205+ anchors {
1206+ fill: root
1207+ margins: active ? -units.gu(2) : -units.gu(1.5)
1208+ }
1209+ source: "graphics/dropshadow2gu.sci"
1210+ opacity: root.shadowOpacity * .3
1211+ enabled: !fullscreen
1212 }
1213
1214 WindowDecoration {
1215@@ -68,12 +76,13 @@
1216 anchors { left: parent.left; top: parent.top; right: parent.right }
1217 height: units.gu(3)
1218 width: root.width
1219- title: window.title !== "" ? window.title : ""
1220+ title: window.title
1221+ visible: root.decorationShown
1222+
1223 onClose: root.close();
1224- onMaximize: root.maximize();
1225+ onMaximize: { root.decorationPressed(); root.maximize(); }
1226 onMinimize: root.minimize();
1227 onPressed: root.decorationPressed();
1228- visible: decorationShown
1229 }
1230
1231 ApplicationWindow {
1232@@ -82,8 +91,7 @@
1233 anchors.top: parent.top
1234 anchors.topMargin: decoration.height
1235 anchors.left: parent.left
1236- width: root.width
1237- height: root.height - decoration.height
1238+ requestedHeight: root.requestedHeight - (root.decorationShown ? decoration.height : 0)
1239 interactive: true
1240 focus: true
1241 }
1242
1243=== modified file 'qml/Stages/DesktopSpread.qml'
1244--- qml/Stages/DesktopSpread.qml 2015-11-06 13:48:29 +0000
1245+++ qml/Stages/DesktopSpread.qml 2015-11-24 17:51:40 +0000
1246@@ -28,6 +28,11 @@
1247
1248 readonly property alias highlightedIndex: spreadRepeater.highlightedIndex
1249
1250+ function show() {
1251+ spreadContainer.animateIn = true;
1252+ root.state = "altTab";
1253+ }
1254+
1255 onFocusChanged: {
1256 // When the spread comes active, we want to keep focus to the input handler below
1257 // Make sure nothing inside the ApplicationWindow grabs our focus!
1258@@ -515,23 +520,4 @@
1259 }
1260
1261 ]
1262-
1263- MouseArea {
1264- id: rightEdgePushArea
1265- anchors {
1266- top: parent.top
1267- right: parent.right
1268- bottom: parent.bottom
1269- }
1270- // TODO: Make this a push to edge thing like the launcher when we can,
1271- // for now, yes, we want 1 pixel, regardless of the scaling
1272- width: 1
1273- hoverEnabled: true
1274- onContainsMouseChanged: {
1275- if (containsMouse) {
1276- spreadContainer.animateIn = true;
1277- root.state = "altTab";
1278- }
1279- }
1280- }
1281 }
1282
1283=== modified file 'qml/Stages/DesktopStage.qml'
1284--- qml/Stages/DesktopStage.qml 2015-11-12 20:40:49 +0000
1285+++ qml/Stages/DesktopStage.qml 2015-11-24 17:51:40 +0000
1286@@ -12,12 +12,9 @@
1287 *
1288 * You should have received a copy of the GNU General Public License
1289 * along with this program. If not, see <http://www.gnu.org/licenses/>.
1290- *
1291- * Authors: Michael Zanetti <michael.zanetti@canonical.com>
1292 */
1293
1294 import QtQuick 2.4
1295-import QtQuick.Layouts 1.1
1296 import Ubuntu.Components 1.3
1297 import Unity.Application 0.1
1298 import "../Components/PanelState"
1299@@ -33,6 +30,11 @@
1300 // functions to be called from outside
1301 function updateFocusedAppOrientation() { /* TODO */ }
1302 function updateFocusedAppOrientationAnimated() { /* TODO */}
1303+ function pushRightEdge(amount) {
1304+ if (spread.state === "") {
1305+ edgeBarrier.push(amount);
1306+ }
1307+ }
1308
1309 mainApp: ApplicationManager.focusedApplicationId
1310 ? ApplicationManager.findApplication(ApplicationManager.focusedApplicationId)
1311@@ -55,7 +57,7 @@
1312 onFocusRequested: {
1313 var appIndex = priv.indexOf(appId);
1314 var appDelegate = appRepeater.itemAt(appIndex);
1315- appDelegate.restoreFromMinimized();
1316+ appDelegate.restore();
1317
1318 if (spread.state == "altTab") {
1319 spread.cancel();
1320@@ -107,7 +109,7 @@
1321 id: minimizeRestoreShortcut
1322 shortcut: Qt.MetaModifier|Qt.ControlModifier|Qt.Key_Down
1323 onTriggered: priv.focusedAppDelegate.maximized || priv.focusedAppDelegate.maximizedLeft || priv.focusedAppDelegate.maximizedRight
1324- ? priv.focusedAppDelegate.restore() : priv.focusedAppDelegate.minimize(true)
1325+ ? priv.focusedAppDelegate.restoreFromMaximized() : priv.focusedAppDelegate.minimize()
1326 active: priv.focusedAppDelegate !== null
1327 }
1328
1329@@ -119,18 +121,16 @@
1330 var index = indexOf(focusedAppId);
1331 return index >= 0 && index < appRepeater.count ? appRepeater.itemAt(index) : null
1332 }
1333+ onFocusedAppDelegateChanged: updateForegroundMaximizedApp();
1334+
1335 property int foregroundMaximizedAppIdIndex: -1
1336
1337 function updateForegroundMaximizedApp() {
1338 for (var i = 0; i < appRepeater.count; i++) {
1339 var item = appRepeater.itemAt(i);
1340-
1341 if (item && item.visuallyMaximized) {
1342- var app = ApplicationManager.get(i);
1343- if (app) {
1344- foregroundMaximizedAppIdIndex = i;
1345- return;
1346- }
1347+ foregroundMaximizedAppIdIndex = i;
1348+ return;
1349 }
1350 }
1351 foregroundMaximizedAppIdIndex = -1;
1352@@ -149,7 +149,7 @@
1353 for (var i = 0; i < appRepeater.count; i++) {
1354 var appDelegate = appRepeater.itemAt(i);
1355 if (appDelegate && !appDelegate.minimized) {
1356- appDelegate.minimize(false); // minimize but don't switch focus
1357+ appDelegate.minimize();
1358 }
1359 }
1360
1361@@ -173,24 +173,47 @@
1362 onClose: {
1363 ApplicationManager.stopApplication(ApplicationManager.focusedApplicationId)
1364 }
1365- onMinimize: appRepeater.itemAt(0).minimize(true);
1366- onMaximize: appRepeater.itemAt(0).restore();
1367+ onMinimize: priv.focusedAppDelegate && priv.focusedAppDelegate.minimize();
1368+ onMaximize: priv.focusedAppDelegate // don't restore minimized apps when double clicking the panel
1369+ && priv.focusedAppDelegate.restoreFromMaximized();
1370+ onFocusMaximizedApp: if (priv.foregroundMaximizedAppIdIndex != -1) {
1371+ ApplicationManager.focusApplication(appRepeater.itemAt(priv.foregroundMaximizedAppIdIndex).appId);
1372+ }
1373 }
1374
1375 Binding {
1376 target: PanelState
1377 property: "buttonsVisible"
1378- value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized
1379+ value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.maximized // FIXME for Locally integrated menus
1380+ && spread.state == ""
1381 }
1382
1383 Binding {
1384 target: PanelState
1385 property: "title"
1386- value: priv.focusedAppDelegate !== null && priv.focusedAppDelegate.title
1387- when: priv.focusedAppDelegate && priv.focusedAppDelegate.maximized
1388- }
1389-
1390- Component.onDestruction: PanelState.buttonsVisible = false;
1391+ value: {
1392+ if (priv.focusedAppDelegate !== null && spread.state == "") {
1393+ if (priv.focusedAppDelegate.maximized)
1394+ return priv.focusedAppDelegate.title
1395+ else
1396+ return priv.focusedAppDelegate.appName
1397+ }
1398+ return ""
1399+ }
1400+ when: priv.focusedAppDelegate
1401+ }
1402+
1403+ Binding {
1404+ target: PanelState
1405+ property: "dropShadow"
1406+ value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppIdIndex !== -1
1407+ }
1408+
1409+ Component.onDestruction: {
1410+ PanelState.title = "";
1411+ PanelState.buttonsVisible = false;
1412+ PanelState.dropShadow = false;
1413+ }
1414
1415 FocusScope {
1416 id: appContainer
1417@@ -211,17 +234,16 @@
1418 model: ApplicationManager
1419 objectName: "appRepeater"
1420
1421- onItemAdded: priv.updateForegroundMaximizedApp()
1422- onItemRemoved: priv.updateForegroundMaximizedApp()
1423-
1424 delegate: FocusScope {
1425 id: appDelegate
1426 objectName: "appDelegate_" + appId
1427 z: ApplicationManager.count - index
1428- y: units.gu(3)
1429- width: units.gu(60)
1430- height: units.gu(50)
1431+ y: PanelState.panelHeight
1432 focus: appId === priv.focusedAppId
1433+ width: decoratedWindow.width
1434+ height: decoratedWindow.height
1435+ property alias requestedWidth: decoratedWindow.requestedWidth
1436+ property alias requestedHeight: decoratedWindow.requestedHeight
1437
1438 QtObject {
1439 id: appDelegatePrivate
1440@@ -238,6 +260,7 @@
1441 readonly property string appId: model.appId
1442 property bool animationsEnabled: true
1443 property alias title: decoratedWindow.title
1444+ readonly property string appName: model.name
1445 property bool visuallyMaximized: false
1446 property bool visuallyMinimized: false
1447
1448@@ -247,7 +270,6 @@
1449 }
1450 }
1451
1452- onZChanged: priv.updateForegroundMaximizedApp()
1453 onVisuallyMaximizedChanged: priv.updateForegroundMaximizedApp()
1454
1455 visible: !visuallyMinimized &&
1456@@ -287,19 +309,18 @@
1457 }
1458 function minimize(animated) {
1459 animationsEnabled = (animated === undefined) || animated;
1460- appDelegatePrivate.maximized = false;
1461 appDelegatePrivate.minimized = true;
1462 }
1463+ function restoreFromMaximized(animated) {
1464+ animationsEnabled = (animated === undefined) || animated;
1465+ appDelegatePrivate.minimized = false;
1466+ appDelegatePrivate.maximized = false;
1467+ appDelegatePrivate.maximizedLeft = false;
1468+ appDelegatePrivate.maximizedRight = false;
1469+ }
1470 function restore(animated) {
1471 animationsEnabled = (animated === undefined) || animated;
1472 appDelegatePrivate.minimized = false;
1473- appDelegatePrivate.maximized = false;
1474- appDelegatePrivate.maximizedLeft = false;
1475- appDelegatePrivate.maximizedRight = false;
1476- }
1477- function restoreFromMinimized(animated) {
1478- animationsEnabled = (animated === undefined) || animated;
1479- appDelegatePrivate.minimized = false;
1480 if (maximized)
1481 maximize();
1482 else if (maximizedLeft)
1483@@ -311,6 +332,14 @@
1484
1485 states: [
1486 State {
1487+ name: "fullscreen"; when: decoratedWindow.fullscreen
1488+ extend: "maximized"
1489+ PropertyChanges {
1490+ target: appDelegate;
1491+ y: -PanelState.panelHeight
1492+ }
1493+ },
1494+ State {
1495 name: "normal";
1496 when: !appDelegate.maximized && !appDelegate.minimized
1497 && !appDelegate.maximizedLeft && !appDelegate.maximizedRight
1498@@ -321,22 +350,24 @@
1499 }
1500 },
1501 State {
1502- name: "maximized"; when: appDelegate.maximized
1503+ name: "maximized"; when: appDelegate.maximized && !appDelegate.minimized
1504 PropertyChanges {
1505 target: appDelegate;
1506 x: 0; y: 0;
1507- width: root.width; height: root.height;
1508+ requestedWidth: root.width; requestedHeight: root.height;
1509 visuallyMinimized: false;
1510 visuallyMaximized: true
1511 }
1512 },
1513 State {
1514 name: "maximizedLeft"; when: appDelegate.maximizedLeft && !appDelegate.minimized
1515- PropertyChanges { target: appDelegate; x: 0; y: units.gu(3); width: root.width/2; height: root.height - units.gu(3) }
1516+ PropertyChanges { target: appDelegate; x: 0; y: PanelState.panelHeight;
1517+ requestedWidth: root.width/2; requestedHeight: root.height - PanelState.panelHeight }
1518 },
1519 State {
1520 name: "maximizedRight"; when: appDelegate.maximizedRight && !appDelegate.minimized
1521- PropertyChanges { target: appDelegate; x: root.width/2; y: units.gu(3); width: root.width/2; height: root.height - units.gu(3) }
1522+ PropertyChanges { target: appDelegate; x: root.width/2; y: PanelState.panelHeight;
1523+ requestedWidth: root.width/2; requestedHeight: root.height - PanelState.panelHeight }
1524 },
1525 State {
1526 name: "minimized"; when: appDelegate.minimized
1527@@ -355,32 +386,32 @@
1528 to: "normal"
1529 enabled: appDelegate.animationsEnabled
1530 PropertyAction { target: appDelegate; properties: "visuallyMinimized,visuallyMaximized" }
1531- UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale"; duration: UbuntuAnimation.FastDuration }
1532- },
1533- Transition {
1534- to: "maximized"
1535- enabled: appDelegate.animationsEnabled
1536- PropertyAction { target: appDelegate; property: "visuallyMinimized" }
1537- SequentialAnimation {
1538- UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale"; duration: UbuntuAnimation.FastDuration }
1539- PropertyAction { target: appDelegate; property: "visuallyMaximized" }
1540- }
1541+ UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,requestedWidth,requestedHeight,scale"; duration: UbuntuAnimation.FastDuration }
1542 },
1543 Transition {
1544 to: "minimized"
1545 enabled: appDelegate.animationsEnabled
1546 PropertyAction { target: appDelegate; property: "visuallyMaximized" }
1547 SequentialAnimation {
1548- UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale"; duration: UbuntuAnimation.FastDuration }
1549+ UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,requestedWidth,requestedHeight,scale"; duration: UbuntuAnimation.FastDuration }
1550 PropertyAction { target: appDelegate; property: "visuallyMinimized" }
1551 ScriptAction {
1552 script: {
1553- if (appDelegate.animationsEnabled && state === "minimized" ) {
1554+ if (appDelegate.minimized) {
1555 priv.focusNext();
1556 }
1557 }
1558 }
1559 }
1560+ },
1561+ Transition {
1562+ to: "*" //maximized and fullscreen
1563+ enabled: appDelegate.animationsEnabled
1564+ PropertyAction { target: appDelegate; property: "visuallyMinimized" }
1565+ SequentialAnimation {
1566+ UbuntuNumberAnimation { target: appDelegate; properties: "x,y,opacity,requestedWidth,requestedHeight,scale"; duration: UbuntuAnimation.FastDuration }
1567+ PropertyAction { target: appDelegate; property: "visuallyMaximized" }
1568+ }
1569 }
1570 ]
1571
1572@@ -410,16 +441,14 @@
1573 objectName: "decoratedWindow"
1574 anchors.left: appDelegate.left
1575 anchors.top: appDelegate.top
1576- width: appDelegate.width
1577- height: appDelegate.height
1578 application: ApplicationManager.get(index)
1579 active: ApplicationManager.focusedApplicationId === model.appId
1580 focus: true
1581
1582 onClose: ApplicationManager.stopApplication(model.appId)
1583 onMaximize: appDelegate.maximized || appDelegate.maximizedLeft || appDelegate.maximizedRight
1584- ? appDelegate.restore() : appDelegate.maximize()
1585- onMinimize: appDelegate.minimize(true)
1586+ ? appDelegate.restoreFromMaximized() : appDelegate.maximize()
1587+ onMinimize: appDelegate.minimize()
1588 onDecorationPressed: { ApplicationManager.focusApplication(model.appId) }
1589 }
1590 }
1591@@ -447,6 +476,29 @@
1592 enabled: visible
1593 }
1594
1595+ EdgeBarrier {
1596+ id: edgeBarrier
1597+
1598+ // NB: it does its own positioning according to the specified edge
1599+ edge: Qt.RightEdge
1600+
1601+ onPassed: { spread.show(); }
1602+ material: Component {
1603+ Item {
1604+ Rectangle {
1605+ width: parent.height
1606+ height: parent.width
1607+ rotation: 90
1608+ anchors.centerIn: parent
1609+ gradient: Gradient {
1610+ GradientStop { position: 0.0; color: Qt.rgba(0.16,0.16,0.16,0.7)}
1611+ GradientStop { position: 1.0; color: Qt.rgba(0.16,0.16,0.16,0)}
1612+ }
1613+ }
1614+ }
1615+ }
1616+ }
1617+
1618 DesktopSpread {
1619 id: spread
1620 objectName: "spread"
1621
1622=== modified file 'qml/Stages/SessionContainer.qml'
1623--- qml/Stages/SessionContainer.qml 2015-09-29 12:28:10 +0000
1624+++ qml/Stages/SessionContainer.qml 2015-11-24 17:51:40 +0000
1625@@ -29,13 +29,37 @@
1626 property alias surfaceOrientationAngle: _surfaceContainer.surfaceOrientationAngle
1627 property alias resizeSurface: _surfaceContainer.resizeSurface
1628
1629+ property int requestedWidth: -1
1630+ property int requestedHeight: -1
1631+
1632 readonly property alias surfaceContainer: _surfaceContainer
1633 SurfaceContainer {
1634 id: _surfaceContainer
1635- anchors.fill: parent
1636+ requestedWidth: root.requestedWidth
1637+ requestedHeight: root.requestedHeight
1638 surface: session ? session.surface : null
1639 }
1640
1641+ // SurfaceContainer size drives SessionContainer size
1642+ Binding {
1643+ target: root; property: "width"; value: _surfaceContainer.width
1644+ when: root.requestedWidth >= 0
1645+ }
1646+ Binding {
1647+ target: root; property: "height"; value: _surfaceContainer.height
1648+ when: root.requestedHeight >= 0
1649+ }
1650+
1651+ // SessionContainer size drives SurfaceContainer size
1652+ Binding {
1653+ target: _surfaceContainer; property: "width"; value: root.width
1654+ when: root.requestedWidth < 0
1655+ }
1656+ Binding {
1657+ target: _surfaceContainer; property: "height"; value: root.height
1658+ when: root.requestedHeight < 0
1659+ }
1660+
1661 Repeater {
1662 id: childSessionsRepeater
1663 model: root.childSessions
1664
1665=== modified file 'qml/Stages/SurfaceContainer.qml'
1666--- qml/Stages/SurfaceContainer.qml 2015-10-26 09:59:50 +0000
1667+++ qml/Stages/SurfaceContainer.qml 2015-11-24 17:51:40 +0000
1668@@ -31,6 +31,9 @@
1669 property string name: surface ? surface.name : ""
1670 property bool resizeSurface: true
1671
1672+ property int requestedWidth: -1
1673+ property int requestedHeight: -1
1674+
1675 onSurfaceChanged: {
1676 if (surface) {
1677 surfaceItem.surface = surface;
1678@@ -54,16 +57,65 @@
1679
1680 consumesInput: true
1681
1682- surfaceWidth: root.resizeSurface ? width : -1
1683- surfaceHeight: root.resizeSurface ? height : -1
1684-
1685- anchors.fill: root
1686+ surfaceWidth: {
1687+ if (root.resizeSurface) {
1688+ if (root.requestedWidth >= 0) {
1689+ return root.requestedWidth;
1690+ } else {
1691+ return width;
1692+ }
1693+ } else {
1694+ return -1;
1695+ }
1696+ }
1697+
1698+ surfaceHeight: {
1699+ if (root.resizeSurface) {
1700+ if (root.requestedHeight >= 0) {
1701+ return root.requestedHeight;
1702+ } else {
1703+ return height;
1704+ }
1705+ } else {
1706+ return -1;
1707+ }
1708+ }
1709+
1710 enabled: root.interactive
1711 focus: true
1712 antialiasing: !root.interactive
1713 orientationAngle: root.surfaceOrientationAngle
1714 }
1715
1716+ // MirSurface size drives SurfaceContainer size
1717+ Binding {
1718+ target: surfaceItem; property: "width"; value: root.surface ? root.surface.size.width : 0
1719+ when: root.requestedWidth >= 0 && root.surface
1720+ }
1721+ Binding {
1722+ target: surfaceItem; property: "height"; value: root.surface ? root.surface.size.height : 0
1723+ when: root.requestedHeight >= 0 && root.surface
1724+ }
1725+ Binding {
1726+ target: root; property: "width"; value: surfaceItem.width
1727+ when: root.requestedWidth >= 0
1728+ }
1729+ Binding {
1730+ target: root; property: "height"; value: surfaceItem.height
1731+ when: root.requestedHeight >= 0
1732+ }
1733+
1734+ // SurfaceContainer size drives MirSurface size
1735+ Binding {
1736+ target: surfaceItem; property: "width"; value: root.width
1737+ when: root.requestedWidth < 0
1738+ }
1739+ Binding {
1740+ target: surfaceItem; property: "height"; value: root.height
1741+ when: root.requestedHeight < 0
1742+ }
1743+
1744+
1745 TouchGate {
1746 targetItem: surfaceItem
1747 anchors.fill: root
1748
1749=== modified file 'qml/Stages/WindowDecoration.qml'
1750--- qml/Stages/WindowDecoration.qml 2015-11-09 10:16:18 +0000
1751+++ qml/Stages/WindowDecoration.qml 2015-11-24 17:51:40 +0000
1752@@ -33,6 +33,8 @@
1753 signal minimize()
1754 signal maximize()
1755
1756+ onDoubleClicked: root.maximize()
1757+
1758 QtObject {
1759 id: priv
1760 property real distanceX
1761@@ -65,20 +67,23 @@
1762 anchors.fill: parent
1763 anchors.bottomMargin: -radius
1764 radius: units.gu(.5)
1765- gradient: Gradient {
1766- GradientStop { color: "#626055"; position: 0 }
1767- GradientStop { color: "#3C3B37"; position: 1 }
1768- }
1769+ color: "#333333"
1770 }
1771
1772 Row {
1773- anchors { fill: parent; margins: units.gu(0.7) }
1774- spacing: units.gu(1)
1775- opacity: root.active ? 1 : 0.5
1776+ anchors {
1777+ fill: parent
1778+ leftMargin: units.gu(1)
1779+ rightMargin: units.gu(1)
1780+ topMargin: units.gu(0.5)
1781+ bottomMargin: units.gu(0.5)
1782+ }
1783+ spacing: units.gu(3)
1784
1785 WindowControlButtons {
1786 id: buttons
1787 height: parent.height
1788+ active: root.active
1789 onClose: root.close();
1790 onMinimize: root.minimize();
1791 onMaximize: root.maximize();
1792@@ -87,12 +92,12 @@
1793 Label {
1794 id: titleLabel
1795 objectName: "windowDecorationTitle"
1796- color: "#DFDBD2"
1797+ color: root.active ? "white" : "#5d5d5d"
1798 height: parent.height
1799 width: parent.width - buttons.width - parent.anchors.rightMargin - parent.anchors.leftMargin
1800 verticalAlignment: Text.AlignVCenter
1801- fontSize: "small"
1802- font.bold: true
1803+ fontSize: "medium"
1804+ font.weight: root.active ? Font.Light : Font.Normal
1805 elide: Text.ElideRight
1806 }
1807 }
1808
1809=== modified file 'qml/Stages/WindowResizeArea.qml'
1810--- qml/Stages/WindowResizeArea.qml 2015-11-09 10:52:53 +0000
1811+++ qml/Stages/WindowResizeArea.qml 2015-11-24 17:51:40 +0000
1812@@ -25,7 +25,7 @@
1813 anchors.fill: target
1814 anchors.margins: -borderThickness
1815
1816- hoverEnabled: true
1817+ hoverEnabled: target && !target.maximized // don't grab the resize under the panel
1818
1819 property var windowStateStorage: WindowStateStorage
1820
1821@@ -36,6 +36,8 @@
1822 property int borderThickness: 0
1823 property int minWidth: 0
1824 property int minHeight: 0
1825+ property int defaultWidth: units.gu(60)
1826+ property int defaultHeight: units.gu(50)
1827 property int screenWidth: 0
1828 property int screenHeight: 0
1829
1830@@ -67,13 +69,14 @@
1831 }
1832
1833 Component.onCompleted: {
1834- var windowGeometry = windowStateStorage.getGeometry(root.windowId, Qt.rect(target.x, target.y, target.width, target.height))
1835- if (windowGeometry !== undefined) {
1836- target.width = Math.min(windowGeometry.width, root.screenWidth)
1837- target.height = Math.min(windowGeometry.height, root.screenHeight - PanelState.panelHeight)
1838- target.x = Math.max(Math.min(windowGeometry.x, root.screenWidth - target.width), 0)
1839- target.y = Math.max(Math.min(windowGeometry.y, root.screenHeight - target.height), PanelState.panelHeight)
1840- }
1841+ var windowGeometry = windowStateStorage.getGeometry(root.windowId,
1842+ Qt.rect(target.x, target.y, defaultWidth, defaultHeight));
1843+
1844+ target.requestedWidth = Math.min(Math.max(windowGeometry.width, minWidth), screenWidth);
1845+ target.requestedHeight = Math.min(Math.max(windowGeometry.height, minHeight), root.screenHeight - PanelState.panelHeight);
1846+ target.x = Math.max(Math.min(windowGeometry.x, root.screenWidth - target.requestedWidth), 0)
1847+ target.y = Math.max(Math.min(windowGeometry.y, root.screenHeight - target.requestedHeight), PanelState.panelHeight)
1848+
1849 var windowState = windowStateStorage.getState(root.windowId, WindowStateStorage.WindowStateNormal)
1850 if (windowState === WindowStateStorage.WindowStateMaximized) {
1851 target.maximize(false)
1852@@ -93,6 +96,18 @@
1853 property bool topBorder: false
1854 property bool bottomBorder: false
1855
1856+ // true - A change in surface size will cause the left border of the window to move accordingly.
1857+ // The window's right border will stay in the same position.
1858+ // false - a change in surface size will cause the right border of the window to move accordingly.
1859+ // The window's left border will stay in the same position.
1860+ property bool moveLeftBorder: false
1861+
1862+ // true - A change in surface size will cause the top border of the window to move accordingly.
1863+ // The window's bottom border will stay in the same position.
1864+ // false - a change in surface size will cause the bottom border of the window to move accordingly.
1865+ // The window's top border will stay in the same position.
1866+ property bool moveTopBorder: false
1867+
1868 property bool dragging: false
1869 property real startMousePosX
1870 property real startMousePosY
1871@@ -100,6 +115,8 @@
1872 property real startY
1873 property real startWidth
1874 property real startHeight
1875+ property real currentWidth
1876+ property real currentHeight
1877
1878 property string cursorName: {
1879 if (root.containsMouse || root.pressed) {
1880@@ -138,11 +155,24 @@
1881 }
1882 }
1883
1884+ Timer {
1885+ id: resetBordersToMoveTimer
1886+ interval: 2000
1887+ onTriggered: {
1888+ d.moveLeftBorder = false;
1889+ d.moveTopBorder = false;
1890+ }
1891+ }
1892+
1893 onPressedChanged: {
1894 var pos = mapToItem(target.parent, mouseX, mouseY);
1895
1896 if (pressed) {
1897 d.updateBorders();
1898+ resetBordersToMoveTimer.stop();
1899+ d.moveLeftBorder = d.leftBorder;
1900+ d.moveTopBorder = d.topBorder;
1901+
1902 var pos = mapToItem(root.target.parent, mouseX, mouseY);
1903 d.startMousePosX = pos.x;
1904 d.startMousePosY = pos.y;
1905@@ -150,8 +180,11 @@
1906 d.startY = target.y;
1907 d.startWidth = target.width;
1908 d.startHeight = target.height;
1909+ d.currentWidth = target.width;
1910+ d.currentHeight = target.height;
1911 d.dragging = true;
1912 } else {
1913+ resetBordersToMoveTimer.start();
1914 d.dragging = false;
1915 if (containsMouse) {
1916 d.updateBorders();
1917@@ -182,37 +215,49 @@
1918 if (d.leftBorder) {
1919 var newTargetX = d.startX + deltaX;
1920 if (target.x + target.width > newTargetX + minWidth) {
1921- target.width = target.x + target.width - newTargetX;
1922- target.x = newTargetX;
1923+ target.requestedWidth = target.x + target.width - newTargetX;
1924 } else {
1925- target.x = target.x + target.width - minWidth;
1926- target.width = minWidth;
1927+ target.requestedWidth = minWidth;
1928 }
1929
1930 } else if (d.rightBorder) {
1931 if (d.startWidth + deltaX >= minWidth) {
1932- target.width = d.startWidth + deltaX;
1933+ target.requestedWidth = d.startWidth + deltaX;
1934 } else {
1935- target.width = minWidth;
1936+ target.requestedWidth = minWidth;
1937 }
1938 }
1939
1940 if (d.topBorder) {
1941 var newTargetY = d.startY + deltaY;
1942 if (target.y + target.height > newTargetY + minHeight) {
1943- target.height = target.y + target.height - newTargetY;
1944- target.y = newTargetY;
1945+ target.requestedHeight = target.y + target.height - newTargetY;
1946 } else {
1947- target.y = target.y + target.height - minHeight;
1948- target.height = minHeight;
1949+ target.requestedHeight = minHeight;
1950 }
1951
1952 } else if (d.bottomBorder) {
1953 if (d.startHeight + deltaY >= minHeight) {
1954- target.height = d.startHeight + deltaY;
1955+ target.requestedHeight = d.startHeight + deltaY;
1956 } else {
1957- target.height = minHeight;
1958- }
1959+ target.requestedHeight = minHeight;
1960+ }
1961+ }
1962+ }
1963+
1964+ Connections {
1965+ target: root.target
1966+ onWidthChanged: {
1967+ if (d.moveLeftBorder) {
1968+ target.x += d.currentWidth - target.width;
1969+ }
1970+ d.currentWidth = target.width;
1971+ }
1972+ onHeightChanged: {
1973+ if (d.moveTopBorder) {
1974+ target.y += d.currentHeight - target.height;
1975+ }
1976+ d.currentHeight = target.height;
1977 }
1978 }
1979 }
1980
1981=== modified file 'tests/mocks/Cursor/Cursor.qml'
1982--- tests/mocks/Cursor/Cursor.qml 2015-09-29 13:45:05 +0000
1983+++ tests/mocks/Cursor/Cursor.qml 2015-11-24 17:51:40 +0000
1984@@ -17,4 +17,6 @@
1985 import QtQuick 2.4
1986
1987 Item {
1988+ signal pushedLeftBoundary(real amount, int buttons)
1989+ signal pushedRightBoundary(real amount, int buttons)
1990 }
1991
1992=== modified file 'tests/mocks/Unity/Application/MirSurface.cpp'
1993--- tests/mocks/Unity/Application/MirSurface.cpp 2015-10-27 21:55:10 +0000
1994+++ tests/mocks/Unity/Application/MirSurface.cpp 2015-11-24 17:51:40 +0000
1995@@ -35,8 +35,12 @@
1996 , m_activeFocus(false)
1997 , m_width(-1)
1998 , m_height(-1)
1999+ , m_slowToResize(false)
2000 {
2001 // qDebug() << "MirSurface::MirSurface() " << name;
2002+ m_delayedResizeTimer.setInterval(600);
2003+ m_delayedResizeTimer.setSingleShot(true);
2004+ connect(&m_delayedResizeTimer, &QTimer::timeout, this, &MirSurface::applyDelayedResize);
2005 }
2006
2007 MirSurface::~MirSurface()
2008@@ -197,7 +201,38 @@
2009
2010 void MirSurface::resize(int width, int height)
2011 {
2012+ if (m_slowToResize) {
2013+ if (!m_delayedResizeTimer.isActive()) {
2014+ m_delayedResize.setWidth(width);
2015+ m_delayedResize.setHeight(height);
2016+ m_delayedResizeTimer.start();
2017+ } else {
2018+ m_pendingResize.setWidth(width);
2019+ m_pendingResize.setHeight(height);
2020+ }
2021+ } else {
2022+ doResize(width, height);
2023+ }
2024+}
2025+
2026+void MirSurface::applyDelayedResize()
2027+{
2028+ doResize(m_delayedResize.width(), m_delayedResize.height());
2029+ m_delayedResize.setWidth(-1);
2030+ m_delayedResize.setHeight(-1);
2031+
2032+ if (m_pendingResize.isValid()) {
2033+ QSize size = m_pendingResize;
2034+ m_pendingResize.setWidth(-1);
2035+ m_pendingResize.setHeight(-1);
2036+ resize(size.width(), size.height());
2037+ }
2038+}
2039+
2040+void MirSurface::doResize(int width, int height)
2041+{
2042 bool changed = false;
2043+
2044 if (width != m_width) {
2045 m_width = width;
2046 Q_EMIT widthChanged();
2047@@ -214,3 +249,20 @@
2048 Q_EMIT sizeChanged(QSize(width, height));
2049 }
2050 }
2051+
2052+bool MirSurface::isSlowToResize() const
2053+{
2054+ return m_slowToResize;
2055+}
2056+
2057+void MirSurface::setSlowToResize(bool value)
2058+{
2059+ if (m_slowToResize != value) {
2060+ m_slowToResize = value;
2061+ Q_EMIT slowToResizeChanged();
2062+ if (!m_slowToResize && m_delayedResizeTimer.isActive()) {
2063+ m_delayedResizeTimer.stop();
2064+ applyDelayedResize();
2065+ }
2066+ }
2067+}
2068
2069=== modified file 'tests/mocks/Unity/Application/MirSurface.h'
2070--- tests/mocks/Unity/Application/MirSurface.h 2015-10-20 16:48:06 +0000
2071+++ tests/mocks/Unity/Application/MirSurface.h 2015-11-24 17:51:40 +0000
2072@@ -18,6 +18,7 @@
2073 #define MOCK_MIR_SURFACE_H
2074
2075 #include <QObject>
2076+#include <QTimer>
2077 #include <QUrl>
2078 #include <QHash>
2079
2080@@ -33,6 +34,7 @@
2081 Q_PROPERTY(int width READ width NOTIFY widthChanged)
2082 Q_PROPERTY(int height READ height NOTIFY heightChanged)
2083 Q_PROPERTY(bool activeFocus READ activeFocus NOTIFY activeFocusChanged)
2084+ Q_PROPERTY(bool slowToResize READ isSlowToResize WRITE setSlowToResize NOTIFY slowToResizeChanged)
2085
2086 public:
2087 MirSurface(const QString& name,
2088@@ -77,6 +79,9 @@
2089 int width() const;
2090 int height() const;
2091
2092+ bool isSlowToResize() const;
2093+ void setSlowToResize(bool value);
2094+
2095 /////
2096 // internal mock stuff
2097
2098@@ -94,13 +99,18 @@
2099 void orientationAngleChanged(Mir::OrientationAngle angle);
2100 void widthChanged();
2101 void heightChanged();
2102+ void slowToResizeChanged();
2103
2104 ////
2105 // internal mock stuff
2106 void screenshotUrlChanged(QUrl);
2107 void activeFocusChanged(bool);
2108
2109+private Q_SLOTS:
2110+ void applyDelayedResize();
2111+
2112 private:
2113+ void doResize(int width, int height);
2114 void updateVisibility();
2115
2116 const QString m_name;
2117@@ -114,6 +124,12 @@
2118 bool m_activeFocus;
2119 int m_width;
2120 int m_height;
2121+
2122+ bool m_slowToResize;
2123+ QTimer m_delayedResizeTimer;
2124+ QSize m_delayedResize;
2125+ QSize m_pendingResize;
2126+
2127 struct View {
2128 bool visible;
2129 };
2130
2131=== added file 'tests/mocks/Utils/EdgeBarrierSettings.qml'
2132--- tests/mocks/Utils/EdgeBarrierSettings.qml 1970-01-01 00:00:00 +0000
2133+++ tests/mocks/Utils/EdgeBarrierSettings.qml 2015-11-24 17:51:40 +0000
2134@@ -0,0 +1,22 @@
2135+/*
2136+ * Copyright (C) 2015 Canonical, Ltd.
2137+ *
2138+ * This program is free software; you can redistribute it and/or modify
2139+ * it under the terms of the GNU General Public License as published by
2140+ * the Free Software Foundation; version 3.
2141+ *
2142+ * This program is distributed in the hope that it will be useful,
2143+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2144+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2145+ * GNU General Public License for more details.
2146+ *
2147+ * You should have received a copy of the GNU General Public License
2148+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2149+ */
2150+
2151+pragma Singleton
2152+import QtQuick 2.4
2153+
2154+QtObject {
2155+ readonly property real pushThreshold: units.gu(8)
2156+}
2157
2158=== modified file 'tests/mocks/Utils/qmldir'
2159--- tests/mocks/Utils/qmldir 2015-05-06 11:22:18 +0000
2160+++ tests/mocks/Utils/qmldir 2015-11-24 17:51:40 +0000
2161@@ -3,3 +3,4 @@
2162 typeinfo Utils.qmltypes
2163 Style 0.1 Style.js
2164 HomeKeyWatcher 0.1 HomeKeyWatcher.qml
2165+singleton EdgeBarrierSettings 0.1 EdgeBarrierSettings.qml
2166
2167=== added file 'tests/qmltests/EdgeBarrierControls.qml'
2168--- tests/qmltests/EdgeBarrierControls.qml 1970-01-01 00:00:00 +0000
2169+++ tests/qmltests/EdgeBarrierControls.qml 2015-11-24 17:51:40 +0000
2170@@ -0,0 +1,97 @@
2171+/*
2172+ * Copyright 2015 Canonical Ltd.
2173+ *
2174+ * This program is free software; you can redistribute it and/or modify
2175+ * it under the terms of the GNU General Public License as published by
2176+ * the Free Software Foundation; version 3.
2177+ *
2178+ * This program is distributed in the hope that it will be useful,
2179+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2180+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2181+ * GNU General Public License for more details.
2182+ *
2183+ * You should have received a copy of the GNU General Public License
2184+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2185+ */
2186+
2187+import QtQuick 2.4
2188+import QtQuick.Layouts 1.1
2189+import Ubuntu.Components 1.3
2190+import Unity.Test 0.1
2191+
2192+RowLayout {
2193+ id: root
2194+ Layout.fillWidth: true
2195+
2196+ property var target: null
2197+ property string backgroundColor: "darkGrey"
2198+ property alias text: label.text
2199+ signal dragged(real amount);
2200+
2201+ Binding {
2202+ id: containsMouseBinding
2203+
2204+ // only activate the binding once the controls start to get used in order to not
2205+ // interfere with automated tests
2206+ property bool activated: false
2207+
2208+ when: root.target !== undefined && root.target !== null && activated
2209+ target: root.target
2210+ property: "_containsMouse"
2211+ value: checkbox.checked
2212+ }
2213+
2214+
2215+ Rectangle {
2216+ width: label.width + units.gu(1)
2217+ height: units.gu(4)
2218+ color: root.backgroundColor
2219+
2220+ Rectangle {
2221+ anchors.fill: parent
2222+ color: "darkGreen"
2223+ opacity: target ? target.progress : 0
2224+ }
2225+
2226+ Label {
2227+ id: label
2228+ color: "white"
2229+ anchors.centerIn: parent
2230+ }
2231+ MouseArea {
2232+ id: mouseArea
2233+ anchors.fill: parent
2234+ property real lastX
2235+ property bool dragging: false
2236+ onPressedChanged: {
2237+ if (pressed) {
2238+ containsMouseBinding.activated = true;
2239+ checkbox.checked = true;
2240+ } else {
2241+ dragging = false;
2242+ }
2243+ }
2244+ onMouseXChanged: {
2245+ if (dragging) {
2246+ var amount = Math.abs(mouseX - lastX);
2247+ lastX = mouseX;
2248+ root.dragged(amount);
2249+ } else {
2250+ lastX = mouseX;
2251+ dragging = true;
2252+ }
2253+ }
2254+ }
2255+ }
2256+
2257+ CheckBox {
2258+ id: checkbox
2259+ checked: false
2260+ activeFocusOnPress: false
2261+ onCheckedChanged: {
2262+ if (checked) {
2263+ containsMouseBinding.activated = true;
2264+ }
2265+ }
2266+ }
2267+}
2268
2269=== modified file 'tests/qmltests/Launcher/tst_Launcher.qml'
2270--- tests/qmltests/Launcher/tst_Launcher.qml 2015-10-26 09:59:50 +0000
2271+++ tests/qmltests/Launcher/tst_Launcher.qml 2015-11-24 17:51:40 +0000
2272@@ -22,6 +22,7 @@
2273 import ".."
2274 import "../../../qml/Launcher"
2275 import Unity.Launcher 0.1
2276+import Utils 0.1 // For EdgeBarrierSettings
2277
2278 /* Nothing is shown at first. If you drag from left edge you will bring up the
2279 launcher. */
2280@@ -67,6 +68,7 @@
2281
2282 Component.onCompleted: {
2283 launcherLoader.itemDestroyed = false;
2284+ edgeBarrierControls.target = testCase.findChild(this, "edgeBarrierController");
2285 }
2286 Component.onDestruction: {
2287 launcherLoader.itemDestroyed = true;
2288@@ -82,6 +84,12 @@
2289
2290 MouseTouchEmulationCheckbox {}
2291
2292+ EdgeBarrierControls {
2293+ id: edgeBarrierControls
2294+ text: "Drag here to pull out launcher"
2295+ onDragged: { launcherLoader.item.pushEdge(amount); }
2296+ }
2297+
2298 Button {
2299 text: "emit hinting signal"
2300 onClicked: LauncherModel.emitHint()
2301@@ -207,8 +215,10 @@
2302 tryCompare(launcher, "state", "visible");
2303 }
2304
2305- function revealByHover() {
2306+ function revealByEdgePush() {
2307+ // Place the mouse against the window/screen edge and push beyond the barrier threshold
2308 mouseMove(root, 1, root.height / 2);
2309+ launcher.pushEdge(EdgeBarrierSettings.pushThreshold * 1.1);
2310
2311 var panel = findChild(launcher, "launcherPanel");
2312 verify(!!panel);
2313@@ -278,7 +288,7 @@
2314
2315 function test_clickingOnAppIconCausesSignalEmission(data) {
2316 if (data.mouse) {
2317- revealByHover();
2318+ revealByEdgePush();
2319 } else {
2320 dragLauncherIntoView();
2321 }
2322@@ -748,12 +758,12 @@
2323 verify(quickList, "state", "")
2324 }
2325
2326- function test_revealByHover() {
2327+ function test_revealByEdgePush() {
2328 var panel = findChild(launcher, "launcherPanel");
2329 verify(!!panel);
2330
2331- revealByHover();
2332- tryCompare(launcher, "state", "visibleTemporary");
2333+ revealByEdgePush();
2334+ compare(launcher.state, "visibleTemporary");
2335
2336 // Now move the mouse away and make sure it hides in less than a second
2337 mouseMove(root, root.width, root.height / 2)
2338
2339=== modified file 'tests/qmltests/Panel/tst_Panel.qml'
2340--- tests/qmltests/Panel/tst_Panel.qml 2015-08-03 13:48:14 +0000
2341+++ tests/qmltests/Panel/tst_Panel.qml 2015-11-24 17:51:40 +0000
2342@@ -23,6 +23,7 @@
2343 import Unity.Indicators 0.1 as Indicators
2344 import Ubuntu.Telephony 0.1 as Telephony
2345 import "../../../qml/Panel"
2346+import "../../../qml/Components/PanelState"
2347
2348 IndicatorTest {
2349 id: root
2350@@ -30,6 +31,12 @@
2351 height: units.gu(71)
2352 color: "white"
2353
2354+ Binding {
2355+ target: mouseEmulation
2356+ property: "checked"
2357+ value: !windowControlsCB.checked
2358+ }
2359+
2360 RowLayout {
2361 anchors.fill: parent
2362 anchors.margins: units.gu(1)
2363@@ -45,17 +52,18 @@
2364 MouseArea {
2365 id: backgroundMouseArea
2366 anchors.fill: parent
2367- }
2368-
2369- Panel {
2370- id: panel
2371- anchors.fill: parent
2372- indicators {
2373- width: parent.width > units.gu(60) ? units.gu(40) : parent.width
2374- indicatorsModel: root.indicatorsModel
2375+ hoverEnabled: true
2376+
2377+ Panel {
2378+ id: panel
2379+ anchors.fill: parent
2380+ indicators {
2381+ width: parent.width > units.gu(60) ? units.gu(40) : parent.width
2382+ indicatorsModel: root.indicatorsModel
2383+ }
2384+
2385+ property real panelAndSeparatorHeight: panel.indicators.minimizedPanelHeight
2386 }
2387-
2388- property real panelAndSeparatorHeight: panel.indicators.minimizedPanelHeight + units.dp(2)
2389 }
2390 }
2391
2392@@ -93,6 +101,32 @@
2393 }
2394 }
2395
2396+ RowLayout {
2397+ Layout.fillWidth: true
2398+ CheckBox {
2399+ id: windowControlsCB
2400+ onClicked: PanelState.buttonsVisible = checked
2401+ }
2402+ Label {
2403+ text: "Show window controls"
2404+ }
2405+ }
2406+
2407+ RowLayout {
2408+ Layout.fillWidth: true
2409+ CheckBox {
2410+ onClicked: {
2411+ if (checked)
2412+ PanelState.title = "Fake window title"
2413+ else
2414+ PanelState.title = ""
2415+ }
2416+ }
2417+ Label {
2418+ text: "Show fake window title"
2419+ }
2420+ }
2421+
2422 Rectangle {
2423 Layout.preferredHeight: units.dp(1);
2424 Layout.fillWidth: true;
2425@@ -127,7 +161,7 @@
2426 color: "black"
2427 }
2428
2429- MouseTouchEmulationCheckbox {}
2430+ MouseTouchEmulationCheckbox { id: mouseEmulation }
2431 }
2432 }
2433
2434
2435=== modified file 'tests/qmltests/Stages/tst_DesktopStage.qml'
2436--- tests/qmltests/Stages/tst_DesktopStage.qml 2015-11-06 13:48:29 +0000
2437+++ tests/qmltests/Stages/tst_DesktopStage.qml 2015-11-24 17:51:40 +0000
2438@@ -17,11 +17,12 @@
2439 import QtQuick 2.4
2440 import QtTest 1.0
2441 import Ubuntu.Components 1.3
2442-import Ubuntu.Components.ListItems 1.3 as ListItem
2443+import Ubuntu.Components.ListItems 1.3
2444 import Unity.Application 0.1
2445 import Unity.Test 0.1
2446 import Utils 0.1
2447
2448+import ".." // For EdgeBarrierControls
2449 import "../../../qml/Stages"
2450 import "../../../qml/Components"
2451
2452@@ -46,8 +47,8 @@
2453 WindowStateStorage.geometry = {
2454 'unity8-dash': Qt.rect(0, units.gu(3), units.gu(50), units.gu(40)),
2455 'dialer-app': Qt.rect(units.gu(51), units.gu(3), units.gu(50), units.gu(40)),
2456- 'camera-app': Qt.rect(0, units.gu(44), units.gu(50), units.gu(40)),
2457- 'gallery-app': Qt.rect(units.gu(51), units.gu(44), units.gu(50), units.gu(40))
2458+ 'gmail-webapp': Qt.rect(0, units.gu(44), units.gu(50), units.gu(40)),
2459+ 'twitter-webapp': Qt.rect(units.gu(51), units.gu(44), units.gu(50), units.gu(40))
2460 }
2461 }
2462
2463@@ -60,10 +61,18 @@
2464
2465 focus: true
2466
2467+ property bool itemDestroyed: false
2468 sourceComponent: Component {
2469 DesktopStage {
2470 color: "darkblue"
2471 anchors.fill: parent
2472+
2473+ Component.onCompleted: {
2474+ edgeBarrierControls.target = testCase.findChild(this, "edgeBarrierController");
2475+ }
2476+ Component.onDestruction: {
2477+ desktopStageLoader.itemDestroyed = true;
2478+ }
2479 orientations: Orientations {}
2480 }
2481 }
2482@@ -82,6 +91,28 @@
2483 Column {
2484 anchors { left: parent.left; right: parent.right; top: parent.top; margins: units.gu(1) }
2485 spacing: units.gu(1)
2486+
2487+ Button {
2488+ color: "white"
2489+ text: "Make surface slow to resize"
2490+ activeFocusOnPress: false
2491+ onClicked: {
2492+ if (ApplicationManager.focusedApplicationId) {
2493+ var surface = ApplicationManager.findApplication(ApplicationManager.focusedApplicationId).session.surface;
2494+ surface.slowToResize = true;
2495+ }
2496+ }
2497+ }
2498+
2499+ EdgeBarrierControls {
2500+ id: edgeBarrierControls
2501+ text: "Drag here to pull out spread"
2502+ backgroundColor: "blue"
2503+ onDragged: { desktopStageLoader.item.pushRightEdge(amount); }
2504+ }
2505+
2506+ Divider {}
2507+
2508 Repeater {
2509 model: ApplicationManager.availableApplications
2510 ApplicationCheckBox {
2511@@ -99,10 +130,16 @@
2512 property Item desktopStage: desktopStageLoader.status === Loader.Ready ? desktopStageLoader.item : null
2513
2514 function cleanup() {
2515+ desktopStageLoader.itemDestroyed = false;
2516 desktopStageLoader.active = false;
2517
2518 tryCompare(desktopStageLoader, "status", Loader.Null);
2519 tryCompare(desktopStageLoader, "item", null);
2520+ // Loader.status might be Loader.Null and Loader.item might be null but the Loader
2521+ // actually took place. Likely because Loader waits until the next event loop
2522+ // iteration to do its work. So to ensure the reload, we will wait until the
2523+ // Shell instance gets destroyed.
2524+ tryCompare(desktopStageLoader, "itemDestroyed", true);
2525
2526 killAllRunningApps();
2527
2528@@ -156,8 +193,8 @@
2529
2530 function test_tappingOnWindowChangesFocusedApp_data() {
2531 return [
2532- {tag: "dash to dialer", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 0, focusTo: 1 },
2533- {tag: "dialer to dash", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 1, focusTo: 0 },
2534+ {tag: "dash to dialer", apps: [ "unity8-dash", "dialer-app", "gmail-webapp"], focusfrom: 0, focusTo: 1 },
2535+ {tag: "dialer to dash", apps: [ "unity8-dash", "dialer-app", "gmail-webapp"], focusfrom: 1, focusTo: 0 }
2536 ]
2537 }
2538
2539@@ -203,8 +240,8 @@
2540
2541 function test_tappingOnDecorationFocusesApplication_data() {
2542 return [
2543- {tag: "dash to dialer", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 0, focusTo: 1 },
2544- {tag: "dialer to dash", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 1, focusTo: 0 },
2545+ {tag: "dash to dialer", apps: [ "unity8-dash", "dialer-app", "gmail-webapp"], focusfrom: 0, focusTo: 1 },
2546+ {tag: "dialer to dash", apps: [ "unity8-dash", "dialer-app", "gmail-webapp"], focusfrom: 1, focusTo: 0 }
2547 ]
2548 }
2549
2550@@ -214,12 +251,16 @@
2551 var fromAppDecoration = findChild(desktopStage, "appWindowDecoration_" + data.apps[data.focusfrom]);
2552 verify(fromAppDecoration);
2553 tap(fromAppDecoration);
2554- tryCompare(ApplicationManager.findApplication(data.apps[data.focusfrom]).session.surface, "activeFocus", true);
2555+ var fromApp = ApplicationManager.findApplication(data.apps[data.focusfrom]);
2556+ verify(fromApp);
2557+ tryCompare(fromApp.session.surface, "activeFocus", true);
2558
2559 var toAppDecoration = findChild(desktopStage, "appWindowDecoration_" + data.apps[data.focusTo]);
2560 verify(toAppDecoration);
2561 tap(toAppDecoration);
2562- tryCompare(ApplicationManager.findApplication(data.apps[data.focusTo]).session.surface, "activeFocus", true);
2563+ var toApp = ApplicationManager.findApplication(data.apps[data.focusTo]);
2564+ verify(toApp);
2565+ tryCompare(toApp.session.surface, "activeFocus", true);
2566 }
2567
2568 function test_clickingOnDecorationFocusesApplication_data() {
2569@@ -339,26 +380,26 @@
2570 function test_maximizeApplicationHidesSurfacesBehindIt() {
2571 var dashApp = startApplication("unity8-dash");
2572 var dialerApp = startApplication("dialer-app");
2573- var cameraApp = startApplication("camera-app");
2574+ var gmailApp = startApplication("gmail-webapp");
2575
2576 var dashDelegate = findChild(desktopStage, "appDelegate_unity8-dash");
2577 verify(dashDelegate);
2578 var dialerDelegate = findChild(desktopStage, "appDelegate_dialer-app");
2579 verify(dialerDelegate);
2580- var cameraDelegate = findChild(desktopStage, "appDelegate_camera-app");
2581- verify(cameraDelegate);
2582+ var gmailDelegate = findChild(desktopStage, "appDelegate_gmail-webapp");
2583+ verify(gmailDelegate);
2584
2585 // maximize
2586- findChild(dialerDelegate, "decoratedWindow").maximize();
2587+ dialerDelegate.maximize();
2588 tryCompare(dialerDelegate, "visuallyMaximized", true);
2589
2590 tryCompare(dashApp.session.surface, "visible", false);
2591- compare(cameraApp.session.surface.visible, true);
2592+ compare(gmailApp.session.surface.visible, true);
2593
2594 // restore
2595- findChild(dialerDelegate, "decoratedWindow").maximize();
2596+ dialerDelegate.restoreFromMaximized();
2597 compare(dashApp.session.surface.visible, true);
2598- compare(cameraApp.session.surface.visible, true);
2599+ compare(gmailApp.session.surface.visible, true);
2600 }
2601
2602 function test_applicationsBecomeVisibleWhenOccludingAppRemoved() {
2603@@ -370,28 +411,52 @@
2604 var dialerDelegate = findChild(desktopStage, "appDelegate_dialer-app");
2605 verify(dialerDelegate);
2606
2607- var cameraApp = startApplication("camera-app");
2608- var cameraDelegate = findChild(desktopStage, "appDelegate_camera-app");
2609- verify(cameraDelegate);
2610- findChild(dialerDelegate, "decoratedWindow").maximize();
2611-
2612- var galleryApp = startApplication("gallery-app");
2613- var galleryDelegate = findChild(desktopStage, "appDelegate_gallery-app");
2614- verify(galleryDelegate);
2615- findChild(galleryDelegate, "decoratedWindow").maximize();
2616+ var dialerMaximizeButton = findChild(dialerDelegate, "maximizeWindowButton");
2617+ verify(dialerMaximizeButton);
2618+ mouseClick(dialerMaximizeButton);
2619+
2620+ var mapApp = startApplication("map");
2621+ var mapDelegate = findChild(desktopStage, "appDelegate_map");
2622+ verify(mapDelegate);
2623+
2624+ var gmailApp = startApplication("gmail-webapp");
2625+ var gmailDelegate = findChild(desktopStage, "appDelegate_gmail-webapp");
2626+ verify(gmailDelegate);
2627+
2628+ var gmailMaximizeButton = findChild(gmailDelegate, "maximizeWindowButton");
2629+ verify(gmailMaximizeButton);
2630+ mouseClick(gmailMaximizeButton);
2631
2632 tryCompare(dialerDelegate, "visuallyMaximized", true);
2633- tryCompare(galleryDelegate, "visuallyMaximized", true);
2634+ tryCompare(gmailDelegate, "visuallyMaximized", true);
2635
2636 tryCompare(dashApp.session.surface, "visible", false);
2637 tryCompare(dialerApp.session.surface, "visible", false);
2638- tryCompare(cameraApp.session.surface, "visible", false);
2639-
2640- ApplicationManager.stopApplication("gallery-app");
2641-
2642- compare(cameraApp.session.surface.visible, true);
2643+ tryCompare(mapApp.session.surface, "visible", false);
2644+
2645+ ApplicationManager.stopApplication("gmail-webapp");
2646+
2647+ compare(mapApp.session.surface.visible, true);
2648 tryCompare(dialerApp.session.surface, "visible", true);
2649 tryCompare(dashApp.session.surface, "visible", false); // still occluded by maximised dialer
2650 }
2651+
2652+ function test_maximisedAppStaysVisibleWhenAppStarts() {
2653+ var dashApp = startApplication("unity8-dash");
2654+ var dashDelegate = findChild(desktopStage, "appDelegate_unity8-dash");
2655+ verify(dashDelegate);
2656+ // maximize
2657+ var dashMaximizeButton = findChild(dashDelegate, "maximizeWindowButton");
2658+ verify(dashMaximizeButton);
2659+ mouseClick(dashMaximizeButton);
2660+ tryCompare(dashDelegate, "visuallyMaximized", true);
2661+
2662+ var dialerApp = startApplication("dialer-app");
2663+ var dialerDelegate = findChild(desktopStage, "appDelegate_dialer-app");
2664+ verify(dialerDelegate);
2665+
2666+ compare(dialerDelegate.visible, true, "Dialer should be visible");
2667+ compare(dashDelegate.visible, true, "Dash should still be visible");
2668+ }
2669 }
2670 }
2671
2672=== modified file 'tests/qmltests/Stages/tst_WindowResizeArea.qml'
2673--- tests/qmltests/Stages/tst_WindowResizeArea.qml 2015-11-09 10:16:18 +0000
2674+++ tests/qmltests/Stages/tst_WindowResizeArea.qml 2015-11-24 17:51:40 +0000
2675@@ -30,8 +30,6 @@
2676 height: units.gu(60)
2677 width: units.gu(60)
2678
2679- property var fakeWindow: windowLoader.item
2680-
2681 Binding {
2682 target: PanelState
2683 property: "panelHeight"
2684@@ -47,10 +45,10 @@
2685 property alias minHeight: windowResizeArea.minHeight
2686 x: units.gu(20)
2687 y: units.gu(20)
2688- height: units.gu(20)
2689- width: units.gu(20)
2690- property int windowHeight: height
2691- property int windowWidth: width
2692+ width: requestedWidth
2693+ height: requestedHeight
2694+ property real requestedWidth
2695+ property real requestedHeight
2696 state: "normal"
2697
2698 function maximize() {
2699@@ -63,6 +61,8 @@
2700 borderThickness: units.gu(2)
2701 minWidth: units.gu(15)
2702 minHeight: units.gu(10)
2703+ defaultWidth: units.gu(20)
2704+ defaultHeight: units.gu(20)
2705 windowId: "test-window-id"
2706 screenWidth: root.width
2707 screenHeight: root.height
2708@@ -87,22 +87,41 @@
2709 Loader {
2710 id: windowLoader
2711 sourceComponent: fakeWindowComponent
2712+ active: windowLoaderCheckbox.checked
2713 }
2714
2715- MouseTouchEmulationCheckbox {
2716- checked: false
2717- color: "black"
2718+ Column {
2719+ MouseTouchEmulationCheckbox {
2720+ checked: false
2721+ color: "black"
2722+ }
2723+ RowLayout {
2724+ Layout.fillWidth: true
2725+ CheckBox {
2726+ id: windowLoaderCheckbox
2727+ checked: true
2728+ activeFocusOnPress: false
2729+ }
2730+ Label {
2731+ id: label
2732+ color: "black"
2733+ text: "Window loader active"
2734+ anchors.verticalCenter: parent.verticalCenter
2735+ }
2736+ }
2737 }
2738
2739 UnityTestCase {
2740 name: "WindowResizeArea"
2741 when: windowShown
2742
2743+ property var fakeWindow: windowLoader.item
2744+
2745 function init() {
2746 fakeWindow.x = units.gu(20)
2747 fakeWindow.y = units.gu(20)
2748- fakeWindow.width = units.gu(20)
2749- fakeWindow.height = units.gu(20)
2750+ fakeWindow.requestedWidth = units.gu(20)
2751+ fakeWindow.requestedHeight = units.gu(20)
2752 }
2753
2754 function test_resizeWindowRightBottom_data() {
2755@@ -188,7 +207,7 @@
2756 function test_resizeSmallerAndLarger_data() {
2757 return [
2758 { tag: "topLeft", startX: -1, startY: -1, dx: units.gu(15), dy: units.gu(15) },
2759- { tag: "bottomRight", startX: fakeWindow.width + 1, startY: fakeWindow.height + 1, dx: -units.gu(15), dy: -units.gu(15) }
2760+ { tag: "bottomRight", startX: units.gu(20) + 1, startY: units.gu(20) + 1, dx: -units.gu(15), dy: -units.gu(15) }
2761 ]
2762 }
2763
2764
2765=== modified file 'tests/qmltests/tst_Shell.qml'
2766--- tests/qmltests/tst_Shell.qml 2015-11-12 20:40:49 +0000
2767+++ tests/qmltests/tst_Shell.qml 2015-11-24 17:51:40 +0000
2768@@ -954,6 +954,22 @@
2769 removeTimeConstraintsFromDirectionalDragAreas(greeter);
2770 }
2771
2772+ function revealLauncherByEdgePushWithMouse() {
2773+ var launcher = findChild(shell, "launcher");
2774+ verify(launcher);
2775+
2776+ // Place the mouse against the window/screen edge and push beyond the barrier threshold
2777+ mouseMove(shell, 0, shell.height / 2);
2778+ launcher.pushEdge(EdgeBarrierSettings.pushThreshold * 1.1);
2779+
2780+ var panel = findChild(launcher, "launcherPanel");
2781+ verify(panel);
2782+
2783+ // wait until it gets fully extended
2784+ tryCompare(panel, "x", 0);
2785+ tryCompare(launcher, "state", "visibleTemporary");
2786+ }
2787+
2788 function test_focusRequestedHidesGreeter() {
2789 loadShell("phone");
2790 swipeAwayGreeter();
2791@@ -1713,8 +1729,7 @@
2792
2793 tryCompare(desktopSpread, "state", "altTab")
2794
2795- mouseMove(shell, 0, shell.height / 2);
2796- tryCompare(launcher, "state", "visibleTemporary")
2797+ revealLauncherByEdgePushWithMouse();
2798 waitForRendering(shell)
2799
2800 mouseClick(bfb, bfb.width / 2, bfb.height / 2)
2801@@ -1777,15 +1792,10 @@
2802 tryCompare(panelButtons, "visible", false);
2803
2804 appDelegate.maximize(false);
2805- tryCompare(panelButtons, "visible", true);
2806
2807 shell.usageScenario = "phone";
2808 waitForRendering(shell);
2809 tryCompare(panelButtons, "visible", false);
2810-
2811- shell.usageScenario = "desktop";
2812- waitForRendering(shell);
2813- tryCompare(panelButtons, "visible", true);
2814 }
2815
2816 function test_lockingGreeterHidesPanelButtons() {
2817@@ -1799,15 +1809,10 @@
2818 tryCompare(panelButtons, "visible", false);
2819
2820 appDelegate.maximize(false);
2821- tryCompare(panelButtons, "visible", true);
2822
2823 LightDM.Greeter.showGreeter();
2824 waitForRendering(shell);
2825 tryCompare(panelButtons, "visible", false);
2826-
2827- LightDM.Greeter.hideGreeter();
2828- waitForRendering(shell);
2829- tryCompare(panelButtons, "visible", true);
2830 }
2831
2832 function test_cantMoveWindowUnderPanel() {

Subscribers

People subscribed via source and target branches