Qt 4.8
qdirectfbmouse.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 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 "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 
55 
57 {
58  Q_OBJECT
59 public:
62 
63  void setEnabled(bool on);
64 private:
66  IDirectFBEventBuffer *eventBuffer;
67 #ifndef QT_NO_DIRECTFB_LAYER
68  IDirectFBDisplayLayer *layer;
69 #endif
71 
73  Qt::MouseButtons prevbuttons;
74 
75  DFBEvent event;
77 
78 private Q_SLOTS:
79  void readMouseData();
80 };
81 
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
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);
130  memset(&event, 0, sizeof(event));
131  bytesRead = 0;
132 
134  connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
135  setEnabled(true);
136 }
137 
139 {
140  if (eventBuffer)
141  eventBuffer->Release(eventBuffer);
142 }
143 
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
169  }
170 }
171 
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);
257 
258  if (p == prevPoint && wheel == 0 && buttons == prevbuttons)
259  continue;
260 
261  prevPoint = p;
263 
264  handler->mouseChanged(p, buttons, wheel);
265  }
266 }
267 
269  const QString &device)
270  : QWSMouseHandler(driver, device)
271 {
272  d = new QDirectFBMouseHandlerPrivate(this);
273 }
274 
276 {
277  delete d;
278 }
279 
281 {
282  d->setEnabled(false);
283 }
284 
286 {
287  d->setEnabled(true);
288 }
289 
291 #include "qdirectfbmouse.moc"
292 #endif // QT_NO_QWS_DIRECTFB
293 
294 
IDirectFBDisplayLayer * layer
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QDirectFBMouseHandler * handler
QDirectFBMouseHandlerPrivate * d
void suspend()
Implement this function to suspend reading and handling of mouse events, e.
The QWSMouseHandler class is a base class for mouse drivers in Qt for Embedded Linux.
Definition: qmouse_qws.h:66
#define SLOT(a)
Definition: qobjectdefs.h:226
static Qt::MouseButtons buttons
IDirectFBDisplayLayer * dfbDisplayLayer()
int deviceWidth() const
Returns the physical width of the framebuffer device in pixels.
Definition: qscreen_qws.h:233
#define Q_SLOTS
Definition: qobjectdefs.h:71
The QString class provides a Unicode character string.
Definition: qstring.h:83
void mouseChanged(const QPoint &pos, int bstate, int wheel=0)
Notifies the system of a new mouse event.
Definition: qmouse_qws.cpp:285
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
IDirectFBEventBuffer * eventBuffer
#define SIGNAL(a)
Definition: qobjectdefs.h:227
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
Q_CORE_EXPORT void qWarning(const char *,...)
IDirectFB * dfb()
unsigned int uint
Definition: qglobal.h:996
static QScreen * instance()
Returns a pointer to the application&#39;s QScreen instance.
Definition: qscreen_qws.h:201
#define Q_OBJECT
Definition: qobjectdefs.h:157
void resume()
Implement this function to resume reading and handling mouse events, e.
QDirectFBMouseHandlerPrivate(QDirectFBMouseHandler *h)
int fcntl(int, int,...)
int deviceHeight() const
Returns the full height of the framebuffer device in pixels.
Definition: qscreen_qws.h:234
QSocketNotifier * mouseNotifier
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
bool isEnabled() const
Returns true if the notifier is enabled; otherwise returns false.
void setEnabled(bool)
If enable is true, the notifier is enabled; otherwise the notifier is disabled.
The QScreen class is a base class for screen drivers in Qt for Embedded Linux.
Definition: qscreen_qws.h:191
int y() const
Returns the y coordinate of this point.
Definition: qpoint.h:131
static QDirectFBScreen * instance()
int x() const
Returns the x coordinate of this point.
Definition: qpoint.h:128
QDirectFBMouseHandler(const QString &driver=QString(), const QString &device=QString())
void limitToScreen(QPoint &pt)
Ensures that the given position is within the screen&#39;s boundaries, changing the position if necessary...
Definition: qmouse_qws.cpp:248
Q_CORE_EXPORT void qCritical(const char *,...)
int errno
int socket() const
Returns the socket identifier specified to the constructor.