on xenial help sign in
Merge
commit2d3318100e351e736f4bf8a6d400bb74040d54a6 authorAlbert Astals Cid <albert.astals@canonical.com> dateWed 13 Jan 2016, 17:59 (11 years ago) parentb80c4c76976414
44 files changed+656−144
CMakeLists.txt+10 debian/changelog+51 debian/control+5−1 debian/rules−4 plugins/Dash/listviewwithpageheader.cpp+5−1 plugins/Unity/DashCommunicator/dashcommunicator.cpp+6 plugins/Unity/DashCommunicator/dashcommunicator.h+1−1 po/unity8.pot+27−27 qml/Dash/DashPageHeader.qml+1 qml/Dash/Previews/PreviewMediaToolbar.qml+2−1 qml/Dash/Previews/PreviewSharing.qml+3−4 qml/Dash/Previews/PreviewVideoPlayback.qml+1−1 qml/Dash/Previews/PreviewZoomableImage.qml+1−1 qml/Greeter/Greeter.qml+7−4 qml/Launcher/Launcher.qml+4−9 qml/Launcher/LauncherPanel.qml+6−3 qml/Panel/Indicators/MenuItemFactory.qml+11−1 qml/Stages/DesktopStage.qml+7−3 qml/Wizard/Pages/30-passwd-type.qml+5 src/CMakeLists.txt+13−7 src/Dash/CMakeLists.txt+8−8 src/Dash/main.cpp+9−5 src/MouseTouchAdaptor.cpp+180−21 src/MouseTouchAdaptor.h+10−3 src/ShellApplication.cpp+5−5 src/ShellApplication.h+12−4 src/UnityCommandLineParser.cpp+6 src/UnityCommandLineParser.h+8 tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/CMakeLists.txt+1−1 tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.cpp+8−1 tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.h+8 tests/plugins/Dash/cardcreator/9.res+1 tests/qmltests/CMakeLists.txt+2−1 tests/qmltests/Components/CMakeLists.txt+1−1 tests/qmltests/Components/tst_DragHandle.qml+6−6 tests/qmltests/Components/tst_DragHandle/SimpleButton.qml+36 tests/qmltests/Dash/Previews/tst_PreviewMediaToolbar.qml+69 tests/qmltests/Dash/Previews/tst_PreviewSharing.qml+1−13 tests/qmltests/Greeter/tst_Greeter.qml+39−3 tests/qmltests/Launcher/tst_Launcher.qml+16 tests/qmltests/Stages/tst_DesktopStage.qml+29 tests/qmltests/Wizard/tst_Wizard.qml+15 tests/utils/modules/Unity/Test/CMakeLists.txt+7−1 tests/utils/modules/Unity/Test/plugin.cpp+13−3
CMakeLists.txt+10
@@ -128,6 +128,16 @@ if(NOT QUIET_LOGGER)
128128 set(STDOUT_LOGGER "-o" "-,txt")
129129endif()
130130
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+
131141# add subdirectories to build
132142add_subdirectory(include)
133143add_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+
152unity8 (8.11+16.04.20160107-0ubuntu1) xenial; urgency=medium
253
354 [ Albert Astals Cid ]
debian/control+5−1
@@ -32,7 +32,11 @@ Build-Depends: cmake,
3232 libudev-dev,
3333 libunity-api-dev (>= 7.105),
3434 libusermetricsoutput1-dev,
35− libxcb1-dev,
35+# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
36+ libx11-dev[!armhf],
37+ libxcb1-dev[!armhf],
38+ libxi-dev[!armhf],
39+# End of X11 libs
3640 pkg-config,
3741 python3-all:any,
3842 python3-setuptools,
debian/rules−4
@@ -11,10 +11,6 @@ export NO_PNG_PKG_MANGLE=1
1111%:
1212 dh $@ --parallel --fail-missing --with python3
1313
14−override_dh_auto_clean:
15− dh_auto_clean
16− rm -rf builddir
17−
1814override_dh_auto_configure:
1915 # Debian defines CMAKE_INSTALL_LOCALSTATEDIR as /usr/var, which is wrong.
2016 # 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
11771177
11781178void ListViewWithPageHeader::adjustMinYExtent()
11791179{
1180− if (m_visibleItems.isEmpty()) {
1180+ if (m_visibleItems.isEmpty() || contentHeight() < height()) {
11811181 m_minYExtent = 0;
11821182 } else {
11831183 qreal nonCreatedHeight = 0;
@@ -1359,6 +1359,10 @@ void ListViewWithPageHeader::updatePolish()
13591359
13601360 m_contentHeightDirty = false;
13611361 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+ }
13621366 m_inContentHeightKeepHeaderShown = m_headerItem && m_headerItem->y() == contentY();
13631367 setContentHeight(contentHeight);
13641368 m_inContentHeightKeepHeaderShown = false;
plugins/Unity/DashCommunicator/dashcommunicator.cpp+6
@@ -27,6 +27,12 @@ DashCommunicator::DashCommunicator(QObject *parent):
2727 start();
2828}
2929
30+DashCommunicator::~DashCommunicator()
31+{
32+ quit();
33+ wait();
34+}
35+
3036void DashCommunicator::setCurrentScope(int index, bool animate, bool isSwipe)
3137{
3238 m_mutex.lock();
plugins/Unity/DashCommunicator/dashcommunicator.h+1−1
@@ -28,7 +28,7 @@ class DashCommunicator: public QThread
2828 Q_OBJECT
2929public:
3030 explicit DashCommunicator(QObject *parent = 0);
31− ~DashCommunicator() = default;
31+ ~DashCommunicator();
3232
3333public Q_SLOTS:
3434 void setCurrentScope(int index, bool animate, bool isSwipe);
po/unity8.pot+27−27
@@ -8,7 +8,7 @@ msgid ""
88msgstr ""
99"Project-Id-Version: unity8\n"
1010"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"
1212"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
1313"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
1414"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -171,26 +171,26 @@ msgstr ""
171171msgid "Close all"
172172msgstr ""
173173
174−#: qml/Dash/DashPageHeader.qml:265
174+#: qml/Dash/DashPageHeader.qml:266
175175msgctxt "Button: Open the Ubuntu Store"
176176msgid "Store"
177177msgstr ""
178178
179−#: qml/Dash/DashPageHeader.qml:272
179+#: qml/Dash/DashPageHeader.qml:273
180180msgctxt "Button: Start a search in the current dash scope"
181181msgid "Search"
182182msgstr ""
183183
184−#: qml/Dash/DashPageHeader.qml:282
184+#: qml/Dash/DashPageHeader.qml:283
185185msgctxt "Button: Show the current dash scope settings"
186186msgid "Settings"
187187msgstr ""
188188
189−#: qml/Dash/DashPageHeader.qml:289
189+#: qml/Dash/DashPageHeader.qml:290
190190msgid "Remove from Favorites"
191191msgstr ""
192192
193−#: qml/Dash/DashPageHeader.qml:289
193+#: qml/Dash/DashPageHeader.qml:290
194194msgid "Add to Favorites"
195195msgstr ""
196196
@@ -228,7 +228,7 @@ msgstr ""
228228msgid "Add a review"
229229msgstr ""
230230
231−#: qml/Dash/Previews/PreviewSharing.qml:51
231+#: qml/Dash/Previews/PreviewSharing.qml:50
232232msgid "Preview Share Item"
233233msgstr ""
234234
@@ -339,62 +339,62 @@ msgstr ""
339339msgid "Conference"
340340msgstr ""
341341
342−#: qml/Panel/Indicators/MenuItemFactory.qml:743
342+#: qml/Panel/Indicators/MenuItemFactory.qml:753
343343msgid "Nothing is playing"
344344msgstr ""
345345
346−#: qml/Panel/Indicators/MenuItemFactory.qml:872
346+#: qml/Panel/Indicators/MenuItemFactory.qml:882
347347#, qt-format
348348msgid "%1 hour"
349349msgid_plural "%1 hours"
350350msgstr[0] ""
351351msgstr[1] ""
352352
353−#: qml/Panel/Indicators/MenuItemFactory.qml:876
353+#: qml/Panel/Indicators/MenuItemFactory.qml:886
354354#, qt-format
355355msgid "%1 minute"
356356msgid_plural "%1 minutes"
357357msgstr[0] ""
358358msgstr[1] ""
359359
360−#: qml/Panel/Indicators/MenuItemFactory.qml:881
360+#: qml/Panel/Indicators/MenuItemFactory.qml:891
361361#, qt-format
362362msgid "%1 second"
363363msgid_plural "%1 seconds"
364364msgstr[0] ""
365365msgstr[1] ""
366366
367−#: qml/Panel/Indicators/MenuItemFactory.qml:884
367+#: qml/Panel/Indicators/MenuItemFactory.qml:894
368368msgid "0 seconds"
369369msgstr ""
370370
371371#. Translators: String like "1 hour, 2 minutes, 3 seconds remaining"
372−#: qml/Panel/Indicators/MenuItemFactory.qml:886
372+#: qml/Panel/Indicators/MenuItemFactory.qml:896
373373#, qt-format
374374msgid "%1 remaining"
375375msgstr ""
376376
377−#: qml/Panel/Indicators/MenuItemFactory.qml:892
377+#: qml/Panel/Indicators/MenuItemFactory.qml:902
378378msgid "In queue…"
379379msgstr ""
380380
381−#: qml/Panel/Indicators/MenuItemFactory.qml:896
381+#: qml/Panel/Indicators/MenuItemFactory.qml:906
382382msgid "Downloading"
383383msgstr ""
384384
385−#: qml/Panel/Indicators/MenuItemFactory.qml:898
385+#: qml/Panel/Indicators/MenuItemFactory.qml:908
386386msgid "Paused, tap to resume"
387387msgstr ""
388388
389−#: qml/Panel/Indicators/MenuItemFactory.qml:900
389+#: qml/Panel/Indicators/MenuItemFactory.qml:910
390390msgid "Canceled"
391391msgstr ""
392392
393−#: qml/Panel/Indicators/MenuItemFactory.qml:902
393+#: qml/Panel/Indicators/MenuItemFactory.qml:912
394394msgid "Finished"
395395msgstr ""
396396
397−#: qml/Panel/Indicators/MenuItemFactory.qml:904
397+#: qml/Panel/Indicators/MenuItemFactory.qml:914
398398msgid "Failed, tap to retry"
399399msgstr ""
400400
@@ -492,7 +492,7 @@ msgstr ""
492492msgid "Let’s get started."
493493msgstr ""
494494
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
496496#: qml/Wizard/Pages/40-wifi.qml:215 qml/Wizard/Pages/50-location.qml:131
497497#: qml/Wizard/Pages/60-reporting.qml:60 qml/Wizard/Pages/passwd-confirm.qml:82
498498#: qml/Wizard/Pages/passwd-set.qml:90
@@ -515,36 +515,36 @@ msgstr ""
515515msgid "Lock security"
516516msgstr ""
517517
518−#: qml/Wizard/Pages/30-passwd-type.qml:74
518+#: qml/Wizard/Pages/30-passwd-type.qml:79
519519msgid "Please select how you’d like to unlock your phone."
520520msgstr ""
521521
522−#: qml/Wizard/Pages/30-passwd-type.qml:97
522+#: qml/Wizard/Pages/30-passwd-type.qml:102
523523msgctxt "Label: Type of security method"
524524msgid "Swipe"
525525msgstr ""
526526
527−#: qml/Wizard/Pages/30-passwd-type.qml:98
527+#: qml/Wizard/Pages/30-passwd-type.qml:103
528528msgctxt "Label: Description of security method"
529529msgid "No security"
530530msgstr ""
531531
532−#: qml/Wizard/Pages/30-passwd-type.qml:100
532+#: qml/Wizard/Pages/30-passwd-type.qml:105
533533msgctxt "Label: Type of security method"
534534msgid "Passcode"
535535msgstr ""
536536
537−#: qml/Wizard/Pages/30-passwd-type.qml:101
537+#: qml/Wizard/Pages/30-passwd-type.qml:106
538538msgctxt "Label: Description of security method"
539539msgid "4 digits only"
540540msgstr ""
541541
542−#: qml/Wizard/Pages/30-passwd-type.qml:103
542+#: qml/Wizard/Pages/30-passwd-type.qml:108
543543msgctxt "Label: Type of security method"
544544msgid "Passphrase"
545545msgstr ""
546546
547−#: qml/Wizard/Pages/30-passwd-type.qml:104
547+#: qml/Wizard/Pages/30-passwd-type.qml:109
548548msgctxt "Label: Description of security method"
549549msgid "Numbers and letters"
550550msgstr ""
qml/Dash/DashPageHeader.qml+1
@@ -102,6 +102,7 @@ Item {
102102 "edgeMargins": units.gu(1)
103103 }
104104 );
105+ searchTextField.forceActiveFocus();
105106 }
106107 }
107108
qml/Dash/Previews/PreviewMediaToolbar.qml+2−1
@@ -23,10 +23,11 @@ Rectangle {
2323
2424 implicitHeight: units.gu(6)
2525 color: Qt.rgba(0, 0, 0, 0.8)
26− visible: sharingWidget.visible
26+ visible: sharingWidget.active
2727
2828 PreviewSharing {
2929 id: sharingWidget
30+ objectName: "sharingWidget"
3031 anchors {
3132 left: parent.left
3233 verticalCenter: parent.verticalCenter
qml/Dash/Previews/PreviewSharing.qml+3−4
@@ -24,13 +24,12 @@ Item {
2424 implicitWidth: button.width
2525
2626 property var shareData
27+ property alias active: peerPicker.active
2728 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"] : ""
2930 readonly property var url: shareData ? shareData["uri"] : ""
3031 readonly property Item rootItem: QuickUtils.rootItem(root)
3132
32− visible: url != ""
33−
3433 AbstractButton {
3534 id: button
3635 height: units.gu(4)
@@ -98,7 +97,7 @@ Item {
9897 parent: rootItem
9998 anchors.fill: parent
10099 visible: false
101− active: root.visible
100+ active: root.url != ""
102101
103102 sourceComponent: contentPeerComponent
104103 }
qml/Dash/Previews/PreviewVideoPlayback.qml+1−1
@@ -81,7 +81,7 @@ PreviewWidget {
8181 right: parent.right
8282 bottom: parent.bottom
8383 }
84− shareData: widgetData["shareData"]
84+ shareData: widgetData["share-data"]
8585 }
8686 }
8787}
qml/Dash/Previews/PreviewZoomableImage.qml+1−1
@@ -72,7 +72,7 @@ PreviewWidget {
7272 right: parent.right
7373 bottom: parent.bottom
7474 }
75− shareData: widgetData["shareData"]
75+ shareData: widgetData["share-data"]
7676 }
7777 }
7878
qml/Greeter/Greeter.qml+7−4
@@ -33,7 +33,7 @@ Showable {
3333 // How far to offset the top greeter layer during a launcher left-drag
3434 property real launcherOffset
3535
36− readonly property bool active: shown || hasLockedApp
36+ readonly property bool active: required || hasLockedApp
3737 readonly property bool fullyShown: loader.item ? loader.item.fullyShown : false
3838
3939 // True when the greeter is waiting for PAM or other setup process
@@ -226,14 +226,17 @@ Showable {
226226 }
227227
228228 function checkForForcedDelay() {
229+ if (greeterSettings.lockedOutTime === 0) {
230+ return;
231+ }
232+
229233 var now = new Date();
230− delayTarget = now;
231− delayTarget.setTime(greeterSettings.lockedOutTime + failedLoginsDelayMinutes * 60000);
234+ delayTarget = new Date(greeterSettings.lockedOutTime + failedLoginsDelayMinutes * 60000);
232235
233236 // If tooEarly is true, something went very wrong. Bug or NTP
234237 // misconfiguration maybe?
235238 var tooEarly = now.getTime() < greeterSettings.lockedOutTime;
236− var tooLate = now > delayTarget;
239+ var tooLate = now >= delayTarget;
237240
238241 // Compare stored time to system time. If a malicious actor is
239242 // able to manipulate time to avoid our lockout, they already have
qml/Launcher/Launcher.qml+4−9
@@ -184,18 +184,13 @@ Item {
184184 }
185185 }
186186
187− MultiPointTouchArea {
187+ InverseMouseArea {
188188 id: closeMouseArea
189− anchors {
190− left: launcherDragArea.right
191− top: parent.top
192− right: parent.right
193− bottom: parent.bottom
194− }
189+ anchors.fill: panel
195190 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
197192 onPressed: {
198− root.state = ""
193+ root.hide();
199194 }
200195 }
201196
qml/Launcher/LauncherPanel.qml+6−3
@@ -392,7 +392,6 @@ Rectangle {
392392 }
393393
394394 onClicked: {
395− Haptics.play();
396395 var index = Math.floor((mouseY + launcherListView.realContentY) / launcherListView.realItemHeight);
397396 var clickedItem = launcherListView.itemAt(mouseX, mouseY + launcherListView.realContentY)
398397
@@ -407,9 +406,11 @@ Rectangle {
407406 quickList.model = launcherListView.model.get(index).quickList;
408407 quickList.appId = launcherListView.model.get(index).appId;
409408 quickList.state = "open";
410− return
409+ return;
411410 }
412411
412+ Haptics.play();
413+
413414 // First/last item do the scrolling at more than 12 degrees
414415 if (index == 0 || index == launcherListView.count - 1) {
415416 if (clickedItem.angle > 12) {
@@ -594,6 +595,7 @@ Rectangle {
594595 width: itemWidth
595596 rotation: root.rotation
596597 itemOpacity: 0.9
598+ onVisibleChanged: if (!visible) iconName = "";
597599
598600 function flatten() {
599601 fakeDragItemAnimation.start();
@@ -636,6 +638,7 @@ Rectangle {
636638 rotation: 90
637639 }
638640 }
641+
639642 InverseMouseArea {
640643 anchors.fill: quickListShape
641644 enabled: quickList.state == "open" || pressed
@@ -692,7 +695,7 @@ Rectangle {
692695 property var item
693696
694697 // 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)
696699 property int offset: itemCenter + (height/2) + units.gu(1) > parent.height ? -itemCenter - (height/2) - units.gu(1) + parent.height :
697700 itemCenter - (height/2) < units.gu(1) ? (height/2) - itemCenter + units.gu(1) : 0
698701
qml/Panel/Indicators/MenuItemFactory.qml+11−1
@@ -576,7 +576,17 @@ Item {
576576 active: serverChecked
577577 secure: getExtendedProperty(extendedData, "xCanonicalWifiApIsSecure", false)
578578 adHoc: getExtendedProperty(extendedData, "xCanonicalWifiApIsAdhoc", false)
579− signalStrength: strengthAction.valid ? strengthAction.state : 0
579+ signalStrength: {
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+ }
580590 highlightWhenPressed: false
581591
582592 onMenuModelChanged: {
qml/Stages/DesktopStage.qml+7−3
@@ -124,16 +124,20 @@ AbstractStage {
124124 onFocusedAppDelegateChanged: updateForegroundMaximizedApp();
125125
126126 property int foregroundMaximizedAppZ: -1
127+ property int foregroundMaximizedAppIndex: -1 // for stuff like drop shadow and focusing maximized app by clicking panel
127128
128129 function updateForegroundMaximizedApp() {
129130 var tmp = -1;
131+ var tmpAppId = -1;
130132 for (var i = appRepeater.count - 1; i >= 0; i--) {
131133 var item = appRepeater.itemAt(i);
132134 if (item && item.visuallyMaximized) {
135+ tmpAppId = i;
133136 tmp = Math.max(tmp, item.normalZ);
134137 }
135138 }
136139 foregroundMaximizedAppZ = tmp;
140+ foregroundMaximizedAppIndex = tmpAppId;
137141 }
138142
139143 function indexOf(appId) {
@@ -176,8 +180,8 @@ AbstractStage {
176180 onMinimize: priv.focusedAppDelegate && priv.focusedAppDelegate.minimize();
177181 onMaximize: priv.focusedAppDelegate // don't restore minimized apps when double clicking the panel
178182 && priv.focusedAppDelegate.restoreFromMaximized();
179− onFocusMaximizedApp: if (priv.foregroundMaximizedAppIdIndex != -1) {
180− ApplicationManager.focusApplication(appRepeater.itemAt(priv.foregroundMaximizedAppIdIndex).appId);
183+ onFocusMaximizedApp: if (priv.foregroundMaximizedAppIndex != -1) {
184+ ApplicationManager.focusApplication(appRepeater.itemAt(priv.foregroundMaximizedAppIndex).appId);
181185 }
182186 }
183187
@@ -206,7 +210,7 @@ AbstractStage {
206210 Binding {
207211 target: PanelState
208212 property: "dropShadow"
209− value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppIdIndex !== -1
213+ value: priv.focusedAppDelegate && !priv.focusedAppDelegate.maximized && priv.foregroundMaximizedAppIndex !== -1
210214 }
211215
212216 Component.onDestruction: {
qml/Wizard/Pages/30-passwd-type.qml+5
@@ -39,6 +39,11 @@ LocalComponents.Page {
3939 title: i18n.tr("Lock security")
4040 forwardButtonSourceComponent: forwardButton
4141
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+
4247 function indexToMethod(index) {
4348 if (index === 0)
4449 return UbuntuSecurityPrivacyPanel.Swipe
src/CMakeLists.txt+13−7
@@ -15,10 +15,9 @@ file(GLOB_RECURSE QML_FILES
1515 ${CMAKE_SOURCE_DIR}/tests/*.svg
1616)
1717
18−add_executable(${SHELL_APP}
18+set(SOURCE_FILES
1919 ApplicationArguments.cpp
2020 main.cpp
21− MouseTouchAdaptor.cpp
2221 CachingNetworkManagerFactory.cpp
2322 SecondaryWindow.cpp
2423 ShellApplication.cpp
@@ -27,15 +26,22 @@ add_executable(${SHELL_APP}
2726 ${QML_FILES} # This is to make qml and image files appear in the IDE's project tree
2827)
2928
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})
3035qt5_use_modules(${SHELL_APP} Gui Qml Quick Test)
3136
32−pkg_check_modules(NEEDED_LIBS REQUIRED xcb libandroid-properties)
33−if (NOT "${NEEDED_LIBS_INCLUDE_DIRS}" STREQUAL "")
34− set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${NEEDED_LIBS_INCLUDE_DIRS})
37+if (NOT "${ANDROID_PROPERTIES_INCLUDE_DIRS}" STREQUAL "")
38+ set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${ANDROID_PROPERTIES_INCLUDE_DIRS})
3539endif()
36−target_link_libraries(${SHELL_APP} ${NEEDED_LIBS_LDFLAGS})
40+target_link_libraries(${SHELL_APP} ${ANDROID_PROPERTIES_LDFLAGS} UbuntuGestures connectivity-qt1)
3741
38−target_link_libraries(${SHELL_APP} UbuntuGestures connectivity-qt1)
42+if (ENABLE_TOUCH_EMULATION)
43+ target_link_libraries(${SHELL_APP} ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
44+endif()
3945
4046# install binaries
4147install(TARGETS ${SHELL_APP}
src/Dash/CMakeLists.txt+8−8
@@ -1,25 +1,25 @@
11set(DASH_SRCS
22 main.cpp
3− ../ApplicationArguments.cpp
4− ../MouseTouchAdaptor.cpp
53 ../CachingNetworkManagerFactory.cpp
64)
75
6+if (ENABLE_TOUCH_EMULATION)
7+ set(DASH_SRCS ${DASH_SRCS} ../MouseTouchAdaptor.cpp)
8+endif()
9+
810add_executable(unity8-dash ${DASH_SRCS})
911
1012qt5_use_modules(unity8-dash Gui Qml Quick Test)
1113
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−
1814# For it to find libUbuntuGestures.so, needed by Ubuntu.Gestures QML module.
1915set_target_properties(unity8-dash PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}")
2016
2117target_link_libraries(unity8-dash UbuntuGestures connectivity-qt1)
2218
19+if (ENABLE_TOUCH_EMULATION)
20+ target_link_libraries(unity8-dash ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
21+endif()
22+
2323set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
2424
2525# install binaries
src/Dash/main.cpp+9−5
@@ -27,8 +27,9 @@
2727#include <libintl.h>
2828
2929#include <paths.h>
30−#include "../MouseTouchAdaptor.h"
31−#include "../ApplicationArguments.h"
30+#ifdef UNITY8_ENABLE_TOUCH_EMULATION
31+ #include "../MouseTouchAdaptor.h"
32+#endif
3233#include "../CachingNetworkManagerFactory.h"
3334
3435int main(int argc, const char *argv[])
@@ -57,8 +58,6 @@ int main(int argc, const char *argv[])
5758 parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions);
5859 parser.process(*application);
5960
60− ApplicationArguments qmlArgs;
61−
6261 if (getenv("QT_LOAD_TESTABILITY")) {
6362 QLibrary testLib(QStringLiteral("qttestability"));
6463 if (testLib.load()) {
@@ -92,14 +91,15 @@ int main(int argc, const char *argv[])
9291 }
9392
9493 view->setTitle(QStringLiteral("Scopes"));
95− view->rootContext()->setContextProperty(QStringLiteral("applicationArguments"), &qmlArgs);
9694
95+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
9796 // You will need this if you want to interact with touch-only components using a mouse
9897 // Needed only when manually testing on a desktop.
9998 MouseTouchAdaptor *mouseTouchAdaptor = 0;
10099 if (parser.isSet(mousetouchOption)) {
101100 mouseTouchAdaptor = MouseTouchAdaptor::instance();
102101 }
102+ #endif
103103
104104 QUrl source(::qmlDirectory() + "/Dash/DashApplication.qml");
105105 prependImportPaths(view->engine(), ::overrideImportPaths());
@@ -114,7 +114,11 @@ int main(int argc, const char *argv[])
114114 int result = application->exec();
115115
116116 delete view;
117+
118+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
117119 delete mouseTouchAdaptor;
120+ #endif
121+
118122 delete application;
119123
120124 return result;
src/MouseTouchAdaptor.cpp+180−21
@@ -16,14 +16,56 @@
1616 * Authored by: Daniel d'Andrada <daniel.dandrada@canonical.com>
1717 */
1818
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+
1957#include "MouseTouchAdaptor.h"
2058
59+#include <qpa/qplatformnativeinterface.h>
2160#include <qpa/qwindowsysteminterface.h>
2261
2362#include <QCoreApplication>
2463#include <QMouseEvent>
2564#include <QTest>
2665
66+#include <X11/extensions/XInput2.h>
67+#include <X11/extensions/XI2proto.h>
68+
2769using QTest::QTouchEventSequence;
2870
2971namespace {
@@ -49,6 +91,8 @@ MouseTouchAdaptor::MouseTouchAdaptor()
4991 m_touchDevice = new QTouchDevice;
5092 m_touchDevice->setType(QTouchDevice::TouchScreen);
5193 QWindowSystemInterface::registerTouchDevice(m_touchDevice);
94+
95+ fetchXInput2Info();
5296}
5397
5498MouseTouchAdaptor::~MouseTouchAdaptor()
@@ -65,9 +109,114 @@ MouseTouchAdaptor* MouseTouchAdaptor::instance()
65109 return g_instance;
66110}
67111
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+
68215bool MouseTouchAdaptor::nativeEventFilter(const QByteArray & eventType,
69216 void * message, long * /*result*/)
70217{
218+ static int eventCount = 0;
219+ eventCount++;
71220 if (!m_enabled) {
72221 return false;
73222 }
@@ -81,32 +230,42 @@ bool MouseTouchAdaptor::nativeEventFilter(const QByteArray & eventType,
81230 xcb_generic_event_t *xcbEvent = static_cast<xcb_generic_event_t *>(message);
82231
83232 switch (xcbEvent->response_type & ~0x80) {
84− case XCB_BUTTON_PRESS:
85− return handleButtonPress(reinterpret_cast<xcb_button_press_event_t *>(xcbEvent));
86− break;
87− case XCB_BUTTON_RELEASE:
88− return handleButtonRelease(reinterpret_cast<xcb_button_release_event_t *>(xcbEvent));
89− break;
90− case XCB_MOTION_NOTIFY:
91− return handleMotionNotify(reinterpret_cast<xcb_motion_notify_event_t *>(xcbEvent));
92− break;
233+ case XCB_BUTTON_PRESS: {
234+ auto pressEvent = reinterpret_cast<xcb_button_press_event_t *>(xcbEvent);
235+ return handleButtonPress(static_cast<WId>(pressEvent->event), pressEvent->detail,
236+ pressEvent->event_x, pressEvent->event_y);
237+ }
238+ case XCB_BUTTON_RELEASE: {
239+ auto releaseEvent = reinterpret_cast<xcb_button_release_event_t *>(xcbEvent);
240+ return handleButtonRelease(static_cast<WId>(releaseEvent->event), releaseEvent->detail,
241+ releaseEvent->event_x, releaseEvent->event_y);
242+ }
243+ case XCB_MOTION_NOTIFY: {
244+ auto motionEvent = reinterpret_cast<xcb_motion_notify_event_t *>(xcbEvent);
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+ }
93253 default:
94254 return false;
95− break;
96255 };
97256}
98257
99−bool MouseTouchAdaptor::handleButtonPress(xcb_button_press_event_t *pressEvent)
258+bool MouseTouchAdaptor::handleButtonPress(WId windowId, uint32_t detail, int x, int y)
100259{
101− Qt::MouseButton button = translateMouseButton(pressEvent->detail);
260+ Qt::MouseButton button = translateMouseButton(detail);
102261
103262 // Just eat the event if it wasn't a left mouse press
104263 if (button != Qt::LeftButton)
105264 return true;
106265
107− QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(pressEvent->event));
266+ QWindow *targetWindow = findQWindowWithXWindowID(windowId);
108267
109− QPoint windowPos(pressEvent->event_x / targetWindow->devicePixelRatio(), pressEvent->event_y / targetWindow->devicePixelRatio());
268+ QPoint windowPos(x / targetWindow->devicePixelRatio(), y / targetWindow->devicePixelRatio());
110269
111270 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
112271 false /* autoCommit */);
@@ -117,17 +276,17 @@ bool MouseTouchAdaptor::handleButtonPress(xcb_button_press_event_t *pressEvent)
117276 return true;
118277}
119278
120−bool MouseTouchAdaptor::handleButtonRelease(xcb_button_release_event_t *releaseEvent)
279+bool MouseTouchAdaptor::handleButtonRelease(WId windowId, uint32_t detail, int x, int y)
121280{
122− Qt::MouseButton button = translateMouseButton(releaseEvent->detail);
281+ Qt::MouseButton button = translateMouseButton(detail);
123282
124283 // Just eat the event if it wasn't a left mouse release
125284 if (button != Qt::LeftButton)
126285 return true;
127286
128− QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(releaseEvent->event));
287+ QWindow *targetWindow = findQWindowWithXWindowID(windowId);
129288
130− QPoint windowPos(releaseEvent->event_x / targetWindow->devicePixelRatio(), releaseEvent->event_y / targetWindow->devicePixelRatio());
289+ QPoint windowPos(x / targetWindow->devicePixelRatio(), y / targetWindow->devicePixelRatio());
131290
132291 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
133292 false /* autoCommit */);
@@ -138,15 +297,15 @@ bool MouseTouchAdaptor::handleButtonRelease(xcb_button_release_event_t *releaseE
138297 return true;
139298}
140299
141−bool MouseTouchAdaptor::handleMotionNotify(xcb_motion_notify_event_t *event)
300+bool MouseTouchAdaptor::handleMotionNotify(WId windowId, int x, int y)
142301{
143302 if (!m_leftButtonIsPressed) {
144303 return true;
145304 }
146305
147− QWindow *targetWindow = findQWindowWithXWindowID(static_cast<WId>(event->event));
306+ QWindow *targetWindow = findQWindowWithXWindowID(windowId);
148307
149− QPoint windowPos(event->event_x / targetWindow->devicePixelRatio(), event->event_y / targetWindow->devicePixelRatio());
308+ QPoint windowPos(x / targetWindow->devicePixelRatio(), y / targetWindow->devicePixelRatio());
150309
151310 QTouchEventSequence touchEvent = QTest::touchEvent(targetWindow, m_touchDevice,
152311 false /* autoCommit */);
src/MouseTouchAdaptor.h+10−3
@@ -21,6 +21,7 @@
2121
2222#include <QtCore/QAbstractNativeEventFilter>
2323#include <QWindow>
24+
2425#include <xcb/xcb.h>
2526
2627class QMouseEvent;
@@ -47,16 +48,22 @@ Q_SIGNALS:
4748
4849private:
4950 MouseTouchAdaptor();
51+ void fetchXInput2Info();
52+ bool xi2HandleEvent(xcb_ge_event_t *event);
5053
51− bool handleButtonPress(xcb_button_press_event_t *pressEvent);
52− bool handleButtonRelease(xcb_button_release_event_t *releaseEvent);
53− bool handleMotionNotify(xcb_motion_notify_event_t *event);
54+ bool handleButtonPress(WId windowId, uint32_t detail, int x, int y);
55+ bool handleButtonRelease(WId windowId, uint32_t detail, int x, int y);
56+ bool handleMotionNotify(WId windowId, int x, int y);
5457 QWindow *findQWindowWithXWindowID(WId windowId);
5558
5659 QTouchDevice *m_touchDevice;
5760 bool m_leftButtonIsPressed;
5861
5962 bool m_enabled;
63+
64+ bool m_xi2Enabled{false};
65+ int m_xi2Minor{-1};
66+ int m_xiOpCode, m_xiEventBase, m_xiErrorBase;
6067};
6168
6269#endif // MOUSE_TOUCH_ADAPTOR_H
src/ShellApplication.cpp+5−5
@@ -28,15 +28,10 @@
2828// local
2929#include <paths.h>
3030#include "CachingNetworkManagerFactory.h"
31−#include "MouseTouchAdaptor.h"
3231#include "UnityCommandLineParser.h"
3332
3433ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer)
3534 : QGuiApplication(argc, argv)
36− , m_shellView(nullptr)
37− , m_secondaryWindow(nullptr)
38− , m_mouseTouchAdaptor(nullptr)
39− , m_qmlEngine(nullptr)
4035{
4136
4237 setApplicationName(QStringLiteral("unity8"));
@@ -89,11 +84,14 @@ ShellApplication::ShellApplication(int & argc, char ** argv, bool isMirServer)
8984 m_shellView->setFlags(Qt::FramelessWindowHint);
9085 }
9186
87+
88+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
9289 // You will need this if you want to interact with touch-only components using a mouse
9390 // Needed only when manually testing on a desktop.
9491 if (parser.hasMouseToTouch()) {
9592 m_mouseTouchAdaptor = MouseTouchAdaptor::instance();
9693 }
94+ #endif
9795
9896
9997 // Some hard-coded policy for now.
@@ -134,8 +132,10 @@ void ShellApplication::destroyResources()
134132 delete m_secondaryWindow;
135133 m_secondaryWindow = nullptr;
136134
135+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
137136 delete m_mouseTouchAdaptor;
138137 m_mouseTouchAdaptor = nullptr;
138+ #endif
139139
140140 delete m_qmlEngine;
141141 m_qmlEngine = nullptr;
src/ShellApplication.h+12−4
@@ -23,7 +23,11 @@
2323#include <QScopedPointer>
2424
2525#include "ApplicationArguments.h"
26+
27+#ifdef UNITY8_ENABLE_TOUCH_EMULATION
2628#include "MouseTouchAdaptor.h"
29+#endif
30+
2731#include "SecondaryWindow.h"
2832#include "ShellView.h"
2933
@@ -46,10 +50,14 @@ private:
4650 void setupQmlEngine(bool isMirServer);
4751 QString m_deviceName;
4852 ApplicationArguments m_qmlArgs;
49− ShellView *m_shellView;
50− SecondaryWindow *m_secondaryWindow;
51− MouseTouchAdaptor *m_mouseTouchAdaptor;
52− QQmlEngine *m_qmlEngine;
53+ ShellView *m_shellView{nullptr};
54+ SecondaryWindow *m_secondaryWindow{nullptr};
55+
56+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
57+ MouseTouchAdaptor *m_mouseTouchAdaptor{nullptr};
58+ #endif
59+
60+ QQmlEngine *m_qmlEngine{nullptr};
5361};
5462
5563#endif // SHELLAPPLICATION_H
src/UnityCommandLineParser.cpp+6
@@ -37,9 +37,11 @@ UnityCommandLineParser::UnityCommandLineParser(const QCoreApplication &app)
3737 QStringLiteral("Run without window borders"));
3838 parser.addOption(framelessOption);
3939
40+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
4041 QCommandLineOption mousetouchOption(QStringLiteral("mousetouch"),
4142 QStringLiteral("Allow the mouse to provide touch input"));
4243 parser.addOption(mousetouchOption);
44+ #endif
4345
4446 QCommandLineOption windowGeometryOption(QStringList() << QStringLiteral("windowgeometry"),
4547 QStringLiteral("Specify the window geometry as [<width>x<height>]"), QStringLiteral("windowgeometry"), QStringLiteral("1"));
@@ -75,7 +77,11 @@ UnityCommandLineParser::UnityCommandLineParser(const QCoreApplication &app)
7577
7678 m_hasTestability = parser.isSet(testabilityOption);
7779 m_hasFrameless = parser.isSet(framelessOption);
80+
81+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
7882 m_hasMouseToTouch = parser.isSet(mousetouchOption);
83+ #endif
84+
7985 m_hasFullscreen = parser.isSet(fullscreenOption);
8086 m_deviceName = parser.value(devicenameOption);
8187 resolveMode(parser, modeOption);
src/UnityCommandLineParser.h+8
@@ -28,7 +28,11 @@ public:
2828 QSize windowGeometry() const { return m_windowGeometry; }
2929 bool hasTestability() const { return m_hasTestability; }
3030 bool hasFrameless() const { return m_hasFrameless; }
31+
32+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
3133 bool hasMouseToTouch() const { return m_hasMouseToTouch; }
34+ #endif
35+
3236 bool hasFullscreen() const { return m_hasFullscreen; }
3337 QString deviceName() const { return m_deviceName; }
3438 QString mode() const { return m_mode; }
@@ -43,7 +47,11 @@ private:
4347 QSize m_windowGeometry;
4448 bool m_hasTestability;
4549 bool m_hasFrameless;
50+
51+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
4652 bool m_hasMouseToTouch;
53+ #endif
54+
4755 bool m_hasFullscreen;
4856 QString m_deviceName;
4957 QString m_mode;
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/CMakeLists.txt+1−1
@@ -7,4 +7,4 @@ add_library(MockSecurityPrivacy MODULE ${MOCK_SECURITYPRIVACY_SOURCES})
77
88qt5_use_modules(MockSecurityPrivacy Qml Quick Core)
99
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 @@
1717#include "MockSecurityPrivacy.h"
1818
1919MockSecurityPrivacy::MockSecurityPrivacy(QObject *parent)
20− : QObject(parent)
20+ : QObject(parent),
21+ m_type(SecurityType::Swipe)
2122{
2223}
2324
25+MockSecurityPrivacy::SecurityType MockSecurityPrivacy::getSecurityType()
26+{
27+ return m_type;
28+}
29+
2430QString MockSecurityPrivacy::setSecurity(const QString &oldPasswd, const QString &newPasswd, SecurityType newType)
2531{
32+ m_type = newType;
2633 Q_EMIT setSecurityCalled(oldPasswd, newPasswd, newType);
2734 return "";
2835}
tests/mocks/Ubuntu/SystemSettings/SecurityPrivacy/MockSecurityPrivacy.h+8
@@ -23,6 +23,9 @@ class MockSecurityPrivacy : public QObject
2323{
2424 Q_OBJECT
2525 Q_ENUMS(SecurityType)
26+ Q_PROPERTY (SecurityType securityType
27+ READ getSecurityType
28+ NOTIFY securityTypeChanged)
2629
2730public:
2831 enum SecurityType {
@@ -33,10 +36,15 @@ public:
3336
3437 MockSecurityPrivacy(QObject *parent = 0);
3538
39+ SecurityType getSecurityType();
3640 Q_INVOKABLE QString setSecurity(const QString &oldPasswd, const QString &newPasswd, SecurityType newType);
3741
3842Q_SIGNALS:
43+ void securityTypeChanged();
3944 void setSecurityCalled(const QString &oldPasswd, const QString &newPasswd, SecurityType newType); // only in mock
45+
46+private:
47+ SecurityType m_type;
4048};
4149
4250#endif // MOCK_SECURITYPRIVACY_H
tests/plugins/Dash/cardcreator/9.res+1
@@ -3,6 +3,7 @@ AbstractButton {
33 property var components;
44 property var cardData;
55 property string artShapeStyle: "inset";
6+ property string backgroundShapeStyle: "inset";
67 property real fontScale: 1.0;
78 property var scopeStyle: null;
89 property int titleAlignment: Text.AlignLeft;
tests/qmltests/CMakeLists.txt+2−1
@@ -38,6 +38,7 @@ add_unity8_qmltest(Dash/Previews PreviewExpandable)
3838add_unity8_qmltest(Dash/Previews PreviewHeader)
3939add_unity8_qmltest(Dash/Previews PreviewIconActions)
4040add_unity8_qmltest(Dash/Previews PreviewImageGallery)
41+add_unity8_qmltest(Dash/Previews PreviewMediaToolbar)
4142add_unity8_qmltest(Dash/Previews PreviewPayments)
4243add_unity8_qmltest(Dash/Previews PreviewProgress)
4344add_unity8_qmltest(Dash/Previews PreviewRatingDisplay)
@@ -87,4 +88,4 @@ add_unity8_qmltest(Stages WindowResizeArea)
8788add_unity8_qmltest(Stages Splash)
8889add_unity8_qmltest(Tutorial Tutorial LIGHTDM)
8990add_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)
1717target_link_libraries(DragHandleTestExec UbuntuGesturesQml ${UBUNTUGESTURES_LIBRARIES})
1818
1919add_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})
2121
2222########## tst_EdgeDragEvaluator
2323add_executable(EdgeDragEvaluatorTestExec tst_EdgeDragEvaluator.cpp)
tests/qmltests/Components/tst_DragHandle.qml+6−6
@@ -1,5 +1,5 @@
11/*
2− * Copyright 2013 Canonical Ltd.
2+ * Copyright 2013,2015 Canonical Ltd.
33 *
44 * This program is free software; you can redistribute it and/or modify
55 * it under the terms of the GNU General Public License as published by
@@ -51,7 +51,7 @@ Rectangle {
5151 objectName: "baseItem"
5252 anchors.fill: parent
5353
54− Button {
54+ SimpleButton {
5555 visible: root.bidirectional && bidirectionalShowable.fullyHidden
5656 text: "bidirectionalShowable.show()"
5757 anchors.centerIn: parent
@@ -169,12 +169,12 @@ Rectangle {
169169 anchors.margins: units.gu(1)
170170 spacing: units.gu(1)
171171
172− Button {
172+ SimpleButton {
173173 text: root.stretch ? "stretch" : "move"
174174 onClicked: { root.stretch = !root.stretch; }
175175 }
176176
177− Button {
177+ SimpleButton {
178178 text: root.hintDisplacement > 0 ? "hint" : "no hint"
179179 onClicked: {
180180 if (root.hintDisplacement > 0) {
@@ -185,7 +185,7 @@ Rectangle {
185185 }
186186 }
187187
188− Button {
188+ SimpleButton {
189189 text: "rotation: " + baseItem.rotation
190190 onClicked: {
191191 if (baseItem.rotation === 0.0) {
@@ -196,7 +196,7 @@ Rectangle {
196196 }
197197 }
198198
199− Button {
199+ SimpleButton {
200200 text: root.bidirectional ? "bidirectional" : "directional"
201201 onClicked: { root.bidirectional = !root.bidirectional; }
202202 }
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 {
3232 "text here 2",
3333 "text here 3"
3434 ],
35− "contentType": "text"
36− }
37−
38− property var shareDataNoUri: {
39− "uri": "",
40− "contentType": "text"
35+ "content-type": "text"
4136 }
4237
4338 PreviewSharing {
@@ -54,13 +49,6 @@ Rectangle {
5449
5550 function cleanup() {
5651 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);
6452 }
6553
6654 function test_open_picker() {
tests/qmltests/Greeter/tst_Greeter.qml+39−3
@@ -71,9 +71,9 @@ Item {
7171 }
7272
7373 SignalSpy {
74− id: emergencyCallSpy
74+ id: activeChangedSpy
7575 target: loader.item
76− signalName: "emergencyCall"
76+ signalName: "activeChanged"
7777 }
7878
7979 GSettings {
@@ -142,7 +142,7 @@ Item {
142142 resetLoader();
143143 teaseSpy.clear();
144144 sessionStartedSpy.clear();
145− emergencyCallSpy.clear();
145+ activeChangedSpy.clear();
146146 viewShowMessageSpy.clear();
147147 viewShowPromptSpy.clear();
148148 viewShowLastChanceSpy.clear();
@@ -458,6 +458,20 @@ Item {
458458 compare(view.delayMinutes, greeter.failedLoginsDelayMinutes);
459459 }
460460
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+
461475 function test_forcedDelayRoundTrip() {
462476 greeter.failedLoginsDelayAttempts = 1;
463477 greeter.failedLoginsDelayMinutes = 0.001; // make delay very short
@@ -471,6 +485,28 @@ Item {
471485 tryCompare(view, "delayMinutes", 0);
472486 }
473487
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+
474510 function test_dbusRequestAuthenticationUser() {
475511 selectUser("no-password");
476512 LightDM.Greeter.requestAuthenticationUser("has-password");
tests/qmltests/Launcher/tst_Launcher.qml+16
@@ -625,6 +625,7 @@ Item {
625625 if(data.mouse) {
626626 mouseClick(root)
627627 } else {
628+ touchRelease(draggedItem)
628629 tap(root)
629630 }
630631
@@ -739,6 +740,21 @@ Item {
739740 mouseRelease(draggedItem);
740741 }
741742
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+
742758 function test_quicklist_positioning_data() {
743759 return [
744760 {tag: "top", flickTo: "top", itemIndex: 0},
tests/qmltests/Stages/tst_DesktopStage.qml+29
@@ -25,6 +25,7 @@ import Utils 0.1
2525import ".." // For EdgeBarrierControls
2626import "../../../qml/Stages"
2727import "../../../qml/Components"
28+import "../../../qml/Components/PanelState"
2829
2930Item {
3031 id: root
@@ -500,5 +501,33 @@ Item {
500501 tryCompare(dialerAppDelegate, "visible", true);
501502 tryCompare(facebookAppDelegate, "visible", false);
502503 }
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+ }
503532 }
504533}
tests/qmltests/Wizard/tst_Wizard.qml+15
@@ -129,6 +129,7 @@ Item {
129129
130130 var pages = findChild(wizard, "wizardPages");
131131 var security = findInvisibleChild(pages, "securityPrivacy");
132+ security.setSecurity("", "", UbuntuSecurityPrivacyPanel.Swipe);
132133 setSecuritySpy.target = security;
133134
134135 setup();
@@ -315,6 +316,20 @@ Item {
315316 }
316317 }
317318
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+
318333 function test_passwdPasscode() {
319334 var page = goToPage("passwdPage");
320335
tests/utils/modules/Unity/Test/CMakeLists.txt+7−1
@@ -15,13 +15,19 @@ set(UnityTestQML_SOURCES
1515 testutil.cpp
1616 plugin.cpp
1717 TouchEventSequenceWrapper.cpp
18− ${CMAKE_SOURCE_DIR}/src/MouseTouchAdaptor.cpp
1918)
2019
20+if (ENABLE_TOUCH_EMULATION)
21+ set(UnityTestQML_SOURCES ${UnityTestQML_SOURCES} ${CMAKE_SOURCE_DIR}/src/MouseTouchAdaptor.cpp)
22+endif()
2123
2224add_library(UnityTestQml MODULE ${UnityTestQML_SOURCES})
2325target_link_libraries(UnityTestQml ${UBUNTUGESTURES_LIBRARIES})
2426
27+if (ENABLE_TOUCH_EMULATION)
28+ target_link_libraries(UnityTestQml ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
29+endif()
30+
2531qt5_use_modules(UnityTestQml Core Quick Test)
2632
2733export_qmlfiles(Unity.Test Unity/Test)
tests/utils/modules/Unity/Test/plugin.cpp+13−3
@@ -17,7 +17,11 @@
1717
1818#include "plugin.h"
1919#include "testutil.h"
20+
21+#ifdef UNITY8_ENABLE_TOUCH_EMULATION
2022#include <MouseTouchAdaptor.h>
23+#endif
24+
2125#include "TouchEventSequenceWrapper.h"
2226
2327#include <qqml.h>
@@ -27,23 +31,29 @@ QObject *testutil_provider(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine
2731{
2832 return new TestUtil();
2933}
34+
35+#ifdef UNITY8_ENABLE_TOUCH_EMULATION
3036QObject *getMouseTouchAdaptorQMLSingleton(QQmlEngine* /* engine */, QJSEngine* /* scriptEngine */)
3137{
3238 return MouseTouchAdaptor::instance();
3339}
40+#endif
41+
3442} // anonymous namespace
3543
3644void UnityTestPlugin::registerTypes(const char *uri)
3745{
3846 Q_ASSERT(QLatin1String(uri) == QLatin1String("Unity.Test"));
3947
40− // Ensure the instance gets created
41− MouseTouchAdaptor::instance();
42−
4348 // @uri Unity.Test
4449 qmlRegisterSingletonType<TestUtil>(uri, 0, 1, "Util", testutil_provider);
4550 qmlRegisterUncreatableType<TouchEventSequenceWrapper>(uri, 0, 1, "TouchEventSequence",
4651 "You cannot directly create a TouchEventSequence object.");
52+
53+ #ifdef UNITY8_ENABLE_TOUCH_EMULATION
54+ // Ensure the instance gets created
55+ MouseTouchAdaptor::instance();
4756 qmlRegisterSingletonType<MouseTouchAdaptor>(uri, 0, 1, "MouseTouchAdaptor",
4857 getMouseTouchAdaptorQMLSingleton);
58+ #endif
4959}