on xenial help sign in
Merge
2d33181Albert Astals Cid
CMakeLists.txt+10
@@ -128,6 +128,16 @@ if(NOT QUIET_LOGGER)
128 set(STDOUT_LOGGER "-o" "-,txt")
128 set(STDOUT_LOGGER "-o" "-,txt")
129endif()
129endif()
130
130
131+execute_process(COMMAND arch OUTPUT_VARIABLE ARCH)
132+if (NOT ARCH MATCHES "arm*")
133+ set(ENABLE_TOUCH_EMULATION true)
134+ add_definitions(-DUNITY8_ENABLE_TOUCH_EMULATION)
135+ pkg_check_modules(MOUSETOUCHADAPTOR_LIBS REQUIRED x11 xcb xi)
136+else()
137+ set(ENABLE_TOUCH_EMULATION false)
138+ message(STATUS "Touch emulation support disabled.")
139+endif()
140+
131# add subdirectories to build
141# add subdirectories to build
132add_subdirectory(include)
142add_subdirectory(include)
133add_subdirectory(src)
143add_subdirectory(src)
debian/changelog+51
@@ -1,3 +1,54 @@
1+unity8 (8.11+16.04.20160111.1-0ubuntu1) xenial; urgency=medium
2+
3+ [ Albert Astals Cid ]
4+ * Clear fake item icon name as soon as it goes invisible (LP:
5+ #1531172)
6+ * Fix LVWPH test failing on Xenial (Qt 5.5)
7+ * Fix dragging so that test passes on Xenial
8+ * Fix focus on the dash page header text field with new SDK (LP:
9+ #1528178)
10+ * Make the card creator test pass again
11+ * Quit the dash communicator thread before destroying it (LP:
12+ #1508485)
13+ * Remove duplicated override_dh_auto_clean
14+ * SDK changed the name they give to the buttons, follow
15+
16+ [ Andrea Cimitan ]
17+ * Fix a broken binding
18+
19+ [ CI Train Bot ]
20+ * Resync trunk.
21+ * Update translation template
22+
23+ [ Daniel d'Andrada ]
24+ * Have "make tryFoo" work with Qt 5.5
25+ * Make DragHandle tests run again.
26+
27+ [ Lukáš Tinkl ]
28+ * Fix dismissing the launcher when clicking/tapping outside (LP:
29+ #1531339, #1530940)
30+ * Fix panel drop shadow and click-to-focus of maximized apps (LP:
31+ #1531854)
32+ * Fix wifi access point indicator items signal strength icon on
33+ desktop
34+
35+ [ Michael Terry ]
36+ * Guard against a couple odd timing scenarios for the too-many-failed-
37+ login-attempts lockout screen.
38+ * Skip the wizard's password screens if there is already a password
39+ set by other means. (LP: #1531268)
40+ * Stop the emergency dialer from accidentally exposing the mtp
41+ service. (LP: #1525981)
42+
43+ [ Michael Zanetti ]
44+ * Make sure the triangle of the quicklist is in bounds (LP: #1531340)
45+
46+ [ Pawel Stolowski ]
47+ * Changes 'shareData' and 'contentType' attributes to 'share-data' and
48+ 'content-type', to match existing naming schema.
49+
50+ -- Michał Sawicz <michal.sawicz@canonical.com> Mon, 11 Jan 2016 17:38:49 +0000
51+
1unity8 (8.11+16.04.20160107-0ubuntu1) xenial; urgency=medium
52unity8 (8.11+16.04.20160107-0ubuntu1) xenial; urgency=medium
2
53
3 [ Albert Astals Cid ]
54 [ Albert Astals Cid ]
debian/control+5−1
@@ -32,7 +32,11 @@ Build-Depends: cmake,
32 libudev-dev,
32 libudev-dev,
33 libunity-api-dev (>= 7.105),
33 libunity-api-dev (>= 7.105),
34 libusermetricsoutput1-dev,
34 libusermetricsoutput1-dev,
35+# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
36+ libx11-dev[!armhf],
35− libxcb1-dev,
37+ libxcb1-dev[!armhf],
38+ libxi-dev[!armhf],
39+# End of X11 libs
36 pkg-config,
40 pkg-config,
37 python3-all:any,
41 python3-all:any,
38 python3-setuptools,
42 python3-setuptools,
debian/rules−4
@@ -11,10 +11,6 @@ export NO_PNG_PKG_MANGLE=1
11%:
11%:
12 dh $@ --parallel --fail-missing --with python3
12 dh $@ --parallel --fail-missing --with python3
13
13
14−override_dh_auto_clean:
15− dh_auto_clean
16− rm -rf builddir
17−
18override_dh_auto_configure:
14override_dh_auto_configure:
19 # Debian defines CMAKE_INSTALL_LOCALSTATEDIR as /usr/var, which is wrong.
15 # Debian defines CMAKE_INSTALL_LOCALSTATEDIR as /usr/var, which is wrong.
20 # So until Debian bug 719148 is fixed, do it ourselves.
16 # So until Debian bug 719148 is fixed, do it ourselves.
plugins/Dash/listviewwithpageheader.cpp+5−1
@@ -1177,7 +1177,7 @@ void ListViewWithPageHeader::headerHeightChanged(qreal newHeaderHeight, qreal ol
1177
1177
1178void ListViewWithPageHeader::adjustMinYExtent()
1178void ListViewWithPageHeader::adjustMinYExtent()
1179{
1179{
1180− if (m_visibleItems.isEmpty()) {
1180+ if (m_visibleItems.isEmpty() || contentHeight() < height()) {
1181 m_minYExtent = 0;
1181 m_minYExtent = 0;
1182 } else {
1182 } else {
1183 qreal nonCreatedHeight = 0;
1183 qreal nonCreatedHeight = 0;
@@ -1359,6 +1359,10 @@ void ListViewWithPageHeader::updatePolish()
1359
1359
1360 m_contentHeightDirty = false;
1360 m_contentHeightDirty = false;
1361 adjustMinYExtent();
1361 adjustMinYExtent();
1362+ if (contentHeight < height()) {
1363+ // need this since in the previous call to adjustMinYExtent contentHeight is not set yet
1364+ m_minYExtent = 0;
1365+ }
1362 m_inContentHeightKeepHeaderShown = m_headerItem && m_headerItem->y() == contentY();
1366 m_inContentHeightKeepHeaderShown = m_headerItem && m_headerItem->y() == contentY();
1363 setContentHeight(contentHeight);
1367 setContentHeight(contentHeight);
1364 m_inContentHeightKeepHeaderShown = false;
1368 m_inContentHeightKeepHeaderShown = false;
plugins/Unity/DashCommunicator/dashcommunicator.cpp+6
@@ -27,6 +27,12 @@ DashCommunicator::DashCommunicator(QObject *parent):
27 start();
27 start();
28}
28}
29
29
30+DashCommunicator::~DashCommunicator()
31+{
32+ quit();
33+ wait();
34+}
35+
30void DashCommunicator::setCurrentScope(int index, bool animate, bool isSwipe)
36void DashCommunicator::setCurrentScope(int index, bool animate, bool isSwipe)
31{
37{
32 m_mutex.lock();
38 m_mutex.lock();
plugins/Unity/DashCommunicator/dashcommunicator.h+1−1
@@ -28,7 +28,7 @@ class DashCommunicator: public QThread
28 Q_OBJECT
28 Q_OBJECT
29public:
29public:
30 explicit DashCommunicator(QObject *parent = 0);
30 explicit DashCommunicator(QObject *parent = 0);
31− ~DashCommunicator() = default;
31+ ~DashCommunicator();
32
32
33public Q_SLOTS:
33public Q_SLOTS:
34 void setCurrentScope(int index, bool animate, bool isSwipe);
34 void setCurrentScope(int index, bool animate, bool isSwipe);
po/unity8.pot+27−27
@@ -8,7 +8,7 @@ msgid ""
8msgstr ""
8msgstr ""
9"Project-Id-Version: unity8\n"
9"Project-Id-Version: unity8\n"
10"Report-Msgid-Bugs-To: \n"
10"Report-Msgid-Bugs-To: \n"
11−"POT-Creation-Date: 2016-01-07 08:09+0000\n"
11+"POT-Creation-Date: 2016-01-11 17:43+0000\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
14"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -171,26 +171,26 @@ msgstr ""
171msgid "Close all"
171msgid "Close all"
172msgstr ""
172msgstr ""
173
173
174−#: qml/Dash/DashPageHeader.qml:265
174+#: qml/Dash/DashPageHeader.qml:266
175msgctxt "Button: Open the Ubuntu Store"
175msgctxt "Button: Open the Ubuntu Store"
176msgid "Store"
176msgid "Store"
177msgstr ""
177msgstr ""
178
178
179−#: qml/Dash/DashPageHeader.qml:272
179+#: qml/Dash/DashPageHeader.qml:273
180msgctxt "Button: Start a search in the current dash scope"
180msgctxt "Button: Start a search in the current dash scope"
181msgid "Search"
181msgid "Search"
182msgstr ""
182msgstr ""
183
183
184−#: qml/Dash/DashPageHeader.qml:282
184+#: qml/Dash/DashPageHeader.qml:283
185msgctxt "Button: Show the current dash scope settings"
185msgctxt "Button: Show the current dash scope settings"
186msgid "Settings"
186msgid "Settings"
187msgstr ""
187msgstr ""
188
188
189−#: qml/Dash/DashPageHeader.qml:289
189+#: qml/Dash/DashPageHeader.qml:290
190msgid "Remove from Favorites"
190msgid "Remove from Favorites"
191msgstr ""
191msgstr ""
192
192
193−#: qml/Dash/DashPageHeader.qml:289
193+#: qml/Dash/DashPageHeader.qml:290
194msgid "Add to Favorites"
194msgid "Add to Favorites"
195msgstr ""
195msgstr ""
196
196
@@ -228,7 +228,7 @@ msgstr ""
228msgid "Add a review"
228msgid "Add a review"
229msgstr ""
229msgstr ""
230
230
231−#: qml/Dash/Previews/PreviewSharing.qml:51
231+#: qml/Dash/Previews/PreviewSharing.qml:50
232msgid "Preview Share Item"
232msgid "Preview Share Item"
233msgstr ""
233msgstr ""
234
234
@@ -339,62 +339,62 @@ msgstr ""
339msgid "Conference"
339msgid "Conference"
340msgstr ""
340msgstr ""
341
341
342−#: qml/Panel/Indicators/MenuItemFactory.qml:743
342+#: qml/Panel/Indicators/MenuItemFactory.qml:753
343msgid "Nothing is playing"
343msgid "Nothing is playing"
344msgstr ""
344msgstr ""
345
345
346−#: qml/Panel/Indicators/MenuItemFactory.qml:872
346+#: qml/Panel/Indicators/MenuItemFactory.qml:882
347#, qt-format
347#, qt-format
348msgid "%1 hour"
348msgid "%1 hour"
349msgid_plural "%1 hours"
349msgid_plural "%1 hours"
350msgstr[0] ""
350msgstr[0] ""
351msgstr[1] ""
351msgstr[1] ""
352
352
353−#: qml/Panel/Indicators/MenuItemFactory.qml:876
353+#: qml/Panel/Indicators/MenuItemFactory.qml:886
354#, qt-format
354#, qt-format
355msgid "%1 minute"
355msgid "%1 minute"
356msgid_plural "%1 minutes"
356msgid_plural "%1 minutes"
357msgstr[0] ""
357msgstr[0] ""
358msgstr[1] ""
358msgstr[1] ""
359
359
360−#: qml/Panel/Indicators/MenuItemFactory.qml:881
360+#: qml/Panel/Indicators/MenuItemFactory.qml:891
361#, qt-format
361#, qt-format
362msgid "%1 second"
362msgid "%1 second"
363msgid_plural "%1 seconds"
363msgid_plural "%1 seconds"
364msgstr[0] ""
364msgstr[0] ""
365msgstr[1] ""
365msgstr[1] ""
366
366
367−#: qml/Panel/Indicators/MenuItemFactory.qml:884
367+#: qml/Panel/Indicators/MenuItemFactory.qml:894
368msgid "0 seconds"
368msgid "0 seconds"
369msgstr ""
369msgstr ""
370
370
371#. Translators: String like "1 hour, 2 minutes, 3 seconds remaining"
371#. Translators: String like "1 hour, 2 minutes, 3 seconds remaining"
372−#: qml/Panel/Indicators/MenuItemFactory.qml:886
372+#: qml/Panel/Indicators/MenuItemFactory.qml:896
373#, qt-format
373#, qt-format
374msgid "%1 remaining"
374msgid "%1 remaining"
375msgstr ""
375msgstr ""
376
376
377−#: qml/Panel/Indicators/MenuItemFactory.qml:892
377+#: qml/Panel/Indicators/MenuItemFactory.qml:902
378msgid "In queue…"
378msgid "In queue…"
379msgstr ""
379msgstr ""
380
380
381−#: qml/Panel/Indicators/MenuItemFactory.qml:896
381+#: qml/Panel/Indicators/MenuItemFactory.qml:906
382msgid "Downloading"
382msgid "Downloading"
383msgstr ""
383msgstr ""
384
384
385−#: qml/Panel/Indicators/MenuItemFactory.qml:898
385+#: qml/Panel/Indicators/MenuItemFactory.qml:908
386msgid "Paused, tap to resume"
386msgid "Paused, tap to resume"
387msgstr ""
387msgstr ""
388
388
389−#: qml/Panel/Indicators/MenuItemFactory.qml:900
389+#: qml/Panel/Indicators/MenuItemFactory.qml:910
390msgid "Canceled"
390msgid "Canceled"
391msgstr ""
391msgstr ""
392
392
393−#: qml/Panel/Indicators/MenuItemFactory.qml:902
393+#: qml/Panel/Indicators/MenuItemFactory.qml:912
394msgid "Finished"
394msgid "Finished"
395msgstr ""
395msgstr ""
396
396
397−#: qml/Panel/Indicators/MenuItemFactory.qml:904
397+#: qml/Panel/Indicators/MenuItemFactory.qml:914
398msgid "Failed, tap to retry"
398msgid "Failed, tap to retry"
399msgstr ""
399msgstr ""
400
400
@@ -492,7 +492,7 @@ msgstr ""
492msgid "Let’s get started."
492msgid "Let’s get started."
493msgstr ""
493msgstr ""
494
494
495−#: qml/Wizard/Pages/10-welcome.qml:88 qml/Wizard/Pages/30-passwd-type.qml:128
495+#: qml/Wizard/Pages/10-welcome.qml:88 qml/Wizard/Pages/30-passwd-type.qml:133
496#: qml/Wizard/Pages/40-wifi.qml:215 qml/Wizard/Pages/50-location.qml:131
496#: qml/Wizard/Pages/40-wifi.qml:215 qml/Wizard/Pages/50-location.qml:131
497#: qml/Wizard/Pages/60-reporting.qml:60 qml/Wizard/Pages/passwd-confirm.qml:82
497#: qml/Wizard/Pages/60-reporting.qml:60 qml/Wizard/Pages/passwd-confirm.qml:82
498#: qml/Wizard/Pages/passwd-set.qml:90
498#: qml/Wizard/Pages/passwd-set.qml:90
@@ -515,36 +515,36 @@ msgstr ""
515msgid "Lock security"
515msgid "Lock security"
516msgstr ""
516msgstr ""
517
517
518−#: qml/Wizard/Pages/30-passwd-type.qml:74
518+#: qml/Wizard/Pages/30-passwd-type.qml:79
519msgid "Please select how you’d like to unlock your phone."
519msgid "Please select how you’d like to unlock your phone."
520msgstr ""
520msgstr ""
521
521
522−#: qml/Wizard/Pages/30-passwd-type.qml:97
522+#: qml/Wizard/Pages/30-passwd-type.qml:102
523msgctxt "Label: Type of security method"
523msgctxt "Label: Type of security method"
524msgid "Swipe"
524msgid "Swipe"
525msgstr ""
525msgstr ""
526
526
527−#: qml/Wizard/Pages/30-passwd-type.qml:98
527+#: qml/Wizard/Pages/30-passwd-type.qml:103
528msgctxt "Label: Description of security method"
528msgctxt "Label: Description of security method"
529msgid "No security"
529msgid "No security"
530msgstr ""
530msgstr ""
531
531
532−#: qml/Wizard/Pages/30-passwd-type.qml:100
532+#: qml/Wizard/Pages/30-passwd-type.qml:105
533msgctxt "Label: Type of security method"
533msgctxt "Label: Type of security method"
534msgid "Passcode"
534msgid "Passcode"
535msgstr ""
535msgstr ""
536
536
537−#: qml/Wizard/Pages/30-passwd-type.qml:101
537+#: qml/Wizard/Pages/30-passwd-type.qml:106
538msgctxt "Label: Description of security method"
538msgctxt "Label: Description of security method"
539msgid "4 digits only"
539msgid "4 digits only"
540msgstr ""
540msgstr ""
541
541
542−#: qml/Wizard/Pages/30-passwd-type.qml:103
542+#: qml/Wizard/Pages/30-passwd-type.qml:108
543msgctxt "Label: Type of security method"
543msgctxt "Label: Type of security method"
544msgid "Passphrase"
544msgid "Passphrase"
545msgstr ""
545msgstr ""
546
546
547−#: qml/Wizard/Pages/30-passwd-type.qml:104
547+#: qml/Wizard/Pages/30-passwd-type.qml:109
548msgctxt "Label: Description of security method"
548msgctxt "Label: Description of security method"
549msgid "Numbers and letters"
549msgid "Numbers and letters"
550msgstr ""
550msgstr ""
qml/Dash/DashPageHeader.qml+1
@@ -102,6 +102,7 @@ Item {
102 "edgeMargins": units.gu(1)
102 "edgeMargins": units.gu(1)
103 }
103 }
104 );
104 );
105+ searchTextField.forceActiveFocus();
105 }
106 }
106 }
107 }
107
108
qml/Dash/Previews/PreviewMediaToolbar.qml+2−1
@@ -23,10 +23,11 @@ Rectangle {
23
23
24 implicitHeight: units.gu(6)
24 implicitHeight: units.gu(6)
25 color: Qt.rgba(0, 0, 0, 0.8)
25 color: Qt.rgba(0, 0, 0, 0.8)
26− visible: sharingWidget.visible
26+ visible: sharingWidget.active
27
27
28 PreviewSharing {
28 PreviewSharing {
29 id: sharingWidget
29 id: sharingWidget
30+ objectName: "sharingWidget"
30 anchors {
31 anchors {
31 left: parent.left
32 left: parent.left
32 verticalCenter: parent.verticalCenter
33 verticalCenter: parent.verticalCenter
qml/Dash/Previews/PreviewSharing.qml+3−4
@@ -24,13 +24,12 @@ Item {
24 implicitWidth: button.width
24 implicitWidth: button.width
25
25
26 property var shareData
26 property var shareData
27+ property alias active: peerPicker.active
27 readonly property bool isUrlExternal: url && url.indexOf("file:///") != 0 && url.indexOf("/") != 0
28 readonly property bool isUrlExternal: url && url.indexOf("file:///") != 0 && url.indexOf("/") != 0
28− readonly property string contentType: shareData ? shareData["contentType"] : ""
29+ readonly property string contentType: shareData ? shareData["content-type"] : ""
29 readonly property var url: shareData ? shareData["uri"] : ""
30 readonly property var url: shareData ? shareData["uri"] : ""
30 readonly property Item rootItem: QuickUtils.rootItem(root)
31 readonly property Item rootItem: QuickUtils.rootItem(root)
31
32
32− visible: url != ""
33−
34 AbstractButton {
33 AbstractButton {
35 id: button
34 id: button
36 height: units.gu(4)
35 height: units.gu(4)
@@ -98,7 +97,7 @@ Item {
98 parent: rootItem
97 parent: rootItem
99 anchors.fill: parent
98 anchors.fill: parent
100 visible: false
99 visible: false
101− active: root.visible
100+ active: root.url != ""
102
101
103 sourceComponent: contentPeerComponent
102 sourceComponent: contentPeerComponent
104 }
103 }
qml/Dash/Previews/PreviewVideoPlayback.qml+1−1
@@ -81,7 +81,7 @@ PreviewWidget {
81 right: parent.right
81 right: parent.right
82 bottom: parent.bottom
82 bottom: parent.bottom
83 }
83 }
84− shareData: widgetData["shareData"]
84+ shareData: widgetData["share-data"]
85 }
85 }
86 }
86 }
87}
87}
qml/Dash/Previews/PreviewZoomableImage.qml+1−1
@@ -72,7 +72,7 @@ PreviewWidget {
72 right: parent.right
72 right: parent.right
73 bottom: parent.bottom
73 bottom: parent.bottom
74 }
74 }
75− shareData: widgetData["shareData"]
75+ shareData: widgetData["share-data"]
76 }
76 }
77 }
77 }
78
78
qml/Greeter/Greeter.qml+7−4
@@ -33,7 +33,7 @@ Showable {
33 // How far to offset the top greeter layer during a launcher left-drag
33 // How far to offset the top greeter layer during a launcher left-drag
34 property real launcherOffset
34 property real launcherOffset
35
35
36− readonly property bool active: shown || hasLockedApp
36+ readonly property bool active: required || hasLockedApp
37 readonly property bool fullyShown: loader.item ? loader.item.fullyShown : false
37 readonly property bool fullyShown: loader.item ? loader.item.fullyShown : false
38
38
39 // True when the greeter is waiting for PAM or other setup process
39 // True when the greeter is waiting for PAM or other setup process
@@ -226,14 +226,17 @@ Showable {
226 }
226 }
227
227
228 function checkForForcedDelay() {
228 function checkForForcedDelay() {
229+ if (greeterSettings.lockedOutTime === 0) {
230+ return;
231+ }
232+
229 var now = new Date();
233 var now = new Date();
230− delayTarget = now;
231− delayTarget.setTime(greeterSettings.lockedOutTime + failedLoginsDelayMinutes * 60000);
234+ delayTarget = new Date(greeterSettings.lockedOutTime + failedLoginsDelayMinutes * 60000);
232
235
233 // If tooEarly is true, something went very wrong. Bug or NTP
236 // If tooEarly is true, something went very wrong. Bug or NTP
234 // misconfiguration maybe?
237 // misconfiguration maybe?
235 var tooEarly = now.getTime() < greeterSettings.lockedOutTime;
238 var tooEarly = now.getTime() < greeterSettings.lockedOutTime;
236− var tooLate = now > delayTarget;
239+ var tooLate = now >= delayTarget;
237
240
238 // Compare stored time to system time. If a malicious actor is
241 // Compare stored time to system time. If a malicious actor is
239 // able to manipulate time to avoid our lockout, they already have
242 // able to manipulate time to avoid our lockout, they already have
qml/Launcher/Launcher.qml+4−9
@@ -184,18 +184,13 @@ Item {
184 }
184 }
185 }
185 }
186
186
187− MultiPointTouchArea {
187+ InverseMouseArea {
188 id: closeMouseArea
188 id: closeMouseArea
189− anchors {
189+ anchors.fill: panel
190− left: launcherDragArea.right
191− top: parent.top
192− right: parent.right
193− bottom: parent.bottom
194− }
195 enabled: root.shadeBackground && root.state == "visible"
190 enabled: root.shadeBackground && root.state == "visible"
196− visible: enabled // otherwise it will get in the way of cursor selection for some reason
191+ visible: enabled
197 onPressed: {
192 onPressed: {
198− root.state = ""
193+ root.hide();
199 }
194 }
200 }
195 }
201
196
qml/Launcher/LauncherPanel.qml+6−3
@@ -392,7 +392,6 @@ Rectangle {
392 }
392 }
393
393
394 onClicked: {
394 onClicked: {
395− Haptics.play();
396 var index = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
395 var index = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
397 var clickedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
396 var clickedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
398
397
@@ -407,9 +406,11 @@ Rectangle {
407 quickList.model = launcherListView.model.get(index).quickList;
406 quickList.model = launcherListView.model.get(index).quickList;
408 quickList.appId = launcherListView.model.get(index).appId;
407 quickList.appId = launcherListView.model.get(index).appId;
409 quickList.state = "open";
408 quickList.state = "open";
410− return
409+ return;
411 }
410 }
412
411
412+ Haptics.play();
413+
413 // First/last item do the scrolling at more than 12 degrees
414 // First/last item do the scrolling at more than 12 degrees
414 if (index == 0 || index == launcherListView.count - 1) {
415 if (index == 0 || index == launcherListView.count - 1) {
415 if (clickedItem.angle > 12) {
416 if (clickedItem.angle > 12) {
@@ -594,6 +595,7 @@ Rectangle {
594 width: itemWidth
595 width: itemWidth
595 rotation: root.rotation
596 rotation: root.rotation
596 itemOpacity: 0.9
597 itemOpacity: 0.9
598+ onVisibleChanged: if (!visible) iconName = "";
597
599
598 function flatten() {
600 function flatten() {
599 fakeDragItemAnimation.start();
601 fakeDragItemAnimation.start();
@@ -636,6 +638,7 @@ Rectangle {
636 rotation: 90
638 rotation: 90
637 }
639 }
638 }
640 }
641+
639 InverseMouseArea {
642 InverseMouseArea {
640 anchors.fill: quickListShape
643 anchors.fill: quickListShape
641 enabled: quickList.state == "open" || pressed
644 enabled: quickList.state == "open" || pressed
@@ -692,7 +695,7 @@ Rectangle {
692 property var item
695 property var item
693
696
694 // internal
697 // internal
695− property int itemCenter: item ? root.mapFromItem(quickList.item).y + (item.height / 2) : units.gu(1)
698+ property int itemCenter: item ? root.mapFromItem(quickList.item).y + (item.height / 2) + quickList.item.offset : units.gu(1)
696 property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
699 property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
697 itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
700 itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
698
701
qml/Panel/Indicators/MenuItemFactory.qml+11−1
@@ -576,7 +576,17 @@ Item {
576 active: serverChecked
576 active: serverChecked
577 secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
577 secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
578 adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
578 adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
579+ signalStrength: {
579− signalStrength: strengthAction.valid ? strengthAction.state : 0
580+ if (strengthAction.valid) {
581+ var state = strengthAction.state; // handle both int and uchar
582+ // FIXME remove the special casing when we switch to indicator-network completely
583+ if (typeof state == "string") {
584+ return state.charCodeAt();
585+ }
586+ return state;
587+ }
588+ return 0;
589+ }
580 highlightWhenPressed: false
590 highlightWhenPressed: false
581
591
582 onMenuModelChanged: {
592 onMenuModelChanged: {
qml/Stages/DesktopStage.qml+7−3
@@ -124,16 +124,20 @@ AbstractStage {
124 onFocusedAppDelegateChanged: updateForegroundMaximizedApp();
124 onFocusedAppDelegateChanged: updateForegroundMaximizedApp();
125
125
126 property int foregroundMaximizedAppZ: -1
126 property int foregroundMaximizedAppZ: -1
127+ property int foregroundMaximizedAppIndex: -1 // for stuff like drop shadow and focusing maximized app by clicking panel
127
128
128 function updateForegroundMaximizedApp() {
129 function updateForegroundMaximizedApp() {
129 var tmp = -1;
130 var tmp = -1;
131+ var tmpAppId = -1;
130 for (var i = appRepeater.count - 1; i >= 0; i--) {
132 for (var i = appRepeater.count - 1; i >= 0; i--) {
131 var item = appRepeater.itemAt(i);
133 var item = appRepeater.itemAt(i);
132 if (item && item.visuallyMaximized) {
134 if (item && item.visuallyMaximized) {
135+ tmpAppId = i;
133 tmp = Math.max(tmp, item.normalZ);
136 tmp = Math.max(tmp, item.normalZ);
134 }
137 }
135 }
138 }
136 foregroundMaximizedAppZ = tmp;
139 foregroundMaximizedAppZ = tmp;
140+ foregroundMaximizedAppIndex = tmpAppId;
137 }
141 }
138
142
139 function indexOf(appId) {
143 function indexOf(appId) {
@@ -176,8 +180,8 @@ AbstractStage {
176 onMinimize: priv.focusedAppDelegate && priv.focusedAppDelegate.minimize();
180 onMinimize: priv.focusedAppDelegate && priv.focusedAppDelegate.minimize();
177 onMaximize: priv.focusedAppDelegate // don't restore minimized apps when double clicking the panel
181 onMaximize: priv.focusedAppDelegate // don't restore minimized apps when double clicking the panel
178 && priv.focusedAppDelegate.restoreFromMaximized();
182 && priv.focusedAppDelegate.restoreFromMaximized();
179− onFocusMaximizedApp: if (priv.foregroundMaximizedAppIdIndex != -1) {
183+ onFocusMaximizedApp: if (priv.foregroundMaximizedAppIndex != -1) {
180− ApplicationManager.focusApplication(appRepeater.itemAt(priv.foregroundMaximizedAppIdIndex).appId);
184+ ApplicationManager.focusApplication(appRepeater.itemAt(priv.foregroundMaximizedAppIndex).appId);
181 }
185 }
182 }
186 }
183
187
@@ -206,7 +210,7 @@ AbstractStage {
206 Binding {
210 Binding {
207 target: PanelState
211 target: PanelState
208 property: "dropShadow"
212 property: "dropShadow"
209− value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppIdIndex !== -1
213+ value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppIndex !== -1
210 }
214 }
211
215
212 Component.onDestruction: {
216 Component.onDestruction: {
qml/Wizard/Pages/30-passwd-type.qml+5
@@ -39,6 +39,11 @@ LocalComponents.Page {
39 title: i18n.tr("Lock security")
39 title: i18n.tr("Lock security")
40 forwardButtonSourceComponent: forwardButton
40 forwardButtonSourceComponent: forwardButton
41
41
42+ // If the user has set a password some other way (via ubuntu-device-flash
43+ // or this isn't the first time the wizard has been run, etc). We can't
44+ // properly set the password again, so let's not pretend we can.
45+ skip: securityPrivacy.securityType !== UbuntuSecurityPrivacyPanel.Swipe
46+
42 function indexToMethod(index) {
47 function indexToMethod(index) {
43 if (index === 0)
48 if (index === 0)
44 return UbuntuSecurityPrivacyPanel.Swipe
49 return UbuntuSecurityPrivacyPanel.Swipe
src/CMakeLists.txt+13−7
@@ -15,10 +15,9 @@ file(GLOB_RECURSE QML_FILES
15 ${CMAKE_SOURCE_DIR}/tests/*.svg
15 ${CMAKE_SOURCE_DIR}/tests/*.svg
16)
16)
17
17
18−add_executable(${SHELL_APP}
18+set(SOURCE_FILES
19 ApplicationArguments.cpp
19 ApplicationArguments.cpp
20 main.cpp
20 main.cpp
21− MouseTouchAdaptor.cpp
22 CachingNetworkManagerFactory.cpp
21 CachingNetworkManagerFactory.cpp
23 SecondaryWindow.cpp
22 SecondaryWindow.cpp
24 ShellApplication.cpp
23 ShellApplication.cpp
@@ -27,15 +26,22 @@ add_executable(${SHELL_APP}
27 ${QML_FILES} # This is to make qml and image files appear in the IDE's project tree
26 ${QML_FILES} # This is to make qml and image files appear in the IDE's project tree
28)
27)
29
28
29+if (ENABLE_TOUCH_EMULATION)
30+ set(SOURCE_FILES ${SOURCE_FILES} MouseTouchAdaptor.cpp)
31+endif()
32+
33+pkg_check_modules(ANDROID_PROPERTIES REQUIRED libandroid-properties)
34+add_executable(${SHELL_APP} ${SOURCE_FILES})
30qt5_use_modules(${SHELL_APP} Gui Qml Quick Test)
35qt5_use_modules(${SHELL_APP} Gui Qml Quick Test)
31
36
32−pkg_check_modules(NEEDED_LIBS REQUIRED xcb libandroid-properties)
37+if (NOT "${ANDROID_PROPERTIES_INCLUDE_DIRS}" STREQUAL "")
33−if (NOT "${NEEDED_LIBS_INCLUDE_DIRS}" STREQUAL "")
34− set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${NEEDED_LIBS_INCLUDE_DIRS})
38+ set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${ANDROID_PROPERTIES_INCLUDE_DIRS})
35endif()
39endif()
36−target_link_libraries(${SHELL_APP} ${NEEDED_LIBS_LDFLAGS})
40+target_link_libraries(${SHELL_APP} ${ANDROID_PROPERTIES_LDFLAGS} UbuntuGestures connectivity-qt1)
37
41
42+if (ENABLE_TOUCH_EMULATION)
38−target_link_libraries(${SHELL_APP} UbuntuGestures connectivity-qt1)
43+ target_link_libraries(${SHELL_APP} ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
44+endif()
39
45
40# install binaries
46# install binaries
41install(TARGETS ${SHELL_APP}
47install(TARGETS ${SHELL_APP}
src/Dash/CMakeLists.txt+8−8
@@ -1,25 +1,25 @@
1set(DASH_SRCS
1set(DASH_SRCS
2 main.cpp
2 main.cpp
3− ../ApplicationArguments.cpp
4− ../MouseTouchAdaptor.cpp
5 ../CachingNetworkManagerFactory.cpp
3 ../CachingNetworkManagerFactory.cpp
6)
4)
7
5
6+if (ENABLE_TOUCH_EMULATION)
7+ set(DASH_SRCS ${DASH_SRCS} ../MouseTouchAdaptor.cpp)
8+endif()
9+
8add_executable(unity8-dash ${DASH_SRCS})
10add_executable(unity8-dash ${DASH_SRCS})
9
11
10qt5_use_modules(unity8-dash Gui Qml Quick Test)
12qt5_use_modules(unity8-dash Gui Qml Quick Test)
11
13
12−pkg_check_modules(NEEDED_LIBS REQUIRED xcb libandroid-properties)
13−if (NOT "${NEEDED_LIBS_INCLUDE_DIRS}" STREQUAL "")
14− set_target_properties(unity8-dash PROPERTIES INCLUDE_DIRECTORIES ${NEEDED_LIBS_INCLUDE_DIRS})
15−endif()
16−target_link_libraries(unity8-dash ${NEEDED_LIBS_LDFLAGS})
17−
18# For it to find libUbuntuGestures.so, needed by Ubuntu.Gestures QML module.
14# For it to find libUbuntuGestures.so, needed by Ubuntu.Gestures QML module.
19set_target_properties(unity8-dash PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}")
15set_target_properties(unity8-dash PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}")
20
16
21target_link_libraries(unity8-dash UbuntuGestures connectivity-qt1)
17target_link_libraries(unity8-dash UbuntuGestures connectivity-qt1)
22
18
19+if (ENABLE_TOUCH_EMULATION)
20+ target_link_libraries(unity8-dash ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
21+endif()
22+
23set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
23set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
24
24
25# install binaries
25# install binaries
src/Dash/main.cpp+9−5
@@ -27,8 +27,9 @@
27#include <libintl.h>
27#include <libintl.h>
28
28
29#include <paths.h>
29#include <paths.h>
30+#ifdef UNITY8_ENABLE_TOUCH_EMULATION
30−#include "../MouseTouchAdaptor.h"
31+ #include "../MouseTouchAdaptor.h"
31−#include "../ApplicationArguments.h"
32+#endif
32#include "../CachingNetworkManagerFactory.h"
33#include "../CachingNetworkManagerFactory.h"
33
34
34int main(int argc, const char *argv[])
35int main(int argc, const char *argv[])
@@ -57,8 +58,6 @@ int main(int argc, const char *argv[])
57 parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
58 parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
58 parser.process(*application);
59 parser.process(*application);
59
60
60− ApplicationArguments qmlArgs;
61−
62 if (getenv("QT_LOAD_TESTABILITY")) {
61 if (getenv("QT_LOAD_TESTABILITY")) {
63 QLibrary testLib(QStringLiteral("qttestability"));
62 QLibrary testLib(QStringLiteral("qttestability"));
64 if (testLib.load()) {
63 if (testLib.load()) {
@@ -92,14 +91,15 @@ int main(int argc, const char *argv[])
92 }
91 }
93
92
94 view->setTitle(QStringLiteral("Scopes"));
93 view->setTitle(QStringLiteral("Scopes"));
95− view->rootContext()->setContextProperty(QStringLiteral("applicationArguments"), &qmlArgs);
96
94
95+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
97 // You will need this if you want to interact with touch-only components using a mouse
96 // You will need this if you want to interact with touch-only components using a mouse
98 // Needed only when manually testing on a desktop.
97 // Needed only when manually testing on a desktop.
99 MouseTouchAdaptor *mouseTouchAdaptor = 0;
98 MouseTouchAdaptor *mouseTouchAdaptor = 0;
100 if (parser.isSet(mousetouchOption)) {
99 if (parser.isSet(mousetouchOption)) {
101 mouseTouchAdaptor = MouseTouchAdaptor::instance();
100 mouseTouchAdaptor = MouseTouchAdaptor::instance();
102 }
101 }
102+ #endif
103
103
104 QUrl source(::qmlDirectory() + "/Dash/DashApplication.qml");
104 QUrl source(::qmlDirectory() + "/Dash/DashApplication.qml");
105 prependImportPaths(view->engine(), ::overrideImportPaths());
105 prependImportPaths(view->engine(), ::overrideImportPaths());
@@ -114,7 +114,11 @@ int main(int argc, const char *argv[])
114 int result = application->exec();
114 int result = application->exec();
115
115
116 delete view;
116 delete view;
117+
118+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
117 delete mouseTouchAdaptor;
119 delete mouseTouchAdaptor;
120+ #endif
121+
118 delete application;
122 delete application;
119
123
120 return result;
124 return result;
src/MouseTouchAdaptor.cpp+180−21
@@ -16,14 +16,56 @@
16 * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
16 * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
17 */
17 */
18
18
19+
20+/* Some parts of the code were copied from the XCB platform plugin of the Qt Toolkit,
21+ * which is under the following license:
22+ */
23+
24+/****************************************************************************
25+**
26+** Copyright (C) 2015 The Qt Company Ltd.
27+** Contact: http://www.qt.io/licensing/
28+**
29+** This file is part of the .
30+**
31+** $QT_BEGIN_LICENSE:LGPL21$
32+** Commercial License Usage
33+** Licensees holding valid commercial Qt licenses may use this file in
34+** accordance with the commercial license agreement provided with the
35+** Software or, alternatively, in accordance with the terms contained in
36+** a written agreement between you and The Qt Company. For licensing terms
37+** and conditions see http://www.qt.io/terms-conditions. For further
38+** information use the contact form at http://www.qt.io/contact-us.
39+**
40+** GNU Lesser General Public License Usage
41+** Alternatively, this file may be used under the terms of the GNU Lesser
42+** General Public License version 2.1 or version 3 as published by the Free
43+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
44+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
45+** following information to ensure the GNU Lesser General Public License
46+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
47+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
48+**
49+** As a special exception, The Qt Company gives you certain additional
50+** rights. These rights are described in The Qt Company LGPL Exception
51+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
52+**
53+** $QT_END_LICENSE$
54+**
55+****************************************************************************/
56+
19#include "MouseTouchAdaptor.h"
57#include "MouseTouchAdaptor.h"
20
58
59+#include <qpa/qplatformnativeinterface.h>
21#include <qpa/qwindowsysteminterface.h>
60#include <qpa/qwindowsysteminterface.h>
22
61
23#include <QCoreApplication>
62#include <QCoreApplication>
24#include <QMouseEvent>
63#include <QMouseEvent>
25#include <QTest>
64#include <QTest>
26
65
66+#include <X11/extensions/XInput2.h>
67+#include <X11/extensions/XI2proto.h>
68+
27using QTest::QTouchEventSequence;
69using QTest::QTouchEventSequence;
28
70
29namespace {
71namespace {
@@ -49,6 +91,8 @@ MouseTouchAdaptor::MouseTouchAdaptor()
49 m_touchDevice = new QTouchDevice;
91 m_touchDevice = new QTouchDevice;
50 m_touchDevice->setType(QTouchDevice::TouchScreen);
92 m_touchDevice->setType(QTouchDevice::TouchScreen);
51 QWindowSystemInterface::registerTouchDevice(m_touchDevice);
93 QWindowSystemInterface::registerTouchDevice(m_touchDevice);
94+
95+ fetchXInput2Info();
52}
96}
53
97
54MouseTouchAdaptor::~MouseTouchAdaptor()
98MouseTouchAdaptor::~MouseTouchAdaptor()
@@ -65,9 +109,114 @@ MouseTouchAdaptor* MouseTouchAdaptor::instance()
65 return g_instance;
109 return g_instance;
66}
110}
67
111
112+void MouseTouchAdaptor::fetchXInput2Info()
113+{
114+ QPlatformNativeInterface *nativeInterface = qGuiApp->platformNativeInterface();
115+ Display *xDisplay = static_cast<Display*>(nativeInterface->nativeResourceForIntegration("Display"));
116+ if (xDisplay && XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) {
117+ int xiMajor = 2;
118+ m_xi2Minor = 2; // try 2.2 first, needed for TouchBegin/Update/End
119+ if (XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) == BadRequest) {
120+ m_xi2Minor = 1; // for smooth scrolling 2.1 is enough
121+ if (XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) == BadRequest) {
122+ m_xi2Minor = 0; // for tablet support 2.0 is enough
123+ m_xi2Enabled = XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) != BadRequest;
124+ } else
125+ m_xi2Enabled = true;
126+ } else {
127+ m_xi2Enabled = true;
128+ }
129+ }
130+}
131+
132+// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
133+// - "pad0" became "extension"
134+// - "pad1" and "pad" became "pad0"
135+// New and old version of this struct share the following fields:
136+// NOTE: API might change again in the next release of xcb in which case this comment will
137+// need to be updated to reflect the reality.
138+typedef struct qt_xcb_ge_event_t {
139+ uint8_t response_type;
140+ uint8_t extension;
141+ uint16_t sequence;
142+ uint32_t length;
143+ uint16_t event_type;
144+} qt_xcb_ge_event_t;
145+
146+bool xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *ev, int opCode)
147+{
148+ qt_xcb_ge_event_t *event = (qt_xcb_ge_event_t *)ev;
149+ // xGenericEvent has "extension" on the second byte, the same is true for xcb_ge_event_t starting from
150+ // the xcb version 1.9.3, prior to that it was called "pad0".
151+ if (event->extension == opCode) {
152+ // xcb event structs contain stuff that wasn't on the wire, the full_sequence field
153+ // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
154+ // Move this data back to have the same layout in memory as it was on the wire
155+ // and allow casting, overwriting the full_sequence field.
156+ memmove((char*) event + 32, (char*) event + 36, event->length * 4);
157+ return true;
158+ }
159+ return false;
160+}
161+
162+static inline qreal fixed1616ToReal(FP1616 val)
163+{
164+ return qreal(val) / 0x10000;
165+}
166+
167+bool MouseTouchAdaptor::xi2HandleEvent(xcb_ge_event_t *event)
168+{
169+ if (!xi2PrepareXIGenericDeviceEvent(event, m_xiOpCode)) {
170+ return false;
171+ }
172+
173+ xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
174+ xXIDeviceEvent *xiDeviceEvent = 0;
175+
176+ switch (xiEvent->evtype) {
177+ case XI_ButtonPress:
178+ case XI_ButtonRelease:
179+ case XI_Motion:
180+ xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
181+ break;
182+ default:
183+ break;
184+ }
185+
186+ if (!xiDeviceEvent) {
187+ return false;
188+ }
189+
190+ switch (xiDeviceEvent->evtype) {
191+ case XI_ButtonPress:
192+ return handleButtonPress(
193+ static_cast<WId>(xiDeviceEvent->event),
194+ xiDeviceEvent->detail,
195+ fixed1616ToReal(xiDeviceEvent->event_x),
196+ fixed1616ToReal(xiDeviceEvent->event_y));
197+ case XI_ButtonRelease:
198+ return handleButtonRelease(
199+ static_cast<WId>(xiDeviceEvent->event),
200+ xiDeviceEvent->detail,
201+ fixed1616ToReal(xiDeviceEvent->event_x),
202+ fixed1616ToReal(xiDeviceEvent->event_y));
203+ case XI_Motion:
204+ return handleMotionNotify(
205+ static_cast<WId>(xiDeviceEvent->event),
206+ fixed1616ToReal(xiDeviceEvent->event_x),
207+ fixed1616ToReal(xiDeviceEvent->event_y));
208+ return true;
209+ default:
210+ return false;
211+ }
212+}
213+
214+
68bool MouseTouchAdaptor::nativeEventFilter(const QByteArray & eventType,
215bool MouseTouchAdaptor::nativeEventFilter(const QByteArray & eventType,
69 void * message, long * /*result*/)
216 void * message, long * /*result*/)
70{
217{
218+ static int eventCount = 0;
219+ eventCount++;
71 if (!m_enabled) {
220 if (!m_enabled) {
72 return false;
221 return false;
73 }
222 }
@@ -81,32 +230,42 @@ bool MouseTouchAdaptor::nativeEventFilter(const QByteArray & eventType,
81 xcb_generic_event_t *xcbEvent = static_cast<xcb_generic_event_t *>(message);
230 xcb_generic_event_t *xcbEvent = static_cast<xcb_generic_event_t *>(message);
82
231
83 switch (xcbEvent->response_type & ~0x80) {
232 switch (xcbEvent->response_type & ~0x80) {
84− case XCB_BUTTON_PRESS:
233+ case XCB_BUTTON_PRESS: {
85− return handleButtonPress(reinterpret_cast<xcb_button_press_event_t *>(xcbEvent));
234+ auto pressEvent = reinterpret_cast<xcb_button_press_event_t *>(xcbEvent);
86− break;
235+ return handleButtonPress(static_cast<WId>(pressEvent->event), pressEvent->detail,
236+ pressEvent->event_x, pressEvent->event_y);
237+ }
87− case XCB_BUTTON_RELEASE:
238+ case XCB_BUTTON_RELEASE: {
88− return handleButtonRelease(reinterpret_cast<xcb_button_release_event_t *>(xcbEvent));
239+ auto releaseEvent = reinterpret_cast<xcb_button_release_event_t *>(xcbEvent);
89− break;
240+ return handleButtonRelease(static_cast<WId>(releaseEvent->event), releaseEvent->detail,
241+ releaseEvent->event_x, releaseEvent->event_y);
242+ }
90− case XCB_MOTION_NOTIFY:
243+ case XCB_MOTION_NOTIFY: {
91− return handleMotionNotify(reinterpret_cast<xcb_motion_notify_event_t *>(xcbEvent));
244+ auto motionEvent = reinterpret_cast<xcb_motion_notify_event_t *>(xcbEvent);
92− break;
245+ return handleMotionNotify(static_cast<WId>(motionEvent->event), motionEvent->event_x, motionEvent->event_y);
246+ }
247+ case XCB_GE_GENERIC:
248+ if (m_xi2Enabled) {
249+ return xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(xcbEvent));
250+ } else {
251+ return false;
252+ }
93 default:
253 default:
94 return false;
254 return false;
95− break;
96 };
255 };
97}
256}
98
257
99−bool MouseTouchAdaptor::handleButtonPress(xcb_button_press_event_t *pressEvent)
258+bool MouseTouchAdaptor::handleButtonPress(WId windowId, uint32_t detail, int x, int y)
100{
259{
101− Qt::MouseButton button = translateMouseButton(pressEvent->detail);
260+ Qt::MouseButton button = translateMouseButton(detail);
102
261
103 // Just eat the event if it wasn't a left mouse press
262 // Just eat the event if it wasn't a left mouse press
104 if (button != Qt::LeftButton)
263 if (button != Qt::LeftButton)
105 return true;
264 return true;
106
265
107− QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(pressEvent->event));
266+ QWindow *targetWindow = findQWindowWithXWindowID(windowId);
108
267
109− QPoint windowPos(pressEvent->event_x / targetWindow->devicePixelRatio(), pressEvent->event_y / targetWindow->devicePixelRatio());
268+ QPoint windowPos(x / targetWindow->devicePixelRatio(), y / targetWindow->devicePixelRatio());
110
269
111 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
270 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
112 false /* autoCommit */);
271 false /* autoCommit */);
@@ -117,17 +276,17 @@ bool MouseTouchAdaptor::handleButtonPress(xcb_button_press_event_t *pressEvent)
117 return true;
276 return true;
118}
277}
119
278
120−bool MouseTouchAdaptor::handleButtonRelease(xcb_button_release_event_t *releaseEvent)
279+bool MouseTouchAdaptor::handleButtonRelease(WId windowId, uint32_t detail, int x, int y)
121{
280{
122− Qt::MouseButton button = translateMouseButton(releaseEvent->detail);
281+ Qt::MouseButton button = translateMouseButton(detail);
123
282
124 // Just eat the event if it wasn't a left mouse release
283 // Just eat the event if it wasn't a left mouse release
125 if (button != Qt::LeftButton)
284 if (button != Qt::LeftButton)
126 return true;
285 return true;
127
286
128− QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(releaseEvent->event));
287+ QWindow *targetWindow = findQWindowWithXWindowID(windowId);
129
288
130− QPoint windowPos(releaseEvent->event_x / targetWindow->devicePixelRatio(), releaseEvent->event_y / targetWindow->devicePixelRatio());
289+ QPoint windowPos(x / targetWindow->devicePixelRatio(), y / targetWindow->devicePixelRatio());
131
290
132 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
291 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
133 false /* autoCommit */);
292 false /* autoCommit */);
@@ -138,15 +297,15 @@ bool MouseTouchAdaptor::handleButtonRelease(xcb_button_release_event_t *releaseE
138 return true;
297 return true;
139}
298}
140
299
141−bool MouseTouchAdaptor::handleMotionNotify(xcb_motion_notify_event_t *event)
300+bool MouseTouchAdaptor::handleMotionNotify(WId windowId, int x, int y)
142{
301{
143 if (!m_leftButtonIsPressed) {
302 if (!m_leftButtonIsPressed) {
144 return true;
303 return true;
145 }
304 }
146
305
147− QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(event->event));
306+ QWindow *targetWindow = findQWindowWithXWindowID(windowId);
148
307
149− QPoint windowPos(event->event_x / targetWindow->devicePixelRatio(), event->event_y / targetWindow->devicePixelRatio());
308+ QPoint windowPos(x / targetWindow->devicePixelRatio(), y / targetWindow->devicePixelRatio());
150
309
151 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
310 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
152 false /* autoCommit */);
311 false /* autoCommit */);
src/MouseTouchAdaptor.h+10−3
@@ -21,6 +21,7 @@
21
21
22#include <QtCore/QAbstractNativeEventFilter>
22#include <QtCore/QAbstractNativeEventFilter>
23#include <QWindow>
23#include <QWindow>
24+
24#include <xcb/xcb.h>
25#include <xcb/xcb.h>
25
26
26class QMouseEvent;
27class QMouseEvent;
@@ -47,16 +48,22 @@ Q_SIGNALS:
47
48
48private:
49private:
49 MouseTouchAdaptor();
50 MouseTouchAdaptor();
51+ void fetchXInput2Info();
52+ bool xi2HandleEvent(xcb_ge_event_t *event);
50
53
51− bool handleButtonPress(xcb_button_press_event_t *pressEvent);
54+ bool handleButtonPress(WId windowId, uint32_t detail, int x, int y);
52− bool handleButtonRelease(xcb_button_release_event_t *releaseEvent);
55+ bool handleButtonRelease(WId windowId, uint32_t detail, int x, int y);
53− bool handleMotionNotify(xcb_motion_notify_event_t *event);
56+ bool handleMotionNotify(WId windowId, int x, int y);
54 QWindow *findQWindowWithXWindowID(WId windowId);
57 QWindow *findQWindowWithXWindowID(WId windowId);
55
58
56 QTouchDevice *m_touchDevice;
59 QTouchDevice *m_touchDevice;
57 bool m_leftButtonIsPressed;
60 bool m_leftButtonIsPressed;
58
61
59 bool m_enabled;
62 bool m_enabled;
63+
64+ bool m_xi2Enabled{false};
65+ int m_xi2Minor{-1};
66+ int m_xiOpCode, m_xiEventBase, m_xiErrorBase;
60};
67};
61
68
62#endif // MOUSE_TOUCH_ADAPTOR_H
69#endif // MOUSE_TOUCH_ADAPTOR_H
src/ShellApplication.cpp+5−5
@@ -28,15 +28,10 @@
28// local
28// local
29#include <paths.h>
29#include <paths.h>
30#include "CachingNetworkManagerFactory.h"
30#include "CachingNetworkManagerFactory.h"
31−#include "MouseTouchAdaptor.h"
32#include "UnityCommandLineParser.h"
31#include "UnityCommandLineParser.h"
33
32
34ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer)
33ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer)
35 : QGuiApplication(argc, argv)
34 : QGuiApplication(argc, argv)
36− , m_shellView(nullptr)
37− , m_secondaryWindow(nullptr)
38− , m_mouseTouchAdaptor(nullptr)
39− , m_qmlEngine(nullptr)
40{
35{
41
36
42 setApplicationName(QStringLiteral("unity8"));
37 setApplicationName(QStringLiteral("unity8"));
@@ -89,11 +84,14 @@ ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer)
89 m_shellView->setFlags(Qt::FramelessWindowHint);
84 m_shellView->setFlags(Qt::FramelessWindowHint);
90 }
85 }
91
86
87+
88+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
92 // You will need this if you want to interact with touch-only components using a mouse
89 // You will need this if you want to interact with touch-only components using a mouse
93 // Needed only when manually testing on a desktop.
90 // Needed only when manually testing on a desktop.
94 if (parser.hasMouseToTouch()) {
91 if (parser.hasMouseToTouch()) {
95 m_mouseTouchAdaptor = MouseTouchAdaptor::instance();
92 m_mouseTouchAdaptor = MouseTouchAdaptor::instance();
96 }
93 }
94+ #endif
97
95
98
96
99 // Some hard-coded policy for now.
97 // Some hard-coded policy for now.
@@ -134,8 +132,10 @@ void ShellApplication::destroyResources()
134 delete m_secondaryWindow;
132 delete m_secondaryWindow;
135 m_secondaryWindow = nullptr;
133 m_secondaryWindow = nullptr;
136
134
135+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
137 delete m_mouseTouchAdaptor;
136 delete m_mouseTouchAdaptor;
138 m_mouseTouchAdaptor = nullptr;
137 m_mouseTouchAdaptor = nullptr;
138+ #endif
139
139
140 delete m_qmlEngine;
140 delete m_qmlEngine;
141 m_qmlEngine = nullptr;
141 m_qmlEngine = nullptr;
src/ShellApplication.h+12−4
@@ -23,7 +23,11 @@
23#include <QScopedPointer>
23#include <QScopedPointer>
24
24
25#include "ApplicationArguments.h"
25#include "ApplicationArguments.h"
26+
27+#ifdef UNITY8_ENABLE_TOUCH_EMULATION
26#include "MouseTouchAdaptor.h"
28#include "MouseTouchAdaptor.h"
29+#endif
30+
27#include "SecondaryWindow.h"
31#include "SecondaryWindow.h"
28#include "ShellView.h"
32#include "ShellView.h"
29
33
@@ -46,10 +50,14 @@ private:
46 void setupQmlEngine(bool isMirServer);
50 void setupQmlEngine(bool isMirServer);
47 QString m_deviceName;
51 QString m_deviceName;
48 ApplicationArguments m_qmlArgs;
52 ApplicationArguments m_qmlArgs;
49− ShellView *m_shellView;
53+ ShellView *m_shellView{nullptr};
50− SecondaryWindow *m_secondaryWindow;
54+ SecondaryWindow *m_secondaryWindow{nullptr};
55+
56+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
51− MouseTouchAdaptor *m_mouseTouchAdaptor;
57+ MouseTouchAdaptor *m_mouseTouchAdaptor{nullptr};
58+ #endif
59+
52− QQmlEngine *m_qmlEngine;
60+ QQmlEngine *m_qmlEngine{nullptr};
53};
61};
54
62
55#endif // SHELLAPPLICATION_H
63#endif // SHELLAPPLICATION_H
src/UnityCommandLineParser.cpp+6
@@ -37,9 +37,11 @@ UnityCommandLineParser::UnityCommandLineParser(const QCoreApplication &app)
37 QStringLiteral("Run without window borders"));
37 QStringLiteral("Run without window borders"));
38 parser.addOption(framelessOption);
38 parser.addOption(framelessOption);
39
39
40+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
40 QCommandLineOption mousetouchOption(QStringLiteral("mousetouch"),
41 QCommandLineOption mousetouchOption(QStringLiteral("mousetouch"),
41 QStringLiteral("Allow the mouse to provide touch input"));
42 QStringLiteral("Allow the mouse to provide touch input"));
42 parser.addOption(mousetouchOption);
43 parser.addOption(mousetouchOption);
44+ #endif
43
45
44 QCommandLineOption windowGeometryOption(QStringList() << QStringLiteral("windowgeometry"),
46 QCommandLineOption windowGeometryOption(QStringList() << QStringLiteral("windowgeometry"),
45 QStringLiteral("Specify the window geometry as [<width>x<height>]"), QStringLiteral("windowgeometry"), QStringLiteral("1"));
47 QStringLiteral("Specify the window geometry as [<width>x<height>]"), QStringLiteral("windowgeometry"), QStringLiteral("1"));
@@ -75,7 +77,11 @@ UnityCommandLineParser::UnityCommandLineParser(const QCoreApplication &app)
75
77
76 m_hasTestability = parser.isSet(testabilityOption);
78 m_hasTestability = parser.isSet(testabilityOption);
77 m_hasFrameless = parser.isSet(framelessOption);
79 m_hasFrameless = parser.isSet(framelessOption);
80+
81+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
78 m_hasMouseToTouch = parser.isSet(mousetouchOption);
82 m_hasMouseToTouch = parser.isSet(mousetouchOption);
83+ #endif
84+
79 m_hasFullscreen = parser.isSet(fullscreenOption);
85 m_hasFullscreen = parser.isSet(fullscreenOption);
80 m_deviceName = parser.value(devicenameOption);
86 m_deviceName = parser.value(devicenameOption);
81 resolveMode(parser, modeOption);
87 resolveMode(parser, modeOption);
src/UnityCommandLineParser.h+8
@@ -28,7 +28,11 @@ public:
28 QSize windowGeometry() const { return m_windowGeometry; }
28 QSize windowGeometry() const { return m_windowGeometry; }
29 bool hasTestability() const { return m_hasTestability; }
29 bool hasTestability() const { return m_hasTestability; }
30 bool hasFrameless() const { return m_hasFrameless; }
30 bool hasFrameless() const { return m_hasFrameless; }
31+
32+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
31 bool hasMouseToTouch() const { return m_hasMouseToTouch; }
33 bool hasMouseToTouch() const { return m_hasMouseToTouch; }
34+ #endif
35+
32 bool hasFullscreen() const { return m_hasFullscreen; }
36 bool hasFullscreen() const { return m_hasFullscreen; }
33 QString deviceName() const { return m_deviceName; }
37 QString deviceName() const { return m_deviceName; }
34 QString mode() const { return m_mode; }
38 QString mode() const { return m_mode; }
@@ -43,7 +47,11 @@ private:
43 QSize m_windowGeometry;
47 QSize m_windowGeometry;
44 bool m_hasTestability;
48 bool m_hasTestability;
45 bool m_hasFrameless;
49 bool m_hasFrameless;
50+
51+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
46 bool m_hasMouseToTouch;
52 bool m_hasMouseToTouch;
53+ #endif
54+
47 bool m_hasFullscreen;
55 bool m_hasFullscreen;
48 QString m_deviceName;
56 QString m_deviceName;
49 QString m_mode;
57 QString m_mode;
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/CMakeLists.txt+1−1
@@ -7,4 +7,4 @@ add_library(MockSecurityPrivacy MODULE ${MOCK_SECURITYPRIVACY_SOURCES})
7
7
8qt5_use_modules(MockSecurityPrivacy Qml Quick Core)
8qt5_use_modules(MockSecurityPrivacy Qml Quick Core)
9
9
10−add_unity8_mock(Ubuntu.SystemSettings.SecurityPrivacy 1.0 Ubuntu/SystemSettings/SecurityPrivacy TARGETS MockSecurityPrivacy)
10+add_unity8_mock(Ubuntu.SystemSettings.SecurityPrivacy 1.0 Ubuntu/SystemSettings/SecurityPrivacy PREFIX mocks TARGETS MockSecurityPrivacy)
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.cpp+8−1
@@ -17,12 +17,19 @@
17#include "MockSecurityPrivacy.h"
17#include "MockSecurityPrivacy.h"
18
18
19MockSecurityPrivacy::MockSecurityPrivacy(QObject *parent)
19MockSecurityPrivacy::MockSecurityPrivacy(QObject *parent)
20− : QObject(parent)
20+ : QObject(parent),
21+ m_type(SecurityType::Swipe)
21{
22{
22}
23}
23
24
25+MockSecurityPrivacy::SecurityType MockSecurityPrivacy::getSecurityType()
26+{
27+ return m_type;
28+}
29+
24QString MockSecurityPrivacy::setSecurity(const QString &oldPasswd, const QString &newPasswd, SecurityType newType)
30QString MockSecurityPrivacy::setSecurity(const QString &oldPasswd, const QString &newPasswd, SecurityType newType)
25{
31{
32+ m_type = newType;
26 Q_EMIT setSecurityCalled(oldPasswd, newPasswd, newType);
33 Q_EMIT setSecurityCalled(oldPasswd, newPasswd, newType);
27 return "";
34 return "";
28}
35}
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.h+8
@@ -23,6 +23,9 @@ class MockSecurityPrivacy : public QObject
23{
23{
24 Q_OBJECT
24 Q_OBJECT
25 Q_ENUMS(SecurityType)
25 Q_ENUMS(SecurityType)
26+ Q_PROPERTY (SecurityType securityType
27+ READ getSecurityType
28+ NOTIFY securityTypeChanged)
26
29
27public:
30public:
28 enum SecurityType {
31 enum SecurityType {
@@ -33,10 +36,15 @@ public:
33
36
34 MockSecurityPrivacy(QObject *parent = 0);
37 MockSecurityPrivacy(QObject *parent = 0);
35
38
39+ SecurityType getSecurityType();
36 Q_INVOKABLE QString setSecurity(const QString &oldPasswd, const QString &newPasswd, SecurityType newType);
40 Q_INVOKABLE QString setSecurity(const QString &oldPasswd, const QString &newPasswd, SecurityType newType);
37
41
38Q_SIGNALS:
42Q_SIGNALS:
43+ void securityTypeChanged();
39 void setSecurityCalled(const QString &oldPasswd, const QString &newPasswd, SecurityType newType); // only in mock
44 void setSecurityCalled(const QString &oldPasswd, const QString &newPasswd, SecurityType newType); // only in mock
45+
46+private:
47+ SecurityType m_type;
40};
48};
41
49
42#endif // MOCK_SECURITYPRIVACY_H
50#endif // MOCK_SECURITYPRIVACY_H
tests/plugins/Dash/cardcreator/9.res+1
@@ -3,6 +3,7 @@ AbstractButton {
3 property var components;
3 property var components;
4 property var cardData;
4 property var cardData;
5 property string artShapeStyle: "inset";
5 property string artShapeStyle: "inset";
6+ property string backgroundShapeStyle: "inset";
6 property real fontScale: 1.0;
7 property real fontScale: 1.0;
7 property var scopeStyle: null;
8 property var scopeStyle: null;
8 property int titleAlignment: Text.AlignLeft;
9 property int titleAlignment: Text.AlignLeft;
tests/qmltests/CMakeLists.txt+2−1
@@ -38,6 +38,7 @@ add_unity8_qmltest(Dash/Previews PreviewExpandable)
38add_unity8_qmltest(Dash/Previews PreviewHeader)
38add_unity8_qmltest(Dash/Previews PreviewHeader)
39add_unity8_qmltest(Dash/Previews PreviewIconActions)
39add_unity8_qmltest(Dash/Previews PreviewIconActions)
40add_unity8_qmltest(Dash/Previews PreviewImageGallery)
40add_unity8_qmltest(Dash/Previews PreviewImageGallery)
41+add_unity8_qmltest(Dash/Previews PreviewMediaToolbar)
41add_unity8_qmltest(Dash/Previews PreviewPayments)
42add_unity8_qmltest(Dash/Previews PreviewPayments)
42add_unity8_qmltest(Dash/Previews PreviewProgress)
43add_unity8_qmltest(Dash/Previews PreviewProgress)
43add_unity8_qmltest(Dash/Previews PreviewRatingDisplay)
44add_unity8_qmltest(Dash/Previews PreviewRatingDisplay)
@@ -87,4 +88,4 @@ add_unity8_qmltest(Stages WindowResizeArea)
87add_unity8_qmltest(Stages Splash)
88add_unity8_qmltest(Stages Splash)
88add_unity8_qmltest(Tutorial Tutorial LIGHTDM)
89add_unity8_qmltest(Tutorial Tutorial LIGHTDM)
89add_unity8_qmltest(Wizard Wizard ENVIRONMENT "OXIDE_NO_SANDBOX=1")
90add_unity8_qmltest(Wizard Wizard ENVIRONMENT "OXIDE_NO_SANDBOX=1")
90−add_unity8_qmlunittest(utils/Unity/Test UnityTest)
91+add_unity8_qmltest(utils/Unity/Test UnityTest)
tests/qmltests/Components/CMakeLists.txt+1−1
@@ -17,7 +17,7 @@ qt5_use_modules(DragHandleTestExec Test Core Qml Gui Quick)
17target_link_libraries(DragHandleTestExec UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES})
17target_link_libraries(DragHandleTestExec UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES})
18
18
19add_unity8_uitest(DragHandle DragHandleTestExec ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures)
19add_unity8_uitest(DragHandle DragHandleTestExec ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures)
20−add_manual_qml_test(. DragHandle IMPORT_PATHS ${UNITY_PLUGINPATH})
20+add_manual_qml_test(. DragHandle IMPORT_PATHS ${UNITY_IMPORT_PATHS})
21
21
22########## tst_EdgeDragEvaluator
22########## tst_EdgeDragEvaluator
23add_executable(EdgeDragEvaluatorTestExec tst_EdgeDragEvaluator.cpp)
23add_executable(EdgeDragEvaluatorTestExec tst_EdgeDragEvaluator.cpp)
tests/qmltests/Components/tst_DragHandle.qml+6−6
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2013 Canonical Ltd.
2+ * Copyright 2013,2015 Canonical Ltd.
3 *
3 *
4 * This program is free software; you can redistribute it and/or modify
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
5 * it under the terms of the GNU General Public License as published by
@@ -51,7 +51,7 @@ Rectangle {
51 objectName: "baseItem"
51 objectName: "baseItem"
52 anchors.fill: parent
52 anchors.fill: parent
53
53
54− Button {
54+ SimpleButton {
55 visible: root.bidirectional && bidirectionalShowable.fullyHidden
55 visible: root.bidirectional && bidirectionalShowable.fullyHidden
56 text: "bidirectionalShowable.show()"
56 text: "bidirectionalShowable.show()"
57 anchors.centerIn: parent
57 anchors.centerIn: parent
@@ -169,12 +169,12 @@ Rectangle {
169 anchors.margins: units.gu(1)
169 anchors.margins: units.gu(1)
170 spacing: units.gu(1)
170 spacing: units.gu(1)
171
171
172− Button {
172+ SimpleButton {
173 text: root.stretch ? "stretch" : "move"
173 text: root.stretch ? "stretch" : "move"
174 onClicked: { root.stretch = !root.stretch; }
174 onClicked: { root.stretch = !root.stretch; }
175 }
175 }
176
176
177− Button {
177+ SimpleButton {
178 text: root.hintDisplacement > 0 ? "hint" : "no hint"
178 text: root.hintDisplacement > 0 ? "hint" : "no hint"
179 onClicked: {
179 onClicked: {
180 if (root.hintDisplacement > 0) {
180 if (root.hintDisplacement > 0) {
@@ -185,7 +185,7 @@ Rectangle {
185 }
185 }
186 }
186 }
187
187
188− Button {
188+ SimpleButton {
189 text: "rotation: " + baseItem.rotation
189 text: "rotation: " + baseItem.rotation
190 onClicked: {
190 onClicked: {
191 if (baseItem.rotation === 0.0) {
191 if (baseItem.rotation === 0.0) {
@@ -196,7 +196,7 @@ Rectangle {
196 }
196 }
197 }
197 }
198
198
199− Button {
199+ SimpleButton {
200 text: root.bidirectional ? "bidirectional" : "directional"
200 text: root.bidirectional ? "bidirectional" : "directional"
201 onClicked: { root.bidirectional = !root.bidirectional; }
201 onClicked: { root.bidirectional = !root.bidirectional; }
202 }
202 }
tests/qmltests/Components/tst_DragHandle/SimpleButton.qmlnew file+36
@@ -0,0 +1,36 @@
1+/*
2+ * Copyright 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 Ubuntu.Components 1.3
19+
20+
21+Rectangle {
22+ id: root
23+ property alias text: textItem.text
24+ signal clicked()
25+ width: textItem.width + units.gu(1.5)
26+ height: textItem.height + units.gu(1.5)
27+ Text {
28+ id: textItem
29+ anchors.centerIn: parent
30+ font.pixelSize: units.gu(1.5)
31+ }
32+ MouseArea {
33+ anchors.fill: parent
34+ onClicked: root.clicked()
35+ }
36+}
tests/qmltests/Dash/Previews/tst_PreviewMediaToolbar.qmlnew file+69
@@ -0,0 +1,69 @@
1+/*
2+ * Copyright 2014 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 QtTest 1.0
19+import Ubuntu.Components 1.3
20+import "../../../../qml/Dash/Previews"
21+import Unity.Test 0.1 as UT
22+
23+Rectangle {
24+ id: root
25+ width: units.gu(40)
26+ height: units.gu(80)
27+ color: "black"
28+
29+ property var shareData: {
30+ "uri": [
31+ "Text here",
32+ "text here 2",
33+ "text here 3"
34+ ],
35+ "content-type": "text"
36+ }
37+
38+ property var shareDataNoUri: {
39+ "uri": "",
40+ "content-type": "text"
41+ }
42+
43+
44+ PreviewMediaToolbar {
45+ id: previewMediaToolbar
46+ anchors { left: parent.left; bottom: parent.bottom; }
47+ shareData: root.shareData
48+ }
49+
50+ UT.UnityTestCase {
51+ name: "PreviewMediaToolbarTest"
52+ when: windowShown
53+
54+ property Item sharingWidget: findChild(previewMediaToolbar, "sharingWidget")
55+
56+ function cleanup() {
57+ previewMediaToolbar.shareData = root.shareData;
58+ }
59+
60+ function test_visible() {
61+ previewMediaToolbar.shareData = shareDataNoUri;
62+ compare(previewMediaToolbar.visible, false);
63+ compare(sharingWidget.visible, false);
64+ previewMediaToolbar.shareData = shareData;
65+ compare(previewMediaToolbar.visible, true);
66+ compare(sharingWidget.visible, true);
67+ }
68+ }
69+}
tests/qmltests/Dash/Previews/tst_PreviewSharing.qml+1−13
@@ -32,12 +32,7 @@ Rectangle {
32 "text here 2",
32 "text here 2",
33 "text here 3"
33 "text here 3"
34 ],
34 ],
35− "contentType": "text"
35+ "content-type": "text"
36− }
37−
38− property var shareDataNoUri: {
39− "uri": "",
40− "contentType": "text"
41 }
36 }
42
37
43 PreviewSharing {
38 PreviewSharing {
@@ -54,13 +49,6 @@ Rectangle {
54
49
55 function cleanup() {
50 function cleanup() {
56 peerPicker.visible = false;
51 peerPicker.visible = false;
57− previewSharing.shareData = root.shareData;
58− }
59−
60− function test_visible() {
61− compare(previewSharing.visible, true);
62− previewSharing.shareData = shareDataNoUri;
63− compare(previewSharing.visible, false);
64 }
52 }
65
53
66 function test_open_picker() {
54 function test_open_picker() {
tests/qmltests/Greeter/tst_Greeter.qml+39−3
@@ -71,9 +71,9 @@ Item {
71 }
71 }
72
72
73 SignalSpy {
73 SignalSpy {
74− id: emergencyCallSpy
74+ id: activeChangedSpy
75 target: loader.item
75 target: loader.item
76− signalName: "emergencyCall"
76+ signalName: "activeChanged"
77 }
77 }
78
78
79 GSettings {
79 GSettings {
@@ -142,7 +142,7 @@ Item {
142 resetLoader();
142 resetLoader();
143 teaseSpy.clear();
143 teaseSpy.clear();
144 sessionStartedSpy.clear();
144 sessionStartedSpy.clear();
145− emergencyCallSpy.clear();
145+ activeChangedSpy.clear();
146 viewShowMessageSpy.clear();
146 viewShowMessageSpy.clear();
147 viewShowPromptSpy.clear();
147 viewShowPromptSpy.clear();
148 viewShowLastChanceSpy.clear();
148 viewShowLastChanceSpy.clear();
@@ -458,6 +458,20 @@ Item {
458 compare(view.delayMinutes, greeter.failedLoginsDelayMinutes);
458 compare(view.delayMinutes, greeter.failedLoginsDelayMinutes);
459 }
459 }
460
460
461+ function test_forcedDelayOnConstructionIgnoredIfInFuture() {
462+ greeterSettings.lockedOutTime = new Date().getTime() + greeter.failedLoginsDelayMinutes * 60000 + 1;
463+ resetLoader();
464+ view = findChild(greeter, "testView");
465+ compare(view.delayMinutes, 0);
466+ }
467+
468+ function test_forcedDelayOnConstructionIgnoredIfInPast() {
469+ greeterSettings.lockedOutTime = new Date().getTime() - greeter.failedLoginsDelayMinutes * 60000 - 1;
470+ resetLoader();
471+ view = findChild(greeter, "testView");
472+ compare(view.delayMinutes, 0);
473+ }
474+
461 function test_forcedDelayRoundTrip() {
475 function test_forcedDelayRoundTrip() {
462 greeter.failedLoginsDelayAttempts = 1;
476 greeter.failedLoginsDelayAttempts = 1;
463 greeter.failedLoginsDelayMinutes = 0.001; // make delay very short
477 greeter.failedLoginsDelayMinutes = 0.001; // make delay very short
@@ -471,6 +485,28 @@ Item {
471 tryCompare(view, "delayMinutes", 0);
485 tryCompare(view, "delayMinutes", 0);
472 }
486 }
473
487
488+ function test_activeIsConstantDuringLockedApp() {
489+ // Regression test for bug 1525981: if we flicker active state even
490+ // briefly, the mpt-server will allow access to the device's drive.
491+
492+ selectUser("has-password");
493+ verify(greeter.active);
494+
495+ // Test opening a locked app
496+ greeter.lockedApp = "test-app";
497+ greeter.notifyAppFocused("test-app");
498+ verify(greeter.hasLockedApp);
499+ verify(!greeter.shown);
500+
501+ // Test going back to greeter from that locked app
502+ LightDM.Greeter.showGreeter();
503+ verify(!greeter.hasLockedApp);
504+ verify(greeter.shown);
505+
506+ // Active state should never have changed
507+ compare(activeChangedSpy.count, 0);
508+ }
509+
474 function test_dbusRequestAuthenticationUser() {
510 function test_dbusRequestAuthenticationUser() {
475 selectUser("no-password");
511 selectUser("no-password");
476 LightDM.Greeter.requestAuthenticationUser("has-password");
512 LightDM.Greeter.requestAuthenticationUser("has-password");
tests/qmltests/Launcher/tst_Launcher.qml+16
@@ -625,6 +625,7 @@ Item {
625 if(data.mouse) {
625 if(data.mouse) {
626 mouseClick(root)
626 mouseClick(root)
627 } else {
627 } else {
628+ touchRelease(draggedItem)
628 tap(root)
629 tap(root)
629 }
630 }
630
631
@@ -739,6 +740,21 @@ Item {
739 mouseRelease(draggedItem);
740 mouseRelease(draggedItem);
740 }
741 }
741
742
743+ function test_launcher_dismiss() {
744+ dragLauncherIntoView();
745+ verify(launcher.state == "visible");
746+ mouseClick(root);
747+ waitUntilLauncherDisappears();
748+ verify(launcher.state == "");
749+
750+ // and repeat, as a test for regression in lpbug#1531339
751+ dragLauncherIntoView();
752+ verify(launcher.state == "visible");
753+ mouseClick(root);
754+ waitUntilLauncherDisappears();
755+ verify(launcher.state == "");
756+ }
757+
742 function test_quicklist_positioning_data() {
758 function test_quicklist_positioning_data() {
743 return [
759 return [
744 {tag: "top", flickTo: "top", itemIndex: 0},
760 {tag: "top", flickTo: "top", itemIndex: 0},
tests/qmltests/Stages/tst_DesktopStage.qml+29
@@ -25,6 +25,7 @@ import Utils 0.1
25import ".." // For EdgeBarrierControls
25import ".." // For EdgeBarrierControls
26import "../../../qml/Stages"
26import "../../../qml/Stages"
27import "../../../qml/Components"
27import "../../../qml/Components"
28+import "../../../qml/Components/PanelState"
28
29
29Item {
30Item {
30 id: root
31 id: root
@@ -500,5 +501,33 @@ Item {
500 tryCompare(dialerAppDelegate, "visible", true);
501 tryCompare(dialerAppDelegate, "visible", true);
501 tryCompare(facebookAppDelegate, "visible", false);
502 tryCompare(facebookAppDelegate, "visible", false);
502 }
503 }
504+
505+ function test_dropShadow() {
506+ killAllRunningApps();
507+
508+ // verify the drop shadow is not visible initially
509+ verify(PanelState.dropShadow == false);
510+
511+ // start an app, maximize it
512+ var facebookApp = startApplication("facebook-webapp");
513+ var facebookAppDelegate = findChild(desktopStage, "appDelegate_facebook-webapp");
514+ facebookAppDelegate.maximize();
515+
516+ // verify the drop shadow is still not visible
517+ verify(PanelState.dropShadow == false);
518+
519+ // start a foreground app, not maximized
520+ var dialerApp = startApplication("dialer-app");
521+ var dialerAppDelegate = findChild(desktopStage, "appDelegate_dialer-app");
522+
523+ // verify the drop shadow becomes visible
524+ verify(PanelState.dropShadow == true);
525+
526+ // close the maximized app
527+ ApplicationManager.stopApplication("facebook-webapp");
528+
529+ // verify the drop shadow is gone
530+ verify(PanelState.dropShadow == false);
531+ }
503 }
532 }
504}
533}
tests/qmltests/Wizard/tst_Wizard.qml+15
@@ -129,6 +129,7 @@ Item {
129
129
130 var pages = findChild(wizard, "wizardPages");
130 var pages = findChild(wizard, "wizardPages");
131 var security = findInvisibleChild(pages, "securityPrivacy");
131 var security = findInvisibleChild(pages, "securityPrivacy");
132+ security.setSecurity("", "", UbuntuSecurityPrivacyPanel.Swipe);
132 setSecuritySpy.target = security;
133 setSecuritySpy.target = security;
133
134
134 setup();
135 setup();
@@ -315,6 +316,20 @@ Item {
315 }
316 }
316 }
317 }
317
318
319+ function test_passwdSkipIfSet() {
320+ var page = goToPage("simPage");
321+
322+ // Set password type to non-swipe
323+ var pages = findChild(wizard, "wizardPages");
324+ var security = findInvisibleChild(pages, "securityPrivacy");
325+ security.setSecurity("", "", UbuntuSecurityPrivacyPanel.Passphrase);
326+ compare(security.securityType, UbuntuSecurityPrivacyPanel.Passphrase);
327+
328+ // Make sure that moving from sim page lands on wifi page
329+ tap(findChild(page, "forwardButton"));
330+ waitForPage("wifiPage"); // thus skipping passwdPage
331+ }
332+
318 function test_passwdPasscode() {
333 function test_passwdPasscode() {
319 var page = goToPage("passwdPage");
334 var page = goToPage("passwdPage");
320
335
tests/utils/modules/Unity/Test/CMakeLists.txt+7−1
@@ -15,13 +15,19 @@ set(UnityTestQML_SOURCES
15 testutil.cpp
15 testutil.cpp
16 plugin.cpp
16 plugin.cpp
17 TouchEventSequenceWrapper.cpp
17 TouchEventSequenceWrapper.cpp
18− ${CMAKE_SOURCE_DIR}/src/MouseTouchAdaptor.cpp
19)
18)
20
19
20+if (ENABLE_TOUCH_EMULATION)
21+ set(UnityTestQML_SOURCES ${UnityTestQML_SOURCES} ${CMAKE_SOURCE_DIR}/src/MouseTouchAdaptor.cpp)
22+endif()
21
23
22add_library(UnityTestQml MODULE ${UnityTestQML_SOURCES})
24add_library(UnityTestQml MODULE ${UnityTestQML_SOURCES})
23target_link_libraries(UnityTestQml ${UBUNTUGESTURES_LIBRARIES})
25target_link_libraries(UnityTestQml ${UBUNTUGESTURES_LIBRARIES})
24
26
27+if (ENABLE_TOUCH_EMULATION)
28+ target_link_libraries(UnityTestQml ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
29+endif()
30+
25qt5_use_modules(UnityTestQml Core Quick Test)
31qt5_use_modules(UnityTestQml Core Quick Test)
26
32
27export_qmlfiles(Unity.Test Unity/Test)
33export_qmlfiles(Unity.Test Unity/Test)
tests/utils/modules/Unity/Test/plugin.cpp+13−3
@@ -17,7 +17,11 @@
17
17
18#include "plugin.h"
18#include "plugin.h"
19#include "testutil.h"
19#include "testutil.h"
20+
21+#ifdef UNITY8_ENABLE_TOUCH_EMULATION
20#include <MouseTouchAdaptor.h>
22#include <MouseTouchAdaptor.h>
23+#endif
24+
21#include "TouchEventSequenceWrapper.h"
25#include "TouchEventSequenceWrapper.h"
22
26
23#include <qqml.h>
27#include <qqml.h>
@@ -27,23 +31,29 @@ QObject *testutil_provider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine
27{
31{
28 return new TestUtil();
32 return new TestUtil();
29}
33}
34+
35+#ifdef UNITY8_ENABLE_TOUCH_EMULATION
30QObject *getMouseTouchAdaptorQMLSingleton(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
36QObject *getMouseTouchAdaptorQMLSingleton(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
31{
37{
32 return MouseTouchAdaptor::instance();
38 return MouseTouchAdaptor::instance();
33}
39}
40+#endif
41+
34} // anonymous namespace
42} // anonymous namespace
35
43
36void UnityTestPlugin::registerTypes(const char *uri)
44void UnityTestPlugin::registerTypes(const char *uri)
37{
45{
38 Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Test"));
46 Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Test"));
39
47
40− // Ensure the instance gets created
41− MouseTouchAdaptor::instance();
42−
43 // @uri Unity.Test
48 // @uri Unity.Test
44 qmlRegisterSingletonType<TestUtil>(uri, 0, 1, "Util", testutil_provider);
49 qmlRegisterSingletonType<TestUtil>(uri, 0, 1, "Util", testutil_provider);
45 qmlRegisterUncreatableType<TouchEventSequenceWrapper>(uri, 0, 1, "TouchEventSequence",
50 qmlRegisterUncreatableType<TouchEventSequenceWrapper>(uri, 0, 1, "TouchEventSequence",
46 "You cannot directly create a TouchEventSequence object.");
51 "You cannot directly create a TouchEventSequence object.");
52+
53+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
54+ // Ensure the instance gets created
55+ MouseTouchAdaptor::instance();
47 qmlRegisterSingletonType<MouseTouchAdaptor>(uri, 0, 1, "MouseTouchAdaptor",
56 qmlRegisterSingletonType<MouseTouchAdaptor>(uri, 0, 1, "MouseTouchAdaptor",
48 getMouseTouchAdaptorQMLSingleton);
57 getMouseTouchAdaptorQMLSingleton);
58+ #endif
49}
59}