source: trunk/src/gui/embedded/qkbd_qws.cpp@ 742

Last change on this file since 742 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

  • Property svn:eol-style set to native
File size: 23.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtGui module 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 [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qkbd_qws.h"
43#include "qkbd_qws_p.h"
44
45#ifndef QT_NO_QWS_KEYBOARD
46
47#include <QFile>
48#include <QDataStream>
49#include <QStringList>
50
51#include "qwindowsystem_qws.h"
52#include "qscreen_qws.h"
53#include "qtimer.h"
54#include <stdlib.h>
55
56//#define QT_DEBUG_KEYMAP
57
58
59QT_BEGIN_NAMESPACE
60
61class QWSKbPrivate : public QObject
62{
63 Q_OBJECT
64public:
65 QWSKbPrivate(QWSKeyboardHandler *h, const QString &device)
66 : m_handler(h), m_modifiers(0), m_composing(0), m_dead_unicode(0xffff),
67 m_no_zap(false), m_do_compose(false),
68 m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0)
69 {
70 m_ar_timer = new QTimer(this);
71 m_ar_timer->setSingleShot(true);
72 connect(m_ar_timer, SIGNAL(timeout()), SLOT(autoRepeat()));
73 m_ar_delay = 400;
74 m_ar_period = 80;
75
76 memset(m_locks, 0, sizeof(m_locks));
77
78 QString keymap;
79 QStringList args = device.split(QLatin1Char(':'));
80 foreach (const QString &arg, args) {
81 if (arg.startsWith(QLatin1String("keymap=")))
82 keymap = arg.mid(7);
83 else if (arg == QLatin1String("disable-zap"))
84 m_no_zap = true;
85 else if (arg == QLatin1String("enable-compose"))
86 m_do_compose = true;
87 else if (arg.startsWith(QLatin1String("repeat-delay=")))
88 m_ar_delay = arg.mid(13).toInt();
89 else if (arg.startsWith(QLatin1String("repeat-rate=")))
90 m_ar_period = arg.mid(12).toInt();
91 }
92
93 if (keymap.isEmpty() || !loadKeymap(keymap))
94 unloadKeymap();
95 }
96
97 ~QWSKbPrivate()
98 {
99 unloadKeymap();
100 }
101
102 void beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod)
103 {
104 m_ar_unicode = uni;
105 m_ar_keycode = code;
106 m_ar_modifier = mod;
107 m_ar_timer->start(m_ar_delay);
108 }
109
110 void endAutoRepeat()
111 {
112 m_ar_timer->stop();
113 }
114
115 static Qt::KeyboardModifiers toQtModifiers(quint8 mod)
116 {
117 Qt::KeyboardModifiers qtmod = Qt::NoModifier;
118
119 if (mod & (QWSKeyboard::ModShift | QWSKeyboard::ModShiftL | QWSKeyboard::ModShiftR))
120 qtmod |= Qt::ShiftModifier;
121 if (mod & (QWSKeyboard::ModControl | QWSKeyboard::ModCtrlL | QWSKeyboard::ModCtrlR))
122 qtmod |= Qt::ControlModifier;
123 if (mod & QWSKeyboard::ModAlt)
124 qtmod |= Qt::AltModifier;
125
126 return qtmod;
127 }
128
129 void unloadKeymap();
130 bool loadKeymap(const QString &file);
131
132private slots:
133 void autoRepeat()
134 {
135 m_handler->processKeyEvent(m_ar_unicode, m_ar_keycode, m_ar_modifier, false, true);
136 m_handler->processKeyEvent(m_ar_unicode, m_ar_keycode, m_ar_modifier, true, true);
137 m_ar_timer->start(m_ar_period);
138 }
139
140private:
141 QWSKeyboardHandler *m_handler;
142
143 // auto repeat simulation
144 int m_ar_unicode;
145 int m_ar_keycode;
146 Qt::KeyboardModifiers m_ar_modifier;
147 int m_ar_delay;
148 int m_ar_period;
149 QTimer *m_ar_timer;
150
151 // keymap handling
152 quint8 m_modifiers;
153 quint8 m_locks[3];
154 int m_composing;
155 quint16 m_dead_unicode;
156
157 bool m_no_zap;
158 bool m_do_compose;
159
160 const QWSKeyboard::Mapping *m_keymap;
161 int m_keymap_size;
162 const QWSKeyboard::Composing *m_keycompose;
163 int m_keycompose_size;
164
165 static const QWSKeyboard::Mapping s_keymap_default[];
166 static const QWSKeyboard::Composing s_keycompose_default[];
167
168 friend class QWSKeyboardHandler;
169};
170
171// simple builtin US keymap
172#include "qkbd_defaultmap_qws_p.h"
173
174// the unloadKeymap() function needs to be AFTER the defaultmap include,
175// since the sizeof(s_keymap_default) wouldn't work otherwise.
176
177void QWSKbPrivate::unloadKeymap()
178{
179 if (m_keymap && m_keymap != s_keymap_default)
180 delete [] m_keymap;
181 if (m_keycompose && m_keycompose != s_keycompose_default)
182 delete [] m_keycompose;
183
184 m_keymap = s_keymap_default;
185 m_keymap_size = sizeof(s_keymap_default) / sizeof(s_keymap_default[0]);
186 m_keycompose = s_keycompose_default;
187 m_keycompose_size = sizeof(s_keycompose_default) / sizeof(s_keycompose_default[0]);
188
189 // reset state, so we could switch keymaps at runtime
190 m_modifiers = 0;
191 memset(m_locks, 0, sizeof(m_locks));
192 m_composing = 0;
193 m_dead_unicode = 0xffff;
194}
195
196bool QWSKbPrivate::loadKeymap(const QString &file)
197{
198 QFile f(file);
199
200 if (!f.open(QIODevice::ReadOnly)) {
201 qWarning("Could not open keymap file '%s'", qPrintable(file));
202 return false;
203 }
204
205 // .qmap files have a very simple structure:
206 // quint32 magic (QWSKeyboard::FileMagic)
207 // quint32 version (1)
208 // quint32 keymap_size (# of struct QWSKeyboard::Mappings)
209 // quint32 keycompose_size (# of struct QWSKeyboard::Composings)
210 // all QWSKeyboard::Mappings via QDataStream::operator(<<|>>)
211 // all QWSKeyboard::Composings via QDataStream::operator(<<|>>)
212
213 quint32 qmap_magic, qmap_version, qmap_keymap_size, qmap_keycompose_size;
214
215 QDataStream ds(&f);
216
217 ds >> qmap_magic >> qmap_version >> qmap_keymap_size >> qmap_keycompose_size;
218
219 if (ds.status() != QDataStream::Ok || qmap_magic != QWSKeyboard::FileMagic || qmap_version != 1 || qmap_keymap_size == 0) {
220 qWarning("'%s' is ot a valid.qmap keymap file.", qPrintable(file));
221 return false;
222 }
223
224 QWSKeyboard::Mapping *qmap_keymap = new QWSKeyboard::Mapping[qmap_keymap_size];
225 QWSKeyboard::Composing *qmap_keycompose = qmap_keycompose_size ? new QWSKeyboard::Composing[qmap_keycompose_size] : 0;
226
227 for (quint32 i = 0; i < qmap_keymap_size; ++i)
228 ds >> qmap_keymap[i];
229 for (quint32 i = 0; i < qmap_keycompose_size; ++i)
230 ds >> qmap_keycompose[i];
231
232 if (ds.status() != QDataStream::Ok) {
233 delete [] qmap_keymap;
234 delete [] qmap_keycompose;
235
236 qWarning("Keymap file '%s' can not be loaded.", qPrintable(file));
237 return false;
238 }
239