ARM ABI requires stack to be aligned on a 64-bit boundary
[bertos.git] / bertos / emul / emulkbd.cpp
1 /**
2  * \file
3  * <!--
4  * This file is part of BeRTOS.
5  *
6  * Bertos is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  * As a special exception, you may use this file as part of a free software
21  * library without restriction.  Specifically, if other files instantiate
22  * templates or use macros or inline functions from this file, or you compile
23  * this file and link it with other files to produce an executable, this
24  * file does not by itself cause the resulting executable to be covered by
25  * the GNU General Public License.  This exception does not however
26  * invalidate any other reasons why the executable file might be covered by
27  * the GNU General Public License.
28  *
29  * Copyright 2006 Develer S.r.l. (http://www.develer.com/)
30  * Copyright 2001 Bernie Innocenti <bernie@codewiz.org>
31  *
32  * -->
33  *
34  * \version $Id$
35  *
36  * \author Bernie Innocenti <bernie@codewiz.org>
37  *
38  * \brief QT-based widget for keyboard emulation (implementation)
39  */
40
41 #include "emulkbd.h"
42 #include "emul.h"
43
44 #include <QtGui/QPainter>
45 #include <QtGui/QPixmap>
46 #include <QtGui/QSizePolicy>
47 #include <QtGui/QLayout>
48 #include <QtGui/QKeyEvent>
49 #include <QtCore/QEvent>
50 #include <QtCore/QSize>
51 #include <QtCore/QRect>
52
53
54 EmulKey::EmulKey(EmulKbd *kbd, const char *label, int _keycode, int _row, int _col) :
55         QPushButton(label, kbd),
56         row(_row), col(_col),
57         keycode(_keycode)
58 {
59         // don't let the widget get focus
60         setFocusPolicy(Qt::NoFocus);
61
62         // unused
63         connect(this, SIGNAL(pressed()), this, SLOT(keyPressed()));
64         connect(this, SIGNAL(released()), this, SLOT(keyReleased()));
65 }
66
67
68 EmulKey::~EmulKey()
69 {
70         // nop
71 }
72
73
74 /**
75  * Override standad QButton behaviour: we must also emit the signals.
76  */
77 // unused
78 void EmulKey::setDown(bool enable)
79 {
80         // let our superclass do everything else
81         QPushButton::setDown(enable);
82
83         if (enable)
84                 emit pressed();
85         else
86                 emit released();
87 }
88
89
90 // unused
91 void EmulKey::keyPressed(void)
92 {
93         static_cast<EmulKbd *>(parent())->setKey(row, col, true);
94 }
95
96
97 // unused
98 void EmulKey::keyReleased(void)
99 {
100         static_cast<EmulKbd *>(parent())->setKey(row, col, false);
101 }
102
103
104 EmulKbd::EmulKbd(QWidget *parent, Qt::WFlags f) :
105         QFrame(parent, f),
106         layout(new QGridLayout(this)),
107         active_row(0)
108 {
109         setFrameStyle(QFrame::Box | QFrame::Sunken);
110         setLineWidth(1);
111         setFocusPolicy(Qt::StrongFocus);
112         frame_width = frameWidth();
113 }
114
115
116 EmulKbd::~EmulKbd()
117 {
118         delete layout;
119 }
120
121
122 QSizePolicy EmulKbd::sizePolicy() const
123 {
124         return QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
125 }
126
127
128 void EmulKbd::resizeEvent(QResizeEvent *event)
129 {
130         // Let our superclass process the event first
131         QFrame::resizeEvent(event);
132 }
133
134
135 // handle key presses for all keys in keyboard
136 bool EmulKbd::event(QEvent *_e)
137 {
138         switch (_e->type())
139         {
140                 case QEvent::KeyPress:
141                 case QEvent::KeyRelease:
142                 {
143                         QKeyEvent *e = static_cast<QKeyEvent *>(_e);
144                         int keycode = e->key();
145                         EmulKey *key;
146
147                         // ignore repeated keys
148                         if (!e->isAutoRepeat())
149                         {
150                                 // scan all children
151                                 for (QObjectList::const_iterator it(children().begin()); it != children().end(); ++it)
152                                 {
153                                         // only keys, not other children!
154                                         if ((*it)->metaObject() == &EmulKey::staticMetaObject)
155                                         // if ((key = dynamic_cast<EmulKey *>(*it)))
156                                         {
157                                                 key = static_cast<EmulKey *>(*it);
158
159                                                 // same key?
160                                                 if (key->keycode == keycode)
161                                                 {
162                                                         // yes, tell key to go down (or up)
163                                                         key->setDown(_e->type() == QEvent::KeyPress);
164                                                         break;
165                                                 }
166                                         }
167                                 }
168                         }
169                         return true;
170                 }
171
172                 default:
173                         // let superclass process this event
174                         return QFrame::event(_e);
175
176         } // end switch(_e->type())
177 }
178
179
180 void EmulKbd::addKey(const char *label, int keycode, int row, int col, int matrix_row, int matrix_col)
181 {
182         if (matrix_row == -1)
183                 matrix_row = row;
184         if (matrix_col == -1)
185                 matrix_col = col;
186
187         layout->addWidget(new EmulKey(this, label, keycode, matrix_row, matrix_col), row, col);
188 }
189
190
191 // unused
192 void EmulKbd::setKey(int /*row*/, int /*col*/, bool /*on*/)
193 {
194 }
195
196
197 void EmulKbd::setRow(int r)
198 {
199         active_row = r;
200 }
201
202 int EmulKbd::readCols(void)
203 {
204         QLayoutItem *item;
205         EmulKey *key;
206         int cols = 0;
207
208         for (int i = 0; (item = layout->itemAt(i)); ++i)
209         {
210                 key = static_cast<EmulKey *>(item->widget());
211                 if (key->row == active_row)
212                 {
213                         if (key->isDown())
214                                 cols |= (1<<key->col);
215                 }
216         }
217         return cols;
218 }
219
220 extern "C" void emul_kbdSetRows(int r)
221 {
222         emul->emulKbd->setRow(r);
223 }
224
225
226 extern "C" int emul_kbdReadCols(void)
227 {
228         return emul->emulKbd->readCols();
229 }
230
231 #include "emulkbd_moc.cpp"