24
29
#include <QtCore/QCoreApplication>
25
30
#include <private/qguiapplication_p.h>
26
31
#include <qpa/qplatforminputcontext.h>
32
#include <qpa/qwindowsysteminterface.h>
34
#include <xkbcommon/xkbcommon.h>
35
#include <xkbcommon/xkbcommon-keysyms.h>
27
38
#include <ubuntu/application/ui/input/event.h>
28
#include <input/input_stack_compatibility_layer_flags.h>
30
40
#define LOG_EVENTS 0
42
// XKB Keysyms which do not map directly to Qt types (i.e. Unicode points)
43
static const uint32_t KeyTable[] = {
44
XKB_KEY_Escape, Qt::Key_Escape,
45
XKB_KEY_Tab, Qt::Key_Tab,
46
XKB_KEY_ISO_Left_Tab, Qt::Key_Backtab,
47
XKB_KEY_BackSpace, Qt::Key_Backspace,
48
XKB_KEY_Return, Qt::Key_Return,
49
XKB_KEY_Insert, Qt::Key_Insert,
50
XKB_KEY_Delete, Qt::Key_Delete,
51
XKB_KEY_Clear, Qt::Key_Delete,
52
XKB_KEY_Pause, Qt::Key_Pause,
53
XKB_KEY_Print, Qt::Key_Print,
55
XKB_KEY_Home, Qt::Key_Home,
56
XKB_KEY_End, Qt::Key_End,
57
XKB_KEY_Left, Qt::Key_Left,
58
XKB_KEY_Up, Qt::Key_Up,
59
XKB_KEY_Right, Qt::Key_Right,
60
XKB_KEY_Down, Qt::Key_Down,
61
XKB_KEY_Prior, Qt::Key_PageUp,
62
XKB_KEY_Next, Qt::Key_PageDown,
64
XKB_KEY_Shift_L, Qt::Key_Shift,
65
XKB_KEY_Shift_R, Qt::Key_Shift,
66
XKB_KEY_Shift_Lock, Qt::Key_Shift,
67
XKB_KEY_Control_L, Qt::Key_Control,
68
XKB_KEY_Control_R, Qt::Key_Control,
69
XKB_KEY_Meta_L, Qt::Key_Meta,
70
XKB_KEY_Meta_R, Qt::Key_Meta,
71
XKB_KEY_Alt_L, Qt::Key_Alt,
72
XKB_KEY_Alt_R, Qt::Key_Alt,
73
XKB_KEY_Caps_Lock, Qt::Key_CapsLock,
74
XKB_KEY_Num_Lock, Qt::Key_NumLock,
75
XKB_KEY_Scroll_Lock, Qt::Key_ScrollLock,
76
XKB_KEY_Super_L, Qt::Key_Super_L,
77
XKB_KEY_Super_R, Qt::Key_Super_R,
78
XKB_KEY_Menu, Qt::Key_Menu,
79
XKB_KEY_Hyper_L, Qt::Key_Hyper_L,
80
XKB_KEY_Hyper_R, Qt::Key_Hyper_R,
81
XKB_KEY_Help, Qt::Key_Help,
83
XKB_KEY_KP_Space, Qt::Key_Space,
84
XKB_KEY_KP_Tab, Qt::Key_Tab,
85
XKB_KEY_KP_Enter, Qt::Key_Enter,
86
XKB_KEY_KP_Home, Qt::Key_Home,
87
XKB_KEY_KP_Left, Qt::Key_Left,
88
XKB_KEY_KP_Up, Qt::Key_Up,
89
XKB_KEY_KP_Right, Qt::Key_Right,
90
XKB_KEY_KP_Down, Qt::Key_Down,
91
XKB_KEY_KP_Prior, Qt::Key_PageUp,
92
XKB_KEY_KP_Next, Qt::Key_PageDown,
93
XKB_KEY_KP_End, Qt::Key_End,
94
XKB_KEY_KP_Begin, Qt::Key_Clear,
95
XKB_KEY_KP_Insert, Qt::Key_Insert,
96
XKB_KEY_KP_Delete, Qt::Key_Delete,
97
XKB_KEY_KP_Equal, Qt::Key_Equal,
98
XKB_KEY_KP_Multiply, Qt::Key_Asterisk,
99
XKB_KEY_KP_Add, Qt::Key_Plus,
100
XKB_KEY_KP_Separator, Qt::Key_Comma,
101
XKB_KEY_KP_Subtract, Qt::Key_Minus,
102
XKB_KEY_KP_Decimal, Qt::Key_Period,
103
XKB_KEY_KP_Divide, Qt::Key_Slash,
105
XKB_KEY_ISO_Level3_Shift, Qt::Key_AltGr,
106
XKB_KEY_Multi_key, Qt::Key_Multi_key,
107
XKB_KEY_Codeinput, Qt::Key_Codeinput,
108
XKB_KEY_SingleCandidate, Qt::Key_SingleCandidate,
109
XKB_KEY_MultipleCandidate, Qt::Key_MultipleCandidate,
110
XKB_KEY_PreviousCandidate, Qt::Key_PreviousCandidate,
112
XKB_KEY_Mode_switch, Qt::Key_Mode_switch,
113
XKB_KEY_script_switch, Qt::Key_Mode_switch,
114
XKB_KEY_XF86AudioRaiseVolume, Qt::Key_VolumeUp,
115
XKB_KEY_XF86AudioLowerVolume, Qt::Key_VolumeDown,
116
XKB_KEY_XF86PowerOff, Qt::Key_PowerOff,
117
XKB_KEY_XF86PowerDown, Qt::Key_PowerDown,
32
122
// Lookup table for the key types.
33
123
// FIXME(loicm) Not sure what to do with that multiple thing.
34
124
static const QEvent::Type kEventType[] = {
35
QEvent::KeyPress, // ISCL_KEY_EVENT_ACTION_DOWN = 0
36
QEvent::KeyRelease, // ISCL_KEY_EVENT_ACTION_UP = 1
37
QEvent::KeyPress // ISCL_KEY_EVENT_ACTION_MULTIPLE = 2
40
// Lookup table for the key codes and unicode values.
42
const quint32 keycode;
43
const quint16 unicode[3]; // { no modifier, shift modifier, other modifiers }
45
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_UNKNOWN = 0
46
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_SOFT_LEFT = 1
47
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_SOFT_RIGHT = 2
48
{ Qt::Key_Home, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_HOME = 3
49
{ Qt::Key_Back, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BACK = 4
50
{ Qt::Key_Call, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CALL = 5
51
{ Qt::Key_Hangup, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_ENDCALL = 6
52
{ Qt::Key_0, { 0x0030, 0x0029, 0xffff } }, // ISCL_KEYCODE_0 = 7
53
{ Qt::Key_1, { 0x0031, 0xffff, 0xffff } }, // ISCL_KEYCODE_1 = 8
54
{ Qt::Key_2, { 0x0032, 0xffff, 0xffff } }, // ISCL_KEYCODE_2 = 9
55
{ Qt::Key_3, { 0x0033, 0xffff, 0xffff } }, // ISCL_KEYCODE_3 = 10
56
{ Qt::Key_4, { 0x0034, 0xffff, 0xffff } }, // ISCL_KEYCODE_4 = 11
57
{ Qt::Key_5, { 0x0035, 0xffff, 0xffff } }, // ISCL_KEYCODE_5 = 12
58
{ Qt::Key_6, { 0x0036, 0xffff, 0xffff } }, // ISCL_KEYCODE_6 = 13
59
{ Qt::Key_7, { 0x0037, 0xffff, 0xffff } }, // ISCL_KEYCODE_7 = 14
60
{ Qt::Key_8, { 0x0038, 0xffff, 0xffff } }, // ISCL_KEYCODE_8 = 15
61
{ Qt::Key_9, { 0x0039, 0x0028, 0xffff } }, // ISCL_KEYCODE_9 = 16
62
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_STAR = 17
63
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_POUND = 18
64
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_DPAD_UP = 19
65
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_DPAD_DOWN = 20
66
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_DPAD_LEFT = 21
67
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_DPAD_RIGHT = 22
68
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_DPAD_CENTER = 23
69
{ Qt::Key_VolumeUp, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_VOLUME_UP = 24
70
{ Qt::Key_VolumeDown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_VOLUME_DOWN = 25
71
{ Qt::Key_PowerOff, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_POWER = 26
72
{ Qt::Key_Camera, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CAMERA = 27
73
{ Qt::Key_Clear, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CLEAR = 28
74
{ Qt::Key_A, { 0x0061, 0x0041, 0xffff } }, // ISCL_KEYCODE_A = 29
75
{ Qt::Key_B, { 0x0062, 0x0042, 0xffff } }, // ISCL_KEYCODE_B = 30
76
{ Qt::Key_C, { 0x0063, 0x0043, 0xffff } }, // ISCL_KEYCODE_C = 31
77
{ Qt::Key_D, { 0x0064, 0x0044, 0xffff } }, // ISCL_KEYCODE_D = 32
78
{ Qt::Key_E, { 0x0065, 0x0045, 0xffff } }, // ISCL_KEYCODE_E = 33
79
{ Qt::Key_F, { 0x0066, 0x0046, 0xffff } }, // ISCL_KEYCODE_F = 34
80
{ Qt::Key_G, { 0x0067, 0x0047, 0xffff } }, // ISCL_KEYCODE_G = 35
81
{ Qt::Key_H, { 0x0068, 0x0048, 0xffff } }, // ISCL_KEYCODE_H = 36
82
{ Qt::Key_I, { 0x0069, 0x0049, 0xffff } }, // ISCL_KEYCODE_I = 37
83
{ Qt::Key_J, { 0x006a, 0x004a, 0xffff } }, // ISCL_KEYCODE_J = 38
84
{ Qt::Key_K, { 0x006b, 0x004b, 0xffff } }, // ISCL_KEYCODE_K = 39
85
{ Qt::Key_L, { 0x006c, 0x004c, 0xffff } }, // ISCL_KEYCODE_L = 40
86
{ Qt::Key_M, { 0x006d, 0x004d, 0xffff } }, // ISCL_KEYCODE_M = 41
87
{ Qt::Key_N, { 0x006e, 0x004e, 0xffff } }, // ISCL_KEYCODE_N = 42
88
{ Qt::Key_O, { 0x006f, 0x004f, 0xffff } }, // ISCL_KEYCODE_O = 43
89
{ Qt::Key_P, { 0x0070, 0x0050, 0xffff } }, // ISCL_KEYCODE_P = 44
90
{ Qt::Key_Q, { 0x0071, 0x0051, 0xffff } }, // ISCL_KEYCODE_Q = 45
91
{ Qt::Key_R, { 0x0072, 0x0052, 0xffff } }, // ISCL_KEYCODE_R = 46
92
{ Qt::Key_S, { 0x0073, 0x0053, 0xffff } }, // ISCL_KEYCODE_S = 47
93
{ Qt::Key_T, { 0x0074, 0x0054, 0xffff } }, // ISCL_KEYCODE_T = 48
94
{ Qt::Key_U, { 0x0075, 0x0055, 0xffff } }, // ISCL_KEYCODE_U = 49
95
{ Qt::Key_V, { 0x0076, 0x0056, 0xffff } }, // ISCL_KEYCODE_V = 50
96
{ Qt::Key_W, { 0x0077, 0x0057, 0xffff } }, // ISCL_KEYCODE_W = 51
97
{ Qt::Key_X, { 0x0078, 0x0058, 0xffff } }, // ISCL_KEYCODE_X = 52
98
{ Qt::Key_Y, { 0x0079, 0x0059, 0xffff } }, // ISCL_KEYCODE_Y = 53
99
{ Qt::Key_Z, { 0x007a, 0x005a, 0xffff } }, // ISCL_KEYCODE_Z = 54
100
{ Qt::Key_Comma, { 0x002c, 0xffff, 0xffff } }, // ISCL_KEYCODE_COMMA = 55
101
{ Qt::Key_Period, { 0x002e, 0xffff, 0xffff } }, // ISCL_KEYCODE_PERIOD = 56
102
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_ALT_LEFT = 57
103
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_ALT_RIGHT = 58
104
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_SHIFT_LEFT = 59
105
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_SHIFT_RIGHT = 60
106
{ Qt::Key_Tab, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_TAB = 61
107
{ Qt::Key_Space, { 0x0020, 0xffff, 0xffff } }, // ISCL_KEYCODE_SPACE = 62
108
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_SYM = 63
109
{ Qt::Key_Explorer, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_EXPLORER = 64
110
{ Qt::Key_LaunchMail, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_ENVELOPE = 65
111
{ Qt::Key_Enter, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_ENTER = 66
112
{ Qt::Key_Delete, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_DEL = 67
113
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_GRAVE = 68
114
{ Qt::Key_Minus, { 0x002d, 0x005f, 0xffff } }, // ISCL_KEYCODE_MINUS = 69
115
{ Qt::Key_Equal, { 0x003d, 0xffff, 0xffff } }, // ISCL_KEYCODE_EQUALS = 70
116
{ Qt::Key_BracketLeft, { 0x005b, 0xffff, 0xffff } }, // ISCL_KEYCODE_LEFT_BRACKET = 71
117
{ Qt::Key_BracketRight, { 0x005d, 0xffff, 0xffff } }, // ISCL_KEYCODE_RIGHT_BRACKET = 72
118
{ Qt::Key_Backslash, { 0x005c, 0xffff, 0xffff } }, // ISCL_KEYCODE_BACKSLASH = 73
119
{ Qt::Key_Semicolon, { 0x003b, 0x003a, 0xffff } }, // ISCL_KEYCODE_SEMICOLON = 74
120
{ Qt::Key_Apostrophe, { 0x0027, 0xffff, 0xffff } }, // ISCL_KEYCODE_APOSTROPHE = 75
121
{ Qt::Key_Slash, { 0x002f, 0xffff, 0xffff } }, // ISCL_KEYCODE_SLASH = 76
122
{ Qt::Key_At, { 0x0040, 0xffff, 0xffff } }, // ISCL_KEYCODE_AT = 77
123
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUM = 78
124
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_HEADSETHOOK = 79
125
{ Qt::Key_CameraFocus, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_FOCUS = 80 // *Camera* focus
126
{ Qt::Key_Plus, { 0x002b, 0xffff, 0xffff } }, // ISCL_KEYCODE_PLUS = 81
127
{ Qt::Key_Menu, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MENU = 82
128
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_NOTIFICATION = 83
129
{ Qt::Key_Search, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_SEARCH = 84
130
{ Qt::Key_MediaTogglePlayPause, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_PLAY_PAUSE= 85
131
{ Qt::Key_MediaStop, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_STOP = 86
132
{ Qt::Key_MediaNext, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_NEXT = 87
133
{ Qt::Key_MediaPrevious, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_PREVIOUS = 88
134
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_REWIND = 89
135
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_FAST_FORWARD = 90
136
{ Qt::Key_VolumeMute, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MUTE = 91
137
{ Qt::Key_PageUp, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_PAGE_UP = 92
138
{ Qt::Key_PageDown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_PAGE_DOWN = 93
139
{ Qt::Key_Pictures, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_PICTSYMBOLS = 94
140
{ Qt::Key_Mode_switch, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_SWITCH_CHARSET = 95
141
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_A = 96
142
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_B = 97
143
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_C = 98
144
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_X = 99
145
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_Y = 100
146
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_Z = 101
147
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_L1 = 102
148
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_R1 = 103
149
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_L2 = 104
150
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_R2 = 105
151
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_THUMBL = 106
152
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_THUMBR = 107
153
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_START = 108
154
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_SELECT = 109
155
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_MODE = 110
156
{ Qt::Key_Escape, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_ESCAPE = 111
157
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_FORWARD_DEL = 112
158
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CTRL_LEFT = 113
159
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CTRL_RIGHT = 114
160
{ Qt::Key_CapsLock, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CAPS_LOCK = 115
161
{ Qt::Key_ScrollLock, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_SCROLL_LOCK = 116
162
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_META_LEFT = 117
163
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_META_RIGHT = 118
164
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_FUNCTION = 119
165
{ Qt::Key_SysReq, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_SYSRQ = 120
166
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BREAK = 121
167
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MOVE_HOME = 122
168
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MOVE_END = 123
169
{ Qt::Key_Insert, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_INSERT = 124
170
{ Qt::Key_Forward, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_FORWARD = 125
171
{ Qt::Key_MediaPlay, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_PLAY = 126
172
{ Qt::Key_MediaPause, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_PAUSE = 127
173
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_CLOSE = 128
174
{ Qt::Key_Eject, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_EJECT = 129
175
{ Qt::Key_MediaRecord, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MEDIA_RECORD = 130
176
{ Qt::Key_F1, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F1 = 131
177
{ Qt::Key_F2, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F2 = 132
178
{ Qt::Key_F3, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F3 = 133
179
{ Qt::Key_F4, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F4 = 134
180
{ Qt::Key_F5, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F5 = 135
181
{ Qt::Key_F6, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F6 = 136
182
{ Qt::Key_F7, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F7 = 137
183
{ Qt::Key_F8, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F8 = 138
184
{ Qt::Key_F9, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F9 = 139
185
{ Qt::Key_F10, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F10 = 140
186
{ Qt::Key_F11, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F11 = 141
187
{ Qt::Key_F12, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_F12 = 142
188
{ Qt::Key_NumLock, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUM_LOCK = 143
189
{ Qt::Key_0, { 0x0030, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_0 = 144
190
{ Qt::Key_1, { 0x0031, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_1 = 145
191
{ Qt::Key_2, { 0x0032, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_2 = 146
192
{ Qt::Key_3, { 0x0033, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_3 = 147
193
{ Qt::Key_4, { 0x0034, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_4 = 148
194
{ Qt::Key_5, { 0x0035, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_5 = 149
195
{ Qt::Key_6, { 0x0036, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_6 = 150
196
{ Qt::Key_7, { 0x0037, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_7 = 151
197
{ Qt::Key_8, { 0x0038, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_8 = 152
198
{ Qt::Key_9, { 0x0039, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_9 = 153
199
{ Qt::Key_Slash, { 0x002f, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_DIVIDE = 154
200
{ Qt::Key_Asterisk, { 0x002a, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_MULTIPLY = 155
201
{ Qt::Key_Minus, { 0x002d, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_SUBTRACT = 156
202
{ Qt::Key_Plus, { 0x002b, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_ADD = 157
203
{ Qt::Key_Period, { 0x002e, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_DOT = 158
204
{ Qt::Key_Comma, { 0x002c, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_COMMA = 159
205
{ Qt::Key_Enter, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_ENTER = 160
206
{ Qt::Key_Equal, { 0x003d, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_EQUALS = 161
207
{ Qt::Key_ParenLeft, { 0x0028, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_LEFT_PAREN = 162
208
{ Qt::Key_ParenRight, { 0x0029, 0xffff, 0xffff } }, // ISCL_KEYCODE_NUMPAD_RIGHT_PAREN = 163
209
{ Qt::Key_VolumeMute, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_VOLUME_MUTE = 164
210
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_INFO = 165
211
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CHANNEL_UP = 166
212
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CHANNEL_DOWN = 167
213
{ Qt::Key_ZoomIn, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_ZOOM_IN = 168
214
{ Qt::Key_ZoomOut, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_ZOOM_OUT = 169
215
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_TV = 170
216
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_WINDOW = 171
217
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_GUIDE = 172
218
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_DVR = 173
219
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BOOKMARK = 174
220
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CAPTIONS = 175
221
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_SETTINGS = 176
222
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_TV_POWER = 177
223
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_TV_INPUT = 178
224
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_STB_POWER = 179
225
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_STB_INPUT = 180
226
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_AVR_POWER = 181
227
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_AVR_INPUT = 182
228
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_PROG_RED = 183
229
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_PROG_GREEN = 184
230
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_PROG_YELLOW = 185
231
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_PROG_BLUE = 186
232
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_APP_SWITCH = 187
233
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_1 = 188
234
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_2 = 189
235
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_3 = 190
236
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_4 = 191
237
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_5 = 192
238
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_6 = 193
239
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_7 = 194
240
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_8 = 195
241
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_9 = 196
242
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_10 = 197
243
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_11 = 198
244
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_12 = 199
245
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_13 = 200
246
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_14 = 201
247
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_15 = 202
248
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_BUTTON_16 = 203
249
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_LANGUAGE_SWITCH = 204
250
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MANNER_MODE = 205
251
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_3D_MODE = 206
252
{ Qt::Key_unknown, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CONTACTS = 207
253
{ Qt::Key_Calendar, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_CALENDAR = 208
254
{ Qt::Key_Music, { 0xffff, 0xffff, 0xffff } }, // ISCL_KEYCODE_MUSIC = 209
255
{ Qt::Key_Calculator, { 0xffff, 0xffff, 0xffff } } // ISCL_KEYCODE_CALCULATOR = 210
258
class QUbuntuBaseEvent : public QEvent {
260
QUbuntuBaseEvent(QWindow* window, const Event* event, QEvent::Type type)
263
memcpy(&nativeEvent_, event, sizeof(Event));
269
QUbuntuBaseInput::QUbuntuBaseInput(QUbuntuBaseIntegration* integration)
270
: integration_(integration)
271
, eventFilterType_(static_cast<QUbuntuBaseNativeInterface*>(
125
QEvent::KeyPress, // U_KEY_ACTION_DOWN = 0
126
QEvent::KeyRelease, // U_KEY_ACTION_UP = 1
127
QEvent::KeyPress // U_KEY_ACTION_MULTIPLE = 2
130
class UbuntuEvent : public QEvent
133
UbuntuEvent(UbuntuWindow* window, const WindowEvent* event, QEvent::Type type)
134
: QEvent(type), window(window) {
135
memcpy(&nativeEvent, event, sizeof(WindowEvent));
137
UbuntuWindow* window;
138
WindowEvent nativeEvent;
141
UbuntuInput::UbuntuInput(UbuntuClientIntegration* integration)
143
, mIntegration(integration)
144
, mEventFilterType(static_cast<UbuntuNativeInterface*>(
272
145
integration->nativeInterface())->genericEventFilterType())
273
, eventType_(static_cast<QEvent::Type>(QEvent::registerEventType())) {
275
// Initialize touch device.
276
touchDevice_ = new QTouchDevice();
277
touchDevice_->setType(QTouchDevice::TouchScreen);
278
touchDevice_->setCapabilities(
279
QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure |
280
QTouchDevice::NormalizedPosition);
281
QWindowSystemInterface::registerTouchDevice(touchDevice_);
283
DLOG("QUbuntuBaseInput::QUbuntuBaseInput (this=%p, integration=%p)", this, integration);
286
QUbuntuBaseInput::~QUbuntuBaseInput() {
287
DLOG("QUbuntuBaseInput::~QUbuntuBaseInput");
288
// touchDevice_ isn't cleaned up on purpose as it crashes or asserts on "Bus Error".
291
void QUbuntuBaseInput::customEvent(QEvent* event) {
292
DLOG("QUbuntuBaseInput::customEvent (this=%p, event=%p)", this, event);
293
DASSERT(QThread::currentThread() == thread());
294
QUbuntuBaseEvent* ubuntuEvent = static_cast<QUbuntuBaseEvent*>(event);
298
if (QWindowSystemInterface::handleNativeEvent(
299
ubuntuEvent->window_, eventFilterType_, &ubuntuEvent->nativeEvent_, &result) == true) {
300
DLOG("event filtered out by native interface");
304
// Event dispatching.
305
switch (ubuntuEvent->nativeEvent_.type) {
306
case MOTION_EVENT_TYPE: {
307
dispatchMotionEvent(ubuntuEvent->window_, &ubuntuEvent->nativeEvent_);
310
case KEY_EVENT_TYPE: {
311
dispatchKeyEvent(ubuntuEvent->window_, &ubuntuEvent->nativeEvent_);
314
case HW_SWITCH_EVENT_TYPE: {
315
dispatchHWSwitchEvent(ubuntuEvent->window_, &ubuntuEvent->nativeEvent_);
319
DLOG("unhandled event type %d", ubuntuEvent->nativeEvent_.type);
324
void QUbuntuBaseInput::postEvent(QWindow* window, const void* event) {
325
DLOG("QUbuntuBaseInput::postEvent (this=%p, window=%p, event=%p)", this, window, event);
326
QCoreApplication::postEvent(this, new QUbuntuBaseEvent(
327
window, reinterpret_cast<const Event*>(event), eventType_));
329
if ((window->flags() && Qt::WindowTransparentForInput) && window->parent()) {
330
DLOG("QUbuntuBaseInput::postEvent (this=%p, window=%p, event=%p)", this, window->parent(), event);
331
QCoreApplication::postEvent(this, new QUbuntuBaseEvent(
332
window->parent(), reinterpret_cast<const Event*>(event), eventType_));
336
void QUbuntuBaseInput::dispatchMotionEvent(QWindow* window, const void* ev) {
337
DLOG("QUbuntuBaseInput::dispatchMotionEvent (this=%p, window=%p, event=%p)", this, window, ev);
338
const Event* event = reinterpret_cast<const Event*>(ev);
340
#if (LOG_EVENTS != 0)
341
// Motion event logging.
342
LOG("MOTION device_id:%d source_id:%d action:%d flags:%d meta_state:%d edge_flags:%d "
343
"button_state:%d x_offset:%.2f y_offset:%.2f x_precision:%.2f y_precision:%.2f "
344
"down_time:%lld event_time:%lld pointer_count:%d {", event->device_id,
345
event->source_id, event->action, event->flags, event->meta_state,
346
event->details.motion.edge_flags, event->details.motion.button_state,
347
event->details.motion.x_offset, event->details.motion.y_offset,
348
event->details.motion.x_precision, event->details.motion.y_precision,
349
event->details.motion.down_time, event->details.motion.event_time,
350
event->details.motion.pointer_count);
351
for (size_t i = 0; i < event->details.motion.pointer_count; i++) {
352
LOG(" id:%d x:%.2f y:%.2f rx:%.2f ry:%.2f maj:%.2f min:%.2f sz:%.2f press:%.2f",
353
event->details.motion.pointer_coordinates[i].id,
354
event->details.motion.pointer_coordinates[i].x,
355
event->details.motion.pointer_coordinates[i].y,
356
event->details.motion.pointer_coordinates[i].raw_x,
357
event->details.motion.pointer_coordinates[i].raw_y,
358
event->details.motion.pointer_coordinates[i].touch_major,
359
event->details.motion.pointer_coordinates[i].touch_minor,
360
event->details.motion.pointer_coordinates[i].size,
361
event->details.motion.pointer_coordinates[i].pressure
362
// event->details.motion.pointer_coordinates[i].orientation -> Always 0.0.
368
// FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That
369
// needs to be fixed as soon as the compat input lib adds query support.
370
const float kMaxPressure = 1.28;
371
const QRect kWindowGeometry = window->geometry();
372
QList<QWindowSystemInterface::TouchPoint> touchPoints;
375
// TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left
376
// as Qt::TouchPointMoved
377
const int kPointerCount = event->details.motion.pointer_count;
378
for (int i = 0; i < kPointerCount; ++i) {
379
QWindowSystemInterface::TouchPoint touchPoint;
381
const float kX = event->details.motion.pointer_coordinates[i].raw_x;
382
const float kY = event->details.motion.pointer_coordinates[i].raw_y;
383
const float kW = event->details.motion.pointer_coordinates[i].touch_major;
384
const float kH = event->details.motion.pointer_coordinates[i].touch_minor;
385
const float kP = event->details.motion.pointer_coordinates[i].pressure;
386
touchPoint.id = event->details.motion.pointer_coordinates[i].id;
387
touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());
388
touchPoint.area = QRectF(kX - (kW / 2.0), kY - (kH / 2.0), kW, kH);
389
touchPoint.pressure = kP / kMaxPressure;
390
touchPoint.state = Qt::TouchPointMoved;
392
touchPoints.append(touchPoint);
395
switch (event->action & ISCL_MOTION_EVENT_ACTION_MASK) {
396
case ISCL_MOTION_EVENT_ACTION_MOVE:
397
// No extra work needed.
400
case ISCL_MOTION_EVENT_ACTION_DOWN:
401
touchPoints[0].state = Qt::TouchPointPressed;
404
case ISCL_MOTION_EVENT_ACTION_UP:
405
touchPoints[0].state = Qt::TouchPointReleased;
408
case ISCL_MOTION_EVENT_ACTION_POINTER_DOWN: {
409
const int index = (event->action & ISCL_MOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
410
ISCL_MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
411
touchPoints[index].state = Qt::TouchPointPressed;
415
case ISCL_MOTION_EVENT_ACTION_CANCEL:
416
case ISCL_MOTION_EVENT_ACTION_POINTER_UP: {
417
const int index = (event->action & ISCL_MOTION_EVENT_ACTION_POINTER_INDEX_MASK) >>
418
ISCL_MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
419
touchPoints[index].state = Qt::TouchPointReleased;
423
case ISCL_MOTION_EVENT_ACTION_OUTSIDE:
424
case ISCL_MOTION_EVENT_ACTION_HOVER_MOVE:
425
case ISCL_MOTION_EVENT_ACTION_SCROLL:
426
case ISCL_MOTION_EVENT_ACTION_HOVER_ENTER:
427
case ISCL_MOTION_EVENT_ACTION_HOVER_EXIT:
429
DLOG("unhandled motion event action %d", event->action & ISCL_MOTION_EVENT_ACTION_MASK);
432
// Touch event propagation.
433
handleTouchEvent(window, event->details.motion.event_time / 1000000, touchDevice_, touchPoints);
436
void QUbuntuBaseInput::handleTouchEvent(
437
QWindow* window, ulong timestamp, QTouchDevice* device,
438
const QList<struct QWindowSystemInterface::TouchPoint> &points) {
439
DLOG("QUbuntuBaseInput::handleTouchEvent (this=%p, window=%p, timestamp=%lu, device=%p)",
440
this, window, timestamp, device);
441
QWindowSystemInterface::handleTouchEvent(window, timestamp, device, points);
444
void QUbuntuBaseInput::dispatchKeyEvent(QWindow* window, const void* ev) {
445
DLOG("QUbuntuBaseInput::dispatchKeyEvent (this=%p, window=%p, event=%p)", this, window, ev);
446
const Event* event = reinterpret_cast<const Event*>(ev);
448
#if (LOG_EVENTS != 0)
449
// Key event logging.
450
LOG("KEY device_id:%d source_id:%d action:%d flags:%d meta_state:%d key_code:%d "
451
"scan_code:%d repeat_count:%d down_time:%lld event_time:%lld is_system_key:%d",
452
event->device_id, event->source_id, event->action, event->flags, event->meta_state,
453
event->details.key.key_code, event->details.key.scan_code,
454
event->details.key.repeat_count, event->details.key.down_time,
455
event->details.key.event_time, event->details.key.is_system_key);
458
// Key modifier and unicode index mapping.
459
const int kMetaState = event->meta_state;
460
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
461
int unicodeIndex = 0;
462
if (kMetaState & ISCL_META_SHIFT_ON) {
463
modifiers |= Qt::ShiftModifier;
466
if (kMetaState & ISCL_META_CTRL_ON) {
467
modifiers |= Qt::ControlModifier;
470
if (kMetaState & ISCL_META_ALT_ON) {
471
modifiers |= Qt::AltModifier;
474
if (kMetaState & ISCL_META_META_ON) {
475
modifiers |= Qt::MetaModifier;
479
// Key event propagation.
480
QEvent::Type keyType = kEventType[event->action];
481
quint32 keyCode = kKeyCode[event->details.key.key_code].keycode;
482
QString text(kKeyCode[event->details.key.key_code].unicode[unicodeIndex]);
483
ulong timestamp = event->details.key.event_time / 1000000;
484
QPlatformInputContext* context = QGuiApplicationPrivate::platformIntegration()->inputContext();
486
QKeyEvent qKeyEvent(keyType, keyCode, modifiers, text);
487
qKeyEvent.setTimestamp(timestamp);
488
if (context->filterEvent(&qKeyEvent)) {
489
DLOG("key event filtered out by input context");
493
handleKeyEvent(window, timestamp, keyType, keyCode, modifiers, text);
496
void QUbuntuBaseInput::handleKeyEvent(
497
QWindow* window, ulong timestamp, QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
498
const QString& text) {
499
DLOG("QUbuntuBaseInput::handleKeyEvent (this=%p window=%p, timestamp=%lu, type=%d, key=%d, "
500
"modifiers=%d, text='%s')", this, window, timestamp, static_cast<int>(type), key,
501
static_cast<int>(modifiers), text.toUtf8().data());
502
QWindowSystemInterface::handleKeyEvent(window, timestamp, type, key, modifiers, text);
505
void QUbuntuBaseInput::dispatchHWSwitchEvent(QWindow* window, const void* ev) {
508
DLOG("QUbuntuBaseInput::dispatchSwitchEvent (this=%p, window=%p, event=%p)", this, window, ev);
510
#if (LOG_EVENTS != 0)
511
// HW switch event logging.
512
const Event* event = reinterpret_cast<const Event*>(ev);
513
LOG("HWSWITCH device_id:%d source_id:%d action:%d flags:%d meta_state:%d event_time:%lld "
514
"policy_flags:%u switch_values:%d switch_mask:%d", event->device_id, event->source_id,
515
event->action, event->flags, event->meta_state, event->details.hw_switch.event_time,
516
event->details.hw_switch.policy_flags, event->details.hw_switch.switch_values,
517
event->details.hw_switch.switch_mask);
520
// FIXME(loicm) Not sure how to interpret that kind of event.
521
DLOG("hw switch events are not handled");
146
, mEventType(static_cast<QEvent::Type>(QEvent::registerEventType()))
148
// Initialize touch device.
149
mTouchDevice = new QTouchDevice;
150
mTouchDevice->setType(QTouchDevice::TouchScreen);
151
mTouchDevice->setCapabilities(
152
QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::Pressure |
153
QTouchDevice::NormalizedPosition);
154
QWindowSystemInterface::registerTouchDevice(mTouchDevice);
157
UbuntuInput::~UbuntuInput()
159
// Qt will take care of deleting mTouchDevice.
163
static const char* nativeEventTypeToStr(int eventType)
166
case MOTION_WEVENT_TYPE:
167
return "MOTION_WEVENT_TYPE";
169
case KEY_WEVENT_TYPE:
170
return "KEY_WEVENT_TYPE";
172
case RESIZE_WEVENT_TYPE:
173
return "RESIZE_WEVENT_TYPE";
175
case SURFACE_WEVENT_TYPE:
176
return "SURFACE_WEVENT_TYPE";
183
void UbuntuInput::customEvent(QEvent* event)
185
DASSERT(QThread::currentThread() == thread());
186
UbuntuEvent* ubuntuEvent = static_cast<UbuntuEvent*>(event);
187
WindowEvent *nativeEvent = &ubuntuEvent->nativeEvent;
191
if (QWindowSystemInterface::handleNativeEvent(
192
ubuntuEvent->window->window(), mEventFilterType, nativeEvent, &result) == true) {
193
DLOG("event filtered out by native interface");
197
DLOG("UbuntuInput::customEvent(type=%s)", nativeEventTypeToStr(nativeEvent->type));
199
// Event dispatching.
200
switch (nativeEvent->type) {
201
case MOTION_WEVENT_TYPE:
202
dispatchMotionEvent(ubuntuEvent->window->window(), nativeEvent);
204
case KEY_WEVENT_TYPE:
205
dispatchKeyEvent(ubuntuEvent->window->window(), nativeEvent);
207
case RESIZE_WEVENT_TYPE:
208
ubuntuEvent->window->handleSurfaceResize(nativeEvent->resize.width,
209
nativeEvent->resize.height);
211
case SURFACE_WEVENT_TYPE:
212
if (nativeEvent->surface.attribute == SURFACE_ATTRIBUTE_FOCUS) {
213
ubuntuEvent->window->handleSurfaceFocusChange(nativeEvent->surface.value == 1);
217
DLOG("unhandled event type %d", nativeEvent->type);
221
void UbuntuInput::postEvent(UbuntuWindow* platformWindow, const void* event)
223
QWindow *window = platformWindow->window();
225
QCoreApplication::postEvent(this, new UbuntuEvent(
226
platformWindow, reinterpret_cast<const WindowEvent*>(event), mEventType));
228
if ((window->flags() && Qt::WindowTransparentForInput) && window->parent()) {
229
QCoreApplication::postEvent(this, new UbuntuEvent(
230
static_cast<UbuntuWindow*>(platformWindow->QPlatformWindow::parent()),
231
reinterpret_cast<const WindowEvent*>(event), mEventType));
235
void UbuntuInput::dispatchMotionEvent(QWindow* window, const void* ev)
237
const WindowEvent* event = reinterpret_cast<const WindowEvent*>(ev);
239
#if (LOG_EVENTS != 0)
240
// Motion event logging.
241
LOG("MOTION device_id:%d source_id:%d action:%d flags:%d meta_state:%d edge_flags:%d "
242
"button_state:%d x_offset:%.2f y_offset:%.2f x_precision:%.2f y_precision:%.2f "
243
"down_time:%lld event_time:%lld pointer_count:%d {", event->motion.device_id,
244
event->motion.source_id, event->motion.action,
245
event->motion.flags, event->motion.meta_state,
246
event->motion.edge_flags, event->motion.button_state,
247
event->motion.x_offset, event->motion.y_offset,
248
event->motion.x_precision, event->motion.y_precision,
249
event->motion.down_time, event->motion.event_time,
250
event->motion.pointer_count);
251
for (size_t i = 0; i < event->motion.pointer_count; i++) {
252
LOG(" id:%d x:%.2f y:%.2f rx:%.2f ry:%.2f maj:%.2f min:%.2f sz:%.2f press:%.2f",
253
event->motion.pointer_coordinates[i].id,
254
event->motion.pointer_coordinates[i].x,
255
event->motion.pointer_coordinates[i].y,
256
event->motion.pointer_coordinates[i].raw_x,
257
event->motion.pointer_coordinates[i].raw_y,
258
event->motion.pointer_coordinates[i].touch_major,
259
event->motion.pointer_coordinates[i].touch_minor,
260
event->motion.pointer_coordinates[i].size,
261
event->motion.pointer_coordinates[i].pressure
262
// event->motion.pointer_coordinates[i].orientation -> Always 0.0.
268
// FIXME(loicm) Max pressure is device specific. That one is for the Samsung Galaxy Nexus. That
269
// needs to be fixed as soon as the compat input lib adds query support.
270
const float kMaxPressure = 1.28;
271
const QRect kWindowGeometry = window->geometry();
272
QList<QWindowSystemInterface::TouchPoint> touchPoints;
275
// TODO: Is it worth setting the Qt::TouchPointStationary ones? Currently they are left
276
// as Qt::TouchPointMoved
277
const int kPointerCount = event->motion.pointer_count;
278
for (int i = 0; i < kPointerCount; ++i) {
279
QWindowSystemInterface::TouchPoint touchPoint;
281
const float kX = event->motion.pointer_coordinates[i].raw_x;
282
const float kY = event->motion.pointer_coordinates[i].raw_y;
283
const float kW = event->motion.pointer_coordinates[i].touch_major;
284
const float kH = event->motion.pointer_coordinates[i].touch_minor;
285
const float kP = event->motion.pointer_coordinates[i].pressure;
286
touchPoint.id = event->motion.pointer_coordinates[i].id;
287
touchPoint.normalPosition = QPointF(kX / kWindowGeometry.width(), kY / kWindowGeometry.height());
288
touchPoint.area = QRectF(kX - (kW / 2.0), kY - (kH / 2.0), kW, kH);
289
touchPoint.pressure = kP / kMaxPressure;
290
touchPoint.state = Qt::TouchPointMoved;
292
touchPoints.append(touchPoint);
295
switch (event->motion.action & U_MOTION_ACTION_MASK) {
296
case U_MOTION_ACTION_MOVE:
297
// No extra work needed.
300
case U_MOTION_ACTION_DOWN:
301
touchPoints[0].state = Qt::TouchPointPressed;
304
case U_MOTION_ACTION_UP:
305
touchPoints[0].state = Qt::TouchPointReleased;
308
case U_MOTION_ACTION_POINTER_DOWN: {
309
const int index = (event->motion.action & U_MOTION_ACTION_POINTER_INDEX_MASK) >>
310
U_MOTION_ACTION_POINTER_INDEX_SHIFT;
311
touchPoints[index].state = Qt::TouchPointPressed;
315
case U_MOTION_ACTION_CANCEL:
316
case U_MOTION_ACTION_POINTER_UP: {
317
const int index = (event->motion.action & U_MOTION_ACTION_POINTER_INDEX_MASK) >>
318
U_MOTION_ACTION_POINTER_INDEX_SHIFT;
319
touchPoints[index].state = Qt::TouchPointReleased;
323
case U_MOTION_ACTION_OUTSIDE:
324
case U_MOTION_ACTION_HOVER_MOVE:
325
case U_MOTION_ACTION_SCROLL:
326
case U_MOTION_ACTION_HOVER_ENTER:
327
case U_MOTION_ACTION_HOVER_EXIT:
329
DLOG("unhandled motion event action %d", event->motion.action & U_MOTION_ACTION_MASK);
332
QWindowSystemInterface::handleTouchEvent(window, event->motion.event_time / 1000000,
333
mTouchDevice, touchPoints);
336
static uint32_t translateKeysym(uint32_t sym, char *string, size_t size)
341
if (sym >= XKB_KEY_F1 && sym <= XKB_KEY_F35)
342
return Qt::Key_F1 + (int(sym) - XKB_KEY_F1);
344
for (int i = 0; KeyTable[i]; i += 2) {
345
if (sym == KeyTable[i])
346
return KeyTable[i + 1];
354
void UbuntuInput::dispatchKeyEvent(QWindow* window, const void* ev)
356
const WindowEvent* event = reinterpret_cast<const WindowEvent*>(ev);
358
#if (LOG_EVENTS != 0)
359
// Key event logging.
360
LOG("KEY device_id:%d source_id:%d action:%d flags:%d meta_state:%d key_code:%d "
361
"scan_code:%d repeat_count:%d down_time:%lld event_time:%lld is_system_key:%d",
362
event->key.device_id, event->key.source_id,
363
event->key.action, event->key.flags, event->key.meta_state,
364
event->key.key_code, event->key.scan_code,
365
event->key.repeat_count, event->key.down_time,
366
event->key.event_time, event->key.is_system_key);
369
ulong timestamp = event->key.event_time / 1000000;
370
xkb_keysym_t xk_sym = (xkb_keysym_t)event->key.key_code;
372
// Key modifier and unicode index mapping.
373
const int kMetaState = event->key.meta_state;
374
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
375
if (kMetaState & U_KEY_MODIFIER_SHIFT) {
376
modifiers |= Qt::ShiftModifier;
378
if (kMetaState & U_KEY_MODIFIER_CTRL) {
379
modifiers |= Qt::ControlModifier;
381
if (kMetaState & U_KEY_MODIFIER_ALT) {
382
modifiers |= Qt::AltModifier;
384
if (kMetaState & U_KEY_MODIFIER_META) {
385
modifiers |= Qt::MetaModifier;
388
QEvent::Type keyType = event->key.action == U_KEY_ACTION_DOWN ? QEvent::KeyPress : QEvent::KeyRelease;
391
int sym = translateKeysym(xk_sym, s, sizeof(s));
392
QString text = QString::fromLatin1(s);
394
QPlatformInputContext* context = QGuiApplicationPrivate::platformIntegration()->inputContext();
396
QKeyEvent qKeyEvent(keyType, sym, modifiers, text);
397
qKeyEvent.setTimestamp(timestamp);
398
if (context->filterEvent(&qKeyEvent)) {
399
DLOG("key event filtered out by input context");
404
QWindowSystemInterface::handleKeyEvent(window, timestamp, keyType, sym, modifiers, text);