source: trunk/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

  • Property svn:eol-style set to native
File size: 17.0 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the plugins of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdirectfbkeyboard.h"
43
44#ifndef QT_NO_QWS_DIRECTFB
45
46#include "qdirectfbscreen.h"
47#include <qobject.h>
48#include <qsocketnotifier.h>
49#include <qhash.h>
50
51#include <directfb.h>
52#include <unistd.h>
53#include <fcntl.h>
54#include <errno.h>
55
56QT_BEGIN_NAMESPACE
57
58class KeyMap : public QHash<DFBInputDeviceKeySymbol, Qt::Key>
59{
60public:
61 KeyMap();
62};
63
64Q_GLOBAL_STATIC(KeyMap, keymap);
65
66class QDirectFBKeyboardHandlerPrivate : public QObject
67{
68 Q_OBJECT
69public:
70 QDirectFBKeyboardHandlerPrivate(QDirectFBKeyboardHandler *handler);
71 ~QDirectFBKeyboardHandlerPrivate();
72
73 void suspend();
74 void resume();
75
76private:
77 QDirectFBKeyboardHandler *handler;
78 IDirectFBEventBuffer *eventBuffer;
79 QSocketNotifier *keyboardNotifier;
80 DFBEvent event;
81 int bytesRead;
82 int lastUnicode, lastKeycode;
83 Qt::KeyboardModifiers lastModifiers;
84private Q_SLOTS:
85 void readKeyboardData();
86};
87
88QDirectFBKeyboardHandlerPrivate::QDirectFBKeyboardHandlerPrivate(QDirectFBKeyboardHandler *h)
89 : handler(h), eventBuffer(0), keyboardNotifier(0), bytesRead(0),
90 lastUnicode(0), lastKeycode(0), lastModifiers(0)
91{
92 Q_ASSERT(qt_screen);
93
94 IDirectFB *fb = QDirectFBScreen::instance()->dfb();
95 if (!fb) {
96 qCritical("QDirectFBKeyboardHandler: DirectFB not initialized");
97 return;
98 }
99
100 DFBResult result;
101 result = fb->CreateInputEventBuffer(fb, DICAPS_KEYS, DFB_TRUE,
102 &eventBuffer);
103 if (result != DFB_OK) {
104 DirectFBError("QDirectFBKeyboardHandler: "
105 "Unable to create input event buffer", result);
106 return;
107 }
108
109 int fd;
110 result = eventBuffer->CreateFileDescriptor(eventBuffer, &fd);
111 if (result != DFB_OK) {
112 DirectFBError("QDirectFBKeyboardHandler: "
113 "Unable to create file descriptor", result);
114 return;
115 }
116
117 int flags = ::fcntl(fd, F_GETFL, 0);
118 ::fcntl(fd, F_SETFL, flags | O_NONBLOCK);
119
120 memset(&event, 0, sizeof(event));
121
122 keyboardNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
123 connect(keyboardNotifier, SIGNAL(activated(int)),
124 this, SLOT(readKeyboardData()));
125 resume();
126}
127
128void QDirectFBKeyboardHandlerPrivate::suspend()
129{
130 keyboardNotifier->setEnabled(false);
131}
132
133void QDirectFBKeyboardHandlerPrivate::resume()
134{
135 eventBuffer->Reset(eventBuffer);
136 keyboardNotifier->setEnabled(true);
137}
138
139QDirectFBKeyboardHandlerPrivate::~QDirectFBKeyboardHandlerPrivate()
140{
141 if (eventBuffer)
142 eventBuffer->Release(eventBuffer);
143}
144
145void QDirectFBKeyboardHandlerPrivate::readKeyboardData()
146{
147 if(!qt_screen)
148 return;
149
150 for (;;) {
151 // GetEvent returns DFB_UNSUPPORTED after CreateFileDescriptor().
152 // This seems stupid and I really hope it's a bug which will be fixed.
153
154 // DFBResult ret = eventBuffer->GetEvent(eventBuffer, &event);
155
156 char *buf = reinterpret_cast<char*>(&event);
157 int ret = ::read(keyboardNotifier->socket(),
158 buf + bytesRead, sizeof(DFBEvent) - bytesRead);
159 if (ret == -1) {
160 if (errno != EAGAIN)
161 qWarning("QDirectFBKeyboardHandlerPrivate::readKeyboardData(): %s",
162 strerror(errno));
163 return;
164 }
165
166 Q_ASSERT(ret >= 0);
167 bytesRead += ret;
168 if (bytesRead < int(sizeof(DFBEvent)))
169 break;
170 bytesRead = 0;
171
172 Q_ASSERT(event.clazz == DFEC_INPUT);
173
174 const DFBInputEvent input = event.input;
175
176 Qt::KeyboardModifiers modifiers = Qt::NoModifier;
177
178 // Not implemented:
179 // if (input.modifiers & DIMM_SUPER)
180 // if (input.modifiers & DIMM_HYPER)
181
182 if (!(input.flags & DIEF_KEYSYMBOL) ||
183 !(input.flags & DIEF_KEYID) ||
184 !(input.type & (DIET_KEYPRESS|DIET_KEYRELEASE)))
185 {
186 static bool first = true;
187 if (first) {
188 qWarning("QDirectFBKeyboardHandler - Getting unexpected non-keyboard related events");
189 first = false;
190 }
191 break;
192 }
193
194 if (input.flags & DIEF_MODIFIERS) {
195 if (input.modifiers & DIMM_SHIFT)
196 modifiers |= Qt::ShiftModifier;
197 if (input.modifiers & DIMM_CONTROL)
198 modifiers |= Qt::ControlModifier;
199 if (input.modifiers & DIMM_ALT)
200 modifiers |= Qt::AltModifier;
201 if (input.modifiers & DIMM_ALTGR)
202 modifiers |= Qt::AltModifier;
203 if (input.modifiers & DIMM_META)
204 modifiers |= Qt::MetaModifier;
205 }
206
207
208 const bool press = input.type & DIET_KEYPRESS;
209 DFBInputDeviceKeySymbol symbol = input.key_symbol;
210 int unicode = -1;
211 int keycode = 0;
212
213 keycode = keymap()->value(symbol);
214 if (DFB_KEY_TYPE(symbol) == DIKT_UNICODE)
215 unicode = symbol;
216
217 if (unicode != -1 || keycode != 0) {
218 bool autoRepeat = false;
219 if (press) {
220 if (unicode == lastUnicode && keycode == lastKeycode && modifiers == lastModifiers) {
221 autoRepeat = true;
222 } else {
223 lastUnicode = unicode;
224 lastKeycode = keycode;
225 lastModifiers = modifiers;
226 }
227 } else {
228 lastUnicode = lastKeycode = -1;
229 lastModifiers = 0;
230 }
231 if (autoRepeat) {
232 handler->processKeyEvent(unicode, keycode,
233 modifiers, false, autoRepeat);
234
235 }
236
237 handler->processKeyEvent(unicode, keycode,
238 modifiers, press, autoRepeat);
239 }
240 }
241}
242
243QDirectFBKeyboardHandler::QDirectFBKeyboardHandler(const QString &device)
244 : QWSKeyboardHandler()
245{
246 Q_UNUSED(device);
247 d = new QDirectFBKeyboardHandlerPrivate(this);
248}
249
250QDirectFBKeyboardHandler::~QDirectFBKeyboardHandler()
251{
252 delete d;
253}
254
255KeyMap::KeyMap()
256{
257 insert(DIKS_BACKSPACE , Qt::Key_Backspace);
258 insert(DIKS_TAB , Qt::Key_Tab);
259 insert(DIKS_RETURN , Qt::Key_Return);
260 insert(DIKS_ESCAPE , Qt::Key_Escape);
261 insert(DIKS_DELETE , Qt::Key_Delete);
262
263 insert(DIKS_CURSOR_LEFT , Qt::Key_Left);
264 insert(DIKS_CURSOR_RIGHT , Qt::Key_Right);
265 insert(DIKS_CURSOR_UP , Qt::Key_Up);
266 insert(DIKS_CURSOR_DOWN , Qt::Key_Down);
267 insert(DIKS_INSERT , Qt::Key_Insert);
268 insert(DIKS_HOME , Qt::Key_Home);
269 insert(DIKS_END , Qt::Key_End);
270 insert(DIKS_PAGE_UP , Qt::Key_PageUp);
271 insert(DIKS_PAGE_DOWN , Qt::Key_PageDown);
272 insert(DIKS_PRINT , Qt::Key_Print);
273 insert(DIKS_PAUSE , Qt::Key_Pause);
274 insert(DIKS_SELECT , Qt::Key_Select);
275 insert(DIKS_GOTO , Qt::Key_OpenUrl);
276 insert(DIKS_CLEAR , Qt::Key_Clear);
277 insert(DIKS_MENU , Qt::Key_Menu);
278 insert(DIKS_HELP , Qt::Key_Help);
279
280 insert(DIKS_INTERNET , Qt::Key_HomePage);
281 insert(DIKS_MAIL , Qt::Key_LaunchMail);
282 insert(DIKS_FAVORITES , Qt::Key_Favorites);
283
284 insert(DIKS_BACK , Qt::Key_Back);
285 insert(DIKS_FORWARD , Qt::Key_Forward);
286 insert(DIKS_VOLUME_UP , Qt::Key_VolumeUp);
287 insert(DIKS_VOLUME_DOWN , Qt::Key_VolumeDown);
288 insert(DIKS_MUTE , Qt::Key_VolumeMute);
289 insert(DIKS_PLAYPAUSE , Qt::Key_Pause);
290 insert(DIKS_PLAY , Qt::Key_MediaPlay);
291 insert(DIKS_STOP , Qt::Key_MediaStop);
292 insert(DIKS_RECORD , Qt::Key_MediaRecord);
293 insert(DIKS_PREVIOUS , Qt::Key_MediaPrevious);
294 insert(DIKS_NEXT , Qt::Key_MediaNext);
295
296 insert(DIKS_F1 , Qt::Key_F1);
297 insert(DIKS_F2 , Qt::Key_F2);
298 insert(DIKS_F3 , Qt::Key_F3);
299 insert(DIKS_F4 , Qt::Key_F4);
300 insert(DIKS_F5 , Qt::Key_F5);
301 insert(DIKS_F6 , Qt::Key_F6);
302 insert(DIKS_F7 , Qt::Key_F7);
303 insert(DIKS_F8 , Qt::Key_F8);
304 insert(DIKS_F9 , Qt::Key_F9);
305 insert(DIKS_F10 , Qt::Key_F10);
306 insert(DIKS_F11 , Qt::Key_F11);
307 insert(DIKS_F12 , Qt::Key_F12);
308
309 insert(DIKS_SHIFT , Qt::Key_Shift);
310 insert(DIKS_CONTROL , Qt::Key_Control);
311 insert(DIKS_ALT , Qt::Key_Alt);
312 insert(DIKS_ALTGR , Qt::Key_AltGr);
313
314 insert(DIKS_META , Qt::Key_Meta);
315 insert(DIKS_SUPER , Qt::Key_Super_L); // ???
316 insert(DIKS_HYPER , Qt::Key_Hyper_L); // ???
317
318 insert(DIKS_CAPS_LOCK , Qt::Key_CapsLock);
319 insert(DIKS_NUM_LOCK , Qt::Key_NumLock);
320 insert(DIKS_SCROLL_LOCK , Qt::Key_ScrollLock);
321
322 insert(DIKS_DEAD_ABOVEDOT , Qt::Key_Dead_Abovedot);
323 insert(DIKS_DEAD_ABOVERING , Qt::Key_Dead_Abovering);
324 insert(DIKS_DEAD_ACUTE , Qt::Key_Dead_Acute);
325 insert(DIKS_DEAD_BREVE , Qt::Key_Dead_Breve);
326 insert(DIKS_DEAD_CARON , Qt::Key_Dead_Caron);
327 insert(DIKS_DEAD_CEDILLA , Qt::Key_Dead_Cedilla);
328 insert(DIKS_DEAD_CIRCUMFLEX , Qt::Key_Dead_Circumflex);
329 insert(DIKS_DEAD_DIAERESIS , Qt::Key_Dead_Diaeresis);
330 insert(DIKS_DEAD_DOUBLEACUTE , Qt::Key_Dead_Doubleacute);
331 insert(DIKS_DEAD_GRAVE , Qt::Key_Dead_Grave);
332 insert(DIKS_DEAD_IOTA , Qt::Key_Dead_Iota);
333 insert(DIKS_DEAD_MACRON , Qt::Key_Dead_Macron);
334 insert(DIKS_DEAD_OGONEK , Qt::Key_Dead_Ogonek);
335 insert(DIKS_DEAD_SEMIVOICED_SOUND , Qt::Key_Dead_Semivoiced_Sound);
336 insert(DIKS_DEAD_TILDE , Qt::Key_Dead_Tilde);
337 insert(DIKS_DEAD_VOICED_SOUND , Qt::Key_Dead_Voiced_Sound);
338 insert(DIKS_SPACE , Qt::Key_Space);
339 insert(DIKS_EXCLAMATION_MARK , Qt::Key_Exclam);
340 insert(DIKS_QUOTATION , Qt::Key_QuoteDbl);
341 insert(DIKS_NUMBER_SIGN , Qt::Key_NumberSign);
342 insert(DIKS_DOLLAR_SIGN , Qt::Key_Dollar);
343 insert(DIKS_PERCENT_SIGN , Qt::Key_Percent);
344 insert(DIKS_AMPERSAND , Qt::Key_Ampersand);
345 insert(DIKS_APOSTROPHE , Qt::Key_Apostrophe);
346 insert(DIKS_PARENTHESIS_LEFT , Qt::Key_ParenLeft);
347 insert(DIKS_PARENTHESIS_RIGHT , Qt::Key_ParenRight);
348 insert(DIKS_ASTERISK , Qt::Key_Asterisk);
349 insert(DIKS_PLUS_SIGN , Qt::Key_Plus);
350 insert(DIKS_COMMA , Qt::Key_Comma);
351 insert(DIKS_MINUS_SIGN , Qt::Key_Minus);
352 insert(DIKS_PERIOD , Qt::Key_Period);
353 insert(DIKS_SLASH , Qt::Key_Slash);
354 insert(DIKS_0 , Qt::Key_0);
355 insert(DIKS_1 , Qt::Key_1);
356 insert(DIKS_2 , Qt::Key_2);
357 insert(DIKS_3 , Qt::Key_3);
358 insert(DIKS_4 , Qt::Key_4);
359 insert(DIKS_5 , Qt::Key_5);
360 insert(DIKS_6 , Qt::Key_6);
361 insert(DIKS_7 , Qt::Key_7);
362 insert(DIKS_8 , Qt::Key_8);
363 insert(DIKS_9 , Qt::Key_9);
364 insert(DIKS_COLON , Qt::Key_Colon);
365 insert(DIKS_SEMICOLON , Qt::Key_Semicolon);
366 insert(DIKS_LESS_THAN_SIGN , Qt::Key_Less);
367 insert(DIKS_EQUALS_SIGN , Qt::Key_Equal);
368 insert(DIKS_GREATER_THAN_SIGN , Qt::Key_Greater);
369 insert(DIKS_QUESTION_MARK , Qt::Key_Question);
370 insert(DIKS_AT , Qt::Key_At);
371 insert(DIKS_CAPITAL_A , Qt::Key_A);
372 insert(DIKS_CAPITAL_B , Qt::Key_B);
373 insert(DIKS_CAPITAL_C , Qt::Key_C);
374 insert(DIKS_CAPITAL_D , Qt::Key_D);
375 insert(DIKS_CAPITAL_E , Qt::Key_E);
376 insert(DIKS_CAPITAL_F , Qt::Key_F);
377 insert(DIKS_CAPITAL_G , Qt::Key_G);
378 insert(DIKS_CAPITAL_H , Qt::Key_H);
379 insert(DIKS_CAPITAL_I , Qt::Key_I);
380 insert(DIKS_CAPITAL_J , Qt::Key_J);
381 insert(DIKS_CAPITAL_K , Qt::Key_K);
382 insert(DIKS_CAPITAL_L , Qt::Key_L);
383 insert(DIKS_CAPITAL_M , Qt::Key_M);
384 insert(DIKS_CAPITAL_N , Qt::Key_N);
385 insert(DIKS_CAPITAL_O , Qt::Key_O);
386 insert(DIKS_CAPITAL_P , Qt::Key_P);
387 insert(DIKS_CAPITAL_Q , Qt::Key_Q);
388 insert(DIKS_CAPITAL_R , Qt::Key_R);
389 insert(DIKS_CAPITAL_S , Qt::Key_S);
390 insert(DIKS_CAPITAL_T , Qt::Key_T);
391 insert(DIKS_CAPITAL_U , Qt::Key_U);
392 insert(DIKS_CAPITAL_V , Qt::Key_V);
393 insert(DIKS_CAPITAL_W , Qt::Key_W);
394 insert(DIKS_CAPITAL_X , Qt::Key_X);
395 insert(DIKS_CAPITAL_Y , Qt::Key_Y);
396 insert(DIKS_CAPITAL_Z , Qt::Key_Z);
397 insert(DIKS_SQUARE_BRACKET_LEFT , Qt::Key_BracketLeft);
398 insert(DIKS_BACKSLASH , Qt::Key_Backslash);
399 insert(DIKS_SQUARE_BRACKET_RIGHT , Qt::Key_BracketRight);
400 insert(DIKS_CIRCUMFLEX_ACCENT , Qt::Key_AsciiCircum);
401 insert(DIKS_UNDERSCORE , Qt::Key_Underscore);
402 insert(DIKS_SMALL_A , Qt::Key_A);
403 insert(DIKS_SMALL_B , Qt::Key_B);
404 insert(DIKS_SMALL_C , Qt::Key_C);
405 insert(DIKS_SMALL_D , Qt::Key_D);
406 insert(DIKS_SMALL_E , Qt::Key_E);
407 insert(DIKS_SMALL_F , Qt::Key_F);
408 insert(DIKS_SMALL_G , Qt::Key_G);
409 insert(DIKS_SMALL_H , Qt::Key_H);
410 insert(DIKS_SMALL_I , Qt::Key_I);
411 insert(DIKS_SMALL_J , Qt::Key_J);
412 insert(DIKS_SMALL_K , Qt::Key_K);
413 insert(DIKS_SMALL_L , Qt::Key_L);
414 insert(DIKS_SMALL_M , Qt::Key_M);
415 insert(DIKS_SMALL_N , Qt::Key_N);
416 insert(DIKS_SMALL_O , Qt::Key_O);
417 insert(DIKS_SMALL_P , Qt::Key_P);
418 insert(DIKS_SMALL_Q , Qt::Key_Q);
419 insert(DIKS_SMALL_R , Qt::Key_R);
420 insert(DIKS_SMALL_S , Qt::Key_S);
421 insert(DIKS_SMALL_T , Qt::Key_T);
422 insert(DIKS_SMALL_U , Qt::Key_U);
423 insert(DIKS_SMALL_V , Qt::Key_V);
424 insert(DIKS_SMALL_W , Qt::Key_W);
425 insert(DIKS_SMALL_X , Qt::Key_X);
426 insert(DIKS_SMALL_Y , Qt::Key_Y);
427 insert(DIKS_SMALL_Z , Qt::Key_Z);
428 insert(DIKS_CURLY_BRACKET_LEFT , Qt::Key_BraceLeft);
429 insert(DIKS_VERTICAL_BAR , Qt::Key_Bar);
430 insert(DIKS_CURLY_BRACKET_RIGHT , Qt::Key_BraceRight);
431 insert(DIKS_TILDE , Qt::Key_AsciiTilde);
432}
433
434QT_END_NAMESPACE
435#include "qdirectfbkeyboard.moc"
436#endif // QT_NO_QWS_DIRECTFB
Note: See TracBrowser for help on using the repository browser.