2 * Copyright (C) 2015 Canonical, Ltd.
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.
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.
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/>.
18 import QtQuick.Window 2.2
19 import Unity.InputInfo 0.1
20 import Unity.Session 0.1
21 import WindowManager 1.0
26 // Workaround https://bugs.launchpad.net/ubuntu/+source/unity8/+bug/1473471
27 import Ubuntu.Components 1.3
32 implicitWidth: units.gu(40)
33 implicitHeight: units.gu(71)
35 property alias deviceConfiguration: _deviceConfiguration
36 property alias orientations: d.orientations
38 onWidthChanged: calculateUsageMode();
41 id: _deviceConfiguration
42 name: applicationArguments.deviceName
48 property Orientations orientations: Orientations {
50 // NB: native and primary orientations here don't map exactly to their QScreen counterparts
51 native_: root.width > root.height ? Qt.LandscapeOrientation : Qt.PortraitOrientation
53 primary: deviceConfiguration.primaryOrientation == deviceConfiguration.useNativeOrientation
54 ? native_ : deviceConfiguration.primaryOrientation
56 landscape: deviceConfiguration.landscapeOrientation
57 invertedLandscape: deviceConfiguration.invertedLandscapeOrientation
58 portrait: deviceConfiguration.portraitOrientation
59 invertedPortrait: deviceConfiguration.invertedPortraitOrientation
65 schema.id: "com.canonical.Unity8"
70 objectName: "oskSettings"
71 schema.id: "com.canonical.keyboard.maliit"
74 property int physicalOrientation: Screen.orientation
75 property bool orientationLocked: OrientationLock.enabled
76 property var orientationLock: OrientationLock
80 deviceFilter: InputInfo.Mouse
81 property int oldCount: 0
86 deviceFilter: InputInfo.TouchPad
87 property int oldCount: 0
92 deviceFilter: InputInfo.Keyboard
93 onDeviceAdded: forceOSKEnabled = autopilotDevicePresent();
94 onDeviceRemoved: forceOSKEnabled = autopilotDevicePresent();
99 deviceFilter: InputInfo.TouchScreen
104 property: "keyboardAttached"
105 value: keyboardsModel.count > 0
108 readonly property int pointerInputDevices: miceModel.count + touchPadModel.count
109 onPointerInputDevicesChanged: calculateUsageMode()
111 function calculateUsageMode() {
112 if (unity8Settings.usageMode === undefined)
113 return; // gsettings isn't loaded yet, we'll try again in Component.onCompleted
115 console.log("Calculating new usage mode. Pointer devices:", pointerInputDevices, "current mode:", unity8Settings.usageMode, "old device count", miceModel.oldCount + touchPadModel.oldCount, "root width:", root.width / units.gu(1), "height:", root.height / units.gu(1))
116 if (unity8Settings.usageMode === "Windowed") {
117 if (Math.min(root.width, root.height) > units.gu(60)) {
118 if (pointerInputDevices === 0) {
119 // All pointer devices have been unplugged. Move to staged.
120 unity8Settings.usageMode = "Staged";
123 // The display is not large enough, use staged.
124 unity8Settings.usageMode = "Staged";
127 if (Math.min(root.width, root.height) > units.gu(60)) {
128 if (pointerInputDevices > 0 && pointerInputDevices > miceModel.oldCount + touchPadModel.oldCount) {
129 unity8Settings.usageMode = "Windowed";
132 // Make sure we initialize to something sane
133 unity8Settings.usageMode = "Staged";
136 miceModel.oldCount = miceModel.count;
137 touchPadModel.oldCount = touchPadModel.count;
140 /* FIXME: This exposes the NameRole as a work arround for lp:1542224.
141 * When QInputInfo exposes NameRole to QML, this should be removed.
143 property bool forceOSKEnabled: false
144 property var autopilotEmulatedDeviceNames: ["py-evdev-uinput"]
145 UnitySortFilterProxyModel {
147 model: keyboardsModel
150 function autopilotDevicePresent() {
151 for(var i = 0; i < autopilotDevices.count; i++) {
152 var device = autopilotDevices.get(i);
153 if (autopilotEmulatedDeviceNames.indexOf(device.name) != -1) {
154 console.warn("Forcing the OSK to be enabled as there is an autopilot eumlated device present.")
161 property int orientation
162 onPhysicalOrientationChanged: {
163 if (!orientationLocked) {
164 orientation = physicalOrientation;
167 onOrientationLockedChanged: {
168 if (orientationLocked) {
169 orientationLock.savedOrientation = physicalOrientation;
171 orientation = physicalOrientation;
174 Component.onCompleted: {
175 if (orientationLocked) {
176 orientation = orientationLock.savedOrientation;
179 calculateUsageMode();
181 // We need to manually update this on startup as the binding
182 // below doesn't seem to have any effect at that stage
183 oskSettings.disableHeight = !shell.oskEnabled || shell.usageScenario == "desktop"
186 // we must rotate to a supported orientation regardless of shell's preference
187 property bool orientationChangesEnabled:
188 (shell.orientation & supportedOrientations) === 0 ? true
189 : shell.orientationChangesEnabled
193 property: "disableHeight"
194 value: !shell.oskEnabled || shell.usageScenario == "desktop"
198 target: unity8Settings
199 property: "oskSwitchVisible"
200 value: shell.hasKeyboard
203 readonly property int supportedOrientations: shell.supportedOrientations
204 & (deviceConfiguration.supportedOrientations == deviceConfiguration.useNativeOrientation
205 ? orientations.native_
206 : deviceConfiguration.supportedOrientations)
208 property int acceptedOrientationAngle: {
209 if (orientation & supportedOrientations) {
210 return Screen.angleBetween(orientations.native_, orientation);
211 } else if (shell.orientation & supportedOrientations) {
213 return shell.orientationAngle;
214 } else if (angleToOrientation(shell.mainAppWindowOrientationAngle) & supportedOrientations) {
215 return shell.mainAppWindowOrientationAngle;
217 // rotate to some supported orientation as we can't stay where we currently are
218 // TODO: Choose the closest to the current one
219 if (supportedOrientations & Qt.PortraitOrientation) {
220 return Screen.angleBetween(orientations.native_, Qt.PortraitOrientation);
221 } else if (supportedOrientations & Qt.LandscapeOrientation) {
222 return Screen.angleBetween(orientations.native_, Qt.LandscapeOrientation);
223 } else if (supportedOrientations & Qt.InvertedPortraitOrientation) {
224 return Screen.angleBetween(orientations.native_, Qt.InvertedPortraitOrientation);
225 } else if (supportedOrientations & Qt.InvertedLandscapeOrientation) {
226 return Screen.angleBetween(orientations.native_, Qt.InvertedLandscapeOrientation);
228 // if all fails, fallback to primary orientation
229 return Screen.angleBetween(orientations.native_, orientations.primary);
234 function angleToOrientation(angle) {
237 return orientations.native_;
239 return orientations.native_ === Qt.PortraitOrientation ? Qt.InvertedLandscapeOrientation
240 : Qt.PortraitOrientation;
242 return orientations.native_ === Qt.PortraitOrientation ? Qt.InvertedPortraitOrientation
243 : Qt.InvertedLandscapeOrientation;
245 return orientations.native_ === Qt.PortraitOrientation ? Qt.LandscapeOrientation
246 : Qt.InvertedPortraitOrientation;
248 console.warn("angleToOrientation: Invalid orientation angle: " + angle);
249 return orientations.primary;
255 objectName: "rotationStates"
258 shellCover: shellCover
259 shellSnapshot: shellSnapshot
267 orientation: root.angleToOrientation(orientationAngle)
268 orientations: root.orientations
269 nativeWidth: root.width
270 nativeHeight: root.height
271 mode: applicationArguments.mode
272 hasMouse: pointerInputDevices > 0
273 hasKeyboard: keyboardsModel.count > 0
274 hasTouchscreen: touchScreensModel.count > 0
275 supportsMultiColorLed: deviceConfiguration.supportsMultiColorLed
277 // Since we dont have proper multiscreen support yet
278 // hardcode screen count to only show osk on this screen
279 // when it's the only one connected.
280 // FIXME once multiscreen has landed
281 oskEnabled: (!hasKeyboard && Screens.count === 1) ||
282 unity8Settings.alwaysShowOsk || forceOSKEnabled
285 if (unity8Settings.usageMode === "Windowed") {
288 if (deviceConfiguration.category === "phone") {
296 property real transformRotationAngle
297 property real transformOriginX
298 property real transformOriginY
300 transform: Rotation {
301 origin.x: shell.transformOriginX; origin.y: shell.transformOriginY; axis { x: 0; y: 0; z: 1 }
302 angle: shell.transformRotationAngle
320 property real transformRotationAngle
321 property real transformOriginX
322 property real transformOriginY
324 transform: Rotation {
325 origin.x: shellSnapshot.transformOriginX; origin.y: shellSnapshot.transformOriginY;
326 axis { x: 0; y: 0; z: 1 }
327 angle: shellSnapshot.transformRotationAngle