eeba99f93bce0d36a725c73f9de31dad43554f34
[profile/ivi/qtbase.git] / src / plugins / platforms / windows / qwindowskeymapper.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwindowskeymapper.h"
43 #include "qwindowscontext.h"
44 #include "qwindowswindow.h"
45 #include "qwindowsguieventdispatcher.h"
46
47 #include <QtGui/QWindow>
48 #include <qpa/qwindowsysteminterface.h>
49 #include <QtGui/QKeyEvent>
50
51 QT_BEGIN_NAMESPACE
52
53 /*!
54     \class QWindowsKeyMapper
55     \brief Translates Windows keys to QWindowSystemInterface events.
56     \internal
57     \ingroup qt-lighthouse-win
58
59     In addition, handles some special keys to display system menus, etc.
60     The code originates from \c qkeymapper_win.cpp.
61 */
62
63 QWindowsKeyMapper::QWindowsKeyMapper()
64     : m_useRTLExtensions(false), m_keyGrabber(0)
65 {
66     memset(keyLayout, 0, sizeof(keyLayout));
67 }
68
69 QWindowsKeyMapper::~QWindowsKeyMapper()
70 {
71     deleteLayouts();
72 }
73
74 #ifndef LANG_PASHTO
75 #define LANG_PASHTO 0x63
76 #endif
77 #ifndef LANG_SYRIAC
78 #define LANG_SYRIAC 0x5a
79 #endif
80 #ifndef LANG_DIVEHI
81 #define LANG_DIVEHI 0x65
82 #endif
83 #ifndef VK_OEM_PLUS
84 #define VK_OEM_PLUS 0xBB
85 #endif
86 #ifndef VK_OEM_3
87 #define VK_OEM_3 0xC0
88 #endif
89
90 // Key recorder ------------------------------------------------------------------------[ start ] --
91 struct KeyRecord {
92     KeyRecord(int c, int a, int s, const QString &t) : code(c), ascii(a), state(s), text(t) {}
93     KeyRecord() {}
94
95     int code;
96     int ascii;
97     int state;
98     QString text;
99 };
100
101 static const int QT_MAX_KEY_RECORDINGS = 64; // User has LOTS of fingers...
102 struct KeyRecorder
103 {
104     KeyRecorder() : nrecs(0) {}
105
106     inline KeyRecord *findKey(int code, bool remove);
107     inline void storeKey(int code, int ascii, int state, const QString& text);
108     inline void clearKeys();
109
110     int nrecs;
111     KeyRecord deleted_record; // A copy of last entry removed from records[]
112     KeyRecord records[QT_MAX_KEY_RECORDINGS];
113 };
114 static KeyRecorder key_recorder;
115
116 KeyRecord *KeyRecorder::findKey(int code, bool remove)
117 {
118     KeyRecord *result = 0;
119     for (int i = 0; i < nrecs; ++i) {
120         if (records[i].code == code) {
121             if (remove) {
122                 deleted_record = records[i];
123                 // Move rest down, and decrease count
124                 while (i + 1 < nrecs) {
125                     records[i] = records[i + 1];
126                     ++i;
127                 }
128                 --nrecs;
129                 result = &deleted_record;
130             } else {
131                 result = &records[i];
132             }
133             break;
134         }
135     }
136     return result;
137 }
138
139 void KeyRecorder::storeKey(int code, int ascii, int state, const QString& text)
140 {
141     Q_ASSERT_X(nrecs != QT_MAX_KEY_RECORDINGS,
142                "Internal KeyRecorder",
143                "Keyboard recorder buffer overflow, consider increasing QT_MAX_KEY_RECORDINGS");
144
145     if (nrecs == QT_MAX_KEY_RECORDINGS) {
146         qWarning("Qt: Internal keyboard buffer overflow");
147         return;
148     }
149     records[nrecs++] = KeyRecord(code,ascii,state,text);
150 }
151
152 void KeyRecorder::clearKeys()
153 {
154     nrecs = 0;
155 }
156 // Key recorder --------------------------------------------------------------------------[ end ] --
157
158
159 // Key translation ---------------------------------------------------------------------[ start ] --
160 // Meaning of values:
161 //             0 = Character output key, needs keyboard driver mapping
162 //   Key_unknown = Unknown Virtual Key, no translation possible, ignore
163 static const uint KeyTbl[] = { // Keyboard mapping table
164                         // Dec |  Hex | Windows Virtual key
165     Qt::Key_unknown,    //   0   0x00
166     Qt::Key_unknown,    //   1   0x01   VK_LBUTTON          | Left mouse button
167     Qt::Key_unknown,    //   2   0x02   VK_RBUTTON          | Right mouse button
168     Qt::Key_Cancel,     //   3   0x03   VK_CANCEL           | Control-Break processing
169     Qt::Key_unknown,    //   4   0x04   VK_MBUTTON          | Middle mouse button
170     Qt::Key_unknown,    //   5   0x05   VK_XBUTTON1         | X1 mouse button
171     Qt::Key_unknown,    //   6   0x06   VK_XBUTTON2         | X2 mouse button
172     Qt::Key_unknown,    //   7   0x07   -- unassigned --
173     Qt::Key_Backspace,  //   8   0x08   VK_BACK             | BackSpace key
174     Qt::Key_Tab,        //   9   0x09   VK_TAB              | Tab key
175     Qt::Key_unknown,    //  10   0x0A   -- reserved --
176     Qt::Key_unknown,    //  11   0x0B   -- reserved --
177     Qt::Key_Clear,      //  12   0x0C   VK_CLEAR            | Clear key
178     Qt::Key_Return,     //  13   0x0D   VK_RETURN           | Enter key
179     Qt::Key_unknown,    //  14   0x0E   -- unassigned --
180     Qt::Key_unknown,    //  15   0x0F   -- unassigned --
181     Qt::Key_Shift,      //  16   0x10   VK_SHIFT            | Shift key
182     Qt::Key_Control,    //  17   0x11   VK_CONTROL          | Ctrl key
183     Qt::Key_Alt,        //  18   0x12   VK_MENU             | Alt key
184     Qt::Key_Pause,      //  19   0x13   VK_PAUSE            | Pause key
185     Qt::Key_CapsLock,   //  20   0x14   VK_CAPITAL          | Caps-Lock
186     Qt::Key_unknown,    //  21   0x15   VK_KANA / VK_HANGUL | IME Kana or Hangul mode
187     Qt::Key_unknown,    //  22   0x16   -- unassigned --
188     Qt::Key_unknown,    //  23   0x17   VK_JUNJA            | IME Junja mode
189     Qt::Key_unknown,    //  24   0x18   VK_FINAL            | IME final mode
190     Qt::Key_unknown,    //  25   0x19   VK_HANJA / VK_KANJI | IME Hanja or Kanji mode
191     Qt::Key_unknown,    //  26   0x1A   -- unassigned --
192     Qt::Key_Escape,     //  27   0x1B   VK_ESCAPE           | Esc key
193     Qt::Key_unknown,    //  28   0x1C   VK_CONVERT          | IME convert
194     Qt::Key_unknown,    //  29   0x1D   VK_NONCONVERT       | IME non-convert
195     Qt::Key_unknown,    //  30   0x1E   VK_ACCEPT           | IME accept
196     Qt::Key_Mode_switch,//  31   0x1F   VK_MODECHANGE       | IME mode change request
197     Qt::Key_Space,      //  32   0x20   VK_SPACE            | Spacebar
198     Qt::Key_PageUp,     //  33   0x21   VK_PRIOR            | Page Up key
199     Qt::Key_PageDown,   //  34   0x22   VK_NEXT             | Page Down key
200     Qt::Key_End,        //  35   0x23   VK_END              | End key
201     Qt::Key_Home,       //  36   0x24   VK_HOME             | Home key
202     Qt::Key_Left,       //  37   0x25   VK_LEFT             | Left arrow key
203     Qt::Key_Up,         //  38   0x26   VK_UP               | Up arrow key
204     Qt::Key_Right,      //  39   0x27   VK_RIGHT            | Right arrow key
205     Qt::Key_Down,       //  40   0x28   VK_DOWN             | Down arrow key
206     Qt::Key_Select,     //  41   0x29   VK_SELECT           | Select key
207     Qt::Key_Printer,    //  42   0x2A   VK_PRINT            | Print key
208     Qt::Key_Execute,    //  43   0x2B   VK_EXECUTE          | Execute key
209     Qt::Key_Print,      //  44   0x2C   VK_SNAPSHOT         | Print Screen key
210     Qt::Key_Insert,     //  45   0x2D   VK_INSERT           | Ins key
211     Qt::Key_Delete,     //  46   0x2E   VK_DELETE           | Del key
212     Qt::Key_Help,       //  47   0x2F   VK_HELP             | Help key
213     0,                  //  48   0x30   (VK_0)              | 0 key
214     0,                  //  49   0x31   (VK_1)              | 1 key
215     0,                  //  50   0x32   (VK_2)              | 2 key
216     0,                  //  51   0x33   (VK_3)              | 3 key
217     0,                  //  52   0x34   (VK_4)              | 4 key
218     0,                  //  53   0x35   (VK_5)              | 5 key
219     0,                  //  54   0x36   (VK_6)              | 6 key
220     0,                  //  55   0x37   (VK_7)              | 7 key
221     0,                  //  56   0x38   (VK_8)              | 8 key
222     0,                  //  57   0x39   (VK_9)              | 9 key
223     Qt::Key_unknown,    //  58   0x3A   -- unassigned --
224     Qt::Key_unknown,    //  59   0x3B   -- unassigned --
225     Qt::Key_unknown,    //  60   0x3C   -- unassigned --
226     Qt::Key_unknown,    //  61   0x3D   -- unassigned --
227     Qt::Key_unknown,    //  62   0x3E   -- unassigned --
228     Qt::Key_unknown,    //  63   0x3F   -- unassigned --
229     Qt::Key_unknown,    //  64   0x40   -- unassigned --
230     0,                  //  65   0x41   (VK_A)              | A key
231     0,                  //  66   0x42   (VK_B)              | B key
232     0,                  //  67   0x43   (VK_C)              | C key
233     0,                  //  68   0x44   (VK_D)              | D key
234     0,                  //  69   0x45   (VK_E)              | E key
235     0,                  //  70   0x46   (VK_F)              | F key
236     0,                  //  71   0x47   (VK_G)              | G key
237     0,                  //  72   0x48   (VK_H)              | H key
238     0,                  //  73   0x49   (VK_I)              | I key
239     0,                  //  74   0x4A   (VK_J)              | J key
240     0,                  //  75   0x4B   (VK_K)              | K key
241     0,                  //  76   0x4C   (VK_L)              | L key
242     0,                  //  77   0x4D   (VK_M)              | M key
243     0,                  //  78   0x4E   (VK_N)              | N key
244     0,                  //  79   0x4F   (VK_O)              | O key
245     0,                  //  80   0x50   (VK_P)              | P key
246     0,                  //  81   0x51   (VK_Q)              | Q key
247     0,                  //  82   0x52   (VK_R)              | R key
248     0,                  //  83   0x53   (VK_S)              | S key
249     0,                  //  84   0x54   (VK_T)              | T key
250     0,                  //  85   0x55   (VK_U)              | U key
251     0,                  //  86   0x56   (VK_V)              | V key
252     0,                  //  87   0x57   (VK_W)              | W key
253     0,                  //  88   0x58   (VK_X)              | X key
254     0,                  //  89   0x59   (VK_Y)              | Y key
255     0,                  //  90   0x5A   (VK_Z)              | Z key
256     Qt::Key_Meta,       //  91   0x5B   VK_LWIN             | Left Windows  - MS Natural kbd
257     Qt::Key_Meta,       //  92   0x5C   VK_RWIN             | Right Windows - MS Natural kbd
258     Qt::Key_Menu,       //  93   0x5D   VK_APPS             | Application key-MS Natural kbd
259     Qt::Key_unknown,    //  94   0x5E   -- reserved --
260     Qt::Key_Sleep,      //  95   0x5F   VK_SLEEP
261     Qt::Key_0,          //  96   0x60   VK_NUMPAD0          | Numeric keypad 0 key
262     Qt::Key_1,          //  97   0x61   VK_NUMPAD1          | Numeric keypad 1 key
263     Qt::Key_2,          //  98   0x62   VK_NUMPAD2          | Numeric keypad 2 key
264     Qt::Key_3,          //  99   0x63   VK_NUMPAD3          | Numeric keypad 3 key
265     Qt::Key_4,          // 100   0x64   VK_NUMPAD4          | Numeric keypad 4 key
266     Qt::Key_5,          // 101   0x65   VK_NUMPAD5          | Numeric keypad 5 key
267     Qt::Key_6,          // 102   0x66   VK_NUMPAD6          | Numeric keypad 6 key
268     Qt::Key_7,          // 103   0x67   VK_NUMPAD7          | Numeric keypad 7 key
269     Qt::Key_8,          // 104   0x68   VK_NUMPAD8          | Numeric keypad 8 key
270     Qt::Key_9,          // 105   0x69   VK_NUMPAD9          | Numeric keypad 9 key
271     Qt::Key_Asterisk,   // 106   0x6A   VK_MULTIPLY         | Multiply key
272     Qt::Key_Plus,       // 107   0x6B   VK_ADD              | Add key
273     Qt::Key_Comma,      // 108   0x6C   VK_SEPARATOR        | Separator key
274     Qt::Key_Minus,      // 109   0x6D   VK_SUBTRACT         | Subtract key
275     Qt::Key_Period,     // 110   0x6E   VK_DECIMAL          | Decimal key
276     Qt::Key_Slash,      // 111   0x6F   VK_DIVIDE           | Divide key
277     Qt::Key_F1,         // 112   0x70   VK_F1               | F1 key
278     Qt::Key_F2,         // 113   0x71   VK_F2               | F2 key
279     Qt::Key_F3,         // 114   0x72   VK_F3               | F3 key
280     Qt::Key_F4,         // 115   0x73   VK_F4               | F4 key
281     Qt::Key_F5,         // 116   0x74   VK_F5               | F5 key
282     Qt::Key_F6,         // 117   0x75   VK_F6               | F6 key
283     Qt::Key_F7,         // 118   0x76   VK_F7               | F7 key
284     Qt::Key_F8,         // 119   0x77   VK_F8               | F8 key
285     Qt::Key_F9,         // 120   0x78   VK_F9               | F9 key
286     Qt::Key_F10,        // 121   0x79   VK_F10              | F10 key
287     Qt::Key_F11,        // 122   0x7A   VK_F11              | F11 key
288     Qt::Key_F12,        // 123   0x7B   VK_F12              | F12 key
289     Qt::Key_F13,        // 124   0x7C   VK_F13              | F13 key
290     Qt::Key_F14,        // 125   0x7D   VK_F14              | F14 key
291     Qt::Key_F15,        // 126   0x7E   VK_F15              | F15 key
292     Qt::Key_F16,        // 127   0x7F   VK_F16              | F16 key
293     Qt::Key_F17,        // 128   0x80   VK_F17              | F17 key
294     Qt::Key_F18,        // 129   0x81   VK_F18              | F18 key
295     Qt::Key_F19,        // 130   0x82   VK_F19              | F19 key
296     Qt::Key_F20,        // 131   0x83   VK_F20              | F20 key
297     Qt::Key_F21,        // 132   0x84   VK_F21              | F21 key
298     Qt::Key_F22,        // 133   0x85   VK_F22              | F22 key
299     Qt::Key_F23,        // 134   0x86   VK_F23              | F23 key
300     Qt::Key_F24,        // 135   0x87   VK_F24              | F24 key
301     Qt::Key_unknown,    // 136   0x88   -- unassigned --
302     Qt::Key_unknown,    // 137   0x89   -- unassigned --
303     Qt::Key_unknown,    // 138   0x8A   -- unassigned --
304     Qt::Key_unknown,    // 139   0x8B   -- unassigned --
305     Qt::Key_unknown,    // 140   0x8C   -- unassigned --
306     Qt::Key_unknown,    // 141   0x8D   -- unassigned --
307     Qt::Key_unknown,    // 142   0x8E   -- unassigned --
308     Qt::Key_unknown,    // 143   0x8F   -- unassigned --
309     Qt::Key_NumLock,    // 144   0x90   VK_NUMLOCK          | Num Lock key
310     Qt::Key_ScrollLock, // 145   0x91   VK_SCROLL           | Scroll Lock key
311                         // Fujitsu/OASYS kbd --------------------
312     0, //Qt::Key_Jisho, // 146   0x92   VK_OEM_FJ_JISHO     | 'Dictionary' key /
313                         //              VK_OEM_NEC_EQUAL  = key on numpad on NEC PC-9800 kbd
314     Qt::Key_Massyo,     // 147   0x93   VK_OEM_FJ_MASSHOU   | 'Unregister word' key
315     Qt::Key_Touroku,    // 148   0x94   VK_OEM_FJ_TOUROKU   | 'Register word' key
316     0, //Qt::Key_Oyayubi_Left,//149   0x95  VK_OEM_FJ_LOYA  | 'Left OYAYUBI' key
317     0, //Qt::Key_Oyayubi_Right,//150  0x96  VK_OEM_FJ_ROYA  | 'Right OYAYUBI' key
318     Qt::Key_unknown,    // 151   0x97   -- unassigned --
319     Qt::Key_unknown,    // 152   0x98   -- unassigned --
320     Qt::Key_unknown,    // 153   0x99   -- unassigned --
321     Qt::Key_unknown,    // 154   0x9A   -- unassigned --
322     Qt::Key_unknown,    // 155   0x9B   -- unassigned --
323     Qt::Key_unknown,    // 156   0x9C   -- unassigned --
324     Qt::Key_unknown,    // 157   0x9D   -- unassigned --
325     Qt::Key_unknown,    // 158   0x9E   -- unassigned --
326     Qt::Key_unknown,    // 159   0x9F   -- unassigned --
327     Qt::Key_Shift,      // 160   0xA0   VK_LSHIFT           | Left Shift key
328     Qt::Key_Shift,      // 161   0xA1   VK_RSHIFT           | Right Shift key
329     Qt::Key_Control,    // 162   0xA2   VK_LCONTROL         | Left Ctrl key
330     Qt::Key_Control,    // 163   0xA3   VK_RCONTROL         | Right Ctrl key
331     Qt::Key_Alt,        // 164   0xA4   VK_LMENU            | Left Menu key
332     Qt::Key_Alt,        // 165   0xA5   VK_RMENU            | Right Menu key
333     Qt::Key_Back,       // 166   0xA6   VK_BROWSER_BACK     | Browser Back key
334     Qt::Key_Forward,    // 167   0xA7   VK_BROWSER_FORWARD  | Browser Forward key
335     Qt::Key_Refresh,    // 168   0xA8   VK_BROWSER_REFRESH  | Browser Refresh key
336     Qt::Key_Stop,       // 169   0xA9   VK_BROWSER_STOP     | Browser Stop key
337     Qt::Key_Search,     // 170   0xAA   VK_BROWSER_SEARCH   | Browser Search key
338     Qt::Key_Favorites,  // 171   0xAB   VK_BROWSER_FAVORITES| Browser Favorites key
339     Qt::Key_HomePage,   // 172   0xAC   VK_BROWSER_HOME     | Browser Start and Home key
340     Qt::Key_VolumeMute, // 173   0xAD   VK_VOLUME_MUTE      | Volume Mute key
341     Qt::Key_VolumeDown, // 174   0xAE   VK_VOLUME_DOWN      | Volume Down key
342     Qt::Key_VolumeUp,   // 175   0xAF   VK_VOLUME_UP        | Volume Up key
343     Qt::Key_MediaNext,  // 176   0xB0   VK_MEDIA_NEXT_TRACK | Next Track key
344     Qt::Key_MediaPrevious, //177 0xB1   VK_MEDIA_PREV_TRACK | Previous Track key
345     Qt::Key_MediaStop,  // 178   0xB2   VK_MEDIA_STOP       | Stop Media key
346     Qt::Key_MediaPlay,  // 179   0xB3   VK_MEDIA_PLAY_PAUSE | Play/Pause Media key
347     Qt::Key_LaunchMail, // 180   0xB4   VK_LAUNCH_MAIL      | Start Mail key
348     Qt::Key_LaunchMedia,// 181   0xB5   VK_LAUNCH_MEDIA_SELECT Select Media key
349     Qt::Key_Launch0,    // 182   0xB6   VK_LAUNCH_APP1      | Start Application 1 key
350     Qt::Key_Launch1,    // 183   0xB7   VK_LAUNCH_APP2      | Start Application 2 key
351     Qt::Key_unknown,    // 184   0xB8   -- reserved --
352     Qt::Key_unknown,    // 185   0xB9   -- reserved --
353     0,                  // 186   0xBA   VK_OEM_1            | ';:' for US
354     0,                  // 187   0xBB   VK_OEM_PLUS         | '+' any country
355     0,                  // 188   0xBC   VK_OEM_COMMA        | ',' any country
356     0,                  // 189   0xBD   VK_OEM_MINUS        | '-' any country
357     0,                  // 190   0xBE   VK_OEM_PERIOD       | '.' any country
358     0,                  // 191   0xBF   VK_OEM_2            | '/?' for US
359     0,                  // 192   0xC0   VK_OEM_3            | '`~' for US
360     Qt::Key_unknown,    // 193   0xC1   -- reserved --
361     Qt::Key_unknown,    // 194   0xC2   -- reserved --
362     Qt::Key_unknown,    // 195   0xC3   -- reserved --
363     Qt::Key_unknown,    // 196   0xC4   -- reserved --
364     Qt::Key_unknown,    // 197   0xC5   -- reserved --
365     Qt::Key_unknown,    // 198   0xC6   -- reserved --
366     Qt::Key_unknown,    // 199   0xC7   -- reserved --
367     Qt::Key_unknown,    // 200   0xC8   -- reserved --
368     Qt::Key_unknown,    // 201   0xC9   -- reserved --
369     Qt::Key_unknown,    // 202   0xCA   -- reserved --
370     Qt::Key_unknown,    // 203   0xCB   -- reserved --
371     Qt::Key_unknown,    // 204   0xCC   -- reserved --
372     Qt::Key_unknown,    // 205   0xCD   -- reserved --
373     Qt::Key_unknown,    // 206   0xCE   -- reserved --
374     Qt::Key_unknown,    // 207   0xCF   -- reserved --
375     Qt::Key_unknown,    // 208   0xD0   -- reserved --
376     Qt::Key_unknown,    // 209   0xD1   -- reserved --
377     Qt::Key_unknown,    // 210   0xD2   -- reserved --
378     Qt::Key_unknown,    // 211   0xD3   -- reserved --
379     Qt::Key_unknown,    // 212   0xD4   -- reserved --
380     Qt::Key_unknown,    // 213   0xD5   -- reserved --
381     Qt::Key_unknown,    // 214   0xD6   -- reserved --
382     Qt::Key_unknown,    // 215   0xD7   -- reserved --
383     Qt::Key_unknown,    // 216   0xD8   -- unassigned --
384     Qt::Key_unknown,    // 217   0xD9   -- unassigned --
385     Qt::Key_unknown,    // 218   0xDA   -- unassigned --
386     0,                  // 219   0xDB   VK_OEM_4            | '[{' for US
387     0,                  // 220   0xDC   VK_OEM_5            | '\|' for US
388     0,                  // 221   0xDD   VK_OEM_6            | ']}' for US
389     0,                  // 222   0xDE   VK_OEM_7            | ''"' for US
390     0,                  // 223   0xDF   VK_OEM_8
391     Qt::Key_unknown,    // 224   0xE0   -- reserved --
392     Qt::Key_unknown,    // 225   0xE1   VK_OEM_AX           | 'AX' key on Japanese AX kbd
393     Qt::Key_unknown,    // 226   0xE2   VK_OEM_102          | "<>" or "\|" on RT 102-key kbd
394     Qt::Key_unknown,    // 227   0xE3   VK_ICO_HELP         | Help key on ICO
395     Qt::Key_unknown,    // 228   0xE4   VK_ICO_00           | 00 key on ICO
396     Qt::Key_unknown,    // 229   0xE5   VK_PROCESSKEY       | IME Process key
397     Qt::Key_unknown,    // 230   0xE6   VK_ICO_CLEAR        |
398     Qt::Key_unknown,    // 231   0xE7   VK_PACKET           | Unicode char as keystrokes
399     Qt::Key_unknown,    // 232   0xE8   -- unassigned --
400                         // Nokia/Ericsson definitions ---------------
401     Qt::Key_unknown,    // 233   0xE9   VK_OEM_RESET
402     Qt::Key_unknown,    // 234   0xEA   VK_OEM_JUMP
403     Qt::Key_unknown,    // 235   0xEB   VK_OEM_PA1
404     Qt::Key_unknown,    // 236   0xEC   VK_OEM_PA2
405     Qt::Key_unknown,    // 237   0xED   VK_OEM_PA3
406     Qt::Key_unknown,    // 238   0xEE   VK_OEM_WSCTRL
407     Qt::Key_unknown,    // 239   0xEF   VK_OEM_CUSEL
408     Qt::Key_unknown,    // 240   0xF0   VK_OEM_ATTN
409     Qt::Key_unknown,    // 241   0xF1   VK_OEM_FINISH
410     Qt::Key_unknown,    // 242   0xF2   VK_OEM_COPY
411     Qt::Key_unknown,    // 243   0xF3   VK_OEM_AUTO
412     Qt::Key_unknown,    // 244   0xF4   VK_OEM_ENLW
413     Qt::Key_unknown,    // 245   0xF5   VK_OEM_BACKTAB
414     Qt::Key_unknown,    // 246   0xF6   VK_ATTN             | Attn key
415     Qt::Key_unknown,    // 247   0xF7   VK_CRSEL            | CrSel key
416     Qt::Key_unknown,    // 248   0xF8   VK_EXSEL            | ExSel key
417     Qt::Key_unknown,    // 249   0xF9   VK_EREOF            | Erase EOF key
418     Qt::Key_Play,       // 250   0xFA   VK_PLAY             | Play key
419     Qt::Key_Zoom,       // 251   0xFB   VK_ZOOM             | Zoom key
420     Qt::Key_unknown,    // 252   0xFC   VK_NONAME           | Reserved
421     Qt::Key_unknown,    // 253   0xFD   VK_PA1              | PA1 key
422     Qt::Key_Clear,      // 254   0xFE   VK_OEM_CLEAR        | Clear key
423     0
424 };
425
426 // Possible modifier states.
427 // NOTE: The order of these states match the order in QWindowsKeyMapper::updatePossibleKeyCodes()!
428 static const Qt::KeyboardModifiers ModsTbl[] = {
429     Qt::NoModifier,                                             // 0
430     Qt::ShiftModifier,                                          // 1
431     Qt::ControlModifier,                                        // 2
432     Qt::ControlModifier | Qt::ShiftModifier,                    // 3
433     Qt::AltModifier,                                            // 4
434     Qt::AltModifier | Qt::ShiftModifier,                        // 5
435     Qt::AltModifier | Qt::ControlModifier,                      // 6
436     Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier,  // 7
437     Qt::NoModifier,                                             // Fall-back to raw Key_*
438 };
439 static const size_t NumMods = sizeof ModsTbl / sizeof *ModsTbl;
440
441 /**
442   Remap return or action key to select key for windows mobile.
443 */
444 inline int winceKeyBend(int keyCode)
445 {
446     return KeyTbl[keyCode];
447 }
448
449 #ifdef Q_OS_WINCE
450 QT_BEGIN_INCLUDE_NAMESPACE
451 int ToUnicode(UINT vk, int /*scancode*/, unsigned char* /*kbdBuffer*/, LPWSTR unicodeBuffer, int, int)
452 {
453     QT_USE_NAMESPACE
454     QChar* buf = reinterpret_cast< QChar*>(unicodeBuffer);
455     if (KeyTbl[vk] == 0) {
456         buf[0] = vk;
457         return 1;
458     }
459     return 0;
460 }
461
462 int ToAscii(UINT vk, int scancode, unsigned char *kbdBuffer, LPWORD unicodeBuffer, int flag)
463 {
464     return ToUnicode(vk, scancode, kbdBuffer, (LPWSTR) unicodeBuffer, 0, flag);
465
466 }
467
468 bool GetKeyboardState(unsigned char* kbuffer)
469 {
470     for (int i=0; i< 256; ++i)
471         kbuffer[i] = GetAsyncKeyState(i);
472     return true;
473 }
474 QT_END_INCLUDE_NAMESPACE
475 #endif // Q_OS_WINCE
476
477 // Translate a VK into a Qt key code, or unicode character
478 static inline int toKeyOrUnicode(int vk, int scancode, unsigned char *kbdBuffer, bool *isDeadkey = 0)
479 {
480     Q_ASSERT(vk > 0 && vk < 256);
481     int code = 0;
482     QChar unicodeBuffer[5];
483     int res = ToUnicode(vk, scancode, kbdBuffer, reinterpret_cast<LPWSTR>(unicodeBuffer), 5, 0);
484     if (res)
485         code = unicodeBuffer[0].toUpper().unicode();
486
487     // Qt::Key_*'s are not encoded below 0x20, so try again, and DEL keys (0x7f) is encoded with a
488     // proper Qt::Key_ code
489     if (code < 0x20 || code == 0x7f) // Handles res==0 too
490         code = winceKeyBend(vk);
491
492     if (isDeadkey)
493         *isDeadkey = (res == -1);
494
495     return code == Qt::Key_unknown ? 0 : code;
496 }
497
498 int qt_translateKeyCode(int vk)
499 {
500     int code = winceKeyBend((vk < 0 || vk > 255) ? 0 : vk);
501     return code == Qt::Key_unknown ? 0 : code;
502 }
503
504 static inline int asciiToKeycode(char a, int state)
505 {
506     if (a >= 'a' && a <= 'z')
507         a = toupper(a);
508     if ((state & Qt::ControlModifier) != 0) {
509         if (a >= 0 && a <= 31)              // Ctrl+@..Ctrl+A..CTRL+Z..Ctrl+_
510             a += '@';                       // to @..A..Z.._
511     }
512     return a & 0xff;
513 }
514
515 static inline bool isModifierKey(int code)
516 {
517     return (code >= Qt::Key_Shift) && (code <= Qt::Key_ScrollLock);
518 }
519 // Key translation -----------------------------------------------------------------------[ end ]---
520
521
522 // Keyboard map private ----------------------------------------------------------------[ start ]---
523
524 /*
525     \internal
526     A Windows KeyboardLayoutItem has 8 possible states:
527         1. Unmodified
528         2. Shift
529         3. Control
530         4. Control + Shift
531         5. Alt
532         6. Alt + Shift
533         7. Alt + Control
534         8. Alt + Control + Shift
535 */
536 struct KeyboardLayoutItem {
537     bool dirty;
538     quint8 deadkeys;
539     quint32 qtKey[NumMods]; // Can by any Qt::Key_<foo>, or unicode character
540 };
541
542 void QWindowsKeyMapper::deleteLayouts()
543 {
544     for (int i = 0; i < 255; ++i) {
545         if (keyLayout[i]) {
546             delete keyLayout[i];
547             keyLayout[i] = 0;
548         }
549     }
550 }
551
552 void QWindowsKeyMapper::changeKeyboard()
553 {
554     deleteLayouts();
555
556     /* MAKELCID()'s first argument is a WORD, and GetKeyboardLayout()
557      * returns a DWORD. */
558
559     LCID newLCID = MAKELCID((quintptr)GetKeyboardLayout(0), SORT_DEFAULT);
560 //    keyboardInputLocale = qt_localeFromLCID(newLCID);
561
562     bool bidi = false;
563     wchar_t LCIDFontSig[16];
564     if (GetLocaleInfo(newLCID, LOCALE_FONTSIGNATURE, LCIDFontSig, sizeof(LCIDFontSig) / sizeof(wchar_t))
565         && (LCIDFontSig[7] & (wchar_t)0x0800))
566         bidi = true;
567
568     keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight;
569 }
570
571 void QWindowsKeyMapper::clearRecordedKeys()
572 {
573     key_recorder.clearKeys();
574 }
575
576
577 inline void setKbdState(unsigned char *kbd, bool shift, bool ctrl, bool alt)
578 {
579     kbd[VK_LSHIFT  ] = (shift ? 0x80 : 0);
580     kbd[VK_SHIFT   ] = (shift ? 0x80 : 0);
581     kbd[VK_LCONTROL] = (ctrl ? 0x80 : 0);
582     kbd[VK_CONTROL ] = (ctrl ? 0x80 : 0);
583     kbd[VK_RMENU   ] = (alt ? 0x80 : 0);
584     kbd[VK_MENU    ] = (alt ? 0x80 : 0);
585 }
586
587 void QWindowsKeyMapper::updateKeyMap(const MSG &msg)
588 {
589     unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
590     GetKeyboardState(kbdBuffer);
591     quint32 scancode = (msg.lParam >> 16) & 0xfff;
592     updatePossibleKeyCodes(kbdBuffer, scancode, msg.wParam);
593 }
594
595 void QWindowsKeyMapper::updatePossibleKeyCodes(unsigned char *kbdBuffer, quint32 scancode,
596                                                quint32 vk_key)
597 {
598     if (!vk_key || (keyLayout[vk_key] && !keyLayout[vk_key]->dirty))
599         return;
600
601     if (!keyLayout[vk_key])
602         keyLayout[vk_key] = new KeyboardLayoutItem;
603
604     // Copy keyboard state, so we can modify and query output for each possible permutation
605     unsigned char buffer[256];
606     memcpy(buffer, kbdBuffer, sizeof(buffer));
607     // Always 0, as Windows doesn't treat these as modifiers;
608     buffer[VK_LWIN    ] = 0;
609     buffer[VK_RWIN    ] = 0;
610     buffer[VK_CAPITAL ] = 0;
611     buffer[VK_NUMLOCK ] = 0;
612     buffer[VK_SCROLL  ] = 0;
613     // Always 0, since we'll only change the other versions
614     buffer[VK_RSHIFT  ] = 0;
615     buffer[VK_RCONTROL] = 0;
616     buffer[VK_LMENU   ] = 0; // Use right Alt, since left Ctrl + right Alt is considered AltGraph
617
618     bool isDeadKey = false;
619     keyLayout[vk_key]->deadkeys = 0;
620     keyLayout[vk_key]->dirty = false;
621     setKbdState(buffer, false, false, false);
622     keyLayout[vk_key]->qtKey[0] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
623     keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x01 : 0;
624     setKbdState(buffer, true, false, false);
625     keyLayout[vk_key]->qtKey[1] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
626     keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x02 : 0;
627     setKbdState(buffer, false, true, false);
628     keyLayout[vk_key]->qtKey[2] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
629     keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x04 : 0;
630     setKbdState(buffer, true, true, false);
631     keyLayout[vk_key]->qtKey[3] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
632     keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x08 : 0;
633     setKbdState(buffer, false, false, true);
634     keyLayout[vk_key]->qtKey[4] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
635     keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x10 : 0;
636     setKbdState(buffer, true, false, true);
637     keyLayout[vk_key]->qtKey[5] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
638     keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x20 : 0;
639     setKbdState(buffer, false, true, true);
640     keyLayout[vk_key]->qtKey[6] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
641     keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x40 : 0;
642     setKbdState(buffer, true, true, true);
643     keyLayout[vk_key]->qtKey[7] = toKeyOrUnicode(vk_key, scancode, buffer, &isDeadKey);
644     keyLayout[vk_key]->deadkeys |= isDeadKey ? 0x80 : 0;
645     // Add a fall back key for layouts which don't do composition and show non-latin1 characters
646     int fallbackKey = winceKeyBend(vk_key);
647     if (!fallbackKey || fallbackKey == Qt::Key_unknown) {
648         fallbackKey = 0;
649         if (vk_key != keyLayout[vk_key]->qtKey[0] && vk_key < 0x5B && vk_key > 0x2F)
650             fallbackKey = vk_key;
651     }
652     keyLayout[vk_key]->qtKey[8] = fallbackKey;
653
654     // If this vk_key a Dead Key
655     if (MapVirtualKey(vk_key, 2) & 0x80000000) {
656         // Push a Space, then the original key through the low-level ToAscii functions.
657         // We do this because these functions (ToAscii / ToUnicode) will alter the internal state of
658         // the keyboard driver By doing the following, we set the keyboard driver state back to what
659         // it was before we wrecked it with the code above.
660         // We need to push the space with an empty keystate map, since the driver checks the map for
661         // transitions in modifiers, so this helps us capture all possible deadkeys.
662         unsigned char emptyBuffer[256];
663         memset(emptyBuffer, 0, sizeof(emptyBuffer));
664         ::ToAscii(VK_SPACE, 0, emptyBuffer, reinterpret_cast<LPWORD>(&buffer), 0);
665         ::ToAscii(vk_key, scancode, kbdBuffer, reinterpret_cast<LPWORD>(&buffer), 0);
666     }
667
668     if (QWindowsContext::verboseEvents > 1) {
669         qDebug("updatePossibleKeyCodes for virtual key = 0x%02x!", vk_key);
670         for (size_t i = 0; i < NumMods; ++i) {
671             qDebug("    [%d] (%d,0x%02x,'%c')  %s", int(i),
672                    keyLayout[vk_key]->qtKey[i],
673                    keyLayout[vk_key]->qtKey[i],
674                    keyLayout[vk_key]->qtKey[i] ? keyLayout[vk_key]->qtKey[i] : 0x03,
675                    keyLayout[vk_key]->deadkeys & (1<<i) ? "deadkey" : "");
676         }
677     }
678 }
679
680 bool QWindowsKeyMapper::isADeadKey(unsigned int vk_key, unsigned int modifiers)
681 {
682     if ((vk_key < 256) && keyLayout[vk_key]) {
683         for (register size_t i = 0; i < NumMods; ++i) {
684             if (uint(ModsTbl[i]) == modifiers)
685                 return bool(keyLayout[vk_key]->deadkeys & 1<<i);
686         }
687     }
688     return false;
689 }
690
691 static inline QString messageKeyText(const MSG &msg)
692 {
693     const QChar ch = QChar((ushort)msg.wParam);
694     return ch.isNull() ? QString() : QString(ch);
695 }
696
697 static void showSystemMenu(QWindow* w)
698 {
699     QWindow *topLevel = QWindowsWindow::topLevelOf(w);
700     HWND topLevelHwnd = QWindowsWindow::handleOf(topLevel);
701     HMENU menu = GetSystemMenu(topLevelHwnd, FALSE);
702     if (!menu)
703         return; // no menu for this window
704
705 #ifndef Q_OS_WINCE
706 #define enabled (MF_BYCOMMAND | MF_ENABLED)
707 #define disabled (MF_BYCOMMAND | MF_GRAYED)
708
709     EnableMenuItem(menu, SC_MINIMIZE, (topLevel->windowFlags() & Qt::WindowMinimizeButtonHint)?enabled:disabled);
710     bool maximized = IsZoomed(topLevelHwnd);
711
712     EnableMenuItem(menu, SC_MAXIMIZE, ! (topLevel->windowFlags() & Qt::WindowMaximizeButtonHint) || maximized?disabled:enabled);
713     EnableMenuItem(menu, SC_RESTORE, maximized?enabled:disabled);
714
715     // We should _not_ check with the setFixedSize(x,y) case here, since Windows is not able to check
716     // this and our menu here would be out-of-sync with the menu produced by mouse-click on the
717     // System Menu, or right-click on the title bar.
718     EnableMenuItem(menu, SC_SIZE, (topLevel->windowFlags() & Qt::MSWindowsFixedSizeDialogHint) || maximized?disabled:enabled);
719     EnableMenuItem(menu, SC_MOVE, maximized?disabled:enabled);
720     EnableMenuItem(menu, SC_CLOSE, enabled);
721     // Set bold on close menu item
722     MENUITEMINFO closeItem;
723     closeItem.cbSize = sizeof(MENUITEMINFO);
724     closeItem.fMask = MIIM_STATE;
725     closeItem.fState = MFS_DEFAULT;
726     SetMenuItemInfo(menu, SC_CLOSE, FALSE, &closeItem);
727
728 #undef enabled
729 #undef disabled
730 #endif // !Q_OS_WINCE
731     const int ret = TrackPopupMenuEx(menu,
732                                TPM_LEFTALIGN  | TPM_TOPALIGN | TPM_NONOTIFY | TPM_RETURNCMD,
733                                topLevel->geometry().x(), topLevel->geometry().y(),
734                                topLevelHwnd,
735                                0);
736     if (ret)
737         qWindowsWndProc(topLevelHwnd, WM_SYSCOMMAND, ret, 0);
738 }
739
740 static inline void sendExtendedPressRelease(QWindow *w, int k,
741                                             Qt::KeyboardModifiers mods,
742                                             quint32 nativeScanCode,
743                                             quint32 nativeVirtualKey,
744                                             quint32 nativeModifiers,
745                                             const QString & text = QString(),
746                                             bool autorep = false,
747                                             ushort count = 1)
748 {
749     QWindowSystemInterface::handleExtendedKeyEvent(w, QEvent::KeyPress, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
750     QWindowSystemInterface::handleExtendedKeyEvent(w, QEvent::KeyRelease, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
751 }
752
753 /*!
754     \brief To be called from the window procedure.
755 */
756
757 bool QWindowsKeyMapper::translateKeyEvent(QWindow *widget, HWND hwnd,
758                                           const MSG &msg, LRESULT *result)
759 {
760     *result = 0;
761     MSG peekedMsg;
762     // consume dead chars?(for example, typing '`','a' resulting in a-accent).
763     if (PeekMessage(&peekedMsg, hwnd, 0, 0, PM_NOREMOVE) && peekedMsg.message == WM_DEADCHAR)
764         return true;
765     if (msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
766         updateKeyMap(msg);
767     return translateKeyEventInternal(widget, msg, false);
768 }
769
770 bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */)
771 {
772     const int  msgType = msg.message;
773
774     const quint32 scancode = (msg.lParam >> 16) & 0xfff;
775     const quint32 vk_key = MapVirtualKey(scancode, 1);
776     const bool isNumpad = (msg.wParam >= VK_NUMPAD0 && msg.wParam <= VK_NUMPAD9);
777     quint32 nModifiers = 0;
778
779     QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
780
781     // Map native modifiers to some bit representation
782     nModifiers |= (GetKeyState(VK_LSHIFT  ) & 0x80 ? ShiftLeft : 0);
783     nModifiers |= (GetKeyState(VK_RSHIFT  ) & 0x80 ? ShiftRight : 0);
784     nModifiers |= (GetKeyState(VK_LCONTROL) & 0x80 ? ControlLeft : 0);
785     nModifiers |= (GetKeyState(VK_RCONTROL) & 0x80 ? ControlRight : 0);
786     nModifiers |= (GetKeyState(VK_LMENU   ) & 0x80 ? AltLeft : 0);
787     nModifiers |= (GetKeyState(VK_RMENU   ) & 0x80 ? AltRight : 0);
788     nModifiers |= (GetKeyState(VK_LWIN    ) & 0x80 ? MetaLeft : 0);
789     nModifiers |= (GetKeyState(VK_RWIN    ) & 0x80 ? MetaRight : 0);
790     // Add Lock keys to the same bits
791     nModifiers |= (GetKeyState(VK_CAPITAL ) & 0x01 ? CapsLock : 0);
792     nModifiers |= (GetKeyState(VK_NUMLOCK ) & 0x01 ? NumLock : 0);
793     nModifiers |= (GetKeyState(VK_SCROLL  ) & 0x01 ? ScrollLock : 0);
794
795     if (msg.lParam & ExtendedKey)
796         nModifiers |= msg.lParam & ExtendedKey;
797
798     // Get the modifier states (may be altered later, depending on key code)
799     int state = 0;
800     state |= (nModifiers & ShiftAny ? int(Qt::ShiftModifier) : 0);
801     state |= (nModifiers & ControlAny ? int(Qt::ControlModifier) : 0);
802     state |= (nModifiers & AltAny ? int(Qt::AltModifier) : 0);
803     state |= (nModifiers & MetaAny ? int(Qt::MetaModifier) : 0);
804
805     // Now we know enough to either have MapVirtualKey or our own keymap tell us if it's a deadkey
806     const bool isDeadKey = isADeadKey(msg.wParam, state)
807                      || MapVirtualKey(msg.wParam, 2) & 0x80000000;
808
809     // A multi-character key or a Input method character
810     // not found by our look-ahead
811     if (msgType == WM_CHAR || msgType == WM_IME_CHAR) {
812         sendExtendedPressRelease(receiver, 0, Qt::KeyboardModifier(state), scancode, vk_key, nModifiers, messageKeyText(msg), false, 0);
813         return true;
814     }
815
816     bool result = false;
817     // handle Directionality changes (BiDi) with RTL extensions
818     if (m_useRTLExtensions) {
819         static int dirStatus = 0;
820         if (!dirStatus && state == Qt::ControlModifier
821                 && msg.wParam == VK_CONTROL
822                 && msgType == WM_KEYDOWN) {
823             if (GetKeyState(VK_LCONTROL) < 0)
824                 dirStatus = VK_LCONTROL;
825             else if (GetKeyState(VK_RCONTROL) < 0)
826                 dirStatus = VK_RCONTROL;
827         } else if (dirStatus) {
828             if (msgType == WM_KEYDOWN) {
829                 if (msg.wParam == VK_SHIFT) {
830                     if (dirStatus == VK_LCONTROL && GetKeyState(VK_LSHIFT) < 0)
831                         dirStatus = VK_LSHIFT;
832                     else if (dirStatus == VK_RCONTROL && GetKeyState(VK_RSHIFT) < 0)
833                         dirStatus = VK_RSHIFT;
834                 } else {
835                     dirStatus = 0;
836                 }
837             } else if (msgType == WM_KEYUP) {
838                 if (dirStatus == VK_LSHIFT
839                         && ((msg.wParam == VK_SHIFT && GetKeyState(VK_LCONTROL))
840                             || (msg.wParam == VK_CONTROL && GetKeyState(VK_LSHIFT)))) {
841                     sendExtendedPressRelease(receiver, Qt::Key_Direction_L, 0, scancode, msg.wParam, nModifiers, QString(), false, 0);
842                     result = true;
843                     dirStatus = 0;
844                 } else if (dirStatus == VK_RSHIFT
845                            && ( (msg.wParam == VK_SHIFT && GetKeyState(VK_RCONTROL))
846                                 || (msg.wParam == VK_CONTROL && GetKeyState(VK_RSHIFT)))) {
847                     sendExtendedPressRelease(receiver, Qt::Key_Direction_R, 0, scancode, msg.wParam, nModifiers, QString(), false, 0);
848                     result = true;
849                     dirStatus = 0;
850                 } else {
851                     dirStatus = 0;
852                 }
853             } else {
854                 dirStatus = 0;
855             }
856         }
857     } // RTL
858
859     // IME will process these keys, so simply return
860     if (msg.wParam == VK_PROCESSKEY)
861         return true;
862
863     // Ignore invalid virtual keycodes (see bugs 127424, QTBUG-3630)
864     if (msg.wParam == 0 || msg.wParam == 0xFF)
865         return true;
866
867     // Translate VK_* (native) -> Key_* (Qt) keys
868     // If it's a dead key, we cannot use the toKeyOrUnicode() function, since that will change
869     // the internal state of the keyboard driver, resulting in that dead keys no longer works.
870     // ..also if we're typing numbers on the keypad, while holding down the Alt modifier.
871     int code = 0;
872     if (isNumpad && (nModifiers & AltAny)) {
873         code = winceKeyBend(msg.wParam);
874     } else if (!isDeadKey) {
875         unsigned char kbdBuffer[256]; // Will hold the complete keyboard state
876         GetKeyboardState(kbdBuffer);
877         code = toKeyOrUnicode(msg.wParam, scancode, kbdBuffer);
878     }
879
880     // Invert state logic:
881     // If the key actually pressed is a modifier key, then we remove its modifier key from the
882     // state, since a modifier-key can't have itself as a modifier
883     if (code == Qt::Key_Control)
884         state = state ^ Qt::ControlModifier;
885     else if (code == Qt::Key_Shift)
886         state = state ^ Qt::ShiftModifier;
887     else if (code == Qt::Key_Alt)
888         state = state ^ Qt::AltModifier;
889
890     // If the bit 24 of lParm is set you received a enter,
891     // otherwise a Return. (This is the extended key bit)
892     if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000))
893         code = Qt::Key_Enter;
894
895     // All cursor keys without extended bit
896     if (!(msg.lParam & 0x1000000)) {
897         switch (code) {
898         case Qt::Key_Left:
899         case Qt::Key_Right:
900         case Qt::Key_Up:
901         case Qt::Key_Down:
902         case Qt::Key_PageUp:
903         case Qt::Key_PageDown:
904         case Qt::Key_Home:
905         case Qt::Key_End:
906         case Qt::Key_Insert:
907         case Qt::Key_Delete:
908         case Qt::Key_Asterisk:
909         case Qt::Key_Plus:
910         case Qt::Key_Minus:
911         case Qt::Key_Period:
912         case Qt::Key_0:
913         case Qt::Key_1:
914         case Qt::Key_2:
915         case Qt::Key_3:
916         case Qt::Key_4:
917         case Qt::Key_5:
918         case Qt::Key_6:
919         case Qt::Key_7:
920         case Qt::Key_8:
921         case Qt::Key_9:
922             state |= ((msg.wParam >= '0' && msg.wParam <= '9')
923                       || (msg.wParam >= VK_OEM_PLUS && msg.wParam <= VK_OEM_3))
924                     ? 0 : int(Qt::KeypadModifier);
925         default:
926             if ((uint)msg.lParam == 0x004c0001 || (uint)msg.lParam == 0xc04c0001)
927                 state |= Qt::KeypadModifier;
928             break;
929         }
930     }
931     // Other keys with with extended bit
932     else {
933         switch (code) {
934         case Qt::Key_Enter:
935         case Qt::Key_Slash:
936         case Qt::Key_NumLock:
937             state |= Qt::KeypadModifier;
938         default:
939             break;
940         }
941     }
942
943     // KEYDOWN ---------------------------------------------------------------------------------
944     if (msgType == WM_KEYDOWN || msgType == WM_IME_KEYDOWN || msgType == WM_SYSKEYDOWN) {
945         // Get the last record of this key press, so we can validate the current state
946         // The record is not removed from the list
947         KeyRecord *rec = key_recorder.findKey(msg.wParam, false);
948
949         // If rec's state doesn't match the current state, something has changed behind our back
950         // (Consumed by modal widget is one possibility) So, remove the record from the list
951         // This will stop the auto-repeat of the key, should a modifier change, for example
952         if (rec && rec->state != state) {
953             key_recorder.findKey(msg.wParam, true);
954             rec = 0;
955         }
956
957         // Find unicode character from Windows Message Queue
958         MSG wm_char;
959         UINT charType = (msgType == WM_KEYDOWN
960                          ? WM_CHAR
961                          : msgType == WM_IME_KEYDOWN ? WM_IME_CHAR : WM_SYSCHAR);
962
963         QChar uch;
964         if (PeekMessage(&wm_char, 0, charType, charType, PM_REMOVE)) {
965             // Found a ?_CHAR
966             uch = QChar((ushort)wm_char.wParam);
967             if (msgType == WM_SYSKEYDOWN && uch.isLetter() && (msg.lParam & KF_ALTDOWN))
968                 uch = uch.toLower(); // (See doc of WM_SYSCHAR) Alt-letter
969             if (!code && !uch.row())
970                 code = asciiToKeycode(uch.cell(), state);
971         }
972
973         // Special handling for the WM_IME_KEYDOWN message. Microsoft IME (Korean) will not
974         // generate a WM_IME_CHAR message corresponding to this message. We might get wrong
975         // results, if we map this virtual key-code directly (for eg '?' US layouts). So try
976         // to find the correct key using the current message parameters & keyboard state.
977         if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
978             BYTE keyState[256];
979             wchar_t newKey[3] = {0};
980             GetKeyboardState(keyState);
981             int val = ToUnicode(vk_key, scancode, keyState, newKey, 2,  0);
982             if (val == 1) {
983                 uch = QChar(newKey[0]);
984             } else {
985                 // If we are still not able to find a unicode key, pass the WM_IME_KEYDOWN
986                 // message to DefWindowProc() for generating a proper WM_KEYDOWN.
987                 return false;
988             }
989         }
990
991         // If no ?_CHAR was found in the queue; deduct character from the ?_KEYDOWN parameters
992         if (uch.isNull()) {
993             if (msg.wParam == VK_DELETE) {
994                 uch = QChar(QLatin1Char(0x7f)); // Windows doesn't know this one.
995             } else {
996                 if (msgType != WM_SYSKEYDOWN || !code) {
997                     UINT map = MapVirtualKey(msg.wParam, 2);
998                     // If the high bit of the return value is set, it's a deadkey
999                     if (!(map & 0x80000000))
1000                         uch = QChar((ushort)map);
1001                 }
1002             }
1003             if (!code && !uch.row())
1004                 code = asciiToKeycode(uch.cell(), state);
1005         }
1006
1007         // Special handling of global Windows hotkeys
1008         if (state == Qt::AltModifier) {
1009             switch (code) {
1010             case Qt::Key_Escape:
1011             case Qt::Key_Tab:
1012             case Qt::Key_Enter:
1013             case Qt::Key_F4:
1014                 return false; // Send the event on to Windows
1015             case Qt::Key_Space:
1016                 // do not pass this key to windows, we will process it ourselves
1017                 showSystemMenu(receiver);
1018                 return true;
1019             default:
1020                 break;
1021             }
1022         }
1023
1024         // Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation
1025         if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
1026             code = Qt::Key_Backtab;
1027
1028         // If we have a record, it means that the key is already pressed, the state is the same
1029         // so, we have an auto-repeating key
1030         if (rec) {
1031             if (code < Qt::Key_Shift || code > Qt::Key_ScrollLock) {
1032                 QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, code,
1033                                                                Qt::KeyboardModifier(state), scancode, msg.wParam, nModifiers, rec->text, true, 0);
1034                 QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code,
1035                                                                Qt::KeyboardModifier(state), scancode, msg.wParam, nModifiers, rec->text, true, 0);
1036                 result = true;
1037             }
1038         }
1039         // No record of the key being previous pressed, so we now send a QEvent::KeyPress event,
1040         // and store the key data into our records.
1041         else {
1042             const QString text = uch.isNull() ? QString() : QString(uch);
1043             const char a = uch.row() ? 0 : uch.cell();
1044             key_recorder.storeKey(msg.wParam, a, state, text);
1045             QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyPress, code,
1046                                                            Qt::KeyboardModifier(state), scancode, msg.wParam, nModifiers, text, false, 0);
1047             result =true;
1048             bool store = true;
1049 #ifndef Q_OS_WINCE
1050             // Alt+<alphanumerical> go to the Win32 menu system if unhandled by Qt
1051             if (msgType == WM_SYSKEYDOWN && !result && a) {
1052                 HWND parent = GetParent(QWindowsWindow::handleOf(receiver));
1053                 while (parent) {
1054                     if (GetMenu(parent)) {
1055                         SendMessage(parent, WM_SYSCOMMAND, SC_KEYMENU, a);
1056                         store = false;
1057                         result = true;
1058                         break;
1059                     }
1060                     parent = GetParent(parent);
1061                 }
1062             }
1063 #endif // !Q_OS_WINCE
1064             if (!store)
1065                 key_recorder.findKey(msg.wParam, true);
1066         }
1067     }
1068
1069     // KEYUP -----------------------------------------------------------------------------------
1070     else {
1071         // Try to locate the key in our records, and remove it if it exists.
1072         // The key may not be in our records if, for example, the down event was handled by
1073         // win32 natively, or our window gets focus while a key is already press, but now gets
1074         // the key release event.
1075         KeyRecord* rec = key_recorder.findKey(msg.wParam, true);
1076         if (!rec && !(code == Qt::Key_Shift
1077                       || code == Qt::Key_Control
1078                       || code == Qt::Key_Meta
1079                       || code == Qt::Key_Alt)) {
1080             // Someone ate the key down event
1081         } else {
1082             if (!code)
1083                 code = asciiToKeycode(rec->ascii ? rec->ascii : msg.wParam, state);
1084
1085             // Map SHIFT + Tab to SHIFT + BackTab, QShortcutMap knows about this translation
1086             if (code == Qt::Key_Tab && (state & Qt::ShiftModifier) == Qt::ShiftModifier)
1087                 code = Qt::Key_Backtab;
1088             QWindowSystemInterface::handleExtendedKeyEvent(receiver, QEvent::KeyRelease, code,
1089                                                            Qt::KeyboardModifier(state), scancode, msg.wParam, nModifiers,
1090                                                            (rec ? rec->text : QString()), false, 0);
1091             result = true;
1092 #ifndef Q_OS_WINCE
1093             // don't pass Alt to Windows unless we are embedded in a non-Qt window
1094             if (code == Qt::Key_Alt) {
1095                 const QWindowsContext *context = QWindowsContext::instance();
1096                 HWND parent = GetParent(QWindowsWindow::handleOf(receiver));
1097                 while (parent) {
1098                     if (!context->findPlatformWindow(parent) && GetMenu(parent)) {
1099                         result = false;
1100                         break;
1101                     }
1102                     parent = GetParent(parent);
1103                 }
1104             }
1105 #endif
1106         }
1107     }
1108     return result;
1109 }
1110
1111 Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers()
1112 {
1113     Qt::KeyboardModifiers modifiers = Qt::NoModifier;
1114     if (GetKeyState(VK_SHIFT) < 0)
1115         modifiers |= Qt::ShiftModifier;
1116     if (GetKeyState(VK_CONTROL) < 0)
1117         modifiers |= Qt::ControlModifier;
1118     if (GetKeyState(VK_MENU) < 0)
1119         modifiers |= Qt::AltModifier;
1120     return modifiers;
1121 }
1122
1123 QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const
1124 {
1125     QList<int> result;
1126
1127     KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()];
1128     if (!kbItem)
1129         return result;
1130
1131     quint32 baseKey = kbItem->qtKey[0];
1132     Qt::KeyboardModifiers keyMods = e->modifiers();
1133     if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) {
1134         result << int(Qt::Key_Enter + keyMods);
1135         return result;
1136     }
1137     result << int(baseKey + keyMods); // The base key is _always_ valid, of course
1138
1139     for (int i = 1; i < NumMods; ++i) {
1140         Qt::KeyboardModifiers neededMods = ModsTbl[i];
1141         quint32 key = kbItem->qtKey[i];
1142         if (key && key != baseKey && ((keyMods & neededMods) == neededMods))
1143             result << int(key + (keyMods & ~neededMods));
1144     }
1145
1146     return result;
1147 }
1148
1149 QT_END_NAMESPACE