From db50af5e307b9fc0c29567ac39012c7716bc45a6 Mon Sep 17 00:00:00 2001 From: Kevin Krammer Date: Thu, 29 Mar 2012 13:23:42 +0200 Subject: Move screen event processing into its own class The event handler class can then be reused when we have proper BPS event support available from corelib Backport of a80a2c6da241dac77f533bc702a1c7d94349a812 Change-Id: I9f8f661ca6b976aa02990bc8c8af8e5472e5faa4 Reviewed-by: Thomas McGuire Reviewed-by: Sean Harmer Reviewed-by: Robin Burchell --- src/plugins/platforms/blackberry/blackberry.pro | 6 +- .../platforms/blackberry/qbbeventthread.cpp | 528 ++------------------- src/plugins/platforms/blackberry/qbbeventthread.h | 22 +- .../platforms/blackberry/qbbintegration.cpp | 2 +- .../platforms/blackberry/qbbscreeneventhandler.cpp | 528 +++++++++++++++++++++ .../platforms/blackberry/qbbscreeneventhandler.h | 81 ++++ 6 files changed, 653 insertions(+), 514 deletions(-) create mode 100644 src/plugins/platforms/blackberry/qbbscreeneventhandler.cpp create mode 100644 src/plugins/platforms/blackberry/qbbscreeneventhandler.h diff --git a/src/plugins/platforms/blackberry/blackberry.pro b/src/plugins/platforms/blackberry/blackberry.pro index 0e55090..c8e483f 100644 --- a/src/plugins/platforms/blackberry/blackberry.pro +++ b/src/plugins/platforms/blackberry/blackberry.pro @@ -18,7 +18,8 @@ SOURCES = main.cpp \ qbbvirtualkeyboard.cpp \ qbbclipboard.cpp \ qbblocalethread.cpp \ - qbbrootwindow.cpp + qbbrootwindow.cpp \ + qbbscreeneventhandler.cpp HEADERS = qbbbuffer.h \ qbbeventthread.h \ @@ -33,7 +34,8 @@ HEADERS = qbbbuffer.h \ qbbvirtualkeyboard.h \ qbbclipboard.h \ qbblocalethread.h \ - qbbrootwindow.h + qbbrootwindow.h \ + qbbscreeneventhandler.h QMAKE_CXXFLAGS += -I./private diff --git a/src/plugins/platforms/blackberry/qbbeventthread.cpp b/src/plugins/platforms/blackberry/qbbeventthread.cpp index 48c9513..ae3d44d 100644 --- a/src/plugins/platforms/blackberry/qbbeventthread.cpp +++ b/src/plugins/platforms/blackberry/qbbeventthread.cpp @@ -40,42 +40,18 @@ // #define QBBEVENTTHREAD_DEBUG #include "qbbeventthread.h" -#include "qbbinputcontext.h" -#include "qbbkeytranslator.h" +#include "qbbscreeneventhandler.h" -#include -#include -#include #include #include -#include -#include -#include +QT_BEGIN_NAMESPACE -QBBEventThread::QBBEventThread(screen_context_t context, QPlatformScreen& screen) +QBBEventThread::QBBEventThread(screen_context_t context) : mContext(context), - mScreen(screen), - mQuit(false), - mLastButtonState(Qt::NoButton), - mLastMouseWindow(0) + mQuit(false) { - // initialize array of touch points - for (int i = 0; i < MAX_TOUCH_POINTS; i++) { - - // map array index to id - mTouchPoints[i].id = i; - - // first finger is primary - mTouchPoints[i].isPrimary = (i == 0); - - // pressure is not supported - use default - mTouchPoints[i].pressure = 1.0; - - // nothing touching - mTouchPoints[i].state = Qt::TouchPointReleased; - } } QBBEventThread::~QBBEventThread() @@ -84,6 +60,16 @@ QBBEventThread::~QBBEventThread() shutdown(); } +void QBBEventThread::injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap) +{ + QBBScreenEventHandler::injectKeyboardEvent(flags, sym, mod, scan, cap); +} + +void QBBEventThread::injectPointerMoveEvent(int x, int y) +{ + mEventHandler.injectPointerMoveEvent(x, y); +} + void QBBEventThread::run() { screen_event_t event; @@ -91,9 +77,8 @@ void QBBEventThread::run() // create screen event errno = 0; int result = screen_create_event(&event); - if (result) { + if (result) qFatal("QBB: failed to create event, errno=%d", errno); - } #if defined(QBBEVENTTHREAD_DEBUG) qDebug() << "QBB: event loop started"; @@ -105,12 +90,25 @@ void QBBEventThread::run() // block until screen event is available errno = 0; result = screen_get_event(mContext, event, -1); - if (result) { + if (result) qFatal("QBB: failed to get event, errno=%d", errno); - } // process received event - dispatchEvent(event); + errno = 0; + int qnxType; + int result = screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType); + if (result) + qFatal("QBB: failed to query event type, errno=%d", errno); + + if (qnxType == SCREEN_EVENT_USER) { + // treat all user events as shutdown requests + #if defined(QBBEVENTTHREAD_DEBUG) + qDebug() << "QBB: QNX user event"; + #endif + mQuit = true; + } else { + mEventHandler.handleEvent(event, qnxType); + } } #if defined(QBBEVENTTHREAD_DEBUG) @@ -128,26 +126,23 @@ void QBBEventThread::shutdown() // create screen event errno = 0; int result = screen_create_event(&event); - if (result) { + if (result) qFatal("QBB: failed to create event, errno=%d", errno); - } // set the event type as user errno = 0; int type = SCREEN_EVENT_USER; result = screen_set_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type); - if (result) { + if (result) qFatal("QBB: failed to set event type, errno=%d", errno); - } // NOTE: ignore SCREEN_PROPERTY_USER_DATA; treat all user events as shutdown events // post event to event loop so it will wake up and die errno = 0; result = screen_send_event(mContext, event, getpid()); - if (result) { + if (result) qFatal("QBB: failed to set event type, errno=%d", errno); - } // cleanup screen_destroy_event(event); @@ -164,457 +159,4 @@ void QBBEventThread::shutdown() #endif } -void QBBEventThread::dispatchEvent(screen_event_t event) -{ - // get the event type - errno = 0; - int qnxType; - int result = screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType); - if (result) { - qFatal("QBB: failed to query event type, errno=%d", errno); - } - - switch (qnxType) { - case SCREEN_EVENT_MTOUCH_TOUCH: - case SCREEN_EVENT_MTOUCH_MOVE: - case SCREEN_EVENT_MTOUCH_RELEASE: - handleTouchEvent(event, qnxType); - break; - - case SCREEN_EVENT_KEYBOARD: - handleKeyboardEvent(event); - break; - - case SCREEN_EVENT_POINTER: - handlePointerEvent(event); - break; - - case SCREEN_EVENT_CLOSE: - handleCloseEvent(event); - break; - - case SCREEN_EVENT_USER: - // treat all user events as shutdown requests -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: QNX user event"; -#endif - mQuit = true; - break; - - default: - // event ignored -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: QNX unknown event"; -#endif - break; - } -} - -void QBBEventThread::handleKeyboardEvent(screen_event_t event) -{ - // get flags of key event - errno = 0; - int flags; - int result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_FLAGS, &flags); - if (result) { - qFatal("QBB: failed to query event flags, errno=%d", errno); - } - - // get key code - errno = 0; - int sym; - result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SYM, &sym); - if (result) { - qFatal("QBB: failed to query event sym, errno=%d", errno); - } - - int modifiers; - result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_MODIFIERS, &modifiers); - if (result) { - qFatal("QBB: failed to query event modifiers, errno=%d", errno); - } - - int scan; - result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SCAN, &scan); - if (result) { - qFatal("QBB: failed to query event modifiers, errno=%d", errno); - } - - int cap; - result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &cap); - if (result) { - qFatal("QBB: failed to query event cap, errno=%d", errno); - } - - // Let the input context have a stab at it first. - QWidget *focusWidget = QApplication::focusWidget(); - if (focusWidget) { - QInputContext* inputContext = focusWidget->inputContext(); - if (inputContext) { - QBBInputContext *qbbInputContext = dynamic_cast(inputContext); - - if (qbbInputContext && qbbInputContext->handleKeyboardEvent(flags, sym, modifiers, scan, cap)) - return; - } - } - - injectKeyboardEvent(flags, sym, modifiers, scan, cap); -} - -void QBBEventThread::injectKeyboardEvent(int flags, int sym, int modifiers, int scan, int cap) -{ - Q_UNUSED(scan); - - Qt::KeyboardModifiers qtMod = Qt::NoModifier; - if (modifiers & KEYMOD_SHIFT) - qtMod |= Qt::ShiftModifier; - if (modifiers & KEYMOD_CTRL) - qtMod |= Qt::ControlModifier; - if (modifiers & KEYMOD_ALT) - qtMod |= Qt::AltModifier; - - // determine event type - QEvent::Type type = (flags & KEY_DOWN) ? QEvent::KeyPress : QEvent::KeyRelease; - - // Check if the key cap is valid - if (flags & KEY_CAP_VALID) { - Qt::Key key; - QString keyStr; - - if (cap >= 0x20 && cap <= 0x0ff) { - key = Qt::Key(std::toupper(cap)); // Qt expects the CAP to be upper case. - - if ( qtMod & Qt::ControlModifier ) { - keyStr = QChar((int)(key & 0x3f)); - } else { - if (flags & KEY_SYM_VALID) { - keyStr = QChar(sym); - } - } - } else if ((cap > 0x0ff && cap < UNICODE_PRIVATE_USE_AREA_FIRST) || cap > UNICODE_PRIVATE_USE_AREA_LAST) { - key = (Qt::Key)cap; - keyStr = QChar(sym); - } else { - if (isKeypadKey(cap)) - qtMod |= Qt::KeypadModifier; // Is this right? - key = keyTranslator(cap); - } - - QWindowSystemInterface::handleKeyEvent(QApplication::activeWindow(), type, key, qtMod, keyStr); -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt key t=" << type << ", k=" << key << ", s=" << keyStr; -#endif - } -} - -void QBBEventThread::injectPointerMoveEvent(int x, int y) -{ -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "Injecting mouse event..." << x << y; -#endif - - QWidget *w = qApp->topLevelAt(x, y); - void *qnxWindow = w ? w->platformWindow() : 0; - - // Generate enter and leave events as needed. - if (qnxWindow != mLastMouseWindow) { - QWidget* wOld = QWidget::find( (WId)mLastMouseWindow ); - - if (wOld) { - QWindowSystemInterface::handleLeaveEvent(wOld); -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt leave, w=" << wOld; -#endif - } - - if (w) { - QWindowSystemInterface::handleEnterEvent(w); -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt enter, w=" << w; -#endif - } - } - - mLastMouseWindow = qnxWindow; - - // convert point to local coordinates - QPoint globalPoint(x, y); - QPoint localPoint(x, y); - - if (w) - localPoint = QPoint(x - w->x(), y - w->y()); - - // Convert buttons. - Qt::MouseButtons buttons = mLastButtonState; - - if (w) { - // Inject mouse event into Qt only if something has changed. - if (mLastGlobalMousePoint != globalPoint || - mLastLocalMousePoint != localPoint || - mLastButtonState != buttons) { - QWindowSystemInterface::handleMouseEvent(w, localPoint, globalPoint, buttons); -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt mouse, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), b=" << (int)buttons; -#endif - } - } - - mLastGlobalMousePoint = globalPoint; - mLastLocalMousePoint = localPoint; - mLastButtonState = buttons; -} - -void QBBEventThread::handlePointerEvent(screen_event_t event) -{ - errno = 0; - - // Query the window that was clicked - void *qnxWindow; - int result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &qnxWindow); - if (result) { - qFatal("QBB: failed to query event window, errno=%d", errno); - } - - // Query the button states - int buttonState = 0; - result = screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttonState); - if (result) { - qFatal("QBB: failed to query event button state, errno=%d", errno); - } - - // Query the window position - int windowPos[2]; - result = screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos); - if (result) { - qFatal("QBB: failed to query event window position, errno=%d", errno); - } - - // Query the screen position - int pos[2]; - result = screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos); - if (result) { - qFatal("QBB: failed to query event position, errno=%d", errno); - } - - // Query the wheel delta - int wheelDelta = 0; - result = screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheelDelta); - if (result) { - qFatal("QBB: failed to query event wheel delta, errno=%d", errno); - } - - // map window to top-level widget - QWidget* w = QWidget::find( (WId)qnxWindow ); - - // Generate enter and leave events as needed. - if (qnxWindow != mLastMouseWindow) { - QWidget* wOld = QWidget::find( (WId)mLastMouseWindow ); - - if (wOld) { - QWindowSystemInterface::handleLeaveEvent(wOld); -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt leave, w=" << wOld; -#endif - } - - if (w) { - QWindowSystemInterface::handleEnterEvent(w); -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt enter, w=" << w; -#endif - } - } - mLastMouseWindow = qnxWindow; - - // Apply scaling to wheel delta and invert value for Qt. We'll probably want to scale - // this via a system preference at some point. But for now this is a sane value and makes - // the wheel usable. - wheelDelta *= -10; - - // convert point to local coordinates - QPoint globalPoint(pos[0], pos[1]); - QPoint localPoint(windowPos[0], windowPos[1]); - - // Convert buttons. - // Some QNX header files invert 'Right Button versus "Left Button' ('Right' == 0x01). But they also offer a 'Button Swap' bit, - // so we may receive events as shown. (If this is wrong, the fix is easy.) - // QNX Button mask is 8 buttons wide, with a maximum value of 0x80. - Qt::MouseButtons buttons = Qt::NoButton; - if (buttonState & 0x01) - buttons |= Qt::LeftButton; - if (buttonState & 0x02) - buttons |= Qt::MidButton; - if (buttonState & 0x04) - buttons |= Qt::RightButton; - if (buttonState & 0x08) - buttons |= Qt::XButton1; - if (buttonState & 0x10) - buttons |= Qt::XButton2; - - if (w) { - // Inject mouse event into Qt only if something has changed. - if (mLastGlobalMousePoint != globalPoint || - mLastLocalMousePoint != localPoint || - mLastButtonState != buttons) { - QWindowSystemInterface::handleMouseEvent(w, localPoint, globalPoint, buttons); -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt mouse, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), b=" << (int)buttons; -#endif - } - - if (wheelDelta) { - // Screen only supports a single wheel, so we will assume Vertical orientation for - // now since that is pretty much standard. - QWindowSystemInterface::handleWheelEvent(w, localPoint, globalPoint, wheelDelta, Qt::Vertical); -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt wheel, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), d=" << (int)wheelDelta; -#endif - } - } - - mLastGlobalMousePoint = globalPoint; - mLastLocalMousePoint = localPoint; - mLastButtonState = buttons; -} - -void QBBEventThread::handleTouchEvent(screen_event_t event, int qnxType) -{ - // get display coordinates of touch - errno = 0; - int pos[2]; - int result = screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos); - if (result) { - qFatal("QBB: failed to query event position, errno=%d", errno); - } - - // get window coordinates of touch - errno = 0; - int windowPos[2]; - result = screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos); - if (result) { - qFatal("QBB: failed to query event window position, errno=%d", errno); - } - - // determine which finger touched - errno = 0; - int touchId; - result = screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touchId); - if (result) { - qFatal("QBB: failed to query event touch id, errno=%d", errno); - } - - // determine which window was touched - errno = 0; - void *qnxWindow; - result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &qnxWindow); - if (result) { - qFatal("QBB: failed to query event window, errno=%d", errno); - } - - // check if finger is valid - if (touchId < MAX_TOUCH_POINTS) { - - // map window to top-level widget - QWidget* w = QWidget::find( (WId)qnxWindow ); - - // Generate enter and leave events as needed. - if (qnxWindow != mLastMouseWindow) { - QWidget* wOld = QWidget::find( (WId)mLastMouseWindow ); - - if (wOld) { - QWindowSystemInterface::handleLeaveEvent(wOld); - #if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt leave, w=" << wOld; - #endif - } - - if (w) { - QWindowSystemInterface::handleEnterEvent(w); - #if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt enter, w=" << w; - #endif - } - } - mLastMouseWindow = qnxWindow; - - if (w) { - // convert primary touch to mouse event - if (touchId == 0) { - - // convert point to local coordinates - QPoint globalPoint(pos[0], pos[1]); - QPoint localPoint(windowPos[0], windowPos[1]); - - // map touch state to button state - Qt::MouseButtons buttons = (qnxType == SCREEN_EVENT_MTOUCH_RELEASE) ? Qt::NoButton : Qt::LeftButton; - - // inject event into Qt - QWindowSystemInterface::handleMouseEvent(w, localPoint, globalPoint, buttons); -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt mouse, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), b=" << buttons; -#endif - } - - // get size of screen which contains window - QPlatformScreen* platformScreen = QPlatformScreen::platformScreenForWidget(w); - QSize screenSize = platformScreen->physicalSize(); - - // update cached position of current touch point - mTouchPoints[touchId].normalPosition = QPointF( ((qreal)pos[0]) / screenSize.width(), ((qreal)pos[1]) / screenSize.height() ); - mTouchPoints[touchId].area = QRectF( pos[0], pos[1], 0.0, 0.0 ); - - // determine event type and update state of current touch point - QEvent::Type type = QEvent::None; - switch (qnxType) { - case SCREEN_EVENT_MTOUCH_TOUCH: - mTouchPoints[touchId].state = Qt::TouchPointPressed; - type = QEvent::TouchBegin; - break; - case SCREEN_EVENT_MTOUCH_MOVE: - mTouchPoints[touchId].state = Qt::TouchPointMoved; - type = QEvent::TouchUpdate; - break; - case SCREEN_EVENT_MTOUCH_RELEASE: - mTouchPoints[touchId].state = Qt::TouchPointReleased; - type = QEvent::TouchEnd; - break; - } - - // build list of active touch points - QList pointList; - for (int i = 0; i < MAX_TOUCH_POINTS; i++) { - if (i == touchId) { - // current touch point is always active - pointList.append(mTouchPoints[i]); - } else if (mTouchPoints[i].state != Qt::TouchPointReleased) { - // finger is down but did not move - mTouchPoints[i].state = Qt::TouchPointStationary; - pointList.append(mTouchPoints[i]); - } - } - - // inject event into Qt - QWindowSystemInterface::handleTouchEvent(w, type, QTouchEvent::TouchScreen, pointList); -#if defined(QBBEVENTTHREAD_DEBUG) - qDebug() << "QBB: Qt touch, w=" << w << ", p=(" << pos[0] << "," << pos[1] << "), t=" << type; -#endif - } - } -} - -void QBBEventThread::handleCloseEvent(screen_event_t event) -{ - // Query the window that was closed - void *qnxWindow; - int result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &qnxWindow); - if (result != 0) { - qFatal("QBB: failed to query event window, errno=%d", errno); - } - - // map window to top-level widget - QWidget* w = QWidget::find( (WId)qnxWindow ); - if (w != NULL) { - QWindowSystemInterface::handleCloseEvent(w); - } -} - +QT_END_NAMESPACE diff --git a/src/plugins/platforms/blackberry/qbbeventthread.h b/src/plugins/platforms/blackberry/qbbeventthread.h index a4557fe..23bb249 100644 --- a/src/plugins/platforms/blackberry/qbbeventthread.h +++ b/src/plugins/platforms/blackberry/qbbeventthread.h @@ -40,21 +40,18 @@ #ifndef QBBEVENTTHREAD_H #define QBBEVENTTHREAD_H -#include -#include +#include "qbbscreeneventhandler.h" + #include #include QT_BEGIN_NAMESPACE -// an arbitrary number -#define MAX_TOUCH_POINTS 10 - class QBBEventThread : public QThread { public: - QBBEventThread(screen_context_t context, QPlatformScreen& screen); + explicit QBBEventThread(screen_context_t context); virtual ~QBBEventThread(); static void injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap); @@ -65,21 +62,10 @@ protected: private: screen_context_t mContext; - QPlatformScreen& mScreen; bool mQuit; - QPoint mLastGlobalMousePoint; - QPoint mLastLocalMousePoint; - Qt::MouseButtons mLastButtonState; - void* mLastMouseWindow; - - QWindowSystemInterface::TouchPoint mTouchPoints[MAX_TOUCH_POINTS]; + QBBScreenEventHandler mEventHandler; void shutdown(); - void dispatchEvent(screen_event_t event); - void handleKeyboardEvent(screen_event_t event); - void handlePointerEvent(screen_event_t event); - void handleTouchEvent(screen_event_t event, int type); - void handleCloseEvent(screen_event_t event); }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/blackberry/qbbintegration.cpp b/src/plugins/platforms/blackberry/qbbintegration.cpp index f68f92e..8d79713 100644 --- a/src/plugins/platforms/blackberry/qbbintegration.cpp +++ b/src/plugins/platforms/blackberry/qbbintegration.cpp @@ -95,7 +95,7 @@ QBBIntegration::QBBIntegration() : QBBScreen::createDisplays(mContext); // create/start event thread - mEventThread = new QBBEventThread(mContext, *QBBScreen::primaryDisplay()); + mEventThread = new QBBEventThread(mContext); mEventThread->start(); // Create/start navigator event handler diff --git a/src/plugins/platforms/blackberry/qbbscreeneventhandler.cpp b/src/plugins/platforms/blackberry/qbbscreeneventhandler.cpp new file mode 100644 index 0000000..567d572 --- /dev/null +++ b/src/plugins/platforms/blackberry/qbbscreeneventhandler.cpp @@ -0,0 +1,528 @@ +/**************************************************************************** +** +** Copyright (C) 2011 - 2012 Research In Motion +** +** Contact: Research In Motion +** Contact: Klarälvdalens Datakonsult AB +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qbbscreeneventhandler.h" + +#include "qbbinputcontext.h" +#include "qbbkeytranslator.h" + +#include +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +QBBScreenEventHandler::QBBScreenEventHandler() + : mLastButtonState(Qt::NoButton) + , mLastMouseWindow(0) +{ + // initialize array of touch points + for (int i = 0; i < MAX_TOUCH_POINTS; i++) { + + // map array index to id + mTouchPoints[i].id = i; + + // first finger is primary + mTouchPoints[i].isPrimary = (i == 0); + + // pressure is not supported - use default + mTouchPoints[i].pressure = 1.0; + + // nothing touching + mTouchPoints[i].state = Qt::TouchPointReleased; + } +} + +bool QBBScreenEventHandler::handleEvent(screen_event_t event) +{ + // get the event type + errno = 0; + int qnxType; + int result = screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType); + if (result) + qFatal("QBB: failed to query event type, errno=%d", errno); + + return handleEvent(event, qnxType); +} + + +bool QBBScreenEventHandler::handleEvent(screen_event_t event, int qnxType) +{ + switch (qnxType) { + case SCREEN_EVENT_MTOUCH_TOUCH: + case SCREEN_EVENT_MTOUCH_MOVE: + case SCREEN_EVENT_MTOUCH_RELEASE: + handleTouchEvent(event, qnxType); + break; + + case SCREEN_EVENT_KEYBOARD: + handleKeyboardEvent(event); + break; + + case SCREEN_EVENT_POINTER: + handlePointerEvent(event); + break; + + case SCREEN_EVENT_CLOSE: + handleCloseEvent(event); + break; + + default: + // event ignored +#if defined(QBBEVENTTHREAD_DEBUG) + qDebug() << "QBB: QNX unknown event"; +#endif + return false; + } + + return true; +} + +void QBBScreenEventHandler::handleKeyboardEvent(screen_event_t event) +{ + // get flags of key event + errno = 0; + int flags; + int result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_FLAGS, &flags); + if (result) { + qFatal("QBB: failed to query event flags, errno=%d", errno); + } + + // get key code + errno = 0; + int sym; + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SYM, &sym); + if (result) { + qFatal("QBB: failed to query event sym, errno=%d", errno); + } + + int modifiers; + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_MODIFIERS, &modifiers); + if (result) { + qFatal("QBB: failed to query event modifiers, errno=%d", errno); + } + + int scan; + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SCAN, &scan); + if (result) { + qFatal("QBB: failed to query event modifiers, errno=%d", errno); + } + + int cap; + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &cap); + if (result) { + qFatal("QBB: failed to query event cap, errno=%d", errno); + } + + // Let the input context have a stab at it first. + QWidget *focusWidget = QApplication::focusWidget(); + if (focusWidget) { + QInputContext* inputContext = focusWidget->inputContext(); + if (inputContext) { + QBBInputContext *qbbInputContext = dynamic_cast(inputContext); + + if (qbbInputContext && qbbInputContext->handleKeyboardEvent(flags, sym, modifiers, scan, cap)) + return; + } + } + + injectKeyboardEvent(flags, sym, modifiers, scan, cap); +} + +void QBBScreenEventHandler::injectKeyboardEvent(int flags, int sym, int modifiers, int scan, int cap) +{ + Q_UNUSED(scan); + + Qt::KeyboardModifiers qtMod = Qt::NoModifier; + if (modifiers & KEYMOD_SHIFT) + qtMod |= Qt::ShiftModifier; + if (modifiers & KEYMOD_CTRL) + qtMod |= Qt::ControlModifier; + if (modifiers & KEYMOD_ALT) + qtMod |= Qt::AltModifier; + + // determine event type + QEvent::Type type = (flags & KEY_DOWN) ? QEvent::KeyPress : QEvent::KeyRelease; + + // Check if the key cap is valid + if (flags & KEY_CAP_VALID) { + Qt::Key key; + QString keyStr; + + if (cap >= 0x20 && cap <= 0x0ff) { + key = Qt::Key(std::toupper(cap)); // Qt expects the CAP to be upper case. + + if ( qtMod & Qt::ControlModifier ) { + keyStr = QChar((int)(key & 0x3f)); + } else { + if (flags & KEY_SYM_VALID) { + keyStr = QChar(sym); + } + } + } else if ((cap > 0x0ff && cap < UNICODE_PRIVATE_USE_AREA_FIRST) || cap > UNICODE_PRIVATE_USE_AREA_LAST) { + key = (Qt::Key)cap; + keyStr = QChar(sym); + } else { + if (isKeypadKey(cap)) + qtMod |= Qt::KeypadModifier; // Is this right? + key = keyTranslator(cap); + } + + QWindowSystemInterface::handleExtendedKeyEvent(QApplication::activeWindow(), type, key, qtMod, + scan, sym, modifiers, keyStr); +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt key t=" << type << ", k=" << key << ", s=" << keyStr; +#endif + } +} + +void QBBScreenEventHandler::injectPointerMoveEvent(int x, int y) +{ +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "Injecting mouse event..." << x << y; +#endif + + QWidget *w = qApp->topLevelAt(x, y); + void *qnxWindow = w ? w->platformWindow() : 0; + + // Generate enter and leave events as needed. + if (qnxWindow != mLastMouseWindow) { + QWidget* wOld = QWidget::find( (WId)mLastMouseWindow ); + + if (wOld) { + QWindowSystemInterface::handleLeaveEvent(wOld); +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt leave, w=" << wOld; +#endif + } + + if (w) { + QWindowSystemInterface::handleEnterEvent(w); +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt enter, w=" << w; +#endif + } + } + + mLastMouseWindow = qnxWindow; + + // convert point to local coordinates + QPoint globalPoint(x, y); + QPoint localPoint(x, y); + + if (w) + localPoint = QPoint(x - w->x(), y - w->y()); + + // Convert buttons. + Qt::MouseButtons buttons = mLastButtonState; + + if (w) { + // Inject mouse event into Qt only if something has changed. + if (mLastGlobalMousePoint != globalPoint || + mLastLocalMousePoint != localPoint || + mLastButtonState != buttons) { + QWindowSystemInterface::handleMouseEvent(w, localPoint, globalPoint, buttons); +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt mouse, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), b=" << (int)buttons; +#endif + } + } + + mLastGlobalMousePoint = globalPoint; + mLastLocalMousePoint = localPoint; + mLastButtonState = buttons; +} + +void QBBScreenEventHandler::handlePointerEvent(screen_event_t event) +{ + errno = 0; + + // Query the window that was clicked + void *qnxWindow; + int result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &qnxWindow); + if (result) { + qFatal("QBB: failed to query event window, errno=%d", errno); + } + + // Query the button states + int buttonState = 0; + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttonState); + if (result) { + qFatal("QBB: failed to query event button state, errno=%d", errno); + } + + // Query the window position + int windowPos[2]; + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos); + if (result) { + qFatal("QBB: failed to query event window position, errno=%d", errno); + } + + // Query the screen position + int pos[2]; + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos); + if (result) { + qFatal("QBB: failed to query event position, errno=%d", errno); + } + + // Query the wheel delta + int wheelDelta = 0; + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheelDelta); + if (result) { + qFatal("QBB: failed to query event wheel delta, errno=%d", errno); + } + + // map window to top-level widget + QWidget* w = QWidget::find( (WId)qnxWindow ); + + // Generate enter and leave events as needed. + if (qnxWindow != mLastMouseWindow) { + QWidget* wOld = QWidget::find( (WId)mLastMouseWindow ); + + if (wOld) { + QWindowSystemInterface::handleLeaveEvent(wOld); +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt leave, w=" << wOld; +#endif + } + + if (w) { + QWindowSystemInterface::handleEnterEvent(w); +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt enter, w=" << w; +#endif + } + } + mLastMouseWindow = qnxWindow; + + // Apply scaling to wheel delta and invert value for Qt. We'll probably want to scale + // this via a system preference at some point. But for now this is a sane value and makes + // the wheel usable. + wheelDelta *= -10; + + // convert point to local coordinates + QPoint globalPoint(pos[0], pos[1]); + QPoint localPoint(windowPos[0], windowPos[1]); + + // Convert buttons. + // Some QNX header files invert 'Right Button versus "Left Button' ('Right' == 0x01). But they also offer a 'Button Swap' bit, + // so we may receive events as shown. (If this is wrong, the fix is easy.) + // QNX Button mask is 8 buttons wide, with a maximum value of 0x80. + Qt::MouseButtons buttons = Qt::NoButton; + if (buttonState & 0x01) + buttons |= Qt::LeftButton; + if (buttonState & 0x02) + buttons |= Qt::MidButton; + if (buttonState & 0x04) + buttons |= Qt::RightButton; + if (buttonState & 0x08) + buttons |= Qt::XButton1; + if (buttonState & 0x10) + buttons |= Qt::XButton2; + + if (w) { + // Inject mouse event into Qt only if something has changed. + if (mLastGlobalMousePoint != globalPoint || + mLastLocalMousePoint != localPoint || + mLastButtonState != buttons) { + QWindowSystemInterface::handleMouseEvent(w, localPoint, globalPoint, buttons); +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt mouse, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), b=" << (int)buttons; +#endif + } + + if (wheelDelta) { + // Screen only supports a single wheel, so we will assume Vertical orientation for + // now since that is pretty much standard. + QWindowSystemInterface::handleWheelEvent(w, localPoint, globalPoint, wheelDelta, Qt::Vertical); +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt wheel, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), d=" << (int)wheelDelta; +#endif + } + } + + mLastGlobalMousePoint = globalPoint; + mLastLocalMousePoint = localPoint; + mLastButtonState = buttons; +} + +void QBBScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType) +{ + // get display coordinates of touch + errno = 0; + int pos[2]; + int result = screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos); + if (result) { + qFatal("QBB: failed to query event position, errno=%d", errno); + } + + // get window coordinates of touch + errno = 0; + int windowPos[2]; + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos); + if (result) { + qFatal("QBB: failed to query event window position, errno=%d", errno); + } + + // determine which finger touched + errno = 0; + int touchId; + result = screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touchId); + if (result) { + qFatal("QBB: failed to query event touch id, errno=%d", errno); + } + + // determine which window was touched + errno = 0; + void *qnxWindow; + result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &qnxWindow); + if (result) { + qFatal("QBB: failed to query event window, errno=%d", errno); + } + + // check if finger is valid + if (touchId < MAX_TOUCH_POINTS) { + + // map window to top-level widget + QWidget* w = QWidget::find( (WId)qnxWindow ); + + // Generate enter and leave events as needed. + if (qnxWindow != mLastMouseWindow) { + QWidget* wOld = QWidget::find( (WId)mLastMouseWindow ); + + if (wOld) { + QWindowSystemInterface::handleLeaveEvent(wOld); + #if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt leave, w=" << wOld; + #endif + } + + if (w) { + QWindowSystemInterface::handleEnterEvent(w); + #if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt enter, w=" << w; + #endif + } + } + mLastMouseWindow = qnxWindow; + + if (w) { + // convert primary touch to mouse event + if (touchId == 0) { + + // convert point to local coordinates + QPoint globalPoint(pos[0], pos[1]); + QPoint localPoint(windowPos[0], windowPos[1]); + + // map touch state to button state + Qt::MouseButtons buttons = (qnxType == SCREEN_EVENT_MTOUCH_RELEASE) ? Qt::NoButton : Qt::LeftButton; + + // inject event into Qt + QWindowSystemInterface::handleMouseEvent(w, localPoint, globalPoint, buttons); +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt mouse, w=" << w << ", (" << localPoint.x() << "," << localPoint.y() << "), b=" << buttons; +#endif + } + + // get size of screen which contains window + QPlatformScreen* platformScreen = QPlatformScreen::platformScreenForWidget(w); + QSize screenSize = platformScreen->physicalSize(); + + // update cached position of current touch point + mTouchPoints[touchId].normalPosition = QPointF( ((qreal)pos[0]) / screenSize.width(), ((qreal)pos[1]) / screenSize.height() ); + mTouchPoints[touchId].area = QRectF( pos[0], pos[1], 0.0, 0.0 ); + + // determine event type and update state of current touch point + QEvent::Type type = QEvent::None; + switch (qnxType) { + case SCREEN_EVENT_MTOUCH_TOUCH: + mTouchPoints[touchId].state = Qt::TouchPointPressed; + type = QEvent::TouchBegin; + break; + case SCREEN_EVENT_MTOUCH_MOVE: + mTouchPoints[touchId].state = Qt::TouchPointMoved; + type = QEvent::TouchUpdate; + break; + case SCREEN_EVENT_MTOUCH_RELEASE: + mTouchPoints[touchId].state = Qt::TouchPointReleased; + type = QEvent::TouchEnd; + break; + } + + // build list of active touch points + QList pointList; + for (int i = 0; i < MAX_TOUCH_POINTS; i++) { + if (i == touchId) { + // current touch point is always active + pointList.append(mTouchPoints[i]); + } else if (mTouchPoints[i].state != Qt::TouchPointReleased) { + // finger is down but did not move + mTouchPoints[i].state = Qt::TouchPointStationary; + pointList.append(mTouchPoints[i]); + } + } + + // inject event into Qt + QWindowSystemInterface::handleTouchEvent(w, type, QTouchEvent::TouchScreen, pointList); +#if defined(QBBScreenEventHandler_DEBUG) + qDebug() << "QBB: Qt touch, w=" << w << ", p=(" << pos[0] << "," << pos[1] << "), t=" << type; +#endif + } + } +} + +void QBBScreenEventHandler::handleCloseEvent(screen_event_t event) +{ + // Query the window that was closed + void *qnxWindow; + int result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &qnxWindow); + if (result != 0) { + qFatal("QBB: failed to query event window, errno=%d", errno); + } + + // map window to top-level widget + QWidget* w = QWidget::find( (WId)qnxWindow ); + if (w != NULL) { + QWindowSystemInterface::handleCloseEvent(w); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/blackberry/qbbscreeneventhandler.h b/src/plugins/platforms/blackberry/qbbscreeneventhandler.h new file mode 100644 index 0000000..2e5851e --- /dev/null +++ b/src/plugins/platforms/blackberry/qbbscreeneventhandler.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2011 - 2012 Research In Motion +** +** Contact: Research In Motion +** Contact: Klarälvdalens Datakonsult AB +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** 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. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QBBSCREENEVENTHANDLER_H +#define QBBSCREENEVENTHANDLER_H + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QBBScreenEventHandler +{ +public: + QBBScreenEventHandler(); + + static void injectKeyboardEvent(int flags, int sym, int mod, int scan, int cap); + void injectPointerMoveEvent(int x, int y); + + bool handleEvent(screen_event_t event); + bool handleEvent(screen_event_t event, int qnxType); + +private: + void handleKeyboardEvent(screen_event_t event); + void handlePointerEvent(screen_event_t event); + void handleTouchEvent(screen_event_t event, int type); + void handleCloseEvent(screen_event_t event); + +private: + enum { + MAX_TOUCH_POINTS = 10 + }; + + QPoint mLastGlobalMousePoint; + QPoint mLastLocalMousePoint; + Qt::MouseButtons mLastButtonState; + void* mLastMouseWindow; + + QWindowSystemInterface::TouchPoint mTouchPoints[MAX_TOUCH_POINTS]; +}; + +QT_END_NAMESPACE + +#endif // QBBSCREENEVENTHANDLER_H -- cgit v0.12