source: trunk/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp@ 561

Last change on this file since 561 was 561, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.1 sources.

  • Property svn:eol-style set to native
File size: 9.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 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 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 [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qdirectfbmouse.h"
43
44#ifndef QT_NO_QWS_DIRECTFB
45
46#include "qdirectfbscreen.h"
47#include <qsocketnotifier.h>
48
49#include <directfb.h>
50#include <unistd.h>
51#include <fcntl.h>
52#include <errno.h>
53
54QT_BEGIN_NAMESPACE
55
56class QDirectFBMouseHandlerPrivate : public QObject
57{
58 Q_OBJECT
59public:
60 QDirectFBMouseHandlerPrivate(QDirectFBMouseHandler *h);
61 ~QDirectFBMouseHandlerPrivate();
62
63 void setEnabled(bool on);
64private:
65 QDirectFBMouseHandler *handler;
66 IDirectFBEventBuffer *eventBuffer;
67#ifndef QT_NO_DIRECTFB_LAYER
68 IDirectFBDisplayLayer *layer;
69#endif
70 QSocketNotifier *mouseNotifier;
71
72 QPoint prevPoint;
73 Qt::MouseButtons prevbuttons;
74
75 DFBEvent event;
76 uint bytesRead;
77
78private Q_SLOTS:
79 void readMouseData();
80};
81
82QDirectFBMouseHandlerPrivate::QDirectFBMouseHandlerPrivate(QDirectFBMouseHandler *h)
83 : handler(h), eventBuffer(0)
84{
85 DFBResult result;
86
87 QScreen *screen = QScreen::instance();
88 if (!screen) {
89 qCritical("QDirectFBMouseHandler: no screen instance found");
90 return;
91 }
92
93 IDirectFB *fb = QDirectFBScreen::instance()->dfb();
94 if (!fb) {
95 qCritical("QDirectFBMouseHandler: DirectFB not initialized");
96 return;
97 }
98
99#ifndef QT_NO_DIRECTFB_LAYER
100 layer = QDirectFBScreen::instance()->dfbDisplayLayer();
101 if (!layer) {
102 qCritical("QDirectFBMouseHandler: Unable to get primary display layer");
103 return;
104 }
105#endif
106
107 DFBInputDeviceCapabilities caps;
108 caps = DICAPS_BUTTONS | DICAPS_AXES;
109 result = fb->CreateInputEventBuffer(fb, caps, DFB_TRUE, &eventBuffer);
110 if (result != DFB_OK) {
111 DirectFBError("QDirectFBMouseHandler: "
112 "Unable to create input event buffer", result);
113 return;
114 }
115
116 int fd;
117 result = eventBuffer->CreateFileDescriptor(eventBuffer, &fd);
118 if (result != DFB_OK) {
119 DirectFBError("QDirectFBMouseHandler: "
120 "Unable to create file descriptor", result);
121 return;
122 }
123
124 int flags = fcntl(fd, F_GETFL, 0);
125 fcntl(fd, F_SETFL, flags | O_NONBLOCK);
126
127 // DirectFB seems to assume that the mouse always starts centered
128 prevPoint = QPoint(screen->deviceWidth() / 2, screen->deviceHeight() / 2);
129 prevbuttons = Qt::NoButton;
130 memset(&event, 0, sizeof(event));
131 bytesRead = 0;
132
133 mouseNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
134 connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
135 setEnabled(true);
136}
137
138QDirectFBMouseHandlerPrivate::~QDirectFBMouseHandlerPrivate()
139{
140 if (eventBuffer)
141 eventBuffer->Release(eventBuffer);
142}
143
144void QDirectFBMouseHandlerPrivate::setEnabled(bool on)
145{
146 if (mouseNotifier->isEnabled() != on) {
147#ifndef QT_NO_DIRECTFB_LAYER
148 DFBResult result;
149 result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
150 if (result != DFB_OK) {
151 DirectFBError("QDirectFBScreenCursor::QDirectFBScreenCursor: "
152 "Unable to set cooperative level", result);
153 }
154 result = layer->EnableCursor(layer, on ? 1 : 0);
155 if (result != DFB_OK) {
156 DirectFBError("QDirectFBScreenCursor::QDirectFBScreenCursor: "
157 "Unable to enable cursor", result);
158 }
159
160 result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
161 if (result != DFB_OK) {
162 DirectFBError("QDirectFBScreenCursor::show: "
163 "Unable to set cooperative level", result);
164 }
165
166 layer->SetCooperativeLevel(layer, DLSCL_SHARED);
167#endif
168 mouseNotifier->setEnabled(on);
169 }
170}
171
172void QDirectFBMouseHandlerPrivate::readMouseData()
173{
174 if (!QScreen::instance())
175 return;
176
177 for (;;) {
178 // GetEvent returns DFB_UNSUPPORTED after CreateFileDescriptor().
179 // This seems stupid and I really hope it's a bug which will be fixed.
180
181 // DFBResult ret = eventBuffer->GetEvent(eventBuffer, &event);
182
183 char *buf = reinterpret_cast<char*>(&event);
184 int ret = ::read(mouseNotifier->socket(),
185 buf + bytesRead, sizeof(DFBEvent) - bytesRead);
186 if (ret == -1) {
187 if (errno == EINTR)
188 continue;
189 if (errno == EAGAIN)
190 return;
191 qWarning("QDirectFBMouseHandlerPrivate::readMouseData(): %s",
192 strerror(errno));
193 return;
194 }
195
196 Q_ASSERT(ret >= 0);
197 bytesRead += ret;
198 if (bytesRead < sizeof(DFBEvent))
199 break;
200 bytesRead = 0;
201
202 Q_ASSERT(event.clazz == DFEC_INPUT);
203
204 const DFBInputEvent input = event.input;
205 int x = prevPoint.x();
206 int y = prevPoint.y();
207 int wheel = 0;
208
209 if (input.type == DIET_AXISMOTION) {
210#if defined(QT_NO_DIRECTFB_LAYER) || defined(QT_DIRECTFB_WINDOW_AS_CURSOR)
211 if (input.flags & DIEF_AXISABS) {
212 switch (input.axis) {
213 case DIAI_X: x = input.axisabs; break;
214 case DIAI_Y: y = input.axisabs; break;
215 default:
216 qWarning("QDirectFBMouseHandlerPrivate::readMouseData: "
217 "unknown axis (absolute) %d", input.axis);
218 break;
219 }
220 } else if (input.flags & DIEF_AXISREL) {
221 switch (input.axis) {
222 case DIAI_X: x += input.axisrel; break;
223 case DIAI_Y: y += input.axisrel; break;
224 case DIAI_Z: wheel = -120 * input.axisrel; break;
225 default:
226 qWarning("QDirectFBMouseHandlerPrivate::readMouseData: "
227 "unknown axis (releative) %d", input.axis);
228 }
229 }
230#else
231 if (input.axis == DIAI_X || input.axis == DIAI_Y) {
232 DFBResult result = layer->GetCursorPosition(layer, &x, &y);
233 if (result != DFB_OK) {
234 DirectFBError("QDirectFBMouseHandler::readMouseData",
235 result);
236 }
237 } else if (input.axis == DIAI_Z) {
238 Q_ASSERT(input.flags & DIEF_AXISREL);
239 wheel = input.axisrel;
240 wheel *= -120;
241 }
242#endif
243 }
244
245 Qt::MouseButtons buttons = Qt::NoButton;
246 if (input.flags & DIEF_BUTTONS) {
247 if (input.buttons & DIBM_LEFT)
248 buttons |= Qt::LeftButton;
249 if (input.buttons & DIBM_MIDDLE)
250 buttons |= Qt::MidButton;
251 if (input.buttons & DIBM_RIGHT)
252 buttons |= Qt::RightButton;
253 }
254
255 QPoint p = QPoint(x, y);
256 handler->limitToScreen(p);
257
258 if (p == prevPoint && wheel == 0 && buttons == prevbuttons)
259 continue;
260
261 prevPoint = p;
262 prevbuttons = buttons;
263
264 handler->mouseChanged(p, buttons, wheel);
265 }
266}
267
268QDirectFBMouseHandler::QDirectFBMouseHandler(const QString &driver,
269 const QString &device)
270 : QWSMouseHandler(driver, device)
271{
272 d = new QDirectFBMouseHandlerPrivate(this);
273}
274
275QDirectFBMouseHandler::~QDirectFBMouseHandler()
276{
277 delete d;
278}
279
280void QDirectFBMouseHandler::suspend()
281{
282 d->setEnabled(false);
283}
284
285void QDirectFBMouseHandler::resume()
286{
287 d->setEnabled(true);
288}
289
290QT_END_NAMESPACE
291#include "qdirectfbmouse.moc"
292#endif // QT_NO_QWS_DIRECTFB
293
294
Note: See TracBrowser for help on using the repository browser.