diff options
Diffstat (limited to 'src/plugins')
31 files changed, 392 insertions, 191 deletions
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index 55847a04a4..2b38409723 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -430,7 +430,6 @@ QCoreWlanEngine::QCoreWlanEngine(QObject *parent) QCoreWlanEngine::~QCoreWlanEngine() { - scanThread->terminate(); scanThread->wait(); while (!foundConfigurations.isEmpty()) diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro index 3c3a4b4b2e..3ba817bf5b 100644 --- a/src/plugins/platforms/android/android.pro +++ b/src/plugins/platforms/android/android.pro @@ -8,12 +8,7 @@ DEFINES += QT_STATICPLUGIN load(qt_plugin) -!contains(ANDROID_PLATFORM, android-9) { - INCLUDEPATH += $$NDK_ROOT/platforms/android-9/arch-$$ANDROID_ARCHITECTURE/usr/include - LIBS += -L$$NDK_ROOT/platforms/android-9/arch-$$ANDROID_ARCHITECTURE/usr/lib -ljnigraphics -landroid -} else { - LIBS += -ljnigraphics -landroid -} +LIBS += -ljnigraphics -landroid QT += core-private gui-private platformsupport-private @@ -54,7 +49,7 @@ SOURCES += $$PWD/androidplatformplugin.cpp \ $$PWD/qandroideventdispatcher.cpp HEADERS += $$PWD/qandroidplatformintegration.h \ - $$PWD/androidandroiddeadlockprotector.h \ + $$PWD/androiddeadlockprotector.h \ $$PWD/androidjnimain.h \ $$PWD/androidjniaccessibility.h \ $$PWD/androidjniinput.h \ diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index aceb9b619b..0b46508782 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -100,7 +100,9 @@ void QCocoaMenuBar::insertNativeMenu(QCocoaMenu *menu, QCocoaMenu *beforeMenu) menu->setMenuBar(this); syncMenu(static_cast<QPlatformMenu *>(menu)); - [m_nativeMenu setSubmenu: menu->nsMenu() forItem: menu->nsMenuItem()]; + if (menu->isVisible()) { + [m_nativeMenu setSubmenu: menu->nsMenu() forItem: menu->nsMenuItem()]; + } } void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *before) diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 771b464805..5d3befa25b 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1824,6 +1824,8 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]); QWindow *target = findEventTargetWindow(m_window); + if (!target) + return NSDragOperationNone; // update these so selecting move/copy/link works QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers: [[NSApp currentEvent] modifierFlags]]; @@ -1843,6 +1845,8 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin - (void)draggingExited:(id <NSDraggingInfo>)sender { QWindow *target = findEventTargetWindow(m_window); + if (!target) + return; NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; QPoint qt_windowPoint(windowPoint.x, windowPoint.y); @@ -1855,6 +1859,8 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender { QWindow *target = findEventTargetWindow(m_window); + if (!target) + return false; NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; QPoint qt_windowPoint(windowPoint.x, windowPoint.y); @@ -1880,6 +1886,8 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin Q_UNUSED(img); Q_UNUSED(operation); QWindow *target = findEventTargetWindow(m_window); + if (!target) + return; // keep our state, and QGuiApplication state (buttons member) in-sync, // or future mouse events will be processed incorrectly diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp index 6216fa8575..6470280e2c 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -31,15 +31,16 @@ ** ****************************************************************************/ -#include "qeglfscontext.h" -#include "qeglfswindow.h" -#include "qeglfshooks.h" +#include <QtGui/QSurface> +#include <QtDebug> +#include <QtPlatformSupport/private/qeglplatformcursor_p.h> #include <QtPlatformSupport/private/qeglconvenience_p.h> #include <QtPlatformSupport/private/qeglpbuffer_p.h> -#include <QtPlatformSupport/private/qeglplatformcursor_p.h> -#include <QtGui/QSurface> -#include <QtDebug> + +#include "qeglfswindow.h" +#include "qeglfshooks.h" +#include "qeglfscontext.h" QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp index 26d77a2abb..120c603125 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp +++ b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp @@ -31,10 +31,10 @@ ** ****************************************************************************/ -#include "qeglfshooks.h" #include <QtPlatformSupport/private/qeglplatformcursor_p.h> #include <QtPlatformSupport/private/qeglconvenience_p.h> #include <QtCore/QRegularExpression> +#include "qeglfshooks.h" #if defined(Q_OS_LINUX) #include <fcntl.h> diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 2a4eae3fe2..fbdd1d4c4d 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -31,26 +31,26 @@ ** ****************************************************************************/ -#include "qeglfsintegration.h" +#include <QtCore/qtextstream.h> +#include <QtGui/private/qguiapplication_p.h> + +#include <qpa/qplatformwindow.h> +#include <QtGui/QSurfaceFormat> +#include <QtGui/QOpenGLContext> +#include <QtGui/QScreen> +#include <QtGui/QOffscreenSurface> +#include <qpa/qplatformcursor.h> +#include "qeglfsintegration.h" #include "qeglfswindow.h" #include "qeglfshooks.h" #include "qeglfscontext.h" -#include <QtGui/private/qguiapplication_p.h> - #include <QtPlatformSupport/private/qeglconvenience_p.h> #include <QtPlatformSupport/private/qeglplatformcontext_p.h> #include <QtPlatformSupport/private/qeglpbuffer_p.h> #include <QtPlatformHeaders/QEGLNativeContext> -#include <qpa/qplatformwindow.h> -#include <QtGui/QSurfaceFormat> -#include <QtGui/QOpenGLContext> -#include <QtGui/QScreen> -#include <QtGui/QOffscreenSurface> -#include <qpa/qplatformcursor.h> - #include <EGL/egl.h> static void initResources() diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp index cd68540581..bc93fe28e7 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -31,10 +31,12 @@ ** ****************************************************************************/ +#include <QtCore/qtextstream.h> +#include <QtPlatformSupport/private/qeglplatformcursor_p.h> + #include "qeglfsscreen.h" #include "qeglfswindow.h" #include "qeglfshooks.h" -#include <QtPlatformSupport/private/qeglplatformcursor_p.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index f5839e086d..39a3ef94e9 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -31,8 +31,7 @@ ** ****************************************************************************/ -#include "qeglfswindow.h" -#include "qeglfshooks.h" +#include <QtCore/qtextstream.h> #include <qpa/qwindowsysteminterface.h> #include <qpa/qplatformintegration.h> #include <private/qguiapplication_p.h> @@ -40,6 +39,9 @@ #include <QtPlatformSupport/private/qeglplatformcursor_p.h> #include <QtPlatformSupport/private/qeglconvenience_p.h> +#include "qeglfswindow.h" +#include "qeglfshooks.h" + #include <QtDebug> QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp b/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp index 906a1308da..d4bee2c9e4 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp +++ b/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp @@ -31,10 +31,10 @@ ** ****************************************************************************/ -#include "qminimaleglwindow.h" - #include <qpa/qwindowsysteminterface.h> +#include "qminimaleglwindow.h" + QT_BEGIN_NAMESPACE QMinimalEglWindow::QMinimalEglWindow(QWindow *w) diff --git a/src/plugins/platforms/windows/qtwindows_additional.h b/src/plugins/platforms/windows/qtwindows_additional.h index 9451b9ce55..4e77350132 100644 --- a/src/plugins/platforms/windows/qtwindows_additional.h +++ b/src/plugins/platforms/windows/qtwindows_additional.h @@ -166,4 +166,8 @@ typedef TOUCHINPUT const * PCTOUCHINPUT; #endif // if defined(Q_CC_MINGW) || !defined(TOUCHEVENTF_MOVE) +#ifndef WM_GESTURE +# define WM_GESTURE 0x0119 +#endif + #endif // QTWINDOWS_ADDITIONAL_H diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h index 90e6d6ab9d..083d82ed8c 100644 --- a/src/plugins/platforms/windows/qtwindowsglobal.h +++ b/src/plugins/platforms/windows/qtwindowsglobal.h @@ -109,6 +109,7 @@ enum WindowsEventType // Simplify event types DisplayChangedEvent = 437, SettingChangedEvent = DisplayChangedEvent + 1, ContextMenu = 123, + GestureEvent = 124, UnknownEvent = 542 }; @@ -247,6 +248,8 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI case WM_APPCOMMAND: return QtWindows::AppCommandEvent; #endif + case WM_GESTURE: + return QtWindows::GestureEvent; default: break; } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 99ba5463bf..72bfeec143 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -430,7 +430,7 @@ void QWindowsContext::setKeyGrabber(QWindow *w) // Window class registering code (from qapplication_win.cpp) -QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL) +QString QWindowsContext::registerWindowClass(const QWindow *w) { Q_ASSERT(w); const Qt::WindowFlags flags = w->flags(); @@ -438,7 +438,9 @@ QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL) // Determine style and icon. uint style = CS_DBLCLKS; bool icon = true; - if (isGL || (flags & Qt::MSWindowsOwnDC)) + // The following will not set CS_OWNDC for any widget window, even if it contains a + // QOpenGLWidget or QQuickWidget later on. That cannot be detected at this stage. + if (w->surfaceType() == QSurface::OpenGLSurface || (flags & Qt::MSWindowsOwnDC)) style |= CS_OWNDC; if (!(flags & Qt::NoDropShadowWindowHint) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based) && (type == Qt::Popup || w->property("_q_windowsDropShadow").toBool())) { @@ -471,8 +473,6 @@ QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL) default: break; } - if (isGL) - cname += QStringLiteral("GL"); if (style & CS_DROPSHADOW) cname += QStringLiteral("DropShadow"); if (style & CS_SAVEBITS) @@ -913,6 +913,8 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return QWindowsInputContext::instance()->endComposition(hwnd); case QtWindows::InputMethodRequest: return QWindowsInputContext::instance()->handleIME_Request(wParam, lParam, result); + case QtWindows::GestureEvent: + return d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result); case QtWindows::InputMethodOpenCandidateWindowEvent: case QtWindows::InputMethodCloseCandidateWindowEvent: // TODO: Release/regrab mouse if a popup has mouse grab. diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 28202219d6..5c2e21192b 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -161,7 +161,7 @@ public: int defaultDPI() const; - QString registerWindowClass(const QWindow *w, bool isGL); + QString registerWindowClass(const QWindow *w); QString registerWindowClass(QString cname, WNDPROC proc, unsigned style = 0, HBRUSH brush = 0, bool icon = false); diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index d10c7fdb20..9a42b7712d 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -126,13 +126,15 @@ HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, const QPoint & // Create a cursor from image and mask of the format QImage::Format_Mono. static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, - QPoint hotSpot = QPoint(), + QPoint hotSpot = QPoint(-1, -1), bool invb = false, bool invm = false) { const int width = bbits.width(); const int height = bbits.height(); - if (hotSpot.isNull()) - hotSpot = QPoint(width / 2, height / 2); + if (hotSpot.x() < 0) + hotSpot.setX(width / 2); + if (hotSpot.y() < 0) + hotSpot.setY(height / 2); const int n = qMax(1, width / 8); #if !defined(Q_OS_WINCE) QScopedArrayPointer<uchar> xBits(new uchar[height * n]); diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 7f0421ad90..f52c5b733c 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE QWindowsLibEGL QWindowsEGLStaticContext::libEGL; QWindowsLibGLESv2 QWindowsEGLStaticContext::libGLESv2; -#ifndef QT_STATIC +#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) #ifdef Q_CC_MINGW static void *resolveFunc(HMODULE lib, const char *name) @@ -111,7 +111,7 @@ void *QWindowsLibEGL::resolve(const char *name) #endif // !QT_STATIC -#ifndef QT_STATIC +#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) # define RESOLVE(signature, name) signature(resolve( #name )); #else # define RESOLVE(signature, name) signature(&::name); @@ -127,7 +127,7 @@ bool QWindowsLibEGL::init() qCDebug(lcQpaGl) << "Qt: Using EGL from" << dllName; -#ifndef QT_STATIC +#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16()); if (!m_lib) { qErrnoWarning(::GetLastError(), "Failed to load %s", dllName); @@ -159,7 +159,7 @@ bool QWindowsLibEGL::init() return eglGetError && eglGetDisplay && eglInitialize; } -#ifndef QT_STATIC +#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) void *QWindowsLibGLESv2::resolve(const char *name) { void *proc = m_lib ? resolveFunc(m_lib, name) : 0; @@ -179,7 +179,7 @@ bool QWindowsLibGLESv2::init() #endif qCDebug(lcQpaGl) << "Qt: Using OpenGL ES 2.0 from" << dllName; -#ifndef QT_STATIC +#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) m_lib = ::LoadLibraryW((const wchar_t *) QString::fromLatin1(dllName).utf16()); if (!m_lib) { qErrnoWarning(::GetLastError(), "Failed to load %s", dllName); @@ -577,6 +577,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api); QWindowsWindow *window = static_cast<QWindowsWindow *>(surface); + window->aboutToMakeCurrent(); EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig)); Q_ASSERT(eglSurface); diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h index 45ccbfb734..c2b153e4c1 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.h +++ b/src/plugins/platforms/windows/qwindowseglcontext.h @@ -75,7 +75,7 @@ struct QWindowsLibEGL __eglMustCastToProperFunctionPointerType (EGLAPIENTRY * eglGetProcAddress)(const char *procname); private: -#ifndef QT_STATIC +#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) void *resolve(const char *name); HMODULE m_lib; #endif @@ -84,7 +84,8 @@ private: struct QWindowsLibGLESv2 { bool init(); -#ifndef QT_STATIC + +#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) void *moduleHandle() const { return m_lib; } #else void *moduleHandle() const { return Q_NULLPTR; } @@ -239,7 +240,7 @@ struct QWindowsLibGLESv2 void (APIENTRY * glDepthRangef)(GLclampf nearVal, GLclampf farVal); private: -#ifndef QT_STATIC +#if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) void *resolve(const char *name); HMODULE m_lib; #endif diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index f15783490e..9c26a227b8 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -946,9 +946,8 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, } static int QT_WIN_CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, - int type, LPARAM namesSetIn) + int type, LPARAM) { - typedef QSet<QString> StringSet; const QString familyName = QString::fromWCharArray(f->elfLogFont.lfFaceName); const uchar charSet = f->elfLogFont.lfCharSet; @@ -957,83 +956,69 @@ static int QT_WIN_CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetr // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is // identical to a TEXTMETRIC except for the last four members, which we don't use // anyway - if (addFontToDatabase(familyName, charSet, (TEXTMETRIC *)textmetric, &signature, type)) - reinterpret_cast<StringSet *>(namesSetIn)->insert(familyName); + addFontToDatabase(familyName, charSet, (TEXTMETRIC *)textmetric, &signature, type); // keep on enumerating return 1; } -static int QT_WIN_CALLBACK storeFontSub(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, - int type, LPARAM namesSetIn) +void QWindowsFontDatabase::populateFamily(const QString &familyName) { - Q_UNUSED(textmetric) - Q_UNUSED(type) - + qCDebug(lcQpaFonts) << familyName; + if (familyName.size() >= LF_FACESIZE) { + qCWarning(lcQpaFonts) << "Unable to enumerate family '" << familyName << '\''; + return; + } HDC dummy = GetDC(0); LOGFONT lf; lf.lfCharSet = DEFAULT_CHARSET; - if (wcslen(f->elfLogFont.lfFaceName) >= LF_FACESIZE) { - qWarning("%s: Unable to enumerate family '%s'.", - __FUNCTION__, qPrintable(QString::fromWCharArray(f->elfLogFont.lfFaceName))); - return 1; - } - wmemcpy(lf.lfFaceName, f->elfLogFont.lfFaceName, - wcslen(f->elfLogFont.lfFaceName) + 1); + familyName.toWCharArray(lf.lfFaceName); + lf.lfFaceName[familyName.size()] = 0; lf.lfPitchAndFamily = 0; - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, - (LPARAM)namesSetIn, 0); + EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, 0, 0); ReleaseDC(0, dummy); - - // keep on enumerating - return 1; } -void QWindowsFontDatabase::populateFontDatabase() +namespace { +// Context for enumerating system fonts, records whether the default font has been encountered, +// which is normally not enumerated by EnumFontFamiliesEx(). +struct PopulateFamiliesContext { - m_families.clear(); - removeApplicationFonts(); - populate(); // Called multiple times. - // Work around EnumFontFamiliesEx() not listing the system font, see below. - const QString sysFontFamily = QGuiApplication::font().family(); - if (!m_families.contains(sysFontFamily)) - populate(sysFontFamily); -} - -/*! - \brief Populate font database using EnumFontFamiliesEx(). - - Normally, leaving the name empty should enumerate - all fonts, however, system fonts like "MS Shell Dlg 2" - are only found when specifying the name explicitly. -*/ + PopulateFamiliesContext(const QString &f) : systemDefaultFont(f), seenSystemDefaultFont(false) {} -void QWindowsFontDatabase::populate(const QString &family) - { + QString systemDefaultFont; + bool seenSystemDefaultFont; +}; +} // namespace - qCDebug(lcQpaFonts) << __FUNCTION__ << m_families.size() << family; +static int QT_WIN_CALLBACK populateFontFamilies(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *, int, LPARAM lparam) +{ + // the "@family" fonts are just the same as "family". Ignore them. + const wchar_t *faceNameW = f->elfLogFont.lfFaceName; + if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) { + const QString faceName = QString::fromWCharArray(faceNameW); + QPlatformFontDatabase::registerFontFamily(faceName); + PopulateFamiliesContext *context = reinterpret_cast<PopulateFamiliesContext *>(lparam); + if (!context->seenSystemDefaultFont && faceName == context->systemDefaultFont) + context->seenSystemDefaultFont = true; + } + return 1; // continue +} +void QWindowsFontDatabase::populateFontDatabase() +{ + removeApplicationFonts(); HDC dummy = GetDC(0); LOGFONT lf; lf.lfCharSet = DEFAULT_CHARSET; - if (family.size() >= LF_FACESIZE) { - qWarning("%s: Unable to enumerate family '%s'.", - __FUNCTION__, qPrintable(family)); - return; - } - wmemcpy(lf.lfFaceName, reinterpret_cast<const wchar_t*>(family.utf16()), - family.size() + 1); + lf.lfFaceName[0] = 0; lf.lfPitchAndFamily = 0; - - if (family.isEmpty()) { - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFontSub, - (LPARAM)&m_families, 0); - } else { - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, - (LPARAM)&m_families, 0); - } - + PopulateFamiliesContext context(QWindowsFontDatabase::systemDefaultFont().family()); + EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)populateFontFamilies, reinterpret_cast<LPARAM>(&context), 0); ReleaseDC(0, dummy); + // Work around EnumFontFamiliesEx() not listing the system font. + if (!context.seenSystemDefaultFont) + QPlatformFontDatabase::registerFontFamily(context.systemDefaultFont); } typedef QSharedPointer<QWindowsFontEngineData> QWindowsFontEngineDataPtr; @@ -1397,7 +1382,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, // Fonts based on files are added via populate, as they will show up in font enumeration. for (int j = 0; j < families.count(); ++j) - populate(families.at(j)); + populateFamily(families.at(j)); } m_applicationFonts << font; @@ -1677,7 +1662,7 @@ QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFon result.append(QWindowsFontDatabase::extraTryFontsForFamily(family)); qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint - << script << result << m_families.size(); + << script << result; return result; } diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h index 4abf2d703e..8a682e6bec 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h @@ -70,6 +70,7 @@ public: ~QWindowsFontDatabase(); void populateFontDatabase() Q_DECL_OVERRIDE; + void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; QFontEngineMulti *fontEngineMulti(QFontEngine *fontEngine, QChar::Script script) Q_DECL_OVERRIDE; QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE; @@ -99,9 +100,7 @@ public: static QString familyForStyleHint(QFont::StyleHint styleHint); private: - void populate(const QString &family = QString()); void removeApplicationFonts(); - QSet<QString> m_families; struct WinApplicationFont { HANDLE handle; diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 42e5a8c6ad..0fc5e0dc0c 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -375,31 +375,6 @@ static int QT_WIN_CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetr return 1; } -static int QT_WIN_CALLBACK storeFontSub(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric, - int type, LPARAM namesSetIn) -{ - Q_UNUSED(textmetric) - Q_UNUSED(type) - - HDC dummy = GetDC(0); - LOGFONT lf; - lf.lfCharSet = DEFAULT_CHARSET; - if (wcslen(f->elfLogFont.lfFaceName) >= LF_FACESIZE) { - qWarning("%s: Unable to enumerate family '%s'.", - __FUNCTION__, qPrintable(QString::fromWCharArray(f->elfLogFont.lfFaceName))); - return 1; - } - wmemcpy(lf.lfFaceName, f->elfLogFont.lfFaceName, - wcslen(f->elfLogFont.lfFaceName) + 1); - lf.lfPitchAndFamily = 0; - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, - (LPARAM)namesSetIn, 0); - ReleaseDC(0, dummy); - - // keep on enumerating - return 1; -} - void QWindowsFontDatabaseFT::populateFontDatabase() { m_families.clear(); @@ -434,15 +409,8 @@ void QWindowsFontDatabaseFT::populate(const QString &family) wmemcpy(lf.lfFaceName, reinterpret_cast<const wchar_t*>(family.utf16()), family.size() + 1); lf.lfPitchAndFamily = 0; - - if (family.isEmpty()) { - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFontSub, - (LPARAM)&m_families, 0); - } else { - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, - (LPARAM)&m_families, 0); - } - + EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, + (LPARAM)&m_families, 0); ReleaseDC(0, dummy); } diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp index 0e3e6826ec..3348241d37 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -1267,6 +1267,7 @@ bool QWindowsGLContext::makeCurrent(QPlatformSurface *surface) // Do we already have a DC entry for that window? QWindowsWindow *window = static_cast<QWindowsWindow *>(surface); + window->aboutToMakeCurrent(); const HWND hwnd = window->handle(); if (const QOpenGLContextData *contextData = findByHWND(m_windowContexts, hwnd)) { // Repeated calls to wglMakeCurrent when vsync is enabled in the driver will diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index acb692579b..0fa34041d6 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -422,11 +422,12 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND, } // from bool QApplicationPrivate::translateTouchEvent() -bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, +bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType, MSG msg, LRESULT *) { #ifndef Q_OS_WINCE + Q_UNUSED(hwnd); typedef QWindowSystemInterface::TouchPoint QTouchPoint; typedef QList<QWindowSystemInterface::TouchPoint> QTouchPointList; @@ -495,8 +496,87 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND, m_touchDevice, touchPoints); return true; -#else - return false; +#else //Q_OS_WINCE + GESTUREINFO gi; + memset(&gi, 0, sizeof(GESTUREINFO)); + gi.cbSize = sizeof(GESTUREINFO); + + if (!GetGestureInfo((HGESTUREINFO)msg.lParam, &gi)) + return false; + + const QPoint position = QPoint(gi.ptsLocation.x, gi.ptsLocation.y); + + if (gi.dwID != GID_DIRECTMANIPULATION) + return true; + static QPoint lastTouchPos; + const QRect screenGeometry = window->screen()->geometry(); + QWindowSystemInterface::TouchPoint touchPoint; + static QWindowSystemInterface::TouchPoint touchPoint2; + touchPoint.id = 0;//gi.dwInstanceID; + touchPoint.pressure = 1.0; + + if (gi.dwFlags & GF_BEGIN) + touchPoint.state = Qt::TouchPointPressed; + else if (gi.dwFlags & GF_END) + touchPoint.state = Qt::TouchPointReleased; + else if (gi.dwFlags == 0) + touchPoint.state = Qt::TouchPointMoved; + else + return true; + touchPoint2.pressure = 1.0; + touchPoint2.id = 1; + const QPoint winEventPosition = position; + const int deltaX = GID_DIRECTMANIPULATION_DELTA_X(gi.ullArguments); + const int deltaY = GID_DIRECTMANIPULATION_DELTA_Y(gi.ullArguments); + //Touch points are taken from the whole screen so map the position to the screen + const QPoint globalPosition = QWindowsGeometryHint::mapToGlobal(hwnd, winEventPosition); + const QPoint globalPosition2 = QWindowsGeometryHint::mapToGlobal(hwnd, QPoint(position.x() + deltaX, position.y() + deltaY)); + + touchPoint.normalPosition = + QPointF( (qreal)globalPosition.x() / screenGeometry.width(), (qreal)globalPosition.y() / screenGeometry.height() ); + + touchPoint.area.moveCenter(globalPosition); + + QList<QWindowSystemInterface::TouchPoint> pointList; + pointList.append(touchPoint); + if (deltaX != 0 && deltaY != 0) { + touchPoint2.state = m_had2ndTouchPoint ? Qt::TouchPointMoved : Qt::TouchPointPressed; + m_had2ndTouchPoint = true; + touchPoint2.normalPosition = + QPointF( (qreal)globalPosition2.x() / screenGeometry.width(), (qreal)globalPosition2.y() / screenGeometry.height() ); + + touchPoint2.area.moveCenter(globalPosition2); + lastTouchPos = globalPosition2; + pointList.append(touchPoint2); + } else if (m_had2ndTouchPoint) { + touchPoint2.normalPosition = + QPointF( (qreal)lastTouchPos.x() / screenGeometry.width(), (qreal)lastTouchPos.y() / screenGeometry.height() ); + + touchPoint2.area.moveCenter(lastTouchPos); + touchPoint2.state = Qt::TouchPointReleased; + pointList.append(touchPoint2); + m_had2ndTouchPoint = false; + } + + if (!m_touchDevice) { + m_touchDevice = new QTouchDevice; + // TODO: Device used to be hardcoded to screen in previous code. + m_touchDevice->setType(QTouchDevice::TouchScreen); + m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::Area | QTouchDevice::NormalizedPosition); + QWindowSystemInterface::registerTouchDevice(m_touchDevice); + } + + QWindowSystemInterface::handleTouchEvent(window, m_touchDevice, pointList); + // handle window focusing in/out + if (window != m_windowUnderMouse) { + if (m_windowUnderMouse) + QWindowSystemInterface::handleLeaveEvent(m_windowUnderMouse); + if (window) + QWindowSystemInterface::handleEnterEvent(window); + m_windowUnderMouse = window; + } + + return true; #endif } diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h index 6491de93b5..60fe26b2b9 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.h +++ b/src/plugins/platforms/windows/qwindowsmousehandler.h @@ -79,6 +79,10 @@ private: QTouchDevice *m_touchDevice; bool m_leftButtonDown; QWindow *m_previousCaptureWindow; +#ifdef Q_OS_WINCE +//This is required to send a touch up if we don't get a second touch position any more + bool m_had2ndTouchPoint; +#endif }; Qt::MouseButtons QWindowsMouseHandler::keyStateToMouseButtons(int wParam) diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index fd57d9ee61..ae8020a53e 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -497,4 +497,13 @@ bool QWindowsScreenManager::handleScreenChanges() return true; } +const QWindowsScreen *QWindowsScreenManager::screenAtDp(const QPoint &p) const +{ + foreach (QWindowsScreen *scr, m_screens) { + if (scr->geometryDp().contains(p)) + return scr; + } + return Q_NULLPTR; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index aa1408358b..28256f3000 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -137,6 +137,8 @@ public: bool handleDisplayChange(WPARAM wParam, LPARAM lParam); const WindowsScreenList &screens() const { return m_screens; } + const QWindowsScreen *screenAtDp(const QPoint &p) const; + private: void removeScreen(int index); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 926e7da67e..0216b40e3e 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -170,6 +170,25 @@ QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p) } #endif // !Q_OS_WINCE +// QTBUG-43872, for windows that do not have WS_EX_TOOLWINDOW set, WINDOWPLACEMENT +// is in workspace/available area coordinates. +static QPoint windowPlacementOffset(HWND hwnd, const QPoint &point) +{ +#ifndef Q_OS_WINCE + if (GetWindowLongPtr(hwnd, GWL_EXSTYLE) & WS_EX_TOOLWINDOW) + return QPoint(0, 0); + const QWindowsScreenManager &screenManager = QWindowsContext::instance()->screenManager(); + const QWindowsScreen *screen = screenManager.screens().size() == 1 + ? screenManager.screens().first() : screenManager.screenAtDp(point); + if (screen) + return screen->availableGeometryDp().topLeft() - screen->geometryDp().topLeft(); +#else + Q_UNUSED(hwnd) + Q_UNUSED(point) +#endif + return QPoint(0, 0); +} + // Return the frame geometry relative to the parent // if there is one. static inline QRect frameGeometry(HWND hwnd, bool topLevel) @@ -180,8 +199,10 @@ static inline QRect frameGeometry(HWND hwnd, bool topLevel) WINDOWPLACEMENT windowPlacement; windowPlacement.length = sizeof(WINDOWPLACEMENT); GetWindowPlacement(hwnd, &windowPlacement); - if (windowPlacement.showCmd == SW_SHOWMINIMIZED) - return qrectFromRECT(windowPlacement.rcNormalPosition); + if (windowPlacement.showCmd == SW_SHOWMINIMIZED) { + const QRect result = qrectFromRECT(windowPlacement.rcNormalPosition); + return result.translated(windowPlacementOffset(hwnd, result.topLeft())); + } } #endif // !Q_OS_WINCE GetWindowRect(hwnd, &rect); // Screen coordinates. @@ -206,6 +227,18 @@ static inline QSize clientSize(HWND hwnd) return qSizeOfRect(rect); } +static inline bool windowIsOpenGL(const QWindow *w) +{ + switch (w->surfaceType()) { + case QSurface::OpenGLSurface: + return true; + case QSurface::RasterGLSurface: + return qt_window_private(const_cast<QWindow *>(w))->compositing; + default: + return false; + } +} + static bool applyBlurBehindWindow(HWND hwnd) { #ifdef Q_OS_WINCE @@ -329,6 +362,17 @@ static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bo #endif // !Q_OS_WINCE } +static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::WindowFlags flags, qreal opacity) +{ + const bool isGL = windowIsOpenGL(w); + const bool hasAlpha = w->format().hasAlpha(); + + if (isGL && hasAlpha) + applyBlurBehindWindow(hwnd); + + setWindowOpacity(hwnd, flags, hasAlpha, isGL, opacity); +} + /*! \class WindowCreationData \brief Window creation code. @@ -370,14 +414,13 @@ struct WindowCreationData void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0); inline WindowData create(const QWindow *w, const WindowData &data, QString title) const; inline void applyWindowFlags(HWND hwnd) const; - void initialize(HWND h, bool frameChange, qreal opacityLevel) const; + void initialize(const QWindow *w, HWND h, bool frameChange, qreal opacityLevel) const; Qt::WindowFlags flags; HWND parentHandle; Qt::WindowType type; unsigned style; unsigned exStyle; - bool isGL; bool topLevel; bool popup; bool dialog; @@ -390,7 +433,7 @@ struct WindowCreationData QDebug operator<<(QDebug debug, const WindowCreationData &d) { debug.nospace() << QWindowsWindow::debugWindowFlags(d.flags) - << " GL=" << d.isGL << " topLevel=" << d.topLevel << " popup=" + << " topLevel=" << d.topLevel << " popup=" << d.popup << " dialog=" << d.dialog << " desktop=" << d.desktop << " embedded=" << d.embedded << " tool=" << d.tool << " style=" << debugWinStyle(d.style) @@ -421,8 +464,6 @@ static inline void fixTopLevelWindowFlags(Qt::WindowFlags &flags) void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flagsIn, unsigned creationFlags) { - isGL = w->surfaceType() == QWindow::OpenGLSurface; - hasAlpha = w->format().hasAlpha(); flags = flagsIn; // Sometimes QWindow doesn't have a QWindow parent but does have a native parent window, @@ -495,7 +536,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag // ### Commented out for now as it causes some problems, but // this should be correct anyway, so dig some more into this #ifdef Q_FLATTEN_EXPOSE - if (isGL) + if (windowIsOpenGL(w)) // a bit incorrect since the is-opengl status may change from false to true at any time later on style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN; // see SetPixelFormat #else style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN ; @@ -574,7 +615,7 @@ QWindowsWindowData const HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); - const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w, isGL); + const QString windowClassName = QWindowsContext::instance()->registerWindowClass(w); const QRect geometryDip = QWindowsScaling::mapFromNative(data.geometry); QRect fixedGeometryDip = QPlatformWindow::initialGeometry(w, geometryDip, defaultWindowWidth, defaultWindowHeight); @@ -603,6 +644,10 @@ QWindowsWindowData context->frameX, context->frameY, context->frameWidth, context->frameHeight, parentHandle, NULL, appinst, NULL); +#ifdef Q_OS_WINCE + if (DisableGestures(result.hwnd, TGF_GID_ALL, TGF_SCOPE_WINDOW)) + EnableGestures(result.hwnd, TGF_GID_DIRECTMANIPULATION, TGF_SCOPE_WINDOW); +#endif qCDebug(lcQpaWindows).nospace() << "CreateWindowEx: returns " << w << ' ' << result.hwnd << " obtained geometry: " << context->obtainedGeometry << context->margins; @@ -617,9 +662,6 @@ QWindowsWindowData result.embedded = embedded; result.customMargins = context->customMargins; - if (isGL && hasAlpha) - applyBlurBehindWindow(result.hwnd); - return result; } @@ -642,7 +684,7 @@ void WindowCreationData::applyWindowFlags(HWND hwnd) const << debugWinExStyle(newExStyle); } -void WindowCreationData::initialize(HWND hwnd, bool frameChange, qreal opacityLevel) const +void WindowCreationData::initialize(const QWindow *w, HWND hwnd, bool frameChange, qreal opacityLevel) const { if (desktop || !hwnd) return; @@ -667,8 +709,7 @@ void WindowCreationData::initialize(HWND hwnd, bool frameChange, qreal opacityLe else EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); } - - setWindowOpacity(hwnd, flags, hasAlpha, isGL, opacityLevel); + updateGLWindowSettings(w, hwnd, flags, opacityLevel); } else { // child. SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, swpFlags); } @@ -1051,7 +1092,7 @@ QWindowsWindowData creationData.fromWindow(w, parameters.flags); QWindowsWindowData result = creationData.create(w, parameters, title); // Force WM_NCCALCSIZE (with wParam=1) via SWP_FRAMECHANGED for custom margin. - creationData.initialize(result.hwnd, !parameters.customMargins.isNull(), 1); + creationData.initialize(w, result.hwnd, !parameters.customMargins.isNull(), 1); return result; } @@ -1287,8 +1328,10 @@ static QRect normalFrameGeometry(HWND hwnd) #ifndef Q_OS_WINCE WINDOWPLACEMENT wp; wp.length = sizeof(WINDOWPLACEMENT); - if (GetWindowPlacement(hwnd, &wp)) - return qrectFromRECT(wp.rcNormalPosition); + if (GetWindowPlacement(hwnd, &wp)) { + const QRect result = qrectFromRECT(wp.rcNormalPosition); + return result.translated(windowPlacementOffset(hwnd, result.topLeft())); + } #else Q_UNUSED(hwnd) #endif @@ -1313,7 +1356,8 @@ void QWindowsWindow::setGeometryDp(const QRect &rectIn) const QMargins margins = frameMarginsDp(); rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top())); } - m_data.geometry = rect; + if (m_windowState == Qt::WindowMinimized) + m_data.geometry = rect; // Otherwise set by handleGeometryChange() triggered by event. if (m_data.hwnd) { // A ResizeEvent with resulting geometry will be sent. If we cannot // achieve that size (for example, window title minimal constraint), @@ -1384,11 +1428,11 @@ void QWindowsWindow::handleGeometryChange() // QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive // expose events when shrinking, synthesize. if (!testFlag(OpenGL_ES2) && isExposed() - && !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) { + && !(m_data.geometry.width() >= previousGeometry.width() || m_data.geometry.height() >= previousGeometry.height())) { fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true); } if (previousGeometry.topLeft() != m_data.geometry.topLeft()) { - QPlatformScreen *newScreen = screenForGeometry(m_data.geometry); + QPlatformScreen *newScreen = screenForGeometry(geometryDip); if (newScreen != screen()) QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); } @@ -1417,7 +1461,8 @@ void QWindowsWindow::setGeometry_sys(const QRect &rect) const // window, set the normal position of the window. if ((windowPlacement.showCmd == SW_MAXIMIZE && !IsWindowVisible(m_data.hwnd)) || windowPlacement.showCmd == SW_SHOWMINIMIZED) { - windowPlacement.rcNormalPosition = RECTfromQRect(frameGeometry); + windowPlacement.rcNormalPosition = + RECTfromQRect(frameGeometry.translated(-windowPlacementOffset(m_data.hwnd, frameGeometry.topLeft()))); windowPlacement.showCmd = windowPlacement.showCmd == SW_SHOWMINIMIZED ? SW_SHOWMINIMIZED : SW_HIDE; result = SetWindowPlacement(m_data.hwnd, &windowPlacement); } else @@ -1538,7 +1583,7 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt, WindowCreationData creationData; creationData.fromWindow(window(), wt, flags); creationData.applyWindowFlags(m_data.hwnd); - creationData.initialize(m_data.hwnd, true, m_opacity); + creationData.initialize(window(), m_data.hwnd, true, m_opacity); QWindowsWindowData result = m_data; result.flags = creationData.flags; @@ -1626,17 +1671,6 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) setFlag(FrameDirty); - if ((oldState == Qt::WindowMaximized) != (newState == Qt::WindowMaximized)) { - if (visible && !(newState == Qt::WindowMinimized)) { - setFlag(WithinMaximize); - if (newState == Qt::WindowFullScreen) - setFlag(MaximizeToFullScreen); - ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE); - clearFlag(WithinMaximize); - clearFlag(MaximizeToFullScreen); - } - } - if ((oldState == Qt::WindowFullScreen) != (newState == Qt::WindowFullScreen)) { #ifdef Q_OS_WINCE HWND handle = FindWindow(L"HHTaskBar", L""); @@ -1716,6 +1750,15 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState) m_savedStyle = 0; m_savedFrameGeometry = QRect(); } + } else if ((oldState == Qt::WindowMaximized) != (newState == Qt::WindowMaximized)) { + if (visible && !(newState == Qt::WindowMinimized)) { + setFlag(WithinMaximize); + if (newState == Qt::WindowFullScreen) + setFlag(MaximizeToFullScreen); + ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE); + clearFlag(WithinMaximize); + clearFlag(MaximizeToFullScreen); + } } if ((oldState == Qt::WindowMinimized) != (newState == Qt::WindowMinimized)) { @@ -2313,4 +2356,22 @@ void *QWindowsWindow::surface(void *nativeConfig) #endif } +void QWindowsWindow::aboutToMakeCurrent() +{ +#ifndef QT_NO_OPENGL + // For RasterGLSurface windows, that become OpenGL windows dynamically, it might be + // time to set up some GL specifics. This is particularly important for layered + // windows (WS_EX_LAYERED due to alpha > 0). + const bool isCompositing = qt_window_private(window())->compositing; + if (isCompositing != testFlag(Compositing)) { + if (isCompositing) + setFlag(Compositing); + else + clearFlag(Compositing); + + updateGLWindowSettings(window(), m_data.hwnd, m_data.flags, m_opacity); + } +#endif +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 922d00f230..6d6d473ccd 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -137,7 +137,8 @@ public: WithinCreate = 0x20000, WithinMaximize = 0x40000, MaximizeToFullScreen = 0x80000, - InputMethodDisabled =0x100000 + InputMethodDisabled = 0x100000, + Compositing = 0x200000 }; QWindowsWindow(QWindow *window, const QWindowsWindowData &data); @@ -250,6 +251,7 @@ public: void setWindowIcon(const QIcon &icon); void *surface(void *nativeConfig); + void aboutToMakeCurrent(); #ifndef Q_OS_WINCE void setAlertState(bool enabled); diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 7286b6b89b..4d0596550c 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -506,6 +506,7 @@ private: XInput2TouchDeviceData *touchDeviceForId(int id); void xi2HandleEvent(xcb_ge_event_t *event); void xi2HandleHierachyEvent(void *event); + void xi2HandleDeviceChangedEvent(void *event); int m_xiOpCode, m_xiEventBase, m_xiErrorBase; #ifndef QT_NO_TABLETEVENT struct TabletData { @@ -539,6 +540,7 @@ private: Qt::Orientations legacyOrientations; QPointF lastScrollPosition; }; + void updateScrollingDevice(ScrollingDevice& scrollingDevice, int num_classes, void *classes); void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice); QHash<int, ScrollingDevice> m_scrollingDevices; #endif // XCB_USE_XINPUT2 diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 90d323ed34..60ae062586 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -346,6 +346,7 @@ void QXcbConnection::xi2Select(xcb_window_t window) // Listen for hotplug events XIEventMask xiEventMask; bitMask = XI_HierarchyChangedMask; + bitMask |= XI_DeviceChangedMask; xiEventMask.deviceid = XIAllDevices; xiEventMask.mask_len = sizeof(bitMask); xiEventMask.mask = xiBitMask; @@ -464,6 +465,11 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) xi2HandleHierachyEvent(xiEvent); return; } + if (xiEvent->evtype == XI_DeviceChanged) { + xi2HandleDeviceChangedEvent(xiEvent); + return; + } + #ifndef QT_NO_TABLETEVENT for (int i = 0; i < m_tabletData.count(); ++i) { if (m_tabletData.at(i).deviceId == xiEvent->deviceid) { @@ -624,6 +630,64 @@ void QXcbConnection::xi2HandleHierachyEvent(void *event) } } +void QXcbConnection::xi2HandleDeviceChangedEvent(void *event) +{ + xXIDeviceChangedEvent *xiEvent = reinterpret_cast<xXIDeviceChangedEvent *>(event); + + // ### If a slave device changes (XIDeviceChange), we should probably run setup on it again. + if (xiEvent->reason != XISlaveSwitch) + return; + +#ifdef XCB_USE_XINPUT21 + // This code handles broken scrolling device drivers that reset absolute positions + // when they are made active. Whenever a new slave device is made active the + // primary pointer sends a DeviceChanged event with XISlaveSwitch, and the new + // active slave in sourceid. + + QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(xiEvent->sourceid); + if (device == m_scrollingDevices.end()) + return; + + int nrDevices = 0; + XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), xiEvent->sourceid, &nrDevices); + if (nrDevices <= 0) { + qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", xiEvent->sourceid); + return; + } + updateScrollingDevice(*device, xiDeviceInfo->num_classes, xiDeviceInfo->classes); + XIFreeDeviceInfo(xiDeviceInfo); +#endif +} + +void QXcbConnection::updateScrollingDevice(ScrollingDevice &scrollingDevice, int num_classes, void *classInfo) +{ +#ifdef XCB_USE_XINPUT21 + XIAnyClassInfo **classes = reinterpret_cast<XIAnyClassInfo**>(classInfo); + QPointF lastScrollPosition; + if (lcQpaXInput().isDebugEnabled()) + lastScrollPosition = scrollingDevice.lastScrollPosition; + for (int c = 0; c < num_classes; ++c) { + if (classes[c]->type == XIValuatorClass) { + XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classes[c]); + const int valuatorAtom = qatom(vci->label); + if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel) + scrollingDevice.lastScrollPosition.setX(vci->value); + else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel) + scrollingDevice.lastScrollPosition.setY(vci->value); + } + } + if (lcQpaXInput().isDebugEnabled() && lastScrollPosition != scrollingDevice.lastScrollPosition) + qCDebug(lcQpaXInput, "scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId, + lastScrollPosition.x(), lastScrollPosition.y(), + scrollingDevice.lastScrollPosition.x(), + scrollingDevice.lastScrollPosition.y()); +#else + Q_UNUSED(scrollingDevice); + Q_UNUSED(num_classes); + Q_UNUSED(classInfo); +#endif +} + void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *) { #ifdef XCB_USE_XINPUT21 @@ -634,19 +698,11 @@ void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *) int nrDevices = 0; XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), scrollingDevice.deviceId, &nrDevices); if (nrDevices <= 0) { + qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", scrollingDevice.deviceId); it = m_scrollingDevices.erase(it); continue; } - for (int c = 0; c < xiDeviceInfo->num_classes; ++c) { - if (xiDeviceInfo->classes[c]->type == XIValuatorClass) { - XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(xiDeviceInfo->classes[c]); - const int valuatorAtom = qatom(vci->label); - if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel) - scrollingDevice.lastScrollPosition.setX(vci->value); - else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel) - scrollingDevice.lastScrollPosition.setY(vci->value); - } - } + updateScrollingDevice(scrollingDevice, xiDeviceInfo->num_classes, xiDeviceInfo->classes); XIFreeDeviceInfo(xiDeviceInfo); ++it; } diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 5fb745717b..85fef3912c 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -933,7 +933,7 @@ xkb_keysym_t QXcbKeyboard::lookupLatinKeysym(xkb_keycode_t keycode) const QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const { // turn off the modifier bits which doesn't participate in shortcuts - Qt::KeyboardModifiers notNeeded = Qt::MetaModifier | Qt::KeypadModifier | Qt::GroupSwitchModifier; + Qt::KeyboardModifiers notNeeded = Qt::KeypadModifier | Qt::GroupSwitchModifier; Qt::KeyboardModifiers modifiers = event->modifiers() &= ~notNeeded; // create a fresh kb state and test against the relevant modifier combinations struct xkb_state *kb_state = xkb_state_new(xkb_keymap); @@ -963,10 +963,12 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const xkb_mod_index_t shiftMod = xkb_keymap_mod_get_index(xkb_keymap, "Shift"); xkb_mod_index_t altMod = xkb_keymap_mod_get_index(xkb_keymap, "Alt"); xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control"); + xkb_mod_index_t metaMod = xkb_keymap_mod_get_index(xkb_keymap, "Meta"); Q_ASSERT(shiftMod < 32); Q_ASSERT(altMod < 32); Q_ASSERT(controlMod < 32); + Q_ASSERT(metaMod < 32); xkb_mod_mask_t depressed; int qtKey = 0; @@ -987,6 +989,8 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const depressed |= (1 << shiftMod); if (neededMods & Qt::ControlModifier) depressed |= (1 << controlMod); + if (neededMods & Qt::MetaModifier) + depressed |= (1 << metaMod); xkb_state_update_mask(kb_state, depressed, latchedMods, lockedMods, 0, 0, lockedLayout); sym = xkb_state_key_get_one_sym(kb_state, keycode); } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 00942787d9..233514a181 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -767,6 +767,9 @@ void QXcbWindow::show() if (connection()->time() != XCB_TIME_CURRENT_TIME) updateNetWmUserTime(connection()->time()); + if (window()->objectName() == QLatin1String("QSystemTrayIconSysWindow")) + return; // defer showing until XEMBED_EMBEDDED_NOTIFY + Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); if (QGuiApplication::modalWindow() == window()) @@ -2350,7 +2353,10 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event) switch (event->data.data32[1]) { case XEMBED_WINDOW_ACTIVATE: case XEMBED_WINDOW_DEACTIVATE: + break; case XEMBED_EMBEDDED_NOTIFY: + Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window)); + m_screen->windowShown(this); break; case XEMBED_FOCUS_IN: Qt::FocusReason reason; |