on xenial help sign in
merge prereq
4179f5aMichael Zanetti
plugins/Utils/CMakeLists.txt+1
@@ -9,6 +9,7 @@ include_directories(
9)
9)
10
10
11set(QMLPLUGIN_SRC
11set(QMLPLUGIN_SRC
12+ activefocuslogger.cpp
12 constants.cpp
13 constants.cpp
13 HomeKeyWatcher.cpp
14 HomeKeyWatcher.cpp
14 inputwatcher.cpp
15 inputwatcher.cpp
tests/uqmlscene/ActiveFocusLogger.cpp → plugins/Utils/activefocuslogger.cpprenamed+21−8
@@ -14,21 +14,34 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17−#include "ActiveFocusLogger.h"
17+#include "activefocuslogger.h"
18
18
19−#include <QDebug>
19+#include <QQuickWindow>
20−#include <QQuickItem>
21
20
22−void ActiveFocusLogger::setWindow(QQuickWindow *window)
21+ActiveFocusLogger::ActiveFocusLogger(QQuickItem *parent)
22+ : QQuickItem(parent)
23{
23{
24+ connect(this, &QQuickItem::windowChanged,
25+ this, &ActiveFocusLogger::setupFilterOnWindow);
26+}
27+
28+void ActiveFocusLogger::setupFilterOnWindow(QQuickWindow *window)
29+{
30+ if (!m_window.isNull()) {
31+ disconnect(m_window.data(), nullptr, this, nullptr);
32+ m_window.clear();
33+ }
34+
35+ if (window) {
24− m_window = window;
36+ m_window = window;
25− QObject::connect(window, &QQuickWindow::activeFocusItemChanged,
37+ QObject::connect(window, &QQuickWindow::activeFocusItemChanged,
26− this, &ActiveFocusLogger::printActiveFocusInfo);
38+ this, &ActiveFocusLogger::printActiveFocusInfo);
39+ }
27}
40}
28
41
29void ActiveFocusLogger::printActiveFocusInfo()
42void ActiveFocusLogger::printActiveFocusInfo()
30{
43{
31− if (!m_window) {
44+ if (!m_window || !isEnabled()) {
32 return;
45 return;
33 }
46 }
34
47
tests/uqmlscene/ActiveFocusLogger.h → plugins/Utils/activefocuslogger.hrenamed+9−8
@@ -14,24 +14,25 @@
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
15 */
16
16
17−#ifndef ACTIVE_FOCUS_LOGGER_H
17+#ifndef UNITY_ACTIVEFOCUSLOGGER_H
18−#define ACTIVE_FOCUS_LOGGER_H
18+#define UNITY_ACTIVEFOCUSLOGGER_H
19
19
20−#include <QObject>
20+#include <QQuickItem>
21−#include <QQuickWindow>
22#include <QPointer>
21#include <QPointer>
23
22
24−class ActiveFocusLogger : public QObject {
23+class ActiveFocusLogger : public QQuickItem
24+{
25 Q_OBJECT
25 Q_OBJECT
26−
27public:
26public:
28− void setWindow(QQuickWindow *window);
27+ ActiveFocusLogger(QQuickItem *parent = 0);
29
28
30private Q_SLOTS:
29private Q_SLOTS:
30+ void setupFilterOnWindow(QQuickWindow *window);
31 void printActiveFocusInfo();
31 void printActiveFocusInfo();
32
32
33private:
33private:
34 QPointer<QQuickWindow> m_window;
34 QPointer<QQuickWindow> m_window;
35};
35};
36
36
37−#endif // ACTIVE_FOCUS_LOGGER_H
37+#endif // UNITY_ACTIVEFOCUSLOGGER_H
38+
plugins/Utils/plugin.cpp+2
@@ -23,6 +23,7 @@
23#include "plugin.h"
23#include "plugin.h"
24
24
25// local
25// local
26+#include "activefocuslogger.h"
26#include "easingcurve.h"
27#include "easingcurve.h"
27#include "HomeKeyWatcher.h"
28#include "HomeKeyWatcher.h"
28#include "inputwatcher.h"
29#include "inputwatcher.h"
@@ -66,6 +67,7 @@ void UtilsPlugin::registerTypes(const char *uri)
66 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
67 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
67 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
68 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
68 qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
69 qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
70+ qmlRegisterType<ActiveFocusLogger>(uri, 0, 1, "ActiveFocusLogger");
69}
71}
70
72
71void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
73void UtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
qml/Stages/ApplicationWindow.qml−3
@@ -137,9 +137,6 @@ FocusScope {
137 onSurfaceChanged: {
137 onSurfaceChanged: {
138 if (sessionContainer.surface) {
138 if (sessionContainer.surface) {
139 surfaceInitTimer.start();
139 surfaceInitTimer.start();
140− if (ApplicationManager.focusedApplicationId == application.appId) {
141− root.forceActiveFocus();
142− }
143 } else {
140 } else {
144 d.surfaceInitialized = false;
141 d.surfaceInitialized = false;
145 }
142 }
qml/Stages/DesktopStage.qml+126−77
@@ -77,7 +77,6 @@ Rectangle {
77 var appIndex = priv.indexOf(appId);
77 var appIndex = priv.indexOf(appId);
78 var appDelegate = appRepeater.itemAt(appIndex);
78 var appDelegate = appRepeater.itemAt(appIndex);
79 appDelegate.minimized = false;
79 appDelegate.minimized = false;
80− appDelegate.focus = true;
81 ApplicationManager.focusApplication(appId);
80 ApplicationManager.focusApplication(appId);
82 }
81 }
83 }
82 }
@@ -91,12 +90,6 @@ Rectangle {
91 return index >= 0 && index < appRepeater.count ? appRepeater.itemAt(index) : null
90 return index >= 0 && index < appRepeater.count ? appRepeater.itemAt(index) : null
92 }
91 }
93
92
94− onFocusedAppDelegateChanged: {
95− if (focusedAppDelegate) {
96− focusedAppDelegate.focus = true;
97− }
98− }
99−
100 function indexOf(appId) {
93 function indexOf(appId) {
101 for (var i = 0; i < ApplicationManager.count; i++) {
94 for (var i = 0; i < ApplicationManager.count; i++) {
102 if (ApplicationManager.get(i).appId == appId) {
95 if (ApplicationManager.get(i).appId == appId) {
@@ -133,23 +126,28 @@ Rectangle {
133 id: appContainer
126 id: appContainer
134 objectName: "appContainer"
127 objectName: "appContainer"
135 anchors.fill: parent
128 anchors.fill: parent
129+ focus: true
136
130
137 Keys.onPressed: {
131 Keys.onPressed: {
138 switch (event.key) {
132 switch (event.key) {
139 case Qt.Key_Left:
133 case Qt.Key_Left:
140 case Qt.Key_Backtab:
134 case Qt.Key_Backtab:
141 selectPrevious(event.isAutoRepeat)
135 selectPrevious(event.isAutoRepeat)
136+ event.accepted = true;
142 break;
137 break;
143 case Qt.Key_Right:
138 case Qt.Key_Right:
144 case Qt.Key_Tab:
139 case Qt.Key_Tab:
145 selectNext(event.isAutoRepeat)
140 selectNext(event.isAutoRepeat)
141+ event.accepted = true;
146 break;
142 break;
147 case Qt.Key_Escape:
143 case Qt.Key_Escape:
148 appRepeater.highlightedIndex = -1
144 appRepeater.highlightedIndex = -1
145+ event.accepted = true;
149 case Qt.Key_Enter:
146 case Qt.Key_Enter:
150 case Qt.Key_Return:
147 case Qt.Key_Return:
151 case Qt.Key_Space:
148 case Qt.Key_Space:
152 root.state = ""
149 root.state = ""
150+ event.accepted = true;
153 }
151 }
154 }
152 }
155
153
@@ -180,7 +178,8 @@ Rectangle {
180
178
181 function focusSelected() {
179 function focusSelected() {
182 if (appRepeater.highlightedIndex != -1) {
180 if (appRepeater.highlightedIndex != -1) {
183− appRepeater.itemAt(appRepeater.highlightedIndex).focus = true;
181+ var application = ApplicationManager.get(appRepeater.highlightedIndex);
182+ ApplicationManager.focusApplication(application.appId);
184 }
183 }
185 }
184 }
186
185
@@ -192,6 +191,15 @@ Rectangle {
192 property int highlightedIndex: -1
191 property int highlightedIndex: -1
193 property int closingIndex: -1
192 property int closingIndex: -1
194
193
194+ function indexOf(delegateItem) {
195+ for (var i = 0; i < appRepeater.count; i++) {
196+ if (appRepeater.itemAt(i) === delegateItem) {
197+ return i;
198+ }
199+ }
200+ return -1;
201+ }
202+
195 delegate: FocusScope {
203 delegate: FocusScope {
196 id: appDelegate
204 id: appDelegate
197 z: ApplicationManager.count - index
205 z: ApplicationManager.count - index
@@ -199,23 +207,19 @@ Rectangle {
199 width: units.gu(60)
207 width: units.gu(60)
200 height: units.gu(50)
208 height: units.gu(50)
201
209
210+ property int windowWidth: 0
211+ property int windowHeight: 0
212+ // We don't want to resize the actual application when we're transforming things for the spread only
213+ onWidthChanged: if (appDelegate.state !== "altTab") windowWidth = width
214+ onHeightChanged: if (appDelegate.state !== "altTab") windowHeight = height
215+
202 readonly property int minWidth: units.gu(10)
216 readonly property int minWidth: units.gu(10)
203 readonly property int minHeight: units.gu(10)
217 readonly property int minHeight: units.gu(10)
204
218
205 property bool maximized: false
219 property bool maximized: false
206 property bool minimized: false
220 property bool minimized: false
207
221
208− onFocusChanged: {
222+ focus: priv.focusedAppId === model.appId && root.state !== "altTab"
209− if (focus && ApplicationManager.focusedApplicationId !== model.appId) {
210− ApplicationManager.requestFocusApplication(model.appId);
211− decoratedWindow.forceActiveFocus();
212− }
213− }
214− Component.onCompleted: {
215− if (ApplicationManager.focusedApplicationId == model.appId) {
216− decoratedWindow.forceActiveFocus();
217− }
218− }
219
223
220 Binding {
224 Binding {
221 target: ApplicationManager.get(index)
225 target: ApplicationManager.get(index)
@@ -266,7 +270,9 @@ Rectangle {
266 PropertyChanges {
270 PropertyChanges {
267 target: appDelegate
271 target: appDelegate
268 x: spreadMaths.animatedX
272 x: spreadMaths.animatedX
269− y: spreadMaths.animatedY + (appDelegate.height - decoratedWindow.height)
273+ y: spreadMaths.animatedY + (appDelegate.height - decoratedWindow.height) - units.gu(2)
274+ width: spreadMaths.spreadHeight
275+ height: spreadMaths.sceneHeight
270 angle: spreadMaths.animatedAngle
276 angle: spreadMaths.animatedAngle
271 itemScale: spreadMaths.scale
277 itemScale: spreadMaths.scale
272 itemScaleOriginY: decoratedWindow.height / 2;
278 itemScaleOriginY: decoratedWindow.height / 2;
@@ -281,6 +287,7 @@ Rectangle {
281 width: spreadMaths.spreadHeight
287 width: spreadMaths.spreadHeight
282 height: spreadMaths.spreadHeight
288 height: spreadMaths.spreadHeight
283 shadowOpacity: spreadMaths.shadowOpacity
289 shadowOpacity: spreadMaths.shadowOpacity
290+ anchors.topMargin: units.gu(2)
284 }
291 }
285 PropertyChanges {
292 PropertyChanges {
286 target: tileInfo
293 target: tileInfo
@@ -302,6 +309,18 @@ Rectangle {
302 from: "maximized,minimized,normal,"
309 from: "maximized,minimized,normal,"
303 to: "maximized,minimized,normal,"
310 to: "maximized,minimized,normal,"
304 PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale" }
311 PropertyAnimation { target: appDelegate; properties: "x,y,opacity,width,height,scale" }
312+ },
313+ Transition {
314+ from: ""
315+ to: "altTab"
316+ PropertyAction { target: appDelegate; properties: "y,angle,z,itemScale,itemScaleOriginY" }
317+ PropertyAction { target: decoratedWindow; properties: "anchors.topMargin" }
318+ PropertyAnimation {
319+ target: appDelegate; properties: "x"
320+ from: root.width
321+ duration: rightEdgePushArea.containsMouse ? UbuntuAnimation.FastDuration :0
322+ easing: UbuntuAnimation.StandardEasing
323+ }
305 }
324 }
306 ]
325 ]
307 property real angle: 0
326 property real angle: 0
@@ -326,7 +345,7 @@ Rectangle {
326 resizeHandleWidth: units.gu(2)
345 resizeHandleWidth: units.gu(2)
327 windowId: model.appId // FIXME: Change this to point to windowId once we have such a thing
346 windowId: model.appId // FIXME: Change this to point to windowId once we have such a thing
328
347
329− onPressed: appDelegate.focus = true;
348+ onPressed: ApplicationManager.focusApplication(model.appId);
330 }
349 }
331
350
332 DecoratedWindow {
351 DecoratedWindow {
@@ -334,11 +353,11 @@ Rectangle {
334 objectName: "decoratedWindow"
353 objectName: "decoratedWindow"
335 anchors.left: appDelegate.left
354 anchors.left: appDelegate.left
336 anchors.top: appDelegate.top
355 anchors.top: appDelegate.top
337− windowWidth: appDelegate.width
356+ windowWidth: appDelegate.windowWidth
338− windowHeight: appDelegate.height
357+ windowHeight: appDelegate.windowHeight
339 application: ApplicationManager.get(index)
358 application: ApplicationManager.get(index)
340 active: ApplicationManager.focusedApplicationId === model.appId
359 active: ApplicationManager.focusedApplicationId === model.appId
341− focus: false
360+ focus: true
342
361
343 onClose: ApplicationManager.stopApplication(model.appId)
362 onClose: ApplicationManager.stopApplication(model.appId)
344 onMaximize: appDelegate.maximize()
363 onMaximize: appDelegate.maximize()
@@ -363,31 +382,6 @@ Rectangle {
363 anchors.fill: parent
382 anchors.fill: parent
364 anchors.margins: -units.gu(2)
383 anchors.margins: -units.gu(2)
365 enabled: false
384 enabled: false
366− hoverEnabled: enabled
367−
368− // There is a bug in MouseArea where containsMouse doesn't
369− // return to false if the MouseArea is disabled while
370− // containing the mouse. Let's manage the property our own.
371− property bool upperThirdContainsMouse: false
372− onContainsMouseChanged: evaluateContainsMouse()
373− onMouseYChanged: evaluateContainsMouse()
374− function evaluateContainsMouse() {
375− if (containsMouse) {
376− appRepeater.highlightedIndex = index
377− }
378−
379− if (containsMouse && mouseY < height / 3) {
380− spreadSelectArea.upperThirdContainsMouse = true
381− } else {
382− spreadSelectArea.upperThirdContainsMouse = false;
383− }
384− }
385− onEnabledChanged: {
386− if (!enabled) {
387− spreadSelectArea.upperThirdContainsMouse = false
388− }
389− }
390−
391 onClicked: {
385 onClicked: {
392 root.state = ""
386 root.state = ""
393 }
387 }
@@ -396,24 +390,28 @@ Rectangle {
396
390
397 Image {
391 Image {
398 id: closeImage
392 id: closeImage
399− anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset }
393+ anchors { left: parent.left; top: parent.top; leftMargin: -height / 2; topMargin: -height / 2 + spreadMaths.closeIconOffset + units.gu(2) }
400 source: "graphics/window-close.svg"
394 source: "graphics/window-close.svg"
401− visible: spreadSelectArea.upperThirdContainsMouse
395+ readonly property var mousePos: hoverMouseArea.mapToItem(appDelegate, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
396+ visible: index == appRepeater.highlightedIndex
397+ && mousePos.y < (decoratedWindow.height / 3)
398+ && mousePos.y > -units.gu(4)
399+ && mousePos.x > -units.gu(4)
400+ && mousePos.x < (decoratedWindow.width * 2 / 3)
402 height: units.gu(1.5)
401 height: units.gu(1.5)
403 width: height
402 width: height
404 sourceSize.width: width
403 sourceSize.width: width
405 sourceSize.height: height
404 sourceSize.height: height
406− }
407
405
408− MouseArea {
406+ MouseArea {
409− id: closeMouseArea
407+ id: closeMouseArea
410− objectName: "closeMouseArea"
408+ objectName: "closeMouseArea"
411− anchors.fill: closeImage
409+ anchors.fill: closeImage
412− anchors.margins: -units.gu(2)
410+ anchors.margins: -units.gu(2)
413− enabled: spreadSelectArea.upperThirdContainsMouse
414− onClicked: {
411+ onClicked: {
415− appRepeater.closingIndex = index;
412+ appRepeater.closingIndex = index;
416− ApplicationManager.stopApplication(model.appId)
413+ ApplicationManager.stopApplication(model.appId)
414+ }
417 }
415 }
418 }
416 }
419
417
@@ -462,9 +460,58 @@ Rectangle {
462 }
460 }
463 }
461 }
464
462
463+ MouseArea {
464+ id: hoverMouseArea
465+ anchors.fill: appContainer
466+ propagateComposedEvents: true
467+ hoverEnabled: true
468+ enabled: false
469+
470+ property int scrollAreaWidth: root.width / 3
471+ property bool progressiveScrollingEnabled: false
472+
473+ onMouseXChanged: {
474+ mouse.accepted = false
475+
476+ // Find the hovered item and mark it active
477+ var mapped = mapToItem(appContainer, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
478+ var itemUnder = appContainer.childAt(mapped.x, mapped.y)
479+ if (itemUnder) {
480+ mapped = mapToItem(itemUnder, hoverMouseArea.mouseX, hoverMouseArea.mouseY)
481+ var delegateChild = itemUnder.childAt(mapped.x, mapped.y)
482+ if (delegateChild.objectName === "decoratedWindow" || delegateChild.objectName === "tileInfo") {
483+ appRepeater.highlightedIndex = appRepeater.indexOf(itemUnder)
484+ }
485+ }
486+
487+ if (spreadFlickable.contentWidth > spreadFlickable.minContentWidth) {
488+ var margins = spreadFlickable.width * 0.05;
489+
490+ if (!progressiveScrollingEnabled && mouseX < spreadFlickable.width - scrollAreaWidth) {
491+ progressiveScrollingEnabled = true
492+ }
493+
494+ // do we need to scroll?
495+ if (mouseX < scrollAreaWidth) {
496+ var progress = Math.min(1, (scrollAreaWidth + margins - mouseX) / (scrollAreaWidth - margins));
497+ var contentX = (1 - progress) * (spreadFlickable.contentWidth - spreadFlickable.width)
498+ spreadFlickable.contentX = Math.max(0, Math.min(spreadFlickable.contentX, contentX))
499+ }
500+ if (mouseX > spreadFlickable.width - scrollAreaWidth && progressiveScrollingEnabled) {
501+ var progress = Math.min(1, (mouseX - (spreadFlickable.width - scrollAreaWidth)) / (scrollAreaWidth - margins))
502+ var contentX = progress * (spreadFlickable.contentWidth - spreadFlickable.width)
503+ spreadFlickable.contentX = Math.min(spreadFlickable.contentWidth - spreadFlickable.width, Math.max(spreadFlickable.contentX, contentX))
504+ }
505+ }
506+ }
507+ onPressed: mouse.accepted = false
508+ }
509+
465 FloatingFlickable {
510 FloatingFlickable {
466 id: spreadFlickable
511 id: spreadFlickable
512+ objectName: "spreadFlickable"
467 anchors.fill: parent
513 anchors.fill: parent
514+ property int minContentWidth: 6 * Math.min(height / 4, width / 5)
468 contentWidth: Math.max(6, ApplicationManager.count) * Math.min(height / 4, width / 5)
515 contentWidth: Math.max(6, ApplicationManager.count) * Math.min(height / 4, width / 5)
469 enabled: false
516 enabled: false
470
517
@@ -579,10 +626,10 @@ Rectangle {
579 State {
626 State {
580 name: "altTab"; when: root.altTabPressed
627 name: "altTab"; when: root.altTabPressed
581 PropertyChanges { target: workspaceSelector; visible: true }
628 PropertyChanges { target: workspaceSelector; visible: true }
582− PropertyChanges { target: spreadFlickable; enabled: true }
629+ PropertyChanges { target: spreadFlickable; enabled: spreadFlickable.contentWidth > spreadFlickable.minContentWidth }
583 PropertyChanges { target: currentSelectedLabel; visible: true }
630 PropertyChanges { target: currentSelectedLabel; visible: true }
584 PropertyChanges { target: spreadBackground; visible: true }
631 PropertyChanges { target: spreadBackground; visible: true }
585− PropertyChanges { target: appContainer; focus: true }
632+ PropertyChanges { target: hoverMouseArea; enabled: true }
586 }
633 }
587 ]
634 ]
588 signal updateWorkspaces();
635 signal updateWorkspaces();
@@ -592,6 +639,7 @@ Rectangle {
592 from: "*"
639 from: "*"
593 to: "altTab"
640 to: "altTab"
594 SequentialAnimation {
641 SequentialAnimation {
642+ PropertyAction { target: hoverMouseArea; property: "progressiveScrollingEnabled"; value: false }
595 PropertyAction { target: appRepeater; property: "highlightedIndex"; value: Math.min(ApplicationManager.count - 1, 1) }
643 PropertyAction { target: appRepeater; property: "highlightedIndex"; value: Math.min(ApplicationManager.count - 1, 1) }
596 PauseAnimation { duration: 50 }
644 PauseAnimation { duration: 50 }
597 PropertyAction { target: workspaceSelector; property: "visible" }
645 PropertyAction { target: workspaceSelector; property: "visible" }
@@ -616,19 +664,20 @@ Rectangle {
616 ]
664 ]
617
665
618 MouseArea {
666 MouseArea {
667+ id: rightEdgePushArea
619− anchors {
668+ anchors {
620− top: parent.top
669+ top: parent.top
621− right: parent.right
670+ right: parent.right
622− bottom: parent.bottom
671+ bottom: parent.bottom
623− }
672+ }
624− // TODO: Make this a push to edge thing like the launcher when we can,
673+ // TODO: Make this a push to edge thing like the launcher when we can,
625− // for now, yes, we want 1 pixel, regardless of the scaling
674+ // for now, yes, we want 1 pixel, regardless of the scaling
626− width: 1
675+ width: 1
627− hoverEnabled: true
676+ hoverEnabled: true
628− onContainsMouseChanged: {
677+ onContainsMouseChanged: {
629− if (containsMouse) {
678+ if (containsMouse) {
630− root.state = "altTab"
679+ root.state = "altTab";
631− }
680+ }
632− }
681+ }
633 }
682 }
634}
683}
qml/Stages/WindowMoveResizeArea.qml+1−1
@@ -104,6 +104,6 @@ MouseArea {
104 }
104 }
105
105
106 Component.onDestruction: {
106 Component.onDestruction: {
107− windowStateStorage.saveGeometry(root.windowId, Qt.rect(target.x, target.y, target.width, target.height))
107+ windowStateStorage.saveGeometry(root.windowId, Qt.rect(target.x, target.y, target.windowWidth, target.windowHeight))
108 }
108 }
109}
109}
tests/mocks/Utils/CMakeLists.txt+1
@@ -10,6 +10,7 @@ include_directories(
10)
10)
11
11
12set(QMLPLUGIN_SRC
12set(QMLPLUGIN_SRC
13+ ${CMAKE_SOURCE_DIR}/plugins/Utils/activefocuslogger.cpp
13 ${CMAKE_SOURCE_DIR}/plugins/Utils/qlimitproxymodelqml.cpp
14 ${CMAKE_SOURCE_DIR}/plugins/Utils/qlimitproxymodelqml.cpp
14 ${CMAKE_SOURCE_DIR}/plugins/Utils/unitysortfilterproxymodelqml.cpp
15 ${CMAKE_SOURCE_DIR}/plugins/Utils/unitysortfilterproxymodelqml.cpp
15 ${CMAKE_SOURCE_DIR}/plugins/Utils/relativetimeformatter.cpp
16 ${CMAKE_SOURCE_DIR}/plugins/Utils/relativetimeformatter.cpp
tests/mocks/Utils/plugin.cpp+2
@@ -35,6 +35,7 @@
35#include "constants.h"
35#include "constants.h"
36
36
37// plugin
37// plugin
38+#include <activefocuslogger.h>
38#include <inputwatcher.h>
39#include <inputwatcher.h>
39#include <qlimitproxymodelqml.h>
40#include <qlimitproxymodelqml.h>
40#include <unitysortfilterproxymodelqml.h>
41#include <unitysortfilterproxymodelqml.h>
@@ -74,6 +75,7 @@ void FakeUtilsPlugin::registerTypes(const char *uri)
74 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
75 qmlRegisterSingletonType<WindowStateStorage>(uri, 0, 1, "WindowStateStorage", createWindowStateStorage);
75 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
76 qmlRegisterType<InputWatcher>(uri, 0, 1, "InputWatcher");
76 qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
77 qmlRegisterSingletonType<Constants>(uri, 0, 1, "Constants", createConstants);
78+ qmlRegisterType<ActiveFocusLogger>(uri, 0, 1, "ActiveFocusLogger");
77}
79}
78
80
79void FakeUtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
81void FakeUtilsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
tests/qmltests/Stages/tst_DesktopStage.qml+2−3
@@ -61,7 +61,6 @@ Item {
61 Component.onDestruction: {
61 Component.onDestruction: {
62 desktopStageLoader.itemDestroyed = true;
62 desktopStageLoader.itemDestroyed = true;
63 }
63 }
64− focus: true
65 }
64 }
66 }
65 }
67 }
66 }
@@ -142,8 +141,8 @@ Item {
142
141
143 function test_appFocusSwitch_data() {
142 function test_appFocusSwitch_data() {
144 return [
143 return [
145− {tag: "dash", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 0, focusTo: 1 },
144+ {tag: "dash to dialer", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 0, focusTo: 1 },
146− {tag: "dash", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 1, focusTo: 0 },
145+ {tag: "dialer to dash", apps: [ "unity8-dash", "dialer-app", "camera-app" ], focusfrom: 1, focusTo: 0 },
147 ]
146 ]
148 }
147 }
149
148
tests/qmltests/tst_Shell.qml+37−3
@@ -1566,8 +1566,6 @@ Rectangle {
1566 keyPress(Qt.Key_Control)
1566 keyPress(Qt.Key_Control)
1567 keyClick(Qt.Key_Tab);
1567 keyClick(Qt.Key_Tab);
1568
1568
1569− appRemovedSpy.clear();
1570−
1571 var focusAppId = ApplicationManager.get(2).appId;
1569 var focusAppId = ApplicationManager.get(2).appId;
1572 var appDelegate2 = appRepeater.itemAt(2);
1570 var appDelegate2 = appRepeater.itemAt(2);
1573 var decoratedWindow = findChild(appDelegate2, "decoratedWindow");
1571 var decoratedWindow = findChild(appDelegate2, "decoratedWindow");
@@ -1577,7 +1575,7 @@ Rectangle {
1577
1575
1578 // Move the mouse over tile 2 and verify the highlight becomes visible
1576 // Move the mouse over tile 2 and verify the highlight becomes visible
1579 var x = 0;
1577 var x = 0;
1580− var y = shell.height * (data.tileInfo ? .5 : 0.95)
1578+ var y = shell.height * (data.tileInfo ? .95 : 0.5)
1581 mouseMove(shell, x, y)
1579 mouseMove(shell, x, y)
1582 while (appRepeater.highlightedIndex !== 2 && x <= 4000) {
1580 while (appRepeater.highlightedIndex !== 2 && x <= 4000) {
1583 x+=10;
1581 x+=10;
@@ -1595,5 +1593,41 @@ Rectangle {
1595
1593
1596 keyRelease(Qt.Key_Control);
1594 keyRelease(Qt.Key_Control);
1597 }
1595 }
1596+
1597+ function test_progressiveAutoScrolling() {
1598+ loadDesktopShellWithApps()
1599+
1600+ var appRepeater = findInvisibleChild(shell, "appRepeater");
1601+ verify(appRepeater !== null);
1602+
1603+ keyPress(Qt.Key_Control)
1604+ keyClick(Qt.Key_Tab);
1605+
1606+ var spreadFlickable = findChild(shell, "spreadFlickable")
1607+ print("have flickable", spreadFlickable, spreadFlickable.contentX)
1608+
1609+ compare(spreadFlickable.contentX, 0);
1610+
1611+ // Move the mouse to the right and make sure it scrolls the Flickable
1612+ var x = 0;
1613+ var y = shell.height * .5
1614+ mouseMove(shell, x, y)
1615+ while (x <= spreadFlickable.width) {
1616+ x+=10;
1617+ mouseMove(shell, x, y)
1618+ wait(0); // spin the loop so bindings get evaluated
1619+ }
1620+ tryCompare(spreadFlickable, "contentX", spreadFlickable.contentWidth - spreadFlickable.width);
1621+
1622+ // And turn around
1623+ while (x > 0) {
1624+ x-=10;
1625+ mouseMove(shell, x, y)
1626+ wait(0); // spin the loop so bindings get evaluated
1627+ }
1628+ tryCompare(spreadFlickable, "contentX", 0);
1629+
1630+ keyRelease(Qt.Key_Control);
1631+ }
1598 }
1632 }
1599}
1633}
tests/uqmlscene/CMakeLists.txt−1
@@ -1,6 +1,5 @@
1add_executable(uqmlscene
1add_executable(uqmlscene
2 ${shellapplication_MOC_SRCS}
2 ${shellapplication_MOC_SRCS}
3− ActiveFocusLogger.cpp
4 main.cpp
3 main.cpp
5 )
4 )
6
5
tests/uqmlscene/main.cpp−13
@@ -63,12 +63,6 @@
63#include <QtCore/QTranslator>
63#include <QtCore/QTranslator>
64#include <QtCore/QLibraryInfo>
64#include <QtCore/QLibraryInfo>
65
65
66−#define UQMLSCENE_DEBUG_ACTIVE_FOCUS 0
67−
68−#if UQMLSCENE_DEBUG_ACTIVE_FOCUS
69− #include "ActiveFocusLogger.h"
70−#endif
71−
72#ifdef QML_RUNTIME_TESTING
66#ifdef QML_RUNTIME_TESTING
73class RenderStatistics
67class RenderStatistics
74{
68{
@@ -393,10 +387,6 @@ int main(int argc, char ** argv)
393{
387{
394 Options options;
388 Options options;
395
389
396− #if UQMLSCENE_DEBUG_ACTIVE_FOCUS
397− ActiveFocusLogger activeFocusLogger;
398− #endif
399−
400 QStringList imports;
390 QStringList imports;
401 QList<QPair<QString, QString> > bundles;
391 QList<QPair<QString, QString> > bundles;
402 for (int i = 1; i < argc; ++i) {
392 for (int i = 1; i < argc; ++i) {
@@ -515,9 +505,6 @@ int main(int argc, char ** argv)
515 QQuickItem *contentItem = qobject_cast<QQuickItem *>(topLevel);
505 QQuickItem *contentItem = qobject_cast<QQuickItem *>(topLevel);
516 if (contentItem) {
506 if (contentItem) {
517 qxView = new QQuickView(&engine, nullptr);
507 qxView = new QQuickView(&engine, nullptr);
518− #if UQMLSCENE_DEBUG_ACTIVE_FOCUS
519− activeFocusLogger.setWindow(qxView);
520− #endif
521 window = qxView;
508 window = qxView;
522 // Set window default properties; the qml can still override them
509 // Set window default properties; the qml can still override them
523 QString oname = contentItem->objectName();
510 QString oname = contentItem->objectName();