on xenial help sign in
Merge
637b3ccAlbert 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(libs)
143add_subdirectory(libs)
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
@@ -31,7 +31,11 @@ Build-Depends: cmake,
31 libudev-dev,
31 libudev-dev,
32 libunity-api-dev (>= 7.106),
32 libunity-api-dev (>= 7.106),
33 libusermetricsoutput1-dev,
33 libusermetricsoutput1-dev,
34+# Need those X11 libs touch emulation from mouse events in manual QML tests on a X11 desktop
35+ libx11-dev[!armhf],
34− libxcb1-dev,
36+ libxcb1-dev[!armhf],
37+ libxi-dev[!armhf],
38+# End of X11 libs
35 pkg-config,
39 pkg-config,
36 python3-all:any,
40 python3-all:any,
37 python3-setuptools,
41 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/Ubuntu/Gestures/DirectionalDragArea.cpp+8−2
@@ -715,8 +715,14 @@ void DirectionalDragArea::itemChange(ItemChange change, const ItemChangeData &va
715 value.window->installEventFilter(TouchRegistry::instance());
715 value.window->installEventFilter(TouchRegistry::instance());
716
716
717 // TODO: Handle window->screen() changes (ie window changing screens)
717 // TODO: Handle window->screen() changes (ie window changing screens)
718+
718− qreal pixelsPerMm = value.window->screen()->physicalDotsPerInch() / 25.4;
719+ qreal pixelsPerInch = value.window->screen()->physicalDotsPerInch();
719− d->setPixelsPerMm(pixelsPerMm);
720+ if (pixelsPerInch < 0) {
721+ // It can return garbage when run in a XVFB server (Virtual Framebuffer 'fake' X server)
722+ pixelsPerInch = 72;
723+ }
724+
725+ d->setPixelsPerMm(pixelsPerInch / 25.4);
720 }
726 }
721 }
727 }
722}
728}
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
@@ -16,10 +16,9 @@ file(GLOB_RECURSE QML_FILES
16 ${CMAKE_SOURCE_DIR}/tests/*.svg
16 ${CMAKE_SOURCE_DIR}/tests/*.svg
17)
17)
18
18
19−add_executable(${SHELL_APP}
19+set(SOURCE_FILES
20 ApplicationArguments.cpp
20 ApplicationArguments.cpp
21 main.cpp
21 main.cpp
22− MouseTouchAdaptor.cpp
23 CachingNetworkManagerFactory.cpp
22 CachingNetworkManagerFactory.cpp
24 SecondaryWindow.cpp
23 SecondaryWindow.cpp
25 ShellApplication.cpp
24 ShellApplication.cpp
@@ -28,15 +27,22 @@ add_executable(${SHELL_APP}
28 ${QML_FILES} # This is to make qml and image files appear in the IDE's project tree
27 ${QML_FILES} # This is to make qml and image files appear in the IDE's project tree
29)
28)
30
29
30+if (ENABLE_TOUCH_EMULATION)
31+ set(SOURCE_FILES ${SOURCE_FILES} MouseTouchAdaptor.cpp)
32+endif()
33+
34+pkg_check_modules(ANDROID_PROPERTIES REQUIRED libandroid-properties)
35+add_executable(${SHELL_APP} ${SOURCE_FILES})
31qt5_use_modules(${SHELL_APP} Gui Qml Quick Test)
36qt5_use_modules(${SHELL_APP} Gui Qml Quick Test)
32
37
33−pkg_check_modules(NEEDED_LIBS REQUIRED xcb libandroid-properties)
38+if (NOT "${ANDROID_PROPERTIES_INCLUDE_DIRS}" STREQUAL "")
34−if (NOT "${NEEDED_LIBS_INCLUDE_DIRS}" STREQUAL "")
35− set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${NEEDED_LIBS_INCLUDE_DIRS})
39+ set_target_properties(${SHELL_APP} PROPERTIES INCLUDE_DIRECTORIES ${ANDROID_PROPERTIES_INCLUDE_DIRS})
36endif()
40endif()
37−target_link_libraries(${SHELL_APP} ${NEEDED_LIBS_LDFLAGS})
41+target_link_libraries(${SHELL_APP} ${ANDROID_PROPERTIES_LDFLAGS} UbuntuGestures connectivity-qt1)
38
42
43+if (ENABLE_TOUCH_EMULATION)
39−target_link_libraries(${SHELL_APP} UbuntuGestures connectivity-qt1)
44+ target_link_libraries(${SHELL_APP} ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
45+endif()
40
46
41# For it to find libUbuntuGestures.so
47# For it to find libUbuntuGestures.so
42set_target_properties(${SHELL_APP} PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}")
48set_target_properties(${SHELL_APP} PROPERTIES INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${SHELL_PRIVATE_LIBDIR}")
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/autopilot/unity8/dash.py+1−1
@@ -158,7 +158,7 @@ class Dash(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
158 def enter_search_query(self, query, keyboard):
158 def enter_search_query(self, query, keyboard):
159 current_header = self._get_current_page_header()
159 current_header = self._get_current_page_header()
160 search_button = \
160 search_button = \
161− current_header.select_single(objectName="search_action_button")
161+ current_header.select_single(objectName="search_button")
162 self.pointing_device.move(
162 self.pointing_device.move(
163 search_button.globalRect.x + search_button.width / 2,
163 search_button.globalRect.x + search_button.width / 2,
164 search_button.globalRect.y + search_button.height / 2)
164 search_button.globalRect.y + search_button.height / 2)
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
@@ -15,7 +15,7 @@ qt5_use_modules(DragHandleTestExec Test Core Qml Gui Quick)
15target_link_libraries(DragHandleTestExec UbuntuGesturesQml UbuntuGestures)
15target_link_libraries(DragHandleTestExec UbuntuGesturesQml UbuntuGestures)
16
16
17add_unity8_uitest(DragHandle DragHandleTestExec ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures)
17add_unity8_uitest(DragHandle DragHandleTestExec ENVIRONMENT LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/plugins/Ubuntu/Gestures)
18−add_manual_qml_test(. DragHandle IMPORT_PATHS ${UNITY_PLUGINPATH})
18+add_manual_qml_test(. DragHandle IMPORT_PATHS ${UNITY_IMPORT_PATHS})
19
19
20########## tst_EdgeDragEvaluator
20########## tst_EdgeDragEvaluator
21add_executable(EdgeDragEvaluatorTestExec tst_EdgeDragEvaluator.cpp)
21add_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/Dash/tst_Dash.qml+1−1
@@ -319,7 +319,7 @@ Item {
319
319
320 // Click on the store
320 // Click on the store
321 var scopesListPageHeader = findChild(scopesList, "pageHeader");
321 var scopesListPageHeader = findChild(scopesList, "pageHeader");
322− var searchButton = findChild(scopesListPageHeader, "store_action_button");
322+ var searchButton = findChild(scopesListPageHeader, "store_button");
323 mouseClick(searchButton);
323 mouseClick(searchButton);
324
324
325 spy.wait();
325 spy.wait();
tests/qmltests/Dash/tst_DashContent.qml+1−1
@@ -497,7 +497,7 @@ Item {
497 {
497 {
498 var dashContentList = findChild(dashContent, "dashContentList");
498 var dashContentList = findChild(dashContent, "dashContentList");
499 var header = findChild(dashContentList.currentItem, "scopePageHeader")
499 var header = findChild(dashContentList.currentItem, "scopePageHeader")
500− var favoriteAction = findChild(header, "favorite_action_button");
500+ var favoriteAction = findChild(header, "favorite_button");
501 compare(dashContentList.currentIndex, 0);
501 compare(dashContentList.currentIndex, 0);
502 compare(dashContentList.indexAt(dashContentList.width * 1.5, 0), 1);
502 compare(dashContentList.indexAt(dashContentList.width * 1.5, 0), 1);
503 var nextScopeId = dashContentList.itemAt(dashContentList.width * 1.5, 0).item.scope.id;
503 var nextScopeId = dashContentList.itemAt(dashContentList.width * 1.5, 0).item.scope.id;
tests/qmltests/Dash/tst_GenericScopeView.qml+2−2
@@ -434,7 +434,7 @@ Item {
434 // open
434 // open
435 tryCompare(testCase.subPageLoader, "open", false);
435 tryCompare(testCase.subPageLoader, "open", false);
436 tryCompare(testCase.subPageLoader, "visible", false);
436 tryCompare(testCase.subPageLoader, "visible", false);
437− var settings = findChild(innerHeader, "settings_action_button");
437+ var settings = findChild(innerHeader, "settings_button");
438 mouseClick(settings);
438 mouseClick(settings);
439 tryCompare(testCase.subPageLoader, "open", true);
439 tryCompare(testCase.subPageLoader, "open", true);
440 tryCompareFunction(function() { return (String(subPageLoader.source)).indexOf("ScopeSettingsPage.qml") != -1; }, true);
440 tryCompareFunction(function() { return (String(subPageLoader.source)).indexOf("ScopeSettingsPage.qml") != -1; }, true);
@@ -582,7 +582,7 @@ Item {
582 verify(innerHeader, "Could not find the inner header");
582 verify(innerHeader, "Could not find the inner header");
583
583
584 expectFail("Apps", "Click scope should not have a favorite button");
584 expectFail("Apps", "Click scope should not have a favorite button");
585− var favoriteAction = findChild(innerHeader, "favorite_action_button");
585+ var favoriteAction = findChild(innerHeader, "favorite_button");
586 verify(favoriteAction, "Could not find the favorite action.");
586 verify(favoriteAction, "Could not find the favorite action.");
587 mouseClick(favoriteAction);
587 mouseClick(favoriteAction);
588
588
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/Panel/tst_IndicatorsMenu.qml+3−3
@@ -243,12 +243,12 @@ IndicatorTest {
243
243
244 // next time position will have moved.
244 // next time position will have moved.
245 var nextItem = get_indicator_item(1);
245 var nextItem = get_indicator_item(1);
246− var nextItemMappedPosition = root.mapFromItem(nextItem, nextItem.width/2, nextItem.height/2);
246+ var nextItemMappedPositionX = firstItemMappedPosition.x + firstItem.width;
247
247
248 // 1) Flick mouse down to bottom
248 // 1) Flick mouse down to bottom
249 touchFlick(indicatorsMenu,
249 touchFlick(indicatorsMenu,
250 firstItemMappedPosition.x, indicatorsMenu.minimizedPanelHeight * 2,
250 firstItemMappedPosition.x, indicatorsMenu.minimizedPanelHeight * 2,
251− nextItemMappedPosition.x, indicatorsMenu.openedHeight / 3,
251+ nextItemMappedPositionX, indicatorsMenu.openedHeight / 3,
252 false /* beginTouch */, false /* endTouch */,
252 false /* beginTouch */, false /* endTouch */,
253 units.gu(50) /* speed */, 5 /* iterations */); // more samples needed for accurate velocity
253 units.gu(50) /* speed */, 5 /* iterations */); // more samples needed for accurate velocity
254
254
@@ -256,7 +256,7 @@ IndicatorTest {
256 // after waiting in the same spot with touch down, it should update to the next item.
256 // after waiting in the same spot with touch down, it should update to the next item.
257 tryCompare(indicatorItemRow, "currentItem", nextItem);
257 tryCompare(indicatorItemRow, "currentItem", nextItem);
258
258
259− touchRelease(indicatorsMenu, nextItemMappedPosition.x, indicatorsMenu.openedHeight / 3);
259+ touchRelease(indicatorsMenu, nextItemMappedPositionX, indicatorsMenu.openedHeight / 3);
260 }
260 }
261 }
261 }
262}
262}
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+8−1
@@ -13,12 +13,19 @@ set(UnityTestQML_SOURCES
13 testutil.cpp
13 testutil.cpp
14 plugin.cpp
14 plugin.cpp
15 TouchEventSequenceWrapper.cpp
15 TouchEventSequenceWrapper.cpp
16− ${CMAKE_SOURCE_DIR}/src/MouseTouchAdaptor.cpp
17)
16)
18
17
18+if (ENABLE_TOUCH_EMULATION)
19+ set(UnityTestQML_SOURCES ${UnityTestQML_SOURCES} ${CMAKE_SOURCE_DIR}/src/MouseTouchAdaptor.cpp)
20+endif()
21+
19add_library(UnityTestQml MODULE ${UnityTestQML_SOURCES})
22add_library(UnityTestQml MODULE ${UnityTestQML_SOURCES})
20target_link_libraries(UnityTestQml UbuntuGestures)
23target_link_libraries(UnityTestQml UbuntuGestures)
21
24
25+if (ENABLE_TOUCH_EMULATION)
26+ target_link_libraries(UnityTestQml ${MOUSETOUCHADAPTOR_LIBS_LDFLAGS})
27+endif()
28+
22qt5_use_modules(UnityTestQml Core Quick Test)
29qt5_use_modules(UnityTestQml Core Quick Test)
23
30
24export_qmlfiles(Unity.Test Unity/Test)
31export_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}