summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qnamespace.qdoc3
-rw-r--r--src/corelib/io/qloggingcategory.cpp16
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp4
-rw-r--r--src/corelib/tools/qvarlengtharray.h6
-rw-r--r--src/gui/configure.json4
-rw-r--r--src/gui/image/qimage.cpp14
-rw-r--r--src/gui/kernel/qevent.cpp2
-rw-r--r--src/gui/kernel/qguiapplication.cpp3
-rw-r--r--src/gui/opengl/qopengltextureuploader.cpp10
-rw-r--r--src/gui/painting/qdrawhelper.cpp56
-rw-r--r--src/gui/painting/qdrawhelper_p.h71
-rw-r--r--src/gui/painting/qimagescale.cpp235
-rw-r--r--src/gui/painting/qrgba64_p.h13
-rw-r--r--src/gui/text/qtextengine.cpp29
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h1
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp53
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp62
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.h1
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp84
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp2
-rw-r--r--src/plugins/printsupport/cups/qcupsprintersupport.cpp6
-rw-r--r--src/testlib/3rdparty/qt_attribution.json3
-rw-r--r--src/tools/androiddeployqt/main.cpp23
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp11
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp3
29 files changed, 603 insertions, 130 deletions
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index e3c51f4be0..37144dcf17 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -383,7 +383,8 @@
\value AltModifier An Alt key on the keyboard is pressed.
\value MetaModifier A Meta key on the keyboard is pressed.
\value KeypadModifier A keypad button is pressed.
- \value GroupSwitchModifier X11 only. A Mode_switch key on the keyboard is pressed.
+ \value GroupSwitchModifier X11 only (unless activated on Windows by a command line argument).
+ A Mode_switch key on the keyboard is pressed.
\omitvalue KeyboardModifierMask
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index d8402c4eb6..aa84f56368 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -471,8 +471,6 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\note Arguments are not processed if debug output for the category is not
enabled, so do not rely on any side effects.
- \note Using the macro is thread-safe.
-
\sa qDebug()
*/
@@ -493,8 +491,6 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\note Arguments might not be processed if debug output for the category is
not enabled, so do not rely on any side effects.
- \note Using the macro is thread-safe.
-
\sa qDebug()
*/
@@ -518,8 +514,6 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\note Arguments are not processed if debug output for the category is not
enabled, so do not rely on any side effects.
- \note Using the macro is thread-safe.
-
\sa qInfo()
*/
@@ -540,8 +534,6 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\note Arguments might not be processed if debug output for the category is
not enabled, so do not rely on any side effects.
- \note Using the macro is thread-safe.
-
\sa qInfo()
*/
@@ -565,8 +557,6 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\note Arguments are not processed if warning output for the category is not
enabled, so do not rely on any side effects.
- \note Using the macro is thread-safe.
-
\sa qWarning()
*/
@@ -587,8 +577,6 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\note Arguments might not be processed if warning output for the category is
not enabled, so do not rely on any side effects.
- \note Using the macro is thread-safe.
-
\sa qWarning()
*/
@@ -612,8 +600,6 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\note Arguments are not processed if critical output for the category is not
enabled, so do not rely on any side effects.
- \note Using the macro is thread-safe.
-
\sa qCritical()
*/
@@ -634,8 +620,6 @@ void QLoggingCategory::setFilterRules(const QString &rules)
\note Arguments might not be processed if critical output for the category
is not enabled, so do not rely on any side effects.
- \note Using the macro is thread-safe.
-
\sa qCritical()
*/
/*!
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index d8b4c8cc97..6b59b0723b 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -2347,7 +2347,7 @@ bool QSortFilterProxyModel::insertRows(int row, int count, const QModelIndex &pa
if (row > m->source_rows.count())
return false;
int source_row = (row >= m->source_rows.count()
- ? m->source_rows.count()
+ ? m->proxy_rows.count()
: m->source_rows.at(row));
return d->model->insertRows(source_row, count, source_parent);
}
@@ -2367,7 +2367,7 @@ bool QSortFilterProxyModel::insertColumns(int column, int count, const QModelInd
if (column > m->source_columns.count())
return false;
int source_column = (column >= m->source_columns.count()
- ? m->source_columns.count()
+ ? m->proxy_columns.count()
: m->source_columns.at(column));
return d->model->insertColumns(source_column, count, source_parent);
}
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index a6bd7847a5..b74b1fd123 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -490,7 +490,7 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
}
} else {
T *b = ptr + offset;
- memmove(b + 1, b, (s - offset) * sizeof(T));
+ memmove(static_cast<void *>(b + 1), static_cast<const void *>(b), (s - offset) * sizeof(T));
new (b) T(std::move(t));
}
s += 1;
@@ -518,7 +518,7 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
} else {
T *b = ptr + offset;
T *i = b + n;
- memmove(i, b, (s - offset - n) * sizeof(T));
+ memmove(static_cast<void *>(i), static_cast<const void *>(b), (s - offset - n) * sizeof(T));
while (i != b)
new (--i) T(copy);
}
@@ -544,7 +544,7 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray<T, Prealloc>::iterator QVarLengthA
i->~T();
}
} else {
- memmove(ptr + f, ptr + l, (s - l) * sizeof(T));
+ memmove(static_cast<void *>(ptr + f), static_cast<const void *>(ptr + l), (s - l) * sizeof(T));
}
s -= n;
return ptr + f;
diff --git a/src/gui/configure.json b/src/gui/configure.json
index 8e6569c069..26a5ae9a3d 100644
--- a/src/gui/configure.json
+++ b/src/gui/configure.json
@@ -294,7 +294,7 @@
},
"sources": [
{ "libs": "-llibjpeg", "condition": "config.msvc" },
- { "libs": "-ljpeg", "condition": "!config.msvc" }
+ "-ljpeg"
]
},
"libpng": {
@@ -305,7 +305,9 @@
},
"sources": [
{ "type": "pkgConfig", "args": "libpng" },
+ { "libs": "-llibpng16", "condition": "config.msvc" },
{ "libs": "-llibpng", "condition": "config.msvc" },
+ { "libs": "-lpng16", "condition": "!config.msvc" },
{ "libs": "-lpng", "condition": "!config.msvc" }
],
"use": [
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 32ef67763a..8a4c6b7fda 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1829,7 +1829,14 @@ void QImage::fill(const QColor &color)
else
fill((uint) 0);
break;
- case QImage::Format_RGBX64:
+ case QImage::Format_RGBX64: {
+ QRgba64 c = color.rgba64();
+ c.setAlpha(65535);
+ qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), c,
+ 0, 0, d->width, d->height, d->bytes_per_line);
+ break;
+
+ }
case QImage::Format_RGBA64:
case QImage::Format_RGBA64_Premultiplied:
qt_rectfill<quint64>(reinterpret_cast<quint64*>(d->data), color.rgba64(),
@@ -4616,6 +4623,11 @@ QImage QImage::smoothScaled(int w, int h) const {
case QImage::Format_RGBX8888:
#endif
case QImage::Format_RGBA8888_Premultiplied:
+ case QImage::Format_RGBX64:
+ case QImage::Format_RGBA64_Premultiplied:
+ break;
+ case QImage::Format_RGBA64:
+ src = src.convertToFormat(QImage::Format_RGBA64_Premultiplied);
break;
default:
if (src.hasAlphaChannel())
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index f5527354a2..6f8ea6dc70 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -4163,7 +4163,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e)
const QNativeGestureEvent *ne = static_cast<const QNativeGestureEvent *>(e);
dbg << "QNativeGestureEvent(";
QtDebugUtils::formatQEnum(dbg, ne->gestureType());
- dbg << "localPos=";
+ dbg << ", localPos=";
QtDebugUtils::formatQPoint(dbg, ne->localPos());
dbg << ", value=" << ne->value() << ')';
}
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 40d82d9269..93e8b6ee8f 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -594,6 +594,9 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME
By default, they will be used if the application is not an
instance of QApplication or for Qt Quick Controls 2
applications.
+
+ \li \c {altgr}, detect the key \c {AltGr} found on some keyboards as
+ Qt::GroupSwitchModifier.
\endlist
The following parameter is available for \c {-platform cocoa} (on macOS):
diff --git a/src/gui/opengl/qopengltextureuploader.cpp b/src/gui/opengl/qopengltextureuploader.cpp
index fc449d8090..2428baed93 100644
--- a/src/gui/opengl/qopengltextureuploader.cpp
+++ b/src/gui/opengl/qopengltextureuploader.cpp
@@ -140,9 +140,12 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
// No support for direct ARGB32 upload.
break;
}
+#else
+ // Big endian requires GL_UNSIGNED_INT_8_8_8_8_REV for ARGB to match BGRA
+ break;
+#endif
}
targetFormat = image.format();
-#endif
break;
case QImage::Format_BGR30:
case QImage::Format_A2BGR30_Premultiplied:
@@ -310,6 +313,11 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
if (newSize != tx.size())
tx = tx.scaled(newSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ // Handle cases where the QImage is actually a sub image of its image data:
+ qsizetype naturalBpl = ((qsizetype(tx.width()) * tx.depth() + 31) >> 5) << 2;
+ if (tx.bytesPerLine() != naturalBpl)
+ tx = tx.copy(tx.rect());
+
funcs->glTexImage2D(target, 0, internalFormat, tx.width(), tx.height(), 0, externalFormat, pixelType, tx.constBits());
qsizetype cost = qint64(tx.width()) * tx.height() * tx.depth() / 8;
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index b1424b5b0a..8f189994f1 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -342,7 +342,7 @@ static void QT_FASTCALL convertToRGB32(uint *buffer, int count, const QVector<QR
buffer[i] = convertPixelToRGB32<Format>(buffer[i]);
}
-#if defined(__SSE2__) && !defined(__SSSE3__)
+#if defined(__SSE2__) && !defined(__SSSE3__) && QT_COMPILER_SUPPORTS_SSSE3
extern const uint * QT_FASTCALL fetchPixelsBPP24_ssse3(uint *dest, const uchar*src, int index, int count);
#endif
@@ -351,7 +351,7 @@ static const uint *QT_FASTCALL fetchRGBToRGB32(uint *buffer, const uchar *src, i
const QVector<QRgb> *, QDitherInfo *)
{
constexpr QPixelLayout::BPP BPP = bitsPerPixel<Format>();
-#if defined(__SSE2__) && !defined(__SSSE3__)
+#if defined(__SSE2__) && !defined(__SSSE3__) && QT_COMPILER_SUPPORTS_SSSE3
if (BPP == QPixelLayout::BPP24 && qCpuHasFeature(SSSE3)) {
// With SSE2 can convertToRGB32 be vectorized, but it takes SSSE3
// to vectorize the deforested version below.
@@ -442,7 +442,7 @@ static const uint *QT_FASTCALL fetchARGBPMToARGB32PM(uint *buffer, const uchar *
const QVector<QRgb> *, QDitherInfo *)
{
constexpr QPixelLayout::BPP BPP = bitsPerPixel<Format>();
-#if defined(__SSE2__) && !defined(__SSSE3__)
+#if defined(__SSE2__) && !defined(__SSSE3__) && QT_COMPILER_SUPPORTS_SSSE3
if (BPP == QPixelLayout::BPP24 && qCpuHasFeature(SSSE3)) {
// With SSE2 can convertToRGB32 be vectorized, but it takes SSSE3
// to vectorize the deforested version below.
@@ -640,6 +640,19 @@ void QT_FASTCALL rbSwap<QImage::Format_RGBA8888>(uchar *d, const uchar *s, int c
{
return rbSwap_rgb32(d, s, count);
}
+#else
+template<>
+void QT_FASTCALL rbSwap<QImage::Format_RGBA8888>(uchar *d, const uchar *s, int count)
+{
+ const uint *src = reinterpret_cast<const uint *>(s);
+ uint *dest = reinterpret_cast<uint *>(d);
+ for (int i = 0; i < count; ++i) {
+ const uint c = src[i];
+ const uint rb = c & 0xff00ff00;
+ const uint ga = c & 0x00ff00ff;
+ dest[i] = ga | (rb << 16) | (rb >> 16);
+ }
+}
#endif
static void QT_FASTCALL rbSwap_rgb30(uchar *d, const uchar *s, int count)
@@ -2264,43 +2277,6 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, u
}
#endif
-#if defined(__SSE2__)
-static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba64 b[], uint distx, uint disty)
-{
- __m128i vt = _mm_loadu_si128((const __m128i*)t);
- if (disty) {
- __m128i vb = _mm_loadu_si128((const __m128i*)b);
- vt = _mm_mulhi_epu16(vt, _mm_set1_epi16(0x10000 - disty));
- vb = _mm_mulhi_epu16(vb, _mm_set1_epi16(disty));
- vt = _mm_add_epi16(vt, vb);
- }
- if (distx) {
- const __m128i vdistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(distx), _MM_SHUFFLE(0, 0, 0, 0));
- const __m128i vidistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(0x10000 - distx), _MM_SHUFFLE(0, 0, 0, 0));
- vt = _mm_mulhi_epu16(vt, _mm_unpacklo_epi64(vidistx, vdistx));
- vt = _mm_add_epi16(vt, _mm_srli_si128(vt, 8));
- }
-#ifdef Q_PROCESSOR_X86_64
- return QRgba64::fromRgba64(_mm_cvtsi128_si64(vt));
-#else
- QRgba64 out;
- _mm_storel_epi64((__m128i*)&out, vt);
- return out;
-#endif
-}
-#else
-static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba64 b[], uint distx, uint disty)
-{
- const uint dx = distx>>8;
- const uint dy = disty>>8;
- const uint idx = 256 - dx;
- const uint idy = 256 - dy;
- QRgba64 xtop = interpolate256(t[0], idx, t[1], dx);
- QRgba64 xbot = interpolate256(b[0], idx, b[1], dx);
- return interpolate256(xtop, idy, xbot, dy);
-}
-#endif
-
template<TextureBlendType blendType>
void fetchTransformedBilinear_pixelBounds(int max, int l1, int l2, int &v1, int &v2);
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 078ab62251..fb08261205 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -747,6 +747,77 @@ static constexpr inline bool hasFastInterpolate4() { return false; }
#endif
+static inline QRgba64 multiplyAlpha256(QRgba64 rgba64, uint alpha256)
+{
+ return QRgba64::fromRgba64((rgba64.red() * alpha256) >> 8,
+ (rgba64.green() * alpha256) >> 8,
+ (rgba64.blue() * alpha256) >> 8,
+ (rgba64.alpha() * alpha256) >> 8);
+}
+static inline QRgba64 interpolate256(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2)
+{
+ return QRgba64::fromRgba64(multiplyAlpha256(x, alpha1) + multiplyAlpha256(y, alpha2));
+}
+
+#ifdef __SSE2__
+static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba64 b[], uint distx, uint disty)
+{
+ __m128i vt = _mm_loadu_si128((const __m128i*)t);
+ if (disty) {
+ __m128i vb = _mm_loadu_si128((const __m128i*)b);
+ vt = _mm_mulhi_epu16(vt, _mm_set1_epi16(0x10000 - disty));
+ vb = _mm_mulhi_epu16(vb, _mm_set1_epi16(disty));
+ vt = _mm_add_epi16(vt, vb);
+ }
+ if (distx) {
+ const __m128i vdistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(distx), _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128i vidistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(0x10000 - distx), _MM_SHUFFLE(0, 0, 0, 0));
+ vt = _mm_mulhi_epu16(vt, _mm_unpacklo_epi64(vidistx, vdistx));
+ vt = _mm_add_epi16(vt, _mm_srli_si128(vt, 8));
+ }
+#ifdef Q_PROCESSOR_X86_64
+ return QRgba64::fromRgba64(_mm_cvtsi128_si64(vt));
+#else
+ QRgba64 out;
+ _mm_storel_epi64((__m128i*)&out, vt);
+ return out;
+#endif // Q_PROCESSOR_X86_64
+}
+#elif defined(__ARM_NEON__)
+static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba64 b[], uint distx, uint disty)
+{
+ uint64x1x2_t vt = vld2_u64(reinterpret_cast<const uint64_t *>(t));
+ if (disty) {
+ uint64x1x2_t vb = vld2_u64(reinterpret_cast<const uint64_t *>(b));
+ uint32x4_t vt0 = vmull_n_u16(vreinterpret_u16_u64(vt.val[0]), 0x10000 - disty);
+ uint32x4_t vt1 = vmull_n_u16(vreinterpret_u16_u64(vt.val[1]), 0x10000 - disty);
+ vt0 = vmlal_n_u16(vt0, vreinterpret_u16_u64(vb.val[0]), disty);
+ vt1 = vmlal_n_u16(vt1, vreinterpret_u16_u64(vb.val[1]), disty);
+ vt.val[0] = vreinterpret_u64_u16(vshrn_n_u32(vt0, 16));
+ vt.val[1] = vreinterpret_u64_u16(vshrn_n_u32(vt1, 16));
+ }
+ if (distx) {
+ uint32x4_t vt0 = vmull_n_u16(vreinterpret_u16_u64(vt.val[0]), 0x10000 - distx);
+ vt0 = vmlal_n_u16(vt0, vreinterpret_u16_u64(vt.val[1]), distx);
+ vt.val[0] = vreinterpret_u64_u16(vshrn_n_u32(vt0, 16));
+ }
+ QRgba64 out;
+ vst1_u64(reinterpret_cast<uint64_t *>(&out), vt.val[0]);
+ return out;
+}
+#else
+static inline QRgba64 interpolate_4_pixels_rgb64(const QRgba64 t[], const QRgba64 b[], uint distx, uint disty)
+{
+ const uint dx = distx>>8;
+ const uint dy = disty>>8;
+ const uint idx = 256 - dx;
+ const uint idy = 256 - dy;
+ QRgba64 xtop = interpolate256(t[0], idx, t[1], dx);
+ QRgba64 xbot = interpolate256(b[0], idx, b[1], dx);
+ return interpolate256(xtop, idy, xbot, dy);
+}
+#endif // __SSE2__
+
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
static Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) {
quint32 rgb = x >> 8;
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 22787b91fe..ca7930500e 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -41,6 +41,7 @@
#include "qimage.h"
#include "qcolor.h"
+#include "qrgba64_p.h"
QT_BEGIN_NAMESPACE
@@ -85,7 +86,7 @@ QT_BEGIN_NAMESPACE
* #ifdef'ed code, and removal of unneeded border calculation code.
* Later the code has been refactored, an SSE4.1 optimizated path have been
* added instead of the removed MMX assembler, and scaling of clipped area
- * removed.
+ * removed, and an RGBA64 version written
*
* Imlib2 is (C) Carsten Haitzler and various contributors. The MMX code
* is by Willem Monsuwe <willem@stack.nl>. All other modifications are
@@ -94,12 +95,11 @@ QT_BEGIN_NAMESPACE
namespace QImageScale {
- const unsigned int** qimageCalcYPoints(const unsigned int *src, int sw, int sh, int dh);
- int* qimageCalcXPoints(int sw, int dw);
- int* qimageCalcApoints(int s, int d, int up);
- QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi);
- QImageScaleInfo *qimageCalcScaleInfo(const QImage &img, int sw, int sh,
- int dw, int dh, char aa);
+ static const unsigned int** qimageCalcYPoints(const unsigned int *src, int sw, int sh, int dh);
+ static int* qimageCalcXPoints(int sw, int dw);
+ static int* qimageCalcApoints(int s, int d, int up);
+ static QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi);
+ static QImageScaleInfo *qimageCalcScaleInfo(const QImage &img, int sw, int sh, int dw, int dh, char aa);
}
using namespace QImageScale;
@@ -108,8 +108,8 @@ using namespace QImageScale;
// Code ported from Imlib...
//
-const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
- int sw, int sh, int dh)
+static const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
+ int sw, int sh, int dh)
{
const unsigned int **p;
int j = 0, rv = 0;
@@ -138,7 +138,7 @@ const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
return(p);
}
-int* QImageScale::qimageCalcXPoints(int sw, int dw)
+static int* QImageScale::qimageCalcXPoints(int sw, int dw)
{
int *p, j = 0, rv = 0;
qint64 val, inc;
@@ -167,7 +167,7 @@ int* QImageScale::qimageCalcXPoints(int sw, int dw)
return p;
}
-int* QImageScale::qimageCalcApoints(int s, int d, int up)
+static int* QImageScale::qimageCalcApoints(int s, int d, int up)
{
int *p, j = 0, rv = 0;
@@ -214,7 +214,7 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
return p;
}
-QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
+static QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
{
if (isi) {
delete[] isi->xpoints;
@@ -226,9 +226,9 @@ QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
return 0;
}
-QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
- int sw, int sh,
- int dw, int dh, char aa)
+static QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
+ int sw, int sh,
+ int dw, int dh, char aa)
{
QImageScaleInfo *isi;
int scw, sch;
@@ -333,7 +333,7 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest,
}
}
-/* scale by area sampling */
+/* scale by area sampling - with alpha */
static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
int dw, int dh, int dow, int sow)
{
@@ -529,6 +529,204 @@ static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *des
}
}
+static void qt_qimageScaleRgba64_up_x_down_y(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleRgba64_down_x_up_y(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleRgba64_up_xy(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba64 **ypoints = (const QRgba64 **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ for (int y = 0; y < dh; y++) {
+ const QRgba64 *sptr = ypoints[y];
+ QRgba64 *dptr = dest + (y * dow);
+ const int yap = yapoints[y];
+ if (yap > 0) {
+ for (int x = 0; x < dw; x++) {
+ const QRgba64 *pix = sptr + xpoints[x];
+ const int xap = xapoints[x];
+ if (xap > 0)
+ *dptr = interpolate_4_pixels_rgb64(pix, pix + sow, xap * 256, yap * 256);
+ else
+ *dptr = interpolate256(pix[0], 256 - yap, pix[sow], yap);
+ dptr++;
+ }
+ } else {
+ for (int x = 0; x < dw; x++) {
+ const QRgba64 *pix = sptr + xpoints[x];
+ const int xap = xapoints[x];
+ *dptr = interpolate256(pix[0], 256 - xap, pix[1], xap);
+ dptr++;
+ }
+ }
+ }
+}
+
+void qt_qimageScaleRgba64(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow)
+{
+ if (isi->xup_yup == 3)
+ qt_qimageScaleRgba64_up_xy(isi, dest, dw, dh, dow, sow);
+ else if (isi->xup_yup == 1)
+ qt_qimageScaleRgba64_up_x_down_y(isi, dest, dw, dh, dow, sow);
+ else if (isi->xup_yup == 2)
+ qt_qimageScaleRgba64_down_x_up_y(isi, dest, dw, dh, dow, sow);
+ else
+ qt_qimageScaleRgba64_down_xy(isi, dest, dw, dh, dow, sow);
+}
+
+inline static void qt_qimageScaleRgba64_helper(const QRgba64 *pix, int xyap, int Cxy, int step, qint64 &r, qint64 &g, qint64 &b, qint64 &a)
+{
+ r = pix->red() * xyap;
+ g = pix->green() * xyap;
+ b = pix->blue() * xyap;
+ a = pix->alpha() * xyap;
+ int j;
+ for (j = (1 << 14) - xyap; j > Cxy; j -= Cxy ){
+ pix += step;
+ r += pix->red() * Cxy;
+ g += pix->green() * Cxy;
+ b += pix->blue() * Cxy;
+ a += pix->alpha() * Cxy;
+ }
+ pix += step;
+ r += pix->red() * j;
+ g += pix->green() * j;
+ b += pix->blue() * j;
+ a += pix->alpha() * j;
+}
+
+static void qt_qimageScaleRgba64_up_x_down_y(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba64 **ypoints = (const QRgba64 **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[y]) >> 16;
+ int yap = (yapoints[y]) & 0xffff;
+
+ QRgba64 *dptr = dest + (y * dow);
+ for (int x = 0; x < dw; x++) {
+ const QRgba64 *sptr = ypoints[y] + xpoints[x];
+ qint64 r, g, b, a;
+ qt_qimageScaleRgba64_helper(sptr, yap, Cy, sow, r, g, b, a);
+
+ int xap = xapoints[x];
+ if (xap > 0) {
+ qint64 rr, gg, bb, aa;
+ qt_qimageScaleRgba64_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
+
+ r = r * (256 - xap);
+ g = g * (256 - xap);
+ b = b * (256 - xap);
+ a = a * (256 - xap);
+ r = (r + (rr * xap)) >> 8;
+ g = (g + (gg * xap)) >> 8;
+ b = (b + (bb * xap)) >> 8;
+ a = (a + (aa * xap)) >> 8;
+ }
+ *dptr++ = qRgba64(r >> 14, g >> 14, b >> 14, a >> 14);
+ }
+ }
+}
+
+static void qt_qimageScaleRgba64_down_x_up_y(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba64 **ypoints = (const QRgba64 **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ for (int y = 0; y < dh; y++) {
+ QRgba64 *dptr = dest + (y * dow);
+ for (int x = 0; x < dw; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const QRgba64 *sptr = ypoints[y] + xpoints[x];
+ qint64 r, g, b, a;
+ qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, r, g, b, a);
+
+ int yap = yapoints[y];
+ if (yap > 0) {
+ qint64 rr, gg, bb, aa;
+ qt_qimageScaleRgba64_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
+
+ r = r * (256 - yap);
+ g = g * (256 - yap);
+ b = b * (256 - yap);
+ a = a * (256 - yap);
+ r = (r + (rr * yap)) >> 8;
+ g = (g + (gg * yap)) >> 8;
+ b = (b + (bb * yap)) >> 8;
+ a = (a + (aa * yap)) >> 8;
+ }
+ *dptr = qRgba64(r >> 14, g >> 14, b >> 14, a >> 14);
+ dptr++;
+ }
+ }
+}
+
+static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
+ int dw, int dh, int dow, int sow)
+{
+ const QRgba64 **ypoints = (const QRgba64 **)isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[y]) >> 16;
+ int yap = (yapoints[y]) & 0xffff;
+
+ QRgba64 *dptr = dest + (y * dow);
+ for (int x = 0; x < dw; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const QRgba64 *sptr = ypoints[y] + xpoints[x];
+ qint64 rx, gx, bx, ax;
+ qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
+
+ qint64 r = rx * yap;
+ qint64 g = gx * yap;
+ qint64 b = bx * yap;
+ qint64 a = ax * yap;
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
+ sptr += sow;
+ qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
+ r += rx * Cy;
+ g += gx * Cy;
+ b += bx * Cy;
+ a += ax * Cy;
+ }
+ sptr += sow;
+ qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
+ r += rx * j;
+ g += gx * j;
+ b += bx * j;
+ a += ax * j;
+
+ *dptr = qRgba64(r >> 28, g >> 28, b >> 28, a >> 28);
+ dptr++;
+ }
+ }
+}
+
static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
int dw, int dh, int dow, int sow);
@@ -745,7 +943,10 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
return QImage();
}
- if (src.hasAlphaChannel())
+ if (src.depth() > 32)
+ qt_qimageScaleRgba64(scaleinfo, (QRgba64 *)buffer.scanLine(0),
+ dw, dh, dw, src.bytesPerLine() / 8);
+ else if (src.hasAlphaChannel())
qt_qimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
dw, dh, dw, src.bytesPerLine() / 4);
else
diff --git a/src/gui/painting/qrgba64_p.h b/src/gui/painting/qrgba64_p.h
index 1ed0e82182..b7e4d4d905 100644
--- a/src/gui/painting/qrgba64_p.h
+++ b/src/gui/painting/qrgba64_p.h
@@ -64,14 +64,6 @@ inline QRgba64 combineAlpha256(QRgba64 rgba64, uint alpha256)
return QRgba64::fromRgba64(rgba64.red(), rgba64.green(), rgba64.blue(), (rgba64.alpha() * alpha256) >> 8);
}
-inline QRgba64 multiplyAlpha256(QRgba64 rgba64, uint alpha256)
-{
- return QRgba64::fromRgba64((rgba64.red() * alpha256) >> 8,
- (rgba64.green() * alpha256) >> 8,
- (rgba64.blue() * alpha256) >> 8,
- (rgba64.alpha() * alpha256) >> 8);
-}
-
inline QRgba64 multiplyAlpha65535(QRgba64 rgba64, uint alpha65535)
{
return QRgba64::fromRgba64(qt_div_65535(rgba64.red() * alpha65535),
@@ -126,11 +118,6 @@ inline T multiplyAlpha255(T rgba64, uint alpha255)
#endif
}
-inline QRgba64 interpolate256(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2)
-{
- return QRgba64::fromRgba64(multiplyAlpha256(x, alpha1) + multiplyAlpha256(y, alpha2));
-}
-
inline QRgba64 interpolate255(QRgba64 x, uint alpha1, QRgba64 y, uint alpha2)
{
return QRgba64::fromRgba64(multiplyAlpha255(x, alpha1) + multiplyAlpha255(y, alpha2));
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 6826f62b61..4e9b00f9c9 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1043,19 +1043,31 @@ struct QBidiAlgorithm {
}
}
- bool process()
+ bool checkForBidi() const
{
- memset(analysis, 0, length * sizeof(QScriptAnalysis));
-
- bool hasBidi = (baseLevel != 0);
- if (!hasBidi) {
- for (int i = 0; i < length; ++i) {
- if (text[i].unicode() >= 0x590) {
- hasBidi = true;
+ if (baseLevel != 0)
+ return true;
+ for (int i = 0; i < length; ++i) {
+ if (text[i].unicode() >= 0x590) {
+ switch (text[i].direction()) {
+ case QChar::DirR: case QChar::DirAN:
+ case QChar::DirLRE: case QChar::DirLRO: case QChar::DirAL:
+ case QChar::DirRLE: case QChar::DirRLO: case QChar::DirPDF:
+ case QChar::DirLRI: case QChar::DirRLI: case QChar::DirFSI: case QChar::DirPDI:
+ return true;
+ default:
break;
}
}
}
+ return false;
+ }
+
+ bool process()
+ {
+ memset(analysis, 0, length * sizeof(QScriptAnalysis));
+
+ bool hasBidi = checkForBidi();
if (!hasBidi)
return false;
@@ -2071,7 +2083,6 @@ void QTextEngine::itemize() const
case QChar::Nbsp:
if (option.flags() & QTextOption::ShowTabsAndSpaces) {
analysis->flags = (*uc == QChar::Space) ? QScriptAnalysis::Space : QScriptAnalysis::Nbsp;
- analysis->bidiLevel = bidi.baseLevel;
break;
}
Q_FALLTHROUGH();
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index bba7d044f7..e29e5b8187 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -378,6 +378,11 @@ void QWindowsContext::setTabletAbsoluteRange(int a)
#endif
}
+void QWindowsContext::setDetectAltGrModifier(bool a)
+{
+ d->m_keyMapper.setDetectAltGrModifier(a);
+}
+
int QWindowsContext::processDpiAwareness()
{
int result;
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index fe83c83934..3709d9deee 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -208,6 +208,8 @@ public:
void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
static int processDpiAwareness();
+ void setDetectAltGrModifier(bool a);
+
// Returns a combination of SystemInfoFlags
unsigned systemInfo() const;
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 1a1d51cae1..4824de5c9c 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -198,6 +198,8 @@ static inline unsigned parseOptions(const QStringList &paramList,
} else if (param.endsWith(QLatin1String("none"))) {
options |= QWindowsIntegration::NoNativeDialogs;
}
+ } else if (param == QLatin1String("altgr")) {
+ options |= QWindowsIntegration::DetectAltGrModifier;
} else if (param == QLatin1String("gl=gdi")) {
options |= QWindowsIntegration::DisableArb;
} else if (param == QLatin1String("nodirectwrite")) {
@@ -269,6 +271,7 @@ QWindowsIntegration::QWindowsIntegration(const QStringList &paramList) :
d->m_clipboard.registerViewer();
#endif
d->m_context.screenManager().handleScreenChanges();
+ d->m_context.setDetectAltGrModifier((d->m_options & DetectAltGrModifier) != 0);
}
QWindowsIntegration::~QWindowsIntegration()
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index 25f485679d..da86852766 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -69,6 +69,7 @@ public:
AlwaysUseNativeMenus = 0x100,
NoNativeMenus = 0x200,
DontUseWMPointer = 0x400,
+ DetectAltGrModifier = 0x800
};
explicit QWindowsIntegration(const QStringList &paramList);
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index e7efd6e057..1209b6c4b4 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -672,6 +672,7 @@ void QWindowsKeyMapper::changeKeyboard()
bidi = true;
keyboardInputDirection = bidi ? Qt::RightToLeft : Qt::LeftToRight;
+ m_seenAltGr = false;
}
// Helper function that is used when obtaining the list of characters that can be produced by one key and
@@ -906,8 +907,34 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con
#endif
}
-bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &msg, bool /* grab */, LRESULT *lResult)
+// QTBUG-69317: Check for AltGr found on some keyboards
+// which is a sequence of left Ctrl (SYSKEY) + right Menu (Alt).
+static bool isAltGr(MSG *msg)
{
+ enum : LONG_PTR { RightFlag = 0x1000000 };
+ if (msg->wParam != VK_CONTROL || (msg->lParam & RightFlag) != 0
+ || (msg->message != WM_KEYDOWN && msg->message != WM_SYSKEYUP)) {
+ return false;
+ }
+ const UINT expectedMessage = msg->message == WM_SYSKEYUP
+ ? WM_KEYUP : msg->message;
+ MSG peekedMsg;
+ if (PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_NOREMOVE) == FALSE
+ || peekedMsg.message != expectedMessage || peekedMsg.wParam != VK_MENU
+ || (peekedMsg.lParam & RightFlag) == 0) {
+ return false;
+ }
+ *msg = peekedMsg;
+ PeekMessage(&peekedMsg, msg->hwnd, 0, 0, PM_REMOVE);
+ return true;
+}
+
+bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
+ bool /* grab */, LRESULT *lResult)
+{
+ const bool altGr = m_detectAltGrModifier && isAltGr(&msg);
+ if (altGr)
+ m_seenAltGr = true;
const UINT msgType = msg.message;
const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask;
@@ -936,10 +963,12 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
// Get the modifier states (may be altered later, depending on key code)
int state = 0;
state |= (nModifiers & ShiftAny ? int(Qt::ShiftModifier) : 0);
- state |= (nModifiers & ControlAny ? int(Qt::ControlModifier) : 0);
- state |= (nModifiers & AltAny ? int(Qt::AltModifier) : 0);
+ state |= (nModifiers & AltLeft ? int(Qt::AltModifier) : 0);
+ if ((nModifiers & AltRight) != 0)
+ state |= m_seenAltGr ? Qt::GroupSwitchModifier : Qt::AltModifier;
+ if ((nModifiers & ControlAny) != 0 && (state & Qt::GroupSwitchModifier) == 0)
+ state |= Qt::ControlModifier;
state |= (nModifiers & MetaAny ? int(Qt::MetaModifier) : 0);
-
// A multi-character key or a Input method character
// not found by our look-ahead
if (msgType == WM_CHAR || msgType == WM_IME_CHAR) {
@@ -1010,8 +1039,17 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
modifiersIndex |= (nModifiers & ControlAny ? 0x2 : 0);
modifiersIndex |= (nModifiers & AltAny ? 0x4 : 0);
+ // Note: For the resulting key, AltGr is equivalent to Alt + Ctrl (as
+ // opposed to Linux); hence no entry in KeyboardLayoutItem is required
int code = keyLayout[vk_key].qtKey[modifiersIndex];
+ // If the bit 24 of lParm is set you received a enter,
+ // otherwise a Return. (This is the extended key bit)
+ if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000))
+ code = Qt::Key_Enter;
+ else if (altGr)
+ code = Qt::Key_AltGr;
+
// Invert state logic:
// If the key actually pressed is a modifier key, then we remove its modifier key from the
// state, since a modifier-key can't have itself as a modifier
@@ -1021,11 +1059,8 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
state = state ^ Qt::ShiftModifier;
else if (code == Qt::Key_Alt)
state = state ^ Qt::AltModifier;
-
- // If the bit 24 of lParm is set you received a enter,
- // otherwise a Return. (This is the extended key bit)
- if ((code == Qt::Key_Return) && (msg.lParam & 0x1000000))
- code = Qt::Key_Enter;
+ else if (code == Qt::Key_AltGr)
+ state = state ^ Qt::GroupSwitchModifier;
// All cursor keys without extended bit
if (!(msg.lParam & 0x1000000)) {
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h
index d569c82437..a454f0f973 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.h
+++ b/src/plugins/platforms/windows/qwindowskeymapper.h
@@ -81,6 +81,9 @@ public:
void setUseRTLExtensions(bool e) { m_useRTLExtensions = e; }
bool useRTLExtensions() const { return m_useRTLExtensions; }
+ void setDetectAltGrModifier(bool a) { m_detectAltGrModifier = a; }
+ bool detectAltGrModifier() const { return m_detectAltGrModifier; }
+
bool translateKeyEvent(QWindow *widget, HWND hwnd, const MSG &msg, LRESULT *result);
QWindow *keyGrabber() const { return m_keyGrabber; }
@@ -90,7 +93,7 @@ public:
QList<int> possibleKeys(const QKeyEvent *e) const;
private:
- bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab, LRESULT *lResult);
+ bool translateKeyEventInternal(QWindow *receiver, MSG msg, bool grab, LRESULT *lResult);
bool translateMultimediaKeyEventInternal(QWindow *receiver, const MSG &msg);
void updateKeyMap(const MSG &msg);
@@ -106,6 +109,9 @@ private:
QChar m_lastHighSurrogate;
static const size_t NumKeyboardLayoutItems = 256;
KeyboardLayoutItem keyLayout[NumKeyboardLayoutItems];
+ bool m_detectAltGrModifier = false;
+ bool m_seenAltGr = false;
+
};
enum WindowsNativeModifiers {
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index c4ee820211..6af9f168a5 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -60,6 +60,8 @@
QT_BEGIN_NAMESPACE
+static const DWORD VENDOR_ID_AMD = 0x1002;
+
GpuDescription GpuDescription::detect()
{
typedef IDirect3D9 * (WINAPI *PtrDirect3DCreate9)(UINT);
@@ -74,9 +76,16 @@ GpuDescription GpuDescription::detect()
IDirect3D9 *direct3D9 = direct3DCreate9(D3D_SDK_VERSION);
if (!direct3D9)
return result;
+
D3DADAPTER_IDENTIFIER9 adapterIdentifier;
- const HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier);
- direct3D9->Release();
+ bool isAMD = false;
+ // Adapter "0" is D3DADAPTER_DEFAULT which returns the default adapter. In
+ // multi-GPU, multi-screen setups this is the GPU that is associated with
+ // the "main display" in the Display Settings, and this is the GPU OpenGL
+ // and D3D uses by default. Therefore querying any additional adapters is
+ // futile and not useful for our purposes in general, except for
+ // identifying a few special cases later on.
+ HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier);
if (SUCCEEDED(hr)) {
result.vendorId = adapterIdentifier.VendorId;
result.deviceId = adapterIdentifier.DeviceId;
@@ -90,7 +99,37 @@ GpuDescription GpuDescription::detect()
result.driverVersion = QVersionNumber(version);
result.driverName = adapterIdentifier.Driver;
result.description = adapterIdentifier.Description;
+ isAMD = result.vendorId == VENDOR_ID_AMD;
}
+
+ // Detect QTBUG-50371 (having AMD as the default adapter results in a crash
+ // when starting apps on a screen connected to the Intel card) by looking
+ // for a default AMD adapter and an additional non-AMD one.
+ if (isAMD) {
+ const UINT adapterCount = direct3D9->GetAdapterCount();
+ for (UINT adp = 1; adp < adapterCount; ++adp) {
+ hr = direct3D9->GetAdapterIdentifier(adp, 0, &adapterIdentifier);
+ if (SUCCEEDED(hr)) {
+ if (adapterIdentifier.VendorId != VENDOR_ID_AMD) {
+ // Bingo. Now figure out the display for the AMD card.
+ DISPLAY_DEVICE dd;
+ memset(&dd, 0, sizeof(dd));
+ dd.cb = sizeof(dd);
+ for (int dev = 0; EnumDisplayDevices(nullptr, dev, &dd, 0); ++dev) {
+ if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
+ // DeviceName is something like \\.\DISPLAY1 which can be used to
+ // match with the MONITORINFOEX::szDevice queried by QWindowsScreen.
+ result.gpuSuitableScreen = QString::fromWCharArray(dd.DeviceName);
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ direct3D9->Release();
return result;
}
@@ -103,7 +142,8 @@ QDebug operator<<(QDebug d, const GpuDescription &gd)
<< ", deviceId=" << gd.deviceId << ", subSysId=" << gd.subSysId
<< dec << noshowbase << ", revision=" << gd.revision
<< ", driver: " << gd.driverName
- << ", version=" << gd.driverVersion << ", " << gd.description << ')';
+ << ", version=" << gd.driverVersion << ", " << gd.description
+ << gd.gpuSuitableScreen << ')';
return d;
}
#endif // !QT_NO_DEBUG_STREAM
@@ -113,15 +153,17 @@ QString GpuDescription::toString() const
{
QString result;
QTextStream str(&result);
- str << " Card name: " << description
- << "\n Driver Name: " << driverName
- << "\n Driver Version: " << driverVersion.toString()
- << "\n Vendor ID: 0x" << qSetPadChar(QLatin1Char('0'))
+ str << " Card name : " << description
+ << "\n Driver Name : " << driverName
+ << "\n Driver Version : " << driverVersion.toString()
+ << "\n Vendor ID : 0x" << qSetPadChar(QLatin1Char('0'))
<< uppercasedigits << hex << qSetFieldWidth(4) << vendorId
- << "\n Device ID: 0x" << qSetFieldWidth(4) << deviceId
- << "\n SubSys ID: 0x" << qSetFieldWidth(8) << subSysId
- << "\n Revision ID: 0x" << qSetFieldWidth(4) << revision
+ << "\n Device ID : 0x" << qSetFieldWidth(4) << deviceId
+ << "\n SubSys ID : 0x" << qSetFieldWidth(8) << subSysId
+ << "\n Revision ID : 0x" << qSetFieldWidth(4) << revision
<< dec;
+ if (!gpuSuitableScreen.isEmpty())
+ str << "\nGL windows forced to screen: " << gpuSuitableScreen;
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h
index 5ee2508462..22170f30b0 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.h
+++ b/src/plugins/platforms/windows/qwindowsopengltester.h
@@ -62,6 +62,7 @@ struct GpuDescription
QVersionNumber driverVersion;
QByteArray driverName;
QByteArray description;
+ QString gpuSuitableScreen;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 528927b0fb..9c31409644 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -58,6 +58,7 @@
#else
# include "qwindowsopenglcontext.h"
#endif
+#include "qwindowsopengltester.h"
#ifdef QT_NO_CURSOR
# include "qwindowscursor.h"
#endif
@@ -541,6 +542,84 @@ static inline void fixTopLevelWindowFlags(Qt::WindowFlags &flags)
flags |= Qt::FramelessWindowHint;
}
+static QScreen *screenForName(const QWindow *w, const QString &name)
+{
+ QScreen *winScreen = w ? w->screen() : QGuiApplication::primaryScreen();
+ if (winScreen && winScreen->name() != name) {
+ const auto screens = winScreen->virtualSiblings();
+ for (QScreen *screen : screens) {
+ if (screen->name() == name)
+ return screen;
+ }
+ }
+ return winScreen;
+}
+
+static QScreen *forcedScreenForGLWindow(const QWindow *w)
+{
+ const QString forceToScreen = GpuDescription::detect().gpuSuitableScreen;
+ return forceToScreen.isEmpty() ? nullptr : screenForName(w, forceToScreen);
+}
+
+static QPoint calcPosition(const QWindow *w, const QWindowCreationContextPtr &context, const QMargins &invMargins)
+{
+ const QPoint orgPos(context->frameX - invMargins.left(), context->frameY - invMargins.top());
+
+ if (!w || (!w->isTopLevel() && w->surfaceType() != QWindow::OpenGLSurface))
+ return orgPos;
+
+ // Workaround for QTBUG-50371
+ const QScreen *screenForGL = forcedScreenForGLWindow(w);
+ if (!screenForGL)
+ return orgPos;
+
+ const QPoint posFrame(context->frameX, context->frameY);
+ const QMargins margins = context->margins;
+ const QRect scrGeo = screenForGL->handle()->availableGeometry();
+
+ // Point is already in the required screen.
+ if (scrGeo.contains(orgPos))
+ return orgPos;
+
+ // If the visible part of the window is already in the
+ // required screen, just ignore the invisible offset.
+ if (scrGeo.contains(posFrame))
+ return posFrame;
+
+ // Find the original screen containing the coordinates.
+ const QList<QScreen *> screens = screenForGL->virtualSiblings();
+ const QScreen *orgScreen = nullptr;
+ for (QScreen *screen : screens) {
+ if (screen->handle()->availableGeometry().contains(posFrame)) {
+ orgScreen = screen;
+ break;
+ }
+ }
+ const QPoint ctPos = QPoint(qMax(scrGeo.left(), scrGeo.center().x()
+ + (margins.right() - margins.left() - context->frameWidth)/2),
+ qMax(scrGeo.top(), scrGeo.center().y()
+ + (margins.bottom() - margins.top() - context->frameHeight)/2));
+
+ // If initial coordinates were outside all screens, center the window on the required screen.
+ if (!orgScreen)
+ return ctPos;
+
+ const QRect orgGeo = orgScreen->handle()->availableGeometry();
+ const QRect orgFrame(QPoint(context->frameX, context->frameY),
+ QSize(context->frameWidth, context->frameHeight));
+
+ // Window would be centered on orgScreen. Center it on the required screen.
+ if (orgGeo.center() == (orgFrame - margins).center())
+ return ctPos;
+
+ // Transform the coordinates to map them into the required screen.
+ const QPoint newPos(scrGeo.left() + ((posFrame.x() - orgGeo.left()) * scrGeo.width()) / orgGeo.width(),
+ scrGeo.top() + ((posFrame.y() - orgGeo.top()) * scrGeo.height()) / orgGeo.height());
+ const QPoint newPosNoMargin(newPos.x() - invMargins.left(), newPos.y() - invMargins.top());
+
+ return scrGeo.contains(newPosNoMargin) ? newPosNoMargin : newPos;
+}
+
void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flagsIn,
unsigned creationFlags)
{
@@ -688,9 +767,12 @@ QWindowsWindowData
<< " custom margins: " << context->customMargins
<< " invisible margins: " << invMargins;
+
+ QPoint pos = calcPosition(w, context, invMargins);
+
result.hwnd = CreateWindowEx(exStyle, classNameUtf16, titleUtf16,
style,
- context->frameX - invMargins.left(), context->frameY - invMargins.top(),
+ pos.x(), pos.y(),
context->frameWidth, context->frameHeight,
parentHandle, NULL, appinst, NULL);
qCDebug(lcQpaWindows).nospace()
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
index 11397fb9ec..7a91c3d4e2 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautils.cpp
@@ -180,7 +180,7 @@ long roleToControlTypeId(QAccessible::Role role)
{QAccessible::PropertyPage, UIA_CustomControlTypeId},
{QAccessible::Indicator, UIA_CustomControlTypeId},
{QAccessible::Graphic, UIA_ImageControlTypeId},
- {QAccessible::StaticText, UIA_EditControlTypeId},
+ {QAccessible::StaticText, UIA_TextControlTypeId},
{QAccessible::EditableText, UIA_EditControlTypeId},
{QAccessible::Button, UIA_ButtonControlTypeId},
{QAccessible::CheckBox, UIA_CheckBoxControlTypeId},
diff --git a/src/plugins/printsupport/cups/qcupsprintersupport.cpp b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
index 56191c4dec..19e1df31f6 100644
--- a/src/plugins/printsupport/cups/qcupsprintersupport.cpp
+++ b/src/plugins/printsupport/cups/qcupsprintersupport.cpp
@@ -47,12 +47,14 @@
#include <QtPrintSupport/QPrinterInfo>
+#if QT_CONFIG(dialogbuttonbox)
#include <QGuiApplication>
#include <QDialog>
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
+#endif // QT_CONFIG(dialogbuttonbox)
#include <cups/ppd.h>
#ifndef QT_LINUXBASE // LSB merges everything into cups.h
@@ -61,6 +63,7 @@
QT_BEGIN_NAMESPACE
+#if QT_CONFIG(dialogbuttonbox)
static const char *getPasswordCB(const char */*prompt*/, http_t *http, const char */*method*/, const char *resource, void */*user_data*/)
{
// cups doesn't free the const char * we return so keep around
@@ -122,13 +125,16 @@ static const char *getPasswordCB(const char */*prompt*/, http_t *http, const cha
return password.constData();
}
+#endif // QT_CONFIG(dialogbuttonbox)
QCupsPrinterSupport::QCupsPrinterSupport()
: QPlatformPrinterSupport()
{
+#if QT_CONFIG(dialogbuttonbox)
// Only show password dialog if GUI application
if (qobject_cast<QGuiApplication*>(QCoreApplication::instance()))
cupsSetPasswordCB2(getPasswordCB, nullptr /* user_data */ );
+#endif // QT_CONFIG(dialogbuttonbox)
}
QCupsPrinterSupport::~QCupsPrinterSupport()
diff --git a/src/testlib/3rdparty/qt_attribution.json b/src/testlib/3rdparty/qt_attribution.json
index 47625634e5..18522b6cd8 100644
--- a/src/testlib/3rdparty/qt_attribution.json
+++ b/src/testlib/3rdparty/qt_attribution.json
@@ -8,6 +8,7 @@
"Description": "An instrumentation framework for building dynamic analysis tools.",
"Homepage": "http://valgrind.org/",
+ "Version": "3.3.0",
"License": "BSD 4-clause \"Original\" or \"Old\" License",
"LicenseId": "BSD-4-Clause",
"LicenseFile": "VALGRIND_LICENSE.txt",
@@ -36,6 +37,8 @@ Copyright (c) 2003, 2006 Massachusetts Institute of Technology"
"Files": "linux_perf_event_p.h",
"Description": "Allows access to the Linux kernel's performance events.",
+ "Homepage": "https://www.kernel.org",
+ "Version": "3.7",
"License": "GNU General Public License v2.0 only with Linux Syscall Note",
"LicenseId": "GPL-2.0 WITH Linux-syscall-note",
"LicenseFile": "LINUX_LICENSE.txt",
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index 29681bf5ce..3b78d2487f 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -95,6 +95,7 @@ struct Options
, generateAssetsFileList(true)
, build(true)
, gradle(false)
+ , auxMode(false)
, deploymentMechanism(Bundled)
, releasePackage(false)
, digestAlg(QLatin1String("SHA1"))
@@ -126,6 +127,7 @@ struct Options
bool generateAssetsFileList;
bool build;
bool gradle;
+ bool auxMode;
QTime timer;
// External tools
@@ -432,6 +434,8 @@ Options parseOptions()
options.jarSigner = true;
} else if (argument.compare(QLatin1String("--no-generated-assets-cache"), Qt::CaseInsensitive) == 0) {
options.generateAssetsFileList = false;
+ } else if (argument.compare(QLatin1String("--aux-mode"), Qt::CaseInsensitive) == 0) {
+ options.auxMode = true;
}
}
@@ -517,6 +521,9 @@ void printHelp()
" --verbose: Prints out information during processing.\n"
" --no-generated-assets-cache: Do not pregenerate the entry list for\n"
" the assets file engine.\n"
+ " --aux-mode: Operate in auxiliary mode. This will only copy the\n"
+ " dependencies into the build directory and update the XML templates.\n"
+ " The project will not be built or installed.\n"
" --help: Displays this information.\n\n",
qPrintable(QCoreApplication::arguments().at(0))
);
@@ -2826,6 +2833,22 @@ int main(int argc, char *argv[])
: "No"
);
+ if (options.auxMode) {
+ if (!readDependencies(&options))
+ return CannotReadDependencies;
+ if (!copyQtFiles(&options))
+ return CannotCopyQtFiles;
+ if (!copyAndroidExtraResources(options))
+ return CannotCopyAndroidExtraResources;
+ if (!stripLibraries(options))
+ return CannotStripLibraries;
+ if (!updateAndroidFiles(options))
+ return CannotUpdateAndroidFiles;
+ if (options.generateAssetsFileList && !generateAssetsFileList(options))
+ return CannotGenerateAssetsFileList;
+ return 0;
+ }
+
if (options.build) {
if (options.gradle)
cleanAndroidFiles(options);
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 2742b152f2..9116bf61fe 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -1047,10 +1047,15 @@ void QFileDialog::selectFile(const QString &filename)
return;
if (!d->usingWidgets()) {
- QUrl url = QUrl::fromLocalFile(filename);
+ QUrl url;
if (QFileInfo(filename).isRelative()) {
- QDir dir(d->options->initialDirectory().toLocalFile());
- url = QUrl::fromLocalFile(dir.absoluteFilePath(filename));
+ url = d->options->initialDirectory();
+ QString path = url.path();
+ if (!path.endsWith(QLatin1Char('/')))
+ path += QLatin1Char('/');
+ url.setPath(path + filename);
+ } else {
+ url = QUrl::fromLocalFile(filename);
}
d->selectFile_sys(url);
d->options->setInitiallySelectedFiles(QList<QUrl>() << url);
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 1c73588b7c..1a2ac4a4dd 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -977,7 +977,10 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
}
if (exposed) {
+ // QTBUG-39220, QTBUG-58575: set all (potentially fully obscured parent widgets) mapped.
m_widget->setAttribute(Qt::WA_Mapped);
+ for (QWidget *p = m_widget->parentWidget(); p && !p->testAttribute(Qt::WA_Mapped); p = p->parentWidget())
+ p->setAttribute(Qt::WA_Mapped);
if (!event->region().isNull())
wPriv->syncBackingStore(event->region());
} else {