~ci-train-bot/miral/miral-ubuntu-zesty-2534

« back to all changes in this revision

Viewing changes to miral-qt/src/platforms/mirserver/qteventfeeder.cpp

  • Committer: Larry Price
  • Date: 2016-09-13 16:19:29 UTC
  • mto: This revision was merged to the branch mainline in revision 331.
  • Revision ID: larry.price@canonical.com-20160913161929-vs9ka1capmljq1es
Removing miral-qt from release branch, updating copyright file, and adding GPL3 license to root dir

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2013-2016 Canonical, Ltd.
3
 
 *
4
 
 * This program is free software: you can redistribute it and/or modify it under
5
 
 * the terms of the GNU Lesser General Public License version 3, as published by
6
 
 * the Free Software Foundation.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 
 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10
 
 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
 
 * Lesser General Public License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU Lesser General Public License
14
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 
 */
16
 
 
17
 
#include "qteventfeeder.h"
18
 
#include "cursor.h"
19
 
#include "logging.h"
20
 
#include "timestamp.h"
21
 
#include "tracepoints.h" // generated from tracepoints.tp
22
 
#include "screen.h" // NEEDED?
23
 
#include "screensmodel.h"
24
 
 
25
 
#include <qpa/qplatforminputcontext.h>
26
 
#include <qpa/qplatformintegration.h>
27
 
#include <QGuiApplication>
28
 
#include <private/qguiapplication_p.h>
29
 
#include <QTextCodec>
30
 
#include <QDebug>
31
 
 
32
 
#include <xkbcommon/xkbcommon.h>
33
 
#include <xkbcommon/xkbcommon-keysyms.h>
34
 
 
35
 
// common dir
36
 
#include <debughelpers.h>
37
 
 
38
 
// XKB Keysyms which do not map directly to Qt types (i.e. Unicode points)
39
 
static const uint32_t KeyTable[] = {
40
 
    // misc keys
41
 
    XKB_KEY_Escape,             Qt::Key_Escape,
42
 
    XKB_KEY_Tab,                Qt::Key_Tab,
43
 
    XKB_KEY_ISO_Left_Tab,       Qt::Key_Backtab,
44
 
    XKB_KEY_BackSpace,          Qt::Key_Backspace,
45
 
    XKB_KEY_Return,             Qt::Key_Return,
46
 
    XKB_KEY_Insert,             Qt::Key_Insert,
47
 
    XKB_KEY_Delete,             Qt::Key_Delete,
48
 
    XKB_KEY_Clear,              Qt::Key_Delete,
49
 
    XKB_KEY_Pause,              Qt::Key_Pause,
50
 
    XKB_KEY_Print,              Qt::Key_Print,
51
 
    0x1005FF60,                 Qt::Key_SysReq,         // hardcoded Sun SysReq
52
 
    0x1007ff00,                 Qt::Key_SysReq,         // hardcoded X386 SysReq
53
 
 
54
 
    // cursor movement
55
 
 
56
 
    XKB_KEY_Home,               Qt::Key_Home,
57
 
    XKB_KEY_End,                Qt::Key_End,
58
 
    XKB_KEY_Left,               Qt::Key_Left,
59
 
    XKB_KEY_Up,                 Qt::Key_Up,
60
 
    XKB_KEY_Right,              Qt::Key_Right,
61
 
    XKB_KEY_Down,               Qt::Key_Down,
62
 
    XKB_KEY_Prior,              Qt::Key_PageUp,
63
 
    XKB_KEY_Next,               Qt::Key_PageDown,
64
 
 
65
 
    // modifiers
66
 
 
67
 
    XKB_KEY_Shift_L,            Qt::Key_Shift,
68
 
    XKB_KEY_Shift_R,            Qt::Key_Shift,
69
 
    XKB_KEY_Shift_Lock,         Qt::Key_Shift,
70
 
    XKB_KEY_Control_L,          Qt::Key_Control,
71
 
    XKB_KEY_Control_R,          Qt::Key_Control,
72
 
    XKB_KEY_Meta_L,             Qt::Key_Meta,
73
 
    XKB_KEY_Meta_R,             Qt::Key_Meta,
74
 
    XKB_KEY_Alt_L,              Qt::Key_Alt,
75
 
    XKB_KEY_Alt_R,              Qt::Key_Alt,
76
 
    XKB_KEY_Caps_Lock,          Qt::Key_CapsLock,
77
 
    XKB_KEY_Num_Lock,           Qt::Key_NumLock,
78
 
    XKB_KEY_Scroll_Lock,        Qt::Key_ScrollLock,
79
 
    XKB_KEY_Super_L,            Qt::Key_Super_L,
80
 
    XKB_KEY_Super_R,            Qt::Key_Super_R,
81
 
    XKB_KEY_Menu,               Qt::Key_Menu,
82
 
    XKB_KEY_Hyper_L,            Qt::Key_Hyper_L,
83
 
    XKB_KEY_Hyper_R,            Qt::Key_Hyper_R,
84
 
    XKB_KEY_Help,               Qt::Key_Help,
85
 
    0x1000FF74,                 Qt::Key_Backtab,        // hardcoded HP backtab
86
 
    0x1005FF10,                 Qt::Key_F11,            // hardcoded Sun F36 (labeled F11)
87
 
    0x1005FF11,                 Qt::Key_F12,            // hardcoded Sun F37 (labeled F12)
88
 
 
89
 
    // numeric and function keypad keys
90
 
 
91
 
    XKB_KEY_KP_Space,           Qt::Key_Space,
92
 
    XKB_KEY_KP_Tab,             Qt::Key_Tab,
93
 
    XKB_KEY_KP_Enter,           Qt::Key_Enter,
94
 
    //XKB_KEY_KP_F1,            Qt::Key_F1,
95
 
    //XKB_KEY_KP_F2,            Qt::Key_F2,
96
 
    //XKB_KEY_KP_F3,            Qt::Key_F3,
97
 
    //XKB_KEY_KP_F4,            Qt::Key_F4,
98
 
    XKB_KEY_KP_Home,            Qt::Key_Home,
99
 
    XKB_KEY_KP_Left,            Qt::Key_Left,
100
 
    XKB_KEY_KP_Up,              Qt::Key_Up,
101
 
    XKB_KEY_KP_Right,           Qt::Key_Right,
102
 
    XKB_KEY_KP_Down,            Qt::Key_Down,
103
 
    XKB_KEY_KP_Prior,           Qt::Key_PageUp,
104
 
    XKB_KEY_KP_Next,            Qt::Key_PageDown,
105
 
    XKB_KEY_KP_End,             Qt::Key_End,
106
 
    XKB_KEY_KP_Begin,           Qt::Key_Clear,
107
 
    XKB_KEY_KP_Insert,          Qt::Key_Insert,
108
 
    XKB_KEY_KP_Delete,          Qt::Key_Delete,
109
 
    XKB_KEY_KP_Equal,           Qt::Key_Equal,
110
 
    XKB_KEY_KP_Multiply,        Qt::Key_Asterisk,
111
 
    XKB_KEY_KP_Add,             Qt::Key_Plus,
112
 
    XKB_KEY_KP_Separator,       Qt::Key_Comma,
113
 
    XKB_KEY_KP_Subtract,        Qt::Key_Minus,
114
 
    XKB_KEY_KP_Decimal,         Qt::Key_Period,
115
 
    XKB_KEY_KP_Divide,          Qt::Key_Slash,
116
 
 
117
 
    // International input method support keys
118
 
 
119
 
    // International & multi-key character composition
120
 
    XKB_KEY_ISO_Level3_Shift,   Qt::Key_AltGr,
121
 
    XKB_KEY_Multi_key,          Qt::Key_Multi_key,
122
 
    XKB_KEY_Codeinput,          Qt::Key_Codeinput,
123
 
    XKB_KEY_SingleCandidate,    Qt::Key_SingleCandidate,
124
 
    XKB_KEY_MultipleCandidate,  Qt::Key_MultipleCandidate,
125
 
    XKB_KEY_PreviousCandidate,  Qt::Key_PreviousCandidate,
126
 
 
127
 
    // Misc Functions
128
 
    XKB_KEY_Mode_switch,        Qt::Key_Mode_switch,
129
 
    XKB_KEY_script_switch,      Qt::Key_Mode_switch,
130
 
 
131
 
    // Japanese keyboard support
132
 
    XKB_KEY_Kanji,              Qt::Key_Kanji,
133
 
    XKB_KEY_Muhenkan,           Qt::Key_Muhenkan,
134
 
    //XKB_KEY_Henkan_Mode,      Qt::Key_Henkan_Mode,
135
 
    XKB_KEY_Henkan_Mode,        Qt::Key_Henkan,
136
 
    XKB_KEY_Henkan,             Qt::Key_Henkan,
137
 
    XKB_KEY_Romaji,             Qt::Key_Romaji,
138
 
    XKB_KEY_Hiragana,           Qt::Key_Hiragana,
139
 
    XKB_KEY_Katakana,           Qt::Key_Katakana,
140
 
    XKB_KEY_Hiragana_Katakana,  Qt::Key_Hiragana_Katakana,
141
 
    XKB_KEY_Zenkaku,            Qt::Key_Zenkaku,
142
 
    XKB_KEY_Hankaku,            Qt::Key_Hankaku,
143
 
    XKB_KEY_Zenkaku_Hankaku,    Qt::Key_Zenkaku_Hankaku,
144
 
    XKB_KEY_Touroku,            Qt::Key_Touroku,
145
 
    XKB_KEY_Massyo,             Qt::Key_Massyo,
146
 
    XKB_KEY_Kana_Lock,          Qt::Key_Kana_Lock,
147
 
    XKB_KEY_Kana_Shift,         Qt::Key_Kana_Shift,
148
 
    XKB_KEY_Eisu_Shift,         Qt::Key_Eisu_Shift,
149
 
    XKB_KEY_Eisu_toggle,        Qt::Key_Eisu_toggle,
150
 
    //XKB_KEY_Kanji_Bangou,     Qt::Key_Kanji_Bangou,
151
 
    //XKB_KEY_Zen_Koho,         Qt::Key_Zen_Koho,
152
 
    //XKB_KEY_Mae_Koho,         Qt::Key_Mae_Koho,
153
 
    XKB_KEY_Kanji_Bangou,       Qt::Key_Codeinput,
154
 
    XKB_KEY_Zen_Koho,           Qt::Key_MultipleCandidate,
155
 
    XKB_KEY_Mae_Koho,           Qt::Key_PreviousCandidate,
156
 
 
157
 
#ifdef XKB_KEY_KOREAN
158
 
    // Korean keyboard support
159
 
    XKB_KEY_Hangul,                  Qt::Key_Hangul,
160
 
    XKB_KEY_Hangul_Start,            Qt::Key_Hangul_Start,
161
 
    XKB_KEY_Hangul_End,              Qt::Key_Hangul_End,
162
 
    XKB_KEY_Hangul_Hanja,            Qt::Key_Hangul_Hanja,
163
 
    XKB_KEY_Hangul_Jamo,             Qt::Key_Hangul_Jamo,
164
 
    XKB_KEY_Hangul_Romaja,           Qt::Key_Hangul_Romaja,
165
 
    //XKB_KEY_Hangul_Codeinput,      Qt::Key_Hangul_Codeinput,
166
 
    XKB_KEY_Hangul_Codeinput,        Qt::Key_Codeinput,
167
 
    XKB_KEY_Hangul_Jeonja,           Qt::Key_Hangul_Jeonja,
168
 
    XKB_KEY_Hangul_Banja,            Qt::Key_Hangul_Banja,
169
 
    XKB_KEY_Hangul_PreHanja,         Qt::Key_Hangul_PreHanja,
170
 
    XKB_KEY_Hangul_PostHanja,        Qt::Key_Hangul_PostHanja,
171
 
    //XKB_KEY_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate,
172
 
    //XKB_KEY_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate,
173
 
    //XKB_KEY_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate,
174
 
    XKB_KEY_Hangul_SingleCandidate,  Qt::Key_SingleCandidate,
175
 
    XKB_KEY_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate,
176
 
    XKB_KEY_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate,
177
 
    XKB_KEY_Hangul_Special,          Qt::Key_Hangul_Special,
178
 
    //XKB_KEY_Hangul_switch,         Qt::Key_Hangul_switch,
179
 
    XKB_KEY_Hangul_switch,           Qt::Key_Mode_switch,
180
 
#endif  // XKB_KEY_KOREAN
181
 
 
182
 
    // dead keys
183
 
    XKB_KEY_dead_grave,              Qt::Key_Dead_Grave,
184
 
    XKB_KEY_dead_acute,              Qt::Key_Dead_Acute,
185
 
    XKB_KEY_dead_circumflex,         Qt::Key_Dead_Circumflex,
186
 
    XKB_KEY_dead_tilde,              Qt::Key_Dead_Tilde,
187
 
    XKB_KEY_dead_macron,             Qt::Key_Dead_Macron,
188
 
    XKB_KEY_dead_breve,              Qt::Key_Dead_Breve,
189
 
    XKB_KEY_dead_abovedot,           Qt::Key_Dead_Abovedot,
190
 
    XKB_KEY_dead_diaeresis,          Qt::Key_Dead_Diaeresis,
191
 
    XKB_KEY_dead_abovering,          Qt::Key_Dead_Abovering,
192
 
    XKB_KEY_dead_doubleacute,        Qt::Key_Dead_Doubleacute,
193
 
    XKB_KEY_dead_caron,              Qt::Key_Dead_Caron,
194
 
    XKB_KEY_dead_cedilla,            Qt::Key_Dead_Cedilla,
195
 
    XKB_KEY_dead_ogonek,             Qt::Key_Dead_Ogonek,
196
 
    XKB_KEY_dead_iota,               Qt::Key_Dead_Iota,
197
 
    XKB_KEY_dead_voiced_sound,       Qt::Key_Dead_Voiced_Sound,
198
 
    XKB_KEY_dead_semivoiced_sound,   Qt::Key_Dead_Semivoiced_Sound,
199
 
    XKB_KEY_dead_belowdot,           Qt::Key_Dead_Belowdot,
200
 
    XKB_KEY_dead_hook,               Qt::Key_Dead_Hook,
201
 
    XKB_KEY_dead_horn,               Qt::Key_Dead_Horn,
202
 
 
203
 
    // Special keys from X.org - This include multimedia keys,
204
 
    // wireless/bluetooth/uwb keys, special launcher keys, etc.
205
 
    XKB_KEY_XF86Back,                Qt::Key_Back,
206
 
    XKB_KEY_XF86Forward,             Qt::Key_Forward,
207
 
    XKB_KEY_XF86Stop,                Qt::Key_Stop,
208
 
    XKB_KEY_XF86Refresh,             Qt::Key_Refresh,
209
 
    XKB_KEY_XF86Favorites,           Qt::Key_Favorites,
210
 
    XKB_KEY_XF86AudioMedia,          Qt::Key_LaunchMedia,
211
 
    XKB_KEY_XF86OpenURL,             Qt::Key_OpenUrl,
212
 
    XKB_KEY_XF86HomePage,            Qt::Key_HomePage,
213
 
    XKB_KEY_XF86Search,              Qt::Key_Search,
214
 
    XKB_KEY_XF86AudioLowerVolume,    Qt::Key_VolumeDown,
215
 
    XKB_KEY_XF86AudioMute,           Qt::Key_VolumeMute,
216
 
    XKB_KEY_XF86AudioRaiseVolume,    Qt::Key_VolumeUp,
217
 
    XKB_KEY_XF86AudioPlay,           Qt::Key_MediaPlay,
218
 
    XKB_KEY_XF86AudioStop,           Qt::Key_MediaStop,
219
 
    XKB_KEY_XF86AudioPrev,           Qt::Key_MediaPrevious,
220
 
    XKB_KEY_XF86AudioNext,           Qt::Key_MediaNext,
221
 
    XKB_KEY_XF86AudioRecord,         Qt::Key_MediaRecord,
222
 
    XKB_KEY_XF86AudioPause,          Qt::Key_MediaPause,
223
 
    XKB_KEY_XF86Mail,                Qt::Key_LaunchMail,
224
 
    XKB_KEY_XF86MyComputer,          Qt::Key_Launch0,  // ### Qt 6: remap properly
225
 
    XKB_KEY_XF86Calculator,          Qt::Key_Launch1,
226
 
    XKB_KEY_XF86Memo,                Qt::Key_Memo,
227
 
    XKB_KEY_XF86ToDoList,            Qt::Key_ToDoList,
228
 
    XKB_KEY_XF86Calendar,            Qt::Key_Calendar,
229
 
    XKB_KEY_XF86PowerDown,           Qt::Key_PowerDown,
230
 
    XKB_KEY_XF86ContrastAdjust,      Qt::Key_ContrastAdjust,
231
 
    XKB_KEY_XF86Standby,             Qt::Key_Standby,
232
 
    XKB_KEY_XF86MonBrightnessUp,     Qt::Key_MonBrightnessUp,
233
 
    XKB_KEY_XF86MonBrightnessDown,   Qt::Key_MonBrightnessDown,
234
 
    XKB_KEY_XF86KbdLightOnOff,       Qt::Key_KeyboardLightOnOff,
235
 
    XKB_KEY_XF86KbdBrightnessUp,     Qt::Key_KeyboardBrightnessUp,
236
 
    XKB_KEY_XF86KbdBrightnessDown,   Qt::Key_KeyboardBrightnessDown,
237
 
    XKB_KEY_XF86PowerOff,            Qt::Key_PowerOff,
238
 
    XKB_KEY_XF86WakeUp,              Qt::Key_WakeUp,
239
 
    XKB_KEY_XF86Eject,               Qt::Key_Eject,
240
 
    XKB_KEY_XF86ScreenSaver,         Qt::Key_ScreenSaver,
241
 
    XKB_KEY_XF86WWW,                 Qt::Key_WWW,
242
 
    XKB_KEY_XF86Sleep,               Qt::Key_Sleep,
243
 
    XKB_KEY_XF86LightBulb,           Qt::Key_LightBulb,
244
 
    XKB_KEY_XF86Shop,                Qt::Key_Shop,
245
 
    XKB_KEY_XF86History,             Qt::Key_History,
246
 
    XKB_KEY_XF86AddFavorite,         Qt::Key_AddFavorite,
247
 
    XKB_KEY_XF86HotLinks,            Qt::Key_HotLinks,
248
 
    XKB_KEY_XF86BrightnessAdjust,    Qt::Key_BrightnessAdjust,
249
 
    XKB_KEY_XF86Finance,             Qt::Key_Finance,
250
 
    XKB_KEY_XF86Community,           Qt::Key_Community,
251
 
    XKB_KEY_XF86AudioRewind,         Qt::Key_AudioRewind,
252
 
    XKB_KEY_XF86BackForward,         Qt::Key_BackForward,
253
 
    XKB_KEY_XF86ApplicationLeft,     Qt::Key_ApplicationLeft,
254
 
    XKB_KEY_XF86ApplicationRight,    Qt::Key_ApplicationRight,
255
 
    XKB_KEY_XF86Book,                Qt::Key_Book,
256
 
    XKB_KEY_XF86CD,                  Qt::Key_CD,
257
 
    XKB_KEY_XF86Calculater,          Qt::Key_Calculator,
258
 
    XKB_KEY_XF86Clear,               Qt::Key_Clear,
259
 
    XKB_KEY_XF86ClearGrab,           Qt::Key_ClearGrab,
260
 
    XKB_KEY_XF86Close,               Qt::Key_Close,
261
 
    XKB_KEY_XF86Copy,                Qt::Key_Copy,
262
 
    XKB_KEY_XF86Cut,                 Qt::Key_Cut,
263
 
    XKB_KEY_XF86Display,             Qt::Key_Display,
264
 
    XKB_KEY_XF86DOS,                 Qt::Key_DOS,
265
 
    XKB_KEY_XF86Documents,           Qt::Key_Documents,
266
 
    XKB_KEY_XF86Excel,               Qt::Key_Excel,
267
 
    XKB_KEY_XF86Explorer,            Qt::Key_Explorer,
268
 
    XKB_KEY_XF86Game,                Qt::Key_Game,
269
 
    XKB_KEY_XF86Go,                  Qt::Key_Go,
270
 
    XKB_KEY_XF86iTouch,              Qt::Key_iTouch,
271
 
    XKB_KEY_XF86LogOff,              Qt::Key_LogOff,
272
 
    XKB_KEY_XF86Market,              Qt::Key_Market,
273
 
    XKB_KEY_XF86Meeting,             Qt::Key_Meeting,
274
 
    XKB_KEY_XF86MenuKB,              Qt::Key_MenuKB,
275
 
    XKB_KEY_XF86MenuPB,              Qt::Key_MenuPB,
276
 
    XKB_KEY_XF86MySites,             Qt::Key_MySites,
277
 
    XKB_KEY_XF86New,                 Qt::Key_New,
278
 
    XKB_KEY_XF86News,                Qt::Key_News,
279
 
    XKB_KEY_XF86OfficeHome,          Qt::Key_OfficeHome,
280
 
    XKB_KEY_XF86Open,                Qt::Key_Open,
281
 
    XKB_KEY_XF86Option,              Qt::Key_Option,
282
 
    XKB_KEY_XF86Paste,               Qt::Key_Paste,
283
 
    XKB_KEY_XF86Phone,               Qt::Key_Phone,
284
 
    XKB_KEY_XF86Reply,               Qt::Key_Reply,
285
 
    XKB_KEY_XF86Reload,              Qt::Key_Reload,
286
 
    XKB_KEY_XF86RotateWindows,       Qt::Key_RotateWindows,
287
 
    XKB_KEY_XF86RotationPB,          Qt::Key_RotationPB,
288
 
    XKB_KEY_XF86RotationKB,          Qt::Key_RotationKB,
289
 
    XKB_KEY_XF86Save,                Qt::Key_Save,
290
 
    XKB_KEY_XF86Send,                Qt::Key_Send,
291
 
    XKB_KEY_XF86Spell,               Qt::Key_Spell,
292
 
    XKB_KEY_XF86SplitScreen,         Qt::Key_SplitScreen,
293
 
    XKB_KEY_XF86Support,             Qt::Key_Support,
294
 
    XKB_KEY_XF86TaskPane,            Qt::Key_TaskPane,
295
 
    XKB_KEY_XF86Terminal,            Qt::Key_Terminal,
296
 
    XKB_KEY_XF86Tools,               Qt::Key_Tools,
297
 
    XKB_KEY_XF86Travel,              Qt::Key_Travel,
298
 
    XKB_KEY_XF86Video,               Qt::Key_Video,
299
 
    XKB_KEY_XF86Word,                Qt::Key_Word,
300
 
    XKB_KEY_XF86Xfer,                Qt::Key_Xfer,
301
 
    XKB_KEY_XF86ZoomIn,              Qt::Key_ZoomIn,
302
 
    XKB_KEY_XF86ZoomOut,             Qt::Key_ZoomOut,
303
 
    XKB_KEY_XF86Away,                Qt::Key_Away,
304
 
    XKB_KEY_XF86Messenger,           Qt::Key_Messenger,
305
 
    XKB_KEY_XF86WebCam,              Qt::Key_WebCam,
306
 
    XKB_KEY_XF86MailForward,         Qt::Key_MailForward,
307
 
    XKB_KEY_XF86Pictures,            Qt::Key_Pictures,
308
 
    XKB_KEY_XF86Music,               Qt::Key_Music,
309
 
    XKB_KEY_XF86Battery,             Qt::Key_Battery,
310
 
    XKB_KEY_XF86Bluetooth,           Qt::Key_Bluetooth,
311
 
    XKB_KEY_XF86WLAN,                Qt::Key_WLAN,
312
 
    XKB_KEY_XF86UWB,                 Qt::Key_UWB,
313
 
    XKB_KEY_XF86AudioForward,        Qt::Key_AudioForward,
314
 
    XKB_KEY_XF86AudioRepeat,         Qt::Key_AudioRepeat,
315
 
    XKB_KEY_XF86AudioRandomPlay,     Qt::Key_AudioRandomPlay,
316
 
    XKB_KEY_XF86Subtitle,            Qt::Key_Subtitle,
317
 
    XKB_KEY_XF86AudioCycleTrack,     Qt::Key_AudioCycleTrack,
318
 
    XKB_KEY_XF86Time,                Qt::Key_Time,
319
 
    XKB_KEY_XF86Select,              Qt::Key_Select,
320
 
    XKB_KEY_XF86View,                Qt::Key_View,
321
 
    XKB_KEY_XF86TopMenu,             Qt::Key_TopMenu,
322
 
    XKB_KEY_XF86Red,                 Qt::Key_Red,
323
 
    XKB_KEY_XF86Green,               Qt::Key_Green,
324
 
    XKB_KEY_XF86Yellow,              Qt::Key_Yellow,
325
 
    XKB_KEY_XF86Blue,                Qt::Key_Blue,
326
 
    XKB_KEY_XF86Bluetooth,           Qt::Key_Bluetooth,
327
 
    XKB_KEY_XF86Suspend,             Qt::Key_Suspend,
328
 
    XKB_KEY_XF86Hibernate,           Qt::Key_Hibernate,
329
 
    XKB_KEY_XF86TouchpadToggle,      Qt::Key_TouchpadToggle,
330
 
    XKB_KEY_XF86TouchpadOn,          Qt::Key_TouchpadOn,
331
 
    XKB_KEY_XF86TouchpadOff,         Qt::Key_TouchpadOff,
332
 
    XKB_KEY_XF86AudioMicMute,        Qt::Key_MicMute,
333
 
    XKB_KEY_XF86Launch0,             Qt::Key_Launch2, // ### Qt 6: remap properly
334
 
    XKB_KEY_XF86Launch1,             Qt::Key_Launch3,
335
 
    XKB_KEY_XF86Launch2,             Qt::Key_Launch4,
336
 
    XKB_KEY_XF86Launch3,             Qt::Key_Launch5,
337
 
    XKB_KEY_XF86Launch4,             Qt::Key_Launch6,
338
 
    XKB_KEY_XF86Launch5,             Qt::Key_Launch7,
339
 
    XKB_KEY_XF86Launch6,             Qt::Key_Launch8,
340
 
    XKB_KEY_XF86Launch7,             Qt::Key_Launch9,
341
 
    XKB_KEY_XF86Launch8,             Qt::Key_LaunchA,
342
 
    XKB_KEY_XF86Launch9,             Qt::Key_LaunchB,
343
 
    XKB_KEY_XF86LaunchA,             Qt::Key_LaunchC,
344
 
    XKB_KEY_XF86LaunchB,             Qt::Key_LaunchD,
345
 
    XKB_KEY_XF86LaunchC,             Qt::Key_LaunchE,
346
 
    XKB_KEY_XF86LaunchD,             Qt::Key_LaunchF,
347
 
    XKB_KEY_XF86LaunchE,             Qt::Key_LaunchG,
348
 
    XKB_KEY_XF86LaunchF,             Qt::Key_LaunchH,
349
 
 
350
 
    0,                          0
351
 
};
352
 
 
353
 
static uint32_t translateKeysym(uint32_t sym, const QString &text) {
354
 
    int code = 0;
355
 
 
356
 
    QTextCodec *systemCodec = QTextCodec::codecForLocale();
357
 
    if (sym < 128 || (sym < 256 && systemCodec->mibEnum() == 4)) {
358
 
        // upper-case key, if known
359
 
        code = isprint((int)sym) ? toupper((int)sym) : 0;
360
 
    } else if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F35) {
361
 
        return Qt::Key_F1 + (int(sym) - XKB_KEY_F1);
362
 
    } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f
363
 
               && text.unicode()->unicode() != 0x7f
364
 
               && !(sym >= XKB_KEY_dead_grave && sym <= XKB_KEY_dead_currency)) {
365
 
        code = text.unicode()->toUpper().unicode();
366
 
    } else {
367
 
        for (int i = 0; KeyTable[i]; i += 2)
368
 
            if (sym == KeyTable[i])
369
 
                code = KeyTable[i + 1];
370
 
    }
371
 
 
372
 
    return code;
373
 
}
374
 
 
375
 
namespace {
376
 
 
377
 
class QtWindowSystem : public QtEventFeeder::QtWindowSystemInterface
378
 
{
379
 
public:
380
 
    QtWindowSystem()
381
 
    {
382
 
        // because we're using QMetaObject::invoke with arguments of those types
383
 
        qRegisterMetaType<Qt::KeyboardModifiers>("Qt::KeyboardModifiers");
384
 
        qRegisterMetaType<Qt::MouseButtons>("Qt::MouseButtons");
385
 
    }
386
 
 
387
 
    void setScreensModel(const QSharedPointer<ScreensModel> &sc) override
388
 
    {
389
 
        m_screensModel = sc;
390
 
    }
391
 
 
392
 
    virtual QWindow* focusedWindow() override
393
 
    {
394
 
        return QGuiApplication::focusWindow();
395
 
    }
396
 
 
397
 
    QWindow* getWindowForTouchPoint(const QPoint &point) override //FIXME: not efficient, not updating focused window
398
 
    {
399
 
        return m_screensModel->getWindowForPoint(point);
400
 
    }
401
 
 
402
 
    void registerTouchDevice(QTouchDevice *device) override
403
 
    {
404
 
        QWindowSystemInterface::registerTouchDevice(device);
405
 
    }
406
 
 
407
 
    void handleExtendedKeyEvent(QWindow *window, ulong timestamp, QEvent::Type type, int key,
408
 
                Qt::KeyboardModifiers modifiers,
409
 
                quint32 nativeScanCode, quint32 nativeVirtualKey,
410
 
                quint32 nativeModifiers,
411
 
                const QString& text, bool autorep, ushort count) override
412
 
    {
413
 
        QWindowSystemInterface::handleExtendedKeyEvent(window, timestamp, type, key, modifiers,
414
 
                nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
415
 
    }
416
 
 
417
 
    void handleTouchEvent(QWindow *window, ulong timestamp, QTouchDevice *device,
418
 
            const QList<struct QWindowSystemInterface::TouchPoint> &points, Qt::KeyboardModifiers mods) override
419
 
    {
420
 
        QWindowSystemInterface::handleTouchEvent(window, timestamp, device, points, mods);
421
 
    }
422
 
 
423
 
    void handleMouseEvent(ulong timestamp, QPointF relative, QPointF absolute, Qt::MouseButtons buttons,
424
 
                          Qt::KeyboardModifiers modifiers) override
425
 
    {
426
 
        // Send to the first screen that handles the mouse event
427
 
        // TODO: Have a mechanism to tell which screen currently has the logical mouse pointer
428
 
        //       (because they all might have their own separate graphical mouse pointer item)
429
 
        //       This will probably come once we implement the feature of having the mouse pointer
430
 
        //       crossing adjacent screens.
431
 
 
432
 
        QList<Screen*> screens = m_screensModel->screens();
433
 
        bool eventHandled = false;
434
 
        int i = 0;
435
 
        while (i < screens.count() && !eventHandled) {
436
 
            auto platformCursor = static_cast<qtmir::Cursor*>(screens[i]->cursor());
437
 
            eventHandled = platformCursor->handleMouseEvent(timestamp, relative, buttons, modifiers);
438
 
            ++i;
439
 
        }
440
 
        if (!eventHandled) {
441
 
            QWindowSystemInterface::handleMouseEvent(focusedWindow(), timestamp, absolute, absolute, buttons, modifiers);
442
 
        }
443
 
    }
444
 
 
445
 
    void handleWheelEvent(ulong timestamp, QPointF absolute, QPoint angleDelta, Qt::KeyboardModifiers modifiers) override
446
 
    {
447
 
        // Send to the first screen that handles the mouse event
448
 
        // TODO: Have a mechanism to tell which screen currently has the logical mouse pointer
449
 
        //       (because they all might have their own separate graphical mouse pointer item)
450
 
        //       This will probably come once we implement the feature of having the mouse pointer
451
 
        //       crossing adjacent screens.
452
 
 
453
 
        QList<Screen*> screens = m_screensModel->screens();
454
 
        bool eventHandled = false;
455
 
        int i = 0;
456
 
        while (i < screens.count() && !eventHandled) {
457
 
            auto platformCursor = static_cast<qtmir::Cursor*>(screens.at(i)->cursor());
458
 
            eventHandled = platformCursor->handleWheelEvent(timestamp, angleDelta, modifiers);
459
 
            ++i;
460
 
        }
461
 
        if (!eventHandled) {
462
 
            QWindowSystemInterface::handleWheelEvent(focusedWindow(), timestamp, absolute, absolute,
463
 
                                                     QPoint(), angleDelta, modifiers, Qt::ScrollUpdate);
464
 
        }
465
 
    }
466
 
 
467
 
private:
468
 
    QSharedPointer<ScreensModel> m_screensModel;
469
 
};
470
 
 
471
 
} // anonymous namespace
472
 
 
473
 
QtEventFeeder::QtEventFeeder(const QSharedPointer<ScreensModel> &screensModel)
474
 
    : QtEventFeeder(screensModel, new QtWindowSystem)
475
 
{
476
 
}
477
 
 
478
 
QtEventFeeder::QtEventFeeder(const QSharedPointer<ScreensModel> &screensModel,
479
 
                             QtEventFeeder::QtWindowSystemInterface *windowSystem)
480
 
    : mQtWindowSystem(windowSystem)
481
 
{
482
 
    // Initialize touch device. Hardcoded just like in qtubuntu
483
 
    // TODO: Create them from info gathered from Mir and store things like device id and source
484
 
    //       in a QTouchDevice-derived class created by us. So that we can properly assemble back
485
 
    //       MirEvents our of QTouchEvents to give to mir::scene::Surface::consume.
486
 
    mTouchDevice = new QTouchDevice();  // Qt takes ownership of mTouchDevice with registerTouchDevice
487
 
    mTouchDevice->setType(QTouchDevice::TouchScreen);
488
 
    mTouchDevice->setCapabilities(
489
 
            QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure |
490
 
            QTouchDevice::NormalizedPosition);
491
 
    mQtWindowSystem->setScreensModel(screensModel);
492
 
    mQtWindowSystem->registerTouchDevice(mTouchDevice);
493
 
}
494
 
 
495
 
QtEventFeeder::~QtEventFeeder()
496
 
{
497
 
    delete mQtWindowSystem;
498
 
}
499
 
 
500
 
bool QtEventFeeder::dispatch(MirEvent const& event)
501
 
{
502
 
    auto type = mir_event_get_type(&event);
503
 
    if (type != mir_event_type_input)
504
 
        return false;
505
 
 
506
 
    auto iev = mir_event_get_input_event(&event);
507
 
 
508
 
    switch (mir_input_event_get_type(iev)) {
509
 
    case mir_input_event_type_key:
510
 
        dispatchKey(mir_input_event_get_keyboard_event(iev));
511
 
        break;
512
 
    case mir_input_event_type_touch:
513
 
        dispatchTouch(mir_input_event_get_touch_event(iev));
514
 
        break;
515
 
    case mir_input_event_type_pointer:
516
 
        dispatchPointer(mir_input_event_get_pointer_event(iev));
517
 
    default:
518
 
        break;
519
 
    }
520
 
 
521
 
    return true;
522
 
}
523
 
 
524
 
namespace
525
 
{
526
 
 
527
 
Qt::KeyboardModifiers getQtModifiersFromMir(MirInputEventModifiers modifiers)
528
 
{
529
 
    Qt::KeyboardModifiers qtModifiers = Qt::NoModifier;
530
 
    if (modifiers & mir_input_event_modifier_shift) {
531
 
        qtModifiers |= Qt::ShiftModifier;
532
 
    }
533
 
    if (modifiers & mir_input_event_modifier_ctrl) {
534
 
        qtModifiers |= Qt::ControlModifier;
535
 
    }
536
 
    if (modifiers & mir_input_event_modifier_alt) {
537
 
        qtModifiers |= Qt::AltModifier;
538
 
    }
539
 
    if (modifiers & mir_input_event_modifier_meta) {
540
 
        qtModifiers |= Qt::MetaModifier;
541
 
    }
542
 
    if (modifiers & mir_input_event_modifier_alt_right) {
543
 
        qtModifiers |= Qt::GroupSwitchModifier;
544
 
    }
545
 
    return qtModifiers;
546
 
}
547
 
 
548
 
Qt::MouseButtons getQtMouseButtonsfromMirPointerEvent(MirPointerEvent const* pev)
549
 
{
550
 
    Qt::MouseButtons buttons = Qt::NoButton;
551
 
    if (mir_pointer_event_button_state(pev, mir_pointer_button_primary))
552
 
        buttons |= Qt::LeftButton;
553
 
    if (mir_pointer_event_button_state(pev, mir_pointer_button_secondary))
554
 
        buttons |= Qt::RightButton;
555
 
    if (mir_pointer_event_button_state(pev, mir_pointer_button_tertiary))
556
 
        buttons |= Qt::MiddleButton;
557
 
    if (mir_pointer_event_button_state(pev, mir_pointer_button_back))
558
 
        buttons |= Qt::BackButton;
559
 
    if (mir_pointer_event_button_state(pev, mir_pointer_button_forward))
560
 
        buttons |= Qt::ForwardButton;
561
 
 
562
 
    return buttons;
563
 
}
564
 
} // namespace
565
 
 
566
 
void QtEventFeeder::dispatchPointer(const MirPointerEvent *pev)
567
 
{
568
 
    auto timestamp = qtmir::compressTimestamp<qtmir::Timestamp>(
569
 
                std::chrono::nanoseconds(mir_input_event_get_event_time(
570
 
                                             mir_pointer_event_input_event(pev))));
571
 
    auto action = mir_pointer_event_action(pev);
572
 
    qCDebug(QTMIR_MIR_INPUT) << "Received" << qPrintable(mirPointerEventToString(pev));
573
 
 
574
 
    auto modifiers = getQtModifiersFromMir(mir_pointer_event_modifiers(pev));
575
 
 
576
 
    auto relative = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_x),
577
 
                            mir_pointer_event_axis_value(pev, mir_pointer_axis_relative_y));
578
 
    auto absolute = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x),
579
 
                            mir_pointer_event_axis_value(pev, mir_pointer_axis_y));
580
 
 
581
 
    switch (action) {
582
 
    case mir_pointer_action_button_up:
583
 
    case mir_pointer_action_button_down:
584
 
    case mir_pointer_action_motion:
585
 
    {
586
 
        const float hDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_hscroll);
587
 
        const float vDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_vscroll);
588
 
 
589
 
        if (hDelta != 0 || vDelta != 0) {
590
 
            // QWheelEvent::DefaultDeltasPerStep = 120 but not defined on vivid
591
 
            const QPoint angleDelta(120 * hDelta, 120 * vDelta);
592
 
            mQtWindowSystem->handleWheelEvent(timestamp.count(), absolute, angleDelta, modifiers);
593
 
        }
594
 
        auto buttons = getQtMouseButtonsfromMirPointerEvent(pev);
595
 
        mQtWindowSystem->handleMouseEvent(timestamp.count(), relative, absolute, buttons, modifiers);
596
 
        break;
597
 
    }
598
 
    default:
599
 
        qCDebug(QTMIR_MIR_INPUT) << "Unrecognized pointer event";
600
 
    }
601
 
}
602
 
 
603
 
void QtEventFeeder::dispatchKey(const MirKeyboardEvent *kev)
604
 
{
605
 
    auto timestamp = qtmir::compressTimestamp<qtmir::Timestamp>(
606
 
                std::chrono::nanoseconds(mir_input_event_get_event_time(
607
 
                                             mir_keyboard_event_input_event(kev))));
608
 
 
609
 
    xkb_keysym_t xk_sym = mir_keyboard_event_key_code(kev);
610
 
 
611
 
    // Key modifier and unicode index mapping.
612
 
    auto modifiers = getQtModifiersFromMir(mir_keyboard_event_modifiers(kev));
613
 
 
614
 
    // Key action
615
 
    QEvent::Type keyType = QEvent::KeyRelease;
616
 
    bool is_auto_rep = false;
617
 
 
618
 
    switch (mir_keyboard_event_action(kev))
619
 
    {
620
 
    case mir_keyboard_action_repeat:
621
 
        is_auto_rep = true; // fall-through
622
 
    case mir_keyboard_action_down:
623
 
        keyType = QEvent::KeyPress;
624
 
        break;
625
 
    case mir_keyboard_action_up:
626
 
        keyType = QEvent::KeyRelease;
627
 
        break;
628
 
    default:
629
 
        break;
630
 
    }
631
 
 
632
 
    // Key event propagation.
633
 
    QString text;
634
 
    QVarLengthArray<char, 32> chars(32);
635
 
    {
636
 
        int result = xkb_keysym_to_utf8(xk_sym, chars.data(), chars.size());
637
 
 
638
 
        if (result > 0) {
639
 
            text = QString::fromUtf8(chars.constData());
640
 
        }
641
 
    }
642
 
    int keyCode = translateKeysym(xk_sym, text);
643
 
 
644
 
    QPlatformInputContext* context = QGuiApplicationPrivate::platformIntegration()->inputContext();
645
 
    if (context) {
646
 
        // TODO: consider event.repeat_count
647
 
        QKeyEvent qKeyEvent(keyType, keyCode, modifiers,
648
 
                            mir_keyboard_event_scan_code(kev),
649
 
                            mir_keyboard_event_key_code(kev),
650
 
                            mir_keyboard_event_modifiers(kev),
651
 
                            text, is_auto_rep);
652
 
        qKeyEvent.setTimestamp(timestamp.count());
653
 
        if (context->filterEvent(&qKeyEvent)) {
654
 
            qCDebug(QTMIR_MIR_INPUT) << "Received" << qPrintable(mirKeyboardEventToString(kev))
655
 
                << "but not dispatching as it was filtered out by input context";
656
 
            return;
657
 
        }
658
 
    }
659
 
 
660
 
    qCDebug(QTMIR_MIR_INPUT).nospace() << "Received " << qPrintable(mirKeyboardEventToString(kev))
661
 
        << ". Dispatching to " << mQtWindowSystem->focusedWindow();
662
 
 
663
 
    mQtWindowSystem->handleExtendedKeyEvent(mQtWindowSystem->focusedWindow(),
664
 
        timestamp.count(), keyType, keyCode, modifiers,
665
 
        mir_keyboard_event_scan_code(kev), xk_sym,
666
 
        mir_keyboard_event_modifiers(kev), text, is_auto_rep);
667
 
}
668
 
 
669
 
void QtEventFeeder::dispatchTouch(const MirTouchEvent *tev)
670
 
{
671
 
    auto timestamp = qtmir::compressTimestamp<qtmir::Timestamp>(
672
 
                std::chrono::nanoseconds(mir_input_event_get_event_time(
673
 
                                             mir_touch_event_input_event(tev))));
674
 
 
675
 
    tracepoint(qtmirserver, touchEventDispatch_start, std::chrono::nanoseconds(timestamp).count());
676
 
 
677
 
    qCDebug(QTMIR_MIR_INPUT) << "Received" << qPrintable(mirTouchEventToString(tev));
678
 
 
679
 
    // FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That
680
 
    //     needs to be fixed as soon as the compat input lib adds query support.
681
 
    const float kMaxPressure = 1.28;
682
 
    const int kPointerCount = mir_touch_event_point_count(tev);
683
 
    QList<QWindowSystemInterface::TouchPoint> touchPoints;
684
 
    QWindow *window = nullptr;
685
 
 
686
 
    if (kPointerCount > 0) {
687
 
        window = mQtWindowSystem->getWindowForTouchPoint(
688
 
                    QPoint(mir_touch_event_axis_value(tev, 0, mir_touch_axis_x),
689
 
                           mir_touch_event_axis_value(tev, 0, mir_touch_axis_y)));
690
 
 
691
 
        if (!window) {
692
 
            qCDebug(QTMIR_MIR_INPUT) << "REJECTING INPUT EVENT, no matching window";
693
 
            return;
694
 
        }
695
 
 
696
 
        const QRect kWindowGeometry = window->geometry();
697
 
 
698
 
        // TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left
699
 
        //       as Qt::TouchPointMoved
700
 
        for (int i = 0; i < kPointerCount; ++i) {
701
 
            QWindowSystemInterface::TouchPoint touchPoint;
702
 
 
703
 
            const float kX = mir_touch_event_axis_value(tev, i, mir_touch_axis_x);
704
 
            const float kY = mir_touch_event_axis_value(tev, i, mir_touch_axis_y);
705
 
            const float kW = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_major);
706
 
            const float kH = mir_touch_event_axis_value(tev, i, mir_touch_axis_touch_minor);
707
 
            const float kP = mir_touch_event_axis_value(tev, i, mir_touch_axis_pressure);
708
 
            touchPoint.id = mir_touch_event_id(tev, i);
709
 
 
710
 
            touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());
711
 
            touchPoint.area = QRectF(kX - (kW / 2.0), kY - (kH / 2.0), kW, kH);
712
 
            touchPoint.pressure = kP / kMaxPressure;
713
 
            switch (mir_touch_event_action(tev, i))
714
 
            {
715
 
            case mir_touch_action_up:
716
 
                touchPoint.state = Qt::TouchPointReleased;
717
 
                break;
718
 
            case mir_touch_action_down:
719
 
                touchPoint.state = Qt::TouchPointPressed;
720
 
                break;
721
 
            case mir_touch_action_change:
722
 
                touchPoint.state = Qt::TouchPointMoved;
723
 
                break;
724
 
            default:
725
 
                break;
726
 
            }
727
 
 
728
 
            touchPoints.append(touchPoint);
729
 
        }
730
 
    }
731
 
 
732
 
    // Qt needs a happy, sane stream of touch events. So let's make sure we're not forwarding
733
 
    // any insanity.
734
 
    validateTouches(window, timestamp.count(), touchPoints);
735
 
 
736
 
    // Touch event propagation.
737
 
    qCDebug(QTMIR_MIR_INPUT) << "Sending to Qt" << qPrintable(touchesToString(touchPoints));
738
 
    mQtWindowSystem->handleTouchEvent(window,
739
 
        //scales down the nsec_t (int64) to fit a ulong, precision lost but time difference suitable
740
 
        timestamp.count(),
741
 
        mTouchDevice,
742
 
        touchPoints);
743
 
 
744
 
    tracepoint(qtmirserver, touchEventDispatch_end, std::chrono::nanoseconds(timestamp).count());
745
 
}
746
 
 
747
 
void QtEventFeeder::validateTouches(QWindow *window, ulong timestamp,
748
 
        QList<QWindowSystemInterface::TouchPoint> &touchPoints)
749
 
{
750
 
    QSet<int> updatedTouches;
751
 
 
752
 
    {
753
 
        int i = 0;
754
 
        while (i < touchPoints.count()) {
755
 
            bool mustDiscardTouch = !validateTouch(touchPoints[i]);
756
 
            if (mustDiscardTouch) {
757
 
                touchPoints.removeAt(i);
758
 
            } else {
759
 
                updatedTouches.insert(touchPoints.at(i).id);
760
 
                ++i;
761
 
            }
762
 
        }
763
 
    }
764
 
 
765
 
    // Release all unmentioned touches, one by one.
766
 
    QHash<int, QWindowSystemInterface::TouchPoint>::iterator it = mActiveTouches.begin();
767
 
    while (it != mActiveTouches.end()) {
768
 
        if (!updatedTouches.contains(it.key())) {
769
 
            qCWarning(QTMIR_MIR_INPUT)
770
 
                << "There's a touch (id =" << it.key() << ") missing. Releasing it.";
771
 
            sendActiveTouchRelease(window, timestamp, it.key());
772
 
            it = mActiveTouches.erase(it);
773
 
        } else {
774
 
            ++it;
775
 
        }
776
 
    }
777
 
 
778
 
    // update mActiveTouches
779
 
    for (int i = 0; i < touchPoints.count(); ++i) {
780
 
        auto &touchPoint = touchPoints.at(i);
781
 
        if (touchPoint.state == Qt::TouchPointReleased) {
782
 
            mActiveTouches.remove(touchPoint.id);
783
 
        } else {
784
 
            mActiveTouches[touchPoint.id] = touchPoint;
785
 
        }
786
 
    }
787
 
}
788
 
 
789
 
void QtEventFeeder::sendActiveTouchRelease(QWindow *window, ulong timestamp, int id)
790
 
{
791
 
    QList<QWindowSystemInterface::TouchPoint> touchPoints = mActiveTouches.values();
792
 
 
793
 
    for (int i = 0; i < touchPoints.count(); ++i) {
794
 
        QWindowSystemInterface::TouchPoint &touchPoint = touchPoints[i];
795
 
        if (touchPoint.id == id) {
796
 
            touchPoint.state = Qt::TouchPointReleased;
797
 
        } else {
798
 
            touchPoint.state = Qt::TouchPointStationary;
799
 
        }
800
 
    }
801
 
 
802
 
    qCDebug(QTMIR_MIR_INPUT) << "Sending to Qt" << qPrintable(touchesToString(touchPoints));
803
 
    mQtWindowSystem->handleTouchEvent(window, timestamp, mTouchDevice, touchPoints);
804
 
}
805
 
 
806
 
bool QtEventFeeder::validateTouch(QWindowSystemInterface::TouchPoint &touchPoint)
807
 
{
808
 
    bool ok = true;
809
 
 
810
 
    switch (touchPoint.state) {
811
 
    case Qt::TouchPointPressed:
812
 
        if (mActiveTouches.contains(touchPoint.id)) {
813
 
            qCWarning(QTMIR_MIR_INPUT)
814
 
                << "Would press an already existing touch (id =" << touchPoint.id
815
 
                << "). Making it move instead.";
816
 
            touchPoint.state = Qt::TouchPointMoved;
817
 
        }
818
 
        break;
819
 
    case Qt::TouchPointMoved:
820
 
        if (!mActiveTouches.contains(touchPoint.id)) {
821
 
            qCWarning(QTMIR_MIR_INPUT)
822
 
                << "Would move a touch that wasn't pressed before (id =" << touchPoint.id
823
 
                << "). Making it press instead.";
824
 
            touchPoint.state = Qt::TouchPointPressed;
825
 
        }
826
 
        break;
827
 
    case Qt::TouchPointStationary:
828
 
        if (!mActiveTouches.contains(touchPoint.id)) {
829
 
            qCWarning(QTMIR_MIR_INPUT)
830
 
                << "There's an stationary touch that wasn't pressed before (id =" << touchPoint.id
831
 
                << "). Making it press instead.";
832
 
            touchPoint.state = Qt::TouchPointPressed;
833
 
        }
834
 
        break;
835
 
    case Qt::TouchPointReleased:
836
 
        if (!mActiveTouches.contains(touchPoint.id)) {
837
 
            qCWarning(QTMIR_MIR_INPUT)
838
 
                << "Would release a touch that wasn't pressed before (id =" << touchPoint.id
839
 
                << "). Ignoring it.";
840
 
            ok = false;
841
 
        }
842
 
        break;
843
 
    default:
844
 
        qFatal("QtEventFeeder: invalid touch state");
845
 
    }
846
 
 
847
 
    return ok;
848
 
}
849
 
 
850
 
QString QtEventFeeder::touchesToString(const QList<struct QWindowSystemInterface::TouchPoint> &points)
851
 
{
852
 
    QString result;
853
 
    for (int i = 0; i < points.count(); ++i) {
854
 
        if (i > 0) {
855
 
            result.append(",");
856
 
        }
857
 
        const struct QWindowSystemInterface::TouchPoint &point = points.at(i);
858
 
        result.append(QStringLiteral("(id=%1,state=%2,normalPosition=(%3,%4))")
859
 
            .arg(point.id)
860
 
            .arg(touchPointStateToString(point.state))
861
 
            .arg(point.normalPosition.x())
862
 
            .arg(point.normalPosition.y())
863
 
            );
864
 
    }
865
 
    return result;
866
 
}