on xenial help sign in
merge prereq
5e3a45cMichael Zanetti
qml/Components/InputMethod.qml−12
@@ -62,18 +62,6 @@ Item {
62 }
62 }
63 ]
63 ]
64
64
65− Connections {
66− target: surface
67− ignoreUnknownSignals: true // don't wanna spam the log when surface is null
68− onStateChanged: {
69− if (state == MirSurfaceItem.Minimized) {
70− root.hide();
71− } else if (state == MirSurfaceItem.Maximized) {
72− root.show();
73− }
74− }
75− }
76−
77 onSurfaceChanged: {
65 onSurfaceChanged: {
78 if (surface) {
66 if (surface) {
79 surface.parent = root;
67 surface.parent = root;
qml/Panel/Indicators.qml+1
@@ -37,6 +37,7 @@ Showable {
37 readonly property int lockThreshold: openedHeight / 2
37 readonly property int lockThreshold: openedHeight / 2
38 property bool fullyOpened: height == openedHeight
38 property bool fullyOpened: height == openedHeight
39 property bool partiallyOpened: height > panelHeight && !fullyOpened
39 property bool partiallyOpened: height > panelHeight && !fullyOpened
40+ property bool fullyClosed: height <= panelHeight
40 property bool contentEnabled: true
41 property bool contentEnabled: true
41 property bool initalizeItem: true
42 property bool initalizeItem: true
42 readonly property alias content: menuContent
43 readonly property alias content: menuContent
qml/Shell.qml+5−2
@@ -115,7 +115,8 @@ Item {
115 anchors.fill: parent
115 anchors.fill: parent
116
116
117 // Whether the underlay is fully covered by opaque UI elements.
117 // Whether the underlay is fully covered by opaque UI elements.
118− property bool fullyCovered: panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth
118+ property bool fullyCovered: (panel.indicators.fullyOpened && shell.width <= panel.indicatorsMenuWidth)
119+ || stages.fullyShown || greeterWrapper.fullyShown
119 visible: !fullyCovered
120 visible: !fullyCovered
120
121
121 Image {
122 Image {
@@ -345,7 +346,7 @@ Item {
345 Binding {
346 Binding {
346 target: applicationsDisplayLoader.item
347 target: applicationsDisplayLoader.item
347 property: "interactive"
348 property: "interactive"
348− value: !greeter.shown && !lockscreen.shown
349+ value: !greeter.shown && !lockscreen.shown && panel.indicators.fullyClosed
349 }
350 }
350 Binding {
351 Binding {
351 target: applicationsDisplayLoader.item
352 target: applicationsDisplayLoader.item
@@ -357,6 +358,7 @@ Item {
357
358
358 InputMethod {
359 InputMethod {
359 id: inputMethod
360 id: inputMethod
361+ objectName: "inputMethod"
360 anchors { fill: parent; topMargin: panel.panelHeight }
362 anchors { fill: parent; topMargin: panel.panelHeight }
361 z: notifications.useModal || panel.indicators.shown ? overlay.z + 1 : overlay.z - 1
363 z: notifications.useModal || panel.indicators.shown ? overlay.z + 1 : overlay.z - 1
362 }
364 }
@@ -473,6 +475,7 @@ Item {
473 StandardAnimation {}
475 StandardAnimation {}
474 }
476 }
475
477
478+ property bool fullyShown: showProgress === 1.0
476 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
479 readonly property real showProgress: MathUtils.clamp((1 - x/width) + greeter.showProgress - 1, 0, 1)
477 onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
480 onShowProgressChanged: if (LightDM.Greeter.promptless && showProgress === 0) greeter.login()
478
481
tests/mocks/Unity/Application/Application.qmltypes−2
@@ -102,8 +102,6 @@ Module {
102 "ForceMainStage": 1
102 "ForceMainStage": 1
103 }
103 }
104 }
104 }
105− Property { name: "keyboardHeight"; type: "int"; isReadonly: true }
106− Property { name: "keyboardVisible"; type: "bool"; isReadonly: true }
107 Property { name: "sideStageWidth"; type: "int"; isReadonly: true }
105 Property { name: "sideStageWidth"; type: "int"; isReadonly: true }
108 Property { name: "stageHint"; type: "StageHint"; isReadonly: true }
106 Property { name: "stageHint"; type: "StageHint"; isReadonly: true }
109 Property { name: "formFactorHint"; type: "FormFactorHint"; isReadonly: true }
107 Property { name: "formFactorHint"; type: "FormFactorHint"; isReadonly: true }
tests/mocks/Unity/Application/ApplicationInfo.cpp+3−2
@@ -91,11 +91,12 @@ void ApplicationInfo::createSurface()
91void ApplicationInfo::destroySurface()
91void ApplicationInfo::destroySurface()
92{
92{
93 if (!m_surface) return;
93 if (!m_surface) return;
94+
95+ SurfaceManager::singleton()->unregisterSurface(m_surface);
96+
94 MirSurfaceItem* oldSurface = m_surface;
97 MirSurfaceItem* oldSurface = m_surface;
95 m_surface = nullptr;
98 m_surface = nullptr;
96−
97 Q_EMIT surfaceChanged(nullptr);
99 Q_EMIT surfaceChanged(nullptr);
98− SurfaceManager::singleton()->unregisterSurface(m_surface);
99 oldSurface->deleteLater();
100 oldSurface->deleteLater();
100}
101}
101
102
tests/mocks/Unity/Application/ApplicationManager.cpp+7−10
@@ -118,6 +118,7 @@ void ApplicationManager::add(ApplicationInfo *application) {
118 endInsertRows();
118 endInsertRows();
119 Q_EMIT applicationAdded(application->appId());
119 Q_EMIT applicationAdded(application->appId());
120 Q_EMIT countChanged();
120 Q_EMIT countChanged();
121+ if (count() == 1) Q_EMIT emptyChanged(isEmpty()); // was empty but not anymore
121 Q_EMIT focusRequested(application->appId());
122 Q_EMIT focusRequested(application->appId());
122
123
123 connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() {
124 connect(application, &ApplicationInfo::surfaceChanged, this, [application, this]() {
@@ -135,6 +136,7 @@ void ApplicationManager::remove(ApplicationInfo *application) {
135 endRemoveRows();
136 endRemoveRows();
136 Q_EMIT applicationRemoved(application->appId());
137 Q_EMIT applicationRemoved(application->appId());
137 Q_EMIT countChanged();
138 Q_EMIT countChanged();
139+ if (isEmpty()) Q_EMIT emptyChanged(isEmpty());
138 }
140 }
139 disconnect(application, &ApplicationInfo::surfaceChanged, this, 0);
141 disconnect(application, &ApplicationInfo::surfaceChanged, this, 0);
140}
142}
@@ -153,16 +155,6 @@ void ApplicationManager::move(int from, int to) {
153 }
155 }
154}
156}
155
157
156−int ApplicationManager::keyboardHeight() const
157−{
158− return 0;
159−}
160−
161−bool ApplicationManager::keyboardVisible() const
162−{
163− return false;
164−}
165−
166int ApplicationManager::sideStageWidth() const
158int ApplicationManager::sideStageWidth() const
167{
159{
168 return 0;
160 return 0;
@@ -601,3 +593,8 @@ void ApplicationManager::setRightMargin(int rightMargin)
601 generateQmlStrings(app);
593 generateQmlStrings(app);
602 }
594 }
603}
595}
596+
597+bool ApplicationManager::isEmpty() const
598+{
599+ return m_runningApplications.isEmpty();
600+}
tests/mocks/Unity/Application/ApplicationManager.h+4−8
@@ -36,8 +36,7 @@ class ApplicationManager : public ApplicationManagerInterface {
36 Q_ENUMS(FavoriteApplication)
36 Q_ENUMS(FavoriteApplication)
37 Q_FLAGS(ExecFlags)
37 Q_FLAGS(ExecFlags)
38
38
39− Q_PROPERTY(int keyboardHeight READ keyboardHeight NOTIFY keyboardHeightChanged)
39+ Q_PROPERTY(bool empty READ isEmpty NOTIFY emptyChanged)
40− Q_PROPERTY(bool keyboardVisible READ keyboardVisible NOTIFY keyboardVisibleChanged)
41
40
42 Q_PROPERTY(int sideStageWidth READ sideStageWidth)
41 Q_PROPERTY(int sideStageWidth READ sideStageWidth)
43 Q_PROPERTY(StageHint stageHint READ stageHint)
42 Q_PROPERTY(StageHint stageHint READ stageHint)
@@ -78,8 +77,6 @@ class ApplicationManager : public ApplicationManagerInterface {
78 };
77 };
79 Q_DECLARE_FLAGS(ExecFlags, Flag)
78 Q_DECLARE_FLAGS(ExecFlags, Flag)
80
79
81− int keyboardHeight() const;
82− bool keyboardVisible() const;
83 int sideStageWidth() const;
80 int sideStageWidth() const;
84 StageHint stageHint() const;
81 StageHint stageHint() const;
85 FormFactorHint formFactorHint() const;
82 FormFactorHint formFactorHint() const;
@@ -114,11 +111,12 @@ class ApplicationManager : public ApplicationManagerInterface {
114
111
115 QModelIndex findIndex(ApplicationInfo* application);
112 QModelIndex findIndex(ApplicationInfo* application);
116
113
114+ bool isEmpty() const;
115+
117 Q_SIGNALS:
116 Q_SIGNALS:
118− void keyboardHeightChanged();
119− void keyboardVisibleChanged();
120 void focusRequested(FavoriteApplication favoriteApplication);
117 void focusRequested(FavoriteApplication favoriteApplication);
121 void focusRequested(const QString &appId);
118 void focusRequested(const QString &appId);
119+ void emptyChanged(bool empty);
122
120
123 private:
121 private:
124 void add(ApplicationInfo *application);
122 void add(ApplicationInfo *application);
@@ -130,8 +128,6 @@ class ApplicationManager : public ApplicationManagerInterface {
130 void createMainStage();
128 void createMainStage();
131 void createSideStageComponent();
129 void createSideStageComponent();
132 void createSideStage();
130 void createSideStage();
133− int m_keyboardHeight;
134− bool m_keyboardVisible;
135 bool m_suspended;
131 bool m_suspended;
136 QList<ApplicationInfo*> m_runningApplications;
132 QList<ApplicationInfo*> m_runningApplications;
137 QList<ApplicationInfo*> m_availableApplications;
133 QList<ApplicationInfo*> m_availableApplications;
tests/mocks/Unity/Application/MirSurfaceItem.h+1−1
@@ -62,7 +62,7 @@ public:
62 State state() const { return m_state; }
62 State state() const { return m_state; }
63 QString name() const { return m_name; }
63 QString name() const { return m_name; }
64
64
65− void setState(State newState);
65+ Q_INVOKABLE void setState(State newState);
66
66
67 Q_INVOKABLE void release() {}
67 Q_INVOKABLE void release() {}
68
68
tests/mocks/Unity/Application/SurfaceManager.cpp+10−5
@@ -52,11 +52,7 @@ void SurfaceManager::unregisterSurface(MirSurfaceItem *surface)
52
52
53void SurfaceManager::showInputMethod()
53void SurfaceManager::showInputMethod()
54{
54{
55− if (!m_virtualKeyboard) {
56− m_virtualKeyboard = new VirtualKeyboard(MirSurfaceItem::Minimized);
57− Q_EMIT surfaceCreated(m_virtualKeyboard);
58− }
59− m_virtualKeyboard->setState(MirSurfaceItem::Restored);
55+ inputMethodSurface()->setState(MirSurfaceItem::Restored);
60}
56}
61
57
62void SurfaceManager::hideInputMethod()
58void SurfaceManager::hideInputMethod()
@@ -65,3 +61,12 @@ void SurfaceManager::hideInputMethod()
65 m_virtualKeyboard->setState(MirSurfaceItem::Minimized);
61 m_virtualKeyboard->setState(MirSurfaceItem::Minimized);
66 }
62 }
67}
63}
64+
65+MirSurfaceItem *SurfaceManager::inputMethodSurface()
66+{
67+ if (!m_virtualKeyboard) {
68+ m_virtualKeyboard = new VirtualKeyboard(MirSurfaceItem::Minimized);
69+ Q_EMIT surfaceCreated(m_virtualKeyboard);
70+ }
71+ return m_virtualKeyboard;
72+}
tests/mocks/Unity/Application/SurfaceManager.h+3
@@ -34,6 +34,9 @@ public:
34 void registerSurface(MirSurfaceItem *surface);
34 void registerSurface(MirSurfaceItem *surface);
35 void unregisterSurface(MirSurfaceItem *surface);
35 void unregisterSurface(MirSurfaceItem *surface);
36
36
37+ // To be used in the tests
38+ Q_INVOKABLE MirSurfaceItem *inputMethodSurface();
39+
37Q_SIGNALS:
40Q_SIGNALS:
38 void countChanged();
41 void countChanged();
39 void surfaceCreated(MirSurfaceItem *surface);
42 void surfaceCreated(MirSurfaceItem *surface);
tests/qmltests/tst_Shell.qml+81−7
@@ -354,6 +354,58 @@ Item {
354 verify(itemIsOnScreen(dashApps));
354 verify(itemIsOnScreen(dashApps));
355 }
355 }
356
356
357+ function test_showInputMethod() {
358+ var item = findChild(shell, "inputMethod");
359+ var surface = SurfaceManager.inputMethodSurface();
360+
361+ surface.setState(MirSurfaceItem.Minimized);
362+ tryCompare(item, "visible", false);
363+
364+ surface.setState(MirSurfaceItem.Restored);
365+ tryCompare(item, "visible", true);
366+
367+ surface.setState(MirSurfaceItem.Minimized);
368+ tryCompare(item, "visible", false);
369+
370+ surface.setState(MirSurfaceItem.Maximized);
371+ tryCompare(item, "visible", true);
372+
373+ surface.setState(MirSurfaceItem.Minimized);
374+ tryCompare(item, "visible", false);
375+ }
376+
377+ function test_surfaceLosesFocusWhilePanelIsOpen() {
378+ var app = ApplicationManager.startApplication("dialer-app");
379+ // wait until the app is fully loaded (ie, real surface replaces splash screen)
380+ tryCompareFunction(function() { return app.surface != null }, true);
381+
382+ tryCompare(app.surface, "focus", true);
383+
384+ // Drag the indicators panel half-open
385+ var touchX = shell.width / 2;
386+ var indicators = findChild(shell, "indicators");
387+ touchFlick(indicators,
388+ touchX /* fromX */, indicators.panelHeight * 0.5 /* fromY */,
389+ touchX /* toX */, shell.height * 0.5 /* toY */,
390+ true /* beginTouch */, false /* endTouch */);
391+ verify(indicators.partiallyOpened);
392+
393+ tryCompare(app.surface, "focus", false);
394+
395+ // And finish getting it open
396+ touchFlick(indicators,
397+ touchX /* fromX */, shell.height * 0.5 /* fromY */,
398+ touchX /* toX */, shell.height * 0.9 /* toY */,
399+ false /* beginTouch */, true /* endTouch */);
400+ tryCompare(indicators, "fullyOpened", true);
401+
402+ tryCompare(app.surface, "focus", false);
403+
404+ dragToCloseIndicatorsPanel();
405+
406+ tryCompare(app.surface, "focus", true);
407+ }
408+
357 // Wait for the whole UI to settle down
409 // Wait for the whole UI to settle down
358 function waitForUIToSettle() {
410 function waitForUIToSettle() {
359 waitUntilApplicationWindowIsFullyHidden();
411 waitUntilApplicationWindowIsFullyHidden();
@@ -361,6 +413,18 @@ Item {
361 tryCompare(dashContentList, "moving", false);
413 tryCompare(dashContentList, "moving", false);
362 }
414 }
363
415
416+ function dragToCloseIndicatorsPanel() {
417+ var indicators = findChild(shell, "indicators");
418+
419+ var touchStartX = shell.width / 2;
420+ var touchStartY = shell.height - (indicators.panelHeight * 0.5);
421+ touchFlick(shell,
422+ touchStartX, touchStartY,
423+ touchStartX, shell.height * 0.1);
424+
425+ tryCompare(indicators, "fullyClosed", true);
426+ }
427+
364 function dragLauncherIntoView() {
428 function dragLauncherIntoView() {
365 var launcherPanel = findChild(shell, "launcherPanel");
429 var launcherPanel = findChild(shell, "launcherPanel");
366 verify(launcherPanel.x = - launcherPanel.width);
430 verify(launcherPanel.x = - launcherPanel.width);
@@ -485,7 +549,7 @@ Item {
485 {tag: "under greeter", greeter: true, app: false, launcher: false, indicators: false, expectedShown: false},
549 {tag: "under greeter", greeter: true, app: false, launcher: false, indicators: false, expectedShown: false},
486 {tag: "under app", greeter: false, app: true, launcher: false, indicators: false, expectedShown: false},
550 {tag: "under app", greeter: false, app: true, launcher: false, indicators: false, expectedShown: false},
487 {tag: "under launcher", greeter: false, app: false, launcher: true, indicators: false, expectedShown: true},
551 {tag: "under launcher", greeter: false, app: false, launcher: true, indicators: false, expectedShown: true},
488− {tag: "under indicators", greeter: false, app: false, launcher: false, indicators: true, expectedShown: true},
552+ {tag: "under indicators", greeter: false, app: false, launcher: false, indicators: true, expectedShown: false},
489 ]
553 ]
490 }
554 }
491
555
@@ -515,14 +579,24 @@ Item {
515 }
579 }
516
580
517 function test_focusRequestedHidesGreeter() {
581 function test_focusRequestedHidesGreeter() {
518− var greeter = findChild(shell, "greeter")
582+ var greeter = findChild(shell, "greeter");
519
583
520− greeter.show()
584+ var app = ApplicationManager.startApplication("dialer-app");
521− tryCompare(greeter, "showProgress", 1)
585+ // wait until the app is fully loaded (ie, real surface replaces splash screen)
586+ tryCompareFunction(function() { return app.surface != null }, true);
522
587
588+ // Minimize the application we just launched
589+ swipeFromLeftEdge(units.gu(27));
590+
591+ // Wait for the whole UI to settle down
592+ waitUntilApplicationWindowIsFullyHidden();
593+
594+ greeter.show();
595+ tryCompare(greeter, "showProgress", 1);
596+
597+ // The main point of this test
523− ApplicationManager.focusRequested("notes-app")
598+ ApplicationManager.requestFocusApplication("dialer-app");
524− tryCompare(greeter, "showProgress", 0)
599+ tryCompare(greeter, "showProgress", 0);
525− waitUntilApplicationWindowIsFullyVisible()
526 }
600 }
527
601
528 function test_showGreeterDBusCall() {
602 function test_showGreeterDBusCall() {