summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/qnx
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/qnx')
-rw-r--r--src/plugins/platforms/qnx/main.cpp7
-rw-r--r--src/plugins/platforms/qnx/qblackberrytheme.cpp (renamed from src/plugins/platforms/qnx/qqnxtheme.cpp)40
-rw-r--r--src/plugins/platforms/qnx/qblackberrytheme.h (renamed from src/plugins/platforms/qnx/qqnxtheme.h)17
-rw-r--r--src/plugins/platforms/qnx/qnx.pro18
-rw-r--r--src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp46
-rw-r--r--src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h24
-rw-r--r--src/plugins/platforms/qnx/qqnxbuffer.cpp28
-rw-r--r--src/plugins/platforms/qnx/qqnxeglwindow.cpp28
-rw-r--r--src/plugins/platforms/qnx/qqnxeglwindow.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxfilepicker.cpp46
-rw-r--r--src/plugins/platforms/qnx/qqnxfilepicker.h1
-rw-r--r--src/plugins/platforms/qnx/qqnxglcontext.cpp24
-rw-r--r--src/plugins/platforms/qnx/qqnxglcontext.h4
-rw-r--r--src/plugins/platforms/qnx/qqnxglobal.cpp63
-rw-r--r--src/plugins/platforms/qnx/qqnxglobal.h59
-rw-r--r--src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp1601
-rw-r--r--src/plugins/platforms/qnx/qqnxinputcontext_imf.h76
-rw-r--r--src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp9
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp109
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.h12
-rw-r--r--src/plugins/platforms/qnx/qqnxlgmon.cpp49
-rw-r--r--src/plugins/platforms/qnx/qqnxlgmon.h80
-rw-r--r--src/plugins/platforms/qnx/qqnxnativeinterface.cpp41
-rw-r--r--src/plugins/platforms/qnx/qqnxnativeinterface.h9
-rw-r--r--src/plugins/platforms/qnx/qqnxnavigatoreventhandler.cpp12
-rw-r--r--src/plugins/platforms/qnx/qqnxnavigatoreventhandler.h1
-rw-r--r--src/plugins/platforms/qnx/qqnxrasterwindow.cpp55
-rw-r--r--src/plugins/platforms/qnx/qqnxrasterwindow.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.cpp29
-rw-r--r--src/plugins/platforms/qnx/qqnxscreen.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventfilter.h58
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp183
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventhandler.h11
-rw-r--r--src/plugins/platforms/qnx/qqnxscreeneventthread.cpp50
-rw-r--r--src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp91
-rw-r--r--src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.h6
-rw-r--r--src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp192
-rw-r--r--src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.h17
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp445
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h18
40 files changed, 2041 insertions, 1524 deletions
diff --git a/src/plugins/platforms/qnx/main.cpp b/src/plugins/platforms/qnx/main.cpp
index 50779d3e12..01e71b3810 100644
--- a/src/plugins/platforms/qnx/main.cpp
+++ b/src/plugins/platforms/qnx/main.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2011 - 2014 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -41,13 +41,16 @@
#include "main.h"
#include "qqnxintegration.h"
+#include "qqnxlgmon.h"
QT_BEGIN_NAMESPACE
QPlatformIntegration *QQnxIntegrationPlugin::create(const QString& system, const QStringList& paramList)
{
- if (!system.compare(QLatin1String("qnx"), Qt::CaseInsensitive))
+ if (!system.compare(QLatin1String("qnx"), Qt::CaseInsensitive)) {
+ qqnxLgmonInit();
return new QQnxIntegration(paramList);
+ }
return 0;
}
diff --git a/src/plugins/platforms/qnx/qqnxtheme.cpp b/src/plugins/platforms/qnx/qblackberrytheme.cpp
index 37c1079441..46ab4d7033 100644
--- a/src/plugins/platforms/qnx/qqnxtheme.cpp
+++ b/src/plugins/platforms/qnx/qblackberrytheme.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#include "qqnxtheme.h"
+#include "qblackberrytheme.h"
#include "qqnxfiledialoghelper.h"
#include "qqnxsystemsettings.h"
@@ -47,16 +47,35 @@
QT_BEGIN_NAMESPACE
-QQnxTheme::QQnxTheme(const QQnxIntegration *integration) : m_integration(integration)
+QBlackberryTheme::QBlackberryTheme(const QQnxIntegration *integration) : m_integration(integration)
{
+ // Set the dark theme as default palette
+ QColor color = QColor(211, 211, 211);
+ m_defaultPalette.setBrush(QPalette::ButtonText, color);
+ m_defaultPalette.setBrush(QPalette::WindowText, color);
+ m_defaultPalette.setBrush(QPalette::Text, color);
+
+ color.setAlpha(179);
+ m_defaultPalette.setBrush(QPalette::Disabled, QPalette::ButtonText, color);
+ m_defaultPalette.setBrush(QPalette::Disabled, QPalette::WindowText, color);
+ m_defaultPalette.setBrush(QPalette::Disabled, QPalette::Text, color);
+
+ color.setRgb(18, 18, 18);
+ m_defaultPalette.setColor(QPalette::Window, color);
+ m_defaultPalette.setColor(QPalette::Base, color);
+ m_defaultPalette.setColor(QPalette::AlternateBase, QColor(50, 50, 50));
+ m_defaultPalette.setColor(QPalette::Button, color);
+
+ m_defaultPalette.setBrush(QPalette::Highlight, QColor(0, 168, 223));
+ m_defaultPalette.setBrush(QPalette::HighlightedText, QColor(250, 250,250));
}
-QQnxTheme::~QQnxTheme()
+QBlackberryTheme::~QBlackberryTheme()
{
qDeleteAll(m_fonts);
}
-bool QQnxTheme::usePlatformNativeDialog(DialogType type) const
+bool QBlackberryTheme::usePlatformNativeDialog(DialogType type) const
{
if (type == QPlatformTheme::FileDialog)
return true;
@@ -71,7 +90,7 @@ bool QQnxTheme::usePlatformNativeDialog(DialogType type) const
return false;
}
-QPlatformDialogHelper *QQnxTheme::createPlatformDialogHelper(DialogType type) const
+QPlatformDialogHelper *QBlackberryTheme::createPlatformDialogHelper(DialogType type) const
{
switch (type) {
case QPlatformTheme::FileDialog:
@@ -87,7 +106,7 @@ QPlatformDialogHelper *QQnxTheme::createPlatformDialogHelper(DialogType type) co
}
}
-const QFont *QQnxTheme::font(Font type) const
+const QFont *QBlackberryTheme::font(Font type) const
{
QPlatformFontDatabase *fontDatabase = m_integration->fontDatabase();
@@ -96,4 +115,13 @@ const QFont *QQnxTheme::font(Font type) const
return m_fonts.value(type, 0);
}
+const QPalette *QBlackberryTheme::palette(Palette type) const
+{
+ // Return the default palette
+ if (type == SystemPalette)
+ return &m_defaultPalette;
+
+ return QPlatformTheme::palette(type);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxtheme.h b/src/plugins/platforms/qnx/qblackberrytheme.h
index 17b2eab142..29fa0b8f61 100644
--- a/src/plugins/platforms/qnx/qqnxtheme.h
+++ b/src/plugins/platforms/qnx/qblackberrytheme.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QQNXTHEME_H
-#define QQNXTHEME_H
+#ifndef QBLACKBERRYTHEME_H
+#define QBLACKBERRYTHEME_H
#include <qpa/qplatformtheme.h>
@@ -49,15 +49,17 @@
#include <QtCore/qhash.h>
#include <QtCore/qstring.h>
+#include <QtGui/QPalette>
+
QT_BEGIN_NAMESPACE
class QQnxIntegration;
-class QQnxTheme : public QPlatformTheme
+class QBlackberryTheme : public QPlatformTheme
{
public:
- explicit QQnxTheme(const QQnxIntegration *);
- ~QQnxTheme();
+ explicit QBlackberryTheme(const QQnxIntegration *);
+ ~QBlackberryTheme();
static QString name() { return QStringLiteral("blackberry"); }
@@ -66,11 +68,14 @@ public:
const QFont *font(Font type = SystemFont) const;
+ const QPalette *palette(Palette type = SystemPalette) const;
+
private:
mutable QHash<QPlatformTheme::Font, QFont*> m_fonts;
const QQnxIntegration *m_integration;
+ QPalette m_defaultPalette;
};
QT_END_NAMESPACE
-#endif // QQNXTHEME_H
+#endif // QBLACKBERRYTHEME_H
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index bc7219de5c..04c6087cd1 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -45,7 +45,8 @@ SOURCES = main.cpp \
qqnxabstractvirtualkeyboard.cpp \
qqnxservices.cpp \
qqnxcursor.cpp \
- qqnxrasterwindow.cpp
+ qqnxrasterwindow.cpp \
+ qqnxglobal.cpp
HEADERS = main.h \
qqnxbuffer.h \
@@ -62,7 +63,10 @@ HEADERS = main.h \
qqnxabstractcover.h \
qqnxservices.h \
qqnxcursor.h \
- qqnxrasterwindow.h
+ qqnxrasterwindow.h \
+ qqnxscreeneventfilter.h \
+ qqnxglobal.h \
+ qqnxlgmon.h
CONFIG(qqnx_screeneventthread) {
DEFINES += QQNX_SCREENEVENTTHREAD
@@ -87,14 +91,14 @@ CONFIG(blackberry) {
qqnxeventdispatcher_blackberry.cpp \
qqnxbpseventfilter.cpp \
qqnxvirtualkeyboardbps.cpp \
- qqnxtheme.cpp \
+ qblackberrytheme.cpp \
qqnxsystemsettings.cpp
HEADERS += qqnxnavigatorbps.h \
qqnxeventdispatcher_blackberry.h \
qqnxbpseventfilter.h \
qqnxvirtualkeyboardbps.h \
- qqnxtheme.h \
+ qblackberrytheme.h \
qqnxsystemsettings.h \
qqnxfiledialoghelper.h
@@ -142,6 +146,12 @@ CONFIG(qqnx_pps) {
}
}
+lgmon {
+ DEFINES += QQNX_LGMON
+ SOURCES += qqnxlgmon.cpp
+ LIBS += -llgmon
+}
+
OTHER_FILES += qnx.json
QMAKE_CXXFLAGS += -I./private
diff --git a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp
index a42f73415e..800cb96bdf 100644
--- a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp
+++ b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -49,6 +49,7 @@ QQnxAbstractVirtualKeyboard::QQnxAbstractVirtualKeyboard(QObject *parent)
, m_visible(false)
, m_locale(QLocale::system())
, m_keyboardMode(Default)
+ , m_enterKeyType(DefaultReturn)
{
}
@@ -59,26 +60,35 @@ void QQnxAbstractVirtualKeyboard::setKeyboardMode(KeyboardMode mode)
m_keyboardMode = mode;
- applyKeyboardMode(mode);
+ if (m_visible)
+ applyKeyboardOptions();
}
-void QQnxAbstractVirtualKeyboard::setInputHintsFromObject(QObject *focusObject)
+void QQnxAbstractVirtualKeyboard::setEnterKeyType(EnterKeyType type)
{
- if (focusObject) {
- const Qt::InputMethodHints hints = static_cast<Qt::InputMethodHints>(
- focusObject->property("inputMethodHints").toInt());
- if (hints & Qt::ImhEmailCharactersOnly) {
- setKeyboardMode(QQnxAbstractVirtualKeyboard::Email);
- } else if (hints & Qt::ImhDialableCharactersOnly) {
- setKeyboardMode(QQnxAbstractVirtualKeyboard::Phone);
- } else if (hints & Qt::ImhUrlCharactersOnly) {
- setKeyboardMode(QQnxAbstractVirtualKeyboard::Web);
- } else if (hints & Qt::ImhFormattedNumbersOnly || hints & Qt::ImhDigitsOnly ||
- hints & Qt::ImhDate || hints & Qt::ImhTime) {
- setKeyboardMode(QQnxAbstractVirtualKeyboard::NumPunc);
- } else {
- setKeyboardMode(QQnxAbstractVirtualKeyboard::Default);
- }
+ if (type == m_enterKeyType)
+ return;
+
+ m_enterKeyType = type;
+
+ if (m_visible)
+ applyKeyboardOptions();
+}
+
+void QQnxAbstractVirtualKeyboard::setInputHints(int inputHints)
+{
+ if (inputHints & Qt::ImhEmailCharactersOnly) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::Email);
+ } else if (inputHints & Qt::ImhDialableCharactersOnly) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::Phone);
+ } else if (inputHints & Qt::ImhUrlCharactersOnly) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::Url);
+ } else if (inputHints & Qt::ImhFormattedNumbersOnly || inputHints & Qt::ImhDigitsOnly) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::Number);
+ } else if (inputHints & Qt::ImhDate || inputHints & Qt::ImhTime) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::NumPunc); // Use NumPunc so that : is available.
+ } else if (inputHints & Qt::ImhHiddenText) {
+ setKeyboardMode(QQnxAbstractVirtualKeyboard::Password);
} else {
setKeyboardMode(QQnxAbstractVirtualKeyboard::Default);
}
diff --git a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h
index 9b911e1dec..bff8c56835 100644
--- a/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h
+++ b/src/plugins/platforms/qnx/qqnxabstractvirtualkeyboard.h
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -51,18 +51,20 @@ class QQnxAbstractVirtualKeyboard : public QObject
{
Q_OBJECT
public:
- // NOTE: Not all the following keyboard modes are currently used.
+ // Keyboard Types currently supported.
// Default - Regular Keyboard
// Url/Email - Enhanced keys for each types.
// Web - Regular keyboard with two blank keys, currently unused.
// NumPunc - Numbers & Punctionation, alternate to Symbol
+ // Number - Number pad
// Symbol - All symbols, alternate to NumPunc, currently unused.
- // Phone - Phone enhanced keyboard - currently unused as no alternate keyboard available to access a-zA-Z
- // Pin - Keyboard for entering Pins (Hex values) currently unused.
+ // Phone - Phone enhanced keyboard
+ // Pin - Keyboard for entering Pins (Hex values).
+ // Password - Keyboard with lots of extra characters for password input.
+ // Alphanumeric - Similar to password without any of the security implications.
//
- // SPECIAL NOTE: Usage of NumPunc may have to be removed, ABC button is non-functional.
- //
- enum KeyboardMode { Default, Url, Email, Web, NumPunc, Symbol, Phone, Pin };
+ enum KeyboardMode { Default, Url, Email, Web, NumPunc, Number, Symbol, Phone, Pin, Password, Alphanumeric };
+ enum EnterKeyType { DefaultReturn, Connect, Done, Go, Join, Next, Search, Send, Submit };
explicit QQnxAbstractVirtualKeyboard(QObject *parent = 0);
@@ -74,8 +76,11 @@ public:
QLocale locale() const { return m_locale; }
void setKeyboardMode(KeyboardMode mode);
- void setInputHintsFromObject(QObject *focusObject);
+ void setEnterKeyType(EnterKeyType type);
+
+ void setInputHints(int inputHints);
KeyboardMode keyboardMode() const { return m_keyboardMode; }
+ EnterKeyType enterKeyType() const { return m_enterKeyType; }
Q_SIGNALS:
void heightChanged(int height);
@@ -83,7 +88,7 @@ Q_SIGNALS:
void localeChanged(const QLocale &locale);
protected:
- virtual void applyKeyboardMode(KeyboardMode mode) = 0;
+ virtual void applyKeyboardOptions() = 0;
void setHeight(int height);
void setVisible(bool visible);
@@ -94,6 +99,7 @@ private:
bool m_visible;
QLocale m_locale;
KeyboardMode m_keyboardMode;
+ EnterKeyType m_enterKeyType;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxbuffer.cpp b/src/plugins/platforms/qnx/qqnxbuffer.cpp
index abb8a07026..e9afd5232b 100644
--- a/src/plugins/platforms/qnx/qqnxbuffer.cpp
+++ b/src/plugins/platforms/qnx/qqnxbuffer.cpp
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#include "qqnxglobal.h"
+
#include "qqnxbuffer.h"
#include <QtCore/QDebug>
@@ -66,34 +68,30 @@ QQnxBuffer::QQnxBuffer(screen_buffer_t buffer)
qBufferDebug() << Q_FUNC_INFO << "normal";
// Get size of buffer
- errno = 0;
int size[2];
- int result = screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_BUFFER_SIZE, size);
- if (result != 0)
- qFatal("QQNX: failed to query buffer size, errno=%d", errno);
+ Q_SCREEN_CRITICALERROR(screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_BUFFER_SIZE, size),
+ "Failed to query buffer size");
// Get stride of buffer
- errno = 0;
int stride;
- result = screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE, &stride);
- if (result != 0)
- qFatal("QQNX: failed to query buffer stride, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_STRIDE, &stride),
+ "Failed to query buffer stride");
// Get access to buffer's data
errno = 0;
uchar *dataPtr = 0;
- result = screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER, (void **)&dataPtr);
- if (result != 0)
- qFatal("QQNX: failed to query buffer pointer, errno=%d", errno);
+ Q_SCREEN_CRITICALERROR(
+ screen_get_buffer_property_pv(buffer, SCREEN_PROPERTY_POINTER, (void **)&dataPtr),
+ "Failed to query buffer pointer");
+
if (dataPtr == 0)
qFatal("QQNX: buffer pointer is NULL, errno=%d", errno);
// Get format of buffer
- errno = 0;
int screenFormat;
- result = screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_FORMAT, &screenFormat);
- if (result != 0)
- qFatal("QQNX: failed to query buffer format, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_get_buffer_property_iv(buffer, SCREEN_PROPERTY_FORMAT, &screenFormat),
+ "Failed to query buffer format");
// Convert screen format to QImage format
QImage::Format imageFormat = QImage::Format_Invalid;
diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.cpp b/src/plugins/platforms/qnx/qqnxeglwindow.cpp
index 984de67d7d..f1f9f5469c 100644
--- a/src/plugins/platforms/qnx/qqnxeglwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxeglwindow.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+** Copyright (C) 2013 - 2014 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -70,8 +70,7 @@ QQnxEglWindow::QQnxEglWindow(QWindow *window, screen_context_t context, bool nee
if (result != 0)
qFatal("QQnxEglWindow: failed to set window alpha usage, errno=%d", errno);
- m_requestedBufferSize = screen()->rootWindow() == this ?
- screen()->geometry().size() : window->geometry().size();
+ m_requestedBufferSize = shouldMakeFullScreen() ? screen()->geometry().size() : window->geometry().size();
}
QQnxEglWindow::~QQnxEglWindow()
@@ -86,8 +85,9 @@ void QQnxEglWindow::createEGLSurface()
// the window's buffers before we create the EGL surface
const QSize surfaceSize = requestedBufferSize();
if (!surfaceSize.isValid()) {
- qFatal("QQNX: Trying to create 0 size EGL surface. "
+ qWarning("QQNX: Trying to create 0 size EGL surface. "
"Please set a valid window size before calling QOpenGLContext::makeCurrent()");
+ return;
}
setBufferSize(surfaceSize);
@@ -104,8 +104,8 @@ void QQnxEglWindow::createEGLSurface()
, platformOpenGLContext()->getEglConfig(),
(EGLNativeWindowType) nativeHandle(), eglSurfaceAttrs);
if (m_eglSurface == EGL_NO_SURFACE) {
- QQnxGLContext::checkEGLError("eglCreateWindowSurface");
- qFatal("QQNX: failed to create EGL surface, err=%d", eglGetError());
+ const EGLenum error = QQnxGLContext::checkEGLError("eglCreateWindowSurface");
+ qWarning("QQNX: failed to create EGL surface, err=%d", error);
}
}
@@ -134,13 +134,14 @@ void QQnxEglWindow::swapEGLBuffers()
if (eglResult != EGL_TRUE)
qFatal("QQNX: failed to swap EGL buffers, err=%d", eglGetError());
- if (m_cover)
- m_cover->updateCover();
+ windowPosted();
}
EGLSurface QQnxEglWindow::getSurface()
{
if (m_newSurfaceRequested.testAndSetOrdered(true, false)) {
+ const QMutexLocker locker(&m_mutex); //Set geomety must not reset the requestedBufferSize till
+ //the surface is created
if (m_eglSurface != EGL_NO_SURFACE) {
platformOpenGLContext()->doneCurrent();
destroyEGLSurface();
@@ -154,7 +155,7 @@ EGLSurface QQnxEglWindow::getSurface()
void QQnxEglWindow::setGeometry(const QRect &rect)
{
//If this is the root window, it has to be shown fullscreen
- const QRect &newGeometry = screen()->rootWindow() == this ? screen()->geometry() : rect;
+ const QRect &newGeometry = shouldMakeFullScreen() ? screen()->geometry() : rect;
//We need to request that the GL context updates
// the EGLsurface on which it is rendering.
@@ -172,17 +173,9 @@ void QQnxEglWindow::setGeometry(const QRect &rect)
QSize QQnxEglWindow::requestedBufferSize() const
{
- const QMutexLocker locker(&m_mutex);
return m_requestedBufferSize;
}
-void QQnxEglWindow::adjustBufferSize()
-{
- const QSize windowSize = window()->size();
- if (windowSize != bufferSize())
- setBufferSize(windowSize);
-}
-
void QQnxEglWindow::setPlatformOpenGLContext(QQnxGLContext *platformOpenGLContext)
{
// This function does not take ownership of the platform gl context.
@@ -220,7 +213,6 @@ int QQnxEglWindow::pixelFormat() const
void QQnxEglWindow::resetBuffers()
{
- const QMutexLocker locker(&m_mutex);
m_requestedBufferSize = QSize();
}
diff --git a/src/plugins/platforms/qnx/qqnxeglwindow.h b/src/plugins/platforms/qnx/qqnxeglwindow.h
index fc53afcd7a..a6a223c58e 100644
--- a/src/plugins/platforms/qnx/qqnxeglwindow.h
+++ b/src/plugins/platforms/qnx/qqnxeglwindow.h
@@ -68,8 +68,6 @@ public:
// Called by QQnxGLContext::createSurface()
QSize requestedBufferSize() const;
- void adjustBufferSize();
-
protected:
int pixelFormat() const;
void resetBuffers();
diff --git a/src/plugins/platforms/qnx/qqnxfilepicker.cpp b/src/plugins/platforms/qnx/qqnxfilepicker.cpp
index 56c804a5b4..830b110f2a 100644
--- a/src/plugins/platforms/qnx/qqnxfilepicker.cpp
+++ b/src/plugins/platforms/qnx/qqnxfilepicker.cpp
@@ -48,7 +48,9 @@
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonParseError>
+#include <QMimeDatabase>
#include <QUrl>
+#include <private/qppsobject_p.h>
#include <bps/navigator.h>
#include <bps/navigator_invoke.h>
@@ -118,7 +120,7 @@ void QQnxFilePicker::open()
}
QVariantMap map;
- map[QStringLiteral("Type")] = QStringLiteral("Other");
+ map[QStringLiteral("Type")] = filePickerType();
map[QStringLiteral("Mode")] = modeToString(m_mode);
map[QStringLiteral("Title")] = m_title;
map[QStringLiteral("ViewMode")] = QStringLiteral("Default");
@@ -132,11 +134,16 @@ void QQnxFilePicker::open()
if (!m_filters.isEmpty())
map[QStringLiteral("Filter")] = m_filters.join(";");
+ QByteArray ppsData;
+#if defined(Q_OS_BLACKBERRY_TABLET)
QJsonDocument document;
document.setObject(QJsonObject::fromVariantMap(map));
- const QByteArray jsonData = document.toJson(QJsonDocument::Compact);
+ ppsData = document.toJson(QJsonDocument::Compact);
+#else
+ ppsData = QPpsObject::encode(map);
+#endif
- errorCode = navigator_invoke_invocation_set_data(m_invocationHandle, jsonData.constData(), jsonData.size());
+ errorCode = navigator_invoke_invocation_set_data(m_invocationHandle, ppsData.constData(), ppsData.size());
if (errorCode != BPS_SUCCESS) {
cleanup();
qWarning() << "QQnxFilePicker: unable to set data:" << strerror(errno);
@@ -275,6 +282,39 @@ void QQnxFilePicker::handleFilePickerResponse(const char *data)
cleanup();
}
+QString QQnxFilePicker::filePickerType() const
+{
+ bool images = false;
+ bool video = false;
+ bool music = false;
+ QMimeDatabase mimeDb;
+ for (int i = 0; i < filters().count(); i++) {
+ QList<QMimeType> mimeTypes = mimeDb.mimeTypesForFileName(filters().at(i));
+ if (mimeTypes.isEmpty())
+ return QStringLiteral("Other");
+
+ if (mimeTypes.first().name().startsWith(QLatin1String("image")))
+ images = true;
+ else if (mimeTypes.first().name().startsWith(QLatin1String("audio")))
+ music = true;
+ else if (mimeTypes.first().name().startsWith(QLatin1String("video")))
+ video = true;
+ else
+ return QStringLiteral("Other");
+ }
+
+ if (!video && !music)
+ return QStringLiteral("Picture");
+
+ if (!images && !music)
+ return QStringLiteral("Video");
+
+ if (!images && !video)
+ return QStringLiteral("Music");
+
+ return QStringLiteral("Other");
+}
+
QString QQnxFilePicker::modeToString(QQnxFilePicker::Mode mode) const
{
switch (mode) {
diff --git a/src/plugins/platforms/qnx/qqnxfilepicker.h b/src/plugins/platforms/qnx/qqnxfilepicker.h
index 5bb8f0969f..e8272900b0 100644
--- a/src/plugins/platforms/qnx/qqnxfilepicker.h
+++ b/src/plugins/platforms/qnx/qqnxfilepicker.h
@@ -92,6 +92,7 @@ public Q_SLOTS:
private:
void cleanup();
void handleFilePickerResponse(const char *data);
+ QString filePickerType() const;
QString modeToString(Mode mode) const;
diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp
index 34e8150928..23db7f09f3 100644
--- a/src/plugins/platforms/qnx/qqnxglcontext.cpp
+++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp
@@ -124,15 +124,11 @@ QQnxGLContext::QQnxGLContext(QOpenGLContext *glContext)
if (m_eglConfig == 0)
qFatal("QQnxGLContext: failed to find EGL config");
- EGLContext shareContext = EGL_NO_CONTEXT;
- if (m_glContext) {
- QQnxGLContext *qshareContext = dynamic_cast<QQnxGLContext*>(m_glContext->shareHandle());
- if (qshareContext) {
- shareContext = qshareContext->m_eglContext;
- }
- }
+ QQnxGLContext *glShareContext = static_cast<QQnxGLContext*>(m_glContext->shareHandle());
+ m_eglShareContext = glShareContext ? glShareContext->m_eglContext : EGL_NO_CONTEXT;
- m_eglContext = eglCreateContext(ms_eglDisplay, m_eglConfig, shareContext, contextAttrs());
+ m_eglContext = eglCreateContext(ms_eglDisplay, m_eglConfig, m_eglShareContext,
+ contextAttrs(format));
if (m_eglContext == EGL_NO_CONTEXT) {
checkEGLError("eglCreateContext");
qFatal("QQnxGLContext: failed to create EGL context, err=%d", eglGetError());
@@ -227,7 +223,8 @@ bool QQnxGLContext::makeCurrent(QPlatformSurface *surface)
eglResult = eglMakeCurrent(ms_eglDisplay, m_currentEglSurface, m_currentEglSurface, m_eglContext);
if (eglResult != EGL_TRUE) {
checkEGLError("eglMakeCurrent");
- qFatal("QQNX: failed to set current EGL context, err=%d", eglGetError());
+ qWarning("QQNX: failed to set current EGL context, err=%d", eglGetError());
+ return false;
}
return (eglResult == EGL_TRUE);
}
@@ -270,17 +267,22 @@ QFunctionPointer QQnxGLContext::getProcAddress(const QByteArray &procName)
return static_cast<QFunctionPointer>(eglGetProcAddress(procName.constData()));
}
+bool QQnxGLContext::isSharing() const
+{
+ return m_eglShareContext != EGL_NO_CONTEXT;
+}
+
EGLDisplay QQnxGLContext::getEglDisplay() {
return ms_eglDisplay;
}
-EGLint *QQnxGLContext::contextAttrs()
+EGLint *QQnxGLContext::contextAttrs(const QSurfaceFormat &format)
{
qGLContextDebug() << Q_FUNC_INFO;
// Choose EGL settings based on OpenGL version
#if defined(QT_OPENGL_ES_2)
- static EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+ static EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, format.version().first, EGL_NONE };
return attrs;
#else
return 0;
diff --git a/src/plugins/platforms/qnx/qqnxglcontext.h b/src/plugins/platforms/qnx/qqnxglcontext.h
index 2b12657da9..d12de7342b 100644
--- a/src/plugins/platforms/qnx/qqnxglcontext.h
+++ b/src/plugins/platforms/qnx/qqnxglcontext.h
@@ -72,6 +72,7 @@ public:
QFunctionPointer getProcAddress(const QByteArray &procName);
virtual QSurfaceFormat format() const { return m_windowFormat; }
+ bool isSharing() const;
static EGLDisplay getEglDisplay();
EGLConfig getEglConfig() const { return m_eglConfig;}
@@ -86,9 +87,10 @@ private:
EGLConfig m_eglConfig;
EGLContext m_eglContext;
+ EGLContext m_eglShareContext;
EGLSurface m_currentEglSurface;
- static EGLint *contextAttrs();
+ static EGLint *contextAttrs(const QSurfaceFormat &format);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxglobal.cpp b/src/plugins/platforms/qnx/qqnxglobal.cpp
new file mode 100644
index 0000000000..cef37af84e
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxglobal.cpp
@@ -0,0 +1,63 @@
+/***************************************************************************
+**
+** Copyright (C) 2011 - 2014 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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 <errno.h>
+
+#include <QDebug>
+#include "qqnxintegration.h"
+
+QT_BEGIN_NAMESPACE
+
+void qScreenCheckError(int rc, const char *funcInfo, const char *message, bool critical)
+{
+ if (!rc && (QQnxIntegration::options() & QQnxIntegration::AlwaysFlushScreenContext)
+ && QQnxIntegration::screenContext() != 0) {
+ rc = screen_flush_context(QQnxIntegration::screenContext(), 0);
+ }
+
+ if (rc) {
+ if (critical)
+ qCritical("%s - Screen: %s - Error: %s (%i)", funcInfo, message, strerror(errno), errno);
+ else
+ qWarning("%s - Screen: %s - Error: %s (%i)", funcInfo, message, strerror(errno), errno);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxglobal.h b/src/plugins/platforms/qnx/qqnxglobal.h
new file mode 100644
index 0000000000..8cfbfb084a
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxglobal.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+**
+** Copyright (C) 2011 - 2014 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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 QQNXGLOBAL_H
+#define QQNXGLOBAL_H
+
+#include <qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+void qScreenCheckError(int rc, const char *funcInfo, const char *message, bool critical);
+
+#define Q_SCREEN_CHECKERROR(x, message) \
+qScreenCheckError(x, Q_FUNC_INFO, message, false)
+
+#define Q_SCREEN_CRITICALERROR(x, message) \
+qScreenCheckError(x, Q_FUNC_INFO, message, true)
+
+QT_END_NAMESPACE
+
+#endif // QQNXGLOBAL_H
diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
index 580553f6e2..619883e843 100644
--- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
+++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -40,10 +40,10 @@
****************************************************************************/
#include "qqnxinputcontext_imf.h"
-#include "qqnxeventthread.h"
#include "qqnxabstractvirtualkeyboard.h"
#include "qqnxintegration.h"
#include "qqnxscreen.h"
+#include "qqnxscreeneventhandler.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QInputMethodEvent>
@@ -54,6 +54,8 @@
#include <QtCore/QVariant>
#include <QtCore/QVariantHash>
#include <QtCore/QWaitCondition>
+#include <QtCore/QQueue>
+#include <QtCore/QGlobalStatic>
#include <dlfcn.h>
#include "imf/imf_client.h"
@@ -62,9 +64,9 @@
#include <sys/keycodes.h>
#if defined(QQNXINPUTCONTEXT_IMF_EVENT_DEBUG)
-#define qInputContextIMFEventDebug qDebug
+#define qInputContextIMFRequestDebug qDebug
#else
-#define qInputContextIMFEventDebug QT_NO_QDEBUG_MACRO
+#define qInputContextIMFRequestDebug QT_NO_QDEBUG_MACRO
#endif
#if defined(QQNXINPUTCONTEXT_DEBUG)
@@ -73,492 +75,426 @@
#define qInputContextDebug QT_NO_QDEBUG_MACRO
#endif
-/** TODO:
- Support inputMethodHints to restrict input (needs additional features in IMF).
-*/
+static QQnxInputContext *sInputContextInstance;
+static QColor sSelectedColor(0,0xb8,0,85);
-#define STRX(x) #x
-#define STR(x) STRX(x)
-
-// Someone tell me why input_control methods are in this namespace, but the rest is not.
-using namespace InputMethodSystem;
-
-#define qs(x) QString::fromLatin1(x)
-#define iarg(name) event->mArgs[qs(#name)] = QVariant::fromValue(name)
-#define parg(name) event->mArgs[qs(#name)] = QVariant::fromValue((void*)name)
-namespace
-{
-
-spannable_string_t *toSpannableString(const QString &text);
+static const input_session_t *sSpellCheckSession = 0;
static const input_session_t *sInputSession = 0;
-bool isSessionOkay(input_session_t *ic)
+static bool isSessionOkay(input_session_t *ic)
{
return ic !=0 && sInputSession != 0 && ic->component_id == sInputSession->component_id;
}
enum ImfEventType
{
- ImfBeginBatchEdit,
- ImfClearMetaKeyStates,
ImfCommitText,
ImfDeleteSurroundingText,
- ImfEndBatchEdit,
ImfFinishComposingText,
- ImfGetCursorCapsMode,
ImfGetCursorPosition,
- ImfGetExtractedText,
- ImfGetSelectedText,
ImfGetTextAfterCursor,
ImfGetTextBeforeCursor,
- ImfPerformEditorAction,
- ImfReportFullscreenMode,
ImfSendEvent,
- ImfSendAsyncEvent,
ImfSetComposingRegion,
ImfSetComposingText,
- ImfSetSelection
+ ImfIsTextSelected,
+ ImfIsAllTextSelected,
};
-// We use this class as a round about way to support a posting synchronous event into
-// Qt's main thread from the IMF thread.
-class ImfEventResult
-{
-public:
- ImfEventResult()
- {
- m_mutex.lock();
- }
-
- ~ImfEventResult()
- {
- m_mutex.unlock();
- }
-
- void wait()
- {
- m_wait.wait(&m_mutex);
- }
-
- void signal()
- {
- m_wait.wakeAll();
- }
-
- void setResult(const QVariant& result)
- {
- m_mutex.lock();
- m_retVal = result;
- signal();
- m_mutex.unlock();
- }
-
- QVariant result()
- {
- return m_retVal;
- }
-
-private:
- QVariant m_retVal;
- QMutex m_mutex;
- QWaitCondition m_wait;
+struct SpellCheckInfo {
+ SpellCheckInfo(void *_context, void (*_spellCheckDone)(void *, const QString &, const QList<int> &))
+ : context(_context), spellCheckDone(_spellCheckDone) {}
+ void *context;
+ void (*spellCheckDone)(void *, const QString &, const QList<int> &);
};
+Q_GLOBAL_STATIC(QQueue<SpellCheckInfo>, sSpellCheckQueue)
-class ImfEvent : public QEvent
+// IMF requests all arrive on IMF's own thread and have to be posted to the main thread to be processed.
+class QQnxImfRequest
{
- public:
- ImfEvent(input_session_t *session, ImfEventType type, ImfEventResult *result) :
- QEvent((QEvent::Type)sUserEventType),
- m_session(session),
- m_imfType(type),
- m_result(result)
- {
- }
- ~ImfEvent() { }
-
- input_session_t *m_session;
- ImfEventType m_imfType;
- QVariantHash m_args;
- ImfEventResult *m_result;
-
- static int sUserEventType;
+public:
+ QQnxImfRequest(input_session_t *_session, ImfEventType _type)
+ : session(_session), type(_type)
+ { }
+ ~QQnxImfRequest() { }
+
+ input_session_t *session;
+ ImfEventType type;
+ union {
+ struct {
+ int32_t n;
+ int32_t flags;
+ bool before;
+ spannable_string_t *result;
+ } gtac; // ic_get_text_before_cursor/ic_get_text_after_cursor
+ struct {
+ int32_t result;
+ } gcp; // ic_get_cursor_position
+ struct {
+ int32_t start;
+ int32_t end;
+ int32_t result;
+ } scr; // ic_set_composing_region
+ struct {
+ spannable_string_t* text;
+ int32_t new_cursor_position;
+ int32_t result;
+ } sct; // ic_set_composing_text
+ struct {
+ spannable_string_t* text;
+ int32_t new_cursor_position;
+ int32_t result;
+ } ct; // ic_commit_text
+ struct {
+ int32_t result;
+ } fct; // ic_finish_composing_text
+ struct {
+ int32_t left_length;
+ int32_t right_length;
+ int32_t result;
+ } dst; // ic_delete_surrounding_text
+ struct {
+ event_t *event;
+ int32_t result;
+ } sae; // ic_send_async_event/ic_send_event
+ struct {
+ int32_t *pIsSelected;
+ int32_t result;
+ } its; // ic_is_text_selected/ic_is_all_text_selected
+ };
};
-int ImfEvent::sUserEventType = QEvent::registerEventType();
-static int32_t imfBeginBatchEdit(input_session_t *ic)
+// Invoke an IMF initiated request synchronously on Qt's main thread. As describe below all
+// IMF requests are made from another thread but need to be executed on the main thread.
+static void executeIMFRequest(QQnxImfRequest *event)
+{
+ QMetaObject::invokeMethod(sInputContextInstance,
+ "processImfEvent",
+ Qt::BlockingQueuedConnection,
+ Q_ARG(QQnxImfRequest*, event));
+}
+
+// The following functions (ic_*) are callback functions called by the input system to query information
+// about the text object that currently has focus or to make changes to it. All calls are made from the
+// input system's own thread. The pattern for each callback function is to copy its parameters into
+// a QQnxImfRequest structure and call executeIMFRequest to have it passed synchronously to Qt's main thread.
+// Any return values should be pre-initialised with suitable default values as in some cases
+// (e.g. a stale session) the call will return without having executed any request specific code.
+//
+// To make the correspondence more obvious, the names of these functions match those defined in the headers.
+// They're in an anonymous namespace to avoid compiler conflicts with external functions defined with the
+// same names.
+namespace
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfBeginBatchEdit, &result);
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- int32_t ret = result.result().value<int32_t>();
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_begin_batch_edit(input_session_t *ic)
+{
+ Q_UNUSED(ic);
- return ret;
+ // Ignore silently.
+ return 0;
}
-static int32_t imfClearMetaKeyStates(input_session_t *ic, int32_t states)
+// End composition, committing the supplied text.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_commit_text(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfClearMetaKeyStates, &result);
- iarg(states);
-
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- int32_t ret = result.result().value<int32_t>();
+ QQnxImfRequest event(ic, ImfCommitText);
+ event.ct.text = text;
+ event.ct.new_cursor_position = new_cursor_position;
+ event.ct.result = -1;
+ executeIMFRequest(&event);
- return ret;
+ return event.ct.result;
}
-static int32_t imfCommitText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
+// Delete left_length characters before and right_length characters after the cursor.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_delete_surrounding_text(input_session_t *ic, int32_t left_length, int32_t right_length)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfCommitText, &result);
- parg(text);
- iarg(new_cursor_position);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest event(ic, ImfDeleteSurroundingText);
+ event.dst.left_length = left_length;
+ event.dst.right_length = right_length;
+ event.dst.result = -1;
+ executeIMFRequest(&event);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
-
- return ret;
+ return event.dst.result;
}
-static int32_t imfDeleteSurroundingText(input_session_t *ic, int32_t left_length, int32_t right_length)
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_end_batch_edit(input_session_t *ic)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfDeleteSurroundingText, &result);
- iarg(left_length);
- iarg(right_length);
+ Q_UNUSED(ic);
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- int32_t ret = result.result().value<int32_t>();
-
- return ret;
+ // Ignore silently.
+ return 0;
}
-static int32_t imfEndBatchEdit(input_session_t *ic)
+// End composition, committing what's there.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_finish_composing_text(input_session_t *ic)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfEndBatchEdit, &result);
-
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- int32_t ret = result.result().value<int32_t>();
+ QQnxImfRequest event(ic, ImfFinishComposingText);
+ event.fct.result = -1;
+ executeIMFRequest(&event);
- return ret;
+ return event.fct.result;
}
-static int32_t imfFinishComposingText(input_session_t *ic)
+// Return the position of the cursor.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_get_cursor_position(input_session_t *ic)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfFinishComposingText, &result);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest event(ic, ImfGetCursorPosition);
+ event.gcp.result = -1;
+ executeIMFRequest(&event);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
-
- return ret;
+ return event.gcp.result;
}
-static int32_t imfGetCursorCapsMode(input_session_t *ic, int32_t req_modes)
+// Return the n characters after the cursor.
+// See comment at beginning of namespace declaration for general information
+static spannable_string_t *ic_get_text_after_cursor(input_session_t *ic, int32_t n, int32_t flags)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetCursorCapsMode, &result);
- iarg(req_modes);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest event(ic, ImfGetTextAfterCursor);
+ event.gtac.n = n;
+ event.gtac.flags = flags;
+ event.gtac.result = 0;
+ executeIMFRequest(&event);
- int32_t ret = result.result().value<int32_t>();
- return ret;
+ return event.gtac.result;
}
-static int32_t imfGetCursorPosition(input_session_t *ic)
+// Return the n characters before the cursor.
+// See comment at beginning of namespace declaration for general information
+static spannable_string_t *ic_get_text_before_cursor(input_session_t *ic, int32_t n, int32_t flags)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetCursorPosition, &result);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest event(ic, ImfGetTextBeforeCursor);
+ event.gtac.n = n;
+ event.gtac.flags = flags;
+ event.gtac.result = 0;
+ executeIMFRequest(&event);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
-
- return ret;
+ return event.gtac.result;
}
-static extracted_text_t *imfGetExtractedText(input_session_t *ic, extracted_text_request_t *request, int32_t flags)
+// Process an event from IMF. Primarily used for reflecting back keyboard events.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_send_event(input_session_t *ic, event_t *event)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic)) {
- extracted_text_t *et = (extracted_text_t *)calloc(sizeof(extracted_text_t),1);
- et->text = (spannable_string_t *)calloc(sizeof(spannable_string_t),1);
- return et;
- }
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetExtractedText, &result);
- parg(request);
- iarg(flags);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest imfEvent(ic, ImfSendEvent);
+ imfEvent.sae.event = event;
+ imfEvent.sae.result = -1;
+ executeIMFRequest(&imfEvent);
- result.wait();
- return result.result().value<extracted_text_t *>();
+ return imfEvent.sae.result;
}
-static spannable_string_t *imfGetSelectedText(input_session_t *ic, int32_t flags)
+// Same as ic_send_event.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_send_async_event(input_session_t *ic, event_t *event)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return toSpannableString("");
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetSelectedText, &result);
- iarg(flags);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ // There's no difference from our point of view between ic_send_event & ic_send_async_event
+ QQnxImfRequest imfEvent(ic, ImfSendEvent);
+ imfEvent.sae.event = event;
+ imfEvent.sae.result = -1;
+ executeIMFRequest(&imfEvent);
- result.wait();
- return result.result().value<extracted_text_t *>();
+ return imfEvent.sae.result;
}
-static spannable_string_t *imfGetTextAfterCursor(input_session_t *ic, int32_t n, int32_t flags)
+// Set the range of text between start and end as the composition range.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_set_composing_region(input_session_t *ic, int32_t start, int32_t end)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return toSpannableString("");
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetTextAfterCursor, &result);
- iarg(n);
- iarg(flags);
+ QQnxImfRequest event(ic, ImfSetComposingRegion);
+ event.scr.start = start;
+ event.scr.end = end;
+ event.scr.result = -1;
+ executeIMFRequest(&event);
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- return result.result().value<extracted_text_t *>();
+ return event.scr.result;
}
-static spannable_string_t *imfGetTextBeforeCursor(input_session_t *ic, int32_t n, int32_t flags)
+// Update the composition range with the supplied text. This can be called when no composition
+// range is in effect in which case one is started at the current cursor position.
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_set_composing_text(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return toSpannableString("");
+ QQnxImfRequest event(ic, ImfSetComposingText);
+ event.sct.text = text;
+ event.sct.new_cursor_position = new_cursor_position;
+ event.sct.result = -1;
+ executeIMFRequest(&event);
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfGetTextBeforeCursor, &result);
- iarg(n);
- iarg(flags);
-
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- return result.result().value<extracted_text_t *>();
+ return event.sct.result;
}
-static int32_t imfPerformEditorAction(input_session_t *ic, int32_t editor_action)
+// Indicate if any text is selected
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_is_text_selected(input_session_t* ic, int32_t* pIsSelected)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfPerformEditorAction, &result);
- iarg(editor_action);
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+ QQnxImfRequest event(ic, ImfIsTextSelected);
+ event.its.pIsSelected = pIsSelected;
+ event.its.result = -1;
+ executeIMFRequest(&event);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
- return ret;
+ return event.its.result;
}
-static int32_t imfReportFullscreenMode(input_session_t *ic, int32_t enabled)
+// Indicate if all text is selected
+// See comment at beginning of namespace declaration for general information
+static int32_t ic_is_all_text_selected(input_session_t* ic, int32_t* pIsSelected)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
+ qInputContextIMFRequestDebug() << Q_FUNC_INFO;
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfReportFullscreenMode, &result);
- iarg(enabled);
+ QQnxImfRequest event(ic, ImfIsAllTextSelected);
+ event.its.pIsSelected = pIsSelected;
+ event.its.result = -1;
+ executeIMFRequest(&event);
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
-
- result.wait();
- int32_t ret = result.result().value<int32_t>();
- return ret;
+ return event.its.result;
}
-static int32_t imfSendEvent(input_session_t *ic, event_t *event)
-{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEvent *imfEvent = new ImfEvent(ic, ImfSendEvent, 0);
- imfEvent->m_args[qs("event")] = QVariant::fromValue(static_cast<void *>(event));
+// LCOV_EXCL_START - exclude from code coverage analysis
+// The following functions are defined in the IMF headers but are not currently called.
- QCoreApplication::postEvent(QCoreApplication::instance(), imfEvent);
+// Not currently used
+static int32_t ic_perform_editor_action(input_session_t *ic, int32_t editor_action)
+{
+ Q_UNUSED(ic);
+ Q_UNUSED(editor_action);
+ qCritical() << "ic_perform_editor_action not implemented";
return 0;
}
-static int32_t imfSendAsyncEvent(input_session_t *ic, event_t *event)
+// Not currently used
+static int32_t ic_report_fullscreen_mode(input_session_t *ic, int32_t enabled)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- ImfEvent *imfEvent = new ImfEvent(ic, ImfSendAsyncEvent, 0);
- imfEvent->m_args[qs("event")] = QVariant::fromValue(static_cast<void *>(event));
-
- QCoreApplication::postEvent(QCoreApplication::instance(), imfEvent);
+ Q_UNUSED(ic);
+ Q_UNUSED(enabled);
+ qCritical() << "ic_report_fullscreen_mode not implemented";
return 0;
}
-static int32_t imfSetComposingRegion(input_session_t *ic, int32_t start, int32_t end)
+// Not currently used
+static extracted_text_t *ic_get_extracted_text(input_session_t *ic, extracted_text_request_t *request, int32_t flags)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
+ Q_UNUSED(ic);
+ Q_UNUSED(request);
+ Q_UNUSED(flags);
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfSetComposingRegion, &result);
- iarg(start);
- iarg(end);
+ qCritical() << "ic_get_extracted_text not implemented";
+ return 0;
+}
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+// Not currently used
+static spannable_string_t *ic_get_selected_text(input_session_t *ic, int32_t flags)
+{
+ Q_UNUSED(ic);
+ Q_UNUSED(flags);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
- return ret;
+ qCritical() << "ic_get_selected_text not implemented";
+ return 0;
}
-static int32_t imfSetComposingText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
+// Not currently used
+static int32_t ic_get_cursor_caps_mode(input_session_t *ic, int32_t req_modes)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
+ Q_UNUSED(ic);
+ Q_UNUSED(req_modes);
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfSetComposingText, &result);
- parg(text);
- iarg(new_cursor_position);
+ qCritical() << "ic_get_cursor_caps_mode not implemented";
+ return 0;
+}
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+// Not currently used
+static int32_t ic_clear_meta_key_states(input_session_t *ic, int32_t states)
+{
+ Q_UNUSED(ic);
+ Q_UNUSED(states);
- result.wait();
- int32_t ret = result.result().value<int32_t>();
- return ret;
+ qCritical() << "ic_clear_meta_key_states not implemented";
+ return 0;
}
-static int32_t imfSetSelection(input_session_t *ic, int32_t start, int32_t end)
+// Not currently used
+static int32_t ic_set_selection(input_session_t *ic, int32_t start, int32_t end)
{
- qInputContextIMFEventDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
+ Q_UNUSED(ic);
+ Q_UNUSED(start);
+ Q_UNUSED(end);
- ImfEventResult result;
- ImfEvent *event = new ImfEvent(ic, ImfSetSelection, &result);
- iarg(start);
- iarg(end);
+ qCritical() << "ic_set_selection not implemented";
+ return 0;
+}
- QCoreApplication::postEvent(QCoreApplication::instance(), event);
+// End of un-hittable code
+// LCOV_EXCL_STOP
- result.wait();
- int32_t ret = result.result().value<int32_t>();
- return ret;
-}
static connection_interface_t ic_funcs = {
- imfBeginBatchEdit,
- imfClearMetaKeyStates,
- imfCommitText,
- imfDeleteSurroundingText,
- imfEndBatchEdit,
- imfFinishComposingText,
- imfGetCursorCapsMode,
- imfGetCursorPosition,
- imfGetExtractedText,
- imfGetSelectedText,
- imfGetTextAfterCursor,
- imfGetTextBeforeCursor,
- imfPerformEditorAction,
- imfReportFullscreenMode,
- NULL, //ic_send_key_event
- imfSendEvent,
- imfSendAsyncEvent,
- imfSetComposingRegion,
- imfSetComposingText,
- imfSetSelection,
- NULL, //ic_set_candidates,
+ ic_begin_batch_edit,
+ ic_clear_meta_key_states,
+ ic_commit_text,
+ ic_delete_surrounding_text,
+ ic_end_batch_edit,
+ ic_finish_composing_text,
+ ic_get_cursor_caps_mode,
+ ic_get_cursor_position,
+ ic_get_extracted_text,
+ ic_get_selected_text,
+ ic_get_text_after_cursor,
+ ic_get_text_before_cursor,
+ ic_perform_editor_action,
+ ic_report_fullscreen_mode,
+ 0, //ic_send_key_event
+ ic_send_event,
+ ic_send_async_event,
+ ic_set_composing_region,
+ ic_set_composing_text,
+ ic_set_selection,
+ 0, //ic_set_candidates,
+ 0, //ic_get_cursor_offset,
+ 0, //ic_get_selection,
+ ic_is_text_selected,
+ ic_is_all_text_selected,
+ 0, //ic_get_max_cursor_offset_t
};
+} // namespace
+
static void
-initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType, int eventId)
+initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType, int eventId, int eventSize)
{
static int s_transactionId;
// Make sure structure is squeaky clean since it's not clear just what is significant.
- memset(pEvent, 0, sizeof(event_t));
+ memset(pEvent, 0, eventSize);
pEvent->event_type = eventType;
pEvent->event_id = eventId;
pEvent->pid = getpid();
@@ -566,31 +502,20 @@ initEvent(event_t *pEvent, const input_session_t *pSession, EventType eventType,
pEvent->transaction_id = ++s_transactionId;
}
-spannable_string_t *toSpannableString(const QString &text)
+static spannable_string_t *toSpannableString(const QString &text)
{
qInputContextDebug() << Q_FUNC_INFO << text;
- spannable_string_t *pString = reinterpret_cast<spannable_string_t *>(malloc(sizeof(spannable_string_t)));
- pString->str = (wchar_t *)malloc(sizeof(wchar_t) * text.length() + 1);
- pString->length = text.length();
+ spannable_string_t *pString = static_cast<spannable_string_t *>(malloc(sizeof(spannable_string_t)));
+ pString->str = static_cast<wchar_t *>(malloc(sizeof(wchar_t) * text.length() + 1));
+ pString->length = text.toWCharArray(pString->str);
pString->spans = 0;
pString->spans_count = 0;
-
- const QChar *pData = text.constData();
- wchar_t *pDst = pString->str;
-
- while (!pData->isNull())
- {
- *pDst = pData->unicode();
- pDst++;
- pData++;
- }
- *pDst = 0;
+ pString->str[pString->length] = 0;
return pString;
}
-} // namespace
static const input_session_t *(*p_ictrl_open_session)(connection_interface_t *) = 0;
static void (*p_ictrl_close_session)(input_session_t *) = 0;
@@ -645,27 +570,30 @@ QT_BEGIN_NAMESPACE
QQnxInputContext::QQnxInputContext(QQnxIntegration *integration, QQnxAbstractVirtualKeyboard &keyboard) :
QPlatformInputContext(),
- m_lastCaretPos(0),
+ m_caretPosition(0),
m_isComposing(false),
+ m_isUpdatingText(false),
m_inputPanelVisible(false),
m_inputPanelLocale(QLocale::c()),
+ m_focusObject(0),
m_integration(integration),
- m_virtualKeyboad(keyboard)
+ m_virtualKeyboard(keyboard)
{
qInputContextDebug() << Q_FUNC_INFO;
if (!imfAvailable())
return;
- if ( p_imf_client_init() != 0 ) {
+ // Save a pointer to ourselves so we can execute calls from IMF through executeIMFRequest
+ // In practice there will only ever be a single instance.
+ Q_ASSERT(sInputContextInstance == 0);
+ sInputContextInstance = this;
+
+ if (p_imf_client_init() != 0) {
s_imfInitFailed = true;
qCritical("imf_client_init failed - IMF services will be unavailable");
}
- QCoreApplication::instance()->installEventFilter(this);
-
- // p_vkb_init_selection_service();
-
connect(&keyboard, SIGNAL(visibilityChanged(bool)), this, SLOT(keyboardVisibilityChanged(bool)));
connect(&keyboard, SIGNAL(localeChanged(QLocale)), this, SLOT(keyboardLocaleChanged(QLocale)));
keyboardVisibilityChanged(keyboard.isVisible());
@@ -676,168 +604,75 @@ QQnxInputContext::~QQnxInputContext()
{
qInputContextDebug() << Q_FUNC_INFO;
+ Q_ASSERT(sInputContextInstance == this);
+ sInputContextInstance = 0;
+
if (!imfAvailable())
return;
- QCoreApplication::instance()->removeEventFilter(this);
p_imf_client_disconnect();
}
-#define getarg(type, name) type name = imfEvent->mArgs[qs(#name)].value<type>()
-#define getparg(type, name) type name = (type)(imfEvent->mArgs[qs(#name)].value<void*>())
-
bool QQnxInputContext::isValid() const
{
return imfAvailable();
}
-bool QQnxInputContext::eventFilter(QObject *obj, QEvent *event)
+void QQnxInputContext::processImfEvent(QQnxImfRequest *imfEvent)
{
- if (event->type() == ImfEvent::sUserEventType) {
- // Forward the event to our real handler.
- ImfEvent *imfEvent = static_cast<ImfEvent *>(event);
- switch (imfEvent->m_imfType) {
- case ImfBeginBatchEdit: {
- int32_t ret = onBeginBatchEdit(imfEvent->m_session);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfClearMetaKeyStates: {
- getarg(int32_t, states);
- int32_t ret = onClearMetaKeyStates(imfEvent->m_session, states);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfCommitText: {
- getparg(spannable_string_t*, text);
- getarg(int32_t, new_cursor_position);
- int32_t ret = onCommitText(imfEvent->m_session, text, new_cursor_position);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfDeleteSurroundingText: {
- getarg(int32_t, left_length);
- getarg(int32_t, right_length);
- int32_t ret = onDeleteSurroundingText(imfEvent->m_session, left_length, right_length);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfEndBatchEdit: {
- int32_t ret = onEndBatchEdit(imfEvent->m_session);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfFinishComposingText: {
- int32_t ret = onFinishComposingText(imfEvent->m_session);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfGetCursorCapsMode: {
- getarg(int32_t, req_modes);
- int32_t ret = onGetCursorCapsMode(imfEvent->m_session, req_modes);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfGetCursorPosition: {
- int32_t ret = onGetCursorPosition(imfEvent->m_session);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
-
- case ImfGetExtractedText: {
- getparg(extracted_text_request_t*, request);
- getarg(int32_t, flags);
- extracted_text_t *ret = onGetExtractedText(imfEvent->m_session, request, flags);
- imfEvent->m_result->setResult(QVariant::fromValue(static_cast<void *>(ret)));
- break;
- }
+ // If input session is no longer current, just bail, imfEvent should already be set with the appropriate
+ // return value. The only exception is spell check events since they're not associated with the
+ // object with focus.
+ if (imfEvent->type != ImfSendEvent || imfEvent->sae.event->event_type != EVENT_SPELL_CHECK) {
+ if (!isSessionOkay(imfEvent->session))
+ return;
+ }
- case ImfGetSelectedText: {
- getarg(int32_t, flags);
- spannable_string_t *ret = onGetSelectedText(imfEvent->m_session, flags);
- imfEvent->m_result->setResult(QVariant::fromValue(static_cast<void *>(ret)));
- break;
- }
+ switch (imfEvent->type) {
+ case ImfCommitText:
+ imfEvent->ct.result = onCommitText(imfEvent->ct.text, imfEvent->ct.new_cursor_position);
+ break;
- case ImfGetTextAfterCursor: {
- getarg(int32_t, n);
- getarg(int32_t, flags);
- spannable_string_t *ret = onGetTextAfterCursor(imfEvent->m_session, n, flags);
- imfEvent->m_result->setResult(QVariant::fromValue(static_cast<void *>(ret)));
- break;
- }
+ case ImfDeleteSurroundingText:
+ imfEvent->dst.result = onDeleteSurroundingText(imfEvent->dst.left_length, imfEvent->dst.right_length);
+ break;
- case ImfGetTextBeforeCursor: {
- getarg(int32_t, n);
- getarg(int32_t, flags);
- spannable_string_t *ret = onGetTextBeforeCursor(imfEvent->m_session, n, flags);
- imfEvent->m_result->setResult(QVariant::fromValue((void*)ret));
- break;
- }
+ case ImfFinishComposingText:
+ imfEvent->fct.result = onFinishComposingText();
+ break;
- case ImfPerformEditorAction: {
- getarg(int32_t, editor_action);
- int32_t ret = onPerformEditorAction(imfEvent->m_session, editor_action);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
+ case ImfGetCursorPosition:
+ imfEvent->gcp.result = onGetCursorPosition();
+ break;
- case ImfReportFullscreenMode: {
- getarg(int32_t, enabled);
- int32_t ret = onReportFullscreenMode(imfEvent->m_session, enabled);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
+ case ImfGetTextAfterCursor:
+ imfEvent->gtac.result = onGetTextAfterCursor(imfEvent->gtac.n, imfEvent->gtac.flags);
+ break;
- case ImfSendEvent: {
- getparg(event_t*, event);
- onSendEvent(imfEvent->m_session, event);
- break;
- }
+ case ImfGetTextBeforeCursor:
+ imfEvent->gtac.result = onGetTextBeforeCursor(imfEvent->gtac.n, imfEvent->gtac.flags);
+ break;
- case ImfSendAsyncEvent: {
- getparg(event_t*, event);
- onSendAsyncEvent(imfEvent->m_session, event);
- break;
- }
+ case ImfSendEvent:
+ imfEvent->sae.result = onSendEvent(imfEvent->sae.event);
+ break;
- case ImfSetComposingRegion: {
- getarg(int32_t, start);
- getarg(int32_t, end);
- int32_t ret = onSetComposingRegion(imfEvent->m_session, start, end);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
+ case ImfSetComposingRegion:
+ imfEvent->scr.result = onSetComposingRegion(imfEvent->scr.start, imfEvent->scr.end);
+ break;
- case ImfSetComposingText: {
- getparg(spannable_string_t*, text);
- getarg(int32_t, new_cursor_position);
- int32_t ret = onSetComposingText(imfEvent->m_session, text, new_cursor_position);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
+ case ImfSetComposingText:
+ imfEvent->sct.result = onSetComposingText(imfEvent->sct.text, imfEvent->sct.new_cursor_position);
+ break;
- case ImfSetSelection: {
- getarg(int32_t, start);
- getarg(int32_t, end);
- int32_t ret = onSetSelection(imfEvent->m_session, start, end);
- imfEvent->m_result->setResult(QVariant::fromValue(ret));
- break;
- }
- }; //switch
+ case ImfIsTextSelected:
+ imfEvent->its.result = onIsTextSelected(imfEvent->its.pIsSelected);
+ break;
- return true;
- } else {
- // standard event processing
- return QObject::eventFilter(obj, event);
- }
+ case ImfIsAllTextSelected:
+ imfEvent->its.result = onIsAllTextSelected(imfEvent->its.pIsSelected);
+ break;
+ }; //switch
}
bool QQnxInputContext::filterEvent( const QEvent *event )
@@ -845,12 +680,12 @@ bool QQnxInputContext::filterEvent( const QEvent *event )
qInputContextDebug() << Q_FUNC_INFO << event;
switch (event->type()) {
- case QEvent::CloseSoftwareInputPanel: {
+ case QEvent::CloseSoftwareInputPanel:
return dispatchCloseSoftwareInputPanel();
- }
- case QEvent::RequestSoftwareInputPanel: {
+
+ case QEvent::RequestSoftwareInputPanel:
return dispatchRequestSoftwareInputPanel();
- }
+
default:
return false;
}
@@ -869,12 +704,30 @@ void QQnxInputContext::reset()
endComposition();
}
-void QQnxInputContext::update(Qt::InputMethodQueries queries)
+void QQnxInputContext::commit()
{
qInputContextDebug() << Q_FUNC_INFO;
- reset();
+ endComposition();
+}
- QPlatformInputContext::update(queries);
+void QQnxInputContext::update(Qt::InputMethodQueries queries)
+{
+ qInputContextDebug() << Q_FUNC_INFO << queries;
+
+ if (queries & Qt::ImCursorPosition) {
+ int lastCaret = m_caretPosition;
+ updateCursorPosition();
+ // If caret position has changed we need to inform IMF unless this is just due to our own action
+ // such as committing text.
+ if (hasSession() && !m_isUpdatingText && lastCaret != m_caretPosition) {
+ caret_event_t caretEvent;
+ initEvent(&caretEvent.event, sInputSession, EVENT_CARET, CARET_POS_CHANGED, sizeof(caretEvent));
+ caretEvent.old_pos = lastCaret;
+ caretEvent.new_pos = m_caretPosition;
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_event caret changed" << lastCaret << m_caretPosition;
+ p_ictrl_dispatch_event(&caretEvent.event);
+ }
+ }
}
void QQnxInputContext::closeSession()
@@ -887,16 +740,23 @@ void QQnxInputContext::closeSession()
p_ictrl_close_session((input_session_t *)sInputSession);
sInputSession = 0;
}
+ // These are likely already in the right state but this depends on the text control
+ // having called reset or commit. So, just in case, set them to proper values.
+ m_isComposing = false;
+ m_composingText.clear();
}
-void QQnxInputContext::openSession()
+bool QQnxInputContext::openSession()
{
- qInputContextDebug() << Q_FUNC_INFO;
if (!imfAvailable())
- return;
+ return false;
closeSession();
sInputSession = p_ictrl_open_session(&ic_funcs);
+
+ qInputContextDebug() << Q_FUNC_INFO;
+
+ return sInputSession != 0;
}
bool QQnxInputContext::hasSession()
@@ -918,79 +778,89 @@ bool QQnxInputContext::hasSelectedText()
bool QQnxInputContext::dispatchRequestSoftwareInputPanel()
{
+ qInputContextDebug() << Q_FUNC_INFO << "requesting keyboard" << m_inputPanelVisible;
m_virtualKeyboard.showKeyboard();
- qInputContextDebug() << Q_FUNC_INFO << "requesting virtual keyboard";
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input || !inputMethodAccepted())
- return true;
-
- if (!hasSession())
- openSession();
- // This also means that the caret position has moved
- QInputMethodQueryEvent query(Qt::ImCursorPosition);
- QCoreApplication::sendEvent(input, &query);
- int caretPos = query.value(Qt::ImCursorPosition).toInt();
- caret_event_t caretEvent;
- memset(&caretEvent, 0, sizeof(caret_event_t));
- initEvent(&caretEvent.event, sInputSession, EVENT_CARET, CARET_POS_CHANGED);
- caretEvent.old_pos = m_lastCaretPos;
- m_lastCaretPos = caretEvent.new_pos = caretPos;
- p_ictrl_dispatch_event((event_t *)&caretEvent);
return true;
}
bool QQnxInputContext::dispatchCloseSoftwareInputPanel()
{
+ qInputContextDebug() << Q_FUNC_INFO << "hiding keyboard" << m_inputPanelVisible;
m_virtualKeyboard.hideKeyboard();
- qInputContextDebug() << Q_FUNC_INFO << "hiding virtual keyboard";
- // This also means we are stopping composition, but we should already have done that.
return true;
}
/**
* IMF Event Dispatchers.
*/
-bool QQnxInputContext::dispatchFocusEvent(FocusEventId id, int hints)
+bool QQnxInputContext::dispatchFocusGainEvent(int inputHints)
{
- qInputContextDebug() << Q_FUNC_INFO;
+ if (hasSession())
+ dispatchFocusLossEvent();
- if (!sInputSession) {
- qWarning() << Q_FUNC_INFO << "Attempt to dispatch a focus event with no input session.";
- return false;
- }
+ QObject *input = qGuiApp->focusObject();
- if (!imfAvailable())
+ if (!input || !openSession())
return false;
// Set the last caret position to 0 since we don't really have one and we don't
// want to have the old one.
- m_lastCaretPos = 0;
+ m_caretPosition = 0;
+
+ QInputMethodQueryEvent query(Qt::ImHints);
+ QCoreApplication::sendEvent(input, &query);
focus_event_t focusEvent;
- memset(&focusEvent, 0, sizeof(focusEvent));
- initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, id);
+ initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, FOCUS_GAINED, sizeof(focusEvent));
focusEvent.style = DEFAULT_STYLE;
- if (hints && Qt::ImhNoPredictiveText)
+ if (inputHints & Qt::ImhNoPredictiveText)
focusEvent.style |= NO_PREDICTION | NO_AUTO_CORRECTION;
- if (hints && Qt::ImhNoAutoUppercase)
+ if (inputHints & Qt::ImhNoAutoUppercase)
focusEvent.style |= NO_AUTO_TEXT;
+ // Following styles are mutually exclusive
+ if (inputHints & Qt::ImhHiddenText) {
+ focusEvent.style |= IMF_PASSWORD_TYPE;
+ } else if (inputHints & Qt::ImhDialableCharactersOnly) {
+ focusEvent.style |= IMF_PHONE_TYPE;
+ } else if (inputHints & Qt::ImhUrlCharactersOnly) {
+ focusEvent.style |= IMF_URL_TYPE;
+ } else if (inputHints & Qt::ImhEmailCharactersOnly) {
+ focusEvent.style |= IMF_EMAIL_TYPE;
+ }
+
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_event focus gain style:" << focusEvent.style;
+
p_ictrl_dispatch_event((event_t *)&focusEvent);
return true;
}
-bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap)
+void QQnxInputContext::dispatchFocusLossEvent()
{
- if (!imfAvailable())
+ if (hasSession()) {
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_event focus lost";
+
+ focus_event_t focusEvent;
+ initEvent(&focusEvent.event, sInputSession, EVENT_FOCUS, FOCUS_LOST, sizeof(focusEvent));
+ p_ictrl_dispatch_event((event_t *)&focusEvent);
+ closeSession();
+ }
+}
+
+bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId)
+{
+ Q_UNUSED(scan);
+
+ if (!hasSession())
return false;
int key = (flags & KEY_SYM_VALID) ? sym : cap;
- bool navKey = false;
- switch ( key ) {
+ bool navigationKey = false;
+ switch (key) {
case KEYCODE_RETURN:
/* In a single line edit we should end composition because enter might be used by something.
endComposition();
@@ -1007,27 +877,22 @@ bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan
break;
case KEYCODE_LEFT:
key = NAVIGATE_LEFT;
- navKey = true;
+ navigationKey = true;
break;
case KEYCODE_RIGHT:
key = NAVIGATE_RIGHT;
- navKey = true;
+ navigationKey = true;
break;
case KEYCODE_UP:
key = NAVIGATE_UP;
- navKey = true;
+ navigationKey = true;
break;
case KEYCODE_DOWN:
key = NAVIGATE_DOWN;
- navKey = true;
+ navigationKey = true;
break;
- case KEYCODE_CAPS_LOCK:
- case KEYCODE_LEFT_SHIFT:
- case KEYCODE_RIGHT_SHIFT:
case KEYCODE_LEFT_CTRL:
case KEYCODE_RIGHT_CTRL:
- case KEYCODE_LEFT_ALT:
- case KEYCODE_RIGHT_ALT:
case KEYCODE_MENU:
case KEYCODE_LEFT_HYPER:
case KEYCODE_RIGHT_HYPER:
@@ -1041,85 +906,183 @@ bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan
break;
}
- if ( mod & KEYMOD_CTRL ) {
- // If CTRL is pressed, just let AIR handle it. But terminate any composition first
- //endComposition();
- return false;
- }
-
// Pass the keys we don't know about on through
if ( key == 0 )
return false;
- // IMF doesn't need key releases so just swallow them.
- if (!(flags & KEY_DOWN))
- return true;
-
- if ( navKey ) {
+ if (navigationKey) {
// Even if we're forwarding up events, we can't do this for
// navigation keys.
if ( flags & KEY_DOWN ) {
navigation_event_t navEvent;
- initEvent(&navEvent.event, sInputSession, EVENT_NAVIGATION, key);
+ initEvent(&navEvent.event, sInputSession, EVENT_NAVIGATION, key, sizeof(navEvent));
navEvent.magnitude = 1;
- qInputContextDebug() << Q_FUNC_INFO << "dispatch navigation event " << key;
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_even navigation" << key;
p_ictrl_dispatch_event(&navEvent.event);
}
- }
- else {
+ } else {
key_event_t keyEvent;
- initEvent(&keyEvent.event, sInputSession, EVENT_KEY, flags & KEY_DOWN ? IMF_KEY_DOWN : IMF_KEY_UP);
- keyEvent.key_code = key;
- keyEvent.character = 0;
- keyEvent.meta_key_state = 0;
+ initEvent(&keyEvent.event, sInputSession, EVENT_KEY, flags & KEY_DOWN ? IMF_KEY_DOWN : IMF_KEY_UP,
+ sizeof(keyEvent));
+ keyEvent.key_code = cap;
+ keyEvent.character = sym;
+ keyEvent.meta_key_state = mod;
+ keyEvent.sequence_id = sequenceId;
p_ictrl_dispatch_event(&keyEvent.event);
- qInputContextDebug() << Q_FUNC_INFO << "dispatch key event " << key;
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_even key" << key;
}
- scan = 0;
return true;
}
-void QQnxInputContext::endComposition()
+void QQnxInputContext::updateCursorPosition()
{
- if (!m_isComposing)
+ QObject *input = qGuiApp->focusObject();
+ if (!input)
return;
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
+ QInputMethodQueryEvent query(Qt::ImCursorPosition);
+ QCoreApplication::sendEvent(input, &query);
+ m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
+
+ qInputContextDebug() << Q_FUNC_INFO << m_caretPosition;
+}
+
+void QQnxInputContext::endComposition()
+{
+ if (!m_isComposing)
return;
- QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event(QLatin1String(""), attributes);
- event.setCommitString(m_composingText);
- m_composingText = QString();
- m_isComposing = false;
- QCoreApplication::sendEvent(input, &event);
+ finishComposingText();
- action_event_t actionEvent;
- memset(&actionEvent, 0, sizeof(actionEvent));
- initEvent(&actionEvent.event, sInputSession, EVENT_ACTION, ACTION_END_COMPOSITION);
- p_ictrl_dispatch_event(&actionEvent.event);
+ if (hasSession()) {
+ action_event_t actionEvent;
+ initEvent(&actionEvent.event, sInputSession, EVENT_ACTION, ACTION_END_COMPOSITION, sizeof(actionEvent));
+ qInputContextDebug() << Q_FUNC_INFO << "ictrl_dispatch_even end composition";
+ p_ictrl_dispatch_event(&actionEvent.event);
+ }
}
-void QQnxInputContext::setComposingText(QString const& composingText)
+void QQnxInputContext::updateComposition(spannable_string_t *text, int32_t new_cursor_position)
{
- m_composingText = composingText;
+ QObject *input = qGuiApp->focusObject();
+ if (!input)
+ return;
+
+ if (new_cursor_position > 0)
+ new_cursor_position += text->length - 1;
+
+ m_composingText = QString::fromWCharArray(text->str, text->length);
m_isComposing = true;
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return;
+ qInputContextDebug() << Q_FUNC_INFO << m_composingText << new_cursor_position;
QList<QInputMethodEvent::Attribute> attributes;
- QTextCharFormat format;
- format.setFontUnderline(true);
- attributes.push_back(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, composingText.length(), format));
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
+ new_cursor_position,
+ 1,
+ QVariant()));
+
+ for (unsigned int i = 0; i < text->spans_count; ++i) {
+ QColor highlightColor;
+ bool underline = false;
+
+ if ((text->spans[i].attributes_mask & COMPOSED_TEXT_ATTRIB) != 0)
+ underline = true;
+
+ if ((text->spans[i].attributes_mask & ACTIVE_REGION_ATTRIB) != 0) {
+ underline = true;
+ highlightColor = m_highlightColor[ActiveRegion];
+ } else if ((text->spans[i].attributes_mask & AUTO_CORRECTION_ATTRIB) != 0) {
+ highlightColor = m_highlightColor[AutoCorrected];
+ } else if ((text->spans[i].attributes_mask & REVERT_CORRECTION_ATTRIB) != 0) {
+ highlightColor = m_highlightColor[Reverted];
+ }
- QInputMethodEvent event(composingText, attributes);
+ if (underline || highlightColor.isValid()) {
+ QTextCharFormat format;
+ if (underline)
+ format.setFontUnderline(true);
+ if (highlightColor.isValid())
+ format.setBackground(QBrush(highlightColor));
+ qInputContextDebug() << " attrib: " << underline << highlightColor << text->spans[i].start << text->spans[i].end;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, text->spans[i].start,
+ text->spans[i].end - text->spans[i].start + 1, QVariant(format)));
+ }
+ }
+ QInputMethodEvent event(m_composingText, attributes);
+ m_isUpdatingText = true;
QCoreApplication::sendEvent(input, &event);
+ m_isUpdatingText = false;
+
+ updateCursorPosition();
+}
+
+void QQnxInputContext::finishComposingText()
+{
+ QObject *input = qGuiApp->focusObject();
+
+ if (input) {
+ qInputContextDebug() << Q_FUNC_INFO << m_composingText;
+
+ QInputMethodEvent event;
+ event.setCommitString(m_composingText);
+ m_isUpdatingText = true;
+ QCoreApplication::sendEvent(input, &event);
+ m_isUpdatingText = false;
+ }
+ m_composingText = QString();
+ m_isComposing = false;
+
+ updateCursorPosition();
+}
+
+// Return the index relative to a UTF-16 sequence of characters for a index that is relative to the
+// corresponding UTF-32 character string given a starting index in the UTF-16 string and a count
+// of the number of lead surrogates prior to that index. Updates the highSurrogateCount to reflect the
+// new surrogate characters encountered.
+static int adjustIndex(const QChar *text, int utf32Index, int utf16StartIndex, int *highSurrogateCount)
+{
+ int utf16Index = utf32Index + *highSurrogateCount;
+ while (utf16StartIndex < utf16Index) {
+ if (text[utf16StartIndex].isHighSurrogate()) {
+ ++utf16Index;
+ ++*highSurrogateCount;
+ }
+ ++utf16StartIndex;
+ }
+ return utf16StartIndex;
+}
+
+int QQnxInputContext::handleSpellCheck(spell_check_event_t *event)
+{
+ // These should never happen.
+ if (sSpellCheckQueue->isEmpty() || event->event.event_id != NOTIFY_SP_CHECK_MISSPELLINGS)
+ return -1;
+
+ SpellCheckInfo callerInfo = sSpellCheckQueue->dequeue();
+ spannable_string_t* spellCheckData = *event->data;
+ QString text = QString::fromWCharArray(spellCheckData->str, spellCheckData->length);
+ // Generate the list of indices indicating misspelled words in the text. We use end + 1
+ // since it's more conventional to have the end index point just past the string. We also
+ // can't use the indices directly since they are relative to UTF-32 encoded data and the
+ // conversion to Qt's UTF-16 internal format might cause lengthening.
+ QList<int> indices;
+ int adjustment = 0;
+ int index = 0;
+ for (unsigned int i = 0; i < spellCheckData->spans_count; ++i) {
+ if (spellCheckData->spans[i].attributes_mask & MISSPELLED_WORD_ATTRIB) {
+ index = adjustIndex(text.data(), spellCheckData->spans[i].start, index, &adjustment);
+ indices.push_back(index);
+ index = adjustIndex(text.data(), spellCheckData->spans[i].end + 1, index, &adjustment);
+ indices.push_back(index);
+ }
+ }
+ callerInfo.spellCheckDone(callerInfo.context, text, indices);
+
+ return 0;
}
int32_t QQnxInputContext::processEvent(event_t *event)
@@ -1128,7 +1091,7 @@ int32_t QQnxInputContext::processEvent(event_t *event)
switch (event->event_type) {
case EVENT_SPELL_CHECK: {
qInputContextDebug() << Q_FUNC_INFO << "EVENT_SPELL_CHECK";
- result = 0;
+ result = handleSpellCheck(reinterpret_cast<spell_check_event_t *>(event));
break;
}
@@ -1140,19 +1103,24 @@ int32_t QQnxInputContext::processEvent(event_t *event)
event->event_id == NAVIGATE_LEFT ? KEYCODE_LEFT :
event->event_id == NAVIGATE_RIGHT ? KEYCODE_RIGHT : 0;
- QQnxEventThread::injectKeyboardEvent(KEY_DOWN | KEY_CAP_VALID, key, 0, 0, 0);
- QQnxEventThread::injectKeyboardEvent(KEY_CAP_VALID, key, 0, 0, 0);
+ QQnxScreenEventHandler::injectKeyboardEvent(KEY_DOWN | KEY_CAP_VALID, key, 0, 0, 0);
+ QQnxScreenEventHandler::injectKeyboardEvent(KEY_CAP_VALID, key, 0, 0, 0);
result = 0;
break;
}
case EVENT_KEY: {
- qInputContextDebug() << Q_FUNC_INFO << "EVENT_KEY";
- key_event_t *kevent = static_cast<key_event_t *>(event);
-
- QQnxEventThread::injectKeyboardEvent(KEY_DOWN | KEY_SYM_VALID | KEY_CAP_VALID, kevent->key_code, 0, 0, kevent->key_code);
- QQnxEventThread::injectKeyboardEvent(KEY_SYM_VALID | KEY_CAP_VALID, kevent->key_code, 0, 0, kevent->key_code);
-
+ key_event_t *kevent = reinterpret_cast<key_event_t *>(event);
+ int keySym = kevent->character != 0 ? kevent->character : kevent->key_code;
+ int keyCap = kevent->key_code;
+ int modifiers = 0;
+ if (kevent->meta_key_state & META_SHIFT_ON)
+ modifiers |= KEYMOD_SHIFT;
+ int flags = KEY_SYM_VALID | KEY_CAP_VALID;
+ if (event->event_id == IMF_KEY_DOWN)
+ flags |= KEY_DOWN;
+ qInputContextDebug() << Q_FUNC_INFO << "EVENT_KEY" << flags << keySym;
+ QQnxScreenEventHandler::injectKeyboardEvent(flags, keySym, modifiers, 0, keyCap);
result = 0;
break;
}
@@ -1179,339 +1147,175 @@ int32_t QQnxInputContext::processEvent(event_t *event)
* IMF Event Handlers
*/
-int32_t QQnxInputContext::onBeginBatchEdit(input_session_t *ic)
-{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- // We don't care.
- return 0;
-}
-
-int32_t QQnxInputContext::onClearMetaKeyStates(input_session_t *ic, int32_t states)
-{
- Q_UNUSED(states);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- // Should never get called.
- qCritical() << Q_FUNC_INFO << "onClearMetaKeyStates is unsupported.";
- return 0;
-}
-
-int32_t QQnxInputContext::onCommitText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
+int32_t QQnxInputContext::onCommitText(spannable_string_t *text, int32_t new_cursor_position)
{
- Q_UNUSED(new_cursor_position); // TODO: How can we set the cursor position it's not part of the API.
- if (!isSessionOkay(ic))
- return 0;
-
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return 0;
-
- QString commitString = QString::fromWCharArray(text->str, text->length);
-
- qInputContextDebug() << Q_FUNC_INFO << "Committing [" << commitString << "]";
-
- QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event(QLatin1String(""), attributes);
- event.setCommitString(commitString, 0, 0);
+ Q_UNUSED(new_cursor_position);
- QCoreApplication::sendEvent(input, &event);
- m_composingText = QString();
+ updateComposition(text, new_cursor_position);
+ finishComposingText();
return 0;
}
-int32_t QQnxInputContext::onDeleteSurroundingText(input_session_t *ic, int32_t left_length, int32_t right_length)
+int32_t QQnxInputContext::onDeleteSurroundingText(int32_t left_length, int32_t right_length)
{
qInputContextDebug() << Q_FUNC_INFO << "L:" << left_length << " R:" << right_length;
- if (!isSessionOkay(ic))
- return 0;
-
QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return 0;
-
- if (hasSelectedText()) {
- QQnxEventThread::injectKeyboardEvent(KEY_DOWN | KEY_CAP_VALID, KEYCODE_DELETE, 0, 0, 0);
- QQnxEventThread::injectKeyboardEvent(KEY_CAP_VALID, KEYCODE_DELETE, 0, 0, 0);
- reset();
+ if (!input)
return 0;
- }
int replacementLength = left_length + right_length;
int replacementStart = -left_length;
- QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event(QLatin1String(""), attributes);
- event.setCommitString(QLatin1String(""), replacementStart, replacementLength);
- QCoreApplication::sendEvent(input, &event);
-
- return 0;
-}
-
-int32_t QQnxInputContext::onEndBatchEdit(input_session_t *ic)
-{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- return 0;
-}
-
-int32_t QQnxInputContext::onFinishComposingText(input_session_t *ic)
-{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return 0;
+ finishComposingText();
- // Only update the control, no need to send a message back to imf (don't call
- // end composition)
- QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event(QLatin1String(""), attributes);
- event.setCommitString(m_composingText);
- m_composingText = QString();
- m_isComposing = false;
+ QInputMethodEvent event;
+ event.setCommitString(QString(), replacementStart, replacementLength);
+ m_isUpdatingText = true;
QCoreApplication::sendEvent(input, &event);
+ m_isUpdatingText = false;
- return 0;
-}
-
-int32_t QQnxInputContext::onGetCursorCapsMode(input_session_t *ic, int32_t req_modes)
-{
- Q_UNUSED(req_modes);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- // Should never get called.
- qCritical() << Q_FUNC_INFO << "onGetCursorCapsMode is unsupported.";
+ updateCursorPosition();
return 0;
}
-int32_t QQnxInputContext::onGetCursorPosition(input_session_t *ic)
+int32_t QQnxInputContext::onFinishComposingText()
{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
+ finishComposingText();
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return 0;
-
- QInputMethodQueryEvent query(Qt::ImCursorPosition);
- QCoreApplication::sendEvent(input, &query);
- m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt();
-
- return m_lastCaretPos;
-}
-
-extracted_text_t *QQnxInputContext::onGetExtractedText(input_session_t *ic, extracted_text_request_t *request, int32_t flags)
-{
- Q_UNUSED(flags);
- Q_UNUSED(request);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic)) {
- extracted_text_t *et = (extracted_text_t *)calloc(sizeof(extracted_text_t),1);
- et->text = reinterpret_cast<spannable_string_t *>(calloc(sizeof(spannable_string_t),1));
- return et;
- }
-
- // Used to update dictionaries, but not supported right now.
- extracted_text_t *et = (extracted_text_t *)calloc(sizeof(extracted_text_t),1);
- et->text = reinterpret_cast<spannable_string_t *>(calloc(sizeof(spannable_string_t),1));
-
- return et;
+ return 0;
}
-spannable_string_t *QQnxInputContext::onGetSelectedText(input_session_t *ic, int32_t flags)
+int32_t QQnxInputContext::onGetCursorPosition()
{
- Q_UNUSED(flags);
qInputContextDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return toSpannableString("");
-
QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
+ if (!input)
return 0;
- QInputMethodQueryEvent query(Qt::ImCurrentSelection);
- QCoreApplication::sendEvent(input, &query);
- QString text = query.value(Qt::ImCurrentSelection).toString();
+ updateCursorPosition();
- return toSpannableString(text);
+ return m_caretPosition;
}
-spannable_string_t *QQnxInputContext::onGetTextAfterCursor(input_session_t *ic, int32_t n, int32_t flags)
+spannable_string_t *QQnxInputContext::onGetTextAfterCursor(int32_t n, int32_t flags)
{
Q_UNUSED(flags);
qInputContextDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return toSpannableString("");
-
QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
+ if (!input)
return toSpannableString("");
QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImSurroundingText);
QCoreApplication::sendEvent(input, &query);
QString text = query.value(Qt::ImSurroundingText).toString();
- m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt();
+ m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
- return toSpannableString(text.mid(m_lastCaretPos+1, n));
+ return toSpannableString(text.mid(m_caretPosition, n));
}
-spannable_string_t *QQnxInputContext::onGetTextBeforeCursor(input_session_t *ic, int32_t n, int32_t flags)
+spannable_string_t *QQnxInputContext::onGetTextBeforeCursor(int32_t n, int32_t flags)
{
Q_UNUSED(flags);
qInputContextDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return toSpannableString("");
-
QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
+ if (!input)
return toSpannableString("");
QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImSurroundingText);
QCoreApplication::sendEvent(input, &query);
QString text = query.value(Qt::ImSurroundingText).toString();
- m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt();
+ m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
- if (n < m_lastCaretPos)
- return toSpannableString(text.mid(m_lastCaretPos - n, n));
+ if (n < m_caretPosition)
+ return toSpannableString(text.mid(m_caretPosition - n, n));
else
- return toSpannableString(text.mid(0, m_lastCaretPos));
-}
-
-int32_t QQnxInputContext::onPerformEditorAction(input_session_t *ic, int32_t editor_action)
-{
- Q_UNUSED(editor_action);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- // Should never get called.
- qCritical() << Q_FUNC_INFO << "onPerformEditorAction is unsupported.";
-
- return 0;
-}
-
-int32_t QQnxInputContext::onReportFullscreenMode(input_session_t *ic, int32_t enabled)
-{
- Q_UNUSED(enabled);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- // Should never get called.
- qCritical() << Q_FUNC_INFO << "onReportFullscreenMode is unsupported.";
-
- return 0;
-}
-
-int32_t QQnxInputContext::onSendEvent(input_session_t *ic, event_t *event)
-{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- return processEvent(event);
+ return toSpannableString(text.mid(0, m_caretPosition));
}
-int32_t QQnxInputContext::onSendAsyncEvent(input_session_t *ic, event_t *event)
+int32_t QQnxInputContext::onSendEvent(event_t *event)
{
qInputContextDebug() << Q_FUNC_INFO;
- if (!isSessionOkay(ic))
- return 0;
-
return processEvent(event);
}
-int32_t QQnxInputContext::onSetComposingRegion(input_session_t *ic, int32_t start, int32_t end)
+int32_t QQnxInputContext::onSetComposingRegion(int32_t start, int32_t end)
{
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
+ if (!input)
return 0;
QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImSurroundingText);
QCoreApplication::sendEvent(input, &query);
QString text = query.value(Qt::ImSurroundingText).toString();
- m_lastCaretPos = query.value(Qt::ImCursorPosition).toInt();
+ m_caretPosition = query.value(Qt::ImCursorPosition).toInt();
- QString empty = QString::fromLatin1("");
- text = text.mid(start, end - start);
+ qInputContextDebug() << Q_FUNC_INFO << text;
+
+ m_isUpdatingText = true;
// Delete the current text.
+ QInputMethodEvent deleteEvent;
+ deleteEvent.setCommitString(QString(), start - m_caretPosition, end - start);
+ QCoreApplication::sendEvent(input, &deleteEvent);
+
+ m_composingText = text.mid(start, end - start);
+ m_isComposing = true;
+
QList<QInputMethodEvent::Attribute> attributes;
- QInputMethodEvent event(empty, attributes);
- event.setCommitString(empty, start - m_lastCaretPos, end - start);
- QCoreApplication::sendEvent(input, &event);
+ QTextCharFormat format;
+ format.setFontUnderline(true);
+ attributes.push_back(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, m_composingText.length(), format));
+
+ QInputMethodEvent setTextEvent(m_composingText, attributes);
+ QCoreApplication::sendEvent(input, &setTextEvent);
- // Move the specified text into a preedit string.
- setComposingText(text);
+ m_isUpdatingText = false;
return 0;
}
-int32_t QQnxInputContext::onSetComposingText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position)
+int32_t QQnxInputContext::onSetComposingText(spannable_string_t *text, int32_t new_cursor_position)
{
- Q_UNUSED(new_cursor_position);
- qInputContextDebug() << Q_FUNC_INFO;
-
- if (!isSessionOkay(ic))
- return 0;
-
- QObject *input = qGuiApp->focusObject();
- if (!imfAvailable() || !input)
- return 0;
+ if (text->length > 0) {
+ updateComposition(text, new_cursor_position);
+ } else {
+ // If the composing text is empty we can simply end composition, the visual effect is the same.
+ // However, sometimes one wants to display hint text in an empty text field and for this to work
+ // QQuickTextEdit.inputMethodComposing has to be false if the composition string is empty.
+ m_composingText.clear();
+ finishComposingText();
+ }
+ return 0;
+}
- m_isComposing = true;
+int32_t QQnxInputContext::onIsTextSelected(int32_t* pIsSelected)
+{
+ *pIsSelected = hasSelectedText();
- QString preeditString = QString::fromWCharArray(text->str, text->length);
- setComposingText(preeditString);
+ qInputContextDebug() << Q_FUNC_INFO << *pIsSelected;
return 0;
}
-int32_t QQnxInputContext::onSetSelection(input_session_t *ic, int32_t start, int32_t end)
+int32_t QQnxInputContext::onIsAllTextSelected(int32_t* pIsSelected)
{
- Q_UNUSED(start);
- Q_UNUSED(end);
- qInputContextDebug() << Q_FUNC_INFO;
+ QObject *input = qGuiApp->focusObject();
+ if (!input)
+ return -1;
- if (!isSessionOkay(ic))
- return 0;
+ QInputMethodQueryEvent query(Qt::ImCurrentSelection | Qt::ImSurroundingText);
+ QCoreApplication::sendEvent(input, &query);
+
+ *pIsSelected = query.value(Qt::ImSurroundingText).toString().length() == query.value(Qt::ImCurrentSelection).toString().length();
- // Should never get called.
- qCritical() << Q_FUNC_INFO << "onSetSelection is unsupported.";
+ qInputContextDebug() << Q_FUNC_INFO << *pIsSelected;
return 0;
}
@@ -1556,19 +1360,74 @@ void QQnxInputContext::keyboardLocaleChanged(const QLocale &locale)
}
}
+void QQnxInputContext::setHighlightColor(int index, const QColor &color)
+{
+ qInputContextDebug() << Q_FUNC_INFO << "setHighlightColor" << index << color << qGuiApp->focusObject();
+
+ if (!sInputContextInstance)
+ return;
+
+ // If the focus has changed, revert all colors to the default.
+ if (sInputContextInstance->m_focusObject != qGuiApp->focusObject()) {
+ QColor invalidColor;
+ sInputContextInstance->m_highlightColor[ActiveRegion] = sSelectedColor;
+ sInputContextInstance->m_highlightColor[AutoCorrected] = invalidColor;
+ sInputContextInstance->m_highlightColor[Reverted] = invalidColor;
+ sInputContextInstance->m_focusObject = qGuiApp->focusObject();
+ }
+ if (index >= 0 && index <= Reverted)
+ sInputContextInstance->m_highlightColor[index] = color;
+}
+
void QQnxInputContext::setFocusObject(QObject *object)
{
qInputContextDebug() << Q_FUNC_INFO << "input item=" << object;
+ // Ensure the colors are reset if we've a change in focus object
+ setHighlightColor(-1, QColor());
+
if (!inputMethodAccepted()) {
if (m_inputPanelVisible)
hideInputPanel();
+ if (hasSession())
+ dispatchFocusLossEvent();
} else {
- m_virtualKeyboard.setInputHintsFromObject(object);
+ QInputMethodQueryEvent query(Qt::ImHints);
+ QCoreApplication::sendEvent(object, &query);
+ int inputHints = query.value(Qt::ImHints).toInt();
+
+ dispatchFocusGainEvent(inputHints);
+
+ m_virtualKeyboard.setInputHints(inputHints);
if (!m_inputPanelVisible)
showInputPanel();
}
}
+bool QQnxInputContext::checkSpelling(const QString &text, void *context, void (*spellCheckDone)(void *context, const QString &text, const QList<int> &indices))
+{
+ qInputContextDebug() << Q_FUNC_INFO << "text" << text;
+
+ if (!imfAvailable())
+ return false;
+
+ if (!sSpellCheckSession)
+ sSpellCheckSession = p_ictrl_open_session(&ic_funcs);
+
+ action_event_t spellEvent;
+ initEvent(&spellEvent.event, sSpellCheckSession, EVENT_ACTION, ACTION_CHECK_MISSPELLINGS, sizeof(spellEvent));
+ int len = text.length();
+ spellEvent.event_data = alloca(sizeof(wchar_t) * (len + 1));
+ spellEvent.length_data = text.toWCharArray(static_cast<wchar_t*>(spellEvent.event_data)) * sizeof(wchar_t);
+
+ int rc = p_ictrl_dispatch_event(reinterpret_cast<event_t*>(&spellEvent));
+
+ if (rc == 0) {
+ sSpellCheckQueue->enqueue(SpellCheckInfo(context, spellCheckDone));
+ return true;
+ }
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.h b/src/plugins/platforms/qnx/qqnxinputcontext_imf.h
index 1980a99ed9..5028215bbe 100644
--- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.h
+++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.h
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -43,9 +43,11 @@
#define QQNXINPUTCONTEXT_H
#include <qpa/qplatforminputcontext.h>
+#include "qqnxscreeneventfilter.h"
#include <QtCore/QLocale>
#include <QtCore/QMetaType>
+#include <QtCore/QList>
#include <qpa/qplatformintegration.h>
#include "imf/imf_client.h"
@@ -55,21 +57,30 @@ QT_BEGIN_NAMESPACE
class QQnxAbstractVirtualKeyboard;
class QQnxIntegration;
+class QQnxImfRequest;
-class QQnxInputContext : public QPlatformInputContext
+class QQnxInputContext : public QPlatformInputContext, public QQnxScreenEventFilter
{
Q_OBJECT
public:
explicit QQnxInputContext(QQnxIntegration *integration, QQnxAbstractVirtualKeyboard &keyboard);
~QQnxInputContext();
+ // Indices for selecting and setting highlight colors.
+ enum HighlightIndex {
+ ActiveRegion,
+ AutoCorrected,
+ Reverted,
+ };
+
bool isValid() const;
bool filterEvent(const QEvent *event);
QRectF keyboardRect() const;
void reset();
+ void commit();
void update(Qt::InputMethodQueries);
- bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap);
+ bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId);
void showInputPanel();
@@ -79,61 +90,62 @@ public:
QLocale locale() const;
void setFocusObject(QObject *object);
-protected:
- // Filters only for IMF events.
- bool eventFilter(QObject *obj, QEvent *event);
+ static void setHighlightColor(int index, const QColor &color);
+
+ static bool checkSpelling(const QString &text, void *context, void (*spellCheckDone)(void *context, const QString &text, const QList<int> &indices));
private Q_SLOTS:
void keyboardVisibilityChanged(bool visible);
void keyboardLocaleChanged(const QLocale &locale);
+ void processImfEvent(QQnxImfRequest *event);
private:
// IMF Event dispatchers
- bool dispatchFocusEvent(FocusEventId id, int hints = Qt::ImhNone);
+ bool dispatchFocusGainEvent(int inputHints);
+ void dispatchFocusLossEvent();
bool dispatchRequestSoftwareInputPanel();
bool dispatchCloseSoftwareInputPanel();
+ int handleSpellCheck(spell_check_event_t *event);
int32_t processEvent(event_t *event);
void closeSession();
- void openSession();
+ bool openSession();
bool hasSession();
+ void updateCursorPosition();
void endComposition();
- void setComposingText(QString const &composingText);
+ void finishComposingText();
bool hasSelectedText();
+ void updateComposition(spannable_string_t *text, int32_t new_cursor_position);
// IMF Event handlers - these events will come in from QCoreApplication.
- int32_t onBeginBatchEdit(input_session_t *ic);
- int32_t onClearMetaKeyStates(input_session_t *ic, int32_t states);
- int32_t onCommitText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position);
- int32_t onDeleteSurroundingText(input_session_t *ic, int32_t left_length, int32_t right_length);
- int32_t onEndBatchEdit(input_session_t *ic);
- int32_t onFinishComposingText(input_session_t *ic);
- int32_t onGetCursorCapsMode(input_session_t *ic, int32_t req_modes);
- int32_t onGetCursorPosition(input_session_t *ic);
- extracted_text_t *onGetExtractedText(input_session_t *ic, extracted_text_request_t *request, int32_t flags);
- spannable_string_t *onGetSelectedText(input_session_t *ic, int32_t flags);
- spannable_string_t *onGetTextAfterCursor(input_session_t *ic, int32_t n, int32_t flags);
- spannable_string_t *onGetTextBeforeCursor(input_session_t *ic, int32_t n, int32_t flags);
- int32_t onPerformEditorAction(input_session_t *ic, int32_t editor_action);
- int32_t onReportFullscreenMode(input_session_t *ic, int32_t enabled);
- int32_t onSendEvent(input_session_t *ic, event_t *event);
- int32_t onSendAsyncEvent(input_session_t *ic, event_t *event);
- int32_t onSetComposingRegion(input_session_t *ic, int32_t start, int32_t end);
- int32_t onSetComposingText(input_session_t *ic, spannable_string_t *text, int32_t new_cursor_position);
- int32_t onSetSelection(input_session_t *ic, int32_t start, int32_t end);
+ int32_t onCommitText(spannable_string_t *text, int32_t new_cursor_position);
+ int32_t onDeleteSurroundingText(int32_t left_length, int32_t right_length);
+ int32_t onGetCursorCapsMode(int32_t req_modes);
+ int32_t onFinishComposingText();
+ int32_t onGetCursorPosition();
+ spannable_string_t *onGetTextAfterCursor(int32_t n, int32_t flags);
+ spannable_string_t *onGetTextBeforeCursor(int32_t n, int32_t flags);
+ int32_t onSendEvent(event_t *event);
+ int32_t onSetComposingRegion(int32_t start, int32_t end);
+ int32_t onSetComposingText(spannable_string_t *text, int32_t new_cursor_position);
+ int32_t onIsTextSelected(int32_t* pIsSelected);
+ int32_t onIsAllTextSelected(int32_t* pIsSelected);
int32_t onForceUpdate();
- int m_lastCaretPos;
+ int m_caretPosition;
bool m_isComposing;
QString m_composingText;
+ bool m_isUpdatingText;
bool m_inputPanelVisible;
QLocale m_inputPanelLocale;
+ // The object that had focus when the last highlight color was set.
+ QObject *m_focusObject;
+ // Indexed by HighlightIndex
+ QColor m_highlightColor[3];
QQnxIntegration *m_integration;
- QQnxAbstractVirtualKeyboard &m_virtualKeyboad;
+ QQnxAbstractVirtualKeyboard &m_virtualKeyboard;
};
-Q_DECLARE_METATYPE(extracted_text_t*)
-
QT_END_NAMESPACE
#endif // QQNXINPUTCONTEXT_H
diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp
index f444d34b5e..9270f1ed6b 100644
--- a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp
+++ b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -46,6 +46,7 @@
#include <QtCore/QDebug>
#include <QtGui/QGuiApplication>
+#include <QtGui/QInputMethodEvent>
#if defined(QQNXINPUTCONTEXT_DEBUG)
#define qInputContextDebug qDebug
@@ -179,7 +180,11 @@ void QQnxInputContext::setFocusObject(QObject *object)
if (m_inputPanelVisible)
hideInputPanel();
} else {
- m_virtualKeyboard.setInputHintsFromObject(object);
+ QInputMethodQueryEvent query(Qt::ImHints);
+ QCoreApplication::sendEvent(object, &query);
+ int inputHints = query.value(Qt::ImHints).toInt();
+
+ m_virtualKeyboard.setInputHints(inputHints);
if (!m_inputPanelVisible)
showInputPanel();
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index 52f836abbe..41ca2b5e18 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2013 BlackBerry Limited. All rights reserved.
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#include "qqnxglobal.h"
+
#include "qqnxintegration.h"
#if defined(QQNX_SCREENEVENTTHREAD)
#include "qqnxscreeneventthread.h"
@@ -61,7 +63,7 @@
#if defined(Q_OS_BLACKBERRY)
#include "qqnxbpseventfilter.h"
#include "qqnxnavigatorbps.h"
-#include "qqnxtheme.h"
+#include "qblackberrytheme.h"
#include "qqnxvirtualkeyboardbps.h"
#elif defined(QQNX_PPS)
#include "qqnxnavigatorpps.h"
@@ -123,6 +125,10 @@ static inline QQnxIntegration::Options parseOptions(const QStringList &paramList
options |= QQnxIntegration::FullScreenApplication;
}
+ if (!paramList.contains(QLatin1String("flush-screen-context"))) {
+ options |= QQnxIntegration::AlwaysFlushScreenContext;
+ }
+
// On Blackberry the first window is treated as a root window
#ifdef Q_OS_BLACKBERRY
if (!paramList.contains(QLatin1String("no-rootwindow"))) {
@@ -156,7 +162,7 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
#else
, m_eventDispatcher(createUnixEventDispatcher())
#endif
- , m_nativeInterface(new QQnxNativeInterface())
+ , m_nativeInterface(new QQnxNativeInterface(this))
, m_screenEventHandler(new QQnxScreenEventHandler(this))
#if !defined(QT_NO_CLIPBOARD)
, m_clipboard(0)
@@ -165,14 +171,12 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
#if !defined(QT_NO_DRAGANDDROP)
, m_drag(new QSimpleDrag())
#endif
- , m_options(parseOptions(paramList))
{
+ ms_options = parseOptions(paramList);
qIntegrationDebug() << Q_FUNC_INFO;
// Open connection to QNX composition manager
- errno = 0;
- int result = screen_create_context(&m_screenContext, SCREEN_APPLICATION_CONTEXT);
- if (result != 0)
- qFatal("QQnx: failed to connect to composition manager, errno=%d", errno);
+ Q_SCREEN_CRITICALERROR(screen_create_context(&ms_screenContext, SCREEN_APPLICATION_CONTEXT),
+ "Failed to create screen context");
// Not on BlackBerry, it has specialized event dispatcher which also handles navigator events
#if !defined(Q_OS_BLACKBERRY) && defined(QQNX_PPS)
@@ -191,7 +195,7 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
// Create/start event thread
#if defined(QQNX_SCREENEVENTTHREAD)
- m_screenEventThread = new QQnxScreenEventThread(m_screenContext, m_screenEventHandler);
+ m_screenEventThread = new QQnxScreenEventThread(ms_screenContext, m_screenEventHandler);
m_screenEventThread->start();
#endif
@@ -251,6 +255,9 @@ QQnxIntegration::QQnxIntegration(const QStringList &paramList)
#if defined(QQNX_PPS)
// Set up the input context
m_inputContext = new QQnxInputContext(this, *m_virtualKeyboard);
+#if defined(QQNX_IMF)
+ m_screenEventHandler->addScreenEventFilter(m_inputContext);
+#endif
#endif
}
@@ -271,17 +278,6 @@ QQnxIntegration::~QQnxIntegration()
delete m_drag;
#endif
-#if defined(QQNX_PPS)
- // Destroy the hardware button notifier
- delete m_buttonsNotifier;
-
- // Destroy input context
- delete m_inputContext;
-#endif
-
- // Destroy the keyboard class.
- delete m_virtualKeyboard;
-
#if !defined(QT_NO_CLIPBOARD)
// Delete the clipboard
delete m_clipboard;
@@ -314,13 +310,24 @@ QQnxIntegration::~QQnxIntegration()
destroyDisplays();
// Close connection to QNX composition manager
- screen_destroy_context(m_screenContext);
+ screen_destroy_context(ms_screenContext);
#if !defined(QT_NO_OPENGL)
// Cleanup global OpenGL resources
QQnxGLContext::shutdown();
#endif
+#if defined(QQNX_PPS)
+ // Destroy the hardware button notifier
+ delete m_buttonsNotifier;
+
+ // Destroy input context
+ delete m_inputContext;
+#endif
+
+ // Destroy the keyboard class.
+ delete m_virtualKeyboard;
+
// Destroy services class
delete m_services;
@@ -355,10 +362,10 @@ QPlatformWindow *QQnxIntegration::createPlatformWindow(QWindow *window) const
const bool needRootWindow = options() & RootWindow;
switch (surfaceType) {
case QSurface::RasterSurface:
- return new QQnxRasterWindow(window, m_screenContext, needRootWindow);
+ return new QQnxRasterWindow(window, ms_screenContext, needRootWindow);
#if !defined(QT_NO_OPENGL)
case QSurface::OpenGLSurface:
- return new QQnxEglWindow(window, m_screenContext, needRootWindow);
+ return new QQnxEglWindow(window, ms_screenContext, needRootWindow);
#endif
default:
qFatal("QQnxWindow: unsupported window API");
@@ -441,7 +448,7 @@ QPlatformDrag *QQnxIntegration::drag() const
QVariant QQnxIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
{
qIntegrationDebug() << Q_FUNC_INFO;
- if ((hint == ShowIsFullScreen) && (m_options & FullScreenApplication))
+ if ((hint == ShowIsFullScreen) && (ms_options & FullScreenApplication))
return true;
return QPlatformIntegration::styleHint(hint);
@@ -455,15 +462,15 @@ QPlatformServices * QQnxIntegration::services() const
#if defined(Q_OS_BLACKBERRY)
QStringList QQnxIntegration::themeNames() const
{
- return QStringList(QQnxTheme::name());
+ return QStringList(QBlackberryTheme::name());
}
QPlatformTheme *QQnxIntegration::createPlatformTheme(const QString &name) const
{
qIntegrationDebug() << Q_FUNC_INFO << "name =" << name;
- if (name == QQnxTheme::name())
- return new QQnxTheme(this);
- return QPlatformIntegration::createPlatformTheme(name);
+ if (name == QBlackberryTheme::name())
+ return new QBlackberryTheme(this);
+ return 0;
}
#endif
@@ -495,11 +502,10 @@ void QQnxIntegration::createDisplays()
{
qIntegrationDebug() << Q_FUNC_INFO;
// Query number of displays
- errno = 0;
- int displayCount;
- int result = screen_get_context_property_iv(m_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT, &displayCount);
- if (result != 0)
- qFatal("QQnxIntegration: failed to query display count, errno=%d", errno);
+ int displayCount = 0;
+ int result = screen_get_context_property_iv(ms_screenContext, SCREEN_PROPERTY_DISPLAY_COUNT,
+ &displayCount);
+ Q_SCREEN_CRITICALERROR(result, "Failed to query display count");
if (displayCount < 1) {
// Never happens, even if there's no display, libscreen returns 1
@@ -507,23 +513,20 @@ void QQnxIntegration::createDisplays()
}
// Get all displays
- errno = 0;
screen_display_t *displays = (screen_display_t *)alloca(sizeof(screen_display_t) * displayCount);
- result = screen_get_context_property_pv(m_screenContext, SCREEN_PROPERTY_DISPLAYS, (void **)displays);
- if (result != 0)
- qFatal("QQnxIntegration: failed to query displays, errno=%d", errno);
+ result = screen_get_context_property_pv(ms_screenContext, SCREEN_PROPERTY_DISPLAYS,
+ (void **)displays);
+ Q_SCREEN_CRITICALERROR(result, "Failed to query displays");
// If it's primary, we create a QScreen for it even if it's not attached
// since Qt will dereference QGuiApplication::primaryScreen()
createDisplay(displays[0], /*isPrimary=*/true);
for (int i=1; i<displayCount; i++) {
- int isAttached = 0;
- result = screen_get_display_property_iv(displays[i], SCREEN_PROPERTY_ATTACHED, &isAttached);
- if (result != 0) {
- qWarning("QQnxIntegration: failed to query display attachment, errno=%d", errno);
- isAttached = 1; // assume attached
- }
+ int isAttached = 1;
+ result = screen_get_display_property_iv(displays[i], SCREEN_PROPERTY_ATTACHED,
+ &isAttached);
+ Q_SCREEN_CHECKERROR(result, "Failed to query display attachment");
if (!isAttached) {
qIntegrationDebug() << Q_FUNC_INFO << "Skipping non-attached display" << i;
@@ -537,7 +540,7 @@ void QQnxIntegration::createDisplays()
void QQnxIntegration::createDisplay(screen_display_t display, bool isPrimary)
{
- QQnxScreen *screen = new QQnxScreen(m_screenContext, display, isPrimary);
+ QQnxScreen *screen = new QQnxScreen(ms_screenContext, display, isPrimary);
m_screens.append(screen);
screenAdded(screen);
screen->adjustOrientation();
@@ -584,11 +587,25 @@ QQnxScreen *QQnxIntegration::primaryDisplay() const
return m_screens.first();
}
-QQnxIntegration::Options QQnxIntegration::options() const
+QQnxIntegration::Options QQnxIntegration::options()
{
- return m_options;
+ return ms_options;
}
+screen_context_t QQnxIntegration::screenContext()
+{
+ return ms_screenContext;
+}
+
+QQnxNavigatorEventHandler *QQnxIntegration::navigatorEventHandler()
+{
+ return m_navigatorEventHandler;
+}
+
+screen_context_t QQnxIntegration::ms_screenContext = 0;
+
+QQnxIntegration::Options QQnxIntegration::ms_options = 0;
+
bool QQnxIntegration::supportsNavigatorEvents() const
{
// If QQNX_PPS or Q_OS_BLACKBERRY is defined then we have navigator
diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h
index 8b5614fe4f..70c95ae673 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.h
+++ b/src/plugins/platforms/qnx/qqnxintegration.h
@@ -85,7 +85,8 @@ public:
enum Option { // Options to be passed on command line.
NoOptions = 0x0,
FullScreenApplication = 0x1,
- RootWindow = 0x2
+ RootWindow = 0x2,
+ AlwaysFlushScreenContext = 0x4
};
Q_DECLARE_FLAGS(Options, Option)
explicit QQnxIntegration(const QStringList &paramList);
@@ -137,7 +138,10 @@ public:
void createDisplay(screen_display_t display, bool isPrimary);
void removeDisplay(QQnxScreen *screen);
QQnxScreen *primaryDisplay() const;
- Options options() const;
+ static Options options();
+ static screen_context_t screenContext();
+
+ QQnxNavigatorEventHandler *navigatorEventHandler();
private:
void createDisplays();
@@ -146,7 +150,7 @@ private:
static void addWindow(screen_window_t qnxWindow, QWindow *window);
static void removeWindow(screen_window_t qnxWindow);
- screen_context_t m_screenContext;
+ static screen_context_t ms_screenContext;
#if defined(QQNX_SCREENEVENTTHREAD)
QQnxScreenEventThread *m_screenEventThread;
#endif
@@ -176,7 +180,7 @@ private:
static QQnxWindowMapper ms_windowMapper;
static QMutex ms_windowMapperMutex;
- const Options m_options;
+ static Options ms_options;
friend class QQnxWindow;
};
diff --git a/src/plugins/platforms/qnx/qqnxlgmon.cpp b/src/plugins/platforms/qnx/qqnxlgmon.cpp
new file mode 100644
index 0000000000..3c8d1c11a5
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxlgmon.cpp
@@ -0,0 +1,49 @@
+/***************************************************************************
+**
+** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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 "qqnxlgmon.h"
+
+QT_BEGIN_NAMESPACE
+
+bool qqnxLgmonFirstFrame = true;
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/qnx/qqnxlgmon.h b/src/plugins/platforms/qnx/qqnxlgmon.h
new file mode 100644
index 0000000000..e3930ce93a
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxlgmon.h
@@ -0,0 +1,80 @@
+/***************************************************************************
+**
+** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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 QQNXLGMON_H
+#define QQNXLGMON_H
+
+#include <qglobal.h>
+
+#if defined(QQNX_LGMON)
+#include <lgmon.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QQNX_LGMON)
+
+extern bool qqnxLgmonFirstFrame;
+
+inline void qqnxLgmonInit()
+{
+ lgmon_supported(getpid());
+}
+
+inline void qqnxLgmonFramePosted(bool isCover)
+{
+ if (qqnxLgmonFirstFrame && !isCover) {
+ qqnxLgmonFirstFrame = false;
+ lgmon_app_ready_for_user_input(getpid());
+ }
+}
+
+#else
+
+inline void qqnxLgmonInit() {}
+inline void qqnxLgmonFramePosted(bool /*isCover*/) {}
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QQNXLGMON_H
+
diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp
index e468b051cd..a245a0c43a 100644
--- a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp
+++ b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp
@@ -44,6 +44,11 @@
#include "qqnxglcontext.h"
#include "qqnxscreen.h"
#include "qqnxwindow.h"
+#if defined(QQNX_IMF)
+#include "qqnxinputcontext_imf.h"
+#endif
+
+#include "qqnxintegration.h"
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
@@ -51,6 +56,11 @@
QT_BEGIN_NAMESPACE
+QQnxNativeInterface::QQnxNativeInterface(QQnxIntegration *integration)
+ : m_integration(integration)
+{
+}
+
void *QQnxNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
{
if (resource == "windowGroup" && window && window->screen()) {
@@ -75,6 +85,16 @@ void *QQnxNativeInterface::nativeResourceForScreen(const QByteArray &resource, Q
return 0;
}
+void *QQnxNativeInterface::nativeResourceForIntegration(const QByteArray &resource)
+{
+#ifdef Q_OS_BLACKBERRY
+ if (resource == "navigatorEventHandler")
+ return m_integration->navigatorEventHandler();
+#endif
+
+ return 0;
+}
+
void *QQnxNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context)
{
if (resource == "eglcontext" && context)
@@ -85,10 +105,29 @@ void *QQnxNativeInterface::nativeResourceForContext(const QByteArray &resource,
void QQnxNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value)
{
+ QQnxWindow *qnxWindow = static_cast<QQnxWindow*>(window);
+
if (name == QStringLiteral("mmRendererWindowName")) {
- QQnxWindow *qnxWindow = static_cast<QQnxWindow*>(window);
qnxWindow->setMMRendererWindowName(value.toString());
+ } else if (name == QStringLiteral("qnxWindowGroup")) {
+ if (value.isNull())
+ qnxWindow->joinWindowGroup(QByteArray());
+ else if (value.canConvert<QByteArray>())
+ qnxWindow->joinWindowGroup(value.toByteArray());
}
}
+QPlatformNativeInterface::NativeResourceForIntegrationFunction QQnxNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource)
+{
+#if defined(QQNX_IMF)
+ if (resource == "blackberryIMFSetHighlightColor")
+ return reinterpret_cast<NativeResourceForIntegrationFunction>(QQnxInputContext::setHighlightColor);
+ if (resource == "blackberryIMFCheckSpelling")
+ return reinterpret_cast<NativeResourceForIntegrationFunction>(QQnxInputContext::checkSpelling);
+#else
+ Q_UNUSED(resource)
+#endif
+ return 0;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.h b/src/plugins/platforms/qnx/qqnxnativeinterface.h
index dfd386214e..83900791f6 100644
--- a/src/plugins/platforms/qnx/qqnxnativeinterface.h
+++ b/src/plugins/platforms/qnx/qqnxnativeinterface.h
@@ -46,13 +46,22 @@
QT_BEGIN_NAMESPACE
+class QQnxIntegration;
+
class QQnxNativeInterface : public QPlatformNativeInterface
{
public:
+ QQnxNativeInterface(QQnxIntegration *integration);
void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen);
+ void *nativeResourceForIntegration(const QByteArray &resource);
+
void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context);
void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value);
+ NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource);
+
+private:
+ QQnxIntegration *m_integration;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.cpp b/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.cpp
index 30dbb330d7..76d0df4920 100644
--- a/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.cpp
@@ -41,6 +41,9 @@
#include "qqnxnavigatoreventhandler.h"
+#include "qqnxintegration.h"
+#include "qqnxscreen.h"
+
#include <QDebug>
#include <QGuiApplication>
#include <qpa/qwindowsysteminterface.h>
@@ -76,15 +79,8 @@ void QQnxNavigatorEventHandler::handleOrientationChange(int angle)
void QQnxNavigatorEventHandler::handleSwipeDown()
{
qNavigatorEventHandlerDebug() << Q_FUNC_INFO;
- QWindow *w = QGuiApplication::focusWindow();
-
- if (w) {
- // Get the top level window that is ancestor of the focus window
- while (QWindow *parent = w->parent())
- w = parent;
- QWindowSystemInterface::handlePlatformPanelEvent(w);
- }
+ Q_EMIT swipeDown();
}
void QQnxNavigatorEventHandler::handleExit()
diff --git a/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.h b/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.h
index cce3921a27..883d893f5e 100644
--- a/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.h
+++ b/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.h
@@ -65,6 +65,7 @@ Q_SIGNALS:
void windowGroupActivated(const QByteArray &id);
void windowGroupDeactivated(const QByteArray &id);
void windowGroupStateChanged(const QByteArray &id, Qt::WindowState state);
+ void swipeDown();
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp
index 0d8daac0ee..eb9fac540f 100644
--- a/src/plugins/platforms/qnx/qqnxrasterwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxrasterwindow.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+** Copyright (C) 2013 - 2014 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#include "qqnxglobal.h"
+
#include "qqnxrasterwindow.h"
#include "qqnxscreen.h"
@@ -108,10 +110,9 @@ void QQnxRasterWindow::post(const QRegion &dirty)
int dirtyRect[4] = { rect.x(), rect.y(), rect.x() + rect.width(), rect.y() + rect.height() };
// Update the display with contents of render buffer
- errno = 0;
- int result = screen_post_window(nativeHandle(), currentBuffer.nativeBuffer(), 1, dirtyRect, 0);
- if (result != 0)
- qFatal("QQnxWindow: failed to post window buffer, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_post_window(nativeHandle(), currentBuffer.nativeBuffer(), 1, dirtyRect, 0),
+ "Failed to post window");
// Advance to next nender buffer
m_previousBufferIndex = m_currentBufferIndex++;
@@ -122,8 +123,7 @@ void QQnxRasterWindow::post(const QRegion &dirty)
m_previousDirty = dirty;
m_scrolled = QRegion();
- if (m_cover)
- m_cover->updateCover();
+ windowPosted();
}
}
@@ -141,28 +141,23 @@ QQnxBuffer &QQnxRasterWindow::renderBuffer()
// Check if render buffer is invalid
if (m_currentBufferIndex == -1) {
// Get all buffers available for rendering
- errno = 0;
screen_buffer_t buffers[MAX_BUFFER_COUNT];
- int result = screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_RENDER_BUFFERS, (void **)buffers);
- if (result != 0)
- qFatal("QQnxRasterWindow: failed to query window buffers, errno=%d", errno);
+ const int result = screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_RENDER_BUFFERS,
+ (void **)buffers);
+ Q_SCREEN_CRITICALERROR(result, "Failed to query window buffers");
// Wrap each buffer and clear
for (int i = 0; i < MAX_BUFFER_COUNT; ++i) {
m_buffers[i] = QQnxBuffer(buffers[i]);
// Clear Buffer
- errno = 0;
int bg[] = { SCREEN_BLIT_COLOR, 0x00000000, SCREEN_BLIT_END };
- result = screen_fill(screen()->nativeContext(), buffers[i], bg);
- if (result != 0)
- qFatal("QQnxWindow: failed to clear window buffer, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_fill(screen()->nativeContext(), buffers[i], bg),
+ "Failed to clear window buffer");
}
- errno = 0;
- result = screen_flush_blits(screen()->nativeContext(), 0);
- if (result != 0)
- qFatal("QQnxWindow: failed to flush blits, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_flush_blits(screen()->nativeContext(), 0),
+ "Failed to flush blits");
// Use the first available render buffer
m_currentBufferIndex = 0;
@@ -172,11 +167,17 @@ QQnxBuffer &QQnxRasterWindow::renderBuffer()
return m_buffers[m_currentBufferIndex];
}
+void QQnxRasterWindow::setParent(const QPlatformWindow *wnd)
+{
+ QQnxWindow::setParent(wnd);
+ adjustBufferSize();
+}
+
void QQnxRasterWindow::adjustBufferSize()
{
// When having a raster window we don't need any buffers, since
// Qt will draw to the parent TLW backing store.
- const QSize windowSize = m_parentWindow ? QSize(1,1) : window()->size();
+ const QSize windowSize = window()->parent() ? QSize(1,1) : window()->size();
if (windowSize != bufferSize())
setBufferSize(windowSize);
}
@@ -226,20 +227,16 @@ void QQnxRasterWindow::blitPreviousToCurrent(const QRegion &region, int dx, int
SCREEN_BLIT_END };
// Queue blit operation
- errno = 0;
- const int result = screen_blit(m_screenContext, currentBuffer.nativeBuffer(),
- previousBuffer.nativeBuffer(), attribs);
- if (result != 0)
- qFatal("QQnxWindow: failed to blit buffers, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_blit(m_screenContext, currentBuffer.nativeBuffer(),
+ previousBuffer.nativeBuffer(), attribs),
+ "Failed to blit buffers");
}
// Check if flush requested
if (flush) {
// Wait for all blits to complete
- errno = 0;
- const int result = screen_flush_blits(m_screenContext, SCREEN_WAIT_IDLE);
- if (result != 0)
- qFatal("QQnxWindow: failed to flush blits, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_flush_blits(m_screenContext, SCREEN_WAIT_IDLE),
+ "Failed to flush blits");
// Buffer was modified outside the CPU
currentBuffer.invalidateInCache();
diff --git a/src/plugins/platforms/qnx/qqnxrasterwindow.h b/src/plugins/platforms/qnx/qqnxrasterwindow.h
index ad34b3ccf2..2be5f63464 100644
--- a/src/plugins/platforms/qnx/qqnxrasterwindow.h
+++ b/src/plugins/platforms/qnx/qqnxrasterwindow.h
@@ -60,6 +60,8 @@ public:
bool hasBuffers() const { return !bufferSize().isEmpty(); }
+ void setParent(const QPlatformWindow *window);
+
void adjustBufferSize();
protected:
diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp
index 3a0607f214..a6c69164c7 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreen.cpp
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#include "qqnxglobal.h"
+
#include "qqnxscreen.h"
#include "qqnxwindow.h"
#include "qqnxcursor.h"
@@ -75,10 +77,9 @@ QT_BEGIN_NAMESPACE
static QSize determineScreenSize(screen_display_t display, bool primaryScreen) {
int val[2];
- errno = 0;
const int result = screen_get_display_property_iv(display, SCREEN_PROPERTY_PHYSICAL_SIZE, val);
+ Q_SCREEN_CHECKERROR(result, "Failed to query display physical size");
if (result != 0) {
- qFatal("QQnxScreen: failed to query display physical size, errno=%d", errno);
return QSize(150, 90);
}
@@ -163,19 +164,16 @@ QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display,
{
qScreenDebug() << Q_FUNC_INFO;
// Cache initial orientation of this display
- errno = 0;
- int result = screen_get_display_property_iv(m_display, SCREEN_PROPERTY_ROTATION, &m_initialRotation);
- if (result != 0)
- qFatal("QQnxScreen: failed to query display rotation, errno=%d", errno);
+ int result = screen_get_display_property_iv(m_display, SCREEN_PROPERTY_ROTATION,
+ &m_initialRotation);
+ Q_SCREEN_CHECKERROR(result, "Failed to query display rotation");
m_currentRotation = m_initialRotation;
// Cache size of this display in pixels
- errno = 0;
int val[2];
- result = screen_get_display_property_iv(m_display, SCREEN_PROPERTY_SIZE, val);
- if (result != 0)
- qFatal("QQnxScreen: failed to query display size, errno=%d", errno);
+ Q_SCREEN_CRITICALERROR(screen_get_display_property_iv(m_display, SCREEN_PROPERTY_SIZE, val),
+ "Failed to query display size");
m_currentGeometry = m_initialGeometry = QRect(0, 0, val[0], val[1]);
@@ -200,6 +198,9 @@ QQnxScreen::~QQnxScreen()
Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
childWindow->setScreen(0);
+ if (m_coverWindow)
+ m_coverWindow->setScreen(0);
+
delete m_cursor;
}
@@ -505,7 +506,6 @@ void QQnxScreen::raiseWindow(QQnxWindow *window)
if (window != m_coverWindow) {
removeWindow(window);
m_childWindows.push_back(window);
- updateHierarchy();
}
}
@@ -516,7 +516,6 @@ void QQnxScreen::lowerWindow(QQnxWindow *window)
if (window != m_coverWindow) {
removeWindow(window);
m_childWindows.push_front(window);
- updateHierarchy();
}
}
@@ -671,7 +670,7 @@ void QQnxScreen::newWindowCreated(void *window)
// Otherwise, assume that if a foreign window already has a Z-Order both negative and
// less than the default Z-Order installed by mmrender on windows it creates,
// the windows should be treated as an underlay. Otherwise, we treat it as an overlay.
- if (!windowName.isEmpty() && windowName.startsWith("BbVideoWindowControl")) {
+ if (!windowName.isEmpty() && windowName.startsWith("MmRendererVideoWindowControl")) {
addMultimediaWindow(windowName, windowHandle);
} else if (!findWindow(windowHandle)) {
if (zorder <= MAX_UNDERLAY_ZORDER)
@@ -728,8 +727,6 @@ void QQnxScreen::activateWindowGroup(const QByteArray &id)
if (m_coverWindow)
m_coverWindow->setExposed(false);
-
- QWindowSystemInterface::handleWindowActivated(window);
}
void QQnxScreen::deactivateWindowGroup(const QByteArray &id)
@@ -744,8 +741,6 @@ void QQnxScreen::deactivateWindowGroup(const QByteArray &id)
Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
childWindow->setExposed(false);
-
- QWindowSystemInterface::handleWindowActivated(rootWindow()->window());
}
QQnxWindow *QQnxScreen::rootWindow() const
diff --git a/src/plugins/platforms/qnx/qqnxscreen.h b/src/plugins/platforms/qnx/qqnxscreen.h
index 61c47e6c72..d39a210d4b 100644
--- a/src/plugins/platforms/qnx/qqnxscreen.h
+++ b/src/plugins/platforms/qnx/qqnxscreen.h
@@ -80,7 +80,7 @@ public:
int nativeFormat() const { return (depth() == 32) ? SCREEN_FORMAT_RGBA8888 : SCREEN_FORMAT_RGB565; }
screen_display_t nativeDisplay() const { return m_display; }
screen_context_t nativeContext() const { return m_screenContext; }
- const char *windowGroupName() const { return rootWindow()->groupName().constData(); }
+ const char *windowGroupName() const { return m_rootWindow ? m_rootWindow->groupName().constData() : 0; }
QQnxWindow *findWindow(screen_window_t windowHandle);
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventfilter.h b/src/plugins/platforms/qnx/qqnxscreeneventfilter.h
new file mode 100644
index 0000000000..f9ecadd2a9
--- /dev/null
+++ b/src/plugins/platforms/qnx/qqnxscreeneventfilter.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+**
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia 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 QQNXSCREENEVENTFILTER_H
+#define QQNXSCREENEVENTFILTER_H
+
+QT_BEGIN_NAMESPACE
+
+class QQnxScreenEventFilter
+{
+protected:
+ ~QQnxScreenEventFilter() {}
+
+public:
+ virtual bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap, int sequenceId) = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
index 6f06797393..5724fbd92a 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#include "qqnxglobal.h"
+
#include "qqnxscreeneventhandler.h"
#if defined(QQNX_SCREENEVENTTHREAD)
#include "qqnxscreeneventthread.h"
@@ -46,6 +48,7 @@
#include "qqnxintegration.h"
#include "qqnxkeytranslator.h"
#include "qqnxscreen.h"
+#include "qqnxscreeneventfilter.h"
#include <QDebug>
#include <QGuiApplication>
@@ -69,6 +72,7 @@ QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration)
#if defined(QQNX_SCREENEVENTTHREAD)
, m_eventThread(0)
#endif
+ , m_focusLostTimer(-1)
{
// Create a touch device
m_touchDevice = new QTouchDevice;
@@ -90,14 +94,22 @@ QQnxScreenEventHandler::QQnxScreenEventHandler(QQnxIntegration *integration)
}
}
+void QQnxScreenEventHandler::addScreenEventFilter(QQnxScreenEventFilter *filter)
+{
+ m_eventFilters.append(filter);
+}
+
+void QQnxScreenEventHandler::removeScreenEventFilter(QQnxScreenEventFilter *filter)
+{
+ m_eventFilters.removeOne(filter);
+}
+
bool QQnxScreenEventHandler::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("QQNX: failed to query event type, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType),
+ "Failed to query event type");
return handleEvent(event, qnxType);
}
@@ -228,35 +240,44 @@ void QQnxScreenEventHandler::processEventsFromScreenThread()
void QQnxScreenEventHandler::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("QQNX: failed to query event flags, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_FLAGS, &flags),
+ "Failed to query event flags");
// get key code
- errno = 0;
int sym;
- result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SYM, &sym);
- if (result)
- qFatal("QQNX: failed to query event sym, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SYM, &sym),
+ "Failed to query event sym");
int modifiers;
- result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_MODIFIERS, &modifiers);
- if (result)
- qFatal("QQNX: failed to query event modifiers, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_MODIFIERS, &modifiers),
+ "Failed to query event modifieres");
int scan;
- result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SCAN, &scan);
- if (result)
- qFatal("QQNX: failed to query event modifiers, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SCAN, &scan),
+ "Failed to query event scan");
int cap;
- result = screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &cap);
- if (result)
- qFatal("QQNX: failed to query event cap, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &cap),
+ "Failed to query event cap");
+
+ int sequenceId = 0;
+#if defined(Q_OS_BLACKBERRY)
+ Q_SCREEN_CHECKERROR(
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_SEQUENCE_ID, &sequenceId),
+ "Failed to query event seqId");
+#endif
+
+ bool inject = true;
+ Q_FOREACH (QQnxScreenEventFilter *filter, m_eventFilters) {
+ if (filter->handleKeyboardEvent(flags, sym, modifiers, scan, cap, sequenceId)) {
+ inject = false;
+ break;
+ }
+ }
- injectKeyboardEvent(flags, sym, modifiers, scan, cap);
+ if (inject)
+ injectKeyboardEvent(flags, sym, modifiers, scan, cap);
}
void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event)
@@ -266,35 +287,32 @@ void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event)
// Query the window that was clicked
screen_window_t qnxWindow;
void *handle;
- int result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &handle);
- if (result)
- qFatal("QQNX: failed to query event window, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &handle),
+ "Failed to query event window");
qnxWindow = static_cast<screen_window_t>(handle);
// Query the button states
int buttonState = 0;
- result = screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttonState);
- if (result)
- qFatal("QQNX: failed to query event button state, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_BUTTONS, &buttonState),
+ "Failed to query event button state");
// Query the window position
int windowPos[2];
- result = screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos);
- if (result)
- qFatal("QQNX: failed to query event window position, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos),
+ "Failed to query event window position");
// Query the screen position
int pos[2];
- result = screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos);
- if (result)
- qFatal("QQNX: failed to query event position, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos),
+ "Failed to query event position");
// Query the wheel delta
int wheelDelta = 0;
- result = screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheelDelta);
- if (result)
- qFatal("QQNX: failed to query event wheel delta, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_MOUSE_WHEEL, &wheelDelta),
+ "Failed to query event wheel delta");
// Map window handle to top-level QWindow
QWindow *w = QQnxIntegration::window(qnxWindow);
@@ -314,10 +332,6 @@ void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event)
}
}
- // If we don't have a navigator, we don't get activation events.
- if (buttonState && w && w != QGuiApplication::focusWindow() && !m_qnxIntegration->supportsNavigatorEvents())
- QWindowSystemInterface::handleWindowActivated(w);
-
m_lastMouseWindow = qnxWindow;
// Apply scaling to wheel delta and invert value for Qt. We'll probably want to scale
@@ -376,34 +390,36 @@ void QQnxScreenEventHandler::handlePointerEvent(screen_event_t event)
void QQnxScreenEventHandler::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("QQNX: failed to query event position, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_POSITION, pos),
+ "Failed to query event position");
QCursor::setPos(pos[0], pos[1]);
// 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("QQNX: failed to query event window position, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SOURCE_POSITION, windowPos),
+ "Failed to query event window position");
// determine which finger touched
- errno = 0;
int touchId;
- result = screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touchId);
- if (result)
- qFatal("QQNX: failed to query event touch id, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_ID, &touchId),
+ "Failed to query event touch id");
// determine which window was touched
- errno = 0;
void *handle;
- result = screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &handle);
- if (result)
- qFatal("QQNX: failed to query event window, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, &handle),
+ "Failed to query event window");
+
+ errno = 0;
+ int touchArea[2];
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_SIZE, touchArea),
+ "Failed to query event touch area");
+
+ int touchPressure;
+ Q_SCREEN_CHECKERROR(
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_TOUCH_PRESSURE, &touchPressure),
+ "Failed to query event touch pressure");
screen_window_t qnxWindow = static_cast<screen_window_t>(handle);
@@ -439,14 +455,23 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType)
QPointF(static_cast<qreal>(pos[0]) / screenSize.width(),
static_cast<qreal>(pos[1]) / screenSize.height());
- m_touchPoints[touchId].area = QRectF(w->geometry().left() + windowPos[0],
- w->geometry().top() + windowPos[1], 0.0, 0.0);
+ m_touchPoints[touchId].area = QRectF(w->geometry().left() + windowPos[0] - (touchArea[0]>>1),
+ w->geometry().top() + windowPos[1] - (touchArea[1]>>1),
+ (touchArea[0]>>1), (touchArea[1]>>1));
QWindow *parent = w->parent();
while (parent) {
m_touchPoints[touchId].area.translate(parent->geometry().topLeft());
parent = parent->parent();
}
+ //Qt expects the pressure between 0 and 1. There is however no definit upper limit for
+ //the integer value of touch event pressure. The 200 was determined by experiment, it
+ //usually does not get higher than that.
+ m_touchPoints[touchId].pressure = static_cast<qreal>(touchPressure)/200.0;
+ // Can happen, because there is no upper limit for pressure
+ if (m_touchPoints[touchId].pressure > 1)
+ m_touchPoints[touchId].pressure = 1;
+
// determine event type and update state of current touch point
QEvent::Type type = QEvent::None;
switch (qnxType) {
@@ -489,8 +514,9 @@ void QQnxScreenEventHandler::handleTouchEvent(screen_event_t event, int qnxType)
void QQnxScreenEventHandler::handleCloseEvent(screen_event_t event)
{
screen_window_t window = 0;
- if (screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0)
- qFatal("QQnx: failed to query window property, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window),
+ "Failed to query window property");
Q_EMIT windowClosed(window);
@@ -503,8 +529,9 @@ void QQnxScreenEventHandler::handleCloseEvent(screen_event_t event)
void QQnxScreenEventHandler::handleCreateEvent(screen_event_t event)
{
screen_window_t window = 0;
- if (screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window) != 0)
- qFatal("QQnx: failed to query window property, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_get_event_property_pv(event, SCREEN_PROPERTY_WINDOW, (void**)&window),
+ "Failed to query window property");
Q_EMIT newWindowCreated(window);
}
@@ -556,8 +583,9 @@ void QQnxScreenEventHandler::handlePropertyEvent(screen_event_t event)
{
errno = 0;
int objectType;
- if (screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType) != 0)
- qFatal("QQNX: failed to query object type property, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_get_event_property_iv(event, SCREEN_PROPERTY_OBJECT_TYPE, &objectType),
+ "Failed to query object type property");
if (objectType != SCREEN_OBJECT_TYPE_WINDOW)
return;
@@ -589,9 +617,28 @@ void QQnxScreenEventHandler::handleKeyboardFocusPropertyEvent(screen_window_t wi
if (window && screen_get_window_property_iv(window, SCREEN_PROPERTY_KEYBOARD_FOCUS, &focus) != 0)
qFatal("QQnx: failed to query keyboard focus property, errno=%d", errno);
- QWindow *w = focus ? QQnxIntegration::window(window) : 0;
+ QWindow *focusWindow = QQnxIntegration::window(window);
+
+ if (m_focusLostTimer != -1) {
+ killTimer(m_focusLostTimer);
+ m_focusLostTimer = -1;
+ }
+
+ if (focus && focusWindow != QGuiApplication::focusWindow())
+ QWindowSystemInterface::handleWindowActivated(focusWindow);
+ else if (!focus && focusWindow == QGuiApplication::focusWindow())
+ m_focusLostTimer = startTimer(50);
+}
- QWindowSystemInterface::handleWindowActivated(w);
+void QQnxScreenEventHandler::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == m_focusLostTimer) {
+ killTimer(m_focusLostTimer);
+ m_focusLostTimer = -1;
+ event->accept();
+ } else {
+ QObject::timerEvent(event);
+ }
}
#include "moc_qqnxscreeneventhandler.cpp"
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
index 1fdb2c83cd..bab6420cb8 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
+++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.h
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2011 - 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -49,6 +49,7 @@
QT_BEGIN_NAMESPACE
class QQnxIntegration;
+class QQnxScreenEventFilter;
#if defined(QQNX_SCREENEVENTTHREAD)
class QQnxScreenEventThread;
#endif
@@ -59,6 +60,9 @@ class QQnxScreenEventHandler : public QObject
public:
explicit QQnxScreenEventHandler(QQnxIntegration *integration);
+ void addScreenEventFilter(QQnxScreenEventFilter *filter);
+ void removeScreenEventFilter(QQnxScreenEventFilter *filter);
+
bool handleEvent(screen_event_t event);
bool handleEvent(screen_event_t event, int qnxType);
@@ -72,6 +76,9 @@ Q_SIGNALS:
void newWindowCreated(void *window);
void windowClosed(void *window);
+protected:
+ void timerEvent(QTimerEvent *event);
+
#if defined(QQNX_SCREENEVENTTHREAD)
private Q_SLOTS:
void processEventsFromScreenThread();
@@ -99,9 +106,11 @@ private:
screen_window_t m_lastMouseWindow;
QTouchDevice *m_touchDevice;
QWindowSystemInterface::TouchPoint m_touchPoints[MaximumTouchPoints];
+ QList<QQnxScreenEventFilter*> m_eventFilters;
#if defined(QQNX_SCREENEVENTTHREAD)
QQnxScreenEventThread *m_eventThread;
#endif
+ int m_focusLostTimer;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
index 25a597bab9..b66de3cac5 100644
--- a/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
+++ b/src/plugins/platforms/qnx/qqnxscreeneventthread.cpp
@@ -39,6 +39,8 @@
**
****************************************************************************/
+#include "qqnxglobal.h"
+
#include "qqnxscreeneventthread.h"
#include "qqnxscreeneventhandler.h"
@@ -92,30 +94,34 @@ void QQnxScreenEventThread::run()
{
qScreenEventThreadDebug() << Q_FUNC_INFO << "screen event thread started";
+ int errorCounter = 0;
// loop indefinitely
while (!m_quit) {
screen_event_t event;
// create screen event
- errno = 0;
- int result = screen_create_event(&event);
- if (result)
- qFatal("QQNX: failed to create screen event, errno=%d", errno);
-
+ Q_SCREEN_CHECKERROR(screen_create_event(&event), "Failed to create screen event");
// block until screen event is available
- errno = 0;
- result = screen_get_event(m_screenContext, event, -1);
- if (result)
- qFatal("QQNX: failed to get screen event, errno=%d", errno);
+ const int error = screen_get_event(m_screenContext, event, -1);
+ Q_SCREEN_CRITICALERROR(error, "Failed to get screen event");
+ // Only allow 50 consecutive errors before we exit the thread
+ if (error) {
+ errorCounter++;
+ if (errorCounter > 50)
+ m_quit = true;
+
+ screen_destroy_event(event);
+ continue;
+ } else {
+ errorCounter = 0;
+ }
// process received event
// get the event type
- errno = 0;
int qnxType;
- result = screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType);
- if (result)
- qFatal("QQNX: failed to query screen event type, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_get_event_property_iv(event, SCREEN_PROPERTY_TYPE, &qnxType),
+ "Failed to query screen event type");
if (qnxType == SCREEN_EVENT_USER) {
// treat all user events as shutdown requests
@@ -145,25 +151,19 @@ void QQnxScreenEventThread::shutdown()
screen_event_t event;
// create screen event
- errno = 0;
- int result = screen_create_event(&event);
- if (result)
- qFatal("QQNX: failed to create screen event, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_create_event(&event),
+ "Failed to create screen event");
// 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)
- qFatal("QQNX: failed to set screen event type, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_set_event_property_iv(event, SCREEN_PROPERTY_TYPE, &type),
+ "Failed to set screen type");
// 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(m_screenContext, event, getpid());
- if (result)
- qFatal("QQNX: failed to set screen event type, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_send_event(m_screenContext, event, getpid()),
+ "Failed to set screen event type");
// cleanup
screen_destroy_event(event);
diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp b/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp
index 11eb4a5082..08de94a082 100644
--- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp
+++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.cpp
@@ -1,6 +1,6 @@
/***************************************************************************
**
-** Copyright (C) 2012 Research In Motion
+** Copyright (C) 2013 BlackBerry Limited. All rights reserved.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -46,6 +46,9 @@
#include <bps/event.h>
#include <bps/locale.h>
#include <bps/virtualkeyboard.h>
+#if defined(Q_OS_BLACKBERRY)
+#include <bbndk.h>
+#endif
#if defined(QQNXVIRTUALKEYBOARD_DEBUG)
#define qVirtualKeyboardDebug qDebug
@@ -89,7 +92,7 @@ bool QQnxVirtualKeyboardBps::showKeyboard()
// They keyboard's mode is global between applications, we have to set it each time
if ( !isVisible() )
- applyKeyboardMode(keyboardMode());
+ applyKeyboardOptions();
virtualkeyboard_show();
return true;
@@ -102,48 +105,76 @@ bool QQnxVirtualKeyboardBps::hideKeyboard()
return true;
}
-void QQnxVirtualKeyboardBps::applyKeyboardMode(KeyboardMode mode)
+void QQnxVirtualKeyboardBps::applyKeyboardOptions()
{
- virtualkeyboard_layout_t layout = VIRTUALKEYBOARD_LAYOUT_DEFAULT;
+ virtualkeyboard_layout_t layout = keyboardLayout();
+ virtualkeyboard_enter_t enter = enterKey();
- switch (mode) {
- case Url:
- layout = VIRTUALKEYBOARD_LAYOUT_URL;
- break;
+ qVirtualKeyboardDebug() << Q_FUNC_INFO << "mode=" << keyboardMode() << "enterKey=" << enterKeyType();
- case Email:
- layout = VIRTUALKEYBOARD_LAYOUT_EMAIL;
- break;
+ virtualkeyboard_change_options(layout, enter);
+}
+virtualkeyboard_layout_t QQnxVirtualKeyboardBps::keyboardLayout() const
+{
+ switch (keyboardMode()) {
+ case Url:
+ return VIRTUALKEYBOARD_LAYOUT_URL;
+ case Email:
+ return VIRTUALKEYBOARD_LAYOUT_EMAIL;
case Web:
- layout = VIRTUALKEYBOARD_LAYOUT_WEB;
- break;
-
+ return VIRTUALKEYBOARD_LAYOUT_WEB;
case NumPunc:
- layout = VIRTUALKEYBOARD_LAYOUT_NUM_PUNC;
- break;
-
+ return VIRTUALKEYBOARD_LAYOUT_NUM_PUNC;
+ case Number:
+ return VIRTUALKEYBOARD_LAYOUT_NUMBER;
case Symbol:
- layout = VIRTUALKEYBOARD_LAYOUT_SYMBOL;
- break;
-
+ return VIRTUALKEYBOARD_LAYOUT_SYMBOL;
case Phone:
- layout = VIRTUALKEYBOARD_LAYOUT_PHONE;
- break;
-
+ return VIRTUALKEYBOARD_LAYOUT_PHONE;
case Pin:
- layout = VIRTUALKEYBOARD_LAYOUT_PIN;
- break;
-
+ return VIRTUALKEYBOARD_LAYOUT_PIN;
+ case Password:
+ return VIRTUALKEYBOARD_LAYOUT_PASSWORD;
+#if defined(Q_OS_BLACKBERRY)
+#if BBNDK_VERSION_AT_LEAST(10, 2, 1)
+ case Alphanumeric:
+ return VIRTUALKEYBOARD_LAYOUT_ALPHANUMERIC;
+#endif
+#endif
case Default: // fall through
default:
- layout = VIRTUALKEYBOARD_LAYOUT_DEFAULT;
- break;
+ return VIRTUALKEYBOARD_LAYOUT_DEFAULT;
}
- qVirtualKeyboardDebug() << Q_FUNC_INFO << "mode=" << mode;
+ return VIRTUALKEYBOARD_LAYOUT_DEFAULT;
+}
+
+virtualkeyboard_enter_t QQnxVirtualKeyboardBps::enterKey() const
+{
+ switch (enterKeyType()) {
+ case Connect:
+ return VIRTUALKEYBOARD_ENTER_CONNECT;
+ case Done:
+ return VIRTUALKEYBOARD_ENTER_DONE;
+ case Go:
+ return VIRTUALKEYBOARD_ENTER_GO;
+ case Join:
+ return VIRTUALKEYBOARD_ENTER_JOIN;
+ case Next:
+ return VIRTUALKEYBOARD_ENTER_NEXT;
+ case Search:
+ return VIRTUALKEYBOARD_ENTER_SEARCH;
+ case Send:
+ return VIRTUALKEYBOARD_ENTER_SEND;
+ case Submit:
+ return VIRTUALKEYBOARD_ENTER_SUBMIT;
+ case Default: // fall through
+ default:
+ return VIRTUALKEYBOARD_ENTER_DEFAULT;
+ }
- virtualkeyboard_change_options(layout, VIRTUALKEYBOARD_ENTER_DEFAULT);
+ return VIRTUALKEYBOARD_ENTER_DEFAULT;
}
bool QQnxVirtualKeyboardBps::handleLocaleEvent(bps_event_t *event)
diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.h b/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.h
index 43ecb4ecf8..5749deb4e0 100644
--- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.h
+++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardbps.h
@@ -43,6 +43,7 @@
#define QQNXVIRTUALKEYBOARDBPS_H
#include "qqnxabstractvirtualkeyboard.h"
+#include <bps/virtualkeyboard.h>
struct bps_event_t;
@@ -60,11 +61,14 @@ public:
bool hideKeyboard();
protected:
- void applyKeyboardMode(KeyboardMode mode);
+ void applyKeyboardOptions();
private:
bool handleLocaleEvent(bps_event_t *event);
bool handleVirtualKeyboardEvent(bps_event_t *event);
+
+ virtualkeyboard_layout_t keyboardLayout() const;
+ virtualkeyboard_enter_t enterKey() const;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp
index 20fce3da70..2b6ee3d1dc 100644
--- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp
+++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp
@@ -67,9 +67,6 @@ QT_BEGIN_NAMESPACE
const char *QQnxVirtualKeyboardPps::ms_PPSPath = "/pps/services/input/control";
const size_t QQnxVirtualKeyboardPps::ms_bufferSize = 2048;
-// Huge hack for keyboard shadow (see QNX PR 88400). Should be removed ASAP.
-#define KEYBOARD_SHADOW_HEIGHT 8
-
QQnxVirtualKeyboardPps::QQnxVirtualKeyboardPps()
: m_encoder(0),
m_decoder(0),
@@ -91,11 +88,6 @@ void QQnxVirtualKeyboardPps::start()
return;
}
-void QQnxVirtualKeyboardPps::applyKeyboardMode(KeyboardMode mode)
-{
- applyKeyboardModeOptions(mode);
-}
-
void QQnxVirtualKeyboardPps::close()
{
delete m_readNotifier;
@@ -159,18 +151,14 @@ bool QQnxVirtualKeyboardPps::connect()
bool QQnxVirtualKeyboardPps::queryPPSInfo()
{
+ if (!prepareToSend())
+ return false;
+
// Request info, requires id to regenerate res message.
pps_encoder_add_string(m_encoder, "msg", "info");
pps_encoder_add_string(m_encoder, "id", "libWebView");
- if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1) {
- close();
- return false;
- }
-
- pps_encoder_reset(m_encoder);
-
- return true;
+ return writeCurrentPPSEncoder();
}
void QQnxVirtualKeyboardPps::ppsDataReady()
@@ -257,9 +245,6 @@ void QQnxVirtualKeyboardPps::handleKeyboardInfoMessage()
}
const QString countryId = QString::fromLatin1(value);
- // HUGE hack, should be removed ASAP.
- newHeight -= KEYBOARD_SHADOW_HEIGHT; // We want to ignore the 8 pixel shadow above the keyboard. (PR 88400)
-
setHeight(newHeight);
const QLocale locale = QLocale(languageId + QLatin1Char('_') + countryId);
@@ -272,13 +257,12 @@ bool QQnxVirtualKeyboardPps::showKeyboard()
{
qVirtualKeyboardDebug() << Q_FUNC_INFO;
- // Try to connect.
- if (m_fd == -1 && !connect())
+ if (!prepareToSend())
return false;
// NOTE: This must be done everytime the keyboard is shown even if there is no change because
// hiding the keyboard wipes the setting.
- applyKeyboardModeOptions(keyboardMode());
+ applyKeyboardOptions();
if (isVisible())
return true;
@@ -288,140 +272,110 @@ bool QQnxVirtualKeyboardPps::showKeyboard()
// Send the show message.
pps_encoder_add_string(m_encoder, "msg", "show");
- if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1) {
- close();
- return false;
- }
-
- pps_encoder_reset(m_encoder);
-
- // Return true if no error occurs. Sizing response will be triggered when confirmation of
- // the change arrives.
- return true;
+ return writeCurrentPPSEncoder();
}
bool QQnxVirtualKeyboardPps::hideKeyboard()
{
qVirtualKeyboardDebug() << Q_FUNC_INFO;
- if (m_fd == -1 && !connect())
+ if (!prepareToSend())
return false;
pps_encoder_add_string(m_encoder, "msg", "hide");
- if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1) {
- close();
+ return writeCurrentPPSEncoder();
+}
- //Try again.
- if (connect()) {
- if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1) {
- close();
- return false;
- }
- }
- else
- return false;
- }
+bool QQnxVirtualKeyboardPps::prepareToSend()
+{
+ if (m_fd == -1 && !connect())
+ return false;
pps_encoder_reset(m_encoder);
+ return true;
+}
- // Return true if no error occurs. Sizing response will be triggered when confirmation of
- // the change arrives.
+bool QQnxVirtualKeyboardPps::writeCurrentPPSEncoder()
+{
+ if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1) {
+ close();
+ return false;
+ }
return true;
}
-void QQnxVirtualKeyboardPps::applyKeyboardModeOptions(KeyboardMode mode)
+void QQnxVirtualKeyboardPps::applyKeyboardOptions()
{
- // Try to connect.
- if (m_fd == -1 && !connect())
+ if (!prepareToSend())
return;
// Send the options message.
pps_encoder_add_string(m_encoder, "msg", "options");
-
pps_encoder_start_object(m_encoder, "dat");
- switch (mode) {
+
+ pps_encoder_add_string(m_encoder, "enter", enterKeyTypeStr());
+ pps_encoder_add_string(m_encoder, "type", keyboardModeStr());
+
+ pps_encoder_end_object(m_encoder);
+
+ writeCurrentPPSEncoder();
+}
+
+const char* QQnxVirtualKeyboardPps::keyboardModeStr() const
+{
+ switch (keyboardMode()) {
case Url:
- addUrlModeOptions();
- break;
+ return "url";
case Email:
- addEmailModeOptions();
- break;
+ return "email";
case Web:
- addWebModeOptions();
- break;
+ return "web";
case NumPunc:
- addNumPuncModeOptions();
- break;
+ return "num_punc";
+ case Number:
+ return "number";
case Symbol:
- addSymbolModeOptions();
- break;
+ return "symbol";
case Phone:
- addPhoneModeOptions();
- break;
+ return "phone";
case Pin:
- addPinModeOptions();
- break;
+ return "pin";
+ case Password:
+ return "password";
+ case Alphanumeric:
+ return "alphanumeric";
case Default:
- default:
- addDefaultModeOptions();
- break;
+ return "default";
}
- pps_encoder_end_object(m_encoder);
-
- if (::write(m_fd, pps_encoder_buffer(m_encoder), pps_encoder_length(m_encoder)) == -1)
- close();
-
- pps_encoder_reset(m_encoder);
-}
-
-void QQnxVirtualKeyboardPps::addDefaultModeOptions()
-{
- pps_encoder_add_string(m_encoder, "enter", "enter.default");
- pps_encoder_add_string(m_encoder, "type", "default");
+ return "";
}
-void QQnxVirtualKeyboardPps::addUrlModeOptions()
+const char* QQnxVirtualKeyboardPps::enterKeyTypeStr() const
{
- pps_encoder_add_string(m_encoder, "enter", "enter.default");
- pps_encoder_add_string(m_encoder, "type", "url");
-}
-
-void QQnxVirtualKeyboardPps::addEmailModeOptions()
-{
- pps_encoder_add_string(m_encoder, "enter", "enter.default");
- pps_encoder_add_string(m_encoder, "type", "email");
-}
-
-void QQnxVirtualKeyboardPps::addWebModeOptions()
-{
- pps_encoder_add_string(m_encoder, "enter", "enter.default");
- pps_encoder_add_string(m_encoder, "type", "web");
-}
-
-void QQnxVirtualKeyboardPps::addNumPuncModeOptions()
-{
- pps_encoder_add_string(m_encoder, "enter", "enter.default");
- pps_encoder_add_string(m_encoder, "type", "numPunc");
-}
-
-void QQnxVirtualKeyboardPps::addPhoneModeOptions()
-{
- pps_encoder_add_string(m_encoder, "enter", "enter.default");
- pps_encoder_add_string(m_encoder, "type", "phone");
-}
-
-void QQnxVirtualKeyboardPps::addPinModeOptions()
-{
- pps_encoder_add_string(m_encoder, "enter", "enter.default");
- pps_encoder_add_string(m_encoder, "type", "pin");
-}
+ switch (enterKeyType()) {
+ case DefaultReturn:
+ return "enter.default";
+ case Connect:
+ return "enter.connect";
+ case Done:
+ return "enter.done";
+ case Go:
+ return "enter.go";
+ case Join:
+ return "enter.join";
+ case Next:
+ return "enter.next";
+ case Search:
+ return "enter.search";
+ case Send:
+ return "enter.send";
+ case Submit:
+ return "enter.submit";
+ }
-void QQnxVirtualKeyboardPps::addSymbolModeOptions()
-{
- pps_encoder_add_string(m_encoder, "enter", "enter.default");
- pps_encoder_add_string(m_encoder, "type", "symbol");
+ return "";
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.h b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.h
index 6048868b08..2b56d5afbe 100644
--- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.h
+++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.h
@@ -48,6 +48,7 @@
QT_BEGIN_NAMESPACE
+
class QSocketNotifier;
class QQnxVirtualKeyboardPps : public QQnxAbstractVirtualKeyboard
@@ -64,7 +65,7 @@ public Q_SLOTS:
void start();
protected:
- void applyKeyboardMode(KeyboardMode mode);
+ void applyKeyboardOptions();
private Q_SLOTS:
void ppsDataReady();
@@ -76,15 +77,11 @@ private:
bool queryPPSInfo();
void handleKeyboardInfoMessage();
- void applyKeyboardModeOptions(KeyboardMode mode);
- void addDefaultModeOptions();
- void addUrlModeOptions();
- void addEmailModeOptions();
- void addWebModeOptions();
- void addNumPuncModeOptions();
- void addSymbolModeOptions();
- void addPhoneModeOptions();
- void addPinModeOptions();
+ const char* keyboardModeStr() const;
+ const char* enterKeyTypeStr() const;
+
+ bool prepareToSend();
+ bool writeCurrentPPSEncoder();
pps_encoder_t *m_encoder;
pps_decoder_t *m_decoder;
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 99071cf4f2..e43aaa83e8 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -39,9 +39,12 @@
**
****************************************************************************/
+#include "qqnxglobal.h"
+
#include "qqnxwindow.h"
#include "qqnxintegration.h"
#include "qqnxscreen.h"
+#include "qqnxlgmon.h"
#include <QUuid>
@@ -70,39 +73,151 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class QQnxWindow
+ \brief The QQnxWindow is the base class of the various classes used as instances of
+ QPlatformWindow in the QNX QPA plugin.
+
+ The standard properties and methods available in Qt are not a perfect match for the
+ features provided by the QNX screen service. While for the majority of applications
+ the default behavior suffices, some circumstances require greater control over the
+ interaction with screen.
+
+ \section1 Window types
+
+ The QNX QPA plugin can operate in two modes, with or without a root window. The
+ selection of mode is made via the \e rootwindow and \e no-rootwindow options to the
+ plugin. The default mode is rootwindow for BlackBerry builds and no-rootwindow for
+ non-BlackBerry builds.
+
+ Windows with parents are always created as child windows, the difference in the modes
+ is in the treatment of parentless windows. In no-rootwindow mode, these windows are
+ created as application windows while in rootwindow mode, the first window on a screen
+ is created as an application window while subsequent windows are created as child
+ windows. The only exception to this is any window of type Qt::Desktop or Qt::CoverWindow;
+ these are created as application windows, but will never become the root window,
+ even if they are the first window created.
+
+ It is also possible to create a parentless child window. These may be useful to
+ create windows that are parented by windows from other processes. To do this, you
+ attach a dynamic property \e qnxInitialWindowGroup to the QWindow though this must be done
+ prior to the platform window class (this class) being created which typically happens
+ when the window is made visible. When the window is created in QML, it is acceptable
+ to have the \e visible property hardcoded to true so long as the qnxInitialWindowGroup
+ is also set.
+
+ \section1 Joining Window Groups
+
+ Window groups may be joined in a number of ways, some are automatic based on
+ predefined rules though an application is also able to provide explicit control.
+
+ A QWindow that has a parent will join its parent's window group. When rootwindow mode
+ is in effect, all but the first parentless window on a screen will be child windows
+ and join the window group of the first parentless window, the root window.
+
+ If a QWindow has a valid dynamic property called \e qnxInitialWindowGroup at the time the
+ QQnxWindow is created, the window will be created as a child window and, if the
+ qnxInitialWindowGroup property is a non-empty string, an attempt will be made to join that
+ window group. This has an effect only when the QQnxWindow is created, subsequent
+ changes to this property are ignored. Setting the property to an empty string
+ provides a means to create 'top level' child windows without automatically joining
+ any group. Typically when this property is used \e qnxWindowId should be used as well
+ so that the process that owns the window group being joined has some means to
+ identify the window.
+
+ At any point following the creation of the QQnxWindow object, an application can
+ change the window group it has joined. This is done by using the \e
+ setWindowProperty function of the native interface to set the \e qnxWindowGroup property
+ to the desired value, for example:
+
+ \code
+ QQuickView *view = new QQuickView(parent);
+ view->create();
+ QGuiApplication::platformNativeInterface()->setWindowProperty(view->handle(), "qnxWindowGroup",
+ group);
+ \endcode
+
+ To leave the current window group, one passes a null value for the property value,
+ for example:
+
+ \code
+ QQuickView *view = new QQuickView(parent);
+ view->create();
+ QGuiApplication::platformNativeInterface()->setWindowProperty(view->handle(), "qnxWindowGroup",
+ QVariant());
+ \endcode
+
+ \section1 Window Id
+
+ The screen window id string property can be set on a window by assigning the desired
+ value to a dynamic property \e qnxWindowId on the QWindow prior to the QQnxWindow having
+ been created. This is often wanted when one joins a window group belonging to a
+ different process.
+
+*/
QQnxWindow::QQnxWindow(QWindow *window, screen_context_t context, bool needRootWindow)
: QPlatformWindow(window),
m_screenContext(context),
- m_parentWindow(0),
m_window(0),
m_screen(0),
+ m_parentWindow(0),
m_visible(false),
m_exposed(true),
m_windowState(Qt::WindowNoState),
m_mmRendererWindow(0)
{
qWindowDebug() << Q_FUNC_INFO << "window =" << window << ", size =" << window->size();
- int result;
QQnxScreen *platformScreen = static_cast<QQnxScreen *>(window->screen()->handle());
- m_isTopLevel = ( needRootWindow && !platformScreen->rootWindow())
- || (!needRootWindow && !parent())
- || window->type() == Qt::CoverWindow;
+ // If a qnxInitialWindowGroup property is set on the window we'll take this as an
+ // indication that we want to create a child window and join that window group.
+ const QVariant windowGroup = window->property("qnxInitialWindowGroup");
+
+ if (window->type() == Qt::CoverWindow || window->type() == Qt::Desktop) {
+ // Cover windows have to be top level to be accessible to window delegate (i.e. navigator)
+ // Desktop windows also need to be toplevel because they are not
+ // supposed to be part of the window hierarchy tree
+ m_isTopLevel = true;
+ } else if (parent() || windowGroup.isValid()) {
+ // If we have a parent we are a child window. Sometimes we have to be a child even if we
+ // don't have a parent e.g. our parent might be in a different process.
+ m_isTopLevel = false;
+ } else {
+ // We're parentless. If we're not using a root window, we'll always be a top-level window
+ // otherwise only the first window is.
+ m_isTopLevel = !needRootWindow || !platformScreen->rootWindow();
+ }
- errno = 0;
if (m_isTopLevel) {
- result = screen_create_window(&m_window, m_screenContext); // Creates an application window
- if (window->type() != Qt::CoverWindow) {
+ Q_SCREEN_CRITICALERROR(screen_create_window(&m_window, m_screenContext),
+ "Could not create top level window"); // Creates an application window
+ if (window->type() != Qt::CoverWindow && window->type() != Qt::Desktop) {
if (needRootWindow)
platformScreen->setRootWindow(this);
- createWindowGroup();
}
} else {
- result = screen_create_window_type(&m_window, m_screenContext, SCREEN_CHILD_WINDOW);
+ Q_SCREEN_CHECKERROR(
+ screen_create_window_type(&m_window, m_screenContext, SCREEN_CHILD_WINDOW),
+ "Could not create child window");
}
- if (result != 0)
- qFatal("QQnxWindow: failed to create window, errno=%d", errno);
+
+ createWindowGroup();
+
+ // If the window has a qnxWindowId property, set this as the string id property. This generally
+ // needs to be done prior to joining any group as it might be used by the owner of the
+ // group to identify the window.
+ const QVariant windowId = window->property("qnxWindowId");
+ if (windowId.isValid() && windowId.canConvert<QByteArray>()) {
+ QByteArray id = windowId.toByteArray();
+ Q_SCREEN_CHECKERROR(screen_set_window_property_cv(m_window, SCREEN_PROPERTY_ID_STRING,
+ id.size(), id), "Failed to set id");
+ }
+
+ // If a window group has been provided join it now. If it's an empty string that's OK too,
+ // it'll cause us not to join a group (the app will presumably join at some future time).
+ if (windowGroup.isValid() && windowGroup.canConvert<QByteArray>())
+ joinWindowGroup(windowGroup.toByteArray());
}
QQnxWindow::~QQnxWindow()
@@ -127,10 +242,10 @@ QQnxWindow::~QQnxWindow()
void QQnxWindow::setGeometry(const QRect &rect)
{
QRect newGeometry = rect;
- if (screen()->rootWindow() == this) //If this is the root window, it has to be shown fullscreen
+ if (shouldMakeFullScreen())
newGeometry = screen()->geometry();
- const QRect oldGeometry = setGeometryHelper(newGeometry);
+ setGeometryHelper(newGeometry);
// Send a geometry change event to Qt (triggers resizeEvent() in QWindow/QWidget).
@@ -140,71 +255,34 @@ void QQnxWindow::setGeometry(const QRect &rect)
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
QWindowSystemInterface::handleExposeEvent(window(), newGeometry);
QWindowSystemInterface::setSynchronousWindowsSystemEvents(false);
-
- // Now move all children.
- if (!oldGeometry.isEmpty()) {
- const QPoint offset = newGeometry.topLeft() - oldGeometry.topLeft();
- Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
- childWindow->setOffset(offset);
- }
}
-QRect QQnxWindow::setGeometryHelper(const QRect &rect)
+void QQnxWindow::setGeometryHelper(const QRect &rect)
{
qWindowDebug() << Q_FUNC_INFO << "window =" << window()
<< ", (" << rect.x() << "," << rect.y()
<< "," << rect.width() << "," << rect.height() << ")";
// Call base class method
- QRect oldGeometry = QPlatformWindow::geometry();
QPlatformWindow::setGeometry(rect);
// Set window geometry equal to widget geometry
- errno = 0;
int val[2];
val[0] = rect.x();
val[1] = rect.y();
- int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_POSITION, val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window position, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_POSITION, val),
+ "Failed to set window position");
- errno = 0;
val[0] = rect.width();
val[1] = rect.height();
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window size, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SIZE, val),
+ "Failed to set window size");
// Set viewport size equal to window size
- errno = 0;
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window source size, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SOURCE_SIZE, val),
+ "Failed to set window source size");
- return oldGeometry;
-}
-
-void QQnxWindow::setOffset(const QPoint &offset)
-{
- qWindowDebug() << Q_FUNC_INFO << "window =" << window();
- // Move self and then children.
- QRect newGeometry = geometry();
- newGeometry.translate(offset);
-
- // Call the base class
- QPlatformWindow::setGeometry(newGeometry);
-
- int val[2];
-
- errno = 0;
- val[0] = newGeometry.x();
- val[1] = newGeometry.y();
- int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_POSITION, val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window position, errno=%d", errno);
-
- Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
- childWindow->setOffset(offset);
+ screen_flush_context(m_screenContext, 0);
}
void QQnxWindow::setVisible(bool visible)
@@ -214,6 +292,12 @@ void QQnxWindow::setVisible(bool visible)
if (m_visible == visible)
return;
+ // The first time through we join a window group if appropriate.
+ if (m_parentGroupName.isNull() && !m_isTopLevel) {
+ joinWindowGroup(parent() ? static_cast<QQnxWindow*>(parent())->groupName()
+ : QByteArray(m_screen->windowGroupName()));
+ }
+
m_visible = visible;
QQnxWindow *root = this;
@@ -222,8 +306,6 @@ void QQnxWindow::setVisible(bool visible)
root->updateVisibility(root->m_visible);
- window()->requestActivate();
-
QWindowSystemInterface::handleExposeEvent(window(), window()->geometry());
if (visible) {
@@ -238,11 +320,9 @@ void QQnxWindow::updateVisibility(bool parentVisible)
{
qWindowDebug() << Q_FUNC_INFO << "parentVisible =" << parentVisible << "window =" << window();
// Set window visibility
- errno = 0;
int val = (m_visible && parentVisible) ? 1 : 0;
- int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window visibility, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_VISIBLE, &val),
+ "Failed to set window visibility");
Q_FOREACH (QQnxWindow *childWindow, m_childWindows)
childWindow->updateVisibility(m_visible && parentVisible);
@@ -252,14 +332,11 @@ void QQnxWindow::setOpacity(qreal level)
{
qWindowDebug() << Q_FUNC_INFO << "window =" << window() << "opacity =" << level;
// Set window global alpha
- errno = 0;
int val = (int)(level * 255);
- int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_GLOBAL_ALPHA, &val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window global alpha, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_GLOBAL_ALPHA, &val),
+ "Failed to set global alpha");
- // TODO: How to handle children of this window? If we change all the visibilities, then
- // the transparency will look wrong...
+ screen_flush_context(m_screenContext, 0);
}
void QQnxWindow::setExposed(bool exposed)
@@ -282,15 +359,12 @@ void QQnxWindow::setBufferSize(const QSize &size)
qWindowDebug() << Q_FUNC_INFO << "window =" << window() << "size =" << size;
// Set window buffer size
- errno = 0;
-
// libscreen fails when creating empty buffers
const QSize nonEmptySize = size.isEmpty() ? QSize(1, 1) : size;
int val[2] = { nonEmptySize.width(), nonEmptySize.height() };
- int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BUFFER_SIZE, val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window buffer size, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BUFFER_SIZE, val),
+ "Failed to set window buffer size");
// Create window buffers if they do not exist
if (m_bufferSize.isEmpty()) {
@@ -298,24 +372,18 @@ void QQnxWindow::setBufferSize(const QSize &size)
if (val[0] == -1) // The platform GL context was not set yet on the window, so we can't procede
return;
- errno = 0;
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_FORMAT, val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window pixel format, errno=%d", errno);
+ Q_SCREEN_CRITICALERROR(
+ screen_set_window_property_iv(m_window, SCREEN_PROPERTY_FORMAT, val),
+ "Failed to set window format");
- errno = 0;
- result = screen_create_window_buffers(m_window, MAX_BUFFER_COUNT);
- if (result != 0) {
- qWarning() << "QQnxWindow: Buffer size was" << size;
- qFatal("QQnxWindow: failed to create window buffers, errno=%d", errno);
- }
+ Q_SCREEN_CRITICALERROR(screen_create_window_buffers(m_window, MAX_BUFFER_COUNT),
+ "Failed to create window buffers");
// check if there are any buffers available
int bufferCount = 0;
- result = screen_get_window_property_iv(m_window, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &bufferCount);
-
- if (result != 0)
- qFatal("QQnxWindow: failed to query window buffer count, errno=%d", errno);
+ Q_SCREEN_CRITICALERROR(
+ screen_get_window_property_iv(m_window, SCREEN_PROPERTY_RENDER_BUFFER_COUNT, &bufferCount),
+ "Failed to query render buffer count");
if (bufferCount != MAX_BUFFER_COUNT) {
qFatal("QQnxWindow: invalid buffer count. Expected = %d, got = %d. You might experience problems.",
@@ -338,10 +406,8 @@ void QQnxWindow::setBufferSize(const QSize &size)
val[0] = SCREEN_TRANSPARENCY_SOURCE_OVER;
}
- errno = 0;
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window transparency, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, val),
+ "Failed to set window transparency");
// Cache new buffer size
m_bufferSize = nonEmptySize;
@@ -366,9 +432,8 @@ void QQnxWindow::setScreen(QQnxScreen *platformScreen)
if (m_screen) {
qWindowDebug() << Q_FUNC_INFO << "Moving window to different screen";
m_screen->removeWindow(this);
- QQnxIntegration *platformIntegration = static_cast<QQnxIntegration*>(QGuiApplicationPrivate::platformIntegration());
- if ((platformIntegration->options() & QQnxIntegration::RootWindow)) {
+ if ((QQnxIntegration::options() & QQnxIntegration::RootWindow)) {
screen_leave_window_group(m_window);
}
}
@@ -378,25 +443,12 @@ void QQnxWindow::setScreen(QQnxScreen *platformScreen)
platformScreen->addWindow(this);
}
if (m_isTopLevel) {
- // Move window to proper screen/display
- errno = 0;
+ // Move window to proper screen/display
screen_display_t display = platformScreen->nativeDisplay();
- int result = screen_set_window_property_pv(m_window, SCREEN_PROPERTY_DISPLAY, (void **)&display);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window display, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_set_window_property_pv(m_window, SCREEN_PROPERTY_DISPLAY, (void **)&display),
+ "Failed to set window display");
} else {
- errno = 0;
- int result;
- if (!parent()) {
- result = screen_join_window_group(m_window, platformScreen->windowGroupName());
- if (result != 0)
- qFatal("QQnxWindow: failed to join window group, errno=%d", errno);
- } else {
- result = screen_join_window_group(m_window, static_cast<QQnxWindow*>(parent())->groupName().constData());
- if (result != 0)
- qFatal("QQnxWindow: failed to join window group, errno=%d", errno);
- }
-
Q_FOREACH (QQnxWindow *childWindow, m_childWindows) {
// Only subwindows and tooltips need necessarily be moved to another display with the window.
if (window()->type() == Qt::SubWindow || window()->type() == Qt::ToolTip)
@@ -430,6 +482,11 @@ void QQnxWindow::setParent(const QPlatformWindow *window)
if (newParent == m_parentWindow)
return;
+ if (screen()->rootWindow() == this) {
+ qWarning() << "Application window cannot be reparented";
+ return;
+ }
+
removeFromParent();
m_parentWindow = newParent;
@@ -439,12 +496,12 @@ void QQnxWindow::setParent(const QPlatformWindow *window)
setScreen(m_parentWindow->m_screen);
m_parentWindow->m_childWindows.push_back(this);
+ joinWindowGroup(m_parentWindow->groupName());
} else {
m_screen->addWindow(this);
+ joinWindowGroup(QByteArray());
}
- adjustBufferSize();
-
m_screen->updateHierarchy();
}
@@ -478,14 +535,59 @@ void QQnxWindow::lower()
void QQnxWindow::requestActivateWindow()
{
- qWindowDebug() << Q_FUNC_INFO << "window =" << window();
+ QQnxWindow *focusWindow = 0;
+ if (QGuiApplication::focusWindow())
+ focusWindow = static_cast<QQnxWindow*>(QGuiApplication::focusWindow()->handle());
+
+ if (focusWindow == this)
+ return;
+
+ if (screen()->rootWindow() == this ||
+ (focusWindow && findWindow(focusWindow->nativeHandle()))) {
+ // If the focus window is a child, we can just set the focus of our own window
+ // group to our window handle
+ setFocus(nativeHandle());
+ } else {
+ // In order to receive focus the parent's window group has to give focus to the
+ // child. If we have several hierarchy layers, we have to do that several times
+ QQnxWindow *currentWindow = this;
+ QList<QQnxWindow*> windowList;
+ while (currentWindow) {
+ windowList.prepend(currentWindow);
+ // If we find the focus window, we don't have to go further
+ if (currentWindow == focusWindow)
+ break;
+
+ if (currentWindow->parent()){
+ currentWindow = static_cast<QQnxWindow*>(currentWindow->parent());
+ } else if (screen()->rootWindow() &&
+ screen()->rootWindow()->m_windowGroupName == currentWindow->m_parentGroupName) {
+ currentWindow = screen()->rootWindow();
+ } else {
+ currentWindow = 0;
+ }
+ }
+
+ // We have to apply the focus from parent to child windows
+ for (int i = 1; i < windowList.size(); ++i)
+ windowList.at(i-1)->setFocus(windowList.at(i)->nativeHandle());
- // TODO: Tell screen to set keyboard focus to this window.
+ windowList.last()->setFocus(windowList.last()->nativeHandle());
+ }
- // Notify that we gained focus.
- gainedFocus();
+ screen_flush_context(m_screenContext, 0);
}
+void QQnxWindow::setFocus(screen_window_t newFocusWindow)
+{
+ screen_group_t screenGroup = 0;
+ screen_get_window_property_pv(nativeHandle(), SCREEN_PROPERTY_GROUP,
+ reinterpret_cast<void**>(&screenGroup));
+ if (screenGroup) {
+ screen_set_group_property_pv(screenGroup, SCREEN_PROPERTY_KEYBOARD_FOCUS,
+ reinterpret_cast<void**>(&newFocusWindow));
+ }
+}
void QQnxWindow::setWindowState(Qt::WindowState state)
{
@@ -507,14 +609,6 @@ void QQnxWindow::propagateSizeHints()
qWindowDebug() << Q_FUNC_INFO << ": ignored";
}
-void QQnxWindow::gainedFocus()
-{
- qWindowDebug() << Q_FUNC_INFO << "window =" << window();
-
- // Got focus
- QWindowSystemInterface::handleWindowActivated(window());
-}
-
void QQnxWindow::setMMRendererWindowName(const QString &name)
{
m_mmRendererWindowName = name;
@@ -569,43 +663,43 @@ void QQnxWindow::minimize()
void QQnxWindow::setRotation(int rotation)
{
qWindowDebug() << Q_FUNC_INFO << "angle =" << rotation;
- errno = 0;
- int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ROTATION, &rotation);
- if (result != 0)
- qFatal("QQnxRootWindow: failed to set window rotation, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ROTATION, &rotation),
+ "Failed to set window rotation");
}
void QQnxWindow::initWindow()
{
// Alpha channel is always pre-multiplied if present
- errno = 0;
int val = SCREEN_PRE_MULTIPLIED_ALPHA;
- int result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ALPHA_MODE, &val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window alpha mode, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_set_window_property_iv(m_window, SCREEN_PROPERTY_ALPHA_MODE, &val),
+ "Failed to set alpha mode");
// Set the window swap interval
- errno = 0;
val = 1;
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, &val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window swap interval, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SWAP_INTERVAL, &val),
+ "Failed to set swap interval");
if (window()->flags() & Qt::WindowDoesNotAcceptFocus) {
- errno = 0;
val = SCREEN_SENSITIVITY_NO_FOCUS;
- result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val);
- if (result != 0)
- qFatal("QQnxWindow: failed to set window sensitivity, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(
+ screen_set_window_property_iv(m_window, SCREEN_PROPERTY_SENSITIVITY, &val),
+ "Failed to set window sensitivity");
}
- setScreen(static_cast<QQnxScreen *>(window()->screen()->handle()));
+ QQnxScreen *platformScreen = static_cast<QQnxScreen *>(window()->screen()->handle());
+ setScreen(platformScreen);
if (window()->type() == Qt::CoverWindow) {
#if defined(Q_OS_BLACKBERRY) && !defined(Q_OS_BLACKBERRY_TABLET)
- screen_set_window_property_pv(m_screen->rootWindow()->nativeHandle(),
- SCREEN_PROPERTY_ALTERNATE_WINDOW, (void**)&m_window);
- m_cover.reset(new QQnxNavigatorCover);
+ if (platformScreen->rootWindow()) {
+ screen_set_window_property_pv(m_screen->rootWindow()->nativeHandle(),
+ SCREEN_PROPERTY_ALTERNATE_WINDOW, (void**)&m_window);
+ m_cover.reset(new QQnxNavigatorCover);
+ } else {
+ qWarning("No root window for cover window");
+ }
#endif
m_exposed = false;
}
@@ -615,10 +709,12 @@ void QQnxWindow::initWindow()
// Qt never calls these setters after creating the window, so we need to do that ourselves here
setWindowState(window()->windowState());
+ setOpacity(window()->opacity());
+
if (window()->parent() && window()->parent()->handle())
setParent(window()->parent()->handle());
- if (screen()->rootWindow() == this) {
+ if (shouldMakeFullScreen()) {
setGeometryHelper(screen()->geometry());
QWindowSystemInterface::handleGeometryChange(window(), screen()->geometry());
} else {
@@ -632,10 +728,36 @@ void QQnxWindow::createWindowGroup()
m_windowGroupName = QUuid::createUuid().toString().toLatin1();
// Create window group so child windows can be parented by container window
- errno = 0;
- int result = screen_create_window_group(m_window, m_windowGroupName.constData());
- if (result != 0)
- qFatal("QQnxRootWindow: failed to create app window group, errno=%d", errno);
+ Q_SCREEN_CHECKERROR(screen_create_window_group(m_window, m_windowGroupName.constData()),
+ "Failed to create window group");
+}
+
+void QQnxWindow::joinWindowGroup(const QByteArray &groupName)
+{
+ bool changed = false;
+
+ qWindowDebug() << Q_FUNC_INFO << "group:" << groupName;
+
+ if (!groupName.isEmpty()) {
+ if (groupName != m_parentGroupName) {
+ screen_join_window_group(m_window, groupName);
+ m_parentGroupName = groupName;
+ changed = true;
+ }
+ } else {
+ if (!m_parentGroupName.isEmpty()) {
+ screen_leave_window_group(m_window);
+ changed = true;
+ }
+ // By setting to an empty string we'll stop setVisible from trying to
+ // change our group, we want that to happen only if joinWindowGroup has
+ // never been called. This allows windows to be created that are not initially
+ // part of any group.
+ m_parentGroupName = "";
+ }
+
+ if (changed)
+ screen_flush_context(m_screenContext, 0);
}
void QQnxWindow::updateZorder(int &topZorder)
@@ -651,12 +773,9 @@ void QQnxWindow::updateZorder(int &topZorder)
void QQnxWindow::updateZorder(screen_window_t window, int &topZorder)
{
- errno = 0;
- int result = screen_set_window_property_iv(window, SCREEN_PROPERTY_ZORDER, &topZorder);
+ Q_SCREEN_CHECKERROR(screen_set_window_property_iv(window, SCREEN_PROPERTY_ZORDER, &topZorder),
+ "Failed to set window z-order");
topZorder++;
-
- if (result != 0)
- qFatal("QQnxWindow: failed to set window z-order=%d, errno=%d, mWindow=%p", topZorder, errno, window);
}
void QQnxWindow::applyWindowState()
@@ -690,5 +809,17 @@ void QQnxWindow::applyWindowState()
}
}
+void QQnxWindow::windowPosted()
+{
+ if (m_cover)
+ m_cover->updateCover();
+
+ qqnxLgmonFramePosted(m_cover); // for performance measurements
+}
+
+bool QQnxWindow::shouldMakeFullScreen() const
+{
+ return ((screen()->rootWindow() == this) && (QQnxIntegration::options() & QQnxIntegration::FullScreenApplication));
+}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h
index 3c8070b0be..9a2006396f 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.h
+++ b/src/plugins/platforms/qnx/qqnxwindow.h
@@ -78,7 +78,6 @@ public:
WId winId() const { return (WId)m_window; }
screen_window_t nativeHandle() const { return m_window; }
- virtual void adjustBufferSize() = 0;
void setBufferSize(const QSize &size);
QSize bufferSize() const { return m_bufferSize; }
@@ -93,7 +92,6 @@ public:
void propagateSizeHints();
- void gainedFocus();
void setMMRendererWindowName(const QString &name);
void setMMRendererWindow(screen_window_t handle);
void clearMMRendererWindow();
@@ -112,33 +110,36 @@ public:
void setRotation(int rotation);
QByteArray groupName() const { return m_windowGroupName; }
+ void joinWindowGroup(const QByteArray &groupName);
+
+ bool shouldMakeFullScreen() const;
protected:
virtual int pixelFormat() const = 0;
virtual void resetBuffers() = 0;
void initWindow();
+ void windowPosted();
screen_context_t m_screenContext;
- QScopedPointer<QQnxAbstractCover> m_cover;
-
- QQnxWindow *m_parentWindow;
private:
void createWindowGroup();
- QRect setGeometryHelper(const QRect &rect);
+ void setGeometryHelper(const QRect &rect);
void removeFromParent();
- void setOffset(const QPoint &setOffset);
void updateVisibility(bool parentVisible);
void updateZorder(int &topZorder);
void updateZorder(screen_window_t window, int &zOrder);
void applyWindowState();
+ void setFocus(screen_window_t newFocusWindow);
screen_window_t m_window;
QSize m_bufferSize;
QQnxScreen *m_screen;
+ QQnxWindow *m_parentWindow;
QList<QQnxWindow*> m_childWindows;
+ QScopedPointer<QQnxAbstractCover> m_cover;
bool m_visible;
bool m_exposed;
QRect m_unmaximizedGeometry;
@@ -146,7 +147,10 @@ private:
QString m_mmRendererWindowName;
screen_window_t m_mmRendererWindow;
+ // Group name of window group headed by this window
QByteArray m_windowGroupName;
+ // Group name that we have joined or "" if we've not joined any group.
+ QByteArray m_parentGroupName;
bool m_isTopLevel;
};