on xenial help sign in
Change the behavior alond with the switch in indicator-display Fixes: #1538591

Approved by: Michael Terry

commitfd5249a4605a507e47ff95ebcbb8a0f8fdaca5ea authorMichael Zanetti <michael.zanetti@canonical.com> dateWed 23 Mar 2016, 09:52 (11 years ago) parent97c7af3ad2d7ba
3 files changed+95−71
qml/Components/Unity8Settings.qml−50 qml/OrientedShell.qml+27−17 tests/qmltests/tst_OrientedShell.qml+68−4
qml/Components/Unity8Settings.qmldeleted−50
@@ -1,50 +0,0 @@
1−/*
2− * Copyright (C) 2015 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.4
18−import GSettings 1.0
19−
20−QtObject {
21− id: root
22−
23− property string usageMode: "Staged"
24−
25− // FIXME: Works around a bug where if we change a Loader's source in response to a GSettings
26− // property change in the same event loop, the Loader's previously loaded component does not
27− // get destroyed and its bindings continue to operate!
28− //
29− // Shouldn't be needed after
30− // https://code.launchpad.net/~lukas-kde/gsettings-qt/queued-processing/+merge/259883 gets
31− // merged.
32− property var timer: Timer {
33− interval: 1
34− onTriggered: { root.usageMode = root.wrapped.usageMode; }
35− }
36− property var wrappedConnections: Connections {
37− target: root.wrapped
38− ignoreUnknownSignals: true // don't spam us
39− onUsageModeChanged: { root.timer.start(); }
40− }
41− property var wrapped: GSettings {
42− schema.id: "com.canonical.Unity8"
43− Component.onCompleted: {
44− // init the value. it's a dynamic prop, so we have to check first
45− if (root.usageMode) {
46− root.usageMode = root.wrapped.usageMode;
47− }
48− }
49− }
50−}
qml/OrientedShell.qml+27−17
@@ -58,7 +58,7 @@ Rectangle {
5858 }
5959 }
6060 // to be overwritten by tests
61− property var unity8Settings: Unity8Settings {}
61+ property var unity8Settings: GSettings { schema.id: "com.canonical.Unity8" }
6262 property var oskSettings: GSettings { schema.id: "com.canonical.keyboard.maliit" }
6363
6464 property int physicalOrientation: Screen.orientation
@@ -68,11 +68,13 @@ Rectangle {
6868 InputDeviceModel {
6969 id: miceModel
7070 deviceFilter: InputInfo.Mouse
71+ property int oldCount: 0
7172 }
7273
7374 InputDeviceModel {
7475 id: touchPadModel
7576 deviceFilter: InputInfo.TouchPad
77+ property int oldCount: 0
7678 }
7779
7880 InputDeviceModel {
@@ -87,6 +89,29 @@ Rectangle {
8789 deviceFilter: InputInfo.TouchScreen
8890 }
8991
92+ readonly property int pointerInputDevices: miceModel.count + touchPadModel.count
93+ onPointerInputDevicesChanged: {
94+ console.log("Pointer input devices changed:", pointerInputDevices, "current mode:", root.unity8Settings.usageMode, "old device count", miceModel.oldCount + touchPadModel.oldCount)
95+ if (root.unity8Settings.usageMode === "Windowed") {
96+ if (pointerInputDevices === 0) {
97+ // All pointer devices have been unplugged. Move to staged.
98+ root.unity8Settings.usageMode = "Staged";
99+ }
100+ } else {
101+ var longEdgeWidth = Math.max(root.width, root.height)
102+ if (longEdgeWidth > units.gu(90)){
103+ if (pointerInputDevices > 0 && pointerInputDevices > miceModel.oldCount + touchPadModel.oldCount) {
104+ root.unity8Settings.usageMode = "Windowed";
105+ }
106+ } else {
107+ // Make sure we initialize to something sane
108+ root.unity8Settings.usageMode = "Staged";
109+ }
110+ }
111+ miceModel.oldCount = miceModel.count;
112+ touchPadModel.oldCount = touchPadModel.count;
113+ }
114+
90115 /* FIXME: This exposes the NameRole as a work arround for lp:1542224.
91116 * When QInputInfo exposes NameRole to QML, this should be removed.
92117 */
@@ -222,30 +247,15 @@ Rectangle {
222247 oskEnabled: (keyboardsModel.count === 0 && screens.count === 1) ||
223248 forceOSKEnabled
224249
225− // TODO: Factor in the connected input devices (eg: physical keyboard, mouse, touchscreen),
226− // what's the output device (eg: big TV, desktop monitor, phone display), etc.
227250 usageScenario: {
228251 if (root.unity8Settings.usageMode === "Windowed") {
229252 return "desktop";
230− } else if (root.unity8Settings.usageMode === "Staged") {
253+ } else {
231254 if (deviceConfiguration.category === "phone") {
232255 return "phone";
233256 } else {
234257 return "tablet";
235258 }
236− } else { // automatic
237− var longEdgeWidth = Math.max(root.width, root.height)
238− if (longEdgeWidth > units.gu(120)) {
239− if (keyboardsModel.count + miceModel.count + touchPadModel.count > 0) {
240− return "desktop";
241− }
242− } else if (longEdgeWidth > units.gu(90)){
243− if (miceModel.count + touchPadModel.count > 0) {
244− return "desktop";
245− }
246− }
247−
248− return deviceConfiguration.category;
249259 }
250260 }
251261
tests/qmltests/tst_OrientedShell.qml+68−4
@@ -47,6 +47,9 @@ Rectangle {
4747 QtObject {
4848 id: mockUnity8Settings
4949 property string usageMode: usageModeSelector.model[usageModeSelector.selectedIndex]
50+ onUsageModeChanged: {
51+ usageModeSelector.selectedIndex = usageModeSelector.model.indexOf(usageMode)
52+ }
5053 }
5154
5255 QtObject{
@@ -307,6 +310,9 @@ Rectangle {
307310 function selectStaged() {selectedIndex = 0;}
308311 function selectWindowed() {selectedIndex = 1;}
309312 function selectAutomatic() {selectedIndex = 2;}
313+ onSelectedIndexChanged: {
314+ mockUnity8Settings.usageMode = usageModeSelector.model[usageModeSelector.selectedIndex]
315+ }
310316 }
311317 MouseTouchEmulationCheckbox {
312318 checked: true
@@ -1058,7 +1064,7 @@ Rectangle {
10581064 { tag: "big screen, mouse", screenWidth: units.gu(200), mouse: true, kbd: false, expectedMode: "desktop", oskExpected: true },
10591065 { tag: "small screen, kbd", screenWidth: units.gu(50), mouse: false, kbd: true, expectedMode: "phone", oskExpected: false },
10601066 { tag: "medium screen, kbd", screenWidth: units.gu(100), mouse: false, kbd: true, expectedMode: "phone", oskExpected: false },
1061− { tag: "big screen, kbd", screenWidth: units.gu(200), mouse: false, kbd: true, expectedMode: "desktop", oskExpected: false },
1067+ { tag: "big screen, kbd", screenWidth: units.gu(200), mouse: false, kbd: true, expectedMode: "phone", oskExpected: false },
10621068 { tag: "small screen, mouse & kbd", screenWidth: units.gu(50), mouse: true, kbd: true, expectedMode: "phone", oskExpected: false },
10631069 { tag: "medium screen, mouse & kbd", screenWidth: units.gu(100), mouse: true, kbd: true, expectedMode: "desktop", oskExpected: false },
10641070 { tag: "big screen, mouse & kbd", screenWidth: units.gu(200), mouse: true, kbd: true, expectedMode: "desktop", oskExpected: false },
@@ -1066,9 +1072,6 @@ Rectangle {
10661072 }
10671073
10681074 function test_attachRemoveInputDevices(data) {
1069− usageModeSelector.selectAutomatic();
1070− tryCompare(mockUnity8Settings, "usageMode", "Automatic")
1071−
10721075 loadShell("mako")
10731076 var shell = findChild(orientedShell, "shell");
10741077 var inputMethod = findChild(shell, "inputMethod");
@@ -1102,6 +1105,67 @@ Rectangle {
11021105 orientedShellLoader.width = oldWidth;
11031106 }
11041107
1108+ function test_overrideStaged() {
1109+ loadShell("mako")
1110+
1111+ // make sure we're big enough so that the automatism starts working
1112+ var oldWidth = orientedShellLoader.width;
1113+ orientedShellLoader.width = units.gu(100);
1114+
1115+ // start off by plugging a mouse, we should switch to windowed
1116+ MockInputDeviceBackend.addMockDevice("/mouse0", InputInfo.Mouse);
1117+ tryCompare(shell, "usageScenario", "desktop");
1118+
1119+ // Use the toggle to go back to Staged
1120+ usageModeSelector.selectStaged();
1121+ tryCompare(shell, "usageScenario", "phone");
1122+
1123+ // attach a second mouse, we should switch again
1124+ MockInputDeviceBackend.addMockDevice("/mouse1", InputInfo.Mouse);
1125+ tryCompare(shell, "usageScenario", "desktop");
1126+
1127+ // Remove one mouse again, stay in windowed as there is another
1128+ MockInputDeviceBackend.removeDevice("/mouse1");
1129+ tryCompare(shell, "usageScenario", "desktop");
1130+
1131+ // use the toggle again
1132+ usageModeSelector.selectStaged();
1133+ tryCompare(shell, "usageScenario", "phone");
1134+
1135+ // Remove the other mouse again, stay in staged
1136+ MockInputDeviceBackend.removeDevice("/mouse0");
1137+ tryCompare(shell, "usageScenario", "phone");
1138+
1139+ // Restore width
1140+ orientedShellLoader.width = oldWidth;
1141+ }
1142+
1143+ function test_overrideWindowed() {
1144+ loadShell("mako")
1145+
1146+ // make sure we're big enough so that the automatism starts working
1147+ var oldWidth = orientedShellLoader.width;
1148+ orientedShellLoader.width = units.gu(100);
1149+
1150+ // No mouse attached... we should be in staged
1151+ tryCompare(shell, "usageScenario", "phone");
1152+
1153+ // use the toggle to go to windowed
1154+ usageModeSelector.selectWindowed();
1155+ tryCompare(shell, "usageScenario", "desktop");
1156+
1157+ // Connect a mouse, stay in windowed
1158+ MockInputDeviceBackend.addMockDevice("/mouse0", InputInfo.Mouse);
1159+ tryCompare(shell, "usageScenario", "desktop");
1160+
1161+ // Remove the mouse again, we should go to staged
1162+ MockInputDeviceBackend.removeDevice("/mouse0");
1163+ tryCompare(shell, "usageScenario", "phone");
1164+
1165+ // Restore width
1166+ orientedShellLoader.width = oldWidth;
1167+ }
1168+
11051169 /*
11061170 Regression test for https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1471609
11071171