summaryrefslogtreecommitdiffstats
path: root/src/platformsupport
diff options
context:
space:
mode:
Diffstat (limited to 'src/platformsupport')
-rw-r--r--src/platformsupport/devicediscovery/qdevicediscovery_p.h2
-rw-r--r--src/platformsupport/devicediscovery/qdevicediscovery_udev_p.h2
-rw-r--r--src/platformsupport/edid/qedidparser.cpp8
-rw-r--r--src/platformsupport/eglconvenience/qeglpbuffer_p.h2
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext_p.h4
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h4
-rw-r--r--src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h2
-rw-r--r--src/platformsupport/fbconvenience/qfbvthandler_p.h2
-rw-r--r--src/platformsupport/fbconvenience/qfbwindow.cpp5
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp4
-rw-r--r--src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp326
-rw-r--r--src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h6
-rw-r--r--src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp2
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm352
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h3
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp101
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp4
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h4
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp7
-rw-r--r--src/platformsupport/fontdatabases/windows/windows.pri4
-rw-r--r--src/platformsupport/fontdatabases/winrt/winrt.pri4
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp4
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp31
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h12
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp76
-rw-r--r--src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h8
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp6
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h4
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp65
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h8
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp22
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h4
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp61
-rw-r--r--src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h9
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp66
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp60
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h7
-rw-r--r--src/platformsupport/input/libinput/qlibinputhandler.cpp3
-rw-r--r--src/platformsupport/input/libinput/qlibinputpointer.cpp18
-rw-r--r--src/platformsupport/input/libinput/qlibinputpointer_p.h1
-rw-r--r--src/platformsupport/input/libinput/qlibinputtouch_p.h2
-rw-r--r--src/platformsupport/input/shared/devicehandlerlist_p.h95
-rw-r--r--src/platformsupport/input/shared/qevdevutil.cpp70
-rw-r--r--src/platformsupport/input/shared/qevdevutil_p.h76
-rw-r--r--src/platformsupport/input/shared/shared.pri3
-rw-r--r--src/platformsupport/input/tslib/qtslib.cpp32
-rw-r--r--src/platformsupport/input/tslib/qtslib_p.h9
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp54
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice_p.h1
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor.cpp9
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor_p.h2
-rw-r--r--src/platformsupport/linuxaccessibility/cache_p.h2
-rw-r--r--src/platformsupport/linuxaccessibility/dbusconnection_p.h2
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h2
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy_p.h16
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h22
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes.cpp12
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes_p.h4
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp16
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h4
-rw-r--r--src/platformsupport/vkconvenience/qvkconvenience.cpp2
-rw-r--r--src/platformsupport/vkconvenience/qvkconvenience_p.h2
62 files changed, 912 insertions, 838 deletions
diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_p.h b/src/platformsupport/devicediscovery/qdevicediscovery_p.h
index b1ce14b5c3..f1f50e9708 100644
--- a/src/platformsupport/devicediscovery/qdevicediscovery_p.h
+++ b/src/platformsupport/devicediscovery/qdevicediscovery_p.h
@@ -86,7 +86,7 @@ public:
Q_ENUM(QDeviceType)
Q_DECLARE_FLAGS(QDeviceTypes, QDeviceType)
- static QDeviceDiscovery *create(QDeviceTypes type, QObject *parent = 0);
+ static QDeviceDiscovery *create(QDeviceTypes type, QObject *parent = nullptr);
virtual QStringList scanConnectedDevices() = 0;
diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_udev_p.h b/src/platformsupport/devicediscovery/qdevicediscovery_udev_p.h
index 28618d0b21..82b475776d 100644
--- a/src/platformsupport/devicediscovery/qdevicediscovery_udev_p.h
+++ b/src/platformsupport/devicediscovery/qdevicediscovery_udev_p.h
@@ -61,7 +61,7 @@ class QDeviceDiscoveryUDev : public QDeviceDiscovery
Q_OBJECT
public:
- QDeviceDiscoveryUDev(QDeviceTypes types, struct udev *udev, QObject *parent = 0);
+ QDeviceDiscoveryUDev(QDeviceTypes types, struct udev *udev, QObject *parent = nullptr);
~QDeviceDiscoveryUDev();
QStringList scanConnectedDevices() override;
diff --git a/src/platformsupport/edid/qedidparser.cpp b/src/platformsupport/edid/qedidparser.cpp
index 06c8852825..6bf1f1db96 100644
--- a/src/platformsupport/edid/qedidparser.cpp
+++ b/src/platformsupport/edid/qedidparser.cpp
@@ -42,8 +42,6 @@
#include "qedidparser_p.h"
#include "qedidvendortable_p.h"
-#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
-
#define EDID_DESCRIPTOR_ALPHANUMERIC_STRING 0xfe
#define EDID_DESCRIPTOR_PRODUCT_NAME 0xfc
#define EDID_DESCRIPTOR_SERIAL_NUMBER 0xff
@@ -139,9 +137,9 @@ bool QEdidParser::parse(const QByteArray &blob)
manufacturer = m_vendorCache.value(pnpIdString);
if (manufacturer.isEmpty()) {
// Find the manufacturer from the vendor lookup table
- for (size_t i = 0; i < ARRAY_LENGTH(q_edidVendorTable); i++) {
- if (strncmp(q_edidVendorTable[i].id, pnpId, 3) == 0) {
- manufacturer = QString::fromUtf8(q_edidVendorTable[i].name);
+ for (const auto &vendor : q_edidVendorTable) {
+ if (strncmp(vendor.id, pnpId, 3) == 0) {
+ manufacturer = QString::fromUtf8(vendor.name);
break;
}
}
diff --git a/src/platformsupport/eglconvenience/qeglpbuffer_p.h b/src/platformsupport/eglconvenience/qeglpbuffer_p.h
index 0285e067a6..8ad2eb7248 100644
--- a/src/platformsupport/eglconvenience/qeglpbuffer_p.h
+++ b/src/platformsupport/eglconvenience/qeglpbuffer_p.h
@@ -60,7 +60,7 @@ class QEGLPbuffer : public QPlatformOffscreenSurface
{
public:
QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface,
- QEGLPlatformContext::Flags flags = 0);
+ QEGLPlatformContext::Flags flags = nullptr);
~QEGLPbuffer();
QSurfaceFormat format() const override { return m_format; }
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
index d6cbbe4131..ed77c57df5 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext_p.h
@@ -68,8 +68,8 @@ public:
Q_DECLARE_FLAGS(Flags, Flag)
QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
- EGLConfig *config = 0, const QVariant &nativeHandle = QVariant(),
- Flags flags = 0);
+ EGLConfig *config = nullptr, const QVariant &nativeHandle = QVariant(),
+ Flags flags = nullptr);
~QEGLPlatformContext();
void initialize() override;
diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h b/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
index 085a1c52f3..b9254d3071 100644
--- a/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
+++ b/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
@@ -64,7 +64,7 @@ class QPAEventDispatcherGlib : public QEventDispatcherGlib
Q_DECLARE_PRIVATE(QPAEventDispatcherGlib)
public:
- explicit QPAEventDispatcherGlib(QObject *parent = 0);
+ explicit QPAEventDispatcherGlib(QObject *parent = nullptr);
~QPAEventDispatcherGlib();
bool processEvents(QEventLoop::ProcessEventsFlags flags) override;
@@ -77,7 +77,7 @@ class QPAEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate
{
Q_DECLARE_PUBLIC(QPAEventDispatcherGlib)
public:
- QPAEventDispatcherGlibPrivate(GMainContext *context = 0);
+ QPAEventDispatcherGlibPrivate(GMainContext *context = nullptr);
GUserEventSource *userEventSource;
};
diff --git a/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h b/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h
index 7f775b73ee..8157b8793d 100644
--- a/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h
+++ b/src/platformsupport/eventdispatchers/qunixeventdispatcher_qpa_p.h
@@ -61,7 +61,7 @@ class QUnixEventDispatcherQPA : public QEventDispatcherUNIX
Q_OBJECT
public:
- explicit QUnixEventDispatcherQPA(QObject *parent = 0);
+ explicit QUnixEventDispatcherQPA(QObject *parent = nullptr);
~QUnixEventDispatcherQPA();
bool processEvents(QEventLoop::ProcessEventsFlags flags);
diff --git a/src/platformsupport/fbconvenience/qfbvthandler_p.h b/src/platformsupport/fbconvenience/qfbvthandler_p.h
index 17d07317b2..d565ec3632 100644
--- a/src/platformsupport/fbconvenience/qfbvthandler_p.h
+++ b/src/platformsupport/fbconvenience/qfbvthandler_p.h
@@ -63,7 +63,7 @@ class QFbVtHandler : public QObject
Q_OBJECT
public:
- QFbVtHandler(QObject *parent = 0);
+ QFbVtHandler(QObject *parent = nullptr);
~QFbVtHandler();
signals:
diff --git a/src/platformsupport/fbconvenience/qfbwindow.cpp b/src/platformsupport/fbconvenience/qfbwindow.cpp
index 36f92b8cea..9f5f87d9d6 100644
--- a/src/platformsupport/fbconvenience/qfbwindow.cpp
+++ b/src/platformsupport/fbconvenience/qfbwindow.cpp
@@ -45,11 +45,12 @@
QT_BEGIN_NAMESPACE
+static QBasicAtomicInt winIdGenerator = Q_BASIC_ATOMIC_INITIALIZER(0);
+
QFbWindow::QFbWindow(QWindow *window)
: QPlatformWindow(window), mBackingStore(0), mWindowState(Qt::WindowNoState)
{
- static QAtomicInt winIdGenerator(1);
- mWindowId = winIdGenerator.fetchAndAddRelaxed(1);
+ mWindowId = winIdGenerator.fetchAndAddRelaxed(1) + 1;
}
QFbWindow::~QFbWindow()
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index e545d54ec2..7abf295782 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -721,7 +721,7 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont
FcValue value;
value.type = FcTypeString;
- QByteArray cs = family.toUtf8();
+ const QByteArray cs = family.toUtf8();
value.u.s = (const FcChar8 *)cs.data();
FcPatternAdd(pattern,FC_FAMILY,value,true);
@@ -863,7 +863,7 @@ QString QFontconfigDatabase::resolveFontFamilyAlias(const QString &family) const
return family;
if (!family.isEmpty()) {
- QByteArray cs = family.toUtf8();
+ const QByteArray cs = family.toUtf8();
FcPatternAddString(pattern, FC_FAMILY, (const FcChar8 *) cs.constData());
}
FcConfigSubstitute(0, pattern, FcMatchPattern);
diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
index 08e652b2a0..8c6cc8fbc1 100644
--- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
+++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp
@@ -121,13 +121,12 @@ class QtFreetypeData
{
public:
QtFreetypeData()
- : library(0), hasPatentFreeLcdRendering(false)
+ : library(0)
{ }
~QtFreetypeData();
FT_Library library;
QHash<QFontEngine::FaceId, QFreetypeFace *> faces;
- bool hasPatentFreeLcdRendering;
};
QtFreetypeData::~QtFreetypeData()
@@ -153,11 +152,6 @@ QtFreetypeData *qt_getFreetypeData()
FT_Bool no_darkening = false;
FT_Property_Set(freetypeData->library, "cff", "no-stem-darkening", &no_darkening);
#endif
- // FreeType has since 2.8.1 a patent free alternative to LCD-filtering.
- FT_Int amajor, aminor = 0, apatch = 0;
- FT_Library_Version(freetypeData->library, &amajor, &aminor, &apatch);
- if (QT_VERSION_CHECK(amajor, aminor, apatch) >= QT_VERSION_CHECK(2, 8, 1))
- freetypeData->hasPatentFreeLcdRendering = true;
}
return freetypeData;
}
@@ -260,7 +254,7 @@ QFreetypeFace *QFreetypeFace::getFace(const QFontEngine::FaceId &face_id,
}
newFreetype->face = face;
- newFreetype->ref.store(1);
+ newFreetype->ref.storeRelaxed(1);
newFreetype->xsize = 0;
newFreetype->ysize = 0;
newFreetype->matrix.xx = 0x10000;
@@ -556,26 +550,7 @@ void QFreetypeFace::addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point,
slot->bitmap.buffer, slot->bitmap.pitch, slot->bitmap.width, slot->bitmap.rows, path);
}
-struct LcdFilterDummy
-{
- static inline void filterPixel(uchar &, uchar &, uchar &)
- {}
-};
-
-struct LcdFilterLegacy
-{
- static inline void filterPixel(uchar &red, uchar &green, uchar &blue)
- {
- uint r = red, g = green, b = blue;
- // intra-pixel filter used by the legacy filter (adopted from _ft_lcd_filter_legacy)
- red = (r * uint(65538 * 9/13) + g * uint(65538 * 1/6) + b * uint(65538 * 1/13)) / 65536;
- green = (r * uint(65538 * 3/13) + g * uint(65538 * 4/6) + b * uint(65538 * 3/13)) / 65536;
- blue = (r * uint(65538 * 1/13) + g * uint(65538 * 1/6) + b * uint(65538 * 9/13)) / 65536;
- }
-};
-
-template <typename LcdFilter>
-static void convertRGBToARGB_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
+static inline void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
{
const int offs = bgr ? -1 : 1;
const int w = width * 3;
@@ -585,7 +560,6 @@ static void convertRGBToARGB_helper(const uchar *src, uint *dst, int width, int
uchar red = src[x + 1 - offs];
uchar green = src[x + 1];
uchar blue = src[x + 1 + offs];
- LcdFilter::filterPixel(red, green, blue);
*dd++ = (0xFFU << 24) | (red << 16) | (green << 8) | blue;
}
dst += width;
@@ -593,16 +567,7 @@ static void convertRGBToARGB_helper(const uchar *src, uint *dst, int width, int
}
}
-static inline void convertRGBToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
-{
- if (!legacyFilter)
- convertRGBToARGB_helper<LcdFilterDummy>(src, dst, width, height, src_pitch, bgr);
- else
- convertRGBToARGB_helper<LcdFilterLegacy>(src, dst, width, height, src_pitch, bgr);
-}
-
-template <typename LcdFilter>
-static void convertRGBToARGB_V_helper(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
+static inline void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr)
{
const int offs = bgr ? -src_pitch : src_pitch;
while (height--) {
@@ -610,54 +575,12 @@ static void convertRGBToARGB_V_helper(const uchar *src, uint *dst, int width, in
uchar red = src[x + src_pitch - offs];
uchar green = src[x + src_pitch];
uchar blue = src[x + src_pitch + offs];
- LcdFilter::filterPixel(red, green, blue);
*dst++ = (0XFFU << 24) | (red << 16) | (green << 8) | blue;
}
src += 3*src_pitch;
}
}
-static inline void convertRGBToARGB_V(const uchar *src, uint *dst, int width, int height, int src_pitch, bool bgr, bool legacyFilter)
-{
- if (!legacyFilter)
- convertRGBToARGB_V_helper<LcdFilterDummy>(src, dst, width, height, src_pitch, bgr);
- else
- convertRGBToARGB_V_helper<LcdFilterLegacy>(src, dst, width, height, src_pitch, bgr);
-}
-
-static inline void convertGRAYToARGB(const uchar *src, uint *dst, int width, int height, int src_pitch)
-{
- while (height--) {
- const uchar *p = src;
- const uchar * const e = p + width;
- while (p < e) {
- uchar gray = *p++;
- *dst++ = (0xFFU << 24) | (gray << 16) | (gray << 8) | gray;
- }
- src += src_pitch;
- }
-}
-
-static void convoluteBitmap(const uchar *src, uchar *dst, int width, int height, int pitch)
-{
- // convolute the bitmap with a triangle filter to get rid of color fringes
- // If we take account for a gamma value of 2, we end up with
- // weights of 1, 4, 9, 4, 1. We use an approximation of 1, 3, 8, 3, 1 here,
- // as this nicely sums up to 16 :)
- int h = height;
- while (h--) {
- dst[0] = dst[1] = 0;
- //
- for (int x = 2; x < width - 2; ++x) {
- uint sum = src[x-2] + 3*src[x-1] + 8*src[x] + 3*src[x+1] + src[x+2];
- dst[x] = (uchar) (sum >> 4);
- }
- dst[width - 2] = dst[width - 1] = 0;
- src += pitch;
- dst += pitch;
- }
-}
-
static QFontEngine::SubpixelAntialiasingType subpixelAntialiasingTypeHint()
{
static int type = -1;
@@ -1148,126 +1071,49 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
int glyph_buffer_size = 0;
QScopedArrayPointer<uchar> glyph_buffer;
- bool useFreetypeRenderGlyph = false;
- if (slot->format == FT_GLYPH_FORMAT_OUTLINE && (hsubpixel || vfactor != 1)) {
- err = FT_Library_SetLcdFilter(slot->library, (FT_LcdFilter)lcdFilterType);
- // We use FT_Render_Glyph if freetype has support for lcd-filtering
- // or is version 2.8.1 or higher and can do without.
- if (err == FT_Err_Ok || qt_getFreetypeData()->hasPatentFreeLcdRendering)
- useFreetypeRenderGlyph = true;
+ FT_Render_Mode renderMode = (default_hint_style == HintLight) ? FT_RENDER_MODE_LIGHT : FT_RENDER_MODE_NORMAL;
+ switch (format) {
+ case Format_Mono:
+ renderMode = FT_RENDER_MODE_MONO;
+ break;
+ case Format_A32:
+ Q_ASSERT(hsubpixel || vfactor != 1);
+ renderMode = hsubpixel ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_LCD_V;
+ break;
+ case Format_A8:
+ case Format_ARGB:
+ break;
+ default:
+ Q_UNREACHABLE();
}
- if (useFreetypeRenderGlyph) {
- err = FT_Render_Glyph(slot, hsubpixel ? FT_RENDER_MODE_LCD : FT_RENDER_MODE_LCD_V);
-
- if (err != FT_Err_Ok)
- qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
-
- FT_Library_SetLcdFilter(slot->library, FT_LCD_FILTER_NONE);
+ FT_Library_SetLcdFilter(slot->library, (FT_LcdFilter)lcdFilterType);
- info.height = slot->bitmap.rows / vfactor;
- info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width;
- info.x = slot->bitmap_left;
- info.y = slot->bitmap_top;
+ err = FT_Render_Glyph(slot, renderMode);
+ if (err != FT_Err_Ok)
+ qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph);
- glyph_buffer_size = info.width * info.height * 4;
- glyph_buffer.reset(new uchar[glyph_buffer_size]);
+ FT_Library_SetLcdFilter(slot->library, FT_LCD_FILTER_NONE);
- if (hsubpixel)
- convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB, false);
- else if (vfactor != 1)
- convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB, false);
- } else {
- int left = slot->metrics.horiBearingX;
- int right = slot->metrics.horiBearingX + slot->metrics.width;
- int top = slot->metrics.horiBearingY;
- int bottom = slot->metrics.horiBearingY - slot->metrics.height;
- if (transform && slot->format != FT_GLYPH_FORMAT_BITMAP)
- transformBoundingBox(&left, &top, &right, &bottom, &matrix);
- left = FLOOR(left);
- right = CEIL(right);
- bottom = FLOOR(bottom);
- top = CEIL(top);
-
- int hpixels = TRUNC(right - left);
- // subpixel position requires one more pixel
- if (subPixelPosition > 0 && format != Format_Mono)
- hpixels++;
-
- if (hsubpixel)
- hpixels = hpixels*3 + 8;
- info.width = hpixels;
- info.height = TRUNC(top - bottom);
- info.x = TRUNC(left);
- info.y = TRUNC(top);
- if (hsubpixel) {
- info.width /= 3;
- info.x -= 1;
- }
-
- // If any of the metrics are too large to fit, don't cache them
- if (areMetricsTooLarge(info))
- return 0;
+ info.height = slot->bitmap.rows;
+ info.width = slot->bitmap.width;
+ info.x = slot->bitmap_left;
+ info.y = slot->bitmap_top;
+ if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD)
+ info.width = info.width / 3;
+ if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V)
+ info.height = info.height / vfactor;
int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 :
(format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4));
- if (glyph_buffer_size < pitch * info.height) {
- glyph_buffer_size = pitch * info.height;
- glyph_buffer.reset(new uchar[glyph_buffer_size]);
- memset(glyph_buffer.data(), 0, glyph_buffer_size);
- }
- if (slot->format == FT_GLYPH_FORMAT_OUTLINE) {
- FT_Bitmap bitmap;
- bitmap.rows = info.height*vfactor;
- bitmap.width = hpixels;
- bitmap.pitch = format == Format_Mono ? (((info.width + 31) & ~31) >> 3) : ((bitmap.width + 3) & ~3);
- int bitmap_buffer_size = bitmap.rows * bitmap.pitch;
- if (!hsubpixel && vfactor == 1 && format != Format_A32) {
- Q_ASSERT(glyph_buffer_size <= bitmap_buffer_size);
- bitmap.buffer = glyph_buffer.data();
- } else {
- bitmap.buffer = new uchar[bitmap_buffer_size];
- memset(bitmap.buffer, 0, bitmap_buffer_size);
- }
- bitmap.pixel_mode = format == Format_Mono ? FT_PIXEL_MODE_MONO : FT_PIXEL_MODE_GRAY;
- FT_Matrix matrix;
- matrix.xx = (hsubpixel ? 3 : 1) << 16;
- matrix.yy = vfactor << 16;
- matrix.yx = matrix.xy = 0;
-
- FT_Outline_Transform(&slot->outline, &matrix);
- FT_Outline_Translate (&slot->outline, (hsubpixel ? -3*left +(4<<6) : -left), -bottom*vfactor);
- FT_Outline_Get_Bitmap(slot->library, &slot->outline, &bitmap);
- if (hsubpixel) {
- Q_ASSERT (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY);
- Q_ASSERT(antialias);
- uchar *convoluted = new uchar[bitmap_buffer_size];
- bool useLegacyLcdFilter = false;
- useLegacyLcdFilter = (lcdFilterType == FT_LCD_FILTER_LEGACY);
- uchar *buffer = bitmap.buffer;
- if (!useLegacyLcdFilter) {
- convoluteBitmap(bitmap.buffer, convoluted, bitmap.width, info.height, bitmap.pitch);
- buffer = convoluted;
- }
- convertRGBToARGB(buffer + 1, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch, subpixelType != Subpixel_RGB, useLegacyLcdFilter);
- delete [] convoluted;
- } else if (vfactor != 1) {
- convertRGBToARGB_V(bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch, subpixelType != Subpixel_VRGB, true);
- } else if (format == Format_A32 && bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
- convertGRAYToARGB(bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, bitmap.pitch);
- }
+ glyph_buffer_size = info.height * pitch;
+ glyph_buffer.reset(new uchar[glyph_buffer_size]);
- if (bitmap.buffer != glyph_buffer.data())
- delete [] bitmap.buffer;
- } else if (slot->format == FT_GLYPH_FORMAT_BITMAP) {
-#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100) >= 20500)
- Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO || slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA);
-#else
- Q_ASSERT(slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO);
-#endif
+ if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
uchar *src = slot->bitmap.buffer;
uchar *dst = glyph_buffer.data();
int h = slot->bitmap.rows;
+ // Some fonts return bitmaps even when we requested something else:
if (format == Format_Mono) {
int bytes = ((info.width + 7) & ~7) >> 3;
while (h--) {
@@ -1275,69 +1121,63 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
dst += pitch;
src += slot->bitmap.pitch;
}
- } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
- if (hsubpixel) {
- while (h--) {
- uint *dd = (uint *)dst;
- *dd++ = 0;
- for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++) {
- uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000);
- *dd++ = a;
- }
- *dd++ = 0;
- dst += pitch;
- src += slot->bitmap.pitch;
- }
- } else if (vfactor != 1) {
- while (h--) {
- uint *dd = (uint *)dst;
- for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++) {
- uint a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffff : 0x000000);
- *dd++ = a;
- }
- dst += pitch;
- src += slot->bitmap.pitch;
- }
- } else {
- while (h--) {
- for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++) {
- unsigned char a = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xff : 0x00);
- dst[x] = a;
- }
- dst += pitch;
- src += slot->bitmap.pitch;
- }
+ } else if (format == Format_A8) {
+ while (h--) {
+ for (int x = 0; x < int{info.width}; x++)
+ dst[x] = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xff : 0x00);
+ dst += pitch;
+ src += slot->bitmap.pitch;
}
- }
-#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100) >= 20500)
- else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
- {
+ } else {
while (h--) {
-#if Q_BYTE_ORDER == Q_BIG_ENDIAN
- const quint32 *srcPixel = (const quint32 *)src;
- quint32 *dstPixel = (quint32 *)dst;
- for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++, srcPixel++, dstPixel++) {
- const quint32 pixel = *srcPixel;
- *dstPixel = qbswap(pixel);
- }
-#else
- memcpy(dst, src, slot->bitmap.width * 4);
-#endif
- dst += slot->bitmap.pitch;
+ uint *dd = reinterpret_cast<uint *>(dst);
+ for (int x = 0; x < int{info.width}; x++)
+ dd[x] = ((src[x >> 3] & (0x80 >> (x & 7))) ? 0xffffffff : 0x00000000);
+ dst += pitch;
src += slot->bitmap.pitch;
}
- info.width = info.linearAdvance = info.xOff = slot->bitmap.width;
- info.height = slot->bitmap.rows;
- info.x = slot->bitmap_left;
- info.y = slot->bitmap_top;
}
+ } else if (slot->bitmap.pixel_mode == 7 /*FT_PIXEL_MODE_BGRA*/) {
+ Q_ASSERT(format == Format_ARGB);
+ uchar *src = slot->bitmap.buffer;
+ uchar *dst = glyph_buffer.data();
+ int h = slot->bitmap.rows;
+ while (h--) {
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ const quint32 *srcPixel = (const quint32 *)src;
+ quint32 *dstPixel = (quint32 *)dst;
+ for (int x = 0; x < static_cast<int>(slot->bitmap.width); x++, srcPixel++, dstPixel++) {
+ const quint32 pixel = *srcPixel;
+ *dstPixel = qbswap(pixel);
+ }
+#else
+ memcpy(dst, src, slot->bitmap.width * 4);
#endif
+ dst += slot->bitmap.pitch;
+ src += slot->bitmap.pitch;
+ }
+ info.linearAdvance = info.xOff = slot->bitmap.width;
+ } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY) {
+ Q_ASSERT(format == Format_A8);
+ uchar *src = slot->bitmap.buffer;
+ uchar *dst = glyph_buffer.data();
+ int h = slot->bitmap.rows;
+ int bytes = info.width;
+ while (h--) {
+ memcpy (dst, src, bytes);
+ dst += pitch;
+ src += slot->bitmap.pitch;
+ }
+ } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD) {
+ Q_ASSERT(format == Format_A32);
+ convertRGBToARGB(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_RGB);
+ } else if (slot->bitmap.pixel_mode == FT_PIXEL_MODE_LCD_V) {
+ Q_ASSERT(format == Format_A32);
+ convertRGBToARGB_V(slot->bitmap.buffer, (uint *)glyph_buffer.data(), info.width, info.height, slot->bitmap.pitch, subpixelType != Subpixel_VRGB);
} else {
- qWarning("QFontEngine: Glyph neither outline nor bitmap format=%d", slot->format);
+ qWarning("QFontEngine: Glyph rendered in unknown pixel_mode=%d", slot->bitmap.pixel_mode);
return 0;
}
- }
-
if (!g) {
g = new Glyph;
diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h
index 2863d206d2..2e3aef6979 100644
--- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h
+++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h
@@ -116,11 +116,11 @@ private:
friend class QFontEngineFT;
friend class QtFreetypeData;
friend struct QScopedPointerDeleter<QFreetypeFace>;
- QFreetypeFace() : _lock(QMutex::Recursive) {}
+ QFreetypeFace() = default;
~QFreetypeFace() {}
void cleanup();
QAtomicInt ref;
- QMutex _lock;
+ QRecursiveMutex _lock;
QByteArray fontData;
QFontEngine::Holder hbFace;
@@ -252,7 +252,7 @@ private:
inline bool isScalableBitmap() const { return freetype->isScalableBitmap(); }
inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const
- { return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly, disableOutlineDrawing); }
+ { return loadGlyph(cacheEnabled ? &defaultGlyphSet : nullptr, glyph, subPixelPosition, format, fetchMetricsOnly, disableOutlineDrawing); }
Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false, bool disableOutlineDrawing = false) const;
Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t, bool fetchBoundingBox = false, bool disableOutlineDrawing = false);
diff --git a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp
index adc2f6c1fe..25c10fbd3c 100644
--- a/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/freetype/qfreetypefontdatabase.cpp
@@ -127,7 +127,7 @@ QStringList QFreeTypeFontDatabase::addTTFile(const QByteArray &fontData, const Q
error = FT_New_Face(library, file.constData(), index, &face);
}
if (error != FT_Err_Ok) {
- qDebug() << "FT_New_Face failed with index" << index << ':' << hex << error;
+ qDebug() << "FT_New_Face failed with index" << index << ':' << Qt::hex << error;
break;
}
numFaces = face->num_faces;
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index c450e91d49..daa3dc94ea 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -48,6 +48,8 @@
#import <UIKit/UIFont.h>
#endif
+#include <QtCore/qelapsedtimer.h>
+
#include "qcoretextfontdatabase_p.h"
#include "qfontengine_coretext_p.h"
#if QT_CONFIG(settings)
@@ -100,20 +102,6 @@ static const char *languageForWritingSystem[] = {
};
enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) };
-#ifdef Q_OS_OSX
-static NSInteger languageMapSort(id obj1, id obj2, void *context)
-{
- NSArray<NSString *> *map1 = reinterpret_cast<NSArray<NSString *> *>(obj1);
- NSArray<NSString *> *map2 = reinterpret_cast<NSArray<NSString *> *>(obj2);
- NSArray<NSString *> *languages = reinterpret_cast<NSArray<NSString *> *>(context);
-
- NSString *lang1 = [map1 objectAtIndex:0];
- NSString *lang2 = [map2 objectAtIndex:0];
-
- return [languages indexOfObject:lang1] - [languages indexOfObject:lang2];
-}
-#endif
-
QCoreTextFontDatabase::QCoreTextFontDatabase()
: m_hasPopulatedAliases(false)
{
@@ -127,39 +115,77 @@ QCoreTextFontDatabase::~QCoreTextFontDatabase()
void QCoreTextFontDatabase::populateFontDatabase()
{
+ qCDebug(lcQpaFonts) << "Populating font database...";
+ QElapsedTimer elapsed;
+ if (lcQpaFonts().isDebugEnabled())
+ elapsed.start();
+
QCFType<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames();
for (NSString *familyName in familyNames.as<const NSArray *>())
QPlatformFontDatabase::registerFontFamily(QString::fromNSString(familyName));
+ qCDebug(lcQpaFonts) << "Populating available families took" << elapsed.restart() << "ms";
+
// Force creating the theme fonts to get the descriptors in m_systemFontDescriptors
if (m_themeFonts.isEmpty())
(void)themeFonts();
+ qCDebug(lcQpaFonts) << "Resolving theme fonts took" << elapsed.restart() << "ms";
+
Q_FOREACH (CTFontDescriptorRef fontDesc, m_systemFontDescriptors)
populateFromDescriptor(fontDesc);
+ qCDebug(lcQpaFonts) << "Populating system descriptors took" << elapsed.restart() << "ms";
+
Q_ASSERT(!m_hasPopulatedAliases);
}
-bool QCoreTextFontDatabase::populateFamilyAliases()
+bool QCoreTextFontDatabase::populateFamilyAliases(const QString &missingFamily)
{
#if defined(Q_OS_MACOS)
if (m_hasPopulatedAliases)
return false;
+ // There's no API to go from a localized family name to its non-localized
+ // name, so we have to resort to enumerating all the available fonts and
+ // doing a reverse lookup.
+
+ qCDebug(lcQpaFonts) << "Populating family aliases...";
+ QElapsedTimer elapsed;
+ elapsed.start();
+
+ QString nonLocalizedMatch;
QCFType<CFArrayRef> familyNames = CTFontManagerCopyAvailableFontFamilyNames();
+ NSFontManager *fontManager = NSFontManager.sharedFontManager;
for (NSString *familyName in familyNames.as<const NSArray *>()) {
- NSFontManager *fontManager = [NSFontManager sharedFontManager];
NSString *localizedFamilyName = [fontManager localizedNameForFamily:familyName face:nil];
if (![localizedFamilyName isEqual:familyName]) {
- QPlatformFontDatabase::registerAliasToFontFamily(
- QString::fromNSString(familyName),
- QString::fromNSString(localizedFamilyName));
+ QString nonLocalizedFamily = QString::fromNSString(familyName);
+ QString localizedFamily = QString::fromNSString(localizedFamilyName);
+ QPlatformFontDatabase::registerAliasToFontFamily(nonLocalizedFamily, localizedFamily);
+ if (localizedFamily == missingFamily)
+ nonLocalizedMatch = nonLocalizedFamily;
}
}
m_hasPopulatedAliases = true;
+
+ if (lcQpaFonts().isWarningEnabled()) {
+ QString warningMessage;
+ QDebug msg(&warningMessage);
+
+ msg << "Populating font family aliases took" << elapsed.restart() << "ms.";
+ if (!nonLocalizedMatch.isNull())
+ msg << "Replace uses of" << missingFamily << "with its non-localized name" << nonLocalizedMatch;
+ else
+ msg << "Replace uses of missing font family" << missingFamily << "with one that exists";
+ msg << "to avoid this cost.";
+
+ qCWarning(lcQpaFonts) << qPrintable(warningMessage);
+ }
+
return true;
#else
+ Q_UNUSED(missingFamily);
return false;
#endif
}
@@ -173,7 +199,7 @@ void QCoreTextFontDatabase::populateFamily(const QString &familyName)
// A single family might match several different fonts with different styles eg.
QCFType<CFArrayRef> matchingFonts = (CFArrayRef) CTFontDescriptorCreateMatchingFontDescriptors(nameOnlyDescriptor, 0);
if (!matchingFonts) {
- qWarning() << "QCoreTextFontDatabase: Found no matching fonts for family" << familyName;
+ qCWarning(lcQpaFonts) << "QCoreTextFontDatabase: Found no matching fonts for family" << familyName;
return;
}
@@ -406,175 +432,163 @@ template class QCoreTextFontDatabaseEngineFactory<QCoreTextFontEngine>;
template class QCoreTextFontDatabaseEngineFactory<QFontEngineFT>;
#endif
-QFont::StyleHint styleHintFromNSString(NSString *style)
+CTFontDescriptorRef descriptorForFamily(const QString &familyName)
+{
+ return CTFontDescriptorCreateWithAttributes(CFDictionaryRef(@{
+ (id)kCTFontFamilyNameAttribute: familyName.toNSString()
+ }));
+}
+
+CTFontDescriptorRef descriptorForFamily(const char *familyName)
{
- if ([style isEqual: @"sans-serif"])
- return QFont::SansSerif;
- else if ([style isEqual: @"monospace"])
- return QFont::Monospace;
- else if ([style isEqual: @"cursive"])
- return QFont::Cursive;
- else if ([style isEqual: @"serif"])
- return QFont::Serif;
- else if ([style isEqual: @"fantasy"])
- return QFont::Fantasy;
- else // if ([style isEqual: @"default"])
- return QFont::AnyStyle;
+ return descriptorForFamily(QString::fromLatin1(familyName));
}
-#ifdef Q_OS_OSX
-static QString familyNameFromPostScriptName(NSString *psName)
+CFArrayRef fallbacksForDescriptor(CTFontDescriptorRef descriptor)
{
- QCFType<CTFontDescriptorRef> fontDescriptor = (CTFontDescriptorRef) CTFontDescriptorCreateWithNameAndSize((CFStringRef)psName, 12.0);
- QCFString familyName = (CFStringRef) CTFontDescriptorCopyAttribute(fontDescriptor, kCTFontFamilyNameAttribute);
- QString name = QString::fromCFString(familyName);
- if (name.isEmpty())
- qWarning() << "QCoreTextFontDatabase: Failed to resolve family name for PostScript name " << QString::fromCFString((CFStringRef)psName);
+ QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(descriptor, 0.0, nullptr);
+ if (!font) {
+ qCWarning(lcQpaFonts) << "Failed to create fallback font for" << descriptor;
+ return nullptr;
+ }
+
+ CFArrayRef cascadeList = CFArrayRef(CTFontCopyDefaultCascadeListForLanguages(font,
+ (CFArrayRef)[NSUserDefaults.standardUserDefaults stringArrayForKey:@"AppleLanguages"]));
+
+ if (!cascadeList) {
+ qCWarning(lcQpaFonts) << "Failed to create fallback cascade list for" << descriptor;
+ return nullptr;
+ }
- return name;
+ return cascadeList;
}
-#endif
-static void addExtraFallbacks(QStringList *fallbackList)
+CFArrayRef QCoreTextFontDatabase::fallbacksForFamily(const QString &family)
{
-#if defined(Q_OS_MACOS)
- // Since we are only returning a list of default fonts for the current language, we do not
- // cover all unicode completely. This was especially an issue for some of the common script
- // symbols such as mathematical symbols, currency or geometric shapes. To minimize the risk
- // of missing glyphs, we add Arial Unicode MS as a final fail safe, since this covers most
- // of Unicode 2.1.
- if (!fallbackList->contains(QStringLiteral("Arial Unicode MS")))
- fallbackList->append(QStringLiteral("Arial Unicode MS"));
- // Since some symbols (specifically Braille) are not in Arial Unicode MS, we
- // add Apple Symbols to cover those too.
- if (!fallbackList->contains(QStringLiteral("Apple Symbols")))
- fallbackList->append(QStringLiteral("Apple Symbols"));
-#else
- Q_UNUSED(fallbackList)
-#endif
+ if (family.isEmpty())
+ return nullptr;
+
+ QCFType<CTFontDescriptorRef> fontDescriptor = descriptorForFamily(family);
+ if (!fontDescriptor) {
+ qCWarning(lcQpaFonts) << "Failed to create fallback font descriptor for" << family;
+ return nullptr;
+ }
+
+ // If the font is not available we want to fall back to the style hint.
+ // By creating a matching font descriptor we can verify whether the font
+ // is available or not, and avoid CTFontCreateWithFontDescriptor picking
+ // a default font for us based on incomplete information.
+ fontDescriptor = CTFontDescriptorCreateMatchingFontDescriptor(fontDescriptor, 0);
+ if (!fontDescriptor)
+ return nullptr;
+
+ return fallbacksForDescriptor(fontDescriptor);
}
-// ### Replace this with QPlatformFontDatabase::isFamilyPopulated() in Qt 5.14
-Q_GUI_EXPORT extern bool qt_isFontFamilyPopulated(const QString &familyName);
+CTFontDescriptorRef descriptorForFontType(CTFontUIFontType uiType)
+{
+ static const CGFloat kDefaultSizeForRequestedUIType = 0.0;
+ QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(
+ uiType, kDefaultSizeForRequestedUIType, nullptr);
+ return CTFontCopyFontDescriptor(ctFont);
+}
+
+CTFontDescriptorRef descriptorForStyle(QFont::StyleHint styleHint)
+{
+ switch (styleHint) {
+ case QFont::SansSerif: return descriptorForFamily("Helvetica");
+ case QFont::Serif: return descriptorForFamily("Times New Roman");
+ case QFont::Monospace: return descriptorForFamily("Menlo");
+#ifdef Q_OS_MACOS
+ case QFont::Cursive: return descriptorForFamily("Apple Chancery");
+#endif
+ case QFont::Fantasy: return descriptorForFamily("Zapfino");
+ case QFont::TypeWriter: return descriptorForFamily("American Typewriter");
+ case QFont::AnyStyle: Q_FALLTHROUGH();
+ case QFont::System: return descriptorForFontType(kCTFontUIFontSystem);
+ default: return nullptr; // No matching font on this platform
+ }
+}
QStringList QCoreTextFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const
{
Q_UNUSED(style);
- Q_UNUSED(script);
+
+ qCDebug(lcQpaFonts).nospace() << "Resolving fallbacks families for"
+ << (!family.isEmpty() ? qPrintable(QLatin1String(" family '%1' with").arg(family)) : "")
+ << " style hint " << styleHint;
QMacAutoReleasePool pool;
- static QHash<QString, QStringList> fallbackLists;
-
- if (!family.isEmpty()) {
- QCFType<CFMutableDictionaryRef> attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
- CFDictionaryAddValue(attributes, kCTFontFamilyNameAttribute, QCFString(family));
- if (QCFType<CTFontDescriptorRef> fontDescriptor = CTFontDescriptorCreateWithAttributes(attributes)) {
- if (QCFType<CTFontRef> font = CTFontCreateWithFontDescriptor(fontDescriptor, 12.0, 0)) {
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
- NSArray *languages = [defaults stringArrayForKey: @"AppleLanguages"];
-
- QCFType<CFArrayRef> cascadeList = (CFArrayRef) CTFontCopyDefaultCascadeListForLanguages(font, (CFArrayRef) languages);
- if (cascadeList) {
- QStringList fallbackList;
- const int numCascades = CFArrayGetCount(cascadeList);
-
- int symbolIndex = -1;
- int notoSansUniversalIndex = -1;
- for (int i = 0; i < numCascades; ++i) {
- CTFontDescriptorRef fontFallback = (CTFontDescriptorRef) CFArrayGetValueAtIndex(cascadeList, i);
- QCFString fallbackFamilyName = (CFStringRef) CTFontDescriptorCopyAttribute(fontFallback, kCTFontFamilyNameAttribute);
-
- QString fallbackName = QString::fromCFString(fallbackFamilyName);
- fallbackList.append(fallbackName);
-
- if (!qt_isFontFamilyPopulated(fallbackName))
- const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(fontFallback, fallbackName);
-
- if (fallbackName == QLatin1String(".Apple Symbols Fallback"))
- symbolIndex = fallbackList.size() - 1;
- else if (fallbackName == QLatin1String(".Noto Sans Universal"))
- notoSansUniversalIndex = fallbackList.size() - 1;
- }
-
- // .Apple Symbols Fallback will be at the beginning of the list and we will
- // detect that this has glyphs for Arabic and other writing systems.
- // Since it is a symbol font, it should be the last resort, so that
- // the proper fonts for these writing systems are preferred.
- if (symbolIndex >= 0) {
- fallbackList.move(symbolIndex, fallbackList.size() - 1);
- if (notoSansUniversalIndex > symbolIndex)
- --notoSansUniversalIndex;
- }
-
- // .Noto Sans Universal appears to have a bug when the application
- // does not have a valid Info.plist, which causes it to return glyph #4
- // (a question mark) for any character.
- if (notoSansUniversalIndex >= 0)
- fallbackList.move(notoSansUniversalIndex, fallbackList.size() - 1);
-
- addExtraFallbacks(&fallbackList);
-
- extern QStringList qt_sort_families_by_writing_system(QChar::Script, const QStringList &);
- fallbackList = qt_sort_families_by_writing_system(script, fallbackList);
-
- return fallbackList;
- }
- }
+ QStringList fallbackList;
+
+ QCFType<CFArrayRef> fallbackFonts = fallbacksForFamily(family);
+ if (!fallbackFonts || !CFArrayGetCount(fallbackFonts)) {
+ // We were not able to find a fallback for the specific family,
+ // or the family was empty, so we fall back to the style hint.
+ if (!family.isEmpty())
+ qCDebug(lcQpaFonts) << "No fallbacks found. Using style hint instead";
+
+ if (QCFType<CTFontDescriptorRef> styleDescriptor = descriptorForStyle(styleHint)) {
+ CFMutableArrayRef tmp = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
+ CFArrayAppendValue(tmp, styleDescriptor);
+ QCFType<CFArrayRef> styleFallbacks = fallbacksForDescriptor(styleDescriptor);
+ CFArrayAppendArray(tmp, styleFallbacks, CFRangeMake(0, CFArrayGetCount(styleFallbacks)));
+ fallbackFonts = tmp;
}
}
- // We were not able to find a fallback for the specific family,
- // so we fall back to the stylehint.
-
- static const QString styleLookupKey = QString::fromLatin1(".QFontStyleHint_%1");
-
- static bool didPopulateStyleFallbacks = false;
- if (!didPopulateStyleFallbacks) {
-#if defined(Q_OS_MACX)
- NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
- NSArray<NSString *> *languages = [defaults stringArrayForKey:@"AppleLanguages"];
-
- NSDictionary<NSString *, id> *fallbackDict = [NSDictionary<NSString *, id> dictionaryWithContentsOfFile:@"/System/Library/Frameworks/ApplicationServices.framework/Frameworks/CoreText.framework/Resources/DefaultFontFallbacks.plist"];
-
- for (NSString *style in [fallbackDict allKeys]) {
- NSArray *list = [fallbackDict valueForKey:style];
- QFont::StyleHint fallbackStyleHint = styleHintFromNSString(style);
- QStringList fallbackList;
- for (id item in list) {
- // sort the array based on system language preferences
- if ([item isKindOfClass:[NSArray class]]) {
- NSArray *langs = [reinterpret_cast<NSArray *>(item)
- sortedArrayUsingFunction:languageMapSort context:languages];
- for (NSArray<NSString *> *map in langs)
- fallbackList.append(familyNameFromPostScriptName([map objectAtIndex:1]));
- }
- else if ([item isKindOfClass: [NSString class]])
- fallbackList.append(familyNameFromPostScriptName(item));
- }
+ if (!fallbackFonts)
+ return fallbackList;
+
+ const int numberOfFallbacks = CFArrayGetCount(fallbackFonts);
+ for (int i = 0; i < numberOfFallbacks; ++i) {
+ auto fallbackDescriptor = CTFontDescriptorRef(CFArrayGetValueAtIndex(fallbackFonts, i));
+ auto fallbackFamilyName = QCFString(CTFontDescriptorCopyAttribute(fallbackDescriptor, kCTFontFamilyNameAttribute));
+
+ if (!isFamilyPopulated(fallbackFamilyName)) {
+ // We need to populate, or at least register the fallback fonts,
+ // otherwise the Qt font database may not know they exist.
+ if (isPrivateFontFamily(fallbackFamilyName))
+ const_cast<QCoreTextFontDatabase *>(this)->populateFromDescriptor(fallbackDescriptor);
+ else
+ registerFontFamily(fallbackFamilyName);
+ }
- fallbackList.append(QLatin1String("Apple Color Emoji"));
+ fallbackList.append(fallbackFamilyName);
+ }
- addExtraFallbacks(&fallbackList);
- fallbackLists[styleLookupKey.arg(fallbackStyleHint)] = fallbackList;
- }
-#else
- QStringList staticFallbackList;
- staticFallbackList << QString::fromLatin1("Helvetica,Apple Color Emoji,Geeza Pro,Arial Hebrew,Thonburi,Kailasa"
- "Hiragino Kaku Gothic ProN,.Heiti J,Apple SD Gothic Neo,.Heiti K,Heiti SC,Heiti TC"
- "Bangla Sangam MN,Devanagari Sangam MN,Gujarati Sangam MN,Gurmukhi MN,Kannada Sangam MN"
- "Malayalam Sangam MN,Oriya Sangam MN,Sinhala Sangam MN,Tamil Sangam MN,Telugu Sangam MN"
- "Euphemia UCAS,.PhoneFallback").split(QLatin1String(","));
-
- for (int i = QFont::Helvetica; i <= QFont::Fantasy; ++i)
- fallbackLists[styleLookupKey.arg(i)] = staticFallbackList;
+ // Some fallback fonts will have have an order in the list returned
+ // by Core Text that would indicate they should be preferred for e.g.
+ // Arabic, or Emoji, while in reality only supporting a tiny subset
+ // of the required glyphs, or representing them by question marks.
+ // Move these to the end, so that the proper fonts are preferred.
+ for (const char *family : { ".Apple Symbols Fallback", ".Noto Sans Universal" }) {
+ int index = fallbackList.indexOf(QLatin1String(family));
+ if (index >= 0)
+ fallbackList.move(index, fallbackList.size() - 1);
+ }
+
+#if defined(Q_OS_MACOS)
+ // Since we are only returning a list of default fonts for the current language, we do not
+ // cover all Unicode completely. This was especially an issue for some of the common script
+ // symbols such as mathematical symbols, currency or geometric shapes. To minimize the risk
+ // of missing glyphs, we add Arial Unicode MS as a final fail safe, since this covers most
+ // of Unicode 2.1.
+ if (!fallbackList.contains(QStringLiteral("Arial Unicode MS")))
+ fallbackList.append(QStringLiteral("Arial Unicode MS"));
+ // Since some symbols (specifically Braille) are not in Arial Unicode MS, we
+ // add Apple Symbols to cover those too.
+ if (!fallbackList.contains(QStringLiteral("Apple Symbols")))
+ fallbackList.append(QStringLiteral("Apple Symbols"));
#endif
- didPopulateStyleFallbacks = true;
- }
+ extern QStringList qt_sort_families_by_writing_system(QChar::Script, const QStringList &);
+ fallbackList = qt_sort_families_by_writing_system(script, fallbackList);
- Q_ASSERT(!fallbackLists.isEmpty());
- return fallbackLists[styleLookupKey.arg(styleHint)];
+ qCDebug(lcQpaFonts).nospace() << "Fallback families ordered by script " << script << ": " << fallbackList;
+
+ return fallbackList;
}
QStringList QCoreTextFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName)
@@ -733,10 +747,8 @@ static CTFontDescriptorRef fontDescriptorFromTheme(QPlatformTheme::Font f)
}
#endif // Q_OS_IOS, Q_OS_TVOS, Q_OS_WATCHOS
- // OSX default case and iOS fallback case
- CTFontUIFontType fontType = fontTypeFromTheme(f);
- QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(fontType, 0.0, NULL);
- return CTFontCopyFontDescriptor(ctFont);
+ // macOS default case and iOS fallback case
+ return descriptorForFontType(fontTypeFromTheme(f));
}
const QHash<QPlatformTheme::Font, QFont *> &QCoreTextFontDatabase::themeFonts() const
@@ -769,8 +781,8 @@ QFont *QCoreTextFontDatabase::themeFont(QPlatformTheme::Font f) const
QFont QCoreTextFontDatabase::defaultFont() const
{
if (defaultFontName.isEmpty()) {
- QCFType<CTFontRef> font = CTFontCreateUIFontForLanguage(kCTFontUIFontSystem, 12.0, NULL);
- defaultFontName = (QString) QCFString(CTFontCopyFullName(font));
+ QCFType<CTFontDescriptorRef> systemFont = descriptorForFontType(kCTFontUIFontSystem);
+ defaultFontName = QCFString(CTFontDescriptorCopyAttribute(systemFont, kCTFontFamilyNameAttribute));
}
return QFont(defaultFontName);
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
index 05f6ed641c..eebb3eb964 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
@@ -71,7 +71,7 @@ public:
QCoreTextFontDatabase();
~QCoreTextFontDatabase();
void populateFontDatabase() override;
- bool populateFamilyAliases() override;
+ bool populateFamilyAliases(const QString &missingFamily) override;
void populateFamily(const QString &familyName) override;
void invalidate() override;
@@ -92,6 +92,7 @@ protected:
private:
void populateFromDescriptor(CTFontDescriptorRef font, const QString &familyName = QString());
+ static CFArrayRef fallbacksForFamily(const QString &family);
mutable QString defaultFontName;
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
index c523e799e6..011476cf13 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase.cpp
@@ -53,6 +53,7 @@
#include <QtCore/QtEndian>
#include <QtCore/QThreadStorage>
#include <QtCore/private/qsystemlibrary_p.h>
+#include <QtCore/private/qwinregistry_p.h>
#include <wchar.h>
@@ -1007,12 +1008,27 @@ static QChar *createFontFile(const QString &faceName)
return faceNamePtr;
}
+namespace {
+ struct StoreFontPayload {
+ StoreFontPayload(const QString &family,
+ QWindowsFontDatabase *fontDatabase)
+ : populatedFontFamily(family)
+ , windowsFontDatabase(fontDatabase)
+ {}
+
+ QString populatedFontFamily;
+ QSet<QPair<QString,QString> > foundFontAndStyles;
+ QWindowsFontDatabase *windowsFontDatabase;
+ };
+}
+
static bool addFontToDatabase(QString familyName,
QString styleName,
const LOGFONT &logFont,
const TEXTMETRIC *textmetric,
const FONTSIGNATURE *signature,
- int type)
+ int type,
+ StoreFontPayload *sfp)
{
// the "@family" fonts are just the same as "family". Ignore them.
if (familyName.isEmpty() || familyName.at(0) == QLatin1Char('@') || familyName.startsWith(QLatin1String("WST_")))
@@ -1092,6 +1108,16 @@ static bool addFontToDatabase(QString familyName,
writingSystems.setSupported(ws);
}
+ // We came here from populating a different font family, so we have
+ // to ensure the entire typographic family is populated before we
+ // mark it as such inside registerFont()
+ if (!subFamilyName.isEmpty()
+ && familyName != subFamilyName
+ && sfp->populatedFontFamily != familyName
+ && !QPlatformFontDatabase::isFamilyPopulated(familyName)) {
+ sfp->windowsFontDatabase->populateFamily(familyName);
+ }
+
QPlatformFontDatabase::registerFont(familyName, styleName, foundryName, weight,
style, stretch, antialias, scalable, size, fixed, writingSystems, createFontFile(faceName));
@@ -1128,17 +1154,18 @@ static int QT_WIN_CALLBACK storeFont(const LOGFONT *logFont, const TEXTMETRIC *t
// to the documentation is identical to a TEXTMETRIC except for the last four
// members, which we don't use anyway
const FONTSIGNATURE *signature = nullptr;
+ StoreFontPayload *sfp = reinterpret_cast<StoreFontPayload *>(lparam);
+ Q_ASSERT(sfp != nullptr);
if (type & TRUETYPE_FONTTYPE) {
signature = &reinterpret_cast<const NEWTEXTMETRICEX *>(textmetric)->ntmFontSig;
// We get a callback for each script-type supported, but we register them all
// at once using the signature, so we only need one call to addFontToDatabase().
- QSet<QPair<QString,QString>> *foundFontAndStyles = reinterpret_cast<QSet<QPair<QString,QString>> *>(lparam);
QPair<QString,QString> fontAndStyle(familyName, styleName);
- if (foundFontAndStyles->contains(fontAndStyle))
+ if (sfp->foundFontAndStyles.contains(fontAndStyle))
return 1;
- foundFontAndStyles->insert(fontAndStyle);
+ sfp->foundFontAndStyles.insert(fontAndStyle);
}
- addFontToDatabase(familyName, styleName, *logFont, textmetric, signature, type);
+ addFontToDatabase(familyName, styleName, *logFont, textmetric, signature, type, sfp);
// keep on enumerating
return 1;
@@ -1157,8 +1184,8 @@ void QWindowsFontDatabase::populateFamily(const QString &familyName)
familyName.toWCharArray(lf.lfFaceName);
lf.lfFaceName[familyName.size()] = 0;
lf.lfPitchAndFamily = 0;
- QSet<QPair<QString,QString>> foundFontAndStyles;
- EnumFontFamiliesEx(dummy, &lf, storeFont, reinterpret_cast<intptr_t>(&foundFontAndStyles), 0);
+ StoreFontPayload sfp(familyName, this);
+ EnumFontFamiliesEx(dummy, &lf, storeFont, reinterpret_cast<intptr_t>(&sfp), 0);
ReleaseDC(0, dummy);
}
@@ -1184,33 +1211,8 @@ static int QT_WIN_CALLBACK populateFontFamilies(const LOGFONT *logFont, const TE
void QWindowsFontDatabase::addDefaultEUDCFont()
{
- QString path;
- {
- HKEY key;
- if (RegOpenKeyEx(HKEY_CURRENT_USER,
- L"EUDC\\1252",
- 0,
- KEY_READ,
- &key) != ERROR_SUCCESS) {
- return;
- }
-
- WCHAR value[MAX_PATH];
- DWORD bufferSize = sizeof(value);
- ZeroMemory(value, bufferSize);
-
- if (RegQueryValueEx(key,
- L"SystemDefaultEUDCFont",
- nullptr,
- nullptr,
- reinterpret_cast<LPBYTE>(value),
- &bufferSize) == ERROR_SUCCESS) {
- path = QString::fromWCharArray(value);
- }
-
- RegCloseKey(key);
- }
-
+ const QString path = QWinRegistryKey(HKEY_CURRENT_USER, LR"(EUDC\1252)")
+ .stringValue(L"SystemDefaultEUDCFont");
if (!path.isEmpty()) {
QFile file(path);
if (!file.open(QIODevice::ReadOnly)) {
@@ -1338,11 +1340,11 @@ QT_WARNING_POP
if (request.family != fontEngine->fontDef.family) {
qWarning("%s: Failed to load font. Got fallback instead: %s",
__FUNCTION__, qPrintable(fontEngine->fontDef.family));
- if (fontEngine->ref.load() == 0)
+ if (fontEngine->ref.loadRelaxed() == 0)
delete fontEngine;
fontEngine = 0;
} else {
- Q_ASSERT(fontEngine->ref.load() == 0);
+ Q_ASSERT(fontEngine->ref.loadRelaxed() == 0);
// Override the generated font name
switch (fontEngine->type()) {
@@ -1514,7 +1516,7 @@ static void getFamiliesAndSignatures(const QByteArray &fontData,
if (names.name.isEmpty())
continue;
- families->append(qMove(names));
+ families->append(std::move(names));
if (values || signatures)
getFontTable(data, font, MAKE_TAG('O', 'S', '/', '2'), &table, &length);
@@ -1598,8 +1600,9 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData,
TEXTMETRIC textMetrics;
GetTextMetrics(hdc, &textMetrics);
+ StoreFontPayload sfp(familyName, this);
addFontToDatabase(familyName, styleName, lf, &textMetrics, &signatures.at(j),
- TRUETYPE_FONTTYPE);
+ TRUETYPE_FONTTYPE, &sfp);
SelectObject(hdc, oldobj);
DeleteObject(hfont);
@@ -2078,28 +2081,6 @@ int QWindowsFontDatabase::defaultVerticalDPI()
return vDPI;
}
-QString QWindowsFontDatabase::readRegistryString(HKEY parentHandle, const wchar_t *keyPath, const wchar_t *keyName)
-{
- QString result;
- HKEY handle = 0;
- if (RegOpenKeyEx(parentHandle, keyPath, 0, KEY_READ, &handle) == ERROR_SUCCESS) {
- // get the size and type of the value
- DWORD dataType;
- DWORD dataSize;
- if (RegQueryValueEx(handle, keyName, 0, &dataType, 0, &dataSize) == ERROR_SUCCESS) {
- if (dataType == REG_SZ || dataType == REG_EXPAND_SZ) {
- dataSize += 2; // '\0' missing?
- QVarLengthArray<unsigned char> data(dataSize);
- data[dataSize - 2] = data[dataSize - 1] = '\0';
- if (RegQueryValueEx(handle, keyName, 0, 0, data.data(), &dataSize) == ERROR_SUCCESS)
- result = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(data.data()));
- }
- }
- RegCloseKey(handle);
- }
- return result;
-}
-
bool QWindowsFontDatabase::isPrivateFontFamily(const QString &family) const
{
return m_eudcFonts.contains(family) || QPlatformFontDatabase::isPrivateFontFamily(family);
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
index fdef0f5ff1..a6b7fcf31e 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_ft.cpp
@@ -48,7 +48,11 @@
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
#include <QtCore/QSettings>
+#if QT_CONFIG(regularexpression)
#include <QtCore/QRegularExpression>
+#else
+#include <QtCore/QRegExp>
+#endif
#include <QtGui/QGuiApplication>
#include <QtGui/QFontDatabase>
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
index b85a2dceee..f132e69d4d 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontdatabase_p.h
@@ -96,6 +96,8 @@ public:
QWindowsFontDatabase();
~QWindowsFontDatabase() override;
+ void ensureFamilyPopulated(const QString &familyName);
+
void populateFontDatabase() override;
void populateFamily(const QString &familyName) override;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) override;
@@ -131,8 +133,6 @@ public:
static void setFontOptions(unsigned options);
static unsigned fontOptions();
- static QString readRegistryString(HKEY parentHandle, const wchar_t *keyPath, const wchar_t *keyName);
-
private:
void removeApplicationFonts();
void addDefaultEUDCFont();
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
index a4490a6664..e796c18e79 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontenginedirectwrite.cpp
@@ -47,6 +47,7 @@
#include <QtCore/QFile>
#include <private/qstringiterator_p.h>
#include <QtCore/private/qsystemlibrary_p.h>
+#include <QtCore/private/qwinregistry_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h>
#include <QtGui/private/qhighdpiscaling_p.h>
@@ -945,10 +946,10 @@ void QWindowsFontEngineDirectWrite::initFontInfo(const QFontDef &request,
QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyName)
{
- const wchar_t key[] = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes";
const QString substitute =
- QWindowsFontDatabase::readRegistryString(HKEY_LOCAL_MACHINE, key,
- reinterpret_cast<const wchar_t *>(familyName.utf16()));
+ QWinRegistryKey(HKEY_LOCAL_MACHINE,
+ LR"(Software\Microsoft\Windows NT\CurrentVersion\FontSubstitutes)")
+ .stringValue(familyName);
return substitute.isEmpty() ? familyName : substitute;
}
diff --git a/src/platformsupport/fontdatabases/windows/windows.pri b/src/platformsupport/fontdatabases/windows/windows.pri
index 9c529f55ea..7ddfb2c281 100644
--- a/src/platformsupport/fontdatabases/windows/windows.pri
+++ b/src/platformsupport/fontdatabases/windows/windows.pri
@@ -30,5 +30,5 @@ qtConfig(directwrite):qtConfig(direct2d) {
DEFINES *= QT_NO_DIRECTWRITE
}
-LIBS += -lole32 -lgdi32 -luser32 -ladvapi32
-mingw: LIBS += -luuid
+QMAKE_USE_PRIVATE += advapi32 ole32 user32 gdi32
+mingw: QMAKE_USE_PRIVATE += uuid
diff --git a/src/platformsupport/fontdatabases/winrt/winrt.pri b/src/platformsupport/fontdatabases/winrt/winrt.pri
index 7617df2e7a..1cd417c1fd 100644
--- a/src/platformsupport/fontdatabases/winrt/winrt.pri
+++ b/src/platformsupport/fontdatabases/winrt/winrt.pri
@@ -8,6 +8,4 @@ HEADERS += \
DEFINES += __WRL_NO_DEFAULT_LIB__
-LIBS += -lws2_32
-
-QMAKE_USE_PRIVATE += dwrite_1
+QMAKE_USE_PRIVATE += dwrite_1 ws2_32
diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp
index 5f16d00dad..81bccb1c25 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience.cpp
+++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp
@@ -317,7 +317,7 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display,
glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize);
glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize);
glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize);
- glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleBuffers);
+ glXGetFBConfigAttrib(display, config, GLX_SAMPLE_BUFFERS_ARB, &sampleBuffers);
glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo);
if (flags & QGLX_SUPPORTS_SRGB)
glXGetFBConfigAttrib(display, config, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgbCapable);
@@ -356,7 +356,7 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display,
glXGetConfig(display, visualInfo, GLX_ALPHA_SIZE, &alphaSize);
glXGetConfig(display, visualInfo, GLX_DEPTH_SIZE, &depthSize);
glXGetConfig(display, visualInfo, GLX_STENCIL_SIZE, &stencilSize);
- glXGetConfig(display, visualInfo, GLX_SAMPLES_ARB, &sampleBuffers);
+ glXGetConfig(display, visualInfo, GLX_SAMPLE_BUFFERS_ARB, &sampleBuffers);
glXGetConfig(display, visualInfo, GLX_STEREO, &stereo);
if (flags & QGLX_SUPPORTS_SRGB)
glXGetConfig(display, visualInfo, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgbCapable);
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
index 666613f09d..3555763b89 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp
@@ -66,7 +66,7 @@ Q_LOGGING_CATEGORY(qLcEvdevKeyMap, "qt.qpa.input.keymap")
// simple builtin US keymap
#include "qevdevkeyboard_defaultmap_p.h"
-void QFdContainer::reset() Q_DECL_NOTHROW
+void QFdContainer::reset() noexcept
{
if (m_fd >= 0)
qt_safe_close(m_fd);
@@ -98,11 +98,12 @@ QEvdevKeyboardHandler::~QEvdevKeyboardHandler()
unloadKeymap();
}
-QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device,
+std::unique_ptr<QEvdevKeyboardHandler> QEvdevKeyboardHandler::create(const QString &device,
const QString &specification,
const QString &defaultKeymapFile)
{
- qCDebug(qLcEvdevKey) << "Try to create keyboard handler for" << device << specification;
+ qCDebug(qLcEvdevKey, "Try to create keyboard handler for \"%ls\" \"%ls\"",
+ qUtf16Printable(device), qUtf16Printable(specification));
QString keymapFile = defaultKeymapFile;
int repeatDelay = 400;
@@ -127,7 +128,7 @@ QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device,
grab = arg.mid(5).toInt();
}
- qCDebug(qLcEvdevKey) << "Opening keyboard at" << device;
+ qCDebug(qLcEvdevKey, "Opening keyboard at %ls", qUtf16Printable(device));
QFdContainer fd(qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0));
if (fd.get() >= 0) {
@@ -137,16 +138,16 @@ QEvdevKeyboardHandler *QEvdevKeyboardHandler::create(const QString &device,
::ioctl(fd.get(), EVIOCSREP, kbdrep);
}
- return new QEvdevKeyboardHandler(device, fd, disableZap, enableCompose, keymapFile);
+ return std::unique_ptr<QEvdevKeyboardHandler>(new QEvdevKeyboardHandler(device, fd, disableZap, enableCompose, keymapFile));
} else {
- qWarning("Cannot open keyboard input device '%s': %s", qPrintable(device), strerror(errno));
- return 0;
+ qErrnoWarning("Cannot open keyboard input device '%ls'", qUtf16Printable(device));
+ return nullptr;
}
}
void QEvdevKeyboardHandler::switchLed(int led, bool state)
{
- qCDebug(qLcEvdevKey) << "switchLed" << led << state;
+ qCDebug(qLcEvdevKey, "switchLed %d %d", led, int(state));
struct ::input_event led_ie;
::gettimeofday(&led_ie.time, 0);
@@ -170,7 +171,7 @@ void QEvdevKeyboardHandler::readKeycode()
return;
} else if (result < 0) {
if (errno != EINTR && errno != EAGAIN) {
- qErrnoWarning(errno, "evdevkeyboard: Could not read from input device");
+ qErrnoWarning("evdevkeyboard: Could not read from input device");
// If the device got disconnected, stop reading, otherwise we get flooded
// by the above error over and over again.
if (errno == ENODEV) {
@@ -230,7 +231,7 @@ void QEvdevKeyboardHandler::processKeyEvent(int nativecode, int unicode, int qtc
QWindowSystemInterface::handleExtendedKeyEvent(0, (isPress ? QEvent::KeyPress : QEvent::KeyRelease),
qtcode, modifiers, nativecode + 8, 0, int(modifiers),
- (unicode != 0xffff ) ? QString(unicode) : QString(), autoRepeat);
+ (unicode != 0xffff ) ? QString(QChar(unicode)) : QString(), autoRepeat);
}
QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint16 keycode, bool pressed, bool autorepeat)
@@ -473,7 +474,7 @@ QEvdevKeyboardHandler::KeycodeAction QEvdevKeyboardHandler::processKeycode(quint
void QEvdevKeyboardHandler::unloadKeymap()
{
- qCDebug(qLcEvdevKey) << "Unload current keymap and restore built-in";
+ qCDebug(qLcEvdevKey, "Unload current keymap and restore built-in");
if (m_keymap && m_keymap != s_keymap_default)
delete [] m_keymap;
@@ -517,12 +518,12 @@ void QEvdevKeyboardHandler::unloadKeymap()
bool QEvdevKeyboardHandler::loadKeymap(const QString &file)
{
- qCDebug(qLcEvdevKey) << "Loading keymap" << file;
+ qCDebug(qLcEvdevKey, "Loading keymap %ls", qUtf16Printable(file));
QFile f(file);
if (!f.open(QIODevice::ReadOnly)) {
- qWarning("Could not open keymap file '%s'", qPrintable(file));
+ qWarning("Could not open keymap file '%ls'", qUtf16Printable(file));
return false;
}
@@ -541,7 +542,7 @@ bool QEvdevKeyboardHandler::loadKeymap(const QString &file)
ds >> qmap_magic >> qmap_version >> qmap_keymap_size >> qmap_keycompose_size;
if (ds.status() != QDataStream::Ok || qmap_magic != QEvdevKeyboardMap::FileMagic || qmap_version != 1 || qmap_keymap_size == 0) {
- qWarning("'%s' is not a valid .qmap keymap file", qPrintable(file));
+ qWarning("'%ls' is not a valid .qmap keymap file", qUtf16Printable(file));
return false;
}
@@ -557,7 +558,7 @@ bool QEvdevKeyboardHandler::loadKeymap(const QString &file)
delete [] qmap_keymap;
delete [] qmap_keycompose;
- qWarning("Keymap file '%s' cannot be loaded.", qPrintable(file));
+ qWarning("Keymap file '%ls' cannot be loaded.", qUtf16Printable(file));
return false;
}
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
index 21e6d055a0..f92a2bf704 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler_p.h
@@ -55,6 +55,8 @@
#include <QTimer>
#include <QDataStream>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QSocketNotifier;
@@ -134,13 +136,13 @@ class QFdContainer
int m_fd;
Q_DISABLE_COPY_MOVE(QFdContainer);
public:
- explicit QFdContainer(int fd = -1) Q_DECL_NOTHROW : m_fd(fd) {}
+ explicit QFdContainer(int fd = -1) noexcept : m_fd(fd) {}
~QFdContainer() { reset(); }
- int get() const Q_DECL_NOTHROW { return m_fd; }
+ int get() const noexcept { return m_fd; }
- int release() Q_DECL_NOTHROW { int result = m_fd; m_fd = -1; return result; }
- void reset() Q_DECL_NOTHROW;
+ int release() noexcept { int result = m_fd; m_fd = -1; return result; }
+ void reset() noexcept;
};
class QEvdevKeyboardHandler : public QObject
@@ -168,7 +170,7 @@ public:
SwitchConsoleMask = 0x0000007f
};
- static QEvdevKeyboardHandler *create(const QString &device,
+ static std::unique_ptr<QEvdevKeyboardHandler> create(const QString &device,
const QString &specification,
const QString &defaultKeymapFile = QString());
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp
index e1659bc0d9..52d9c34b1c 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager.cpp
@@ -39,6 +39,8 @@
#include "qevdevkeyboardmanager_p.h"
+#include <QtInputSupport/private/qevdevutil_p.h>
+
#include <QStringList>
#include <QCoreApplication>
#include <QLoggingCategory>
@@ -61,36 +63,24 @@ QEvdevKeyboardManager::QEvdevKeyboardManager(const QString &key, const QString &
if (spec.isEmpty())
spec = specification;
- QStringList args = spec.split(QLatin1Char(':'));
- QStringList devices;
-
- foreach (const QString &arg, args) {
- if (arg.startsWith(QLatin1String("/dev/"))) {
- // if device is specified try to use it
- devices.append(arg);
- args.removeAll(arg);
- }
- }
-
- // build new specification without /dev/ elements
- m_spec = args.join(QLatin1Char(':'));
+ auto parsed = QEvdevUtil::parseSpecification(spec);
+ m_spec = std::move(parsed.spec);
// add all keyboards for devices specified in the argument list
- foreach (const QString &device, devices)
+ for (const QString &device : qAsConst(parsed.devices))
addKeyboard(device);
- if (devices.isEmpty()) {
- qCDebug(qLcEvdevKey) << "evdevkeyboard: Using device discovery";
- m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Keyboard, this);
- if (m_deviceDiscovery) {
+ if (parsed.devices.isEmpty()) {
+ qCDebug(qLcEvdevKey, "evdevkeyboard: Using device discovery");
+ if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Keyboard, this)) {
// scan and add already connected keyboards
- const QStringList devices = m_deviceDiscovery->scanConnectedDevices();
+ const QStringList devices = deviceDiscovery->scanConnectedDevices();
for (const QString &device : devices)
addKeyboard(device);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceDetected,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected,
this, &QEvdevKeyboardManager::addKeyboard);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
this, &QEvdevKeyboardManager::removeKeyboard);
}
}
@@ -98,36 +88,34 @@ QEvdevKeyboardManager::QEvdevKeyboardManager(const QString &key, const QString &
QEvdevKeyboardManager::~QEvdevKeyboardManager()
{
- qDeleteAll(m_keyboards);
- m_keyboards.clear();
}
void QEvdevKeyboardManager::addKeyboard(const QString &deviceNode)
{
- qCDebug(qLcEvdevKey) << "Adding keyboard at" << deviceNode;
- QEvdevKeyboardHandler *keyboard;
- keyboard = QEvdevKeyboardHandler::create(deviceNode, m_spec, m_defaultKeymapFile);
+ qCDebug(qLcEvdevKey, "Adding keyboard at %ls", qUtf16Printable(deviceNode));
+ auto keyboard = QEvdevKeyboardHandler::create(deviceNode, m_spec, m_defaultKeymapFile);
if (keyboard) {
- m_keyboards.insert(deviceNode, keyboard);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypeKeyboard, m_keyboards.count());
+ m_keyboards.add(deviceNode, std::move(keyboard));
+ updateDeviceCount();
} else {
- qWarning("Failed to open keyboard device %s", qPrintable(deviceNode));
+ qWarning("Failed to open keyboard device %ls", qUtf16Printable(deviceNode));
}
}
void QEvdevKeyboardManager::removeKeyboard(const QString &deviceNode)
{
- if (m_keyboards.contains(deviceNode)) {
- qCDebug(qLcEvdevKey) << "Removing keyboard at" << deviceNode;
- QEvdevKeyboardHandler *keyboard = m_keyboards.value(deviceNode);
- m_keyboards.remove(deviceNode);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypeKeyboard, m_keyboards.count());
- delete keyboard;
+ if (m_keyboards.remove(deviceNode)) {
+ qCDebug(qLcEvdevKey, "Removing keyboard at %ls", qUtf16Printable(deviceNode));
+ updateDeviceCount();
}
}
+void QEvdevKeyboardManager::updateDeviceCount()
+{
+ QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
+ QInputDeviceManager::DeviceTypeKeyboard, m_keyboards.count());
+}
+
void QEvdevKeyboardManager::loadKeymap(const QString &file)
{
m_defaultKeymapFile = file;
@@ -141,22 +129,22 @@ void QEvdevKeyboardManager::loadKeymap(const QString &file)
if (arg.startsWith(QLatin1String("keymap=")))
keymapFromSpec = arg.mid(7).toString();
}
- foreach (QEvdevKeyboardHandler *handler, m_keyboards) {
+ for (const auto &keyboard : m_keyboards) {
if (keymapFromSpec.isEmpty())
- handler->unloadKeymap();
+ keyboard.handler->unloadKeymap();
else
- handler->loadKeymap(keymapFromSpec);
+ keyboard.handler->loadKeymap(keymapFromSpec);
}
} else {
- foreach (QEvdevKeyboardHandler *handler, m_keyboards)
- handler->loadKeymap(file);
+ for (const auto &keyboard : m_keyboards)
+ keyboard.handler->loadKeymap(file);
}
}
void QEvdevKeyboardManager::switchLang()
{
- foreach (QEvdevKeyboardHandler *handler, m_keyboards)
- handler->switchLang();
+ for (const auto &keyboard : m_keyboards)
+ keyboard.handler->switchLang();
}
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h
index 326e438a7c..d91da330c3 100644
--- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h
+++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardmanager_p.h
@@ -53,6 +53,7 @@
#include "qevdevkeyboardhandler_p.h"
+#include <QtInputSupport/private/devicehandlerlist_p.h>
#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
#include <QObject>
@@ -64,7 +65,7 @@ QT_BEGIN_NAMESPACE
class QEvdevKeyboardManager : public QObject
{
public:
- QEvdevKeyboardManager(const QString &key, const QString &specification, QObject *parent = 0);
+ QEvdevKeyboardManager(const QString &key, const QString &specification, QObject *parent = nullptr);
~QEvdevKeyboardManager();
void loadKeymap(const QString &file);
@@ -74,9 +75,10 @@ public:
void removeKeyboard(const QString &deviceNode);
private:
+ void updateDeviceCount();
+
QString m_spec;
- QHash<QString,QEvdevKeyboardHandler*> m_keyboards;
- QDeviceDiscovery *m_deviceDiscovery;
+ QtInputSupport::DeviceHandlerList<QEvdevKeyboardHandler> m_keyboards;
QString m_defaultKeymapFile;
};
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
index 86a4cd0076..6a53ad2088 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
@@ -66,7 +66,7 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(qLcEvdevMouse, "qt.qpa.input")
-QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QString &specification)
+std::unique_ptr<QEvdevMouseHandler> QEvdevMouseHandler::create(const QString &device, const QString &specification)
{
qCDebug(qLcEvdevMouse) << "create mouse handler for" << device << specification;
@@ -91,10 +91,10 @@ QEvdevMouseHandler *QEvdevMouseHandler::create(const QString &device, const QStr
fd = qt_safe_open(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
if (fd >= 0) {
::ioctl(fd, EVIOCGRAB, grab);
- return new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit);
+ return std::unique_ptr<QEvdevMouseHandler>(new QEvdevMouseHandler(device, fd, abs, compression, jitterLimit));
} else {
qErrnoWarning(errno, "Cannot open mouse input device %s", qPrintable(device));
- return 0;
+ return nullptr;
}
}
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
index c7f2b04eb2..727f1a02f9 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
@@ -56,6 +56,8 @@
#include <QPoint>
#include <QEvent>
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QSocketNotifier;
@@ -64,7 +66,7 @@ class QEvdevMouseHandler : public QObject
{
Q_OBJECT
public:
- static QEvdevMouseHandler *create(const QString &device, const QString &specification);
+ static std::unique_ptr<QEvdevMouseHandler> create(const QString &device, const QString &specification);
~QEvdevMouseHandler();
void readMouseData();
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
index 06025c016e..daa52d690e 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
@@ -39,6 +39,8 @@
#include "qevdevmousemanager_p.h"
+#include <QtInputSupport/private/qevdevutil_p.h>
+
#include <QStringList>
#include <QGuiApplication>
#include <QScreen>
@@ -63,40 +65,32 @@ QEvdevMouseManager::QEvdevMouseManager(const QString &key, const QString &specif
if (spec.isEmpty())
spec = specification;
- QStringList args = spec.split(QLatin1Char(':'));
- QStringList devices;
+ auto parsed = QEvdevUtil::parseSpecification(spec);
+ m_spec = std::move(parsed.spec);
- foreach (const QString &arg, args) {
- if (arg.startsWith(QLatin1String("/dev/"))) {
- // if device is specified try to use it
- devices.append(arg);
- args.removeAll(arg);
- } else if (arg.startsWith(QLatin1String("xoffset="))) {
+ for (const QStringRef &arg : qAsConst(parsed.args)) {
+ if (arg.startsWith(QLatin1String("xoffset="))) {
m_xoffset = arg.mid(8).toInt();
} else if (arg.startsWith(QLatin1String("yoffset="))) {
m_yoffset = arg.mid(8).toInt();
}
}
- // build new specification without /dev/ elements
- m_spec = args.join(QLatin1Char(':'));
-
// add all mice for devices specified in the argument list
- foreach (const QString &device, devices)
+ for (const QString &device : qAsConst(parsed.devices))
addMouse(device);
- if (devices.isEmpty()) {
- qCDebug(qLcEvdevMouse) << "evdevmouse: Using device discovery";
- m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Mouse | QDeviceDiscovery::Device_Touchpad, this);
- if (m_deviceDiscovery) {
+ if (parsed.devices.isEmpty()) {
+ qCDebug(qLcEvdevMouse, "evdevmouse: Using device discovery");
+ if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Mouse | QDeviceDiscovery::Device_Touchpad, this)) {
// scan and add already connected keyboards
- const QStringList devices = m_deviceDiscovery->scanConnectedDevices();
+ const QStringList devices = deviceDiscovery->scanConnectedDevices();
for (const QString &device : devices)
addMouse(device);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceDetected,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected,
this, &QEvdevMouseManager::addMouse);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
this, &QEvdevMouseManager::removeMouse);
}
}
@@ -111,8 +105,6 @@ QEvdevMouseManager::QEvdevMouseManager(const QString &key, const QString &specif
QEvdevMouseManager::~QEvdevMouseManager()
{
- qDeleteAll(m_mice);
- m_mice.clear();
}
void QEvdevMouseManager::clampPosition()
@@ -159,31 +151,32 @@ void QEvdevMouseManager::handleWheelEvent(QPoint delta)
void QEvdevMouseManager::addMouse(const QString &deviceNode)
{
- qCDebug(qLcEvdevMouse) << "Adding mouse at" << deviceNode;
- QEvdevMouseHandler *handler = QEvdevMouseHandler::create(deviceNode, m_spec);
+ qCDebug(qLcEvdevMouse, "Adding mouse at %ls", qUtf16Printable(deviceNode));
+ auto handler = QEvdevMouseHandler::create(deviceNode, m_spec);
if (handler) {
- connect(handler, &QEvdevMouseHandler::handleMouseEvent,
+ connect(handler.get(), &QEvdevMouseHandler::handleMouseEvent,
this, &QEvdevMouseManager::handleMouseEvent);
- connect(handler, &QEvdevMouseHandler::handleWheelEvent,
+ connect(handler.get(), &QEvdevMouseHandler::handleWheelEvent,
this, &QEvdevMouseManager::handleWheelEvent);
- m_mice.insert(deviceNode, handler);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypePointer, m_mice.count());
+ m_mice.add(deviceNode, std::move(handler));
+ updateDeviceCount();
} else {
- qWarning("evdevmouse: Failed to open mouse device %s", qPrintable(deviceNode));
+ qWarning("evdevmouse: Failed to open mouse device %ls", qUtf16Printable(deviceNode));
}
}
void QEvdevMouseManager::removeMouse(const QString &deviceNode)
{
- if (m_mice.contains(deviceNode)) {
- qCDebug(qLcEvdevMouse) << "Removing mouse at" << deviceNode;
- QEvdevMouseHandler *handler = m_mice.value(deviceNode);
- m_mice.remove(deviceNode);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypePointer, m_mice.count());
- delete handler;
+ if (m_mice.remove(deviceNode)) {
+ qCDebug(qLcEvdevMouse, "Removing mouse at %ls", qUtf16Printable(deviceNode));
+ updateDeviceCount();
}
}
+void QEvdevMouseManager::updateDeviceCount()
+{
+ QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
+ QInputDeviceManager::DeviceTypePointer, m_mice.count());
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
index 13a8e3dec5..f5c32ed8b5 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
@@ -53,6 +53,8 @@
#include "qevdevmousehandler_p.h"
+#include <QtInputSupport/private/devicehandlerlist_p.h>
+
#include <QObject>
#include <QHash>
#include <QSocketNotifier>
@@ -65,7 +67,7 @@ class QDeviceDiscovery;
class QEvdevMouseManager : public QObject
{
public:
- QEvdevMouseManager(const QString &key, const QString &specification, QObject *parent = 0);
+ QEvdevMouseManager(const QString &key, const QString &specification, QObject *parent = nullptr);
~QEvdevMouseManager();
void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons,
@@ -77,10 +79,10 @@ public:
private:
void clampPosition();
+ void updateDeviceCount();
QString m_spec;
- QHash<QString,QEvdevMouseHandler*> m_mice;
- QDeviceDiscovery *m_deviceDiscovery;
+ QtInputSupport::DeviceHandlerList<QEvdevMouseHandler> m_mice;
int m_x;
int m_y;
int m_xoffset;
diff --git a/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
index b6051aaf3c..c86840b76c 100644
--- a/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
+++ b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp
@@ -172,11 +172,11 @@ QEvdevTabletHandler::QEvdevTabletHandler(const QString &device, const QString &s
setObjectName(QLatin1String("Evdev Tablet Handler"));
- qCDebug(qLcEvdevTablet, "evdevtablet: using %s", qPrintable(device));
+ qCDebug(qLcEvdevTablet, "evdevtablet: using %ls", qUtf16Printable(device));
m_fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
if (m_fd < 0) {
- qErrnoWarning(errno, "evdevtablet: Cannot open input device %s", qPrintable(device));
+ qErrnoWarning("evdevtablet: Cannot open input device %ls", qUtf16Printable(device));
return;
}
@@ -184,11 +184,11 @@ QEvdevTabletHandler::QEvdevTabletHandler(const QString &device, const QString &s
if (grabSuccess)
ioctl(m_fd, EVIOCGRAB, (void *) 0);
else
- qWarning("evdevtablet: %s: The device is grabbed by another process. No events will be read.", qPrintable(device));
+ qWarning("evdevtablet: %ls: The device is grabbed by another process. No events will be read.", qUtf16Printable(device));
d = new QEvdevTabletData(this);
if (!queryLimits())
- qWarning("evdevtablet: %s: Unset or invalid ABS limits. Behavior will be unspecified.", qPrintable(device));
+ qWarning("evdevtablet: %ls: Unset or invalid ABS limits. Behavior will be unspecified.", qUtf16Printable(device));
m_notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated, this, &QEvdevTabletHandler::readData);
@@ -216,32 +216,32 @@ bool QEvdevTabletHandler::queryLimits()
if (ok) {
d->minValues.x = absInfo.minimum;
d->maxValues.x = absInfo.maximum;
- qCDebug(qLcEvdevTablet, "evdevtablet: %s: min X: %d max X: %d", qPrintable(m_device),
+ qCDebug(qLcEvdevTablet, "evdevtablet: %ls: min X: %d max X: %d", qUtf16Printable(m_device),
d->minValues.x, d->maxValues.x);
}
ok &= ioctl(m_fd, EVIOCGABS(ABS_Y), &absInfo) >= 0;
if (ok) {
d->minValues.y = absInfo.minimum;
d->maxValues.y = absInfo.maximum;
- qCDebug(qLcEvdevTablet, "evdevtablet: %s: min Y: %d max Y: %d", qPrintable(m_device),
+ qCDebug(qLcEvdevTablet, "evdevtablet: %ls: min Y: %d max Y: %d", qUtf16Printable(m_device),
d->minValues.y, d->maxValues.y);
}
if (ioctl(m_fd, EVIOCGABS(ABS_PRESSURE), &absInfo) >= 0) {
d->minValues.p = absInfo.minimum;
d->maxValues.p = absInfo.maximum;
- qCDebug(qLcEvdevTablet, "evdevtablet: %s: min pressure: %d max pressure: %d", qPrintable(m_device),
+ qCDebug(qLcEvdevTablet, "evdevtablet: %ls: min pressure: %d max pressure: %d", qUtf16Printable(m_device),
d->minValues.p, d->maxValues.p);
}
if (ioctl(m_fd, EVIOCGABS(ABS_DISTANCE), &absInfo) >= 0) {
d->minValues.d = absInfo.minimum;
d->maxValues.d = absInfo.maximum;
- qCDebug(qLcEvdevTablet, "evdevtablet: %s: min distance: %d max distance: %d", qPrintable(m_device),
+ qCDebug(qLcEvdevTablet, "evdevtablet: %ls: min distance: %d max distance: %d", qUtf16Printable(m_device),
d->minValues.d, d->maxValues.d);
}
char name[128];
if (ioctl(m_fd, EVIOCGNAME(sizeof(name) - 1), name) >= 0) {
d->devName = QString::fromLocal8Bit(name);
- qCDebug(qLcEvdevTablet, "evdevtablet: %s: device name: %s", qPrintable(m_device), name);
+ qCDebug(qLcEvdevTablet, "evdevtablet: %ls: device name: %s", qUtf16Printable(m_device), name);
}
return ok;
}
@@ -253,11 +253,11 @@ void QEvdevTabletHandler::readData()
for (; ;) {
int result = QT_READ(m_fd, reinterpret_cast<char*>(buffer) + n, sizeof(buffer) - n);
if (!result) {
- qWarning("evdevtablet: %s: Got EOF from input device", qPrintable(m_device));
+ qWarning("evdevtablet: %ls: Got EOF from input device", qUtf16Printable(m_device));
return;
} else if (result < 0) {
if (errno != EINTR && errno != EAGAIN) {
- qErrnoWarning(errno, "evdevtablet: %s: Could not read from input device", qPrintable(m_device));
+ qErrnoWarning("evdevtablet: %ls: Could not read from input device", qUtf16Printable(m_device));
if (errno == ENODEV) { // device got disconnected -> stop reading
delete m_notifier;
m_notifier = 0;
diff --git a/src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h b/src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h
index 66e821117a..b83bb21258 100644
--- a/src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h
+++ b/src/platformsupport/input/evdevtablet/qevdevtablethandler_p.h
@@ -64,7 +64,7 @@ class QEvdevTabletData;
class QEvdevTabletHandler : public QObject
{
public:
- explicit QEvdevTabletHandler(const QString &device, const QString &spec = QString(), QObject *parent = 0);
+ explicit QEvdevTabletHandler(const QString &device, const QString &spec = QString(), QObject *parent = nullptr);
~QEvdevTabletHandler();
qint64 deviceId() const;
@@ -83,7 +83,7 @@ private:
class QEvdevTabletHandlerThread : public QDaemonThread
{
public:
- explicit QEvdevTabletHandlerThread(const QString &device, const QString &spec, QObject *parent = 0);
+ explicit QEvdevTabletHandlerThread(const QString &device, const QString &spec, QObject *parent = nullptr);
~QEvdevTabletHandlerThread();
void run() override;
QEvdevTabletHandler *handler() { return m_handler; }
diff --git a/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp b/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp
index 90949408ac..d9888c5b97 100644
--- a/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp
+++ b/src/platformsupport/input/evdevtablet/qevdevtabletmanager.cpp
@@ -40,12 +40,15 @@
#include "qevdevtabletmanager_p.h"
#include "qevdevtablethandler_p.h"
+#include <QtInputSupport/private/qevdevutil_p.h>
+
#include <QStringList>
#include <QGuiApplication>
#include <QLoggingCategory>
#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
#include <private/qguiapplication_p.h>
#include <private/qinputdevicemanager_p_p.h>
+#include <private/qmemory_p.h>
QT_BEGIN_NAMESPACE
@@ -64,34 +67,23 @@ QEvdevTabletManager::QEvdevTabletManager(const QString &key, const QString &spec
if (spec.isEmpty())
spec = specification;
- QStringList args = spec.split(QLatin1Char(':'));
- QStringList devices;
-
- foreach (const QString &arg, args) {
- if (arg.startsWith(QLatin1String("/dev/"))) {
- devices.append(arg);
- args.removeAll(arg);
- }
- }
-
- // build new specification without /dev/ elements
- m_spec = args.join(QLatin1Char(':'));
+ auto parsed = QEvdevUtil::parseSpecification(spec);
+ m_spec = std::move(parsed.spec);
- foreach (const QString &device, devices)
+ for (const QString &device : qAsConst(parsed.devices))
addDevice(device);
// when no devices specified, use device discovery to scan and monitor
- if (devices.isEmpty()) {
- qCDebug(qLcEvdevTablet) << "evdevtablet: Using device discovery";
- m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Tablet, this);
- if (m_deviceDiscovery) {
- const QStringList devices = m_deviceDiscovery->scanConnectedDevices();
+ if (parsed.devices.isEmpty()) {
+ qCDebug(qLcEvdevTablet, "evdevtablet: Using device discovery");
+ if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Tablet, this)) {
+ const QStringList devices = deviceDiscovery->scanConnectedDevices();
for (const QString &device : devices)
addDevice(device);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceDetected,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected,
this, &QEvdevTabletManager::addDevice);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
this, &QEvdevTabletManager::removeDevice);
}
}
@@ -99,33 +91,32 @@ QEvdevTabletManager::QEvdevTabletManager(const QString &key, const QString &spec
QEvdevTabletManager::~QEvdevTabletManager()
{
- qDeleteAll(m_activeDevices);
}
void QEvdevTabletManager::addDevice(const QString &deviceNode)
{
- qCDebug(qLcEvdevTablet) << "Adding device at" << deviceNode;
- QEvdevTabletHandlerThread *handler;
- handler = new QEvdevTabletHandlerThread(deviceNode, m_spec);
+ qCDebug(qLcEvdevTablet, "Adding device at %ls", qUtf16Printable(deviceNode));
+ auto handler = qt_make_unique<QEvdevTabletHandlerThread>(deviceNode, m_spec);
if (handler) {
- m_activeDevices.insert(deviceNode, handler);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypeTablet, m_activeDevices.count());
+ m_activeDevices.add(deviceNode, std::move(handler));
+ updateDeviceCount();
} else {
- qWarning("evdevtablet: Failed to open tablet device %s", qPrintable(deviceNode));
+ qWarning("evdevtablet: Failed to open tablet device %ls", qUtf16Printable(deviceNode));
}
}
void QEvdevTabletManager::removeDevice(const QString &deviceNode)
{
- if (m_activeDevices.contains(deviceNode)) {
- qCDebug(qLcEvdevTablet) << "Removing device at" << deviceNode;
- QEvdevTabletHandlerThread *handler = m_activeDevices.value(deviceNode);
- m_activeDevices.remove(deviceNode);
- QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
- QInputDeviceManager::DeviceTypeTablet, m_activeDevices.count());
- delete handler;
+ if (m_activeDevices.remove(deviceNode)) {
+ qCDebug(qLcEvdevTablet, "Removing device at %ls", qUtf16Printable(deviceNode));
+ updateDeviceCount();
}
}
+void QEvdevTabletManager::updateDeviceCount()
+{
+ QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
+ QInputDeviceManager::DeviceTypeTablet, m_activeDevices.count());
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h b/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h
index cde91c55aa..bb18ffba04 100644
--- a/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h
+++ b/src/platformsupport/input/evdevtablet/qevdevtabletmanager_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+#include <QtInputSupport/private/devicehandlerlist_p.h>
+
#include <QObject>
#include <QHash>
#include <QSocketNotifier>
@@ -63,16 +65,17 @@ class QEvdevTabletHandlerThread;
class QEvdevTabletManager : public QObject
{
public:
- QEvdevTabletManager(const QString &key, const QString &spec, QObject *parent = 0);
+ QEvdevTabletManager(const QString &key, const QString &spec, QObject *parent = nullptr);
~QEvdevTabletManager();
void addDevice(const QString &deviceNode);
void removeDevice(const QString &deviceNode);
private:
+ void updateDeviceCount();
+
QString m_spec;
- QDeviceDiscovery *m_deviceDiscovery;
- QHash<QString, QEvdevTabletHandlerThread *> m_activeDevices;
+ QtInputSupport::DeviceHandlerList<QEvdevTabletHandlerThread> m_activeDevices;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
index f86f80785e..c51db59e1f 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
@@ -49,6 +49,9 @@
#include <QtCore/private/qcore_unix_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/private/qguiapplication_p.h>
+
+#include <mutex>
+
#ifdef Q_OS_FREEBSD
#include <dev/evdev/input.h>
#else
@@ -66,6 +69,7 @@ extern "C" {
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(qLcEvdevTouch, "qt.qpa.input")
+Q_LOGGING_CATEGORY(qLcEvents, "qt.qpa.input.events")
/* android (and perhaps some other linux-derived stuff) don't define everything
* in linux/input.h, so we'll need to do that ourselves.
@@ -228,7 +232,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
}
}
- qCDebug(qLcEvdevTouch, "evdevtouch: Using device %s", qPrintable(device));
+ qCDebug(qLcEvdevTouch, "evdevtouch: Using device %ls", qUtf16Printable(device));
m_fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
@@ -236,7 +240,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
connect(m_notify, &QSocketNotifier::activated, this, &QEvdevTouchScreenHandler::readData);
} else {
- qErrnoWarning(errno, "evdevtouch: Cannot open input device %s", qPrintable(device));
+ qErrnoWarning("evdevtouch: Cannot open input device %ls", qUtf16Printable(device));
return;
}
@@ -266,8 +270,8 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
d->deviceNode = device;
qCDebug(qLcEvdevTouch,
- "evdevtouch: %s: Protocol type %c %s (%s), filtered=%s",
- qPrintable(d->deviceNode),
+ "evdevtouch: %ls: Protocol type %c %s (%s), filtered=%s",
+ qUtf16Printable(d->deviceNode),
d->m_typeB ? 'B' : 'A', mtdevStr,
d->m_singleTouch ? "single" : "multi",
d->m_filtered ? "yes" : "no");
@@ -279,7 +283,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
bool has_x_range = false, has_y_range = false;
if (ioctl(m_fd, EVIOCGABS((d->m_singleTouch ? ABS_X : ABS_MT_POSITION_X)), &absInfo) >= 0) {
- qCDebug(qLcEvdevTouch, "evdevtouch: %s: min X: %d max X: %d", qPrintable(device),
+ qCDebug(qLcEvdevTouch, "evdevtouch: %ls: min X: %d max X: %d", qUtf16Printable(device),
absInfo.minimum, absInfo.maximum);
d->hw_range_x_min = absInfo.minimum;
d->hw_range_x_max = absInfo.maximum;
@@ -287,7 +291,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
}
if (ioctl(m_fd, EVIOCGABS((d->m_singleTouch ? ABS_Y : ABS_MT_POSITION_Y)), &absInfo) >= 0) {
- qCDebug(qLcEvdevTouch, "evdevtouch: %s: min Y: %d max Y: %d", qPrintable(device),
+ qCDebug(qLcEvdevTouch, "evdevtouch: %ls: min Y: %d max Y: %d", qUtf16Printable(device),
absInfo.minimum, absInfo.maximum);
d->hw_range_y_min = absInfo.minimum;
d->hw_range_y_max = absInfo.maximum;
@@ -295,10 +299,10 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
}
if (!has_x_range || !has_y_range)
- qWarning("evdevtouch: %s: Invalid ABS limits, behavior unspecified", qPrintable(device));
+ qWarning("evdevtouch: %ls: Invalid ABS limits, behavior unspecified", qUtf16Printable(device));
if (ioctl(m_fd, EVIOCGABS(ABS_PRESSURE), &absInfo) >= 0) {
- qCDebug(qLcEvdevTouch, "evdevtouch: %s: min pressure: %d max pressure: %d", qPrintable(device),
+ qCDebug(qLcEvdevTouch, "evdevtouch: %ls: min pressure: %d max pressure: %d", qUtf16Printable(device),
absInfo.minimum, absInfo.maximum);
if (absInfo.maximum > absInfo.minimum) {
d->hw_pressure_min = absInfo.minimum;
@@ -309,7 +313,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
char name[1024];
if (ioctl(m_fd, EVIOCGNAME(sizeof(name) - 1), name) >= 0) {
d->hw_name = QString::fromLocal8Bit(name);
- qCDebug(qLcEvdevTouch, "evdevtouch: %s: device name: %s", qPrintable(device), name);
+ qCDebug(qLcEvdevTouch, "evdevtouch: %ls: device name: %s", qUtf16Printable(device), name);
}
// Fix up the coordinate ranges for am335x in case the kernel driver does not have them fixed.
@@ -345,8 +349,8 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const
if (mapping.load()) {
d->m_screenName = mapping.screenNameForDeviceNode(d->deviceNode);
if (!d->m_screenName.isEmpty())
- qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %s to screen %s",
- qPrintable(d->deviceNode), qPrintable(d->m_screenName));
+ qCDebug(qLcEvdevTouch, "evdevtouch: Mapping device %ls to screen %ls",
+ qUtf16Printable(d->deviceNode), qUtf16Printable(d->m_screenName));
}
registerTouchDevice();
@@ -427,7 +431,7 @@ err:
return;
} else if (events < 0) {
if (errno != EINTR && errno != EAGAIN) {
- qErrnoWarning(errno, "evdevtouch: Could not read from input device");
+ qErrnoWarning("evdevtouch: Could not read from input device");
if (errno == ENODEV) { // device got disconnected -> stop reading
delete m_notify;
m_notify = nullptr;
@@ -536,6 +540,9 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
if (m_typeB)
m_contacts[m_currentSlot].maj = m_currentData.maj;
} else if (data->code == ABS_PRESSURE || data->code == ABS_MT_PRESSURE) {
+ if (Q_UNLIKELY(qLcEvents().isDebugEnabled()))
+ qCDebug(qLcEvents, "EV_ABS code 0x%x: pressure %d; bounding to [%d,%d]",
+ data->code, data->value, hw_pressure_min, hw_pressure_max);
m_currentData.pressure = qBound(hw_pressure_min, data->value, hw_pressure_max);
if (m_typeB || m_singleTouch)
m_contacts[m_currentSlot].pressure = m_currentData.pressure;
@@ -563,8 +570,9 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
if (!m_contacts.isEmpty() && m_contacts.constBegin().value().trackingId == -1)
assignIds();
+ std::unique_lock<QMutex> locker;
if (m_filtered)
- m_mutex.lock();
+ locker = std::unique_lock<QMutex>{m_mutex};
// update timestamps
m_lastTimeStamp = m_timeStamp;
@@ -573,10 +581,11 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
m_lastTouchPoints = m_touchPoints;
m_touchPoints.clear();
Qt::TouchPointStates combinedStates;
+ bool hasPressure = false;
+
+ for (auto i = m_contacts.begin(), end = m_contacts.end(); i != end; /*erasing*/) {
+ auto it = i++;
- QMutableHashIterator<int, Contact> it(m_contacts);
- while (it.hasNext()) {
- it.next();
Contact &contact(it.value());
if (!contact.state)
@@ -599,17 +608,18 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
// Avoid reporting a contact in released state more than once.
if (!m_typeB && contact.state == Qt::TouchPointReleased
&& !m_lastContacts.contains(key)) {
- it.remove();
+ m_contacts.erase(it);
continue;
}
+ if (contact.pressure)
+ hasPressure = true;
+
addTouchPoint(contact, &combinedStates);
}
// Now look for contacts that have disappeared since the last sync.
- it = m_lastContacts;
- while (it.hasNext()) {
- it.next();
+ for (auto it = m_lastContacts.begin(), end = m_lastContacts.end(); it != end; ++it) {
Contact &contact(it.value());
int key = m_typeB ? it.key() : contact.trackingId;
if (m_typeB) {
@@ -626,9 +636,9 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
}
// Remove contacts that have just been reported as released.
- it = m_contacts;
- while (it.hasNext()) {
- it.next();
+ for (auto i = m_contacts.begin(), end = m_contacts.end(); i != end; /*erasing*/) {
+ auto it = i++;
+
Contact &contact(it.value());
if (!contact.state)
@@ -638,7 +648,7 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
if (m_typeB)
contact.state = static_cast<Qt::TouchPointState>(0);
else
- it.remove();
+ m_contacts.erase(it);
} else {
contact.state = Qt::TouchPointStationary;
}
@@ -649,11 +659,8 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
m_contacts.clear();
- if (!m_touchPoints.isEmpty() && combinedStates != Qt::TouchPointStationary)
+ if (!m_touchPoints.isEmpty() && (hasPressure || combinedStates != Qt::TouchPointStationary))
reportPoints();
-
- if (m_filtered)
- m_mutex.unlock();
}
m_lastEventType = data->type;
@@ -778,6 +785,9 @@ void QEvdevTouchScreenData::reportPoints()
tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
else
tp.pressure = (tp.pressure - hw_pressure_min) / qreal(hw_pressure_max - hw_pressure_min);
+
+ if (Q_UNLIKELY(qLcEvents().isDebugEnabled()))
+ qCDebug(qLcEvents) << "reporting" << tp;
}
// Let qguiapp pick the target window.
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
index 4cacbf03e5..bf2df93d11 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
@@ -40,12 +40,15 @@
#include "qevdevtouchmanager_p.h"
#include "qevdevtouchhandler_p.h"
+#include <QtInputSupport/private/qevdevutil_p.h>
+
#include <QStringList>
#include <QGuiApplication>
#include <QLoggingCategory>
#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
#include <private/qguiapplication_p.h>
#include <private/qinputdevicemanager_p_p.h>
+#include <private/qmemory_p.h>
QT_BEGIN_NAMESPACE
@@ -64,34 +67,23 @@ QEvdevTouchManager::QEvdevTouchManager(const QString &key, const QString &specif
if (spec.isEmpty())
spec = specification;
- QStringList args = spec.split(QLatin1Char(':'));
- QStringList devices;
-
- foreach (const QString &arg, args) {
- if (arg.startsWith(QLatin1String("/dev/"))) {
- devices.append(arg);
- args.removeAll(arg);
- }
- }
-
- // build new specification without /dev/ elements
- m_spec = args.join(QLatin1Char(':'));
+ auto parsed = QEvdevUtil::parseSpecification(spec);
+ m_spec = std::move(parsed.spec);
- foreach (const QString &device, devices)
+ for (const QString &device : qAsConst(parsed.devices))
addDevice(device);
// when no devices specified, use device discovery to scan and monitor
- if (devices.isEmpty()) {
- qCDebug(qLcEvdevTouch) << "evdevtouch: Using device discovery";
- m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Touchpad | QDeviceDiscovery::Device_Touchscreen, this);
- if (m_deviceDiscovery) {
- const QStringList devices = m_deviceDiscovery->scanConnectedDevices();
+ if (parsed.devices.isEmpty()) {
+ qCDebug(qLcEvdevTouch, "evdevtouch: Using device discovery");
+ if (auto deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Touchpad | QDeviceDiscovery::Device_Touchscreen, this)) {
+ const QStringList devices = deviceDiscovery->scanConnectedDevices();
for (const QString &device : devices)
addDevice(device);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceDetected,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceDetected,
this, &QEvdevTouchManager::addDevice);
- connect(m_deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
+ connect(deviceDiscovery, &QDeviceDiscovery::deviceRemoved,
this, &QEvdevTouchManager::removeDevice);
}
}
@@ -99,30 +91,24 @@ QEvdevTouchManager::QEvdevTouchManager(const QString &key, const QString &specif
QEvdevTouchManager::~QEvdevTouchManager()
{
- qDeleteAll(m_activeDevices);
}
void QEvdevTouchManager::addDevice(const QString &deviceNode)
{
- qCDebug(qLcEvdevTouch) << "evdevtouch: Adding device at" << deviceNode;
- QEvdevTouchScreenHandlerThread *handler;
- handler = new QEvdevTouchScreenHandlerThread(deviceNode, m_spec);
+ qCDebug(qLcEvdevTouch, "evdevtouch: Adding device at %ls", qUtf16Printable(deviceNode));
+ auto handler = qt_make_unique<QEvdevTouchScreenHandlerThread>(deviceNode, m_spec);
if (handler) {
- m_activeDevices.insert(deviceNode, handler);
- connect(handler, &QEvdevTouchScreenHandlerThread::touchDeviceRegistered, this, &QEvdevTouchManager::updateInputDeviceCount);
+ connect(handler.get(), &QEvdevTouchScreenHandlerThread::touchDeviceRegistered, this, &QEvdevTouchManager::updateInputDeviceCount);
+ m_activeDevices.add(deviceNode, std::move(handler));
} else {
- qWarning("evdevtouch: Failed to open touch device %s", qPrintable(deviceNode));
+ qWarning("evdevtouch: Failed to open touch device %ls", qUtf16Printable(deviceNode));
}
}
void QEvdevTouchManager::removeDevice(const QString &deviceNode)
{
- if (m_activeDevices.contains(deviceNode)) {
- qCDebug(qLcEvdevTouch) << "evdevtouch: Removing device at" << deviceNode;
- QEvdevTouchScreenHandlerThread *handler = m_activeDevices.value(deviceNode);
- m_activeDevices.remove(deviceNode);
- delete handler;
-
+ if (m_activeDevices.remove(deviceNode)) {
+ qCDebug(qLcEvdevTouch, "evdevtouch: Removing device at %ls", qUtf16Printable(deviceNode));
updateInputDeviceCount();
}
}
@@ -130,13 +116,13 @@ void QEvdevTouchManager::removeDevice(const QString &deviceNode)
void QEvdevTouchManager::updateInputDeviceCount()
{
int registeredTouchDevices = 0;
- Q_FOREACH (QEvdevTouchScreenHandlerThread *handler, m_activeDevices) {
- if (handler->isTouchDeviceRegistered())
+ for (const auto &device : m_activeDevices) {
+ if (device.handler->isTouchDeviceRegistered())
++registeredTouchDevices;
}
- qCDebug(qLcEvdevTouch) << "evdevtouch: Updating QInputDeviceManager device count:" << registeredTouchDevices << " touch devices,"
- << m_activeDevices.count() - registeredTouchDevices << "pending handler(s)" ;
+ qCDebug(qLcEvdevTouch, "evdevtouch: Updating QInputDeviceManager device count: %d touch devices, %d pending handler(s)",
+ registeredTouchDevices, m_activeDevices.count() - registeredTouchDevices);
QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
QInputDeviceManager::DeviceTypeTouch, registeredTouchDevices);
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h b/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
index e524c516f1..94ee05d900 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+#include <QtInputSupport/private/devicehandlerlist_p.h>
+
#include <QObject>
#include <QHash>
#include <QSocketNotifier>
@@ -63,7 +65,7 @@ class QEvdevTouchScreenHandlerThread;
class QEvdevTouchManager : public QObject
{
public:
- QEvdevTouchManager(const QString &key, const QString &spec, QObject *parent = 0);
+ QEvdevTouchManager(const QString &key, const QString &spec, QObject *parent = nullptr);
~QEvdevTouchManager();
void addDevice(const QString &deviceNode);
@@ -73,8 +75,7 @@ public:
private:
QString m_spec;
- QDeviceDiscovery *m_deviceDiscovery;
- QHash<QString, QEvdevTouchScreenHandlerThread *> m_activeDevices;
+ QtInputSupport::DeviceHandlerList<QEvdevTouchScreenHandlerThread> m_activeDevices;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/libinput/qlibinputhandler.cpp b/src/platformsupport/input/libinput/qlibinputhandler.cpp
index e5dc182bec..95dfb46d16 100644
--- a/src/platformsupport/input/libinput/qlibinputhandler.cpp
+++ b/src/platformsupport/input/libinput/qlibinputhandler.cpp
@@ -205,6 +205,9 @@ void QLibInputHandler::processEvent(libinput_event *ev)
case LIBINPUT_EVENT_POINTER_MOTION:
m_pointer->processMotion(libinput_event_get_pointer_event(ev));
break;
+ case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
+ m_pointer->processAbsMotion(libinput_event_get_pointer_event(ev));
+ break;
case LIBINPUT_EVENT_POINTER_AXIS:
m_pointer->processAxis(libinput_event_get_pointer_event(ev));
break;
diff --git a/src/platformsupport/input/libinput/qlibinputpointer.cpp b/src/platformsupport/input/libinput/qlibinputpointer.cpp
index c54b61fc66..db9e81b5df 100644
--- a/src/platformsupport/input/libinput/qlibinputpointer.cpp
+++ b/src/platformsupport/input/libinput/qlibinputpointer.cpp
@@ -103,6 +103,24 @@ void QLibInputPointer::processMotion(libinput_event_pointer *e)
Qt::NoButton, QEvent::MouseMove, mods);
}
+void QLibInputPointer::processAbsMotion(libinput_event_pointer *e)
+{
+ QScreen * const primaryScreen = QGuiApplication::primaryScreen();
+ const QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen);
+
+ const double x = libinput_event_pointer_get_absolute_x_transformed(e, g.width());
+ const double y = libinput_event_pointer_get_absolute_y_transformed(e, g.height());
+
+ m_pos.setX(qBound(g.left(), qRound(g.left() + x), g.right()));
+ m_pos.setY(qBound(g.top(), qRound(g.top() + y), g.bottom()));
+
+ Qt::KeyboardModifiers mods = QGuiApplicationPrivate::inputDeviceManager()->keyboardModifiers();
+
+ QWindowSystemInterface::handleMouseEvent(nullptr, m_pos, m_pos, m_buttons,
+ Qt::NoButton, QEvent::MouseMove, mods);
+
+}
+
void QLibInputPointer::processAxis(libinput_event_pointer *e)
{
double value; // default axis value is 15 degrees per wheel click
diff --git a/src/platformsupport/input/libinput/qlibinputpointer_p.h b/src/platformsupport/input/libinput/qlibinputpointer_p.h
index a7a66337f1..55d4a5f919 100644
--- a/src/platformsupport/input/libinput/qlibinputpointer_p.h
+++ b/src/platformsupport/input/libinput/qlibinputpointer_p.h
@@ -64,6 +64,7 @@ public:
void processButton(libinput_event_pointer *e);
void processMotion(libinput_event_pointer *e);
+ void processAbsMotion(libinput_event_pointer *e);
void processAxis(libinput_event_pointer *e);
void setPos(const QPoint &pos);
diff --git a/src/platformsupport/input/libinput/qlibinputtouch_p.h b/src/platformsupport/input/libinput/qlibinputtouch_p.h
index 6f88001d19..51304e6a21 100644
--- a/src/platformsupport/input/libinput/qlibinputtouch_p.h
+++ b/src/platformsupport/input/libinput/qlibinputtouch_p.h
@@ -73,7 +73,7 @@ public:
private:
struct DeviceState {
- DeviceState() : m_touchDevice(0) { }
+ DeviceState() : m_touchDevice(nullptr) { }
QWindowSystemInterface::TouchPoint *point(int32_t slot);
QList<QWindowSystemInterface::TouchPoint> m_points;
QTouchDevice *m_touchDevice;
diff --git a/src/platformsupport/input/shared/devicehandlerlist_p.h b/src/platformsupport/input/shared/devicehandlerlist_p.h
new file mode 100644
index 0000000000..97794d4d7d
--- /dev/null
+++ b/src/platformsupport/input/shared/devicehandlerlist_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or 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.GPL2 and 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTINPUTSUPPORT_DEVICEHANDLERLIST_P_H
+#define QTINPUTSUPPORT_DEVICEHANDLERLIST_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QString>
+
+#include <vector>
+#include <memory>
+
+namespace QtInputSupport {
+
+template <typename Handler>
+class DeviceHandlerList {
+public:
+ struct Device {
+ QString deviceNode;
+ std::unique_ptr<Handler> handler;
+ };
+
+ void add(const QString &deviceNode, std::unique_ptr<Handler> handler)
+ {
+ v.push_back({deviceNode, std::move(handler)});
+ }
+
+ bool remove(const QString &deviceNode)
+ {
+ const auto deviceNodeMatches = [&] (const Device &d) { return d.deviceNode == deviceNode; };
+ const auto it = std::find_if(v.cbegin(), v.cend(), deviceNodeMatches);
+ if (it == v.cend())
+ return false;
+ v.erase(it);
+ return true;
+ }
+
+ int count() const noexcept { return static_cast<int>(v.size()); }
+
+ typename std::vector<Device>::const_iterator begin() const noexcept { return v.begin(); }
+ typename std::vector<Device>::const_iterator end() const noexcept { return v.end(); }
+
+private:
+ std::vector<Device> v;
+};
+
+} // QtInputSupport
+
+#endif // QTINPUTSUPPORT_DEVICEHANDLERLIST_P_H
diff --git a/src/platformsupport/input/shared/qevdevutil.cpp b/src/platformsupport/input/shared/qevdevutil.cpp
new file mode 100644
index 0000000000..74f8bcdc2b
--- /dev/null
+++ b/src/platformsupport/input/shared/qevdevutil.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or 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.GPL2 and 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qevdevutil_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QEvdevUtil {
+
+ParsedSpecification parseSpecification(const QString &specification)
+{
+ ParsedSpecification result;
+
+ result.args = specification.splitRef(QLatin1Char(':'));
+
+ for (const QStringRef &arg : qAsConst(result.args)) {
+ if (arg.startsWith(QLatin1String("/dev/"))) {
+ // if device is specified try to use it
+ result.devices.append(arg.toString());
+ } else {
+ // build new specification without /dev/ elements
+ result.spec += arg + QLatin1Char(':');
+ }
+ }
+
+ if (!result.spec.isEmpty())
+ result.spec.chop(1); // remove trailing ':'
+
+ return result;
+}
+
+} // namespace QEvdevUtil
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/input/shared/qevdevutil_p.h b/src/platformsupport/input/shared/qevdevutil_p.h
new file mode 100644
index 0000000000..7d0a5af130
--- /dev/null
+++ b/src/platformsupport/input/shared/qevdevutil_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or 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.GPL2 and 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVDEVUTIL_P_H
+#define QEVDEVUTIL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QString>
+#include <QStringList>
+#include <QVector>
+#include <QStringRef>
+
+QT_BEGIN_NAMESPACE
+
+namespace QEvdevUtil {
+
+struct ParsedSpecification
+{
+ QString spec;
+ QStringList devices;
+ QVector<QStringRef> args;
+};
+
+ParsedSpecification parseSpecification(const QString &specification);
+
+}
+
+QT_END_NAMESPACE
+
+#endif // QEVDEVUTIL_P_H
diff --git a/src/platformsupport/input/shared/shared.pri b/src/platformsupport/input/shared/shared.pri
index 1443235244..c29d11e7d6 100644
--- a/src/platformsupport/input/shared/shared.pri
+++ b/src/platformsupport/input/shared/shared.pri
@@ -1,5 +1,8 @@
HEADERS += \
+ $$PWD/devicehandlerlist_p.h \
+ $$PWD/qevdevutil_p.h \
$$PWD/qtouchoutputmapping_p.h
SOURCES += \
+ $$PWD/qevdevutil.cpp \
$$PWD/qtouchoutputmapping.cpp
diff --git a/src/platformsupport/input/tslib/qtslib.cpp b/src/platformsupport/input/tslib/qtslib.cpp
index 7609416fea..e105f5ea98 100644
--- a/src/platformsupport/input/tslib/qtslib.cpp
+++ b/src/platformsupport/input/tslib/qtslib.cpp
@@ -57,38 +57,22 @@ QTsLibMouseHandler::QTsLibMouseHandler(const QString &key,
const QString &specification,
QObject *parent)
: QObject(parent),
- m_notify(0), m_x(0), m_y(0), m_pressed(0), m_rawMode(false)
+ m_rawMode(!key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive))
{
qCDebug(qLcTsLib) << "Initializing tslib plugin" << key << specification;
setObjectName(QLatin1String("TSLib Mouse Handler"));
- QByteArray device = qgetenv("TSLIB_TSDEVICE");
-
- if (specification.startsWith(QLatin1String("/dev/")))
- device = specification.toLocal8Bit();
-
- if (device.isEmpty())
- device = QByteArrayLiteral("/dev/input/event1");
-
- m_dev = ts_open(device.constData(), 1);
+ m_dev = ts_setup(nullptr, 1);
if (!m_dev) {
- qErrnoWarning(errno, "ts_open() failed");
+ qErrnoWarning(errno, "ts_setup() failed");
return;
}
- if (ts_config(m_dev))
- qErrnoWarning(errno, "ts_config() failed");
-
- m_rawMode = !key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive);
-
- int fd = ts_fd(m_dev);
- if (fd >= 0) {
- qCDebug(qLcTsLib) << "tslib device is" << device;
- m_notify = new QSocketNotifier(fd, QSocketNotifier::Read, this);
- connect(m_notify, &QSocketNotifier::activated, this, &QTsLibMouseHandler::readMouseData);
- } else {
- qErrnoWarning(errno, "tslib: Cannot open input device %s", device.constData());
- }
+#ifdef TSLIB_VERSION_EVENTPATH /* also introduced in 1.15 */
+ qCDebug(qLcTsLib) << "tslib device is" << ts_get_eventpath(m_dev);
+#endif
+ m_notify = new QSocketNotifier(ts_fd(m_dev), QSocketNotifier::Read, this);
+ connect(m_notify, &QSocketNotifier::activated, this, &QTsLibMouseHandler::readMouseData);
}
QTsLibMouseHandler::~QTsLibMouseHandler()
diff --git a/src/platformsupport/input/tslib/qtslib_p.h b/src/platformsupport/input/tslib/qtslib_p.h
index 0c08fb6a3d..ffd60cd0e3 100644
--- a/src/platformsupport/input/tslib/qtslib_p.h
+++ b/src/platformsupport/input/tslib/qtslib_p.h
@@ -71,11 +71,12 @@ private slots:
void readMouseData();
private:
- QSocketNotifier * m_notify;
+ QSocketNotifier * m_notify = nullptr;
tsdev *m_dev;
- int m_x, m_y;
- bool m_pressed;
- bool m_rawMode;
+ int m_x = 0;
+ int m_y = 0;
+ bool m_pressed = false;
+ const bool m_rawMode;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
index fec59cfc7b..6121faf362 100644
--- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp
+++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -66,6 +66,8 @@ enum OutputConfiguration {
int QKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector)
{
+ int candidate = -1;
+
for (int i = 0; i < connector->count_encoders; i++) {
drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoders[i]);
if (!encoder) {
@@ -73,19 +75,30 @@ int QKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr co
continue;
}
+ quint32 encoderId = encoder->encoder_id;
+ quint32 crtcId = encoder->crtc_id;
quint32 possibleCrtcs = encoder->possible_crtcs;
drmModeFreeEncoder(encoder);
for (int j = 0; j < resources->count_crtcs; j++) {
bool isPossible = possibleCrtcs & (1 << j);
bool isAvailable = !(m_crtc_allocator & (1 << j));
-
- if (isPossible && isAvailable)
+ // Preserve the existing CRTC -> encoder -> connector routing if
+ // any. It makes the initialization faster, and may be better
+ // since we have a very dumb picking algorithm.
+ bool isBestChoice = (!connector->encoder_id ||
+ (connector->encoder_id == encoderId &&
+ resources->crtcs[j] == crtcId));
+
+ if (isPossible && isAvailable && isBestChoice) {
return j;
+ } else if (isPossible && isAvailable) {
+ candidate = j;
+ }
}
}
- return -1;
+ return candidate;
}
static const char * const connector_type_names[] = { // must match DRM_MODE_CONNECTOR_*
@@ -381,23 +394,26 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
if (!cloneSource.isEmpty())
qCDebug(qLcKmsDebug) << "Output" << connectorName << " clones output " << cloneSource;
- const QByteArray fbsize = userConnectorConfig.value(QStringLiteral("size")).toByteArray().toLower();
QSize framebufferSize;
- framebufferSize.setWidth(modes[selected_mode].hdisplay);
- framebufferSize.setHeight(modes[selected_mode].vdisplay);
-
+ bool framebufferSizeSet = false;
+ const QByteArray fbsize = userConnectorConfig.value(QStringLiteral("size")).toByteArray().toLower();
+ if (!fbsize.isEmpty()) {
+ if (sscanf(fbsize.constData(), "%dx%d", &framebufferSize.rwidth(), &framebufferSize.rheight()) == 2) {
#if QT_CONFIG(drm_atomic)
- if (hasAtomicSupport()) {
- if (sscanf(fbsize.constData(), "%dx%d", &framebufferSize.rwidth(), &framebufferSize.rheight()) != 2) {
- qWarning("Framebuffer size format is invalid.");
+ if (hasAtomicSupport())
+ framebufferSizeSet = true;
+#endif
+ if (!framebufferSizeSet)
+ qWarning("Setting framebuffer size is only available with DRM atomic API");
+ } else {
+ qWarning("Invalid framebuffer size '%s'", fbsize.constData());
}
- } else {
- qWarning("Setting framebuffer size is only available with DRM atomic API");
}
-#else
- if (fbsize.size())
- qWarning("Setting framebuffer size is only available with DRM atomic API");
-#endif
+ if (!framebufferSizeSet) {
+ framebufferSize.setWidth(modes[selected_mode].hdisplay);
+ framebufferSize.setHeight(modes[selected_mode].vdisplay);
+ }
+
qCDebug(qLcKmsDebug) << "Output" << connectorName << "framebuffer size is " << framebufferSize;
QKmsOutput output;
@@ -799,9 +815,7 @@ void QKmsDevice::discoverPlanes()
for (int i = 0; i < countFormats; ++i) {
uint32_t f = drmplane->formats[i];
plane.supportedFormats.append(f);
- QString s;
- s.sprintf("%c%c%c%c ", f, f >> 8, f >> 16, f >> 24);
- formatStr += s;
+ formatStr += QString::asprintf("%c%c%c%c ", f, f >> 8, f >> 16, f >> 24);
}
qCDebug(qLcKmsDebug, "plane %d: id = %u countFormats = %d possibleCrtcs = 0x%x supported formats = %s",
@@ -848,6 +862,8 @@ void QKmsDevice::discoverPlanes()
plane.crtcYPropertyId = prop->prop_id;
} else if (!strcasecmp(prop->name, "zpos")) {
plane.zposPropertyId = prop->prop_id;
+ } else if (!strcasecmp(prop->name, "blend_op")) {
+ plane.blendOpPropertyId = prop->prop_id;
}
});
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice_p.h b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
index 14da6bb947..b1150e2875 100644
--- a/src/platformsupport/kmsconvenience/qkmsdevice_p.h
+++ b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
@@ -178,6 +178,7 @@ struct QKmsPlane
uint32_t crtcwidthPropertyId = 0;
uint32_t crtcheightPropertyId = 0;
uint32_t zposPropertyId = 0;
+ uint32_t blendOpPropertyId = 0;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QKmsPlane::Rotations)
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
index 6e8cab93a2..4a83c6eb80 100644
--- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
+++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
@@ -2050,8 +2050,8 @@ QVariantList AtSpiAdaptor::getAttributes(QAccessibleInterface *interface, int of
int endOffset;
QString joined = interface->textInterface()->attributes(offset, &startOffset, &endOffset);
- QStringList attributes = joined.split (QLatin1Char(';'), QString::SkipEmptyParts, Qt::CaseSensitive);
- foreach (const QString &attr, attributes) {
+ const QStringList attributes = joined.split (QLatin1Char(';'), QString::SkipEmptyParts, Qt::CaseSensitive);
+ for (const QString &attr : attributes) {
QStringList items;
items = attr.split(QLatin1Char(':'), QString::SkipEmptyParts, Qt::CaseSensitive);
AtSpiAttribute attribute = atspiTextAttribute(items[0], items[1]);
@@ -2069,14 +2069,13 @@ QVariantList AtSpiAdaptor::getAttributeValue(QAccessibleInterface *interface, in
{
QString mapped;
QString joined;
- QStringList attributes;
QSpiAttributeSet map;
int startOffset;
int endOffset;
joined = interface->textInterface()->attributes(offset, &startOffset, &endOffset);
- attributes = joined.split (QLatin1Char(';'), QString::SkipEmptyParts, Qt::CaseSensitive);
- foreach (const QString& attr, attributes) {
+ const QStringList attributes = joined.split (QLatin1Char(';'), QString::SkipEmptyParts, Qt::CaseSensitive);
+ for (const QString& attr : attributes) {
QStringList items;
items = attr.split(QLatin1Char(':'), QString::SkipEmptyParts, Qt::CaseSensitive);
AtSpiAttribute attribute = atspiTextAttribute(items[0], items[1]);
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h
index b5704f53ad..0b624389a3 100644
--- a/src/platformsupport/linuxaccessibility/atspiadaptor_p.h
+++ b/src/platformsupport/linuxaccessibility/atspiadaptor_p.h
@@ -76,7 +76,7 @@ class AtSpiAdaptor :public QDBusVirtualObject
Q_OBJECT
public:
- explicit AtSpiAdaptor(DBusConnection *connection, QObject *parent = 0);
+ explicit AtSpiAdaptor(DBusConnection *connection, QObject *parent = nullptr);
~AtSpiAdaptor();
void registerApplication();
diff --git a/src/platformsupport/linuxaccessibility/cache_p.h b/src/platformsupport/linuxaccessibility/cache_p.h
index e8529b779b..cc55acc6f8 100644
--- a/src/platformsupport/linuxaccessibility/cache_p.h
+++ b/src/platformsupport/linuxaccessibility/cache_p.h
@@ -65,7 +65,7 @@ class QSpiDBusCache : public QObject
Q_OBJECT
public:
- explicit QSpiDBusCache(QDBusConnection c, QObject* parent = 0);
+ explicit QSpiDBusCache(QDBusConnection c, QObject* parent = nullptr);
void emitAddAccessible(const QSpiAccessibleCacheItem& item);
void emitRemoveAccessible(const QSpiObjectReference& item);
diff --git a/src/platformsupport/linuxaccessibility/dbusconnection_p.h b/src/platformsupport/linuxaccessibility/dbusconnection_p.h
index 4030fabc22..860c18ca05 100644
--- a/src/platformsupport/linuxaccessibility/dbusconnection_p.h
+++ b/src/platformsupport/linuxaccessibility/dbusconnection_p.h
@@ -65,7 +65,7 @@ class DBusConnection : public QObject
Q_OBJECT
public:
- DBusConnection(QObject *parent = 0);
+ DBusConnection(QObject *parent = nullptr);
QDBusConnection connection() const;
bool isEnabled() const { return m_enabled; }
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
index 7959f0c28a..f484795fbb 100644
--- a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuconnection_p.h
@@ -69,7 +69,7 @@ class QDBusMenuConnection : public QObject
Q_OBJECT
public:
- QDBusMenuConnection(QObject *parent = 0, const QString &serviceName = QString());
+ QDBusMenuConnection(QObject *parent = nullptr, const QString &serviceName = QString());
QDBusConnection connection() const { return m_connection; }
QDBusServiceWatcher *dbusWatcher() const { return m_dbusWatcher; }
bool isStatusNotifierHostRegistered() const { return m_statusNotifierHostRegistered; }
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy_p.h
index c92de0a140..cffc080f87 100644
--- a/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy_p.h
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusmenuregistrarproxy_p.h
@@ -92,15 +92,11 @@ public:
public Q_SLOTS: // METHODS
QDBusPendingReply<QString, QDBusObjectPath> GetMenuForWindow(uint windowId)
{
- QList<QVariant> argumentList;
- argumentList << QVariant::fromValue(windowId);
- return asyncCallWithArgumentList(QStringLiteral("GetMenuForWindow"), argumentList);
+ return asyncCall(QStringLiteral("GetMenuForWindow"), windowId);
}
QDBusReply<QString> GetMenuForWindow(uint windowId, QDBusObjectPath &menuObjectPath)
{
- QList<QVariant> argumentList;
- argumentList << QVariant::fromValue(windowId);
- QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("GetMenuForWindow"), argumentList);
+ QDBusMessage reply = call(QDBus::Block, QStringLiteral("GetMenuForWindow"), windowId);
QList<QVariant> arguments = reply.arguments();
if (reply.type() == QDBusMessage::ReplyMessage && arguments.count() == 2)
menuObjectPath = qdbus_cast<QDBusObjectPath>(arguments.at(1));
@@ -109,16 +105,12 @@ public Q_SLOTS: // METHODS
QDBusPendingReply<> RegisterWindow(uint windowId, const QDBusObjectPath &menuObjectPath)
{
- QList<QVariant> argumentList;
- argumentList << QVariant::fromValue(windowId) << QVariant::fromValue(menuObjectPath);
- return asyncCallWithArgumentList(QStringLiteral("RegisterWindow"), argumentList);
+ return asyncCall(QStringLiteral("RegisterWindow"), windowId, menuObjectPath);
}
QDBusPendingReply<> UnregisterWindow(uint windowId)
{
- QList<QVariant> argumentList;
- argumentList << QVariant::fromValue(windowId);
- return asyncCallWithArgumentList(QStringLiteral("UnregisterWindow"), argumentList);
+ return asyncCall(QStringLiteral("UnregisterWindow"), windowId);
}
};
diff --git a/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h b/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h
index 352b4aa5d6..2194a787eb 100644
--- a/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h
+++ b/src/platformsupport/themes/genericunix/dbustray/qxdgnotificationproxy_p.h
@@ -88,33 +88,28 @@ public:
public:
QXdgNotificationInterface(const QString &service, const QString &path,
- const QDBusConnection &connection, QObject *parent = 0);
+ const QDBusConnection &connection, QObject *parent = nullptr);
~QXdgNotificationInterface();
public Q_SLOTS: // METHODS
inline QDBusPendingReply<> closeNotification(uint id)
{
- QList<QVariant> argumentList;
- argumentList << QVariant::fromValue(id);
- return asyncCallWithArgumentList(QStringLiteral("CloseNotification"), argumentList);
+ return asyncCall(QStringLiteral("CloseNotification"), id);
}
inline QDBusPendingReply<QStringList> getCapabilities()
{
- QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QStringLiteral("GetCapabilities"), argumentList);
+ return asyncCall(QStringLiteral("GetCapabilities"));
}
inline QDBusPendingReply<QString, QString, QString, QString> getServerInformation()
{
- QList<QVariant> argumentList;
- return asyncCallWithArgumentList(QStringLiteral("GetServerInformation"), argumentList);
+ return asyncCall(QStringLiteral("GetServerInformation"));
}
inline QDBusReply<QString> getServerInformation(QString &vendor, QString &version, QString &specVersion)
{
- QList<QVariant> argumentList;
- QDBusMessage reply = callWithArgumentList(QDBus::Block, QStringLiteral("GetServerInformation"), argumentList);
+ QDBusMessage reply = call(QDBus::Block, QStringLiteral("GetServerInformation"));
if (reply.type() == QDBusMessage::ReplyMessage && reply.arguments().count() == 4) {
vendor = qdbus_cast<QString>(reply.arguments().at(1));
version = qdbus_cast<QString>(reply.arguments().at(2));
@@ -129,12 +124,7 @@ public Q_SLOTS: // METHODS
const QVariantMap &hints, int timeout)
{
qCDebug(qLcTray) << appName << replacesId << appIcon << summary << body << actions << hints << timeout;
- QList<QVariant> argumentList;
- argumentList << QVariant::fromValue(appName) << QVariant::fromValue(replacesId) <<
- QVariant::fromValue(appIcon) << QVariant::fromValue(summary) <<
- QVariant::fromValue(body) << QVariant::fromValue(actions) <<
- QVariant::fromValue(hints) << QVariant::fromValue(timeout);
- return asyncCallWithArgumentList(QStringLiteral("Notify"), argumentList);
+ return asyncCall(QStringLiteral("Notify"), appName, replacesId, appIcon, summary, body, actions, hints, timeout);
}
Q_SIGNALS:
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index 6db25a90da..70d5616075 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -175,15 +175,9 @@ QStringList QGenericUnixTheme::xdgIconThemePaths()
if (homeIconDir.isDir())
paths.prepend(homeIconDir.absoluteFilePath());
- QString xdgDirString = QFile::decodeName(qgetenv("XDG_DATA_DIRS"));
- if (xdgDirString.isEmpty())
- xdgDirString = QLatin1String("/usr/local/share/:/usr/share/");
- const auto xdgDirs = xdgDirString.splitRef(QLatin1Char(':'));
- for (const QStringRef &xdgDir : xdgDirs) {
- const QFileInfo xdgIconsDir(xdgDir + QLatin1String("/icons"));
- if (xdgIconsDir.isDir())
- paths.append(xdgIconsDir.absoluteFilePath());
- }
+ paths.append(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation,
+ QStringLiteral("icons"),
+ QStandardPaths::LocateDirectory));
return paths;
}
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
index a5963b79ea..c0da9d8370 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes_p.h
@@ -109,7 +109,7 @@ public:
QVariant themeHint(ThemeHint hint) const override;
QIcon fileIcon(const QFileInfo &fileInfo,
- QPlatformTheme::IconOptions iconOptions = 0) const override;
+ QPlatformTheme::IconOptions iconOptions = nullptr) const override;
const QPalette *palette(Palette type = SystemPalette) const override;
@@ -134,7 +134,7 @@ public:
QGnomeTheme();
QVariant themeHint(ThemeHint hint) const override;
QIcon fileIcon(const QFileInfo &fileInfo,
- QPlatformTheme::IconOptions = 0) const override;
+ QPlatformTheme::IconOptions = nullptr) const override;
const QFont *font(Font type) const override;
QString standardButtonText(int button) const override;
diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
index b9c5669b3f..68340a3173 100644
--- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
+++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
@@ -330,6 +330,11 @@ bool QBasicPlatformVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevi
return supported;
}
+void QBasicPlatformVulkanInstance::setDebugFilters(const QVector<QVulkanInstance::DebugFilter> &filters)
+{
+ m_debugFilters = filters;
+}
+
void QBasicPlatformVulkanInstance::destroySurface(VkSurfaceKHR surface) const
{
if (m_destroySurface && surface)
@@ -345,11 +350,11 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugReportFlag
const char *pMessage,
void *pUserData)
{
- Q_UNUSED(flags);
- Q_UNUSED(objectType);
- Q_UNUSED(object);
- Q_UNUSED(location);
- Q_UNUSED(pUserData);
+ QBasicPlatformVulkanInstance *self = static_cast<QBasicPlatformVulkanInstance *>(pUserData);
+ for (QVulkanInstance::DebugFilter filter : *self->debugFilters()) {
+ if (filter(flags, objectType, object, location, messageCode, pLayerPrefix, pMessage))
+ return VK_FALSE;
+ }
// not categorized, just route to plain old qDebug
qDebug("vkDebug: %s: %d: %s", pLayerPrefix, messageCode, pMessage);
@@ -374,6 +379,7 @@ void QBasicPlatformVulkanInstance::setupDebugOutput()
| VK_DEBUG_REPORT_WARNING_BIT_EXT
| VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
dbgCallbackInfo.pfnCallback = defaultDebugCallbackFunc;
+ dbgCallbackInfo.pUserData = this;
VkResult err = createDebugReportCallback(m_vkInst, &dbgCallbackInfo, nullptr, &m_debugCallback);
if (err != VK_SUCCESS)
diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
index 566140b032..e59d9219fb 100644
--- a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
+++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
@@ -73,7 +73,10 @@ public:
QByteArrayList enabledExtensions() const override;
PFN_vkVoidFunction getInstanceProcAddr(const char *name) override;
bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override;
+ void setDebugFilters(const QVector<QVulkanInstance::DebugFilter> &filters) override;
+
void destroySurface(VkSurfaceKHR surface) const;
+ const QVector<QVulkanInstance::DebugFilter> *debugFilters() const { return &m_debugFilters; }
protected:
void loadVulkanLibrary(const QString &defaultLibraryName);
@@ -105,6 +108,7 @@ private:
VkDebugReportCallbackEXT m_debugCallback;
PFN_vkDestroyDebugReportCallbackEXT m_vkDestroyDebugReportCallbackEXT;
+ QVector<QVulkanInstance::DebugFilter> m_debugFilters;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/vkconvenience/qvkconvenience.cpp b/src/platformsupport/vkconvenience/qvkconvenience.cpp
index 462cdc9e0d..acde1d1bda 100644
--- a/src/platformsupport/vkconvenience/qvkconvenience.cpp
+++ b/src/platformsupport/vkconvenience/qvkconvenience.cpp
@@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE
\ingroup qpa
*/
+#if QT_CONFIG(opengl)
VkFormat QVkConvenience::vkFormatFromGlFormat(uint glFormat)
{
using GlFormat = QOpenGLTexture::TextureFormat;
@@ -211,5 +212,6 @@ VkFormat QVkConvenience::vkFormatFromGlFormat(uint glFormat)
default: return VK_FORMAT_UNDEFINED;
}
}
+#endif
QT_END_NAMESPACE
diff --git a/src/platformsupport/vkconvenience/qvkconvenience_p.h b/src/platformsupport/vkconvenience/qvkconvenience_p.h
index 1dd1dfc4a7..580271b593 100644
--- a/src/platformsupport/vkconvenience/qvkconvenience_p.h
+++ b/src/platformsupport/vkconvenience/qvkconvenience_p.h
@@ -59,7 +59,9 @@ QT_BEGIN_NAMESPACE
class QVkConvenience
{
public:
+#if QT_CONFIG(opengl)
static VkFormat vkFormatFromGlFormat(uint glFormat);
+#endif
};
QT_END_NAMESPACE