on xenial help sign in
replace MouseArea with MultiPointTouchArea
deee36bMichael Zanetti
plugins/UInput/uinput.cpp+33−9
@@ -40,6 +40,8 @@ void UInput::createMouse()
40 ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_REL);
40 ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_REL);
41 ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_X);
41 ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_X);
42 ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_Y);
42 ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_Y);
43+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_HWHEEL);
44+ ioctl(m_uinput.handle(), UI_SET_RELBIT, REL_WHEEL);
43
45
44 ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_KEY);
46 ioctl(m_uinput.handle(), UI_SET_EVBIT, EV_KEY);
45 ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_MOUSE);
47 ioctl(m_uinput.handle(), UI_SET_KEYBIT, BTN_MOUSE);
@@ -107,36 +109,58 @@ void UInput::moveMouse(int dx, int dy)
107 write(m_uinput.handle(), &event, sizeof(event));
109 write(m_uinput.handle(), &event, sizeof(event));
108}
110}
109
111
110−void UInput::pressMouse(Qt::MouseButton button)
112+void UInput::pressMouse(Button button)
111{
113{
112 injectMouse(button, 1);
114 injectMouse(button, 1);
113}
115}
114
116
115−void UInput::releaseMouse(Qt::MouseButton button)
117+void UInput::releaseMouse(Button button)
116{
118{
117 injectMouse(button, 0);
119 injectMouse(button, 0);
118}
120}
119
121
122+void UInput::scrollMouse(int dh, int dv)
123+{
124+ struct input_event event;
125+ memset(&event, 0, sizeof(event));
126+ gettimeofday(&event.time, 0);
127+ event.type = EV_REL;
128+ event.code = REL_HWHEEL;
129+ event.value = dh;
130+ write(m_uinput.handle(), &event, sizeof(event));
131+
132+ event.code = REL_WHEEL;
133+ event.value = dv;
134+ write(m_uinput.handle(), &event, sizeof(event));
135+
136+ event.type = EV_SYN;
137+ event.code = SYN_REPORT;
138+ event.value = 0;
139+ write(m_uinput.handle(), &event, sizeof(event));
140+}
141+
120−void UInput::injectMouse(Qt::MouseButton button, int down)
142+void UInput::injectMouse(Button button, int down)
121{
143{
122 struct input_event event;
144 struct input_event event;
123 memset(&event, 0, sizeof(event));
145 memset(&event, 0, sizeof(event));
124 gettimeofday(&event.time, 0);
146 gettimeofday(&event.time, 0);
125 event.type = EV_KEY;
147 event.type = EV_KEY;
126 switch (button) {
148 switch (button) {
127− case Qt::LeftButton:
149+ case ButtonLeft:
128 event.code = BTN_LEFT;
150 event.code = BTN_LEFT;
129 break;
151 break;
130− case Qt::RightButton:
152+ case ButtonRight:
131 event.code = BTN_RIGHT;
153 event.code = BTN_RIGHT;
132 break;
154 break;
133− case Qt::MiddleButton:
155+ case ButtonMiddle:
134 event.code = BTN_MIDDLE;
156 event.code = BTN_MIDDLE;
135 break;
157 break;
136− default:
137− qWarning() << "Unsupported mouse button.";
138− return;
139 }
158 }
140 event.value = down;
159 event.value = down;
141 write(m_uinput.handle(), &event, sizeof(event));
160 write(m_uinput.handle(), &event, sizeof(event));
161+
162+ event.type = EV_SYN;
163+ event.code = SYN_REPORT;
164+ event.value = 0;
165+ write(m_uinput.handle(), &event, sizeof(event));
142}
166}
plugins/UInput/uinput.h+12−3
@@ -10,7 +10,15 @@
10class UInput : public QObject
10class UInput : public QObject
11{
11{
12 Q_OBJECT
12 Q_OBJECT
13+ Q_ENUMS(Button)
14+
13public:
15public:
16+ enum Button {
17+ ButtonLeft,
18+ ButtonRight,
19+ ButtonMiddle
20+ };
21+
14 explicit UInput(QObject *parent = 0);
22 explicit UInput(QObject *parent = 0);
15 ~UInput();
23 ~UInput();
16
24
@@ -18,11 +26,12 @@ public:
18 Q_INVOKABLE void removeMouse();
26 Q_INVOKABLE void removeMouse();
19
27
20 Q_INVOKABLE void moveMouse(int dx, int dy);
28 Q_INVOKABLE void moveMouse(int dx, int dy);
21− Q_INVOKABLE void pressMouse(Qt::MouseButton button);
29+ Q_INVOKABLE void pressMouse(Button button);
22− Q_INVOKABLE void releaseMouse(Qt::MouseButton button);
30+ Q_INVOKABLE void releaseMouse(Button button);
31+ Q_INVOKABLE void scrollMouse(int dh, int dv);
23
32
24private:
33private:
25− void injectMouse(Qt::MouseButton button, int down);
34+ void injectMouse(Button button, int down);
26
35
27private:
36private:
28 QFile m_uinput;
37 QFile m_uinput;
qml/DisabledScreenNotice.qml+142−27
@@ -15,8 +15,10 @@
15 */
15 */
16
16
17import QtQuick 2.4
17import QtQuick 2.4
18+import QtQuick.Layouts 1.1
18import Ubuntu.Components 1.3
19import Ubuntu.Components 1.3
19import UInput 0.1
20import UInput 0.1
21+import Cursor 1.0
20import "Components"
22import "Components"
21
23
22Image {
24Image {
@@ -29,45 +31,158 @@ Image {
29
31
30 source: wallpaperResolver.background
32 source: wallpaperResolver.background
31
33
32− UbuntuShape {
33− anchors.fill: virtualTouchPad
34− backgroundColor: "black"
35− opacity: 0.4
36− }
37−
38 UInput {
34 UInput {
39 id: uinput
35 id: uinput
40 Component.onCompleted: createMouse();
36 Component.onCompleted: createMouse();
41 Component.onDestruction: removeMouse();
37 Component.onDestruction: removeMouse();
42 }
38 }
43
39
44− MouseArea {
40+ ColumnLayout {
45− id: virtualTouchPad
46 anchors.fill: parent
41 anchors.fill: parent
47 anchors.margins: units.gu(2)
42 anchors.margins: units.gu(2)
43+ spacing: units.gu(2)
44+
45+ Label {
46+ id: text
47+ Layout.fillWidth: true
48+ text: i18n.tr("Your device is now connected to an external display.")
49+ color: "white"
50+ horizontalAlignment: Text.AlignHCenter
51+ verticalAlignment: Text.AlignVCenter
52+ fontSize: "x-large"
53+ wrapMode: Text.Wrap
54+ }
55+
56+ UbuntuShape {
57+ Layout.fillWidth: true
58+ Layout.fillHeight: true
59+ backgroundColor: "black"
60+ opacity: 0.4
61+
62+ Image {
63+ anchors.centerIn: parent
64+ height: units.gu(2)
65+ width: units.gu(2)
66+ source: "image://cursor/default/left_ptr"
67+ }
68+
69+ MultiPointTouchArea {
70+ anchors.fill: parent
71+
72+ property int clickThreshold: units.gu(1.5)
73+ property bool isClick: false
74+
75+ onPressed: {
76+ if (point1.pressed && !point2.pressed && clickTimer.running) {
77+ clickTimer.stop();
78+ uinput.pressMouse(UInput.ButtonLeft)
79+ }
80+ isClick = true;
81+ }
48
82
49− property int oldX
83+ onUpdated: {
50− property int oldY
84+ switch (touchPoints.length) {
85+ case 1:
86+ moveMouse(touchPoints);
87+ return;
88+ case 2:
89+ scroll(touchPoints);
90+ return;
91+ }
92+ }
51
93
52− onPressed: {
94+ onReleased: {
53− oldX = mouseX;
95+ var tp = touchPoints[0]
54− oldY = mouseY;
96+ if (isClick) {
97+ clickTimer.scheduleClick(point1.pressed ? UInput.ButtonRight : UInput.ButtonLeft)
98+ }
99+ isClick = false;
100+ }
101+
102+ Timer {
103+ id: clickTimer
104+ repeat: false
105+ interval: 100
106+ property int button: UInput.ButtonLeft
107+ onTriggered: {
108+ uinput.pressMouse(button);
109+ uinput.releaseMouse(button);
110+ }
111+ function scheduleClick(button) {
112+ clickTimer.button = button;
113+ clickTimer.start();
114+ }
115+ }
116+
117+ function moveMouse(touchPoints) {
118+ var tp = touchPoints[0];
119+ if (isClick &&
120+ (Math.abs(tp.x - tp.startX) > clickThreshold ||
121+ Math.abs(tp.y - tp.startY) > clickThreshold)) {
122+ isClick = false;
123+ }
124+
125+ uinput.moveMouse(tp.x - tp.previousX, tp.y - tp.previousY);
126+ }
127+
128+ function scroll(touchPoints) {
129+ var dh = 0;
130+ var dv = 0;
131+ var tp = touchPoints[0];
132+ if (isClick &&
133+ (Math.abs(tp.x - tp.startX) > clickThreshold ||
134+ Math.abs(tp.y - tp.startY) > clickThreshold)) {
135+ isClick = false;
136+ }
137+ dh += tp.x - tp.previousX;
138+ dv += tp.y - tp.previousY;
139+
140+ tp = touchPoints[1];
141+ if (isClick &&
142+ (Math.abs(tp.x - tp.startX) > clickThreshold ||
143+ Math.abs(tp.y - tp.startY) > clickThreshold)) {
144+ isClick = false;
145+ }
146+ dh += tp.x - tp.previousX;
147+ dv += tp.y - tp.previousY;
148+
149+ uinput.scrollMouse(dh, dv);
150+ }
151+
152+ touchPoints: [
153+ TouchPoint {
154+ id: point1
155+ },
156+ TouchPoint {
157+ id: point2
158+ }
159+ ]
160+ }
55 }
161 }
56
162
57− onPositionChanged: {
163+ RowLayout {
58− uinput.moveMouse(mouseX - oldX, mouseY - oldY)
164+ Layout.fillWidth: true
165+ spacing: units.gu(2)
166+ Button {
167+ Layout.fillWidth: true
168+ onPressedChanged: {
169+ if (pressed) {
170+ uinput.pressMouse(UInput.ButtonLeft)
171+ } else {
172+ uinput.releaseMouse(UInput.ButtonLeft)
173+ }
174+ }
175+ }
176+ Button {
177+ Layout.fillWidth: true
178+ onPressedChanged: {
179+ if (pressed) {
180+ uinput.pressMouse(UInput.ButtonRight)
181+ } else {
182+ uinput.releaseMouse(UInput.ButtonRight)
183+ }
184+ }
185+ }
59 }
186 }
60 }
187 }
61−
62−// Label {
63−// id: text
64−// anchors.centerIn: parent
65−// width: parent.width / 2
66−// text: i18n.tr("Your device is now connected to an external display.")
67−// color: "white"
68−// horizontalAlignment: Text.AlignHCenter
69−// verticalAlignment: Text.AlignVCenter
70−// fontSize: "x-large"
71−// wrapMode: Text.Wrap
72−// }
73}
188}