on xenial help sign in
make pinlockscreen adjust better to larger displays
37ad6e0Michael Zanetti
qml/Components/Lockscreen.qml+14−7
@@ -60,6 +60,8 @@ Showable {
60 // 0: normal background, 1: black background
60 // 0: normal background, 1: black background
61 property real darkenBackground: 0
61 property real darkenBackground: 0
62
62
63+ property color foregroundColor: "#f3f3e7"
64+
63 readonly property string passphrase: (pinPadLoader.item && pinPadLoader.item.passphrase) ? pinPadLoader.item.passphrase : ""
65 readonly property string passphrase: (pinPadLoader.item && pinPadLoader.item.passphrase) ? pinPadLoader.item.passphrase : ""
64
66
65 signal entered(string passphrase)
67 signal entered(string passphrase)
@@ -210,11 +212,16 @@ Showable {
210 property: "delayMinutes"
212 property: "delayMinutes"
211 value: root.delayMinutes
213 value: root.delayMinutes
212 }
214 }
215+ Binding {
216+ target: pinPadLoader.item
217+ property: "showCancelButton"
218+ value: root.showCancelButton
213− }
219+ }
214− Binding {
220+ Binding {
215− target: pinPadLoader.item
221+ target: pinPadLoader.item
216− property: "showCancelButton"
222+ property: "foregroundColor"
217− value: root.showCancelButton
223+ value: root.foregroundColor
224+ }
218 }
225 }
219 }
226 }
220
227
@@ -236,7 +243,7 @@ Showable {
236 anchors.horizontalCenter: parent.horizontalCenter
243 anchors.horizontalCenter: parent.horizontalCenter
237
244
238 text: callManager.hasCalls ? i18n.tr("Return to Call") : i18n.tr("Emergency Call")
245 text: callManager.hasCalls ? i18n.tr("Return to Call") : i18n.tr("Emergency Call")
239− color: "#f3f3e7"
246+ color: root.foregroundColor
240 }
247 }
241
248
242 Icon {
249 Icon {
@@ -246,7 +253,7 @@ Showable {
246 width: emergencyCallLabel.height
253 width: emergencyCallLabel.height
247 height: emergencyCallLabel.height
254 height: emergencyCallLabel.height
248 name: "call-start"
255 name: "call-start"
249− color: "#f3f3e7"
256+ color: root.foregroundColor
250 }
257 }
251
258
252 MouseArea {
259 MouseArea {
qml/Components/PassphraseLockscreen.qml+5−4
@@ -26,6 +26,7 @@ Item {
26 property string infoText
26 property string infoText
27 property string errorText
27 property string errorText
28 property bool entryEnabled: true
28 property bool entryEnabled: true
29+ property color foregroundColor: "#000000"
29
30
30 readonly property string passphrase: pinentryField.text
31 readonly property string passphrase: pinentryField.text
31
32
@@ -53,7 +54,7 @@ Item {
53 id: infoField
54 id: infoField
54 objectName: "infoTextLabel"
55 objectName: "infoTextLabel"
55 fontSize: "x-large"
56 fontSize: "x-large"
56− color: "#f3f3e7"
57+ color: root.foregroundColor
57 anchors.horizontalCenter: parent.horizontalCenter
58 anchors.horizontalCenter: parent.horizontalCenter
58 text: root.infoText
59 text: root.infoText
59 }
60 }
@@ -79,7 +80,7 @@ Item {
79 echoMode: TextInput.Password
80 echoMode: TextInput.Password
80 inputMethodHints: Qt.ImhHiddenText | Qt.ImhSensitiveData |
81 inputMethodHints: Qt.ImhHiddenText | Qt.ImhSensitiveData |
81 Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText
82 Qt.ImhNoAutoUppercase | Qt.ImhNoPredictiveText
82− color: "#f3f3e7"
83+ color: root.foregroundColor
83 cursorDelegate: Item {} // disable cursor
84 cursorDelegate: Item {} // disable cursor
84 onCursorPositionChanged: {
85 onCursorPositionChanged: {
85 // And because we don't show the cursor, always position the
86 // And because we don't show the cursor, always position the
@@ -119,7 +120,7 @@ Item {
119 Repeater {
120 Repeater {
120 model: pinentryField.length
121 model: pinentryField.length
121 delegate: Rectangle {
122 delegate: Rectangle {
122− color: "#f3f3e7"
123+ color: root.foregroundColor
123 width: dotRow.dotSize
124 width: dotRow.dotSize
124 height: width
125 height: width
125 radius: width / 2
126 radius: width / 2
@@ -131,7 +132,7 @@ Item {
131 id: wrongNoticeLabel
132 id: wrongNoticeLabel
132 objectName: "wrongNoticeLabel"
133 objectName: "wrongNoticeLabel"
133 fontSize: "large"
134 fontSize: "large"
134− color: "#f3f3e7"
135+ color: root.foregroundColor
135 anchors.horizontalCenter: parent.horizontalCenter
136 anchors.horizontalCenter: parent.horizontalCenter
136 horizontalAlignment: Text.AlignHCenter
137 horizontalAlignment: Text.AlignHCenter
137 text: root.errorText
138 text: root.errorText
qml/Components/PinLockscreen.qml+156−144
@@ -19,19 +19,16 @@ import Ubuntu.Components 0.1
19import Ubuntu.Components.ListItems 0.1
19import Ubuntu.Components.ListItems 0.1
20import "../Components"
20import "../Components"
21
21
22−Column {
22+Item {
23 id: root
23 id: root
24− y: units.gu(4)
25− spacing: units.gu(2)
26
24
27 property string infoText
25 property string infoText
28 property string retryText
26 property string retryText
29 property string errorText
27 property string errorText
30− property int padWidth: units.gu(34)
31− property int padHeight: units.gu(28)
32 property int minPinLength: -1
28 property int minPinLength: -1
33 property int maxPinLength: -1
29 property int maxPinLength: -1
34 property bool showCancelButton: true
30 property bool showCancelButton: true
31+ property color foregroundColor: "#000000"
35
32
36 readonly property string passphrase: pinentryField.text
33 readonly property string passphrase: pinentryField.text
37
34
@@ -49,180 +46,195 @@ Column {
49 }
46 }
50
47
51 Column {
48 Column {
52− id: shakeContainer
49+ anchors {
53− anchors.horizontalCenter: parent.horizontalCenter
50+ left: parent.left;
54− width: parent.width
51+ right: parent.right;
55− spacing: units.gu(1)
52+ verticalCenter: parent.verticalCenter;
56−
53+ verticalCenterOffset: Math.max(-units.gu(10), -(root.height - height) / 2) + units.gu(4)
57− Label {
58− id: infoField
59− objectName: "infoTextLabel"
60− fontSize: "large"
61− color: "#f3f3e7"
62− anchors.horizontalCenter: parent.horizontalCenter
63− text: root.infoText
64 }
54 }
55+ spacing: units.gu(2)
65
56
66− Item {
57+ Column {
67− id: pinContainer
58+ id: shakeContainer
68− anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
59+ anchors.horizontalCenter: parent.horizontalCenter
60+ width: parent.width
69− height: units.gu(4)
61+ spacing: units.gu(1)
70
62
71− Row {
63+ Label {
72− id: pinentryField
64+ id: infoField
73− objectName: "pinentryField"
65+ objectName: "infoTextLabel"
66+ fontSize: "large"
67+ color: root.foregroundColor
74 anchors.horizontalCenter: parent.horizontalCenter
68 anchors.horizontalCenter: parent.horizontalCenter
75− anchors.verticalCenter: parent.verticalCenter
69+ text: root.infoText
76− spacing: Math.max(0, Math.min(units.gu(3), (parent.width / root.maxPinLength) - units.gu(3)))
77−
78− property string text
79− property bool incorrectOverride: false
80−
81− Repeater {
82− model: pinentryField.text.length
83− delegate: Rectangle {
84− color: "#f3f3e7"
85− width: Math.min(units.gu(2), (pinContainer.width - pinContainer.height*2 ) / (root.maxPinLength >= 0 ? root.maxPinLength : 16))
86− height: width
87− radius: width / 2
88− }
89− }
70+ }
90
71
91− function appendNumber(number) {
72+ Item {
92− if (incorrectOverride) {
73+ id: pinContainer
93− incorrectOverride = false;
74+ anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
75+ height: units.gu(4)
76+
77+ Row {
78+ id: pinentryField
79+ objectName: "pinentryField"
80+ anchors.horizontalCenter: parent.horizontalCenter
81+ anchors.verticalCenter: parent.verticalCenter
82+ spacing: Math.max(0, Math.min(units.gu(3), (parent.width / root.maxPinLength) - units.gu(3)))
83+
84+ property string text
85+ property bool incorrectOverride: false
86+
87+ Repeater {
88+ model: pinentryField.text.length
89+ delegate: Rectangle {
90+ color: root.foregroundColor
91+ width: Math.min(units.gu(2), (pinContainer.width - pinContainer.height*2 ) / (root.maxPinLength >= 0 ? root.maxPinLength : 16))
92+ height: width
93+ radius: width / 2
94+ }
94 }
95 }
95
96
96− pinentryField.text = pinentryField.text + number
97+ function appendNumber(number) {
98+ if (incorrectOverride) {
99+ incorrectOverride = false;
100+ }
97
101
102+ pinentryField.text = pinentryField.text + number
103+
98− if (root.minPinLength > 0 && root.maxPinLength > 0
104+ if (root.minPinLength > 0 && root.maxPinLength > 0
99− && root.minPinLength == root.maxPinLength && pinentryField.text.length == root.minPinLength) {
105+ && root.minPinLength == root.maxPinLength && pinentryField.text.length == root.minPinLength) {
100− root.entered(pinentryField.text)
106+ root.entered(pinentryField.text)
107+ }
101 }
108 }
102− }
103
109
104− function backspace() {
110+ function backspace() {
105− pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1)
111+ pinentryField.text = pinentryField.text.substring(0, pinentryField.text.length-1)
112+ }
113+ }
114+ Label {
115+ id: wrongNoticeLabel
116+ objectName: "wrongNoticeLabel"
117+ fontSize: "x-large"
118+ color: root.foregroundColor
119+ anchors.horizontalCenter: parent.horizontalCenter
120+ horizontalAlignment: Text.AlignHCenter
121+ text: root.errorText
122+ visible: pinentryField.incorrectOverride
123+ scale: Math.min(1, parent.width / width)
106 }
124 }
107− }
108− Label {
109− id: wrongNoticeLabel
110− objectName: "wrongNoticeLabel"
111− fontSize: "x-large"
112− color: "#f3f3e7"
113− anchors.horizontalCenter: parent.horizontalCenter
114− horizontalAlignment: Text.AlignHCenter
115− text: root.errorText
116− visible: pinentryField.incorrectOverride
117− scale: Math.min(1, parent.width / width)
118− }
119
125
120− AbstractButton {
126+ AbstractButton {
121− objectName: "backspaceIcon"
127+ objectName: "backspaceIcon"
122− anchors { right: parent.right; top: parent.top; bottom: parent.bottom }
128+ anchors { right: parent.right; top: parent.top; bottom: parent.bottom }
123− width: height
129+ width: height
124− enabled: root.entryEnabled
130+ enabled: root.entryEnabled
125
131
126− Icon {
132+ Icon {
127− anchors.fill: parent
133+ anchors.fill: parent
128− name: "erase"
134+ name: "erase"
129− color: "#f3f3e7"
135+ color: root.foregroundColor
130− }
136+ }
131
137
132− opacity: (pinentryField.text.length > 0 && !pinentryField.incorrectOverride) ? 1 : 0
138+ opacity: (pinentryField.text.length > 0 && !pinentryField.incorrectOverride) ? 1 : 0
133
139
134− Behavior on opacity {
140+ Behavior on opacity {
135− UbuntuNumberAnimation {}
141+ UbuntuNumberAnimation {}
142+ }
143+
144+ onClicked: pinentryField.backspace()
136 }
145 }
146+ }
137
147
138− onClicked: pinentryField.backspace()
148+ Label {
149+ objectName: "retryLabel"
150+ fontSize: "x-small"
151+ color: root.foregroundColor
152+ anchors.horizontalCenter: parent.horizontalCenter
153+ text: root.retryText || " "
139 }
154 }
140 }
155 }
141
156
142− Label {
157+ ThinDivider {
143− objectName: "retryLabel"
158+ anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
144− fontSize: "x-small"
145− color: "#f3f3e7"
146− anchors.horizontalCenter: parent.horizontalCenter
147− text: root.retryText || " "
148 }
159 }
149− }
150−
151− ThinDivider {
152− anchors { left: parent.left; right: parent.right; margins: units.gu(2) }
153− }
154−
155− Grid {
156− id: numbersGrid
157− anchors { horizontalCenter: parent.horizontalCenter }
158− columns: 3
159−
160− property int buttonHeight: units.gu(8)
161− property int buttonWidth: units.gu(12)
162−
163− Repeater {
164− model: 9
165
160
161+ Grid {
162+ id: numbersGrid
163+ objectName: "numbersGrid"
164+ anchors { horizontalCenter: parent.horizontalCenter }
165+ columns: 3
166+
167+ property int maxWidth: Math.min(units.gu(50), root.width - units.gu(8))
168+ property int buttonWidth: maxWidth / 3
169+ property int buttonHeight: buttonWidth * 2 / 3
170+
171+ Repeater {
172+ model: 9
173+
174+ PinPadButton {
175+ objectName: "pinPadButton" + text
176+ text: index + 1
177+ height: numbersGrid.buttonHeight
178+ width: numbersGrid.buttonWidth
179+ foregroundColor: root.foregroundColor
180+ enabled: root.entryEnabled && (root.maxPinLength == -1 ||
181+ pinentryField.text.length < root.maxPinLength ||
182+ pinentryField.incorrectOverride)
183+
184+ onClicked: {
185+ pinentryField.appendNumber(index + 1)
186+ }
187+ }
188+ }
189+ Item {
190+ height: numbersGrid.buttonHeight
191+ width: numbersGrid.buttonWidth
192+ }
166 PinPadButton {
193 PinPadButton {
167− objectName: "pinPadButton" + text
194+ text: "0"
168− text: index + 1
169 height: numbersGrid.buttonHeight
195 height: numbersGrid.buttonHeight
170 width: numbersGrid.buttonWidth
196 width: numbersGrid.buttonWidth
197+ foregroundColor: root.foregroundColor
171 enabled: root.entryEnabled && (root.maxPinLength == -1 ||
198 enabled: root.entryEnabled && (root.maxPinLength == -1 ||
172 pinentryField.text.length < root.maxPinLength ||
199 pinentryField.text.length < root.maxPinLength ||
173 pinentryField.incorrectOverride)
200 pinentryField.incorrectOverride)
174
201
175 onClicked: {
202 onClicked: {
176− pinentryField.appendNumber(index + 1)
203+ pinentryField.appendNumber(0)
177 }
204 }
178 }
205 }
179− }
180− Item {
206+ Item {
181− height: numbersGrid.buttonHeight
182− width: numbersGrid.buttonWidth
183− }
184− PinPadButton {
185− text: "0"
186− height: numbersGrid.buttonHeight
207+ height: numbersGrid.buttonHeight
187− width: numbersGrid.buttonWidth
208+ width: numbersGrid.buttonWidth
188− enabled: root.entryEnabled && (root.maxPinLength == -1 ||
189− pinentryField.text.length < root.maxPinLength ||
190− pinentryField.incorrectOverride)
191−
192− onClicked: {
193− pinentryField.appendNumber(0)
194 }
209 }
195− }
196− Item {
197− height: numbersGrid.buttonHeight
198− width: numbersGrid.buttonWidth
199− }
200− PinPadButton {
210+ PinPadButton {
201− iconName: "close"
211+ iconName: "close"
202− height: units.gu(5) // visual spec has this row a little closer in
212+ height: units.gu(5) // visual spec has this row a little closer in
213+ width: numbersGrid.buttonWidth
214+ foregroundColor: root.foregroundColor
215+ onClicked: root.cancel()
216+ visible: root.showCancelButton
217+ }
218+ Item {
219+ height: units.gu(5)
203− width: numbersGrid.buttonWidth
220+ width: numbersGrid.buttonWidth
221+ }
222+ PinPadButton {
223+ iconName: "tick"
224+ objectName: "confirmButton"
225+ height: units.gu(5)
226+ width: numbersGrid.buttonWidth
227+ foregroundColor: root.foregroundColor
228+ enabled: root.enabled && pinentryField.text.length >= root.minPinLength
229+ visible: root.minPinLength == -1 || root.minPinLength !== root.maxPinLength
204
230
205− onClicked: root.cancel()
231+ onClicked: root.entered(pinentryField.text)
206− visible: root.showCancelButton
207− }
232+ }
208− Item {
209− height: units.gu(5)
210− width: numbersGrid.buttonWidth
211 }
233 }
212− PinPadButton {
234+ WrongPasswordAnimation {
213− iconName: "tick"
235+ id: wrongPasswordAnimation
214− objectName: "confirmButton"
236+ objectName: "wrongPasswordAnimation"
215− height: units.gu(5)
237+ target: shakeContainer
216− width: numbersGrid.buttonWidth
217− enabled: root.enabled && pinentryField.text.length >= root.minPinLength
218− visible: root.minPinLength == -1 || root.minPinLength !== root.maxPinLength
219−
220− onClicked: root.entered(pinentryField.text)
221 }
238 }
222 }
239 }
223− WrongPasswordAnimation {
224− id: wrongPasswordAnimation
225− objectName: "wrongPasswordAnimation"
226− target: shakeContainer
227− }
228}
240}
qml/Components/PinPadButton.qml+3−2
@@ -23,6 +23,7 @@ AbstractButton {
23
23
24 property alias text: label.text
24 property alias text: label.text
25 property string iconName
25 property string iconName
26+ property color foregroundColor: "#000000"
26
27
27 UbuntuShape {
28 UbuntuShape {
28 anchors.fill: parent
29 anchors.fill: parent
@@ -36,7 +37,7 @@ AbstractButton {
36 id: label
37 id: label
37 anchors.centerIn: parent
38 anchors.centerIn: parent
38 horizontalAlignment: Text.AlignHCenter
39 horizontalAlignment: Text.AlignHCenter
39− color: "#f3f3e7"
40+ color: root.foregroundColor
40 fontSize: "x-large"
41 fontSize: "x-large"
41 font.weight: Font.DemiBold
42 font.weight: Font.DemiBold
42 visible: text.length > 0
43 visible: text.length > 0
@@ -52,7 +53,7 @@ AbstractButton {
52 width: height
53 width: height
53 anchors.centerIn: parent
54 anchors.centerIn: parent
54 name: root.iconName
55 name: root.iconName
55− color: "#f3f3e7"
56+ color: root.foregroundColor
56 visible: name.length > 0
57 visible: name.length > 0
57 scale: root.pressed ? 0.9 : 1
58 scale: root.pressed ? 0.9 : 1
58 Behavior on scale {
59 Behavior on scale {
tests/qmltests/Components/tst_Lockscreen.qml+26
@@ -173,6 +173,10 @@ Rectangle {
173 function cleanup() {
173 function cleanup() {
174 lockscreen.clear(false);
174 lockscreen.clear(false);
175 delayMinutesTextField.text = "0"
175 delayMinutesTextField.text = "0"
176+
177+ // Reset sizing
178+ root.width = units.gu(80)
179+ root.height = units.gu(76)
176 }
180 }
177
181
178 function waitForLockscreenReady() {
182 function waitForLockscreenReady() {
@@ -450,6 +454,28 @@ Rectangle {
450 var label = findChild(lockscreen, "deviceLockedLabel")
454 var label = findChild(lockscreen, "deviceLockedLabel")
451 compare(label.text, "Device Locked")
455 compare(label.text, "Device Locked")
452 }
456 }
457+
458+ function test_resize_data() {
459+ return [
460+ { tag: "small", width: units.gu(40), height: units.gu(76) },
461+ { tag: "medium", width: units.gu(50), height: units.gu(86) },
462+ { tag: "large", width: units.gu(60), height: units.gu(96) },
463+ { tag: "x-large", width: units.gu(80), height: units.gu(116) },
464+ ]
465+ }
466+
467+ function test_resize(data) {
468+ var controlsAreaWidth = lockscreen.anchors.rightMargin;
469+ root.width = data.width + controlsAreaWidth;
470+ root.height = data.height;
471+ waitForRendering(root);
472+
473+ var numbersGrid = findChild(lockscreen, "numbersGrid");
474+ // Make sure the numbers pad keeps a 4gu margin on left/right but doesn't grow larger than 50 gu's width.
475+ // For rounding reasons it might be off 1 pixel. Let's make sure it's within +/- 1 pixel of what we expect
476+ verify(numbersGrid.width >= Math.min(units.gu(50), data.width - units.gu(8)) - 1);
477+ verify(numbersGrid.width <= Math.min(units.gu(50), data.width - units.gu(8)) + 1);
478+ }
453 }
479 }
454
480
455 SignalSpy {
481 SignalSpy {