Changeset View
Standalone View
lookandfeel/contents/lockscreen/LockScreenUi.qml
Show First 20 Lines • Show All 62 Lines • ▼ Show 20 Line(s) | 30 | PlasmaCore.ColorScope { | |||
---|---|---|---|---|---|
63 | 63 | | |||
64 | Loader { | 64 | Loader { | ||
65 | id: changeSessionComponent | 65 | id: changeSessionComponent | ||
66 | active: false | 66 | active: false | ||
67 | source: "ChangeSession.qml" | 67 | source: "ChangeSession.qml" | ||
68 | visible: false | 68 | visible: false | ||
69 | } | 69 | } | ||
70 | 70 | | |||
71 | Item { | 71 | Item { | ||
graesslin: Why the change to MouseArea? | |||||
mart: to dismiss the keyboard by clicking anywhere in an empty area | |||||
72 | id: lockScreenRoot | 72 | id: lockScreenRoot | ||
73 | 73 | | |||
74 | x: parent.x | 74 | x: parent.x | ||
75 | y: parent.y | 75 | y: parent.y | ||
76 | width: parent.width | 76 | width: parent.width | ||
77 | height: parent.height | 77 | height: parent.height | ||
78 | 78 | | |||
79 | Component.onCompleted: PropertyAnimation { id: launchAnimation; target: lockScreenRoot; property: "opacity"; from: 0; to: 1; duration: 1000 } | 79 | Component.onCompleted: PropertyAnimation { id: launchAnimation; target: lockScreenRoot; property: "opacity"; from: 0; to: 1; duration: 1000 } | ||
80 | 80 | | |||
81 | states: [ | 81 | states: [ | ||
This is not related to the described change. Do we really want to close when clicking outside the keyboard? That could be rather annoying? Anyway I think it should not be bundled with a change saying it's about animations graesslin: This is not related to the described change. Do we really want to close when clicking outside… | |||||
that's how on screen keyboards usually work on pretty much any device. mart: that's how on screen keyboards usually work on pretty much any device.
removed from this, will… | |||||
Fair enough, but then it should be a Touch enabled field and not a MouseArea? graesslin: > that's how on screen keyboards usually work on pretty much any device.
Fair enough, but then… | |||||
mart: good point | |||||
82 | State { | 82 | State { | ||
83 | name: "onOtherSession" | 83 | name: "onOtherSession" | ||
84 | // for slide out animation | 84 | // for slide out animation | ||
85 | PropertyChanges { target: lockScreenRoot; y: lockScreenRoot.height } | 85 | PropertyChanges { target: lockScreenRoot; y: lockScreenRoot.height } | ||
86 | // we also change the opacity just to be sure it's not visible even on unexpected screen dimension changes with possible race conditions | 86 | // we also change the opacity just to be sure it's not visible even on unexpected screen dimension changes with possible race conditions | ||
87 | PropertyChanges { target: lockScreenRoot; opacity: 0 } | 87 | PropertyChanges { target: lockScreenRoot; opacity: 0 } | ||
88 | } | 88 | } | ||
89 | ] | 89 | ] | ||
Show All 12 Lines | 101 | onRunningChanged: { | |||
102 | // after the animation has finished switch session: since we only animate the transition TO state "onOtherSession" | 102 | // after the animation has finished switch session: since we only animate the transition TO state "onOtherSession" | ||
103 | // and not the other way around, we don't have to check the state we transitioned into | 103 | // and not the other way around, we don't have to check the state we transitioned into | ||
104 | if (/* lockScreenRoot.state == "onOtherSession" && */ !running) { | 104 | if (/* lockScreenRoot.state == "onOtherSession" && */ !running) { | ||
105 | mainStack.currentItem.switchSession() | 105 | mainStack.currentItem.switchSession() | ||
106 | } | 106 | } | ||
107 | } | 107 | } | ||
108 | } | 108 | } | ||
109 | 109 | | |||
110 | ColumnLayout { | | |||
111 | anchors.top: parent.top | | |||
112 | anchors.bottom: parent.verticalCenter | | |||
113 | anchors.horizontalCenter: parent.horizontalCenter | | |||
114 | Clock { | 110 | Clock { | ||
111 | id: clock | ||||
Could you please rebase this to the changes introduces with 097db85e297aba8b4b3f0ddabcddf8a03b5482c0 graesslin: Could you please rebase this to the changes introduces with… | |||||
i see that commit puts the clock in a column layout together with just an empty item.. why? looks like some easy cleanup can be done there in adapting to that diff, now hiding the user icon when it goes over the clock, but i think the clock sliding away was actually more correct ui-wise mart: i see that commit puts the clock in a column layout together with just an empty item.. why? | |||||
purely ui-wise, i think the correct behavior of the clock (for a future review) should be:
mart: purely ui-wise, i think the correct behavior of the clock (for a future review) should be:
*… | |||||
yeah hiding the clock if it overlaps with the user icon would be a good thing. I didn't see an easy way for it, but well me and QML ;-) graesslin: yeah hiding the clock if it overlaps with the user icon would be a good thing. I didn't see an… | |||||
this way seems to behave as intended, i tried to resize the lockscreen test window to various sizes that may be challenging and seems to behave quite well mart: this way seems to behave as intended, i tried to resize the lockscreen test window to various… | |||||
112 | anchors.horizontalCenter: parent.horizontalCenter | ||||
113 | y: (mainBlock.userList.y + mainStack.y)/2 - height/2 | ||||
114 | visible: y > 0 | ||||
115 | Layout.alignment: Qt.AlignBaseline | 115 | Layout.alignment: Qt.AlignBaseline | ||
116 | } | 116 | } | ||
117 | Item { | | |||
118 | Layout.maximumHeight: units.gridUnit * 13 | | |||
119 | Layout.fillHeight: true | | |||
120 | } | | |||
121 | } | | |||
122 | 117 | | |||
123 | ListModel { | 118 | ListModel { | ||
124 | id: users | 119 | id: users | ||
125 | 120 | | |||
126 | Component.onCompleted: { | 121 | Component.onCompleted: { | ||
127 | users.append({name: kscreenlocker_userName, | 122 | users.append({name: kscreenlocker_userName, | ||
128 | realName: kscreenlocker_userName, | 123 | realName: kscreenlocker_userName, | ||
129 | icon: kscreenlocker_userImage, | 124 | icon: kscreenlocker_userImage, | ||
130 | 125 | | |||
131 | }) | 126 | }) | ||
132 | } | 127 | } | ||
133 | } | 128 | } | ||
134 | 129 | | |||
135 | ColumnLayout { | 130 | | ||
136 | anchors.fill: parent | | |||
137 | StackView { | 131 | StackView { | ||
138 | id: mainStack | 132 | id: mainStack | ||
139 | Layout.fillWidth: true | 133 | anchors { | ||
140 | Layout.fillHeight: true | 134 | left: parent.left | ||
135 | right: parent.right | ||||
136 | } | ||||
137 | height: lockScreenRoot.height | ||||
141 | focus: true //StackView is an implicit focus scope, so we need to give this focus so the item inside will have it | 138 | focus: true //StackView is an implicit focus scope, so we need to give this focus so the item inside will have it | ||
142 | 139 | | |||
143 | initialItem: MainBlock { | 140 | initialItem: MainBlock { | ||
144 | id: mainBlock | 141 | id: mainBlock | ||
145 | 142 | | |||
143 | showUserList: userList.y + mainStack.y > 0 | ||||
144 | | ||||
146 | Stack.onStatusChanged: { | 145 | Stack.onStatusChanged: { | ||
147 | // prepare for presenting again to the user | 146 | // prepare for presenting again to the user | ||
148 | if (Stack.status == Stack.Activating) { | 147 | if (Stack.status == Stack.Activating) { | ||
149 | mainPasswordBox.remove(0, mainPasswordBox.length) | 148 | mainPasswordBox.remove(0, mainPasswordBox.length) | ||
150 | mainPasswordBox.focus = true | 149 | mainPasswordBox.focus = true | ||
151 | } | 150 | } | ||
152 | } | 151 | } | ||
153 | userListModel: users | 152 | userListModel: users | ||
Show All 27 Lines | |||||
181 | Loader { | 180 | Loader { | ||
182 | Layout.fillWidth: true | 181 | Layout.fillWidth: true | ||
183 | Layout.preferredHeight: item ? item.implicitHeight : 0 | 182 | Layout.preferredHeight: item ? item.implicitHeight : 0 | ||
184 | active: true // TODO configurable | 183 | active: true // TODO configurable | ||
185 | source: "MediaControls.qml" | 184 | source: "MediaControls.qml" | ||
186 | } | 185 | } | ||
187 | } | 186 | } | ||
188 | } | 187 | } | ||
188 | | ||||
189 | Loader { | 189 | Loader { | ||
190 | id: inputPanel | 190 | id: inputPanel | ||
191 | property bool keyboardActive: item ? item.active : false | 191 | state: "hidden" | ||
192 | Layout.fillWidth: true | 192 | readonly property bool keyboardActive: item ? item.active : false | ||
193 | Layout.preferredHeight: item ? (item.active ? item.implicitHeight : 0) : 0 | 193 | anchors { | ||
194 | left: parent.left | ||||
195 | right: parent.right | ||||
196 | } | ||||
194 | function showHide() { | 197 | function showHide() { | ||
195 | if (Qt.inputMethod.visible) { | 198 | state = state == "hidden" ? "visible" : "hidden"; | ||
196 | Qt.inputMethod.hide(); | 199 | } | ||
197 | } else { | 200 | Component.onCompleted: inputPanel.source = "VirtualKeyboard.qml" | ||
198 | item.activated = true; | 201 | | ||
202 | states: [ | ||||
203 | State { | ||||
204 | name: "visible" | ||||
205 | PropertyChanges { | ||||
206 | target: mainStack | ||||
207 | y: Math.min(0, lockScreenRoot.height - inputPanel.height - mainBlock.visibleBoundary) | ||||
208 | } | ||||
209 | PropertyChanges { | ||||
210 | target: inputPanel | ||||
211 | y: lockScreenRoot.height - inputPanel.height | ||||
212 | opacity: 1 | ||||
213 | } | ||||
214 | }, | ||||
215 | State { | ||||
216 | name: "hidden" | ||||
217 | PropertyChanges { | ||||
218 | target: mainStack | ||||
219 | y: 0 | ||||
220 | } | ||||
221 | PropertyChanges { | ||||
222 | target: inputPanel | ||||
223 | y: lockScreenRoot.height - lockScreenRoot.height/4 | ||||
I'm especially afraid of reintroducing units here with a fixed multiplier. That was exactly the thing causing problems with scaling and the clock. graesslin: I'm especially afraid of reintroducing units here with a fixed multiplier. That was exactly the… | |||||
this is not really a functional position: mart: this is not really a functional position:
this is when the keyboard is hidden and its opacity… | |||||
224 | opacity: 0 | ||||
225 | } | ||||
226 | } | ||||
227 | ] | ||||
228 | transitions: [ | ||||
229 | Transition { | ||||
230 | from: "hidden" | ||||
231 | to: "visible" | ||||
232 | SequentialAnimation { | ||||
233 | ScriptAction { | ||||
234 | script: { | ||||
235 | inputPanel.item.activated = true; | ||||
199 | Qt.inputMethod.show(); | 236 | Qt.inputMethod.show(); | ||
200 | } | 237 | } | ||
201 | } | 238 | } | ||
202 | Component.onCompleted: inputPanel.source = "../components/VirtualKeyboard.qml" | 239 | ParallelAnimation { | ||
240 | NumberAnimation { | ||||
241 | target: mainStack | ||||
242 | property: "y" | ||||
243 | duration: units.longDuration | ||||
244 | easing.type: Easing.InOutQuad | ||||
245 | } | ||||
246 | NumberAnimation { | ||||
247 | target: inputPanel | ||||
248 | property: "y" | ||||
249 | duration: units.longDuration | ||||
250 | easing.type: Easing.OutQuad | ||||
251 | } | ||||
252 | OpacityAnimator { | ||||
253 | target: inputPanel | ||||
254 | duration: units.longDuration | ||||
255 | easing.type: Easing.OutQuad | ||||
256 | } | ||||
257 | } | ||||
258 | } | ||||
259 | }, | ||||
260 | Transition { | ||||
261 | from: "visible" | ||||
262 | to: "hidden" | ||||
263 | SequentialAnimation { | ||||
264 | ParallelAnimation { | ||||
265 | NumberAnimation { | ||||
266 | target: mainStack | ||||
267 | property: "y" | ||||
268 | duration: units.longDuration | ||||
269 | easing.type: Easing.InOutQuad | ||||
270 | } | ||||
271 | NumberAnimation { | ||||
272 | target: inputPanel | ||||
273 | property: "y" | ||||
274 | duration: units.longDuration | ||||
275 | easing.type: Easing.InQuad | ||||
276 | } | ||||
277 | OpacityAnimator { | ||||
278 | target: inputPanel | ||||
279 | duration: units.longDuration | ||||
280 | easing.type: Easing.InQuad | ||||
281 | } | ||||
282 | } | ||||
283 | ScriptAction { | ||||
284 | script: { | ||||
285 | Qt.inputMethod.hide(); | ||||
203 | } | 286 | } | ||
note that the previous code did not set the active to false. The idea was that once you activated the virtual keyboard, clicking/touching into the password field also activates if. For that the inputPanel needs to be active. In summary: if you thought I just had forgotten to set it to false, nope, it was intended ;-) graesslin: note that the previous code did not set the active to false. The idea was that once you… | |||||
204 | } | 287 | } | ||
288 | } | ||||
289 | } | ||||
290 | ] | ||||
291 | } | ||||
205 | 292 | | |||
206 | Component { | 293 | Component { | ||
207 | id: switchSessionPage | 294 | id: switchSessionPage | ||
208 | SessionManagementScreen { | 295 | SessionManagementScreen { | ||
209 | property var switchSession: finalSwitchSession | 296 | property var switchSession: finalSwitchSession | ||
210 | 297 | | |||
211 | Stack.onStatusChanged: { | 298 | Stack.onStatusChanged: { | ||
212 | if (Stack.status == Stack.Activating) { | 299 | if (Stack.status == Stack.Activating) { | ||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Line(s) | 352 | anchors { | |||
268 | right: parent.right | 355 | right: parent.right | ||
269 | margins: units.smallSpacing | 356 | margins: units.smallSpacing | ||
270 | } | 357 | } | ||
271 | 358 | | |||
272 | PlasmaComponents.ToolButton { | 359 | PlasmaComponents.ToolButton { | ||
273 | text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Button to show/hide virtual keyboard", "Virtual Keyboard") | 360 | text: i18ndc("plasma_lookandfeel_org.kde.lookandfeel", "Button to show/hide virtual keyboard", "Virtual Keyboard") | ||
274 | iconName: inputPanel.keyboardActive ? "input-keyboard-virtual-on" : "input-keyboard-virtual-off" | 361 | iconName: inputPanel.keyboardActive ? "input-keyboard-virtual-on" : "input-keyboard-virtual-off" | ||
275 | onClicked: inputPanel.showHide() | 362 | onClicked: inputPanel.showHide() | ||
363 | | ||||
276 | visible: inputPanel.status == Loader.Ready | 364 | visible: inputPanel.status == Loader.Ready | ||
277 | } | 365 | } | ||
278 | 366 | | |||
279 | KeyboardLayoutButton { | 367 | KeyboardLayoutButton { | ||
280 | } | 368 | } | ||
281 | 369 | | |||
282 | Item { | 370 | Item { | ||
283 | Layout.fillWidth: true | 371 | Layout.fillWidth: true | ||
Show All 14 Lines |
Why the change to MouseArea?