summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2019-07-11 17:17:13 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2019-07-11 17:17:51 +0200
commit4dac45c9ee59ff6586d90d423654da91523ab679 (patch)
treecd4a4adf2cbc9e77bf86d2d11e71ec66afdf3be4 /src/plugins/platforms
parent078cd61751aeaa310d35a3d596a21a36004a1a0f (diff)
parentf44850b5c3464cdda0ee9b1ee858d95f3ffaa3e2 (diff)
Merge remote-tracking branch 'origin/wip/qt6' into wip/cmake
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/android/androidjnimenu.cpp4
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.cpp4
-rw-r--r--src/plugins/platforms/android/qandroideventdispatcher.h2
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp767
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.h6
-rw-r--r--src/plugins/platforms/android/qandroidplatformtheme.cpp2
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp5
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm24
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm31
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaglcontext.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm19
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.h4
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm10
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoansmenu.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.h5
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm62
-rw-r--r--src/plugins/platforms/cocoa/qcocoavulkaninstance.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm20
-rw-r--r--src/plugins/platforms/cocoa/qnsview_mouse.mm7
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h7
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp20
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h1
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp22
-rw-r--r--src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp2
-rw-r--r--src/plugins/platforms/ios/quiview_accessibility.mm8
-rw-r--r--src/plugins/platforms/wasm/qwasmbackingstore.cpp6
-rw-r--r--src/plugins/platforms/wasm/qwasmbackingstore.h1
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.cpp36
-rw-r--r--src/plugins/platforms/wasm/qwasmcompositor.h1
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp31
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.h2
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp32
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.h2
-rw-r--r--src/plugins/platforms/wasm/qwasmoffscreensurface.cpp41
-rw-r--r--src/plugins/platforms/wasm/qwasmoffscreensurface.h49
-rw-r--r--src/plugins/platforms/wasm/qwasmopenglcontext.cpp59
-rw-r--r--src/plugins/platforms/wasm/qwasmopenglcontext.h6
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.cpp5
-rw-r--r--src/plugins/platforms/wasm/qwasmscreen.h1
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.cpp6
-rw-r--r--src/plugins/platforms/wasm/qwasmwindow.h1
-rw-r--r--src/plugins/platforms/wasm/wasm.pro6
-rw-r--r--src/plugins/platforms/windows/qwin10helpers.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsbackingstore.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp30
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp17
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsservices.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp24
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp4
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp6
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp6
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp2
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp8
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp6
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp20
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h4
81 files changed, 1052 insertions, 553 deletions
diff --git a/src/plugins/platforms/android/androidjnimenu.cpp b/src/plugins/platforms/android/androidjnimenu.cpp
index 6f548aba52..f51a3920b8 100644
--- a/src/plugins/platforms/android/androidjnimenu.cpp
+++ b/src/plugins/platforms/android/androidjnimenu.cpp
@@ -60,12 +60,12 @@ namespace QtAndroidMenu
{
static QList<QAndroidPlatformMenu *> pendingContextMenus;
static QAndroidPlatformMenu *visibleMenu = 0;
- static QMutex visibleMenuMutex(QMutex::Recursive);
+ static QRecursiveMutex visibleMenuMutex;
static QSet<QAndroidPlatformMenuBar *> menuBars;
static QAndroidPlatformMenuBar *visibleMenuBar = 0;
static QWindow *activeTopLevelWindow = 0;
- static QMutex menuBarMutex(QMutex::Recursive);
+ static QRecursiveMutex menuBarMutex;
static jmethodID openContextMenuMethodID = 0;
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp
index e12551283f..3a1fb7a6de 100644
--- a/src/plugins/platforms/android/qandroideventdispatcher.cpp
+++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp
@@ -78,14 +78,14 @@ void QAndroidEventDispatcher::stop()
void QAndroidEventDispatcher::goingToStop(bool stop)
{
- m_goingToStop.store(stop ? 1 : 0);
+ m_goingToStop.storeRelaxed(stop ? 1 : 0);
if (!stop)
wakeUp();
}
bool QAndroidEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
{
- if (m_goingToStop.load())
+ if (m_goingToStop.loadRelaxed())
flags |= QEventLoop::ExcludeSocketNotifiers | QEventLoop::X11ExcludeTimers;
{
diff --git a/src/plugins/platforms/android/qandroideventdispatcher.h b/src/plugins/platforms/android/qandroideventdispatcher.h
index e6f903bced..4fdd7af7a5 100644
--- a/src/plugins/platforms/android/qandroideventdispatcher.h
+++ b/src/plugins/platforms/android/qandroideventdispatcher.h
@@ -68,7 +68,7 @@ class QAndroidEventDispatcherStopper
{
public:
static QAndroidEventDispatcherStopper *instance();
- static bool stopped() {return !instance()->m_started.load(); }
+ static bool stopped() {return !instance()->m_started.loadRelaxed(); }
void startAll();
void stopAll();
void addEventDispatcher(QAndroidEventDispatcher *dispatcher);
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index db40c30d7d..5614d3b04f 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -64,29 +64,33 @@
QT_BEGIN_NAMESPACE
-template <typename T>
-class ScopedValueChangeBack
+namespace {
+
+class BatchEditLock
{
public:
- ScopedValueChangeBack(T &variable, T newValue)
- : m_oldValue(variable),
- m_variable(variable)
- {
- m_variable = newValue;
- }
- inline void setOldValue()
+
+ explicit BatchEditLock(QAndroidInputContext *context)
+ : m_context(context)
{
- m_variable = m_oldValue;
+ m_context->beginBatchEdit();
}
- ~ScopedValueChangeBack()
+
+ ~BatchEditLock()
{
- setOldValue();
+ m_context->endBatchEdit();
}
+
+ BatchEditLock(const BatchEditLock &) = delete;
+ BatchEditLock &operator=(const BatchEditLock &) = delete;
+
private:
- T m_oldValue;
- T &m_variable;
+
+ QAndroidInputContext *m_context;
};
+} // namespace anonymous
+
static QAndroidInputContext *m_androidInputContext = 0;
static char const *const QtNativeInputConnectionClassName = "org/qtproject/qt5/android/QtNativeInputConnection";
static char const *const QtExtractedTextClassName = "org/qtproject/qt5/android/QtExtractedText";
@@ -423,8 +427,12 @@ static QRect inputItemRectangle()
}
QAndroidInputContext::QAndroidInputContext()
- : QPlatformInputContext(), m_composingTextStart(-1), m_blockUpdateSelection(false),
- m_handleMode(Hidden), m_batchEditNestingLevel(0), m_focusObject(0)
+ : QPlatformInputContext()
+ , m_composingTextStart(-1)
+ , m_composingCursor(-1)
+ , m_handleMode(Hidden)
+ , m_batchEditNestingLevel(0)
+ , m_focusObject(0)
{
jclass clazz = QJNIEnvironmentPrivate::findClass(QtNativeInputConnectionClassName);
if (Q_UNLIKELY(!clazz)) {
@@ -550,6 +558,7 @@ static inline int getBlockPosition(const QSharedPointer<QInputMethodQueryEvent>
void QAndroidInputContext::reset()
{
+ focusObjectStopComposing();
clear();
m_batchEditNestingLevel = 0;
m_handleMode = Hidden;
@@ -565,13 +574,13 @@ void QAndroidInputContext::reset()
void QAndroidInputContext::commit()
{
- finishComposingText();
+ focusObjectStopComposing();
}
void QAndroidInputContext::updateCursorPosition()
{
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
- if (!query.isNull() && !m_blockUpdateSelection && !m_batchEditNestingLevel) {
+ if (!query.isNull() && m_batchEditNestingLevel == 0) {
const int cursorPos = getAbsoluteCursorPosition(query);
const int composeLength = m_composingText.length();
@@ -579,24 +588,29 @@ void QAndroidInputContext::updateCursorPosition()
if (m_composingText.isEmpty() != (m_composingTextStart == -1))
qWarning() << "Input method out of sync" << m_composingText << m_composingTextStart;
- int realCursorPosition = cursorPos;
- int realAnchorPosition = cursorPos;
+ int realSelectionStart = cursorPos;
+ int realSelectionEnd = cursorPos;
int cpos = query->value(Qt::ImCursorPosition).toInt();
int anchor = query->value(Qt::ImAnchorPosition).toInt();
if (cpos != anchor) {
if (!m_composingText.isEmpty()) {
qWarning("Selecting text while preediting may give unpredictable results.");
- finishComposingText();
+ focusObjectStopComposing();
}
int blockPos = getBlockPosition(query);
- realCursorPosition = blockPos + cpos;
- realAnchorPosition = blockPos + anchor;
+ realSelectionStart = blockPos + cpos;
+ realSelectionEnd = blockPos + anchor;
}
// Qt's idea of the cursor position is the start of the preedit area, so we maintain our own preedit cursor pos
- if (!m_composingText.isEmpty())
- realCursorPosition = realAnchorPosition = m_composingCursor;
- QtAndroidInput::updateSelection(realCursorPosition, realAnchorPosition,
+ if (focusObjectIsComposing())
+ realSelectionStart = realSelectionEnd = m_composingCursor;
+
+ // Some keyboards misbahave when selStart > selEnd
+ if (realSelectionStart > realSelectionEnd)
+ std::swap(realSelectionStart, realSelectionEnd);
+
+ QtAndroidInput::updateSelection(realSelectionStart, realSelectionEnd,
m_composingTextStart, m_composingTextStart + composeLength); // pre-edit text
}
}
@@ -666,13 +680,11 @@ void QAndroidInputContext::updateSelectionHandles()
*/
void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y)
{
- if (m_batchEditNestingLevel.load() || m_blockUpdateSelection) {
+ if (m_batchEditNestingLevel != 0) {
qWarning() << "QAndroidInputContext::handleLocationChanged returned";
return;
}
- finishComposingText();
-
auto im = qGuiApp->inputMethod();
auto leftRect = im->cursorRectangle();
// The handle is down of the cursor, but we want the position in the middle.
@@ -682,63 +694,96 @@ void QAndroidInputContext::handleLocationChanged(int handleId, int x, int y)
: QHighDpiScaling::factor(QtAndroid::androidPlatformIntegration()->screen());
QPointF point(x / pixelDensity, y / pixelDensity);
point.setY(point.y() - leftRect.width() / 2);
- if (handleId == 1) {
- setSelectionOnFocusObject(point, point);
- return;
- }
- QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition | Qt::ImCurrentSelection);
+ QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition
+ | Qt::ImAbsolutePosition | Qt::ImCurrentSelection);
QCoreApplication::sendEvent(m_focusObject, &query);
int cpos = query.value(Qt::ImCursorPosition).toInt();
int anchor = query.value(Qt::ImAnchorPosition).toInt();
- bool rtl = query.value(Qt::ImCurrentSelection).toString().isRightToLeft();
auto rightRect = im->anchorRectangle();
if (cpos > anchor)
std::swap(leftRect, rightRect);
- auto checkLeftHandle = [&rightRect](QPointF &handlePos) {
- if (handlePos.y() > rightRect.center().y())
- handlePos.setY(rightRect.center().y()); // adjust Y handle pos
- if (handlePos.y() >= rightRect.y() && handlePos.y() <= rightRect.bottom() && handlePos.x() >= rightRect.x())
- return false; // same line and wrong X pos ?
- return true;
- };
-
- auto checkRtlRightHandle = [&rightRect](QPointF &handlePos) {
- if (handlePos.y() > rightRect.center().y())
- handlePos.setY(rightRect.center().y()); // adjust Y handle pos
- if (handlePos.y() >= rightRect.y() && handlePos.y() <= rightRect.bottom() && rightRect.x() >= handlePos.x())
- return false; // same line and wrong X pos ?
- return true;
- };
-
- auto checkRightHandle = [&leftRect](QPointF &handlePos) {
- if (handlePos.y() < leftRect.center().y())
- handlePos.setY(leftRect.center().y()); // adjust Y handle pos
- if (handlePos.y() >= leftRect.y() && handlePos.y() <= leftRect.bottom() && leftRect.x() >= handlePos.x())
- return false; // same line and wrong X pos ?
- return true;
- };
-
- auto checkRtlLeftHandle = [&leftRect](QPointF &handlePos) {
- if (handlePos.y() < leftRect.center().y())
- handlePos.setY(leftRect.center().y()); // adjust Y handle pos
- if (handlePos.y() >= leftRect.y() && handlePos.y() <= leftRect.bottom() && handlePos.x() >= leftRect.x())
- return false; // same line and wrong X pos ?
- return true;
- };
-
- if (handleId == 2) {
- QPointF rightPoint(rightRect.center());
- if ((!rtl && !checkLeftHandle(point)) || (rtl && !checkRtlRightHandle(point)))
- return;
- setSelectionOnFocusObject(point, rightPoint);
+ // Do not allow dragging left handle below right handle, or right handle above left handle
+ if (handleId == 2 && point.y() > rightRect.center().y()) {
+ point.setY(rightRect.center().y());
+ } else if (handleId == 3 && point.y() < leftRect.center().y()) {
+ point.setY(leftRect.center().y());
+ }
+
+ const QPointF pointLocal = im->inputItemTransform().inverted().map(point);
+ bool ok;
+ const int handlePos =
+ QInputMethod::queryFocusObject(Qt::ImCursorPosition, pointLocal).toInt(&ok);
+ if (!ok)
+ return;
+
+ int newCpos = cpos;
+ int newAnchor = anchor;
+ if (newAnchor > newCpos)
+ std::swap(newAnchor, newCpos);
+
+ if (handleId == 1) {
+ newCpos = handlePos;
+ newAnchor = handlePos;
+ } else if (handleId == 2) {
+ newAnchor = handlePos;
} else if (handleId == 3) {
- QPointF leftPoint(leftRect.center());
- if ((!rtl && !checkRightHandle(point)) || (rtl && !checkRtlLeftHandle(point)))
+ newCpos = handlePos;
+ }
+
+ /*
+ Do not allow clearing selection by dragging selection handles and do not allow swapping
+ selection handles for consistency with Android's native text editing controls. Ensure that at
+ least one symbol remains selected.
+ */
+ if ((handleId == 2 || handleId == 3) && newCpos <= newAnchor) {
+ QTextBoundaryFinder finder(QTextBoundaryFinder::Grapheme,
+ query.value(Qt::ImCurrentSelection).toString());
+
+ const int oldSelectionStartPos = qMin(cpos, anchor);
+
+ if (handleId == 2) {
+ finder.toEnd();
+ finder.toPreviousBoundary();
+ newAnchor = finder.position() + oldSelectionStartPos;
+ } else {
+ finder.toStart();
+ finder.toNextBoundary();
+ newCpos = finder.position() + oldSelectionStartPos;
+ }
+ }
+
+ // Check if handle has been dragged far enough
+ if (!focusObjectIsComposing() && newCpos == cpos && newAnchor == anchor)
+ return;
+
+ /*
+ If the editor is currently in composing state, we have to compare newCpos with
+ m_composingCursor instead of cpos. And since there is nothing to compare with newAnchor, we
+ perform the check only when user drags the cursor handle.
+ */
+ if (focusObjectIsComposing() && handleId == 1) {
+ int absoluteCpos = query.value(Qt::ImAbsolutePosition).toInt(&ok);
+ if (!ok)
+ absoluteCpos = cpos;
+ const int blockPos = absoluteCpos - cpos;
+
+ if (blockPos + newCpos == m_composingCursor)
return;
- setSelectionOnFocusObject(leftPoint, point);
}
+
+ BatchEditLock batchEditLock(this);
+
+ focusObjectStopComposing();
+
+ QList<QInputMethodEvent::Attribute> attributes;
+ attributes.append({ QInputMethodEvent::Selection, newAnchor, newCpos - newAnchor });
+ if (newCpos != newAnchor)
+ attributes.append({ QInputMethodEvent::Cursor, 0, 0 });
+
+ QInputMethodEvent event(QString(), attributes);
+ QGuiApplication::sendEvent(m_focusObject, &event);
}
void QAndroidInputContext::touchDown(int x, int y)
@@ -748,7 +793,25 @@ void QAndroidInputContext::touchDown(int x, int y)
m_handleMode = ShowCursor;
// The VK will appear in a moment, stop the timer
m_hideCursorHandleTimer.stop();
- finishComposingText();
+
+ if (focusObjectIsComposing()) {
+ const double pixelDensity =
+ QGuiApplication::focusWindow()
+ ? QHighDpiScaling::factor(QGuiApplication::focusWindow())
+ : QHighDpiScaling::factor(QtAndroid::androidPlatformIntegration()->screen());
+
+ const QPointF touchPointLocal =
+ QGuiApplication::inputMethod()->inputItemTransform().inverted().map(
+ QPointF(x / pixelDensity, y / pixelDensity));
+
+ const int curBlockPos = getBlockPosition(
+ focusObjectInputMethodQuery(Qt::ImCursorPosition | Qt::ImAbsolutePosition));
+ const int touchPosition = curBlockPos
+ + QInputMethod::queryFocusObject(Qt::ImCursorPosition, touchPointLocal).toInt();
+ if (touchPosition != m_composingCursor)
+ focusObjectStopComposing();
+ }
+
updateSelectionHandles();
}
}
@@ -760,13 +823,19 @@ void QAndroidInputContext::longPress(int x, int y)
return;
if (m_focusObject && inputItemRectangle().contains(x, y)) {
- finishComposingText();
+ BatchEditLock batchEditLock(this);
+
+ focusObjectStopComposing();
// Release left button, otherwise the following events will cancel the menu popup
QtAndroidInput::releaseMouse(x, y);
- handleLocationChanged(1, x, y);
- ScopedValueChangeBack<bool> svcb(m_blockUpdateSelection, true);
+ const double pixelDensity =
+ QGuiApplication::focusWindow()
+ ? QHighDpiScaling::factor(QGuiApplication::focusWindow())
+ : QHighDpiScaling::factor(QtAndroid::androidPlatformIntegration()->screen());
+ const QPointF touchPoint(x / pixelDensity, y / pixelDensity);
+ setSelectionOnFocusObject(touchPoint, touchPoint);
QInputMethodQueryEvent query(Qt::ImCursorPosition | Qt::ImAnchorPosition | Qt::ImTextBeforeCursor | Qt::ImTextAfterCursor);
QCoreApplication::sendEvent(m_focusObject, &query);
@@ -905,6 +974,7 @@ void QAndroidInputContext::clear()
{
m_composingText.clear();
m_composingTextStart = -1;
+ m_composingCursor = -1;
m_extractedText.clear();
}
@@ -912,9 +982,8 @@ void QAndroidInputContext::clear()
void QAndroidInputContext::setFocusObject(QObject *object)
{
if (object != m_focusObject) {
+ focusObjectStopComposing();
m_focusObject = object;
- if (!m_composingText.isEmpty())
- finishComposingText();
reset();
}
QPlatformInputContext::setFocusObject(object);
@@ -929,78 +998,135 @@ jboolean QAndroidInputContext::beginBatchEdit()
jboolean QAndroidInputContext::endBatchEdit()
{
- if (--m_batchEditNestingLevel == 0 && !m_blockUpdateSelection) //ending batch edit mode
+ if (--m_batchEditNestingLevel == 0) { //ending batch edit mode
+ focusObjectStartComposing();
updateCursorPosition();
+ }
return JNI_TRUE;
}
/*
- Android docs say: If composing, replace compose text with \a text.
- Otherwise insert \a text at current cursor position.
-
- The cursor should then be 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. updateSelection() needs to be called.
+ Android docs say: This behaves like calling setComposingText(text, newCursorPosition) then
+ finishComposingText().
*/
jboolean QAndroidInputContext::commitText(const QString &text, jint newCursorPosition)
{
- ScopedValueChangeBack<bool> svcb(m_blockUpdateSelection, true);
- QInputMethodEvent event;
- event.setCommitString(text);
- sendInputMethodEvent(&event);
- clear();
-
- // Qt has now put the cursor at the end of the text, corresponding to newCursorPosition == 1
- if (newCursorPosition != 1) {
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
- if (!query.isNull()) {
- QList<QInputMethodEvent::Attribute> attributes;
- const int localPos = query->value(Qt::ImCursorPosition).toInt();
- const int newLocalPos = newCursorPosition > 0
- ? localPos + newCursorPosition - 1
- : localPos - text.length() + newCursorPosition;
- //move the cursor
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
- newLocalPos, 0));
- }
- }
- svcb.setOldValue();
- updateCursorPosition();
- return JNI_TRUE;
+ BatchEditLock batchEditLock(this);
+ return setComposingText(text, newCursorPosition) && finishComposingText();
}
jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint rightLength)
{
+ BatchEditLock batchEditLock(this);
+
+ focusObjectStopComposing();
+
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
return JNI_TRUE;
- m_composingText.clear();
- m_composingTextStart = -1;
-
if (leftLength < 0) {
rightLength += -leftLength;
leftLength = 0;
}
+ const int initialBlockPos = getBlockPosition(query);
+ const int initialCursorPos = getAbsoluteCursorPosition(query);
+ const int initialAnchorPos = initialBlockPos + query->value(Qt::ImAnchorPosition).toInt();
+
+ /*
+ According to documentation, we should delete leftLength characters before current selection
+ and rightLength characters after current selection (without affecting selection). But that is
+ absolutely not what Android's native EditText does. It deletes leftLength characters before
+ min(selection start, composing region start) and rightLength characters after max(selection
+ end, composing region end). There are no known keyboards that depend on this behavior, but
+ it is better to be consistent with EditText behavior, because there definetly should be no
+ keyboards that depend on documented behavior.
+ */
+ const int leftEnd =
+ m_composingText.isEmpty()
+ ? qMin(initialCursorPos, initialAnchorPos)
+ : qMin(qMin(initialCursorPos, initialAnchorPos), m_composingTextStart);
+
+ const int rightBegin =
+ m_composingText.isEmpty()
+ ? qMax(initialCursorPos, initialAnchorPos)
+ : qMax(qMax(initialCursorPos, initialAnchorPos),
+ m_composingTextStart + m_composingText.length());
+
+ int textBeforeCursorLen;
+ int textAfterCursorLen;
+
QVariant textBeforeCursor = query->value(Qt::ImTextBeforeCursor);
QVariant textAfterCursor = query->value(Qt::ImTextAfterCursor);
if (textBeforeCursor.isValid() && textAfterCursor.isValid()) {
- leftLength = qMin(leftLength, textBeforeCursor.toString().length());
- rightLength = qMin(rightLength, textAfterCursor.toString().length());
+ textBeforeCursorLen = textBeforeCursor.toString().length();
+ textAfterCursorLen = textAfterCursor.toString().length();
} else {
- int cursorPos = query->value(Qt::ImCursorPosition).toInt();
- leftLength = qMin(leftLength, cursorPos);
- rightLength = qMin(rightLength, query->value(Qt::ImSurroundingText).toString().length() - cursorPos);
+ textBeforeCursorLen = initialCursorPos - initialBlockPos;
+ textAfterCursorLen =
+ query->value(Qt::ImSurroundingText).toString().length() - textBeforeCursorLen;
}
+ leftLength = qMin(qMax(0, textBeforeCursorLen - (initialCursorPos - leftEnd)), leftLength);
+ rightLength = qMin(qMax(0, textAfterCursorLen - (rightBegin - initialCursorPos)), rightLength);
+
if (leftLength == 0 && rightLength == 0)
return JNI_TRUE;
- QInputMethodEvent event;
- event.setCommitString(QString(), -leftLength, leftLength+rightLength);
- sendInputMethodEvent(&event);
- clear();
+ if (leftEnd == rightBegin) {
+ // We have no selection and no composing region; we can do everything using one event
+ QInputMethodEvent event;
+ event.setCommitString({}, -leftLength, leftLength + rightLength);
+ QGuiApplication::sendEvent(m_focusObject, &event);
+ } else {
+ if (initialCursorPos != initialAnchorPos) {
+ QInputMethodEvent event({}, {
+ { QInputMethodEvent::Selection, initialCursorPos - initialBlockPos, 0 }
+ });
+
+ QGuiApplication::sendEvent(m_focusObject, &event);
+ }
+
+ int currentCursorPos = initialCursorPos;
+
+ if (rightLength > 0) {
+ QInputMethodEvent event;
+ event.setCommitString({}, rightBegin - currentCursorPos, rightLength);
+ QGuiApplication::sendEvent(m_focusObject, &event);
+
+ currentCursorPos = rightBegin;
+ }
+
+ if (leftLength > 0) {
+ const int leftBegin = leftEnd - leftLength;
+
+ QInputMethodEvent event;
+ event.setCommitString({}, leftBegin - currentCursorPos, leftLength);
+ QGuiApplication::sendEvent(m_focusObject, &event);
+
+ currentCursorPos = leftBegin;
+
+ if (!m_composingText.isEmpty())
+ m_composingTextStart -= leftLength;
+ }
+
+ // Restore cursor position or selection
+ if (currentCursorPos != initialCursorPos - leftLength
+ || initialCursorPos != initialAnchorPos) {
+ // If we have deleted a newline character, we are now in a new block
+ const int currentBlockPos = getBlockPosition(
+ focusObjectInputMethodQuery(Qt::ImAbsolutePosition | Qt::ImCursorPosition));
+
+ QInputMethodEvent event({}, {
+ { QInputMethodEvent::Selection, initialCursorPos - leftLength - currentBlockPos,
+ initialAnchorPos - initialCursorPos },
+ { QInputMethodEvent::Cursor, 0, 0 }
+ });
+
+ QGuiApplication::sendEvent(m_focusObject, &event);
+ }
+ }
return JNI_TRUE;
}
@@ -1008,16 +1134,70 @@ jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint right
// Android docs say the cursor must not move
jboolean QAndroidInputContext::finishComposingText()
{
- if (m_composingText.isEmpty())
- return JNI_TRUE; // not composing
+ BatchEditLock batchEditLock(this);
+
+ if (!focusObjectStopComposing())
+ return JNI_FALSE;
+
+ clear();
+ return JNI_TRUE;
+}
+
+bool QAndroidInputContext::focusObjectIsComposing() const
+{
+ return m_composingCursor != -1;
+}
+
+void QAndroidInputContext::focusObjectStartComposing()
+{
+ if (focusObjectIsComposing() || m_composingText.isEmpty())
+ return;
+
+ // Composing strings containing newline characters are rare and may cause problems
+ if (m_composingText.contains(QLatin1Char('\n')))
+ return;
+
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ if (!query)
+ return;
+
+ if (query->value(Qt::ImCursorPosition).toInt() != query->value(Qt::ImAnchorPosition).toInt())
+ return;
+
+ const int absoluteCursorPos = getAbsoluteCursorPosition(query);
+ if (absoluteCursorPos < m_composingTextStart
+ || absoluteCursorPos > m_composingTextStart + m_composingText.length())
+ return;
+
+ m_composingCursor = absoluteCursorPos;
+
+ QTextCharFormat underlined;
+ underlined.setFontUnderline(true);
+
+ QInputMethodEvent event(m_composingText, {
+ { QInputMethodEvent::Cursor, absoluteCursorPos - m_composingTextStart, 1 },
+ { QInputMethodEvent::TextFormat, 0, m_composingText.length(), underlined }
+ });
+
+ event.setCommitString({}, m_composingTextStart - absoluteCursorPos, m_composingText.length());
+
+ QGuiApplication::sendEvent(m_focusObject, &event);
+}
+
+bool QAndroidInputContext::focusObjectStopComposing()
+{
+ if (!focusObjectIsComposing())
+ return true; // not composing
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
- return JNI_FALSE;
+ return false;
const int blockPos = getBlockPosition(query);
const int localCursorPos = m_composingCursor - blockPos;
+ m_composingCursor = -1;
+
// Moving Qt's cursor to where the preedit cursor used to be
QList<QInputMethodEvent::Attribute> attributes;
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection, localCursorPos, 0));
@@ -1025,9 +1205,8 @@ jboolean QAndroidInputContext::finishComposingText()
QInputMethodEvent event(QString(), attributes);
event.setCommitString(m_composingText);
sendInputMethodEvent(&event);
- clear();
- return JNI_TRUE;
+ return true;
}
jint QAndroidInputContext::getCursorCapsMode(jint /*reqModes*/)
@@ -1040,13 +1219,18 @@ jint QAndroidInputContext::getCursorCapsMode(jint /*reqModes*/)
const uint qtInputMethodHints = query->value(Qt::ImHints).toUInt();
const int localPos = query->value(Qt::ImCursorPosition).toInt();
- bool atWordBoundary = (localPos == 0);
+ bool atWordBoundary =
+ localPos == 0
+ && (!focusObjectIsComposing() || m_composingCursor == m_composingTextStart);
+
if (!atWordBoundary) {
QString surroundingText = query->value(Qt::ImSurroundingText).toString();
surroundingText.truncate(localPos);
+ if (focusObjectIsComposing())
+ surroundingText += m_composingText.leftRef(m_composingCursor - m_composingTextStart);
// Add a character to see if it is at the end of the sentence or not
QTextBoundaryFinder finder(QTextBoundaryFinder::Sentence, surroundingText + QLatin1Char('A'));
- finder.setPosition(localPos);
+ finder.setPosition(surroundingText.length());
if (finder.isAtBoundary())
atWordBoundary = finder.isAtBoundary();
}
@@ -1067,52 +1251,51 @@ const QAndroidInputContext::ExtractedText &QAndroidInputContext::getExtractedTex
// updateExtractedText(View, int, ExtractedText) whenever you call
// updateSelection(View, int, int, int, int)." QTBUG-37980
- QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
+ QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery(
+ Qt::ImCursorPosition | Qt::ImAbsolutePosition | Qt::ImAnchorPosition);
if (query.isNull())
return m_extractedText;
- int localPos = query->value(Qt::ImCursorPosition).toInt(); //position before pre-edit text relative to the current block
- 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.leftRef(localComposePos) + m_composingText + blockText.midRef(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 (blockPos > 0) {
- QString prevBlockEnding = query->value(Qt::ImTextBeforeCursor).toString();
- prevBlockEnding.chop(localPos);
- if (prevBlockEnding.endsWith(QLatin1Char('\n'))) {
- localOffset = -qMin(20, prevBlockEnding.length());
- blockText = prevBlockEnding.right(-localOffset) + blockText;
- }
- }
+ const int cursorPos = getAbsoluteCursorPosition(query);
+ const int blockPos = getBlockPosition(query);
// It is documented that we should try to return hintMaxChars
- // characters, but that's not what the standard Android controls do, and
+ // characters, but standard Android controls always return all text, 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;
+ QVariant textBeforeCursor = QInputMethod::queryFocusObject(Qt::ImTextBeforeCursor, INT_MAX);
+ QVariant textAfterCursor = QInputMethod::queryFocusObject(Qt::ImTextAfterCursor, INT_MAX);
+ if (textBeforeCursor.isValid() && textAfterCursor.isValid()) {
+ if (focusObjectIsComposing()) {
+ m_extractedText.text =
+ textBeforeCursor.toString() + m_composingText + textAfterCursor.toString();
+ } else {
+ m_extractedText.text = textBeforeCursor.toString() + textAfterCursor.toString();
+ }
+
+ m_extractedText.startOffset = qMax(0, cursorPos - textBeforeCursor.toString().length());
+ } else {
+ m_extractedText.text = focusObjectInputMethodQuery(Qt::ImSurroundingText)
+ ->value(Qt::ImSurroundingText).toString();
+
+ if (focusObjectIsComposing())
+ m_extractedText.text.insert(cursorPos - blockPos, m_composingText);
+
+ m_extractedText.startOffset = blockPos;
+ }
- 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 if (composeLength > 0) {
+ if (focusObjectIsComposing()) {
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;
+ m_extractedText.selectionEnd = m_extractedText.selectionStart;
+ } else {
+ m_extractedText.selectionStart = cursorPos - m_extractedText.startOffset;
+ m_extractedText.selectionEnd =
+ blockPos + query->value(Qt::ImAnchorPosition).toInt() - m_extractedText.startOffset;
+
+ // Some keyboards misbehave when selectionStart > selectionEnd
+ if (m_extractedText.selectionStart > m_extractedText.selectionEnd)
+ std::swap(m_extractedText.selectionStart, m_extractedText.selectionEnd);
}
return m_extractedText;
@@ -1147,10 +1330,20 @@ QString QAndroidInputContext::getTextAfterCursor(jint length, jint /*flags*/)
}
}
- // Controls do not report preedit text, so we have to add it
- if (!m_composingText.isEmpty()) {
+ if (focusObjectIsComposing()) {
+ // Controls do not report preedit text, so we have to add it
const int cursorPosInsidePreedit = m_composingCursor - m_composingTextStart;
text = m_composingText.midRef(cursorPosInsidePreedit) + text;
+ } else {
+ // We must not return selected text if there is any
+ QSharedPointer<QInputMethodQueryEvent> query =
+ focusObjectInputMethodQuery(Qt::ImCursorPosition | Qt::ImAnchorPosition);
+ if (query) {
+ const int cursorPos = query->value(Qt::ImCursorPosition).toInt();
+ const int anchorPos = query->value(Qt::ImAnchorPosition).toInt();
+ if (anchorPos > cursorPos)
+ text.remove(0, anchorPos - cursorPos);
+ }
}
text.truncate(length);
@@ -1177,10 +1370,20 @@ QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
}
}
- // Controls do not report preedit text, so we have to add it
- if (!m_composingText.isEmpty()) {
+ if (focusObjectIsComposing()) {
+ // Controls do not report preedit text, so we have to add it
const int cursorPosInsidePreedit = m_composingCursor - m_composingTextStart;
text += m_composingText.leftRef(cursorPosInsidePreedit);
+ } else {
+ // We must not return selected text if there is any
+ QSharedPointer<QInputMethodQueryEvent> query =
+ focusObjectInputMethodQuery(Qt::ImCursorPosition | Qt::ImAnchorPosition);
+ if (query) {
+ const int cursorPos = query->value(Qt::ImCursorPosition).toInt();
+ const int anchorPos = query->value(Qt::ImAnchorPosition).toInt();
+ if (anchorPos < cursorPos)
+ text.chop(cursorPos - anchorPos);
+ }
}
if (text.length() > length)
@@ -1189,11 +1392,13 @@ QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
}
/*
- 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.
+ Android docs say that this function should:
+ - remove the current composing text, if there is any
+ - otherwise remove currently selected text, if there is any
+ - insert new text in place of old composing text or, if there was none, at current cursor position
+ - mark the inserted text as composing
+ - move cursor as specified by newCursorPosition: if > 0, it is relative to the end of inserted
+ text - 1; if <= 0, it is relative to the start of inserted text
*/
jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCursorPosition)
@@ -1202,47 +1407,110 @@ jboolean QAndroidInputContext::setComposingText(const QString &text, jint newCur
if (query.isNull())
return JNI_FALSE;
- const int cursorPos = getAbsoluteCursorPosition(query);
- if (newCursorPosition > 0)
- newCursorPosition += text.length() - 1;
+ BatchEditLock batchEditLock(this);
+
+ const int absoluteCursorPos = getAbsoluteCursorPosition(query);
+ int absoluteAnchorPos = getBlockPosition(query) + query->value(Qt::ImAnchorPosition).toInt();
+ // If we have composing region and selection (and therefore focusObjectIsComposing() == false),
+ // we must clear selection so that we won't delete it when we will be replacing composing text
+ if (!m_composingText.isEmpty() && absoluteCursorPos != absoluteAnchorPos) {
+ const int cursorPos = query->value(Qt::ImCursorPosition).toInt();
+ QInputMethodEvent event({}, { { QInputMethodEvent::Selection, cursorPos, 0 } });
+ QGuiApplication::sendEvent(m_focusObject, &event);
+
+ absoluteAnchorPos = absoluteCursorPos;
+ }
+
+ // If we had no composing region, pretend that we had a zero-length composing region at current
+ // cursor position to simplify code. Also account for that we must delete selected text if there
+ // (still) is any.
+ const int effectiveAbsoluteCursorPos = qMin(absoluteCursorPos, absoluteAnchorPos);
+ if (m_composingTextStart == -1)
+ m_composingTextStart = effectiveAbsoluteCursorPos;
+
+ const int oldComposingTextLen = m_composingText.length();
m_composingText = text;
- m_composingTextStart = text.isEmpty() ? -1 : cursorPos;
- m_composingCursor = cursorPos + newCursorPosition;
- QList<QInputMethodEvent::Attribute> attributes;
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor,
- newCursorPosition,
- 1));
- // Show compose text underlined
- QTextCharFormat underlined;
- underlined.setFontUnderline(true);
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,0, text.length(),
- QVariant(underlined)));
- QInputMethodEvent event(m_composingText, attributes);
- sendInputMethodEvent(&event);
+ const int newAbsoluteCursorPos =
+ newCursorPosition <= 0
+ ? m_composingTextStart + newCursorPosition
+ : m_composingTextStart + m_composingText.length() + newCursorPosition - 1;
- QMetaObject::invokeMethod(this, "keyDown");
+ const bool focusObjectWasComposing = focusObjectIsComposing();
- updateCursorPosition();
+ // Same checks as in focusObjectStartComposing()
+ if (!m_composingText.isEmpty() && !m_composingText.contains(QLatin1Char('\n'))
+ && newAbsoluteCursorPos >= m_composingTextStart
+ && newAbsoluteCursorPos <= m_composingTextStart + m_composingText.length())
+ m_composingCursor = newAbsoluteCursorPos;
+ else
+ m_composingCursor = -1;
+
+ QInputMethodEvent event;
+ if (focusObjectIsComposing()) {
+ QTextCharFormat underlined;
+ underlined.setFontUnderline(true);
+
+ event = QInputMethodEvent(m_composingText, {
+ { QInputMethodEvent::TextFormat, 0, m_composingText.length(), underlined },
+ { QInputMethodEvent::Cursor, m_composingCursor - m_composingTextStart, 1 }
+ });
+
+ if (oldComposingTextLen > 0 && !focusObjectWasComposing) {
+ event.setCommitString({}, m_composingTextStart - effectiveAbsoluteCursorPos,
+ oldComposingTextLen);
+ }
+ } else {
+ event = QInputMethodEvent({}, {});
+
+ if (focusObjectWasComposing) {
+ event.setCommitString(m_composingText);
+ } else {
+ event.setCommitString(m_composingText,
+ m_composingTextStart - effectiveAbsoluteCursorPos,
+ oldComposingTextLen);
+ }
+ }
+
+ if (m_composingText.isEmpty())
+ clear();
+
+ QGuiApplication::sendEvent(m_focusObject, &event);
+
+ if (!focusObjectIsComposing() && newCursorPosition != 1) {
+ // Move cursor using a separate event because if we have inserted or deleted a newline
+ // character, then we are now inside an another block
+
+ const int newBlockPos = getBlockPosition(
+ focusObjectInputMethodQuery(Qt::ImCursorPosition | Qt::ImAbsolutePosition));
+
+ event = QInputMethodEvent({}, {
+ { QInputMethodEvent::Selection, newAbsoluteCursorPos - newBlockPos, 0 }
+ });
+
+ QGuiApplication::sendEvent(m_focusObject, &event);
+ }
+
+ keyDown();
return JNI_TRUE;
}
// Android docs say:
// * start may be after end, same meaning as if swapped
-// * this function should not trigger updateSelection
+// * this function should not trigger updateSelection, but Android's native EditText does trigger it
// * if start == end then we should stop composing
jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
{
+ BatchEditLock batchEditLock(this);
+
// 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();
+ finishComposingText();
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQuery();
if (query.isNull())
@@ -1253,54 +1521,42 @@ jboolean QAndroidInputContext::setComposingRegion(jint start, jint end)
if (start > end)
qSwap(start, end);
- /*
- start and end are cursor positions, not character positions,
- i.e. selecting the first character is done by start == 0 and end == 1,
- and start == end means no character selected
-
- Therefore, the length of the region is end - start
- */
-
- int length = end - start;
- int localPos = query->value(Qt::ImCursorPosition).toInt();
- int blockPosition = getBlockPosition(query);
- int localStart = start - blockPosition; // Qt uses position inside block
- int currentCursor = wasComposing ? m_composingCursor : blockPosition + localPos;
-
- ScopedValueChangeBack<bool> svcb(m_blockUpdateSelection, true);
-
QString text = query->value(Qt::ImSurroundingText).toString();
+ int textOffset = getBlockPosition(query);
- m_composingText = text.mid(localStart, length);
- m_composingTextStart = start;
- m_composingCursor = currentCursor;
-
- //in the Qt text controls, the preedit is defined relative to the cursor position
- int relativeStart = localStart - localPos;
+ if (start < textOffset || end > textOffset + text.length()) {
+ const int cursorPos = query->value(Qt::ImCursorPosition).toInt();
- QList<QInputMethodEvent::Attribute> attributes;
+ if (end - textOffset > text.length()) {
+ const QString after = query->value(Qt::ImTextAfterCursor).toString();
+ const int additionalSuffixLen = after.length() - (text.length() - cursorPos);
- // Show compose text underlined
- QTextCharFormat underlined;
- underlined.setFontUnderline(true);
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,0, length,
- QVariant(underlined)));
+ if (additionalSuffixLen > 0)
+ text += after.rightRef(additionalSuffixLen);
+ }
- // Keep the cursor position unchanged (don't move to end of preedit)
- attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, currentCursor - start, 1));
+ if (start < textOffset) {
+ QString before = query->value(Qt::ImTextBeforeCursor).toString();
+ before.chop(cursorPos);
- QInputMethodEvent event(m_composingText, attributes);
- event.setCommitString(QString(), relativeStart, length);
- sendInputMethodEvent(&event);
+ if (!before.isEmpty()) {
+ text = before + text;
+ textOffset -= before.length();
+ }
+ }
+ if (start < textOffset || end - textOffset > text.length()) {
#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);
- }
+ qWarning("setComposingRegion: failed to retrieve text from composing region");
#endif
+ return JNI_TRUE;
+ }
+ }
+
+ m_composingText = text.mid(start - textOffset, end - start);
+ m_composingTextStart = start;
+
return JNI_TRUE;
}
@@ -1310,15 +1566,18 @@ jboolean QAndroidInputContext::setSelection(jint start, jint end)
if (query.isNull())
return JNI_FALSE;
+ BatchEditLock batchEditLock(this);
+
int blockPosition = getBlockPosition(query);
int localCursorPos = start - blockPosition;
- QList<QInputMethodEvent::Attribute> attributes;
- if (!m_composingText.isEmpty() && start == end) {
+ if (focusObjectIsComposing() && start == end && start >= m_composingTextStart
+ && start <= m_composingTextStart + m_composingText.length()) {
// not actually changing the selection; just moving the
// preedit cursor
int localOldPos = query->value(Qt::ImCursorPosition).toInt();
int pos = localCursorPos - localOldPos;
+ QList<QInputMethodEvent::Attribute> attributes;
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, pos, 1));
//but we have to tell Qt about the compose text all over again
@@ -1330,21 +1589,26 @@ jboolean QAndroidInputContext::setSelection(jint start, jint end)
QVariant(underlined)));
m_composingCursor = start;
+ QInputMethodEvent event(m_composingText, attributes);
+ QGuiApplication::sendEvent(m_focusObject, &event);
} else {
// actually changing the selection
+ focusObjectStopComposing();
+ QList<QInputMethodEvent::Attribute> attributes;
attributes.append(QInputMethodEvent::Attribute(QInputMethodEvent::Selection,
localCursorPos,
end - start));
+ QInputMethodEvent event({}, attributes);
+ QGuiApplication::sendEvent(m_focusObject, &event);
}
- QInputMethodEvent event(m_composingText, attributes);
- sendInputMethodEvent(&event);
- updateCursorPosition();
return JNI_TRUE;
}
jboolean QAndroidInputContext::selectAll()
{
- finishComposingText();
+ BatchEditLock batchEditLock(this);
+
+ focusObjectStopComposing();
m_handleMode = ShowCursor;
sendShortcut(QKeySequence::SelectAll);
return JNI_TRUE;
@@ -1352,7 +1616,12 @@ jboolean QAndroidInputContext::selectAll()
jboolean QAndroidInputContext::cut()
{
+ BatchEditLock batchEditLock(this);
+
+ // This is probably not what native EditText would do, but normally if there is selection, then
+ // there will be no composing region
finishComposingText();
+
m_handleMode = ShowCursor;
sendShortcut(QKeySequence::Cut);
return JNI_TRUE;
@@ -1360,7 +1629,9 @@ jboolean QAndroidInputContext::cut()
jboolean QAndroidInputContext::copy()
{
- finishComposingText();
+ BatchEditLock batchEditLock(this);
+
+ focusObjectStopComposing();
m_handleMode = ShowCursor;
sendShortcut(QKeySequence::Copy);
return JNI_TRUE;
@@ -1374,7 +1645,11 @@ jboolean QAndroidInputContext::copyURL()
jboolean QAndroidInputContext::paste()
{
+ BatchEditLock batchEditLock(this);
+
+ // TODO: This is not what native EditText does
finishComposingText();
+
m_handleMode = ShowCursor;
sendShortcut(QKeySequence::Paste);
return JNI_TRUE;
@@ -1386,8 +1661,12 @@ void QAndroidInputContext::sendShortcut(const QKeySequence &sequence)
const int keys = sequence[i];
Qt::Key key = Qt::Key(keys & ~Qt::KeyboardModifierMask);
Qt::KeyboardModifiers mod = Qt::KeyboardModifiers(keys & Qt::KeyboardModifierMask);
- QGuiApplication::postEvent(m_focusObject, new QKeyEvent(QEvent::KeyPress, key, mod));
- QGuiApplication::postEvent(m_focusObject, new QKeyEvent(QEvent::KeyRelease, key, mod));
+
+ QKeyEvent pressEvent(QEvent::KeyPress, key, mod);
+ QKeyEvent releaseEvent(QEvent::KeyRelease, key, mod);
+
+ QGuiApplication::sendEvent(m_focusObject, &pressEvent);
+ QGuiApplication::sendEvent(m_focusObject, &releaseEvent);
}
}
diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h
index bd3edb30f0..e9bfb98e66 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.h
+++ b/src/plugins/platforms/android/qandroidinputcontext.h
@@ -151,6 +151,9 @@ private slots:
private:
void sendInputMethodEvent(QInputMethodEvent *event);
QSharedPointer<QInputMethodQueryEvent> focusObjectInputMethodQuery(Qt::InputMethodQueries queries = Qt::ImQueryAll);
+ bool focusObjectIsComposing() const;
+ void focusObjectStartComposing();
+ bool focusObjectStopComposing();
private:
ExtractedText m_extractedText;
@@ -158,9 +161,8 @@ private:
int m_composingTextStart;
int m_composingCursor;
QMetaObject::Connection m_updateCursorPosConnection;
- bool m_blockUpdateSelection;
HandleModes m_handleMode;
- QAtomicInt m_batchEditNestingLevel;
+ int m_batchEditNestingLevel;
QObject *m_focusObject;
QTimer m_hideCursorHandleTimer;
};
diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp
index a78a62337f..7fc68c3d7c 100644
--- a/src/plugins/platforms/android/qandroidplatformtheme.cpp
+++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp
@@ -489,6 +489,8 @@ QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const
Q_FALLTHROUGH();
}
+ case DialogButtonBoxLayout:
+ return QVariant(QPlatformDialogHelper::AndroidLayout);
default:
return QPlatformTheme::themeHint(hint);
}
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index c095f51fa3..4f691ce112 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -49,13 +49,14 @@
QT_BEGIN_NAMESPACE
+static QBasicAtomicInt winIdGenerator = Q_BASIC_ATOMIC_INITIALIZER(0);
+
QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
: QPlatformWindow(window)
{
m_windowFlags = Qt::Widget;
m_windowState = Qt::WindowNoState;
- static QAtomicInt winIdGenerator(1);
- m_windowId = winIdGenerator.fetchAndAddRelaxed(1);
+ m_windowId = winIdGenerator.fetchAndAddRelaxed(1) + 1;
setWindowState(window->windowStates());
}
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index acddc3ecc8..2398e6351e 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -55,6 +55,7 @@ public:
QNSWindowBackingStore(QWindow *window);
~QNSWindowBackingStore();
+ void resize(const QSize &size, const QRegion &staticContents) override;
void flush(QWindow *, const QRegion &, const QPoint &) override;
private:
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index c381f87844..01b4894324 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -71,6 +71,24 @@ QImage::Format QNSWindowBackingStore::format() const
return QRasterBackingStore::format();
}
+void QNSWindowBackingStore::resize(const QSize &size, const QRegion &staticContents)
+{
+ qCDebug(lcQpaBackingStore) << "Resize requested to" << size;
+ QRasterBackingStore::resize(size, staticContents);
+
+ // The window shadow rendered by AppKit is based on the shape/content of the
+ // NSWindow surface. Technically any flush of the backingstore can result in
+ // a potentially new shape of the window, and would need a shadow invalidation,
+ // but this is likely too expensive to do at every flush for the few cases where
+ // clients change the shape dynamically. One case where we do know that the shadow
+ // likely needs invalidation, if the window has partially transparent content,
+ // is after a resize, where AppKit's default shadow may be based on the previous
+ // window content.
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle());
+ if (cocoaWindow->isContentView() && !cocoaWindow->isOpaque())
+ cocoaWindow->m_needsInvalidateShadow = true;
+}
+
/*!
Flushes the given \a region from the specified \a window onto the
screen.
@@ -217,6 +235,7 @@ void QNSWindowBackingStore::flush(QWindow *window, const QRegion &region, const
QCocoaWindow *topLevelCocoaWindow = static_cast<QCocoaWindow *>(topLevelWindow->handle());
if (Q_UNLIKELY(topLevelCocoaWindow->m_needsInvalidateShadow)) {
+ qCDebug(lcQpaBackingStore) << "Invalidating window shadow for" << topLevelCocoaWindow;
[topLevelView.window invalidateShadow];
topLevelCocoaWindow->m_needsInvalidateShadow = false;
}
@@ -382,10 +401,11 @@ void QCALayerBackingStore::ensureBackBuffer()
bool QCALayerBackingStore::recreateBackBufferIfNeeded()
{
- const qreal devicePixelRatio = window()->devicePixelRatio();
+ const QCocoaWindow *platformWindow = static_cast<QCocoaWindow *>(window()->handle());
+ const qreal devicePixelRatio = platformWindow->devicePixelRatio();
QSize requestedBufferSize = m_requestedSize * devicePixelRatio;
- const NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view();
+ const NSView *backingStoreView = platformWindow->view();
Q_UNUSED(backingStoreView);
auto bufferSizeMismatch = [&](const QSize requested, const QSize actual) {
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index 9771cd0289..69587a24be 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -191,6 +191,7 @@ public:
static void waitingObserverCallback(CFRunLoopObserverRef observer,
CFRunLoopActivity activity, void *info);
static void firstLoopEntry(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info);
+ bool sendQueuedUserInputEvents();
void processPostedEvents();
};
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 84ffadea83..d3bb0711f0 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -377,16 +377,9 @@ bool QCocoaEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
NSEvent* event = nil;
// First, send all previously excluded input events, if any:
- if (!excludeUserEvents) {
- while (!d->queuedUserInputEvents.isEmpty()) {
- event = static_cast<NSEvent *>(d->queuedUserInputEvents.takeFirst());
- if (!filterNativeEvent("NSEvent", event, nullptr)) {
- [NSApp sendEvent:event];
- retVal = true;
- }
- [event release];
- }
- }
+ if (d->sendQueuedUserInputEvents())
+ retVal = true;
+
// If Qt is used as a plugin, or as an extension in a native cocoa
// application, we should not run or stop NSApplication; This will be
@@ -843,6 +836,23 @@ void QCocoaEventDispatcherPrivate::waitingObserverCallback(CFRunLoopObserverRef,
emit static_cast<QCocoaEventDispatcher*>(info)->awake();
}
+bool QCocoaEventDispatcherPrivate::sendQueuedUserInputEvents()
+{
+ Q_Q(QCocoaEventDispatcher);
+ if (processEventsFlags & QEventLoop::ExcludeUserInputEvents)
+ return false;
+ bool didSendEvent = false;
+ while (!queuedUserInputEvents.isEmpty()) {
+ NSEvent *event = static_cast<NSEvent *>(queuedUserInputEvents.takeFirst());
+ if (!q->filterNativeEvent("NSEvent", event, nullptr)) {
+ [NSApp sendEvent:event];
+ didSendEvent = true;
+ }
+ [event release];
+ }
+ return didSendEvent;
+}
+
void QCocoaEventDispatcherPrivate::processPostedEvents()
{
if (blockSendPostedEvents) {
@@ -896,6 +906,7 @@ void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info)
d->maybeCancelWaitForMoreEvents();
return;
}
+ d->sendQueuedUserInputEvents();
d->processPostedEvents();
d->maybeCancelWaitForMoreEvents();
}
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h
index eefb1cd0fb..c1041ac2da 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.h
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h
@@ -80,7 +80,7 @@ private:
NSOpenGLContext *m_shareContext = nil;
QSurfaceFormat m_format;
bool m_didCheckForSoftwareContext = false;
- QVarLengthArray<QMacScopedObserver, 3> m_updateObservers;
+ QVarLengthArray<QMacNotificationObserver, 3> m_updateObservers;
QAtomicInt m_needsUpdate = false;
};
diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
index fe1fc31553..0f8fec0548 100644
--- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm
+++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm
@@ -404,13 +404,13 @@ bool QCocoaGLContext::setDrawable(QPlatformSurface *surface)
m_updateObservers.clear();
if (view.layer) {
- m_updateObservers.append(QMacScopedObserver(view, NSViewFrameDidChangeNotification, updateCallback));
- m_updateObservers.append(QMacScopedObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback));
+ m_updateObservers.append(QMacNotificationObserver(view, NSViewFrameDidChangeNotification, updateCallback));
+ m_updateObservers.append(QMacNotificationObserver(view.window, NSWindowDidChangeScreenNotification, updateCallback));
} else {
- m_updateObservers.append(QMacScopedObserver(view, NSViewGlobalFrameDidChangeNotification, updateCallback));
+ m_updateObservers.append(QMacNotificationObserver(view, NSViewGlobalFrameDidChangeNotification, updateCallback));
}
- m_updateObservers.append(QMacScopedObserver([NSApplication sharedApplication],
+ m_updateObservers.append(QMacNotificationObserver([NSApplication sharedApplication],
NSApplicationDidChangeScreenParametersNotification, updateCallback));
// If any of the observers fire at this point it's fine. We check the
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 1b184cd60f..c9eafa81d0 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -297,13 +297,12 @@ Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
*/
Qt::MouseButton cocoaButton2QtButton(NSEvent *event)
{
- switch (event.type) {
- case NSEventTypeMouseMoved:
+ if (cocoaEvent2QtMouseEvent(event) == QEvent::MouseMove)
return Qt::NoButton;
+ switch (event.type) {
case NSEventTypeRightMouseUp:
case NSEventTypeRightMouseDown:
- case NSEventTypeRightMouseDragged:
return Qt::RightButton;
default:
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 300082d694..08e7447a75 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -215,6 +215,25 @@ QCocoaIntegration::QCocoaIntegration(const QStringList &paramList)
connect(qGuiApp, &QGuiApplication::focusWindowChanged,
this, &QCocoaIntegration::focusWindowChanged);
+
+ static auto splashScreenHider = QMacKeyValueObserver(NSApp, @"modalWindow", []{
+ const QWindowList allWindows = QGuiApplication::topLevelWindows();
+ for (QWindow *window : allWindows) {
+ if ((window->flags() & Qt::SplashScreen) == Qt::SplashScreen) {
+ QCocoaWindow *platformWindow = static_cast<QCocoaWindow*>(window->handle());
+ NSWindow *splashWindow = platformWindow->view().window;
+ if (!splashWindow)
+ continue;
+ if (NSApp.modalWindow) {
+ NSInteger originalLevel = splashWindow.level;
+ splashWindow.level = NSNormalWindowLevel;
+ window->setProperty("_q_levelBeforeModalSession", (qlonglong)originalLevel);
+ } else if (NSInteger originalLevel = window->property("_q_levelBeforeModalSession").toLongLong()) {
+ splashWindow.level = originalLevel;
+ }
+ }
+ }
+ });
}
QCocoaIntegration::~QCocoaIntegration()
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h
index 34d8428188..a957710a88 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.h
+++ b/src/plugins/platforms/cocoa/qcocoamenu.h
@@ -92,6 +92,9 @@ public:
bool isOpen() const;
void setIsOpen(bool isOpen);
+ bool isAboutToShow() const;
+ void setIsAboutToShow(bool isAbout);
+
void timerEvent(QTimerEvent *e) override;
void syncMenuItem_helper(QPlatformMenuItem *menuItem, bool menubarUpdate);
@@ -111,6 +114,7 @@ private:
bool m_parentEnabled:1;
bool m_visible:1;
bool m_isOpen:1;
+ bool m_isAboutToShow:1;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index f34988721d..8c4fca0d29 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -178,6 +178,16 @@ void QCocoaMenu::setIsOpen(bool isOpen)
m_isOpen = isOpen;
}
+bool QCocoaMenu::isAboutToShow() const
+{
+ return m_isAboutToShow;
+}
+
+void QCocoaMenu::setIsAboutToShow(bool isAbout)
+{
+ m_isAboutToShow = isAbout;
+}
+
void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem)
{
QMacAutoReleasePool pool;
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index 32fc3ab660..c35cf6d799 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -141,6 +141,12 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu)
if (menu == m_menu)
return;
+ bool setAttached = false;
+ if ([m_native.menu isKindOfClass:[QCocoaNSMenu class]]) {
+ auto parentMenu = static_cast<QCocoaNSMenu *>(m_native.menu);
+ setAttached = parentMenu.platformMenu && parentMenu.platformMenu->isAboutToShow();
+ }
+
if (m_menu && m_menu->menuParent() == this) {
m_menu->setMenuParent(nullptr);
// Free the menu from its parent's influence
@@ -154,6 +160,8 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu)
if (m_menu) {
m_menu->setMenuParent(this);
m_menu->propagateEnabledState(isEnabled());
+ if (setAttached)
+ m_menu->setAttachedItem(m_native);
} else {
// we previously had a menu, but no longer
// clear out our item so the nexy sync() call builds a new one
diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.mm b/src/plugins/platforms/cocoa/qcocoansmenu.mm
index 65b0832d9f..c51460282a 100644
--- a/src/plugins/platforms/cocoa/qcocoansmenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoansmenu.mm
@@ -195,7 +195,9 @@ static NSString *qt_mac_removePrivateUnicode(NSString *string)
return;
platformMenu->setIsOpen(true);
+ platformMenu->setIsAboutToShow(true);
emit platformMenu->aboutToShow();
+ platformMenu->setIsAboutToShow(false);
}
- (void)menuDidClose:(NSMenu *)menu
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h
index c42fa7d2e8..788b616e78 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.h
+++ b/src/plugins/platforms/cocoa/qcocoatheme.h
@@ -45,6 +45,8 @@
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaThemeAppAppearanceObserver));
+#include <QtCore/private/qcore_mac_p.h>
+
QT_BEGIN_NAMESPACE
class QPalette;
@@ -82,9 +84,10 @@ public:
private:
mutable QPalette *m_systemPalette;
+ QMacNotificationObserver m_systemColorObserver;
mutable QHash<QPlatformTheme::Palette, QPalette*> m_palettes;
mutable QHash<QPlatformTheme::Font, QFont*> m_fonts;
- QT_MANGLE_NAMESPACE(QCocoaThemeAppAppearanceObserver) *m_appearanceObserver;
+ QMacKeyValueObserver m_appearanceObserver;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index efe670abed..7c10456824 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -80,70 +80,32 @@
#include <CoreServices/CoreServices.h>
-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
-@interface QT_MANGLE_NAMESPACE(QCocoaThemeAppAppearanceObserver) : NSObject
-@property (readonly, nonatomic) QCocoaTheme *theme;
-- (instancetype)initWithTheme:(QCocoaTheme *)theme;
-@end
-
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaThemeAppAppearanceObserver);
-
-@implementation QCocoaThemeAppAppearanceObserver
-- (instancetype)initWithTheme:(QCocoaTheme *)theme
-{
- if ((self = [super init])) {
- _theme = theme;
- [NSApp addObserver:self forKeyPath:@"effectiveAppearance" options:NSKeyValueObservingOptionNew context:nullptr];
- }
- return self;
-}
-
-- (void)dealloc
-{
- [NSApp removeObserver:self forKeyPath:@"effectiveAppearance"];
- [super dealloc];
-}
-
-- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
- change:(NSDictionary<NSKeyValueChangeKey, id> *)change context:(void *)context
-{
- Q_UNUSED(change);
- Q_UNUSED(context);
-
- Q_ASSERT(object == NSApp);
- Q_ASSERT([keyPath isEqualToString:@"effectiveAppearance"]);
-
- if (__builtin_available(macOS 10.14, *))
- NSAppearance.currentAppearance = NSApp.effectiveAppearance;
-
- self.theme->handleSystemThemeChange();
-}
-@end
-#endif // QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
-
QT_BEGIN_NAMESPACE
const char *QCocoaTheme::name = "cocoa";
QCocoaTheme::QCocoaTheme()
- : m_systemPalette(nullptr), m_appearanceObserver(nil)
+ : m_systemPalette(nullptr)
{
#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
- if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave)
- m_appearanceObserver = [[QCocoaThemeAppAppearanceObserver alloc] initWithTheme:this];
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) {
+ m_appearanceObserver = QMacKeyValueObserver(NSApp, @"effectiveAppearance", [this] {
+ if (__builtin_available(macOS 10.14, *))
+ NSAppearance.currentAppearance = NSApp.effectiveAppearance;
+
+ handleSystemThemeChange();
+ });
+ }
#endif
- [[NSNotificationCenter defaultCenter] addObserverForName:NSSystemColorsDidChangeNotification
- object:nil queue:nil usingBlock:^(NSNotification *) {
+ m_systemColorObserver = QMacNotificationObserver(nil,
+ NSSystemColorsDidChangeNotification, [this] {
handleSystemThemeChange();
- }];
+ });
}
QCocoaTheme::~QCocoaTheme()
{
- if (m_appearanceObserver)
- [m_appearanceObserver release];
-
reset();
qDeleteAll(m_fonts);
}
diff --git a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
index b00fde6c6f..7ce78ee738 100644
--- a/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
+++ b/src/plugins/platforms/cocoa/qcocoavulkaninstance.mm
@@ -54,7 +54,7 @@ QCocoaVulkanInstance::~QCocoaVulkanInstance()
void QCocoaVulkanInstance::createOrAdoptInstance()
{
- initInstance(m_instance, QByteArrayList());
+ initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_MVK_macos_surface"));
}
VkSurfaceKHR *QCocoaVulkanInstance::createSurface(QWindow *window)
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 67b0cbdfe9..363a026e71 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -1011,16 +1011,16 @@ void QCocoaWindow::setMask(const QRegion &region)
} else {
m_view.layer.mask = nil;
}
- }
-
- if (isContentView()) {
- // Setting the mask requires invalidating the NSWindow shadow, but that needs
- // to happen after the backingstore has been redrawn, so that AppKit can pick
- // up the new window shape based on the backingstore content. Doing a display
- // directly here is not an option, as the window might not be exposed at this
- // time, and so would not result in an updated backingstore.
- m_needsInvalidateShadow = true;
- [m_view setNeedsDisplay:YES];
+ } else {
+ if (isContentView()) {
+ // Setting the mask requires invalidating the NSWindow shadow, but that needs
+ // to happen after the backingstore has been redrawn, so that AppKit can pick
+ // up the new window shape based on the backingstore content. Doing a display
+ // directly here is not an option, as the window might not be exposed at this
+ // time, and so would not result in an updated backingstore.
+ m_needsInvalidateShadow = true;
+ [m_view setNeedsDisplay:YES];
+ }
}
}
diff --git a/src/plugins/platforms/cocoa/qnsview_mouse.mm b/src/plugins/platforms/cocoa/qnsview_mouse.mm
index 4408385aa8..7c566442f0 100644
--- a/src/plugins/platforms/cocoa/qnsview_mouse.mm
+++ b/src/plugins/platforms/cocoa/qnsview_mouse.mm
@@ -282,20 +282,19 @@
nativeDrag->setLastMouseEvent(theEvent, self);
const auto modifiers = [QNSView convertKeyModifiers:theEvent.modifierFlags];
- const auto buttons = currentlyPressedMouseButtons();
auto button = cocoaButton2QtButton(theEvent);
if (button == Qt::LeftButton && m_sendUpAsRightButton)
button = Qt::RightButton;
const auto eventType = cocoaEvent2QtMouseEvent(theEvent);
if (eventType == QEvent::MouseMove)
- qCDebug(lcQpaMouse) << eventType << "at" << qtWindowPoint << "with" << buttons;
+ qCDebug(lcQpaMouse) << eventType << "at" << qtWindowPoint << "with" << m_buttons;
else
- qCInfo(lcQpaMouse) << eventType << "of" << button << "at" << qtWindowPoint << "with" << buttons;
+ qCInfo(lcQpaMouse) << eventType << "of" << button << "at" << qtWindowPoint << "with" << m_buttons;
QWindowSystemInterface::handleMouseEvent(targetView->m_platformWindow->window(),
timestamp, qtWindowPoint, qtScreenPoint,
- buttons, button, eventType, modifiers);
+ m_buttons, button, eventType, modifiers);
}
- (bool)handleMouseDownEvent:(NSEvent *)theEvent
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h b/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h
index babe646fd8..6d880e24cf 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h
@@ -69,12 +69,15 @@ inline D2D1_RECT_F to_d2d_rect_f(const QRectF &qrect)
inline D2D1_SIZE_U to_d2d_size_u(const QSizeF &qsize)
{
- return D2D1::SizeU(qsize.width(), qsize.height());
+
+ return D2D1::SizeU(UINT32(qRound(qsize.width())),
+ UINT32(qRound(qsize.height())));
}
inline D2D1_SIZE_U to_d2d_size_u(const QSize &qsize)
{
- return D2D1::SizeU(qsize.width(), qsize.height());
+ return D2D1::SizeU(UINT32(qsize.width()),
+ UINT32(qsize.height()));
}
inline D2D1_POINT_2F to_d2d_point_2f(const QPointF &qpoint)
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
index 86c863ec50..e074f87eb4 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp
@@ -51,22 +51,11 @@
#include <QtCore/qversionnumber.h>
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/qpa/qwindowsysteminterface.h>
-#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
#include <QVarLengthArray>
QT_BEGIN_NAMESPACE
-class QWindowsDirect2DEventDispatcher : public QWindowsGuiEventDispatcher
-{
-public:
- QWindowsDirect2DEventDispatcher(QObject *parent = nullptr)
- : QWindowsGuiEventDispatcher(parent)
- {
- uninstallMessageHook(); // ### Workaround for QTBUG-42428
- }
-};
-
class QWindowsDirect2DIntegrationPrivate
{
public:
@@ -91,7 +80,7 @@ static QVersionNumber systemD2DVersion()
if (VerQueryValue(info.constData(), __TEXT("\\"),
reinterpret_cast<void **>(&fi), &size) && size) {
- const VS_FIXEDFILEINFO *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi);
+ const auto *verInfo = reinterpret_cast<const VS_FIXEDFILEINFO *>(fi);
return QVersionNumber{HIWORD(verInfo->dwFileVersionMS), LOWORD(verInfo->dwFileVersionMS),
HIWORD(verInfo->dwFileVersionLS), LOWORD(verInfo->dwFileVersionLS)};
}
@@ -140,7 +129,7 @@ QWindowsDirect2DIntegration *QWindowsDirect2DIntegration::create(const QStringLi
return nullptr;
}
- QWindowsDirect2DIntegration *integration = new QWindowsDirect2DIntegration(paramList);
+ auto *integration = new QWindowsDirect2DIntegration(paramList);
if (!integration->init()) {
delete integration;
@@ -188,11 +177,6 @@ QPlatformBackingStore *QWindowsDirect2DIntegration::createPlatformBackingStore(Q
return new QWindowsDirect2DBackingStore(window);
}
-QAbstractEventDispatcher *QWindowsDirect2DIntegration::createEventDispatcher() const
-{
- return new QWindowsDirect2DEventDispatcher;
-}
-
QWindowsDirect2DContext *QWindowsDirect2DIntegration::direct2DContext() const
{
return &d->m_d2dContext;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
index 19c7521eb7..5ea36e04bc 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.h
@@ -61,7 +61,6 @@ public:
QPlatformNativeInterface *nativeInterface() const override;
QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const override;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
- QAbstractEventDispatcher *createEventDispatcher() const override;
QWindowsDirect2DContext *direct2DContext() const;
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
index 1b82db0b37..d7aba66b2f 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp
@@ -253,7 +253,7 @@ struct D2DVectorPathCache {
static void cleanup_func(QPaintEngineEx *engine, void *data) {
Q_UNUSED(engine);
- D2DVectorPathCache *e = static_cast<D2DVectorPathCache *>(data);
+ auto *e = static_cast<D2DVectorPathCache *>(data);
delete e;
}
};
@@ -689,7 +689,7 @@ public:
*needsEmulation = true;
} else {
ComPtr<ID2D1LinearGradientBrush> linear;
- const QLinearGradient *qlinear = static_cast<const QLinearGradient *>(newBrush.gradient());
+ const auto *qlinear = static_cast<const QLinearGradient *>(newBrush.gradient());
D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES linearGradientBrushProperties;
ComPtr<ID2D1GradientStopCollection> gradientStopCollection;
@@ -727,7 +727,7 @@ public:
*needsEmulation = true;
} else {
ComPtr<ID2D1RadialGradientBrush> radial;
- const QRadialGradient *qradial = static_cast<const QRadialGradient *>(newBrush.gradient());
+ const auto *qradial = static_cast<const QRadialGradient *>(newBrush.gradient());
D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES radialGradientBrushProperties;
ComPtr<ID2D1GradientStopCollection> gradientStopCollection;
@@ -807,7 +807,7 @@ public:
: nullptr;
if (cacheEntry) {
- D2DVectorPathCache *e = static_cast<D2DVectorPathCache *>(cacheEntry->data);
+ auto *e = static_cast<D2DVectorPathCache *>(cacheEntry->data);
if (alias && e->aliased)
return e->aliased;
else if (!alias && e->antiAliased)
@@ -885,7 +885,7 @@ public:
if (!cacheEntry)
cacheEntry = path.addCacheData(q, new D2DVectorPathCache, D2DVectorPathCache::cleanup_func);
- D2DVectorPathCache *e = static_cast<D2DVectorPathCache *>(cacheEntry->data);
+ auto *e = static_cast<D2DVectorPathCache *>(cacheEntry->data);
if (alias)
e->aliased = geometry;
else
@@ -943,7 +943,11 @@ public:
// Default path (no optimization)
if (!(path.shape() == QVectorPath::LinesHint || path.shape() == QVectorPath::PolygonHint)
- || !pen.dashBrush || q->state()->renderHints.testFlag(QPainter::HighQualityAntialiasing)) {
+ || !pen.dashBrush
+#if QT_DEPRECATED_SINCE(5, 14)
+ || q->state()->renderHints.testFlag(QPainter::HighQualityAntialiasing)
+#endif
+ || q->state()->renderHints.testFlag(QPainter::Antialiasing)) {
ComPtr<ID2D1Geometry> geometry = vectorPathToID2D1PathGeometry(path);
if (!geometry) {
qWarning("%s: Could not convert path to d2d geometry", __FUNCTION__);
@@ -1481,7 +1485,7 @@ void QWindowsDirect2DPaintEngine::drawPixmap(const QRectF &r,
return;
}
- QWindowsDirect2DPlatformPixmap *pp = static_cast<QWindowsDirect2DPlatformPixmap *>(pm.handle());
+ auto *pp = static_cast<QWindowsDirect2DPlatformPixmap *>(pm.handle());
QWindowsDirect2DBitmap *bitmap = pp->bitmap();
ensurePen();
@@ -1593,7 +1597,7 @@ void QWindowsDirect2DPaintEngine::drawTextItem(const QPointF &p, const QTextItem
Q_D(QWindowsDirect2DPaintEngine);
D2D_TAG(D2DDebugDrawTextItemTag);
- const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+ const auto &ti = static_cast<const QTextItemInt &>(textItem);
if (ti.glyphs.numGlyphs == 0)
return;
@@ -1686,7 +1690,7 @@ void QWindowsDirect2DPaintEngine::rasterFill(const QVectorPath &path, const QBru
p.setBrush(state()->brush);
p.setPen(state()->pen);
- QPaintEngineEx *extended = static_cast<QPaintEngineEx *>(engine);
+ auto *extended = static_cast<QPaintEngineEx *>(engine);
for (const QPainterClipInfo &info : qAsConst(state()->clipInfo)) {
extended->state()->matrix = info.matrix;
extended->transformChanged();
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
index 239e5f3087..c417daaeae 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp
@@ -310,7 +310,7 @@ void QWindowsDirect2DWindow::setupBitmap()
QWindowsDirect2DPaintEngine::Flags flags = QWindowsDirect2DPaintEngine::NoFlag;
if (!m_directRendering)
flags |= QWindowsDirect2DPaintEngine::TranslucentTopLevelWindow;
- QWindowsDirect2DPlatformPixmap *pp = new QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixmapType,
+ auto *pp = new QWindowsDirect2DPlatformPixmap(QPlatformPixmap::PixmapType,
flags,
m_bitmap.data());
m_pixmap.reset(new QPixmap(pp));
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp
index 2e84915c80..07b2de7c58 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp
@@ -66,7 +66,7 @@ QAtomicInt running;
void EventReader::run()
{
xcb_generic_event_t *event = nullptr;
- while (running.load() && (event = xcb_wait_for_event(m_integration->connection()))) {
+ while (running.loadRelaxed() && (event = xcb_wait_for_event(m_integration->connection()))) {
uint response_type = event->response_type & ~0x80;
switch (response_type) {
case XCB_CLIENT_MESSAGE: {
diff --git a/src/plugins/platforms/ios/quiview_accessibility.mm b/src/plugins/platforms/ios/quiview_accessibility.mm
index a3f4156a59..458ddcc9b8 100644
--- a/src/plugins/platforms/ios/quiview_accessibility.mm
+++ b/src/plugins/platforms/ios/quiview_accessibility.mm
@@ -101,6 +101,8 @@
- (id)accessibilityElementAtIndex:(NSInteger)index
{
[self initAccessibility];
+ if (index >= [m_accessibleElements count])
+ return nil;
return m_accessibleElements[index];
}
@@ -110,4 +112,10 @@
return [m_accessibleElements indexOfObject:element];
}
+- (NSArray *)accessibilityElements
+{
+ [self initAccessibility];
+ return m_accessibleElements;
+}
+
@end
diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.cpp b/src/plugins/platforms/wasm/qwasmbackingstore.cpp
index 5b40c44807..e8eda2605f 100644
--- a/src/plugins/platforms/wasm/qwasmbackingstore.cpp
+++ b/src/plugins/platforms/wasm/qwasmbackingstore.cpp
@@ -55,6 +55,12 @@ QWasmBackingStore::~QWasmBackingStore()
{
}
+void QWasmBackingStore::destroy()
+{
+ if (m_texture->isCreated())
+ m_texture->destroy();
+}
+
QPaintDevice *QWasmBackingStore::paintDevice()
{
return &m_image;
diff --git a/src/plugins/platforms/wasm/qwasmbackingstore.h b/src/plugins/platforms/wasm/qwasmbackingstore.h
index 6ffa262e3d..4bca83c457 100644
--- a/src/plugins/platforms/wasm/qwasmbackingstore.h
+++ b/src/plugins/platforms/wasm/qwasmbackingstore.h
@@ -44,6 +44,7 @@ class QWasmBackingStore : public QPlatformBackingStore
public:
QWasmBackingStore(QWasmCompositor *compositor, QWindow *window);
~QWasmBackingStore();
+ void destroy();
QPaintDevice *paintDevice() override;
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.cpp b/src/plugins/platforms/wasm/qwasmcompositor.cpp
index e6a69c4814..6d211667be 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.cpp
+++ b/src/plugins/platforms/wasm/qwasmcompositor.cpp
@@ -37,6 +37,7 @@
#include <QtGui/qopenglcontext.h>
#include <QtGui/qopenglfunctions.h>
#include <QtGui/qopengltextureblitter.h>
+#include <QtGui/qoffscreensurface.h>
#include <QtGui/qpainter.h>
#include <private/qpixmapcache_p.h>
@@ -71,6 +72,28 @@ QWasmCompositor::QWasmCompositor(QWasmScreen *screen)
QWasmCompositor::~QWasmCompositor()
{
delete m_frameBuffer;
+ destroy();
+}
+
+void QWasmCompositor::destroy()
+{
+ // Destroy OpenGL resources. This is done here in a separate function
+ // which can be called while screen() still returns a valid screen
+ // (which it might not, during destruction). A valid QScreen is
+ // a requirement for QOffscreenSurface on Wasm since the native
+ // context is tied to a single canvas.
+ if (m_context) {
+ QOffscreenSurface offScreenSurface(screen()->screen());
+ offScreenSurface.setFormat(m_context->format());
+ offScreenSurface.create();
+ m_context->makeCurrent(&offScreenSurface);
+ for (QWasmWindow *window : m_windowStack)
+ window->destroy();
+ m_blitter.reset(nullptr);
+ m_context.reset(nullptr);
+ }
+
+ m_isEnabled = false; // prevent frame() from creating a new m_context
}
void QWasmCompositor::setEnabled(bool enabled)
@@ -251,10 +274,13 @@ void QWasmCompositor::blit(QOpenGLTextureBlitter *blitter, QWasmScreen *screen,
void QWasmCompositor::drawWindowContent(QOpenGLTextureBlitter *blitter, QWasmScreen *screen, QWasmWindow *window)
{
QWasmBackingStore *backingStore = window->backingStore();
+ if (!backingStore)
+ return;
QOpenGLTexture const *texture = backingStore->getUpdatedTexture();
-
- blit(blitter, screen, texture, window->geometry());
+ QPoint windowCanvasPosition = window->geometry().topLeft() - screen->geometry().topLeft();
+ QRect windowCanvasGeometry = QRect(windowCanvasPosition, window->geometry().size());
+ blit(blitter, screen, texture, windowCanvasGeometry);
}
QPalette QWasmCompositor::makeWindowPalette()
@@ -650,7 +676,7 @@ void QWasmCompositor::frame()
m_needComposit = false;
- if (m_windowStack.empty() || !screen())
+ if (!m_isEnabled || m_windowStack.empty() || !screen())
return;
QWasmWindow *someWindow = nullptr;
@@ -673,7 +699,9 @@ void QWasmCompositor::frame()
m_context->create();
}
- m_context->makeCurrent(someWindow->window());
+ bool ok = m_context->makeCurrent(someWindow->window());
+ if (!ok)
+ return;
if (!m_blitter->isCreated())
m_blitter->create();
diff --git a/src/plugins/platforms/wasm/qwasmcompositor.h b/src/plugins/platforms/wasm/qwasmcompositor.h
index 3104573073..98f4a79b27 100644
--- a/src/plugins/platforms/wasm/qwasmcompositor.h
+++ b/src/plugins/platforms/wasm/qwasmcompositor.h
@@ -64,6 +64,7 @@ class QWasmCompositor : public QObject
public:
QWasmCompositor(QWasmScreen *screen);
~QWasmCompositor();
+ void destroy();
enum QWasmSubControl {
SC_None = 0x00000000,
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
index 6a02a457a0..3895646b89 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -337,8 +337,6 @@ QWasmEventTranslator::QWasmEventTranslator(QWasmScreen *screen)
void QWasmEventTranslator::initEventHandlers()
{
- qDebug() << "QWasmEventTranslator::initEventHandlers";
-
QByteArray _canvasId = screen()->canvasId().toUtf8();
const char *canvasId = _canvasId.constData();
@@ -377,9 +375,6 @@ void QWasmEventTranslator::initEventHandlers()
emscripten_set_touchend_callback(canvasId, (void *)this, 1, &touchCallback);
emscripten_set_touchmove_callback(canvasId, (void *)this, 1, &touchCallback);
emscripten_set_touchcancel_callback(canvasId, (void *)this, 1, &touchCallback);
-
- emscripten_set_resize_callback(nullptr, (void *)this, 1, uiEvent_cb); // Note: handles browser window resize
-
}
template <typename Event>
@@ -557,9 +552,12 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
Qt::KeyboardModifiers modifiers = translateMouseEventModifier(mouseEvent);
QWindow *window2 = screen()->compositor()->windowAt(globalPoint, 5);
- if (window2 == nullptr)
- return;
- lastWindow = window2;
+
+ if (window2 == nullptr) {
+ window2 = lastWindow;
+ } else {
+ lastWindow = window2;
+ }
QPoint localPoint = window2->mapFromGlobal(globalPoint);
bool interior = window2->geometry().contains(globalPoint);
@@ -621,7 +619,7 @@ void QWasmEventTranslator::processMouse(int eventType, const EmscriptenMouseEven
}
if (resizeMode != QWasmWindow::ResizeNone && !(htmlWindow->m_windowState & Qt::WindowFullScreen)) {
- QPoint delta = QPoint(mouseEvent->canvasX, mouseEvent->canvasY) - resizePoint;
+ QPoint delta = QPoint(mouseEvent->targetX, mouseEvent->targetY) - resizePoint;
resizeWindow(draggedWindow, resizeMode, resizeStartRect, delta);
}
}
@@ -911,19 +909,4 @@ bool QWasmEventTranslator::processKeyboard(int eventType, const EmscriptenKeyboa
return accepted;
}
-int QWasmEventTranslator::uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData)
-{
- Q_UNUSED(e)
- QWasmEventTranslator *eventTranslator = static_cast<QWasmEventTranslator *>(userData);
-
- if (eventType == EMSCRIPTEN_EVENT_RESIZE) {
- // This resize event is called when the HTML window is resized. Depending
- // on the page layout the the canvas might also have been resized, so we
- // update the Qt screen size (and canvas render size).
- eventTranslator->screen()->updateQScreenAndCanvasRenderSize();
- }
-
- return 0;
-}
-
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.h b/src/plugins/platforms/wasm/qwasmeventtranslator.h
index d6043072ba..1655b7226a 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.h
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.h
@@ -57,8 +57,6 @@ public:
static int touchCallback(int eventType, const EmscriptenTouchEvent *ev, void *userData);
- static int uiEvent_cb(int eventType, const EmscriptenUiEvent *e, void *userData);
-
void processEvents();
void initEventHandlers();
int handleTouch(int eventType, const EmscriptenTouchEvent *touchEvent);
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index 31b9104de1..116612c286 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -35,6 +35,7 @@
#include "qwasmtheme.h"
#include "qwasmclipboard.h"
#include "qwasmservices.h"
+#include "qwasmoffscreensurface.h"
#include "qwasmwindow.h"
#ifndef QT_NO_OPENGL
@@ -123,6 +124,21 @@ QWasmIntegration::QWasmIntegration()
}
emscripten::val::global("window").set("onbeforeunload", val::module_property("qtBrowserBeforeUnload"));
+
+ // install browser window resize handler
+ auto onWindowResize = [](int eventType, const EmscriptenUiEvent *e, void *userData) -> int {
+ Q_UNUSED(eventType);
+ Q_UNUSED(e);
+ Q_UNUSED(userData);
+
+ // This resize event is called when the HTML window is resized. Depending
+ // on the page layout the the canvas(es) might also have been resized, so we
+ // update the Qt screen sizes (and canvas render sizes).
+ if (QWasmIntegration *integration = QWasmIntegration::get())
+ integration->resizeAllScreens();
+ return 0;
+ };
+ emscripten_set_resize_callback(nullptr, nullptr, 1, onWindowResize);
}
QWasmIntegration::~QWasmIntegration()
@@ -193,6 +209,11 @@ QPlatformInputContext *QWasmIntegration::inputContext() const
return m_inputContext.data();
}
+QPlatformOffscreenSurface *QWasmIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
+{
+ return new QWasmOffscrenSurface(surface);
+}
+
QPlatformFontDatabase *QWasmIntegration::fontDatabase() const
{
if (m_fontDb == nullptr)
@@ -257,7 +278,9 @@ void QWasmIntegration::addScreen(const QString &canvasId)
void QWasmIntegration::removeScreen(const QString &canvasId)
{
- QWindowSystemInterface::handleScreenRemoved(m_screens.take(canvasId));
+ QWasmScreen *exScreen = m_screens.take(canvasId);
+ exScreen->destroy(); // clean up before deleting the screen
+ QWindowSystemInterface::handleScreenRemoved(exScreen);
}
void QWasmIntegration::resizeScreen(const QString &canvasId)
@@ -275,4 +298,11 @@ void QWasmIntegration::updateDpi()
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen->screen(), dpiValue, dpiValue);
}
+void QWasmIntegration::resizeAllScreens()
+{
+ qDebug() << "resizeAllScreens";
+ for (QWasmScreen *screen : m_screens)
+ screen->updateQScreenAndCanvasRenderSize();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/wasm/qwasmintegration.h b/src/plugins/platforms/wasm/qwasmintegration.h
index c04c0eaecc..2102f5c226 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.h
+++ b/src/plugins/platforms/wasm/qwasmintegration.h
@@ -66,6 +66,7 @@ public:
#ifndef QT_NO_OPENGL
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override;
#endif
+ QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override;
QPlatformFontDatabase *fontDatabase() const override;
QAbstractEventDispatcher *createEventDispatcher() const override;
QVariant styleHint(QPlatformIntegration::StyleHint hint) const override;
@@ -85,6 +86,7 @@ public:
void addScreen(const QString &canvasId);
void removeScreen(const QString &canvasId);
void resizeScreen(const QString &canvasId);
+ void resizeAllScreens();
void updateDpi();
private:
diff --git a/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp b/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp
new file mode 100644
index 0000000000..a205e5ddea
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmoffscreensurface.cpp
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwasmoffscreensurface.h"
+
+QWasmOffscrenSurface::QWasmOffscrenSurface(QOffscreenSurface *offscreenSurface)
+ :QPlatformOffscreenSurface(offscreenSurface)
+{
+
+}
+
+QWasmOffscrenSurface::~QWasmOffscrenSurface()
+{
+
+}
diff --git a/src/plugins/platforms/wasm/qwasmoffscreensurface.h b/src/plugins/platforms/wasm/qwasmoffscreensurface.h
new file mode 100644
index 0000000000..9d3e805be0
--- /dev/null
+++ b/src/plugins/platforms/wasm/qwasmoffscreensurface.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWASMOFFSCREENSURFACE_H
+#define QWASMOFFSCREENSURFACE_H
+
+#include <qpa/qplatformoffscreensurface.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOffscreenSurface;
+class QWasmOffscrenSurface : public QPlatformOffscreenSurface
+{
+public:
+ explicit QWasmOffscrenSurface(QOffscreenSurface *offscreenSurface);
+ ~QWasmOffscrenSurface();
+private:
+
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
index 1658f32f9e..62087f54bd 100644
--- a/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
+++ b/src/plugins/platforms/wasm/qwasmopenglcontext.cpp
@@ -49,40 +49,31 @@ QWasmOpenGLContext::QWasmOpenGLContext(const QSurfaceFormat &format)
QWasmOpenGLContext::~QWasmOpenGLContext()
{
- if (m_context)
+ if (m_context) {
emscripten_webgl_destroy_context(m_context);
+ m_context = 0;
+ }
}
-void QWasmOpenGLContext::maybeRecreateEmscriptenContext(QPlatformSurface *surface)
+bool QWasmOpenGLContext::maybeCreateEmscriptenContext(QPlatformSurface *surface)
{
- // Native emscripten contexts are tied to a single surface. Recreate
- // the context if the surface is changed.
- if (surface != m_surface) {
- m_surface = surface;
-
- // Destroy existing context
- if (m_context)
- emscripten_webgl_destroy_context(m_context);
-
- // Create new context
- const QString canvasId = QWasmScreen::get(surface->screen())->canvasId();
- m_context = createEmscriptenContext(canvasId, m_requestedFormat);
-
- // Register context-lost callback.
- auto callback = [](int eventType, const void *reserved, void *userData) -> EM_BOOL
- {
- Q_UNUSED(eventType);
- Q_UNUSED(reserved);
- // The application may get contex-lost if e.g. moved to the background. Set
- // m_contextLost which will make isValid() return false. Application code will
- // then detect this and recrate the the context, resulting in a new QWasmOpenGLContext
- // instance.
- reinterpret_cast<QWasmOpenGLContext *>(userData)->m_contextLost = true;
- return true;
- };
- bool capture = true;
- emscripten_set_webglcontextlost_callback(canvasId.toLocal8Bit().constData(), this, capture, callback);
- }
+ // Native emscripten/WebGL contexts are tied to a single screen/canvas. The first
+ // call to this function creates a native canvas for the given screen, subsequent
+ // calls verify that the surface is on/off the same screen.
+ QPlatformScreen *screen = surface->screen();
+ if (m_context && !screen)
+ return false; // Alternative: return true to support makeCurrent on QOffScreenSurface with
+ // no screen. However, Qt likes to substitute QGuiApplication::primaryScreen()
+ // for null screens, which foils this plan.
+ if (!screen)
+ return false;
+ if (m_context)
+ return m_screen == screen;
+
+ QString canvasId = QWasmScreen::get(screen)->canvasId();
+ m_context = createEmscriptenContext(canvasId, m_requestedFormat);
+ m_screen = screen;
+ return true;
}
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE QWasmOpenGLContext::createEmscriptenContext(const QString &canvasId, QSurfaceFormat format)
@@ -125,7 +116,9 @@ GLuint QWasmOpenGLContext::defaultFramebufferObject(QPlatformSurface *surface) c
bool QWasmOpenGLContext::makeCurrent(QPlatformSurface *surface)
{
- maybeRecreateEmscriptenContext(surface);
+ bool ok = maybeCreateEmscriptenContext(surface);
+ if (!ok)
+ return false;
return emscripten_webgl_make_context_current(m_context) == EMSCRIPTEN_RESULT_SUCCESS;
}
@@ -148,7 +141,9 @@ bool QWasmOpenGLContext::isSharing() const
bool QWasmOpenGLContext::isValid() const
{
- return (m_contextLost == false);
+ // Note: we get isValid() calls before we see the surface and can
+ // create a native context, so no context is also a valid state.
+ return !m_context || !emscripten_is_webgl_context_lost(m_context);
}
QFunctionPointer QWasmOpenGLContext::getProcAddress(const char *procName)
diff --git a/src/plugins/platforms/wasm/qwasmopenglcontext.h b/src/plugins/platforms/wasm/qwasmopenglcontext.h
index 126b596a7e..d27007e8ea 100644
--- a/src/plugins/platforms/wasm/qwasmopenglcontext.h
+++ b/src/plugins/platforms/wasm/qwasmopenglcontext.h
@@ -34,6 +34,7 @@
QT_BEGIN_NAMESPACE
+class QPlatformScreen;
class QWasmOpenGLContext : public QPlatformOpenGLContext
{
public:
@@ -50,12 +51,11 @@ public:
QFunctionPointer getProcAddress(const char *procName) override;
private:
- void maybeRecreateEmscriptenContext(QPlatformSurface *surface);
+ bool maybeCreateEmscriptenContext(QPlatformSurface *surface);
static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE createEmscriptenContext(const QString &canvasId, QSurfaceFormat format);
- bool m_contextLost = false;
QSurfaceFormat m_requestedFormat;
- QPlatformSurface *m_surface = nullptr;
+ QPlatformScreen *m_screen = nullptr;
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE m_context = 0;
};
diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp
index af50ce7440..f2eabfa486 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.cpp
+++ b/src/plugins/platforms/wasm/qwasmscreen.cpp
@@ -58,7 +58,12 @@ QWasmScreen::QWasmScreen(const QString &canvasId)
QWasmScreen::~QWasmScreen()
{
+ destroy();
+}
+void QWasmScreen::destroy()
+{
+ m_compositor->destroy();
}
QWasmScreen *QWasmScreen::get(QPlatformScreen *screen)
diff --git a/src/plugins/platforms/wasm/qwasmscreen.h b/src/plugins/platforms/wasm/qwasmscreen.h
index 8d0d15f245..fcf693681c 100644
--- a/src/plugins/platforms/wasm/qwasmscreen.h
+++ b/src/plugins/platforms/wasm/qwasmscreen.h
@@ -52,6 +52,7 @@ class QWasmScreen : public QObject, public QPlatformScreen
public:
QWasmScreen(const QString &canvasId);
~QWasmScreen();
+ void destroy();
static QWasmScreen *get(QPlatformScreen *screen);
static QWasmScreen *get(QScreen *screen);
diff --git a/src/plugins/platforms/wasm/qwasmwindow.cpp b/src/plugins/platforms/wasm/qwasmwindow.cpp
index 39797cb09d..594db65cfd 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.cpp
+++ b/src/plugins/platforms/wasm/qwasmwindow.cpp
@@ -65,6 +65,12 @@ QWasmWindow::~QWasmWindow()
m_compositor->removeWindow(this);
}
+void QWasmWindow::destroy()
+{
+ if (m_backingStore)
+ m_backingStore->destroy();
+}
+
void QWasmWindow::initialize()
{
QRect rect = windowGeometry();
diff --git a/src/plugins/platforms/wasm/qwasmwindow.h b/src/plugins/platforms/wasm/qwasmwindow.h
index cbbce99aeb..a098172649 100644
--- a/src/plugins/platforms/wasm/qwasmwindow.h
+++ b/src/plugins/platforms/wasm/qwasmwindow.h
@@ -58,6 +58,7 @@ public:
QWasmWindow(QWindow *w, QWasmCompositor *compositor, QWasmBackingStore *backingStore);
~QWasmWindow();
+ void destroy();
void initialize() override;
diff --git a/src/plugins/platforms/wasm/wasm.pro b/src/plugins/platforms/wasm/wasm.pro
index e8728d9dba..c28df8f893 100644
--- a/src/plugins/platforms/wasm/wasm.pro
+++ b/src/plugins/platforms/wasm/wasm.pro
@@ -20,7 +20,8 @@ SOURCES = \
qwasmopenglcontext.cpp \
qwasmtheme.cpp \
qwasmclipboard.cpp \
- qwasmservices.cpp
+ qwasmservices.cpp \
+ qwasmoffscreensurface.cpp
HEADERS = \
qwasmintegration.h \
@@ -35,7 +36,8 @@ HEADERS = \
qwasmopenglcontext.h \
qwasmtheme.h \
qwasmclipboard.h \
- qwasmservices.h
+ qwasmservices.h \
+ qwasmoffscreensurface.h
wasmfonts.files = \
../../../3rdparty/wasm/Vera.ttf \
diff --git a/src/plugins/platforms/windows/qwin10helpers.cpp b/src/plugins/platforms/windows/qwin10helpers.cpp
index cc17d8798f..9a7fce9cd5 100644
--- a/src/plugins/platforms/windows/qwin10helpers.cpp
+++ b/src/plugins/platforms/windows/qwin10helpers.cpp
@@ -137,7 +137,7 @@ bool qt_windowsIsTabletMode(HWND hwnd)
const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
HSTRING_HEADER uiViewSettingsIdRefHeader;
HSTRING uiViewSettingsIdHs = nullptr;
- const UINT32 uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
+ const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
if (FAILED(baseComDll.windowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
return false;
diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
index 68807fabdd..bd7bdc55d1 100644
--- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp
+++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp
@@ -158,7 +158,7 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion &region)
format = qt_maybeAlphaVersionWithSameDepth(format);
QWindowsNativeImage *oldwni = m_image.data();
- QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format);
+ auto *newwni = new QWindowsNativeImage(size.width(), size.height(), format);
if (oldwni && !region.isEmpty()) {
const QImage &oldimg(oldwni->image());
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index e36a285aa2..f5b0dced93 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -77,6 +77,7 @@
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qsysinfo.h>
#include <QtCore/qscopedpointer.h>
+#include <QtCore/quuid.h>
#include <QtCore/private/qsystemlibrary_p.h>
#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
@@ -133,8 +134,8 @@ static inline bool useRTL_Extensions()
#if QT_CONFIG(sessionmanager)
static inline QWindowsSessionManager *platformSessionManager()
{
- QGuiApplicationPrivate *guiPrivate = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
- QSessionManagerPrivate *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(guiPrivate->session_manager));
+ auto *guiPrivate = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
+ auto *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(guiPrivate->session_manager));
return static_cast<QWindowsSessionManager *>(managerPrivate->platformSessionManager);
}
@@ -317,6 +318,8 @@ QWindowsContext::~QWindowsContext()
OleUninitialize();
d->m_screenManager.clearScreens(); // Order: Potentially calls back to the windows.
+ if (d->m_displayContext)
+ ReleaseDC(nullptr, d->m_displayContext);
m_instance = nullptr;
}
@@ -542,10 +545,10 @@ QString QWindowsContext::registerWindowClass(QString cname,
// each one has to have window class names with a unique name
// The first instance gets the unmodified name; if the class
// has already been registered by another instance of Qt then
- // add an instance-specific ID, the address of the window proc.
+ // add a UUID.
static int classExists = -1;
- const HINSTANCE appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
+ const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
if (classExists == -1) {
WNDCLASS wcinfo;
classExists = GetClassInfo(appInstance, reinterpret_cast<LPCWSTR>(cname.utf16()), &wcinfo);
@@ -553,7 +556,7 @@ QString QWindowsContext::registerWindowClass(QString cname,
}
if (classExists)
- cname += QString::number(reinterpret_cast<quintptr>(proc));
+ cname += QUuid::createUuid().toString();
if (d->m_registeredWindowClassNames.contains(cname)) // already registered in our list
return cname;
@@ -598,7 +601,7 @@ QString QWindowsContext::registerWindowClass(QString cname,
void QWindowsContext::unregisterWindowClasses()
{
- const HINSTANCE appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
+ const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
for (const QString &name : qAsConst(d->m_registeredWindowClassNames)) {
if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose)
@@ -749,6 +752,12 @@ QWindowsWindow *QWindowsContext::findPlatformWindowAt(HWND parent,
QWindowsWindow *result = nullptr;
const POINT screenPoint = { screenPointIn.x(), screenPointIn.y() };
while (findPlatformWindowHelper(screenPoint, cwex_flags, this, &parent, &result)) {}
+ // QTBUG-40815: ChildWindowFromPointEx() can hit on special windows from
+ // screen recorder applications like ScreenToGif. Fall back to WindowFromPoint().
+ if (result == nullptr) {
+ if (const HWND window = WindowFromPoint(screenPoint))
+ result = findPlatformWindow(window);
+ }
return result;
}
@@ -925,7 +934,7 @@ bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void
bool QWindowsContext::systemParametersInfoForScreen(unsigned action, unsigned param, void *out,
const QPlatformScreen *screen)
{
- return systemParametersInfo(action, param, out, screen ? screen->logicalDpi().first : 0);
+ return systemParametersInfo(action, param, out, screen ? unsigned(screen->logicalDpi().first) : 0u);
}
bool QWindowsContext::systemParametersInfoForWindow(unsigned action, unsigned param, void *out,
@@ -944,7 +953,8 @@ bool QWindowsContext::nonClientMetrics(NONCLIENTMETRICS *ncm, unsigned dpi)
bool QWindowsContext::nonClientMetricsForScreen(NONCLIENTMETRICS *ncm,
const QPlatformScreen *screen)
{
- return nonClientMetrics(ncm, screen ? screen->logicalDpi().first : 0);
+ const int dpi = screen ? qRound(screen->logicalDpi().first) : 0;
+ return nonClientMetrics(ncm, unsigned(dpi));
}
bool QWindowsContext::nonClientMetricsForWindow(NONCLIENTMETRICS *ncm, const QPlatformWindow *win)
@@ -1351,7 +1361,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
sessionManager->blocksInteraction();
sessionManager->clearCancellation();
- QGuiApplicationPrivate *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
+ auto *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
qGuiAppPriv->commitData();
if (lParam & ENDSESSION_LOGOFF)
@@ -1369,7 +1379,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
// we receive the message for each toplevel window included internal hidden ones,
// but the aboutToQuit signal should be emitted only once.
- QGuiApplicationPrivate *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
+ auto *qGuiAppPriv = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
if (endsession && !qGuiAppPriv->aboutToQuitEmitted) {
qGuiAppPriv->aboutToQuitEmitted = true;
int index = QGuiApplication::staticMetaObject.indexOfSignal("aboutToQuit()");
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 20a8117304..17e8cffb76 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -752,7 +752,7 @@ QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const
&& GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor)
&& bmColor.bmWidth == bmColor.bmWidthBytes / 4) {
const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes;
- uchar *colorBits = new uchar[colorBitsLength];
+ auto *colorBits = new uchar[colorBitsLength];
GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits);
const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight,
bmColor.bmWidthBytes, QImage::Format_ARGB32);
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 57f19b5ff2..b7ab952a1d 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -356,7 +356,7 @@ struct FindDialogContext
static BOOL QT_WIN_CALLBACK findDialogEnumWindowsProc(HWND hwnd, LPARAM lParam)
{
- FindDialogContext *context = reinterpret_cast<FindDialogContext *>(lParam);
+ auto *context = reinterpret_cast<FindDialogContext *>(lParam);
DWORD winPid = 0;
GetWindowThreadProcessId(hwnd, &winPid);
if (winPid != context->processId)
@@ -531,7 +531,7 @@ private:
IFileDialogEvents *QWindowsNativeFileDialogEventHandler::create(QWindowsNativeFileDialogBase *nativeFileDialog)
{
IFileDialogEvents *result;
- QWindowsNativeFileDialogEventHandler *eventHandler = new QWindowsNativeFileDialogEventHandler(nativeFileDialog);
+ auto *eventHandler = new QWindowsNativeFileDialogEventHandler(nativeFileDialog);
if (FAILED(eventHandler->QueryInterface(IID_IFileDialogEvents, reinterpret_cast<void **>(&result)))) {
qErrnoWarning("Unable to obtain IFileDialogEvents");
return nullptr;
@@ -1112,7 +1112,7 @@ void QWindowsNativeFileDialogBase::setDefaultSuffixSys(const QString &s)
// If this parameter is non-empty, it will be appended by the dialog for the 'Any files'
// filter ('*'). If this parameter is non-empty and the current filter has a suffix,
// the dialog will append the filter's suffix.
- wchar_t *wSuffix = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(s.utf16()));
+ auto *wSuffix = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(s.utf16()));
m_fileDialog->SetDefaultExtension(wSuffix);
}
@@ -1125,7 +1125,7 @@ static inline IFileDialog2 *getFileDialog2(IFileDialog *fileDialog)
void QWindowsNativeFileDialogBase::setLabelText(QFileDialogOptions::DialogLabel l, const QString &text)
{
- wchar_t *wText = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(text.utf16()));
+ auto *wText = const_cast<wchar_t *>(reinterpret_cast<const wchar_t *>(text.utf16()));
switch (l) {
case QFileDialogOptions::FileName:
m_fileDialog->SetFileNameLabel(wText);
@@ -1770,7 +1770,7 @@ void QWindowsXpNativeFileDialog::doExec(HWND owner)
static int QT_WIN_CALLBACK xpFileDialogGetExistingDirCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
- QWindowsXpNativeFileDialog *dialog = reinterpret_cast<QWindowsXpNativeFileDialog *>(lpData);
+ auto *dialog = reinterpret_cast<QWindowsXpNativeFileDialog *>(lpData);
return dialog->existingDirCallback(hwnd, uMsg, lParam);
}
@@ -1843,7 +1843,7 @@ void QWindowsXpNativeFileDialog::populateOpenFileName(OPENFILENAME *ofn, HWND ow
const QList<FilterSpec> specs =
filterSpecs(m_options->nameFilters(), m_options->options() & QFileDialogOptions::HideNameFilterDetails, &totalStringLength);
const int size = specs.size();
- wchar_t *ptr = new wchar_t[totalStringLength + 2 * size + 1];
+ auto *ptr = new wchar_t[totalStringLength + 2 * size + 1];
ofn->lpstrFilter = ptr;
for (const FilterSpec &spec : specs) {
ptr += spec.description.toWCharArray(ptr);
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 502c92ef59..3e4c93d47a 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -627,7 +627,7 @@ QWindowsOleDropTarget::Drop(LPDATAOBJECT pDataObj, DWORD grfKeyState,
m_chosenEffect = DROPEFFECT_COPY;
HGLOBAL hData = GlobalAlloc(0, sizeof(DWORD));
if (hData) {
- DWORD *moveEffect = reinterpret_cast<DWORD *>(GlobalLock(hData));
+ auto *moveEffect = reinterpret_cast<DWORD *>(GlobalLock(hData));
*moveEffect = DROPEFFECT_MOVE;
GlobalUnlock(hData);
STGMEDIUM medium;
@@ -704,9 +704,9 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag)
DWORD resultEffect;
QWindowsDrag::m_canceled = false;
- QWindowsOleDropSource *windowDropSource = new QWindowsOleDropSource(this);
+ auto *windowDropSource = new QWindowsOleDropSource(this);
windowDropSource->createCursors();
- QWindowsDropDataObject *dropDataObject = new QWindowsDropDataObject(dropData);
+ auto *dropDataObject = new QWindowsDropDataObject(dropData);
const Qt::DropActions possibleActions = drag->supportedActions();
const DWORD allowedEffects = translateToWinDragEffects(possibleActions);
qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x"
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index 063e81150e..e9f3dc5189 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -469,10 +469,10 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
+ auto *window = static_cast<QWindowsWindow *>(surface);
window->aboutToMakeCurrent();
int err = 0;
- EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
+ auto eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
if (eglSurface == EGL_NO_SURFACE) {
if (err == EGL_CONTEXT_LOST) {
m_eglContext = EGL_NO_CONTEXT;
@@ -531,9 +531,9 @@ void QWindowsEGLContext::doneCurrent()
void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
{
QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
- QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
+ auto *window = static_cast<QWindowsWindow *>(surface);
int err = 0;
- EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
+ auto eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
if (eglSurface == EGL_NO_SURFACE) {
if (err == EGL_CONTEXT_LOST) {
m_eglContext = EGL_NO_CONTEXT;
diff --git a/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp b/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
index 08e11c5e39..f2418b0e60 100644
--- a/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsgdinativeinterface.cpp
@@ -50,7 +50,7 @@ void *QWindowsGdiNativeInterface::nativeResourceForBackingStore(const QByteArray
qWarning("%s: '%s' requested for null backingstore or backingstore without handle.", __FUNCTION__, resource.constData());
return nullptr;
}
- QWindowsBackingStore *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
+ auto *wbs = static_cast<QWindowsBackingStore *>(bs->handle());
if (resource == "getDC")
return wbs->getDC();
qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 66dd32d05e..24526bad2c 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -1009,7 +1009,7 @@ QOpenGLStaticContext *QOpenGLStaticContext::create(bool softwareRendering)
QScopedPointer<QOpenGLTemporaryContext> temporaryContext;
if (!QOpenGLStaticContext::opengl32.wglGetCurrentContext())
temporaryContext.reset(new QOpenGLTemporaryContext);
- QOpenGLStaticContext *result = new QOpenGLStaticContext;
+ auto *result = new QOpenGLStaticContext;
qCDebug(lcQpaGl) << __FUNCTION__ << *result;
return result;
}
@@ -1051,7 +1051,7 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext,
qWarning("QWindowsGLContext: Requires a QWGLNativeContext");
return;
}
- QWGLNativeContext handle = nativeHandle.value<QWGLNativeContext>();
+ auto handle = nativeHandle.value<QWGLNativeContext>();
HGLRC wglcontext = handle.context();
HWND wnd = handle.window();
if (!wglcontext || !wnd) {
@@ -1233,7 +1233,7 @@ bool QWindowsGLContext::updateObtainedParams(HDC hdc, int *obtainedSwapInterval)
hasRobustness = exts && strstr(exts, "GL_ARB_robustness");
} else {
typedef const GLubyte * (APIENTRY *glGetStringi_t)(GLenum, GLuint);
- glGetStringi_t glGetStringi = reinterpret_cast<glGetStringi_t>(
+ auto glGetStringi = reinterpret_cast<glGetStringi_t>(
reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress("glGetStringi")));
if (glGetStringi) {
GLint n = 0;
@@ -1305,7 +1305,7 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface)
Q_ASSERT(surface->surface()->supportsOpenGL());
// Do we already have a DC entry for that window?
- QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
+ auto *window = static_cast<QWindowsWindow *>(surface);
window->aboutToMakeCurrent();
const HWND hwnd = window->handle();
if (const QOpenGLContextData *contextData = findByHWND(m_windowContexts, hwnd)) {
@@ -1374,7 +1374,7 @@ QFunctionPointer QWindowsGLContext::getProcAddress(const char *procName)
// Even though we use QFunctionPointer, it does not mean the function can be called.
// It will need to be cast to the proper function type with the correct calling
// convention. QFunctionPointer is nothing more than a glorified void* here.
- QFunctionPointer procAddress = reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(procName));
+ auto procAddress = reinterpret_cast<QFunctionPointer>(QOpenGLStaticContext::opengl32.wglGetProcAddress(procName));
// We support AllGLFunctionsQueryable, which means this function must be able to
// return a function pointer even for functions that are in GL.h and exported
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 71ed33f85b..e681dbb0cb 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -717,7 +717,7 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv)
reconv->dwCompStrOffset = DWORD(startPos) * sizeof(ushort); // byte count.
reconv->dwTargetStrLen = reconv->dwCompStrLen;
reconv->dwTargetStrOffset = reconv->dwCompStrOffset;
- ushort *pastReconv = reinterpret_cast<ushort *>(reconv + 1);
+ auto *pastReconv = reinterpret_cast<ushort *>(reconv + 1);
std::copy(surroundingText.utf16(), surroundingText.utf16() + surroundingText.size(),
QT_MAKE_UNCHECKED_ARRAY_ITERATOR(pastReconv));
return memSize;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index f0754e3e57..eccf1c4928 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -324,7 +324,7 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co
QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) const
{
if (window->type() == Qt::Desktop) {
- QWindowsDesktopWindow *result = new QWindowsDesktopWindow(window);
+ auto *result = new QWindowsDesktopWindow(window);
qCDebug(lcQpaWindows) << "Desktop window:" << window
<< Qt::showbase << Qt::hex << result->winId() << Qt::noshowbase << Qt::dec << result->geometry();
return result;
@@ -371,7 +371,7 @@ QPlatformWindow *QWindowsIntegration::createForeignWindow(QWindow *window, WId n
qWarning("Windows QPA: Invalid foreign window ID %p.", hwnd);
return nullptr;
}
- QWindowsForeignWindow *result = new QWindowsForeignWindow(window, hwnd);
+ auto *result = new QWindowsForeignWindow(window, hwnd);
const QRect obtainedGeometry = result->geometry();
QScreen *screen = nullptr;
if (const QPlatformScreen *pScreen = result->screenForGeometry(obtainedGeometry))
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 44668cde78..4b54051e0c 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -100,7 +100,7 @@ QWindowsKeyMapper::QWindowsKeyMapper()
: m_useRTLExtensions(false), m_keyGrabber(nullptr)
{
memset(keyLayout, 0, sizeof(keyLayout));
- QGuiApplication *app = static_cast<QGuiApplication *>(QGuiApplication::instance());
+ auto *app = static_cast<QGuiApplication *>(QGuiApplication::instance());
QObject::connect(app, &QGuiApplication::applicationStateChanged,
app, clearKeyRecorderOnApplicationInActive);
changeKeyboard();
@@ -950,7 +950,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
const UINT msgType = msg.message;
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
- quint32 vk_key = quint32(msg.wParam);
+ auto vk_key = quint32(msg.wParam);
quint32 nModifiers = 0;
QWindow *receiver = m_keyGrabber ? m_keyGrabber : window;
@@ -1182,7 +1182,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
// results, if we map this virtual key-code directly (for eg '?' US layouts). So try
// to find the correct key using the current message parameters & keyboard state.
if (uch.isNull() && msgType == WM_IME_KEYDOWN) {
- const QWindowsInputContext *windowsInputContext =
+ const auto *windowsInputContext =
qobject_cast<const QWindowsInputContext *>(QWindowsIntegration::instance()->inputContext());
if (!(windowsInputContext && windowsInputContext->isComposing()))
vk_key = ImmGetVirtualKey(reinterpret_cast<HWND>(window->winId()));
diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp
index e55e283fe1..d20edd685e 100644
--- a/src/plugins/platforms/windows/qwindowsmenu.cpp
+++ b/src/plugins/platforms/windows/qwindowsmenu.cpp
@@ -518,7 +518,7 @@ QWindowsMenu::~QWindowsMenu()
void QWindowsMenu::insertMenuItem(QPlatformMenuItem *menuItemIn, QPlatformMenuItem *before)
{
qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << menuItemIn << ", before=" << before << ')' << this;
- QWindowsMenuItem *menuItem = static_cast<QWindowsMenuItem *>(menuItemIn);
+ auto *menuItem = static_cast<QWindowsMenuItem *>(menuItemIn);
const int index = insertBefore(&m_menuItems, menuItemIn, before);
const bool append = index == m_menuItems.size() - 1;
menuItem->insertIntoMenu(this, append, index);
@@ -689,7 +689,7 @@ void QWindowsPopupMenu::showPopup(const QWindow *parentWindow, const QRect &targ
const QPlatformMenuItem *item)
{
qCDebug(lcQpaMenus) << __FUNCTION__ << '>' << this << parentWindow << targetRect << item;
- const QWindowsBaseWindow *window = static_cast<const QWindowsBaseWindow *>(parentWindow->handle());
+ const auto *window = static_cast<const QWindowsBaseWindow *>(parentWindow->handle());
const QPoint globalPos = window->mapToGlobal(targetRect.topLeft());
trackPopupMenu(window->handle(), globalPos.x(), globalPos.y());
}
@@ -756,7 +756,7 @@ QWindowsMenuBar::~QWindowsMenuBar()
void QWindowsMenuBar::insertMenu(QPlatformMenu *menuIn, QPlatformMenu *before)
{
qCDebug(lcQpaMenus) << __FUNCTION__ << menuIn << "before=" << before;
- QWindowsMenu *menu = static_cast<QWindowsMenu *>(menuIn);
+ auto *menu = static_cast<QWindowsMenu *>(menuIn);
const int index = insertBefore(&m_menus, menuIn, before);
menu->insertIntoMenuBar(this, index == m_menus.size() - 1, index);
}
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 030d8d1e0f..b9d8b191f5 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -178,7 +178,7 @@ static bool qt_write_dibv5(QDataStream &s, QImage image)
if (image.format() != QImage::Format_ARGB32)
image = image.convertToFormat(QImage::Format_ARGB32);
- uchar *buf = new uchar[bpl_bmp];
+ auto *buf = new uchar[bpl_bmp];
memset(buf, 0, size_t(bpl_bmp));
for (int y=image.height()-1; y>=0; y--) {
@@ -264,7 +264,7 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image)
const int bpl = image.bytesPerLine();
uchar *data = image.bits();
- uchar *buf24 = new uchar[bpl];
+ auto *buf24 = new uchar[bpl];
const int bpl24 = ((w * nbits + 31) / 32) * 4;
while (--h >= 0) {
@@ -286,7 +286,7 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image)
if (bi.bV5Height < 0) {
// Flip the image
- uchar *buf = new uchar[bpl];
+ auto *buf = new uchar[bpl];
h = -bi.bV5Height;
for (int y = 0; y < h/2; ++y) {
memcpy(buf, data + y * bpl, size_t(bpl));
@@ -772,16 +772,16 @@ bool QWindowsMimeURI::convertFromMime(const FORMATETC &formatetc, const QMimeDat
}
QByteArray result(size, '\0');
- DROPFILES* d = reinterpret_cast<DROPFILES *>(result.data());
+ auto* d = reinterpret_cast<DROPFILES *>(result.data());
d->pFiles = sizeof(DROPFILES);
GetCursorPos(&d->pt); // try
d->fNC = true;
char *files = (reinterpret_cast<char*>(d)) + d->pFiles;
d->fWide = true;
- wchar_t *f = reinterpret_cast<wchar_t *>(files);
+ auto *f = reinterpret_cast<wchar_t *>(files);
for (int i=0; i<fileNames.size(); i++) {
- const size_t l = size_t(fileNames.at(i).length());
+ const auto l = size_t(fileNames.at(i).length());
memcpy(f, fileNames.at(i).utf16(), l * sizeof(ushort));
f += l;
*f++ = 0;
@@ -852,9 +852,9 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD
if (data.isEmpty())
return QVariant();
- const DROPFILES *hdrop = reinterpret_cast<const DROPFILES *>(data.constData());
+ const auto *hdrop = reinterpret_cast<const DROPFILES *>(data.constData());
if (hdrop->fWide) {
- const wchar_t *filesw = reinterpret_cast<const wchar_t *>(data.constData() + hdrop->pFiles);
+ const auto *filesw = reinterpret_cast<const wchar_t *>(data.constData() + hdrop->pFiles);
int i = 0;
while (filesw[i]) {
QString fileurl = QString::fromWCharArray(filesw + i);
@@ -1055,7 +1055,7 @@ QVector<FORMATETC> QWindowsMimeImage::formatsForMime(const QString &mimeType, co
QVector<FORMATETC> formatetcs;
if (mimeData->hasImage() && mimeType == QLatin1String("application/x-qt-image")) {
//add DIBV5 if image has alpha channel. Do not add CF_PNG here as it will confuse MS Office (QTBUG47656).
- QImage image = qvariant_cast<QImage>(mimeData->imageData());
+ auto image = qvariant_cast<QImage>(mimeData->imageData());
if (!image.isNull() && image.hasAlphaChannel())
formatetcs += setCf(CF_DIBV5);
formatetcs += setCf(CF_DIB);
@@ -1097,7 +1097,7 @@ bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeD
{
int cf = getCf(formatetc);
if ((cf == CF_DIB || cf == CF_DIBV5 || cf == int(CF_PNG)) && mimeData->hasImage()) {
- QImage img = qvariant_cast<QImage>(mimeData->imageData());
+ auto img = qvariant_cast<QImage>(mimeData->imageData());
if (img.isNull())
return false;
QByteArray ba;
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index c15819a65f..6df5e6aa27 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -127,7 +127,7 @@ static inline QTouchDevice *createTouchDevice()
qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY)
<< "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase
<< "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints;
- QTouchDevice *result = new QTouchDevice;
+ auto *result = new QTouchDevice;
result->setType(digitizers & NID_INTEGRATED_TOUCH
? QTouchDevice::TouchScreen : QTouchDevice::TouchPad);
QTouchDevice::Capabilities capabilities = QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition;
@@ -306,7 +306,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
// However, when tablet support is active, extraInfo is a packet serial number. This is not a problem
// since we do not want to ignore mouse events coming from a tablet.
// See https://msdn.microsoft.com/en-us/library/windows/desktop/ms703320.aspx
- const quint64 extraInfo = quint64(GetMessageExtraInfo());
+ const auto extraInfo = quint64(GetMessageExtraInfo());
if ((extraInfo & signatureMask) == miWpSignature) {
if (extraInfo & 0x80) { // Bit 7 indicates touch event, else tablet pen.
source = Qt::MouseEventSynthesizedBySystem;
@@ -370,7 +370,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd,
return true;
}
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+ auto *platformWindow = static_cast<QWindowsWindow *>(window->handle());
// If the window was recently resized via mouse doubleclick on the frame or title bar,
// we don't get WM_LBUTTONDOWN or WM_LBUTTONDBLCLK for the second click,
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index e581b30ced..d1d181d66e 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -98,7 +98,7 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc
qWarning("%s: '%s' requested for null window or window without handle.", __FUNCTION__, resource.constData());
return nullptr;
}
- QWindowsWindow *bw = static_cast<QWindowsWindow *>(window->handle());
+ auto *bw = static_cast<QWindowsWindow *>(window->handle());
int type = resourceType(resource);
if (type == HandleType)
return bw->handle();
@@ -131,7 +131,7 @@ void *QWindowsNativeInterface::nativeResourceForScreen(const QByteArray &resourc
qWarning("%s: '%s' requested for null screen or screen without handle.", __FUNCTION__, resource.constData());
return nullptr;
}
- QWindowsScreen *bs = static_cast<QWindowsScreen *>(screen->handle());
+ auto *bs = static_cast<QWindowsScreen *>(screen->handle());
int type = resourceType(resource);
if (type == HandleType)
return bs->handle();
@@ -157,7 +157,7 @@ static const char customMarginPropertyC[] = "WindowsCustomMargins";
QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const QString &name) const
{
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window);
+ auto *platformWindow = static_cast<QWindowsWindow *>(window);
if (name == QLatin1String(customMarginPropertyC))
return QVariant::fromValue(platformWindow->customMargins());
return QVariant();
@@ -171,7 +171,7 @@ QVariant QWindowsNativeInterface::windowProperty(QPlatformWindow *window, const
void QWindowsNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value)
{
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window);
+ auto *platformWindow = static_cast<QWindowsWindow *>(window);
if (name == QLatin1String(customMarginPropertyC))
platformWindow->setCustomMargins(qvariant_cast<QMargins>(value));
}
@@ -206,7 +206,7 @@ void *QWindowsNativeInterface::nativeResourceForContext(const QByteArray &resour
return nullptr;
}
- QWindowsOpenGLContext *glcontext = static_cast<QWindowsOpenGLContext *>(context->handle());
+ auto *glcontext = static_cast<QWindowsOpenGLContext *>(context->handle());
switch (resourceType(resource)) {
case RenderingContextType: // Fall through.
case EglContextType:
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index fb6a74581a..f3450e2806 100644
--- a/src/plugins/platforms/windows/qwindowsole.cpp
+++ b/src/plugins/platforms/windows/qwindowsole.cpp
@@ -155,7 +155,7 @@ QWindowsOleDataObject::SetData(LPFORMATETC pFormatetc, STGMEDIUM *pMedium, BOOL
HRESULT hr = ResultFromScode(E_NOTIMPL);
if (pFormatetc->cfFormat == CF_PERFORMEDDROPEFFECT && pMedium->tymed == TYMED_HGLOBAL) {
- DWORD * val = (DWORD*)GlobalLock(pMedium->hGlobal);
+ auto * val = (DWORD*)GlobalLock(pMedium->hGlobal);
performedEffect = *val;
GlobalUnlock(pMedium->hGlobal);
if (fRelease)
@@ -193,7 +193,7 @@ QWindowsOleDataObject::EnumFormatEtc(DWORD dwDirection, LPENUMFORMATETC FAR* ppe
fmtetcs.append(formatetc);
}
- QWindowsOleEnumFmtEtc *enumFmtEtc = new QWindowsOleEnumFmtEtc(fmtetcs);
+ auto *enumFmtEtc = new QWindowsOleEnumFmtEtc(fmtetcs);
*ppenumFormatEtc = enumFmtEtc;
if (enumFmtEtc->isNull()) {
delete enumFmtEtc;
@@ -237,7 +237,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs)
qCDebug(lcQpaMime) << __FUNCTION__ << fmtetcs;
m_lpfmtetcs.reserve(fmtetcs.count());
for (int idx = 0; idx < fmtetcs.count(); ++idx) {
- LPFORMATETC destetc = new FORMATETC();
+ auto destetc = new FORMATETC();
if (copyFormatEtc(destetc, &(fmtetcs.at(idx)))) {
m_lpfmtetcs.append(destetc);
} else {
@@ -255,7 +255,7 @@ QWindowsOleEnumFmtEtc::QWindowsOleEnumFmtEtc(const QVector<LPFORMATETC> &lpfmtet
m_lpfmtetcs.reserve(lpfmtetcs.count());
for (int idx = 0; idx < lpfmtetcs.count(); ++idx) {
LPFORMATETC srcetc = lpfmtetcs.at(idx);
- LPFORMATETC destetc = new FORMATETC();
+ auto destetc = new FORMATETC();
if (copyFormatEtc(destetc, srcetc)) {
m_lpfmtetcs.append(destetc);
} else {
@@ -357,7 +357,7 @@ QWindowsOleEnumFmtEtc::Clone(LPENUMFORMATETC FAR* newEnum)
if (newEnum == nullptr)
return ResultFromScode(E_INVALIDARG);
- QWindowsOleEnumFmtEtc *result = new QWindowsOleEnumFmtEtc(m_lpfmtetcs);
+ auto *result = new QWindowsOleEnumFmtEtc(m_lpfmtetcs);
result->m_nIndex = m_nIndex;
if (result->isNull()) {
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index ff495c8290..afc1991e2c 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -457,7 +457,7 @@ bool QWindowsOpenGLTester::testDesktopGL()
// Check the version. If we got 1.x then it's all hopeless and we can stop right here.
typedef const GLubyte * (APIENTRY * GetString_t)(GLenum name);
- GetString_t GetString = reinterpret_cast<GetString_t>(
+ auto GetString = reinterpret_cast<GetString_t>(
reinterpret_cast<QFunctionPointer>(::GetProcAddress(lib, "glGetString")));
if (GetString) {
if (const char *versionStr = reinterpret_cast<const char *>(GetString(GL_VERSION))) {
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 36c614af34..b3d961db72 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -269,7 +269,10 @@ static Qt::MouseButtons queryMouseButtons()
static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos)
{
- QWindow *currentWindowUnderPointer = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
+ QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+
+ QWindow *currentWindowUnderPointer = platformWindow->hasMouseCapture() ?
+ QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT) : window;
while (currentWindowUnderPointer && currentWindowUnderPointer->flags() & Qt::WindowTransparentForInput)
currentWindowUnderPointer = currentWindowUnderPointer->parent();
@@ -318,7 +321,7 @@ static QTouchDevice *createTouchDevice()
qCDebug(lcQpaEvents) << "Digitizers:" << Qt::hex << Qt::showbase << (digitizers & ~NID_READY)
<< "Ready:" << (digitizers & NID_READY) << Qt::dec << Qt::noshowbase
<< "Tablet PC:" << tabletPc << "Max touch points:" << maxTouchPoints;
- QTouchDevice *result = new QTouchDevice;
+ auto *result = new QTouchDevice;
result->setType(digitizers & NID_INTEGRATED_TOUCH
? QTouchDevice::TouchScreen : QTouchDevice::TouchPad);
QTouchDevice::Capabilities capabilities = QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition;
@@ -348,7 +351,7 @@ void QWindowsPointerHandler::handleCaptureRelease(QWindow *window,
QEvent::Type eventType,
Qt::MouseButtons mouseButtons)
{
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+ auto *platformWindow = static_cast<QWindowsWindow *>(window->handle());
// Qt expects the platform plugin to capture the mouse on any button press until release.
if (!platformWindow->hasMouseCapture() && eventType == QEvent::MouseButtonPress) {
@@ -384,7 +387,7 @@ void QWindowsPointerHandler::handleEnterLeave(QWindow *window,
QWindow *currentWindowUnderPointer,
QPoint globalPos)
{
- QWindowsWindow *platformWindow = static_cast<QWindowsWindow *>(window->handle());
+ auto *platformWindow = static_cast<QWindowsWindow *>(window->handle());
const bool hasCapture = platformWindow->hasMouseCapture();
// No enter or leave events are sent as long as there is an autocapturing window.
@@ -468,7 +471,7 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
if (!screen)
return false;
- POINTER_TOUCH_INFO *touchInfo = static_cast<POINTER_TOUCH_INFO *>(vTouchInfo);
+ auto *touchInfo = static_cast<POINTER_TOUCH_INFO *>(vTouchInfo);
const QRect screenGeometry = screen->geometry();
@@ -548,13 +551,13 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
if (et & QtWindows::NonClientEventFlag)
return false; // Let DefWindowProc() handle Non Client messages.
- POINTER_PEN_INFO *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
+ auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
RECT pRect, dRect;
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
return false;
- const qint64 sourceDevice = (qint64)penInfo->pointerInfo.sourceDevice;
+ const auto sourceDevice = (qint64)penInfo->pointerInfo.sourceDevice;
const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y);
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left)
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index e3931b3bb1..d919d97211 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -91,7 +91,7 @@ static bool monitorData(HMONITOR hMonitor, QWindowsScreenData *data)
} else {
if (const HDC hdc = CreateDC(info.szDevice, nullptr, nullptr, nullptr)) {
const QDpi dpi = monitorDPI(hMonitor);
- data->dpi = dpi.first ? dpi : deviceDPI(hdc);
+ data->dpi = dpi.first > 0 ? dpi : deviceDPI(hdc);
data->depth = GetDeviceCaps(hdc, BITSPIXEL);
data->format = data->depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
data->physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE));
@@ -120,7 +120,7 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
{
QWindowsScreenData data;
if (monitorData(hMonitor, &data)) {
- WindowsScreenDataList *result = reinterpret_cast<WindowsScreenDataList *>(p);
+ auto *result = reinterpret_cast<WindowsScreenDataList *>(p);
// QWindowSystemInterface::handleScreenAdded() documentation specifies that first
// added screen will be the primary screen, so order accordingly.
// Note that the side effect of this policy is that there is no way to change primary
@@ -552,7 +552,7 @@ bool QWindowsScreenManager::handleScreenChanges()
if (existingIndex != -1) {
m_screens.at(existingIndex)->handleChanges(newData);
} else {
- QWindowsScreen *newScreen = new QWindowsScreen(newData);
+ auto *newScreen = new QWindowsScreen(newData);
m_screens.push_back(newScreen);
QWindowSystemInterface::handleScreenAdded(newScreen,
newData.flags & QWindowsScreenData::PrimaryScreen);
diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp
index 9504513a5e..b2b1dee232 100644
--- a/src/plugins/platforms/windows/qwindowsservices.cpp
+++ b/src/plugins/platforms/windows/qwindowsservices.cpp
@@ -57,7 +57,7 @@ static inline bool shellExecute(const QUrl &url)
const QString nativeFilePath = url.isLocalFile() && !url.hasFragment() && !url.hasQuery()
? QDir::toNativeSeparators(url.toLocalFile())
: url.toString(QUrl::FullyEncoded);
- const quintptr result =
+ const auto result =
reinterpret_cast<quintptr>(ShellExecute(nullptr, nullptr,
reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()),
nullptr, nullptr, SW_SHOWNORMAL));
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index b75c64c40e..437c9562ab 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -162,8 +162,8 @@ public:
m_init = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
QMutexLocker readyLocker(&m_readyMutex);
- while (!m_cancelled.load()) {
- if (!m_params && !m_cancelled.load()
+ while (!m_cancelled.loadRelaxed()) {
+ if (!m_params && !m_cancelled.loadRelaxed()
&& !m_readyCondition.wait(&m_readyMutex, 1000))
continue;
@@ -174,7 +174,7 @@ public:
m_params->attributes, &info, sizeof(SHFILEINFO),
m_params->flags);
m_doneMutex.lock();
- if (!m_cancelled.load()) {
+ if (!m_cancelled.loadRelaxed()) {
*m_params->result = result;
memcpy(m_params->info, &info, sizeof(SHFILEINFO));
}
@@ -204,7 +204,7 @@ public:
void cancel()
{
QMutexLocker doneLocker(&m_doneMutex);
- m_cancelled.store(1);
+ m_cancelled.storeRelaxed(1);
m_readyCondition.wakeAll();
}
@@ -583,7 +583,7 @@ Q_GUI_EXPORT QPixmap qt_pixmapFromWinHICON(HICON icon);
static QPixmap loadIconFromShell32(int resourceId, QSizeF size)
{
if (const HMODULE hmod = QSystemLibrary::load(L"shell32")) {
- HICON iconHandle =
+ auto iconHandle =
static_cast<HICON>(LoadImage(hmod, MAKEINTRESOURCE(resourceId),
IMAGE_ICON, int(size.width()), int(size.height()), 0));
if (iconHandle) {
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index b52a82c9f1..e80eefc34d 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -764,8 +764,8 @@ QWindowsWindowData
if (title.isEmpty() && (result.flags & Qt::WindowTitleHint))
title = topLevel ? qAppName() : w->objectName();
- const wchar_t *titleUtf16 = reinterpret_cast<const wchar_t *>(title.utf16());
- const wchar_t *classNameUtf16 = reinterpret_cast<const wchar_t *>(windowClassName.utf16());
+ const auto *titleUtf16 = reinterpret_cast<const wchar_t *>(title.utf16());
+ const auto *classNameUtf16 = reinterpret_cast<const wchar_t *>(windowClassName.utf16());
// Capture events before CreateWindowEx() returns. The context is cleared in
// the QWindowsWindow constructor.
@@ -883,10 +883,12 @@ static QSize toNativeSizeConstrained(QSize dip, const QWindow *w)
{
if (QHighDpiScaling::isActive()) {
const qreal factor = QHighDpiScaling::factor(w);
- if (dip.width() > 0 && dip.width() < QWINDOWSIZE_MAX)
- dip.rwidth() *= factor;
- if (dip.height() > 0 && dip.height() < QWINDOWSIZE_MAX)
- dip.rheight() *= factor;
+ if (!qFuzzyCompare(factor, qreal(1))) {
+ if (dip.width() > 0 && dip.width() < QWINDOWSIZE_MAX)
+ dip.setWidth(qRound(qreal(dip.width()) * factor));
+ if (dip.height() > 0 && dip.height() < QWINDOWSIZE_MAX)
+ dip.setHeight(qRound(qreal(dip.height()) * factor));
+ }
}
return dip;
}
@@ -980,7 +982,7 @@ bool QWindowsGeometryHint::handleCalculateSize(const QMargins &customMargins, co
if (!msg.wParam || customMargins.isNull())
return false;
*result = DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
- NCCALCSIZE_PARAMS *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
+ auto *ncp = reinterpret_cast<NCCALCSIZE_PARAMS *>(msg.lParam);
const RECT oldClientArea = ncp->rgrc[0];
ncp->rgrc[0].left += customMargins.left();
ncp->rgrc[0].top += customMargins.top();
@@ -1500,7 +1502,7 @@ QWindow *QWindowsWindow::topLevelOf(QWindow *w)
w = parent;
if (const QPlatformWindow *handle = w->handle()) {
- const QWindowsWindow *ww = static_cast<const QWindowsWindow *>(handle);
+ const auto *ww = static_cast<const QWindowsWindow *>(handle);
if (ww->isEmbedded()) {
HWND parentHWND = GetAncestor(ww->handle(), GA_PARENT);
const HWND desktopHwnd = GetDesktopWindow();
@@ -1574,7 +1576,7 @@ bool QWindowsWindow::isActive() const
bool QWindowsWindow::isAncestorOf(const QPlatformWindow *child) const
{
- const QWindowsWindow *childWindow = static_cast<const QWindowsWindow *>(child);
+ const auto *childWindow = static_cast<const QWindowsWindow *>(child);
return IsChild(m_data.hwnd, childWindow->handle());
}
@@ -1723,7 +1725,7 @@ void QWindowsWindow::setParent_sys(const QPlatformWindow *parent)
HWND oldParentHWND = parentHwnd();
HWND newParentHWND = nullptr;
if (parent) {
- const QWindowsWindow *parentW = static_cast<const QWindowsWindow *>(parent);
+ const auto *parentW = static_cast<const QWindowsWindow *>(parent);
newParentHWND = parentW->handle();
}
@@ -2366,7 +2368,7 @@ void QWindowsWindow::propagateSizeHints()
bool QWindowsWindow::handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &margins)
{
- WINDOWPOS *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam);
+ auto *windowPos = reinterpret_cast<WINDOWPOS *>(message->lParam);
if ((windowPos->flags & SWP_NOZORDER) == 0) {
if (QWindowsWindow *platformWindow = QWindowsWindow::windowsWindowOf(qWindow)) {
QWindow *parentWindow = qWindow->parent();
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index a427e553f0..943c1ff368 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -82,7 +82,7 @@ QWindowsUiaMainProvider *QWindowsUiaMainProvider::providerForAccessible(QAccessi
QAccessible::Id id = QAccessible::uniqueId(accessible);
QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance();
- QWindowsUiaMainProvider *provider = qobject_cast<QWindowsUiaMainProvider *>(providerCache->providerForId(id));
+ auto *provider = qobject_cast<QWindowsUiaMainProvider *>(providerCache->providerForId(id));
if (provider) {
provider->AddRef();
@@ -153,7 +153,7 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
int count = listacc->childCount();
for (int i = 0; i < count; ++i) {
QAccessibleInterface *item = listacc->child(i);
- if (item && item->text(QAccessible::Name) == event->value()) {
+ if (item && item->isValid() && item->text(QAccessible::Name) == event->value()) {
if (!item->state().selected) {
if (QAccessibleActionInterface *actionInterface = item->actionInterface())
actionInterface->doAction(QAccessibleActionInterface::toggleAction());
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
index 9d1e72fb78..50ecfc7ecd 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextprovider.cpp
@@ -100,7 +100,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetSelection(SAFEARRAY **pRet
for (LONG i = 0; i < selCount; ++i) {
int startOffset = 0, endOffset = 0;
textInterface->selection((int)i, &startOffset, &endOffset);
- QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), startOffset, endOffset);
+ auto *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), startOffset, endOffset);
SafeArrayPutElement(*pRetVal, &i, static_cast<IUnknown *>(textRangeProvider));
textRangeProvider->Release();
}
@@ -110,7 +110,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetSelection(SAFEARRAY **pRet
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1))) {
LONG i = 0;
int cursorPosition = textInterface->cursorPosition();
- QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), cursorPosition, cursorPosition);
+ auto *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), cursorPosition, cursorPosition);
SafeArrayPutElement(*pRetVal, &i, static_cast<IUnknown *>(textRangeProvider));
textRangeProvider->Release();
}
@@ -138,7 +138,7 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTextProvider::GetVisibleRanges(SAFEARRAY **
// Considering the entire text as visible.
if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 1))) {
LONG i = 0;
- QWindowsUiaTextRangeProvider *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), 0, textInterface->characterCount());
+ auto *textRangeProvider = new QWindowsUiaTextRangeProvider(id(), 0, textInterface->characterCount());
SafeArrayPutElement(*pRetVal, &i, static_cast<IUnknown *>(textRangeProvider));
textRangeProvider->Release();
}
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
index 1be186f6b3..8e395669f8 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiatextrangeprovider.cpp
@@ -92,7 +92,7 @@ HRESULT QWindowsUiaTextRangeProvider::Compare(ITextRangeProvider *range, BOOL *p
if (!range || !pRetVal)
return E_INVALIDARG;
- QWindowsUiaTextRangeProvider *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(range);
+ auto *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(range);
*pRetVal = ((targetProvider->m_startOffset == m_startOffset) && (targetProvider->m_endOffset == m_endOffset));
return S_OK;
}
@@ -110,7 +110,7 @@ HRESULT QWindowsUiaTextRangeProvider::CompareEndpoints(TextPatternRangeEndpoint
if (!targetRange || !pRetVal)
return E_INVALIDARG;
- QWindowsUiaTextRangeProvider *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
+ auto *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
int point = (endpoint == TextPatternRangeEndpoint_Start) ? m_startOffset : m_endOffset;
int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
@@ -373,7 +373,7 @@ HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByRange(TextPatternRangeEndpoi
qCDebug(lcQpaUiAutomation) << __FUNCTION__
<< "endpoint=" << endpoint << "targetRange=" << targetRange << "targetEndpoint=" << targetEndpoint << "this: " << this;
- QWindowsUiaTextRangeProvider *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
+ auto *targetProvider = static_cast<QWindowsUiaTextRangeProvider *>(targetRange);
int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
targetProvider->m_startOffset : targetProvider->m_endOffset;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
index 7980826b49..ab04384616 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
@@ -114,7 +114,7 @@ void setVariantBool(bool value, VARIANT *variant)
void setVariantDouble(double value, VARIANT *variant)
{
variant->vt = VT_R8;
- variant->boolVal = value;
+ variant->dblVal = value;
}
BSTR bStrFromQString(const QString &value)
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index e611c7be24..0d77889a36 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -1097,7 +1097,7 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args)
d->currentTargetWindow = topWindow();
if (d->mouseGrabWindow)
- d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+ d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window();
qCDebug(lcQpaEvents) << __FUNCTION__ << "handleEnterEvent" << d->currentTargetWindow << pos;
QWindowSystemInterface::handleEnterEvent(d->currentTargetWindow, pos, pos);
@@ -1121,7 +1121,7 @@ HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args)
d->touchPoints.remove(id);
if (d->mouseGrabWindow)
- d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+ d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window();
qCDebug(lcQpaEvents) << __FUNCTION__ << "handleLeaveEvent" << d->currentTargetWindow;
QWindowSystemInterface::handleLeaveEvent(d->currentTargetWindow);
@@ -1152,7 +1152,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args)
d->currentTargetWindow = windowUnderPointer;
if (d->mouseGrabWindow)
- d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+ d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window();
if (d->currentTargetWindow) {
const QPointF globalPosDelta = pos - posPoint;
@@ -1354,7 +1354,7 @@ void QWinRTScreen::emulateMouseMove(const QPointF &point, MousePositionTransitio
d->currentTargetWindow = windowUnderPointer;
if (d->mouseGrabWindow)
- d->currentTargetWindow = d->mouseGrabWindow.load()->window();
+ d->currentTargetWindow = d->mouseGrabWindow.loadRelaxed()->window();
if (d->currentTargetWindow) {
const QPointF globalPosDelta = pos - posPoint;
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
index 4adf662152..f26f698e76 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -204,7 +204,6 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
, m_shareContext(0)
, m_format(format)
, m_isPBufferCurrent(false)
- , m_swapInterval(-1)
, m_ownsContext(nativeHandle.isNull())
, m_getGraphicsResetStatus(0)
, m_lost(false)
@@ -567,9 +566,9 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface)
if (success && surfaceClass == QSurface::Window) {
int interval = surface->format().swapInterval();
+ QXcbWindow *window = static_cast<QXcbWindow *>(surface);
QXcbScreen *screen = screenForPlatformSurface(surface);
- if (interval >= 0 && m_swapInterval != interval && screen) {
- m_swapInterval = interval;
+ if (interval >= 0 && interval != window->swapInterval() && screen) {
typedef void (*qt_glXSwapIntervalEXT)(Display *, GLXDrawable, int);
typedef void (*qt_glXSwapIntervalMESA)(unsigned int);
static qt_glXSwapIntervalEXT glXSwapIntervalEXT = 0;
@@ -588,6 +587,7 @@ bool QGLXContext::makeCurrent(QPlatformSurface *surface)
glXSwapIntervalEXT(m_display, glxDrawable, interval);
else if (glXSwapIntervalMESA)
glXSwapIntervalMESA(interval);
+ window->setSwapInterval(interval);
}
}
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
index be9d3f5dcb..2a88fd6e59 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
@@ -87,7 +87,6 @@ private:
GLXContext m_shareContext;
QSurfaceFormat m_format;
bool m_isPBufferCurrent;
- int m_swapInterval;
bool m_ownsContext;
GLenum (APIENTRY * m_getGraphicsResetStatus)();
bool m_lost;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index bfc105a040..8c34bd9c91 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -658,16 +658,24 @@ QImage::Format QXcbScreen::format() const
return format;
}
-QDpi QXcbScreen::logicalDpi() const
+int QXcbScreen::forcedDpi() const
{
static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI");
if (overrideDpi)
- return QDpi(overrideDpi, overrideDpi);
+ return overrideDpi;
const int forcedDpi = m_virtualDesktop->forcedDpi();
- if (forcedDpi > 0) {
+ if (forcedDpi > 0)
+ return forcedDpi;
+ return 0;
+}
+
+QDpi QXcbScreen::logicalDpi() const
+{
+ const int forcedDpi = this->forcedDpi();
+ if (forcedDpi > 0)
return QDpi(forcedDpi, forcedDpi);
- }
+
return m_virtualDesktop->dpi();
}
@@ -739,7 +747,9 @@ void QXcbScreen::updateGeometry(const QRect &geometry, uint8_t rotation)
if (m_sizeMillimeters.isEmpty())
m_sizeMillimeters = sizeInMillimeters(geometry.size(), m_virtualDesktop->dpi());
- qreal dpi = geometry.width() / physicalSize().width() * qreal(25.4);
+ qreal dpi = forcedDpi();
+ if (dpi <= 0)
+ dpi = geometry.width() / physicalSize().width() * qreal(25.4);
// Use 128 as a reference DPI on small screens. This favors "small UI" over "large UI".
qreal referenceDpi = physicalSize().width() <= 320 ? 128 : 96;
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index be6c45e415..ec3b07bfb7 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -208,6 +208,7 @@ public:
private:
void sendStartupMessage(const QByteArray &message) const;
+ int forcedDpi() const;
QByteArray getOutputProperty(xcb_atom_t atom) const;
QByteArray getEdid() const;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index e4a04f5308..5de5974ca7 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -184,6 +184,9 @@ public:
static void setWindowTitle(const QXcbConnection *conn, xcb_window_t window, const QString &title);
static QString windowTitle(const QXcbConnection *conn, xcb_window_t window);
+ int swapInterval() const { return m_swapInterval; }
+ void setSwapInterval(int swapInterval) { m_swapInterval = swapInterval; }
+
public Q_SLOTS:
void updateSyncRequestCounter();
@@ -276,6 +279,7 @@ protected:
SyncState m_syncState = NoSyncNeeded;
QXcbSyncWindowRequest *m_pendingSyncRequest = nullptr;
+ int m_swapInterval = -1;
};
class QXcbForeignWindow : public QXcbWindow