summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp')
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp
new file mode 100644
index 0000000000..3999b85afb
--- /dev/null
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp
@@ -0,0 +1,294 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdirectfbmouse.h"
+
+#ifndef QT_NO_QWS_DIRECTFB
+
+#include "qdirectfbscreen.h"
+#include <qsocketnotifier.h>
+
+#include <directfb.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDirectFBMouseHandlerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QDirectFBMouseHandlerPrivate(QDirectFBMouseHandler *h);
+ ~QDirectFBMouseHandlerPrivate();
+
+ void setEnabled(bool on);
+private:
+ QDirectFBMouseHandler *handler;
+ IDirectFBEventBuffer *eventBuffer;
+#ifndef QT_NO_DIRECTFB_LAYER
+ IDirectFBDisplayLayer *layer;
+#endif
+ QSocketNotifier *mouseNotifier;
+
+ QPoint prevPoint;
+ Qt::MouseButtons prevbuttons;
+
+ DFBEvent event;
+ uint bytesRead;
+
+private Q_SLOTS:
+ void readMouseData();
+};
+
+QDirectFBMouseHandlerPrivate::QDirectFBMouseHandlerPrivate(QDirectFBMouseHandler *h)
+ : handler(h), eventBuffer(0)
+{
+ DFBResult result;
+
+ QScreen *screen = QScreen::instance();
+ if (!screen) {
+ qCritical("QDirectFBMouseHandler: no screen instance found");
+ return;
+ }
+
+ IDirectFB *fb = QDirectFBScreen::instance()->dfb();
+ if (!fb) {
+ qCritical("QDirectFBMouseHandler: DirectFB not initialized");
+ return;
+ }
+
+#ifndef QT_NO_DIRECTFB_LAYER
+ layer = QDirectFBScreen::instance()->dfbDisplayLayer();
+ if (!layer) {
+ qCritical("QDirectFBMouseHandler: Unable to get primary display layer");
+ return;
+ }
+#endif
+
+ DFBInputDeviceCapabilities caps;
+ caps = DICAPS_BUTTONS | DICAPS_AXES;
+ result = fb->CreateInputEventBuffer(fb, caps, DFB_TRUE, &eventBuffer);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBMouseHandler: "
+ "Unable to create input event buffer", result);
+ return;
+ }
+
+ int fd;
+ result = eventBuffer->CreateFileDescriptor(eventBuffer, &fd);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBMouseHandler: "
+ "Unable to create file descriptor", result);
+ return;
+ }
+
+ int flags = fcntl(fd, F_GETFL, 0);
+ fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+
+ // DirectFB seems to assume that the mouse always starts centered
+ prevPoint = QPoint(screen->deviceWidth() / 2, screen->deviceHeight() / 2);
+ prevbuttons = Qt::NoButton;
+ memset(&event, 0, sizeof(event));
+ bytesRead = 0;
+
+ mouseNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+ connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
+ setEnabled(true);
+}
+
+QDirectFBMouseHandlerPrivate::~QDirectFBMouseHandlerPrivate()
+{
+ if (eventBuffer)
+ eventBuffer->Release(eventBuffer);
+}
+
+void QDirectFBMouseHandlerPrivate::setEnabled(bool on)
+{
+ if (mouseNotifier->isEnabled() != on) {
+#ifndef QT_NO_DIRECTFB_LAYER
+ DFBResult result;
+ result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::QDirectFBScreenCursor: "
+ "Unable to set cooperative level", result);
+ }
+ result = layer->EnableCursor(layer, on ? 1 : 0);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::QDirectFBScreenCursor: "
+ "Unable to enable cursor", result);
+ }
+
+ result = layer->SetCooperativeLevel(layer, DLSCL_SHARED);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreenCursor::show: "
+ "Unable to set cooperative level", result);
+ }
+
+ layer->SetCooperativeLevel(layer, DLSCL_SHARED);
+#endif
+ mouseNotifier->setEnabled(on);
+ }
+}
+
+void QDirectFBMouseHandlerPrivate::readMouseData()
+{
+ if (!QScreen::instance())
+ return;
+
+ for (;;) {
+ // GetEvent returns DFB_UNSUPPORTED after CreateFileDescriptor().
+ // This seems stupid and I really hope it's a bug which will be fixed.
+
+ // DFBResult ret = eventBuffer->GetEvent(eventBuffer, &event);
+
+ char *buf = reinterpret_cast<char*>(&event);
+ int ret = ::read(mouseNotifier->socket(),
+ buf + bytesRead, sizeof(DFBEvent) - bytesRead);
+ if (ret == -1) {
+ if (errno == EINTR)
+ continue;
+ if (errno == EAGAIN)
+ return;
+ qWarning("QDirectFBMouseHandlerPrivate::readMouseData(): %s",
+ strerror(errno));
+ return;
+ }
+
+ Q_ASSERT(ret >= 0);
+ bytesRead += ret;
+ if (bytesRead < sizeof(DFBEvent))
+ break;
+ bytesRead = 0;
+
+ Q_ASSERT(event.clazz == DFEC_INPUT);
+
+ const DFBInputEvent input = event.input;
+ int x = prevPoint.x();
+ int y = prevPoint.y();
+ int wheel = 0;
+
+ if (input.type == DIET_AXISMOTION) {
+#if defined(QT_NO_DIRECTFB_LAYER) || defined(QT_DIRECTFB_WINDOW_AS_CURSOR)
+ if (input.flags & DIEF_AXISABS) {
+ switch (input.axis) {
+ case DIAI_X: x = input.axisabs; break;
+ case DIAI_Y: y = input.axisabs; break;
+ default:
+ qWarning("QDirectFBMouseHandlerPrivate::readMouseData: "
+ "unknown axis (absolute) %d", input.axis);
+ break;
+ }
+ } else if (input.flags & DIEF_AXISREL) {
+ switch (input.axis) {
+ case DIAI_X: x += input.axisrel; break;
+ case DIAI_Y: y += input.axisrel; break;
+ case DIAI_Z: wheel = -120 * input.axisrel; break;
+ default:
+ qWarning("QDirectFBMouseHandlerPrivate::readMouseData: "
+ "unknown axis (releative) %d", input.axis);
+ }
+ }
+#else
+ if (input.axis == DIAI_X || input.axis == DIAI_Y) {
+ DFBResult result = layer->GetCursorPosition(layer, &x, &y);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBMouseHandler::readMouseData",
+ result);
+ }
+ } else if (input.axis == DIAI_Z) {
+ Q_ASSERT(input.flags & DIEF_AXISREL);
+ wheel = input.axisrel;
+ wheel *= -120;
+ }
+#endif
+ }
+
+ Qt::MouseButtons buttons = Qt::NoButton;
+ if (input.flags & DIEF_BUTTONS) {
+ if (input.buttons & DIBM_LEFT)
+ buttons |= Qt::LeftButton;
+ if (input.buttons & DIBM_MIDDLE)
+ buttons |= Qt::MidButton;
+ if (input.buttons & DIBM_RIGHT)
+ buttons |= Qt::RightButton;
+ }
+
+ QPoint p = QPoint(x, y);
+ handler->limitToScreen(p);
+
+ if (p == prevPoint && wheel == 0 && buttons == prevbuttons)
+ continue;
+
+ prevPoint = p;
+ prevbuttons = buttons;
+
+ handler->mouseChanged(p, buttons, wheel);
+ }
+}
+
+QDirectFBMouseHandler::QDirectFBMouseHandler(const QString &driver,
+ const QString &device)
+ : QWSMouseHandler(driver, device)
+{
+ d = new QDirectFBMouseHandlerPrivate(this);
+}
+
+QDirectFBMouseHandler::~QDirectFBMouseHandler()
+{
+ delete d;
+}
+
+void QDirectFBMouseHandler::suspend()
+{
+ d->setEnabled(false);
+}
+
+void QDirectFBMouseHandler::resume()
+{
+ d->setEnabled(true);
+}
+
+QT_END_NAMESPACE
+#include "qdirectfbmouse.moc"
+#endif // QT_NO_QWS_DIRECTFB
+
+