on xenial help sign in
Prevent mouse wheel events from going through shell elements (LP: #1536268)
fde5775Lukáš Tinkl
qml/Launcher/LauncherPanel.qml+3−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2013 Canonical, Ltd.
2+ * Copyright (C) 2013-2016 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
@@ -69,7 +69,9 @@ Rectangle {
69 MouseArea {
69 MouseArea {
70 id: mouseEventEater
70 id: mouseEventEater
71 anchors.fill: parent
71 anchors.fill: parent
72+ acceptedButtons: Qt.AllButtons
72 hoverEnabled: true
73 hoverEnabled: true
74+ onWheel: wheel.accepted = true;
73 }
75 }
74
76
75 Column {
77 Column {
qml/Panel/IndicatorsMenu.qml+3−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright (C) 2014 Canonical, Ltd.
2+ * Copyright (C) 2014-2016 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
@@ -80,6 +80,8 @@ Showable {
80 MouseArea {
80 MouseArea {
81 anchors.fill: parent
81 anchors.fill: parent
82 hoverEnabled: true
82 hoverEnabled: true
83+ acceptedButtons: Qt.AllButtons
84+ onWheel: wheel.accepted = true;
83 }
85 }
84
86
85 MenuContent {
87 MenuContent {
qml/Stages/DesktopSpread.qml+2
@@ -132,6 +132,8 @@ FocusScope {
132 anchors.fill: parent
132 anchors.fill: parent
133 visible: spreadBackground.visible
133 visible: spreadBackground.visible
134 enabled: visible
134 enabled: visible
135+ acceptedButtons: Qt.AllButtons
136+ onWheel: wheel.accepted = true;
135 }
137 }
136
138
137 Item {
139 Item {
tests/qmltests/Launcher/tst_Launcher.qml+23−3
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2013-2014 Canonical Ltd.
2+ * Copyright 2013-2016 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
@@ -210,6 +210,11 @@ Rectangle {
210 target: LauncherModel
210 target: LauncherModel
211 }
211 }
212
212
213+ SignalSpy {
214+ id: clickThroughSpy
215+ target: clickThroughTester
216+ }
217+
213 Item {
218 Item {
214 id: fakeDismissTimer
219 id: fakeDismissTimer
215 property bool running: false
220 property bool running: false
@@ -231,6 +236,8 @@ Rectangle {
231
236
232 property Item launcher: launcherLoader.status === Loader.Ready ? launcherLoader.item : null
237 property Item launcher: launcherLoader.status === Loader.Ready ? launcherLoader.item : null
233 function cleanup() {
238 function cleanup() {
239+ signalSpy.clear();
240+ clickThroughSpy.clear();
234 launcherLoader.active = false;
241 launcherLoader.active = false;
235 // Loader.status might be Loader.Null and Loader.item might be null but the Loader
242 // Loader.status might be Loader.Null and Loader.item might be null but the Loader
236 // item might still be alive. So if we set Loader.active back to true
243 // item might still be alive. So if we set Loader.active back to true
@@ -925,7 +932,6 @@ Rectangle {
925
932
926 var quickListEntry = findChild(quickList, "quickListEntry" + data.index)
933 var quickListEntry = findChild(quickList, "quickListEntry" + data.index)
927
934
928− signalSpy.clear();
929 signalSpy.signalName = "quickListTriggered"
935 signalSpy.signalName = "quickListTriggered"
930
936
931 mouseClick(quickListEntry)
937 mouseClick(quickListEntry)
@@ -1218,7 +1224,6 @@ Rectangle {
1218 launcher.openForKeyboardNavigation();
1224 launcher.openForKeyboardNavigation();
1219 waitForRendering(launcher);
1225 waitForRendering(launcher);
1220
1226
1221− signalSpy.clear();
1222 signalSpy.signalName = "quickListTriggered"
1227 signalSpy.signalName = "quickListTriggered"
1223
1228
1224 keyClick(Qt.Key_Down); // Down to launcher item 0
1229 keyClick(Qt.Key_Down); // Down to launcher item 0
@@ -1311,5 +1316,20 @@ Rectangle {
1311 compare(surfacePipRepeater.model, Math.min(3, LauncherModel.get(i).surfaceCount))
1316 compare(surfacePipRepeater.model, Math.min(3, LauncherModel.get(i).surfaceCount))
1312 }
1317 }
1313 }
1318 }
1319+
1320+ function test_preventMouseEventsThru() {
1321+ dragLauncherIntoView();
1322+ var launcherPanel = findChild(launcher, "launcherPanel");
1323+ tryCompare(launcherPanel, "visible", true);
1324+
1325+ clickThroughSpy.signalName = "wheel";
1326+ mouseWheel(launcherPanel, launcherPanel.width/2, launcherPanel.height/2, 10, 10);
1327+ tryCompare(clickThroughSpy, "count", 0);
1328+
1329+ clickThroughSpy.clear();
1330+ clickThroughSpy.signalName = "clicked";
1331+ mouseWheel(launcherPanel, launcherPanel.width/2, launcherPanel.height/2, Qt.RightButton);
1332+ tryCompare(clickThroughSpy, "count", 0);
1333+ }
1314 }
1334 }
1315}
1335}
tests/qmltests/Panel/tst_IndicatorsMenu.qml+29−1
@@ -1,5 +1,5 @@
1/*
1/*
2− * Copyright 2013-2014 Canonical Ltd.
2+ * Copyright 2013-2016 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
@@ -27,6 +27,16 @@ IndicatorTest {
27 width: units.gu(80)
27 width: units.gu(80)
28 height: units.gu(71)
28 height: units.gu(71)
29
29
30+ SignalSpy {
31+ id: clickThroughSpy
32+ target: clickThroughTester
33+ }
34+
35+ MouseArea {
36+ id: clickThroughTester
37+ anchors.fill: root
38+ }
39+
30 RowLayout {
40 RowLayout {
31 anchors.fill: parent
41 anchors.fill: parent
32 anchors.margins: units.gu(1)
42 anchors.margins: units.gu(1)
@@ -112,6 +122,10 @@ IndicatorTest {
112 indicatorsMenu.verticalVelocityThreshold = 0.5
122 indicatorsMenu.verticalVelocityThreshold = 0.5
113 }
123 }
114
124
125+ function cleanup() {
126+ clickThroughSpy.clear();
127+ }
128+
115 function get_indicator_item(index) {
129 function get_indicator_item(index) {
116 var indicatorItem = findChild(indicatorsMenu, root.originalModelData[index]["identifier"] + "-panelItem");
130 var indicatorItem = findChild(indicatorsMenu, root.originalModelData[index]["identifier"] + "-panelItem");
117 verify(indicatorItem !== null);
131 verify(indicatorItem !== null);
@@ -257,5 +271,19 @@ IndicatorTest {
257
271
258 touchRelease(indicatorsMenu, nextItemMappedPositionX, indicatorsMenu.openedHeight / 3);
272 touchRelease(indicatorsMenu, nextItemMappedPositionX, indicatorsMenu.openedHeight / 3);
259 }
273 }
274+
275+ function test_preventMouseEventsThru() {
276+ indicatorsMenu.show();
277+ tryCompare(indicatorsMenu, "fullyOpened", true);
278+
279+ clickThroughSpy.signalName = "wheel";
280+ mouseWheel(indicatorsMenu, indicatorsMenu.width/2, indicatorsMenu.height/2, 10, 10);
281+ tryCompare(clickThroughSpy, "count", 0);
282+
283+ clickThroughSpy.clear();
284+ clickThroughSpy.signalName = "clicked";
285+ mouseClick(indicatorsMenu, indicatorsMenu.width/2, indicatorsMenu.height/2, Qt.RightButton);
286+ tryCompare(clickThroughSpy, "count", 0);
287+ }
260 }
288 }
261}
289}
tests/qmltests/Stages/tst_DesktopStage.qml+31
@@ -89,6 +89,13 @@ Item {
89 topLevelSurfaceList: topSurfaceList
89 topLevelSurfaceList: topSurfaceList
90 }
90 }
91 }
91 }
92+
93+ MouseArea {
94+ id: clickThroughTester
95+ anchors.fill: desktopStageLoader.item
96+ acceptedButtons: Qt.AllButtons
97+ hoverEnabled: true
98+ }
92 }
99 }
93
100
94 Rectangle {
101 Rectangle {
@@ -140,6 +147,11 @@ Item {
140 }
147 }
141 }
148 }
142
149
150+ SignalSpy {
151+ id: mouseEaterSpy
152+ target: clickThroughTester
153+ }
154+
143 UnityTestCase {
155 UnityTestCase {
144 id: testCase
156 id: testCase
145 name: "DesktopStage"
157 name: "DesktopStage"
@@ -179,6 +191,7 @@ Item {
179 desktopStageLoader.active = true;
191 desktopStageLoader.active = true;
180 tryCompare(desktopStageLoader, "status", Loader.Ready);
192 tryCompare(desktopStageLoader, "status", Loader.Ready);
181
193
194+ mouseEaterSpy.clear();
182 }
195 }
183
196
184 function waitUntilAppSurfaceShowsUp(surfaceId) {
197 function waitUntilAppSurfaceShowsUp(surfaceId) {
@@ -677,5 +690,23 @@ Item {
677 var closeButton = findChild(dashAppDelegate, "closeWindowButton");
690 var closeButton = findChild(dashAppDelegate, "closeWindowButton");
678 tryCompare(closeButton, "visible", false);
691 tryCompare(closeButton, "visible", false);
679 }
692 }
693+
694+ function test_preventMouseEventsThruDesktopSpread() {
695+ var spread = findChild(desktopStage, "spread");
696+ verify(spread);
697+ spread.show();
698+ tryCompareFunction( function(){ return spread.ready }, true );
699+
700+ mouseEaterSpy.signalName = "wheel";
701+ mouseWheel(spread, spread.width/2, spread.height/2, 10, 10);
702+ tryCompare(mouseEaterSpy, "count", 0);
703+
704+ mouseEaterSpy.clear();
705+ mouseEaterSpy.signalName = "clicked";
706+ mouseClick(spread, spread.width/2, spread.height/2, Qt.RightButton);
707+ tryCompare(mouseEaterSpy, "count", 0);
708+
709+ spread.cancel();
710+ }
680 }
711 }
681}
712}