summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp182
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.h2
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro1
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm3
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm2
-rw-r--r--src/plugins/platforms/direct2d/direct2d.pro1
-rw-r--r--src/plugins/platforms/directfb/directfb.pro1
-rw-r--r--src/plugins/platforms/eglfs/eglfs.pro1
-rw-r--r--src/plugins/platforms/ios/ios.pro1
-rw-r--r--src/plugins/platforms/kms/kms.pro1
-rw-r--r--src/plugins/platforms/linuxfb/linuxfb.pro1
-rw-r--r--src/plugins/platforms/minimal/minimal.pro1
-rw-r--r--src/plugins/platforms/minimalegl/minimalegl.pro1
-rw-r--r--src/plugins/platforms/offscreen/offscreen.pro1
-rw-r--r--src/plugins/platforms/openwfd/openwf.pro1
-rw-r--r--src/plugins/platforms/qnx/qnx.pro1
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp2
-rw-r--r--src/plugins/platforms/windows/windows.pro1
-rw-r--r--src/plugins/platforms/winrt/winrt.pro1
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp13
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp46
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp20
-rw-r--r--src/plugins/platforms/xcb/xcb-plugin.pro1
26 files changed, 243 insertions, 62 deletions
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index 02fda19d76..e255a49ac7 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2012 BogDan Vatra <bogdan@kde.org>
** Contact: http://www.qt-project.org/legal
**
@@ -338,7 +339,7 @@ static JNINativeMethod methods[] = {
QAndroidInputContext::QAndroidInputContext()
- : QPlatformInputContext(), m_blockUpdateSelection(false), m_batchEditNestingLevel(0), m_focusObject(0)
+ : QPlatformInputContext(), m_composingTextStart(-1), m_blockUpdateSelection(false), m_batchEditNestingLevel(0), m_focusObject(0)
{
QtAndroid::AttachedJNIEnv env;
if (!env.jniEnv)
@@ -431,9 +432,24 @@ QAndroidInputContext *QAndroidInputContext::androidInputContext()
return m_androidInputContext;
}
+// cursor position getter that also works with editors that have not been updated to the new API
+static inline int getAbsoluteCursorPosition(const QSharedPointer<QInputMethodQueryEvent> &query)
+{
+ QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
+ return absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt();
+}
+
+// position of the start of the current block
+static inline int getBlockPosition(const QSharedPointer<QInputMethodQueryEvent> &query)
+{
+ QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
+ return absolutePos.isValid() ? absolutePos.toInt() - query->value(Qt::ImCursorPosition).toInt() : 0;
+}
+
void QAndroidInputContext::reset()
{
clear();
+ m_batchEditNestingLevel = 0;
if (qGuiApp->focusObject())
QtAndroidInput::resetSoftwareKeyboard();
else
@@ -449,13 +465,20 @@ void QAndroidInputContext::updateCursorPosition()
{
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (!query.isNull() && !m_blockUpdateSelection && !m_batchEditNestingLevel) {
- // make sure it also works with editors that have not been updated to the new API
- QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
- const int cursorPos = absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt();
+ const int cursorPos = getAbsoluteCursorPosition(query);
const int composeLength = m_composingText.length();
- const int composeStart = composeLength ? cursorPos : -1;
- QtAndroidInput::updateSelection(cursorPos + composeLength, cursorPos + composeLength, //empty selection
- composeStart, composeStart + composeLength); // pre-edit text
+
+ //Q_ASSERT(m_composingText.isEmpty() == (m_composingTextStart == -1));
+ if (m_composingText.isEmpty() != (m_composingTextStart == -1))
+ qWarning() << "Input method out of sync" << m_composingText << m_composingTextStart;
+
+
+ // Qt's idea of the cursor position is the start of the preedit area, so we have to maintain our own preedit cursor pos
+ int realCursorPosition = cursorPos;
+ if (!m_composingText.isEmpty())
+ realCursorPosition = m_composingCursor;
+ QtAndroidInput::updateSelection(realCursorPosition, realCursorPosition, //empty selection
+ m_composingTextStart, m_composingTextStart + composeLength); // pre-edit text
}
}
@@ -529,6 +552,7 @@ bool QAndroidInputContext::isComposing() const
void QAndroidInputContext::clear()
{
m_composingText.clear();
+ m_composingTextStart = -1;
m_extractedText.clear();
}
@@ -569,8 +593,18 @@ jboolean QAndroidInputContext::endBatchEdit()
jboolean QAndroidInputContext::commitText(const QString &text, jint /*newCursorPosition*/)
{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return JNI_FALSE;
+
+
+ const int cursorPos = getAbsoluteCursorPosition(query);
m_composingText = text;
- return finishComposingText();
+ m_composingTextStart = cursorPos;
+ m_composingCursor = cursorPos + text.length();
+ finishComposingText();
+ //### move cursor to newCursorPosition and call updateCursorPosition()
+ return JNI_TRUE;
}
jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint rightLength)
@@ -580,6 +614,7 @@ jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint right
return JNI_TRUE;
m_composingText.clear();
+ m_composingTextStart = -1;
QInputMethodEvent event;
event.setCommitString(QString(), -leftLength, leftLength+rightLength);
@@ -617,7 +652,9 @@ jint QAndroidInputContext::getCursorCapsMode(jint /*reqModes*/)
return res;
}
-const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedText(jint hintMaxChars, jint /*hintMaxLines*/, jint /*flags*/)
+
+
+const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedText(jint /*hintMaxChars*/, jint /*hintMaxLines*/, jint /*flags*/)
{
// Note to self: "if the GET_EXTRACTED_TEXT_MONITOR flag is set, you should be calling
// updateExtractedText(View, int, ExtractedText) whenever you call
@@ -628,28 +665,37 @@ const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedTex
return m_extractedText;
int localPos = query->value(Qt::ImCursorPosition).toInt(); //position before pre-edit text relative to the current block
- QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
- int blockPos = absolutePos.isValid() ? absolutePos.toInt() - localPos : 0; // position of the start of the current block
- QString blockText = query->value(Qt::ImSurroundingText).toString() + m_composingText;
+ int blockPos = getBlockPosition(query);
+ QString blockText = query->value(Qt::ImSurroundingText).toString();
int composeLength = m_composingText.length();
+ if (composeLength > 0) {
+ //Qt doesn't give us the preedit text, so we have to insert it at the correct position
+ int localComposePos = m_composingTextStart - blockPos;
+ blockText = blockText.left(localComposePos) + m_composingText + blockText.mid(localComposePos);
+ }
+
int cpos = localPos + composeLength; //actual cursor pos relative to the current block
int localOffset = 0; // start of extracted text relative to the current block
- if (hintMaxChars) {
- if (cpos > hintMaxChars)
- localOffset = cpos - hintMaxChars;
- m_extractedText.text = blockText.mid(localOffset, hintMaxChars);
- }
- m_extractedText.startOffset = blockPos + localOffset; // "The offset in the overall text at which the extracted text starts."
+ // It is documented that we should try to return hintMaxChars
+ // characters, but that's not what the standard Android controls do, and
+ // there are input methods out there that (surprise) seem to depend on
+ // what happens in reality rather than what's documented.
+
+ m_extractedText.text = blockText;
+ m_extractedText.startOffset = blockPos + localOffset;
const QString &selection = query->value(Qt::ImCurrentSelection).toString();
const int selLen = selection.length();
if (selLen) {
m_extractedText.selectionStart = query->value(Qt::ImAnchorPosition).toInt() - localOffset;
m_extractedText.selectionEnd = m_extractedText.selectionStart + selLen;
- } else {
+ } else if (composeLength > 0) {
+ m_extractedText.selectionStart = m_composingCursor - m_extractedText.startOffset;
+ m_extractedText.selectionEnd = m_composingCursor - m_extractedText.startOffset;
+ } else {
m_extractedText.selectionStart = cpos - localOffset;
m_extractedText.selectionEnd = cpos - localOffset;
}
@@ -668,6 +714,7 @@ QString QAndroidInputContext::getSelectedText(jint /*flags*/)
QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/)
{
+ //### the preedit text could theoretically be after the cursor
QVariant textAfter = queryFocusObjectThreadSafe(Qt::ImTextAfterCursor, QVariant(length));
if (textAfter.isValid()) {
return textAfter.toString().left(length);
@@ -703,15 +750,34 @@ QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
if (!text.length())
return text;
- const int wordLeftPos = cursorPos - length;
- return text.mid(wordLeftPos > 0 ? wordLeftPos : 0, cursorPos) + m_composingText;
+ //### the preedit text does not need to be immediately before the cursor
+ if (cursorPos <= length)
+ return text.left(cursorPos) + m_composingText;
+ else
+ return text.mid(cursorPos - length, length) + m_composingText;
}
+/*
+ Android docs say that this function should remove the current preedit text
+ if any, and replace it with the given text. Any selected text should be
+ removed. The cursor is then moved to newCursorPosition. If > 0, this is
+ relative to the end of the text - 1; if <= 0, this is relative to the start
+ of the text.
+ */
+
jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCursorPosition)
{
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (query.isNull())
+ return JNI_FALSE;
+
+ const int cursorPos = getAbsoluteCursorPosition(query);
if (newCursorPosition > 0)
newCursorPosition += text.length() - 1;
+
m_composingText = text;
+ m_composingTextStart = text.isEmpty() ? -1 : cursorPos;
+ m_composingCursor = cursorPos + newCursorPosition;
QList<QInputMethodEvent::Attribute> attributes;
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
newCursorPosition,
@@ -726,23 +792,26 @@ jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCur
QInputMethodEvent event(m_composingText, attributes);
sendInputMethodEvent(&event);
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
- if (!query.isNull() && !m_blockUpdateSelection && !m_batchEditNestingLevel) {
- QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
- const int cursorPos = absolutePos.isValid() ? absolutePos.toInt() : query->value(Qt::ImCursorPosition).toInt();
- const int preeditLength = text.length();
- QtAndroidInput::updateSelection(cursorPos+preeditLength, cursorPos+preeditLength, -1, -1);
- }
+ updateCursorPosition();
return JNI_TRUE;
}
// Android docs say:
// * start may be after end, same meaning as if swapped
-// * this function must not trigger updateSelection
+// * this function should not trigger updateSelection
// * if start == end then we should stop composing
jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
{
+ // Qt will not include the current preedit text in the query results, and interprets all
+ // parameters relative to the text excluding the preedit. The simplest solution is therefore to
+ // tell Qt that we commit the text before we set the new region. This may cause a little flicker, but is
+ // much more robust than trying to keep the two different world views in sync
+
+ bool wasComposing = !m_composingText.isEmpty();
+ if (wasComposing)
+ finishComposingText();
+
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return JNI_FALSE;
@@ -757,19 +826,23 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
Therefore, the length of the region is end - start
*/
+
int length = end - start;
int localPos = query->value(Qt::ImCursorPosition).toInt();
- QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
- int blockPosition = absolutePos.isValid() ? absolutePos.toInt() - localPos : 0;
+ int blockPosition = getBlockPosition(query);
int localStart = start - blockPosition; // Qt uses position inside block
+ int currentCursor = wasComposing ? m_composingCursor : blockPosition + localPos;
bool updateSelectionWasBlocked = m_blockUpdateSelection;
m_blockUpdateSelection = true;
QString text = query->value(Qt::ImSurroundingText).toString();
+
m_composingText = text.mid(localStart, length);
+ m_composingTextStart = start;
+ m_composingCursor = currentCursor;
- //in the Qt text controls, the cursor position is the start of the preedit
+ //in the Qt text controls, the preedit is defined relative to the cursor position
int relativeStart = localStart - localPos;
QList<QInputMethodEvent::Attribute> attributes;
@@ -781,13 +854,22 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
QVariant(underlined)));
// Keep the cursor position unchanged (don't move to end of preedit)
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, localPos - localStart, length, QVariant()));
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, currentCursor - start, 1, QVariant()));
QInputMethodEvent event(m_composingText, attributes);
event.setCommitString(QString(), relativeStart, length);
sendInputMethodEvent(&event);
m_blockUpdateSelection = updateSelectionWasBlocked;
+
+#ifdef QT_DEBUG_ANDROID_IM_PROTOCOL
+ QSharedPointer<QInputMethodQueryEvent> query2 = focusObjectInputMethodQuery();
+ if (!query2.isNull()) {
+ qDebug() << "Setting. Prev local cpos:" << localPos << "block pos:" <<blockPosition << "comp.start:" << m_composingTextStart << "rel.start:" << relativeStart << "len:" << length << "cpos attr:" << localPos - localStart;
+ qDebug() << "New cursor pos" << getAbsoluteCursorPosition(query2);
+ }
+#endif
+
return JNI_TRUE;
}
@@ -797,18 +879,36 @@ jboolean QAndroidInputContext::setSelection(jint start, jint end)
if (query.isNull())
return JNI_FALSE;
- int localPos = query->value(Qt::ImCursorPosition).toInt();
- QVariant absolutePos = query->value(Qt::ImAbsolutePosition);
- int blockPosition = absolutePos.isValid() ? absolutePos.toInt() - localPos : 0;
+ int blockPosition = getBlockPosition(query);
+ int localCursorPos = start - blockPosition;
QList<QInputMethodEvent::Attribute> attributes;
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
- start - blockPosition,
- end - start,
- QVariant()));
+ if (!m_composingText.isEmpty() && start == end) {
+ // not actually changing the selection; just moving the
+ // preedit cursor
+ int localOldPos = query->value(Qt::ImCursorPosition).toInt();
+ int pos = localCursorPos - localOldPos;
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, pos, 1, QVariant()));
+
+ //but we have to tell Qt about the compose text all over again
+
+ // Show compose text underlined
+ QTextCharFormat underlined;
+ underlined.setFontUnderline(true);
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,0, m_composingText.length(),
+ QVariant(underlined)));
+ m_composingCursor = start;
- QInputMethodEvent event(QString(), attributes);
+ } else {
+ // actually changing the selection
+ attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
+ localCursorPos,
+ end - start,
+ QVariant()));
+ }
+ QInputMethodEvent event(m_composingText, attributes);
sendInputMethodEvent(&event);
+ updateCursorPosition();
return JNI_TRUE;
}
diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h
index 3ce141ae15..a467e4849e 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.h
+++ b/src/plugins/platforms/android/qandroidinputcontext.h
@@ -134,6 +134,8 @@ private slots:
private:
ExtractedText m_extractedText;
QString m_composingText;
+ int m_composingTextStart;
+ int m_composingCursor;
QMetaObject::Connection m_updateCursorPosConnection;
bool m_blockUpdateSelection;
int m_batchEditNestingLevel;
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index a60f4adc28..1f9c0e051d 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -2,6 +2,7 @@ TARGET = qcocoa
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QCocoaIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
OBJECTIVE_SOURCES += main.mm \
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 5def64ee0a..60152b56b2 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -1375,7 +1375,8 @@ QCocoaNSWindow * QCocoaWindow::createNSWindow()
qPlatformWindow:this];
if ((type & Qt::Popup) == Qt::Popup)
[window setHasShadow:YES];
- [window setHidesOnDeactivate: NO];
+
+ [window setHidesOnDeactivate:(type & Qt::Tool) == Qt::Tool];
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 5d20764c87..24a9f6fff0 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -678,9 +678,9 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
return [super mouseDown:theEvent];
m_sendUpAsRightButton = false;
if (m_platformWindow->m_activePopupWindow) {
+ Qt::WindowType type = m_platformWindow->m_activePopupWindow->type();
QWindowSystemInterface::handleCloseEvent(m_platformWindow->m_activePopupWindow);
QWindowSystemInterface::flushWindowSystemEvents();
- Qt::WindowType type = m_platformWindow->m_activePopupWindow->type();
m_platformWindow->m_activePopupWindow = 0;
// Consume the mouse event when closing the popup, except for tool tips
// were it's expected that the event is processed normally.
diff --git a/src/plugins/platforms/direct2d/direct2d.pro b/src/plugins/platforms/direct2d/direct2d.pro
index 4f986b57d7..439d31fb56 100644
--- a/src/plugins/platforms/direct2d/direct2d.pro
+++ b/src/plugins/platforms/direct2d/direct2d.pro
@@ -2,6 +2,7 @@ TARGET = qdirect2d
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QWindowsDirect2DIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT *= core-private
diff --git a/src/plugins/platforms/directfb/directfb.pro b/src/plugins/platforms/directfb/directfb.pro
index ec4a612b52..89d8d42cea 100644
--- a/src/plugins/platforms/directfb/directfb.pro
+++ b/src/plugins/platforms/directfb/directfb.pro
@@ -2,6 +2,7 @@ TARGET = qdirectfb
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QDirectFbIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT += core-private gui-private platformsupport-private
diff --git a/src/plugins/platforms/eglfs/eglfs.pro b/src/plugins/platforms/eglfs/eglfs.pro
index 8827f7680c..3ebe05b35e 100644
--- a/src/plugins/platforms/eglfs/eglfs.pro
+++ b/src/plugins/platforms/eglfs/eglfs.pro
@@ -2,6 +2,7 @@ TARGET = qeglfs
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QEglFSIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
SOURCES += $$PWD/main.cpp
diff --git a/src/plugins/platforms/ios/ios.pro b/src/plugins/platforms/ios/ios.pro
index b7e074b95a..ffc4ff9b12 100644
--- a/src/plugins/platforms/ios/ios.pro
+++ b/src/plugins/platforms/ios/ios.pro
@@ -2,6 +2,7 @@ TARGET = qios
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QIOSIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT += core-private gui-private platformsupport-private
diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro
index 1b3678f13a..baa8778153 100644
--- a/src/plugins/platforms/kms/kms.pro
+++ b/src/plugins/platforms/kms/kms.pro
@@ -2,6 +2,7 @@ TARGET = qkms
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QKmsIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT += core-private gui-private platformsupport-private
diff --git a/src/plugins/platforms/linuxfb/linuxfb.pro b/src/plugins/platforms/linuxfb/linuxfb.pro
index 9e9f9b29b7..389d45c29c 100644
--- a/src/plugins/platforms/linuxfb/linuxfb.pro
+++ b/src/plugins/platforms/linuxfb/linuxfb.pro
@@ -2,6 +2,7 @@ TARGET = qlinuxfb
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QLinuxFbIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT += core-private gui-private platformsupport-private
diff --git a/src/plugins/platforms/minimal/minimal.pro b/src/plugins/platforms/minimal/minimal.pro
index 3131b16232..3ed4d2cdde 100644
--- a/src/plugins/platforms/minimal/minimal.pro
+++ b/src/plugins/platforms/minimal/minimal.pro
@@ -2,6 +2,7 @@ TARGET = qminimal
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QMinimalIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT += core-private gui-private platformsupport-private
diff --git a/src/plugins/platforms/minimalegl/minimalegl.pro b/src/plugins/platforms/minimalegl/minimalegl.pro
index 00c83eb1ca..e78dcb8bc5 100644
--- a/src/plugins/platforms/minimalegl/minimalegl.pro
+++ b/src/plugins/platforms/minimalegl/minimalegl.pro
@@ -2,6 +2,7 @@ TARGET = qminimalegl
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QMinimalEglIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT += core-private gui-private platformsupport-private
diff --git a/src/plugins/platforms/offscreen/offscreen.pro b/src/plugins/platforms/offscreen/offscreen.pro
index 5db5e32e65..94eeac6acc 100644
--- a/src/plugins/platforms/offscreen/offscreen.pro
+++ b/src/plugins/platforms/offscreen/offscreen.pro
@@ -2,6 +2,7 @@ TARGET = qoffscreen
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QOffscreenIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT += core-private gui-private platformsupport-private
diff --git a/src/plugins/platforms/openwfd/openwf.pro b/src/plugins/platforms/openwfd/openwf.pro
index 2dbcb282db..38bac057bd 100644
--- a/src/plugins/platforms/openwfd/openwf.pro
+++ b/src/plugins/platforms/openwfd/openwf.pro
@@ -2,6 +2,7 @@ TARGET = qopenwf
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QOpenWFDIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT += core-private gui-private platformsupport-private
diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro
index 04c6087cd1..856b7d2abe 100644
--- a/src/plugins/platforms/qnx/qnx.pro
+++ b/src/plugins/platforms/qnx/qnx.pro
@@ -161,4 +161,5 @@ include (../../../platformsupport/fontdatabases/fontdatabases.pri)
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QQnxIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index de34663286..78bf833526 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -243,7 +243,7 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
return true;
case ThreadedOpenGL:
#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- return QOpenGLContext::openGLModuleType() != QOpenGLContext::DesktopGL
+ return QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL
? QWindowsEGLContext::hasThreadedOpenGLCapability() : true;
# else
return true;
@@ -308,7 +308,7 @@ QPlatformOpenGLContext
{
qCDebug(lcQpaGl) << __FUNCTION__ << context->format();
#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (QOpenGLContext::openGLModuleType() != QOpenGLContext::DesktopGL) {
+ if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) {
if (d->m_staticEGLContext.isNull()) {
QWindowsEGLStaticContext *staticContext = QWindowsEGLStaticContext::create();
if (!staticContext)
@@ -319,7 +319,7 @@ QPlatformOpenGLContext
}
#endif
#if !defined(QT_OPENGL_ES_2)
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::DesktopGL) {
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
if (d->m_staticOpenGLContext.isNull())
d->m_staticOpenGLContext =
QSharedPointer<QOpenGLStaticContext>(QOpenGLStaticContext::create());
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index 7e15be1d19..06c0122bbb 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -125,7 +125,7 @@ void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resour
return 0;
}
#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (QOpenGLContext::openGLModuleType() != QOpenGLContext::DesktopGL) {
+ if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) {
QWindowsEGLContext *windowsEglContext = static_cast<QWindowsEGLContext *>(context->handle());
if (resource == QByteArrayLiteral("eglDisplay"))
return windowsEglContext->eglDisplay();
@@ -136,7 +136,7 @@ void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resour
}
#endif // QT_OPENGL_ES_2 || QT_OPENGL_DYNAMIC
#if !defined(QT_OPENGL_ES_2)
- if (QOpenGLContext::openGLModuleType() == QOpenGLContext::DesktopGL) {
+ if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
QWindowsGLContext *windowsContext = static_cast<QWindowsGLContext *>(context->handle());
if (resource == QByteArrayLiteral("renderingContext"))
return windowsContext->renderingContext();
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index db06525508..c8eaded38d 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -880,7 +880,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
if (aWindow->surfaceType() == QWindow::OpenGLSurface) {
setFlag(OpenGLSurface);
#if defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_DYNAMIC)
- if (QOpenGLContext::openGLModuleType() != QOpenGLContext::DesktopGL)
+ if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL)
setFlag(OpenGL_ES2);
#endif
}
diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro
index 188bd7917c..cc0373c077 100644
--- a/src/plugins/platforms/windows/windows.pro
+++ b/src/plugins/platforms/windows/windows.pro
@@ -2,6 +2,7 @@ TARGET = qwindows
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QWindowsIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT *= core-private
diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro
index 60c87bb61a..0122bf9475 100644
--- a/src/plugins/platforms/winrt/winrt.pro
+++ b/src/plugins/platforms/winrt/winrt.pro
@@ -12,6 +12,7 @@ winphone {
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QWinRTIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT += core-private gui-private platformsupport-private
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index f5f6c712c5..e3b81c2b40 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -1791,6 +1791,19 @@ bool QXcbConnection::xi2GetValuatorValueIfSet(void *event, int valuatorNum, doub
return true;
}
+bool QXcbConnection::xi2GetButtonState(void *event, int buttonNum)
+{
+ xXIDeviceEvent *xideviceevent = static_cast<xXIDeviceEvent *>(event);
+ unsigned char *buttonsMaskAddr = (unsigned char*)&xideviceevent[1];
+
+ for (int i = 0; i < (xideviceevent->buttons_len * 4); i++) {
+ if (buttonNum < 8)
+ return (buttonsMaskAddr[i] & (1 << buttonNum));
+ buttonNum -= 8;
+ }
+ return false;
+}
+
// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
// - "pad0" became "extension"
// - "pad1" and "pad" became "pad0"
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 13a0280baf..1933b89a19 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -402,6 +402,12 @@ public:
#elif defined(XCB_USE_XINPUT2)
void xi2Select(xcb_window_t window);
#endif
+#ifdef XCB_USE_XINPUT21
+ bool isUsingXInput21() { return m_xi2Enabled && m_xi2Minor >= 1; }
+#else
+ bool isUsingXInput21() { return false; }
+#endif
+
void sync();
void flush() { xcb_flush(m_connection); }
@@ -511,11 +517,12 @@ private:
QVector<TabletData> m_tabletData;
#endif
struct ScrollingDevice {
- ScrollingDevice() : deviceId(0), verticalIndex(0), horizontalIndex(0), orientations(0) { }
+ ScrollingDevice() : deviceId(0), verticalIndex(0), horizontalIndex(0), orientations(0), legacyOrientations(0) { }
int deviceId;
int verticalIndex, horizontalIndex;
double verticalIncrement, horizontalIncrement;
Qt::Orientations orientations;
+ Qt::Orientations legacyOrientations;
QPointF lastScrollPosition;
};
void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice);
@@ -525,6 +532,7 @@ private:
#if defined(XCB_USE_XINPUT2) || defined(XCB_USE_XINPUT2_MAEMO)
static bool xi2GetValuatorValueIfSet(void *event, int valuatorNum, double *value);
static bool xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode);
+ static bool xi2GetButtonState(void *event, int buttonNum);
#endif
xcb_connection_t *m_connection;
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index d7b3c75aee..831ccba6f6 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -134,7 +134,6 @@ void QXcbConnection::initializeXInput2()
#ifdef XCB_USE_XINPUT21
case XIScrollClass: {
XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(devices[i].classes[c]);
- scrollingDevice.deviceId = devices[i].deviceid;
if (sci->scroll_type == XIScrollTypeVertical) {
scrollingDevice.orientations |= Qt::Vertical;
scrollingDevice.verticalIndex = sci->number;
@@ -147,6 +146,20 @@ void QXcbConnection::initializeXInput2()
}
break;
}
+ case XIButtonClass: {
+ XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(devices[i].classes[c]);
+ for (int i=0; i < bci->num_buttons; ++i) {
+ const int buttonAtom = qatom(bci->labels[i]);
+ if (buttonAtom == QXcbAtom::ButtonWheelUp
+ || buttonAtom == QXcbAtom::ButtonWheelDown) {
+ scrollingDevice.legacyOrientations |= Qt::Vertical;
+ } else if (buttonAtom == QXcbAtom::ButtonHorizWheelLeft
+ || buttonAtom == QXcbAtom::ButtonHorizWheelRight) {
+ scrollingDevice.legacyOrientations |= Qt::Horizontal;
+ }
+ }
+ break;
+ }
#endif
default:
break;
@@ -170,7 +183,10 @@ void QXcbConnection::initializeXInput2()
#endif // QT_NO_TABLETEVENT
#ifdef XCB_USE_XINPUT21
- if (scrollingDevice.orientations) {
+ if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) {
+ scrollingDevice.deviceId = devices[i].deviceid;
+ // Only use legacy wheel button events when we don't have real scroll valuators.
+ scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations;
m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice);
if (Q_UNLIKELY(debug_xinput_devices))
qDebug() << " it's a scrolling device";
@@ -256,6 +272,7 @@ void QXcbConnection::xi2Select(xcb_window_t window)
if (!m_scrollingDevices.isEmpty()) {
QVector<XIEventMask> xiEventMask(m_scrollingDevices.size());
bitMask = XI_MotionMask;
+ bitMask |= XI_ButtonReleaseMask;
int i=0;
Q_FOREACH (const ScrollingDevice& scrollingDevice, m_scrollingDevices) {
xiEventMask[i].deviceid = scrollingDevice.deviceId;
@@ -595,6 +612,31 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiEvent->time, local, global, rawDelta, angleDelta, modifiers);
}
}
+ } else if (xiEvent->evtype == XI_ButtonRelease) {
+ xXIDeviceEvent* xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event);
+ if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) {
+ QPoint angleDelta;
+ if (scrollingDevice.legacyOrientations & Qt::Vertical) {
+ if (xi2GetButtonState(xiDeviceEvent, 4))
+ angleDelta.setY(120);
+ else if (xi2GetButtonState(xiDeviceEvent, 5))
+ angleDelta.setY(-120);
+ }
+ if (scrollingDevice.legacyOrientations & Qt::Horizontal) {
+ if (xi2GetButtonState(xiDeviceEvent, 6))
+ angleDelta.setX(120);
+ if (xi2GetButtonState(xiDeviceEvent, 7))
+ angleDelta.setX(-120);
+ }
+ if (!angleDelta.isNull()) {
+ QPoint local(fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y));
+ QPoint global(fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y));
+ Qt::KeyboardModifiers modifiers = keyboard()->translateModifiers(xiDeviceEvent->mods.effective_mods);
+ if (modifiers & Qt::AltModifier)
+ std::swap(angleDelta.rx(), angleDelta.ry());
+ QWindowSystemInterface::handleWheelEvent(platformWindow->window(), xiEvent->time, local, global, QPoint(), angleDelta, modifiers);
+ }
+ }
}
#else
Q_UNUSED(event);
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index fb9c03b66d..3645b6469a 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1771,16 +1771,16 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
if (isWheel) {
-#ifndef XCB_USE_XINPUT21
- // Logic borrowed from qapplication_x11.cpp
- int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1);
- bool hor = (((event->detail == 4 || event->detail == 5)
- && (modifiers & Qt::AltModifier))
- || (event->detail == 6 || event->detail == 7));
-
- QWindowSystemInterface::handleWheelEvent(window(), event->time,
- local, global, delta, hor ? Qt::Horizontal : Qt::Vertical, modifiers);
-#endif
+ if (!connection()->isUsingXInput21()) {
+ // Logic borrowed from qapplication_x11.cpp
+ int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1);
+ bool hor = (((event->detail == 4 || event->detail == 5)
+ && (modifiers & Qt::AltModifier))
+ || (event->detail == 6 || event->detail == 7));
+
+ QWindowSystemInterface::handleWheelEvent(window(), event->time,
+ local, global, delta, hor ? Qt::Horizontal : Qt::Vertical, modifiers);
+ }
return;
}
diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro
index 9e4e997f55..a52aaa4a2e 100644
--- a/src/plugins/platforms/xcb/xcb-plugin.pro
+++ b/src/plugins/platforms/xcb/xcb-plugin.pro
@@ -2,6 +2,7 @@ TARGET = qxcb
PLUGIN_TYPE = platforms
PLUGIN_CLASS_NAME = QXcbIntegrationPlugin
+!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = -
load(qt_plugin)
QT += core-private gui-private platformsupport-private