diff options
Diffstat (limited to 'src/plugins/platforms')
36 files changed, 761 insertions, 242 deletions
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 780be644e7..fb7b615ee1 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1830,6 +1830,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]]; @@ -1849,6 +1851,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); @@ -1861,6 +1865,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); @@ -1886,6 +1892,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 7054c90521..4bda09653f 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/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 80a029c27f..a13a334433 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -31,27 +31,27 @@ ** ****************************************************************************/ -#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 "qeglfsoffscreenwindow.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 84ea1c6483..cb726a016b 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -31,10 +31,12 @@ ** ****************************************************************************/ +#include <QtCore/qtextstream.h> +#include <QtGui/qpa/qplatformcursor.h> + #include "qeglfsscreen.h" #include "qeglfswindow.h" #include "qeglfshooks.h" -#include <QtGui/qpa/qplatformcursor.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index d568d50e59..8a61bcf30d 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -31,14 +31,17 @@ ** ****************************************************************************/ -#include "qeglfswindow.h" -#include "qeglfshooks.h" +#include <QtCore/qtextstream.h> #include <qpa/qwindowsysteminterface.h> #include <qpa/qplatformintegration.h> #include <private/qguiapplication_p.h> #include <QtGui/QOpenGLContext> #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 13a3d044a0..c253a9605b 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) @@ -676,7 +676,7 @@ static inline bool findPlatformWindowHelper(const POINT &screenPoint, unsigned c const HWND child = ChildWindowFromPointEx(*hwnd, point, cwexFlags); #else Q_UNUSED(cwexFlags) - const HWND child = ChildWindowFromPoint(*hwnd, point); + const HWND child = WindowFromPoint(point); #endif if (!child || child == *hwnd) return false; @@ -905,6 +905,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/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 0872741e47..b71497b176 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); @@ -340,7 +340,7 @@ QWindowsEGLStaticContext::QWindowsEGLStaticContext(EGLDisplay display, int versi { } -QWindowsEGLStaticContext *QWindowsEGLStaticContext::create() +QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester::Renderers preferredType) { const HDC dc = QWindowsContext::instance()->displayContext(); if (!dc){ @@ -358,28 +358,34 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create() } EGLDisplay display = EGL_NO_DISPLAY; + EGLint major = 0; + EGLint minor = 0; #ifdef EGL_ANGLE_platform_angle_opengl - if (libEGL.eglGetPlatformDisplayEXT && qEnvironmentVariableIsSet("QT_ANGLE_PLATFORM")) { + if (libEGL.eglGetPlatformDisplayEXT + && (preferredType & QWindowsOpenGLTester::AngleBackendMask)) { const EGLint anglePlatformAttributes[][5] = { { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE }, { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE }, { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_TRUE, EGL_NONE } }; const EGLint *attributes = 0; - const QByteArray anglePlatform = qgetenv("QT_ANGLE_PLATFORM"); - if (anglePlatform == "d3d11") + if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11) attributes = anglePlatformAttributes[0]; - else if (anglePlatform == "d3d9") + else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d9) attributes = anglePlatformAttributes[1]; - else if (anglePlatform == "warp") + else if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11Warp) attributes = anglePlatformAttributes[2]; - else - qCWarning(lcQpaGl) << "Invalid value set for QT_ANGLE_PLATFORM:" << anglePlatform; - - if (attributes) + if (attributes) { display = libEGL.eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, dc, attributes); + if (!libEGL.eglInitialize(display, &major, &minor)) { + display = EGL_NO_DISPLAY; + major = minor = 0; + } + } } -#endif // EGL_ANGLE_platform_angle_opengl +#else // EGL_ANGLE_platform_angle_opengl + Q_UNUSED(preferredType) +#endif if (display == EGL_NO_DISPLAY) display = libEGL.eglGetDisplay((EGLNativeDisplayType)dc); if (!display) { @@ -387,9 +393,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create() return 0; } - EGLint major; - EGLint minor; - if (!libEGL.eglInitialize(display, &major, &minor)) { + if (!major && !libEGL.eglInitialize(display, &major, &minor)) { int err = libEGL.eglGetError(); qWarning("%s: Could not initialize EGL display: error 0x%x\n", Q_FUNC_INFO, err); if (err == 0x3001) @@ -573,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 63a7c25a6f..c2b153e4c1 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.h +++ b/src/plugins/platforms/windows/qwindowseglcontext.h @@ -35,6 +35,7 @@ #define QWINDOWSEGLCONTEXT_H #include "qwindowsopenglcontext.h" +#include "qwindowsopengltester.h" #include <EGL/egl.h> QT_BEGIN_NAMESPACE @@ -74,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 @@ -83,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; } @@ -238,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 @@ -249,7 +251,7 @@ class QWindowsEGLStaticContext : public QWindowsStaticOpenGLContext Q_DISABLE_COPY(QWindowsEGLStaticContext) public: - static QWindowsEGLStaticContext *create(); + static QWindowsEGLStaticContext *create(QWindowsOpenGLTester::Renderers preferredType); ~QWindowsEGLStaticContext(); EGLDisplay display() const { return m_display; } diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 724d0e7aaf..91bc4c64a5 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -932,9 +932,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; @@ -943,79 +942,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; - memset(&lf, 0, sizeof(LOGFONT)); lf.lfCharSet = DEFAULT_CHARSET; - memcpy(lf.lfFaceName, f->elfLogFont.lfFaceName, LF_FACESIZE * sizeof(wchar_t)); + 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; - memset(&lf, 0, sizeof(LOGFONT)); lf.lfCharSet = DEFAULT_CHARSET; - if (family.size() >= LF_FACESIZE) { - qWarning("%s: Unable to enumerate family '%s'.", - __FUNCTION__, qPrintable(family)); - return; - } - + lf.lfFaceName[0] = 0; lf.lfPitchAndFamily = 0; - - if (family.isEmpty()) { - EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFontSub, - (LPARAM)&m_families, 0); - } else { - memcpy(lf.lfFaceName, family.utf16(), family.size() * sizeof(wchar_t)); - 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; @@ -1379,7 +1368,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; @@ -1663,7 +1652,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 aa48fb2b08..eb6273b835 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 f562b82a2c..c3bfd9825f 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -483,26 +483,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; - memset(&lf, 0, sizeof(LOGFONT)); - lf.lfCharSet = DEFAULT_CHARSET; - memcpy(lf.lfFaceName, f->elfLogFont.lfFaceName, LF_FACESIZE * sizeof(wchar_t)); - 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(); @@ -528,7 +508,6 @@ void QWindowsFontDatabaseFT::populate(const QString &family) HDC dummy = GetDC(0); LOGFONT lf; - memset(&lf, 0, sizeof(LOGFONT)); lf.lfCharSet = DEFAULT_CHARSET; if (family.size() >= LF_FACESIZE) { qWarning("%s: Unable to enumerate family '%s'.", @@ -536,16 +515,12 @@ void QWindowsFontDatabaseFT::populate(const QString &family) return; } + 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 { - memcpy(lf.lfFaceName, family.utf16(), family.size() * sizeof(wchar_t)); - 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 786a662287..e71b101125 100644 --- a/src/plugins/platforms/windows/qwindowsglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp @@ -1305,6 +1305,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/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index d8e4900780..32074fd9b1 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -209,7 +209,7 @@ void QWindowsInputContext::setFocusObject(QObject *object) imeNotifyCancelComposition(m_compositionContext.hwnd); const QWindow *window = QGuiApplication::focusWindow(); - if (object && window) { + if (object && window && window->handle()) { QWindowsWindow *platformWindow = QWindowsWindow::baseWindowOf(window); if (inputMethodAccepted()) { // Re-enable IME by associating default context saved on first disabling. diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 54fb138d85..58d675876b 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -130,7 +130,6 @@ struct QWindowsIntegrationPrivate { explicit QWindowsIntegrationPrivate(const QStringList ¶mList); ~QWindowsIntegrationPrivate(); - bool ensureStaticOpenGLContext(); unsigned m_options; QWindowsContext m_context; @@ -266,7 +265,9 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co case OpenGL: return true; case ThreadedOpenGL: - return d->ensureStaticOpenGLContext() ? d->m_staticOpenGLContext->supportsThreadedOpenGL() : false; + if (const QWindowsStaticOpenGLContext *glContext = QWindowsIntegration::staticOpenGLContext()) + return glContext->supportsThreadedOpenGL(); + return false; #endif // !QT_NO_OPENGL case WindowMasks: return true; @@ -312,11 +313,6 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const QWindowSystemInterface::handleGeometryChange(window, QWindowsScaling::mapFromNative(obtained.geometry)); } -#ifndef QT_NO_OPENGL - d->ensureStaticOpenGLContext(); - obtained.staticOpenGLContext = d->m_staticOpenGLContext; -#endif // QT_NO_OPENGL - return obtained; } @@ -328,61 +324,65 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons } #ifndef QT_NO_OPENGL -static QWindowsStaticOpenGLContext *q_staticOpenGLContext = 0; -QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::create() +QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::doCreate() { - QWindowsStaticOpenGLContext *ctx = 0; - #if defined(QT_OPENGL_DYNAMIC) - const QByteArray requested = qgetenv("QT_OPENGL"); // angle, desktop, software - const bool angleRequested = QCoreApplication::testAttribute(Qt::AA_UseOpenGLES) || requested == "angle"; - const bool desktopRequested = QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL) || requested == "desktop"; - const bool softwareRequested = QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL) || requested == "software"; - + QWindowsOpenGLTester::Renderer requestedRenderer = QWindowsOpenGLTester::requestedRenderer(); + switch (requestedRenderer) { + case QWindowsOpenGLTester::DesktopGl: + if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) + return glCtx; + qCWarning(lcQpaGl, "System OpenGL failed. Falling back to Software OpenGL."); + return QOpenGLStaticContext::create(true); // If ANGLE is requested, use it, don't try anything else. - if (angleRequested) { - ctx = QWindowsEGLStaticContext::create(); - } else { - // If opengl32.dll seems to be OpenGL 2.x capable, or desktop OpenGL is requested, use it. - if (!softwareRequested && (desktopRequested || QWindowsOpenGLTester::testDesktopGL())) - ctx = QOpenGLStaticContext::create(); - // If failed and desktop OpenGL is not explicitly requested, try ANGLE. - if (!ctx && !desktopRequested && !softwareRequested) - ctx = QWindowsEGLStaticContext::create(); - // Try software. - if (!ctx) { - ctx = QOpenGLStaticContext::create(true); - // If software was explicitly requested but failed, try the regular one. - if (!ctx && softwareRequested && QWindowsOpenGLTester::testDesktopGL()) { - qCWarning(lcQpaGl, "Software OpenGL failed. Falling back to system OpenGL."); - ctx = QOpenGLStaticContext::create(); - } - } + case QWindowsOpenGLTester::AngleRendererD3d9: + case QWindowsOpenGLTester::AngleRendererD3d11: + case QWindowsOpenGLTester::AngleRendererD3d11Warp: + return QWindowsEGLStaticContext::create(requestedRenderer); + case QWindowsOpenGLTester::Gles: + return QWindowsEGLStaticContext::create(QWindowsOpenGLTester::supportedGlesRenderers()); + case QWindowsOpenGLTester::SoftwareRasterizer: + if (QWindowsStaticOpenGLContext *swCtx = QOpenGLStaticContext::create(true)) + return swCtx; + qCWarning(lcQpaGl, "Software OpenGL failed. Falling back to system OpenGL."); + if (QWindowsOpenGLTester::supportedRenderers() & QWindowsOpenGLTester::DesktopGl) + return QOpenGLStaticContext::create(); + return Q_NULLPTR; + default: + break; + } + + const QWindowsOpenGLTester::Renderers supportedRenderers = QWindowsOpenGLTester::supportedRenderers(); + if (supportedRenderers & QWindowsOpenGLTester::DesktopGl) { + if (QWindowsStaticOpenGLContext *glCtx = QOpenGLStaticContext::create()) + return glCtx; + } + if (QWindowsOpenGLTester::Renderers glesRenderers = supportedRenderers & QWindowsOpenGLTester::GlesMask) { + if (QWindowsEGLStaticContext *eglCtx = QWindowsEGLStaticContext::create(glesRenderers)) + return eglCtx; } + return QOpenGLStaticContext::create(true); #elif defined(QT_OPENGL_ES_2) - ctx = QWindowsEGLStaticContext::create(); + QWindowsOpenGLTester::Renderers glesRenderers = QWindowsOpenGLTester::requestedGlesRenderer(); + if (glesRenderers == QWindowsOpenGLTester::InvalidRenderer) + glesRenderers = QWindowsOpenGLTester::supportedGlesRenderers(); + return QWindowsEGLStaticContext::create(glesRenderers); #elif !defined(QT_NO_OPENGL) - ctx = QOpenGLStaticContext::create(); + return QOpenGLStaticContext::create(); #endif - - q_staticOpenGLContext = ctx; - - return ctx; } -bool QWindowsIntegrationPrivate::ensureStaticOpenGLContext() +QWindowsStaticOpenGLContext *QWindowsStaticOpenGLContext::create() { - if (m_staticOpenGLContext.isNull()) - m_staticOpenGLContext = QSharedPointer<QWindowsStaticOpenGLContext>(QWindowsStaticOpenGLContext::create()); - return !m_staticOpenGLContext.isNull(); + return QWindowsStaticOpenGLContext::doCreate(); } QPlatformOpenGLContext *QWindowsIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { qCDebug(lcQpaGl) << __FUNCTION__ << context->format(); - if (d->ensureStaticOpenGLContext()) { - QScopedPointer<QWindowsOpenGLContext> result(d->m_staticOpenGLContext->createContext(context)); + if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) { + QScopedPointer<QWindowsOpenGLContext> result(staticOpenGLContext->createContext(context)); if (result->isValid()) return result.take(); } @@ -396,13 +396,18 @@ QOpenGLContext::OpenGLModuleType QWindowsIntegration::openGLModuleType() #elif !defined(QT_OPENGL_DYNAMIC) return QOpenGLContext::LibGL; #else - return d->ensureStaticOpenGLContext() ? d->m_staticOpenGLContext->moduleType() : QOpenGLContext::LibGL; + if (const QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) + return staticOpenGLContext->moduleType(); + return QOpenGLContext::LibGL; #endif } QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext() { - return q_staticOpenGLContext; + QWindowsIntegrationPrivate *d = QWindowsIntegration::instance()->d.data(); + if (d->m_staticOpenGLContext.isNull()) + d->m_staticOpenGLContext = QSharedPointer<QWindowsStaticOpenGLContext>(QWindowsStaticOpenGLContext::create()); + return d->m_staticOpenGLContext.data(); } #endif // !QT_NO_OPENGL 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/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index bd5022505f..b2f853f3e6 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -35,6 +35,7 @@ #include "qwindowswindow.h" #include "qwindowscontext.h" #include "qwindowsopenglcontext.h" +#include "qwindowsopengltester.h" #include "qwindowsintegration.h" #include "qwindowsmime.h" @@ -223,4 +224,9 @@ QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &fun return Q_NULLPTR; } +QVariant QWindowsNativeInterface::gpu() const +{ + return GpuDescription::detect().toVariant(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index 9b2ac00986..5c9e15fa35 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -58,6 +58,7 @@ class QWindowsNativeInterface : public QPlatformNativeInterface { Q_OBJECT Q_PROPERTY(bool asyncExpose READ asyncExpose WRITE setAsyncExpose) + Q_PROPERTY(QVariant gpu READ gpu STORED false) public: void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE; @@ -81,6 +82,8 @@ public: bool asyncExpose() const; void setAsyncExpose(bool value); + QVariant gpu() const; + QVariantMap windowProperties(QPlatformWindow *window) const Q_DECL_OVERRIDE; QVariant windowProperty(QPlatformWindow *window, const QString &name) const Q_DECL_OVERRIDE; QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h index 2f724f3dd7..550bf00a40 100644 --- a/src/plugins/platforms/windows/qwindowsopenglcontext.h +++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h @@ -58,6 +58,9 @@ public: // reimplement these. virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/) { return 0; } virtual void destroyWindowSurface(void * /*nativeSurface*/) { } + +private: + static QWindowsStaticOpenGLContext *doCreate(); }; class QWindowsOpenGLContext : public QPlatformOpenGLContext diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index ba3a95ce7a..f6caf8b06e 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -32,13 +32,231 @@ ****************************************************************************/ #include "qwindowsopengltester.h" -#include "qt_windows.h" #include "qwindowscontext.h" +#include <QtCore/QVariantMap> +#include <QtCore/QDebug> +#include <QtCore/QTextStream> +#include <QtCore/QCoreApplication> + +#ifndef Q_OS_WINCE +# include <QtCore/qt_windows.h> +# include <private/qsystemlibrary_p.h> +# include <d3d9.h> +# include <GL/gl.h> +#endif + QT_BEGIN_NAMESPACE +QString GpuDriverVersion::toString() const +{ + return QString::number(product) + + QLatin1Char('.') + QString::number(version) + + QLatin1Char('.') + QString::number(subVersion) + + QLatin1Char('.') + QString::number(build); +} + +int GpuDriverVersion::compare(const GpuDriverVersion &rhs) const +{ + if (product < rhs.product) + return -1; + if (product > rhs.product) + return 1; + if (version < rhs.version) + return -1; + if (version > rhs.version) + return 1; + if (subVersion < rhs.subVersion) + return -1; + if (subVersion > rhs.subVersion) + return 1; + if (build < rhs.build) + return -1; + if (build > rhs.build) + return 1; + return 0; +} + +GpuDescription GpuDescription::detect() +{ +#ifndef Q_OS_WINCE + typedef IDirect3D9 * (WINAPI *PtrDirect3DCreate9)(UINT); + + GpuDescription result; + QSystemLibrary d3d9lib(QStringLiteral("d3d9")); + if (!d3d9lib.load()) + return result; + PtrDirect3DCreate9 direct3DCreate9 = (PtrDirect3DCreate9)d3d9lib.resolve("Direct3DCreate9"); + if (!direct3DCreate9) + return result; + IDirect3D9 *direct3D9 = direct3DCreate9(D3D_SDK_VERSION); + if (!direct3D9) + return result; + D3DADAPTER_IDENTIFIER9 adapterIdentifier; + const HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier); + direct3D9->Release(); + if (SUCCEEDED(hr)) { + result.vendorId = int(adapterIdentifier.VendorId); + result.deviceId = int(adapterIdentifier.DeviceId); + result.revision = int(adapterIdentifier.Revision); + result.subSysId = int(adapterIdentifier.SubSysId); + result.driverVersion.product = HIWORD(adapterIdentifier.DriverVersion.HighPart); + result.driverVersion.version = LOWORD(adapterIdentifier.DriverVersion.HighPart); + result.driverVersion.subVersion = HIWORD(adapterIdentifier.DriverVersion.LowPart); + result.driverVersion.build = LOWORD(adapterIdentifier.DriverVersion.LowPart); + result.driverName = adapterIdentifier.Driver; + result.description = adapterIdentifier.Description; + } + return result; +#else // !Q_OS_WINCE + GpuDescription result; + result.vendorId = result.deviceId = result.revision + = result.driverVersion.product = result.driverVersion.version + = result.driverVersion.build = 1; + result.driverName = result.description = QByteArrayLiteral("Generic"); + return result; +#endif +} + +QDebug operator<<(QDebug d, const GpuDriverVersion &v) +{ + QDebugStateSaver s(d); + d.nospace(); + d << v.product << '.' << v.version << '.' << v.subVersion << '.' << v.build; + return d; +} + +QDebug operator<<(QDebug d, const GpuDescription &gd) +{ + QDebugStateSaver s(d); + d.nospace(); + d << hex << showbase << "GpuDescription(vendorId=" << gd.vendorId + << ", deviceId=" << gd.deviceId << ", subSysId=" << gd.subSysId + << dec << noshowbase << ", revision=" << gd.revision + << ", driver: " << gd.driverName + << ", version=" << gd.driverVersion << ", " << gd.description << ')'; + return d; +} + +// Return printable string formatted like the output of the dxdiag tool. +QString GpuDescription::toString() const +{ + QString result; + QTextStream str(&result); + str << " Card name: " << description + << "\n Driver Name: " << driverName + << "\n Driver Version: " << driverVersion.toString() + << "\n Vendor ID: 0x" << qSetPadChar(QLatin1Char('0')) + << uppercasedigits << hex << qSetFieldWidth(4) << vendorId + << "\n Device ID: 0x" << qSetFieldWidth(4) << deviceId + << "\n SubSys ID: 0x" << qSetFieldWidth(8) << subSysId + << "\n Revision ID: 0x" << qSetFieldWidth(4) << revision + << dec; + return result; +} + +QVariant GpuDescription::toVariant() const +{ + QVariantMap result; + result.insert(QStringLiteral("vendorId"), QVariant(vendorId)); + result.insert(QStringLiteral("deviceId"), QVariant(deviceId)); + result.insert(QStringLiteral("subSysId"),QVariant(subSysId)); + result.insert(QStringLiteral("revision"), QVariant(revision)); + result.insert(QStringLiteral("driver"), QVariant(QLatin1String(driverName))); + result.insert(QStringLiteral("driverProduct"), QVariant(driverVersion.product)); + result.insert(QStringLiteral("driverVersion"), QVariant(driverVersion.version)); + result.insert(QStringLiteral("driverSubVersion"), QVariant(driverVersion.subVersion)); + result.insert(QStringLiteral("driverBuild"), QVariant(driverVersion.build)); + result.insert(QStringLiteral("driverVersionString"), driverVersion.toString()); + result.insert(QStringLiteral("description"), QVariant(QLatin1String(description))); + result.insert(QStringLiteral("printable"), QVariant(toString())); + return result; +} + +QWindowsOpenGLTester::Renderer QWindowsOpenGLTester::requestedGlesRenderer() +{ +#ifndef Q_OS_WINCE + const char platformVar[] = "QT_ANGLE_PLATFORM"; + if (qEnvironmentVariableIsSet(platformVar)) { + const QByteArray anglePlatform = qgetenv(platformVar); + if (anglePlatform == "d3d11") + return QWindowsOpenGLTester::AngleRendererD3d11; + if (anglePlatform == "d3d9") + return QWindowsOpenGLTester::AngleRendererD3d9; + if (anglePlatform == "warp") + return QWindowsOpenGLTester::AngleRendererD3d11Warp; + qCWarning(lcQpaGl) << "Invalid value set for " << platformVar << ": " << anglePlatform; + } +#endif // !Q_OS_WINCE + return QWindowsOpenGLTester::InvalidRenderer; +} + +QWindowsOpenGLTester::Renderer QWindowsOpenGLTester::requestedRenderer() +{ +#ifndef Q_OS_WINCE + const char openGlVar[] = "QT_OPENGL"; + if (QCoreApplication::testAttribute(Qt::AA_UseOpenGLES)) { + const Renderer glesRenderer = QWindowsOpenGLTester::requestedGlesRenderer(); + return glesRenderer != InvalidRenderer ? glesRenderer : Gles; + } + if (QCoreApplication::testAttribute(Qt::AA_UseDesktopOpenGL)) + return QWindowsOpenGLTester::DesktopGl; + if (QCoreApplication::testAttribute(Qt::AA_UseSoftwareOpenGL)) + return QWindowsOpenGLTester::SoftwareRasterizer; + if (qEnvironmentVariableIsSet(openGlVar)) { + const QByteArray requested = qgetenv(openGlVar); + if (requested == "angle") { + const Renderer glesRenderer = QWindowsOpenGLTester::requestedGlesRenderer(); + return glesRenderer != InvalidRenderer ? glesRenderer : Gles; + } + if (requested == "desktop") + return QWindowsOpenGLTester::DesktopGl; + if (requested == "software") + return QWindowsOpenGLTester::SoftwareRasterizer; + qCWarning(lcQpaGl) << "Invalid value set for " << openGlVar << ": " << requested; + } +#endif // !Q_OS_WINCE + return QWindowsOpenGLTester::InvalidRenderer; +} + +static inline QWindowsOpenGLTester::Renderers + detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly) +{ + Q_UNUSED(gpu) +#ifndef Q_OS_WINCE + // Add checks for card types with known issues here. + QWindowsOpenGLTester::Renderers result(QWindowsOpenGLTester::AngleRendererD3d11 + | QWindowsOpenGLTester::AngleRendererD3d9 + | QWindowsOpenGLTester::AngleRendererD3d11Warp + | QWindowsOpenGLTester::SoftwareRasterizer); + + if (!glesOnly && QWindowsOpenGLTester::testDesktopGL()) + result |= QWindowsOpenGLTester::DesktopGl; + return result; +#else // !Q_OS_WINCE + return QWindowsOpenGLTester::Gles; +#endif +} + +QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedGlesRenderers() +{ + const GpuDescription gpu = GpuDescription::detect(); + const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, true); + qDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result; + return result; +} + +QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers() +{ + const GpuDescription gpu = GpuDescription::detect(); + const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, false); + qDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result; + return result; +} + bool QWindowsOpenGLTester::testDesktopGL() { +#ifndef Q_OS_WINCE HMODULE lib = 0; HWND wnd = 0; HDC dc = 0; @@ -109,6 +327,37 @@ bool QWindowsOpenGLTester::testDesktopGL() goto cleanup; // Now that there is finally a context current, try doing something useful. + + // Check the version. If we got 1.x then it's all hopeless and we can stop right here. + typedef const GLubyte * (APIENTRY * GetString_t)(GLenum name); + GetString_t GetString = reinterpret_cast<GetString_t>(::GetProcAddress(lib, "glGetString")); + if (GetString) { + const char *versionStr = (const char *) GetString(GL_VERSION); + if (versionStr) { + const QByteArray version(versionStr); + const int majorDot = version.indexOf('.'); + if (majorDot != -1) { + int minorDot = version.indexOf('.', majorDot + 1); + if (minorDot == -1) + minorDot = version.size(); + const int major = version.mid(0, majorDot).toInt(); + const int minor = version.mid(majorDot + 1, minorDot - majorDot - 1).toInt(); + qCDebug(lcQpaGl, "Basic wglCreateContext gives version %d.%d", major, minor); + // Try to be as lenient as possible. Missing version, bogus values and + // such are all accepted. The driver may still be functional. Only + // check for known-bad cases, like versions "1.4.0 ...". + if (major == 1) { + result = false; + qCDebug(lcQpaGl, "OpenGL version too low"); + } + } + } + } else { + result = false; + qCDebug(lcQpaGl, "OpenGL 1.x entry points not found"); + } + + // Check for a shader-specific function. if (WGL_GetProcAddress("glCreateShader")) { result = true; qCDebug(lcQpaGl, "OpenGL 2.0 entry points available"); @@ -133,6 +382,9 @@ cleanup: // No FreeLibrary. Some implementations, Mesa in particular, deadlock when trying to unload. return result; +#else // !Q_OS_WINCE + return false; +#endif } QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h index 40a8e9d3ac..6238eea4b0 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.h +++ b/src/plugins/platforms/windows/qwindowsopengltester.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -31,14 +31,91 @@ ** ****************************************************************************/ +#ifndef QWINDOWSOPENGLTESTER_H +#define QWINDOWSOPENGLTESTER_H + #include <qtwindowsglobal.h> +#include <QtCore/QByteArray> +#include <QtCore/QFlags> + QT_BEGIN_NAMESPACE +class QDebug; +class QVariant; + +struct GpuDriverVersion // ### fixme: Use QVersionNumber in Qt 5.5? +{ + GpuDriverVersion(int p = 0, int v = 0, int sv =0, int b = 0) : product(p), version(v), subVersion(sv), build(b) {} + QString toString() const; + int compare(const GpuDriverVersion &rhs) const; + + int product; + int version; + int subVersion; + int build; +}; + +inline bool operator==(const GpuDriverVersion &v1, const GpuDriverVersion &v2) + { return !v1.compare(v2); } +inline bool operator!=(const GpuDriverVersion &v1, const GpuDriverVersion &v2) + { return v1.compare(v2); } +inline bool operator< (const GpuDriverVersion &v1, const GpuDriverVersion &v2) + { return v1.compare(v2) < 0; } +inline bool operator<=(const GpuDriverVersion &v1, const GpuDriverVersion &v2) + { return v1.compare(v2) <= 0; } +inline bool operator> (const GpuDriverVersion &v1, const GpuDriverVersion &v2) + { return v1.compare(v2) > 0; } +inline bool operator>=(const GpuDriverVersion &v1, const GpuDriverVersion &v2) + { return v1.compare(v2) >= 0; } + +QDebug operator<<(QDebug d, const GpuDriverVersion &gd); + +struct GpuDescription +{ + GpuDescription() : vendorId(0), deviceId(0), revision(0), subSysId(0) {} + + static GpuDescription detect(); + QString toString() const; + QVariant toVariant() const; + + int vendorId; + int deviceId; + int revision; + int subSysId; + GpuDriverVersion driverVersion; + QByteArray driverName; + QByteArray description; +}; + +QDebug operator<<(QDebug d, const GpuDescription &gd); + class QWindowsOpenGLTester { public: + enum Renderer { + InvalidRenderer = 0x0000, + DesktopGl = 0x0001, + AngleRendererD3d11 = 0x0002, + AngleRendererD3d9 = 0x0004, + AngleRendererD3d11Warp = 0x0008, // "Windows Advanced Rasterization Platform" + AngleBackendMask = AngleRendererD3d11 | AngleRendererD3d9 | AngleRendererD3d11Warp, + Gles = 0x0010, // ANGLE/unspecified or Generic GLES for Windows CE. + GlesMask = Gles | AngleBackendMask, + SoftwareRasterizer = 0x0020 + }; + Q_DECLARE_FLAGS(Renderers, Renderer) + + static Renderer requestedGlesRenderer(); + static Renderer requestedRenderer(); + static Renderers supportedGlesRenderers(); + static Renderers supportedRenderers(); + static bool testDesktopGL(); }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QWindowsOpenGLTester::Renderers) + QT_END_NAMESPACE + +#endif // QWINDOWSOPENGLTESTER_H diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 79219e361a..2566f70436 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -504,4 +504,13 @@ void QWindowsScreenManager::clearScreens() QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeLast()); } +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 924912dbc2..ab0fecd970 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -133,6 +133,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 5dfc48df99..d9c5c97672 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -37,6 +37,7 @@ #include "qwindowsdrag.h" #include "qwindowsscreen.h" #include "qwindowsscaling.h" +#include "qwindowsintegration.h" #ifdef QT_NO_CURSOR # include "qwindowscursor.h" #endif @@ -169,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) @@ -179,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. @@ -205,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 @@ -328,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. @@ -369,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; @@ -389,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) @@ -420,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, @@ -494,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 ; @@ -514,8 +556,12 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag if (flags & Qt::WindowSystemMenuHint) style |= WS_SYSMENU; else if (dialog) { - style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu. - exStyle |= WS_EX_DLGMODALFRAME; + // QTBUG-2027, dialogs without system menu. + style |= WS_SYSMENU; + if (!(flags & Qt::FramelessWindowHint)) { + style |= WS_BORDER; + exStyle |= WS_EX_DLGMODALFRAME; + } } if (flags & Qt::WindowMinimizeButtonHint) style |= WS_MINIMIZEBOX; @@ -569,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); @@ -598,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; @@ -612,9 +662,6 @@ QWindowsWindowData result.embedded = embedded; result.customMargins = context->customMargins; - if (isGL && hasAlpha) - applyBlurBehindWindow(result.hwnd); - return result; } @@ -637,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; @@ -662,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); } @@ -945,7 +991,8 @@ void QWindowsWindow::destroyWindow() setDropSiteEnabled(false); #ifndef QT_NO_OPENGL if (m_surface) { - m_data.staticOpenGLContext->destroyWindowSurface(m_surface); + if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) + staticOpenGLContext->destroyWindowSurface(m_surface); m_surface = 0; } #endif @@ -1036,7 +1083,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; } @@ -1272,8 +1319,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 @@ -1298,7 +1347,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), @@ -1369,11 +1419,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()); } @@ -1402,7 +1452,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 @@ -1523,7 +1574,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; @@ -2287,8 +2338,10 @@ void *QWindowsWindow::surface(void *nativeConfig) #ifdef QT_NO_OPENGL return 0; #else - if (!m_surface) - m_surface = m_data.staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig); + if (!m_surface) { + if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) + m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig); + } return m_surface; #endif @@ -2297,7 +2350,8 @@ void *QWindowsWindow::surface(void *nativeConfig) void QWindowsWindow::invalidateSurface() { if (m_surface) { - m_data.staticOpenGLContext->destroyWindowSurface(m_surface); + if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) + staticOpenGLContext->destroyWindowSurface(m_surface); m_surface = 0; } } @@ -2322,4 +2376,22 @@ void QWindowsWindow::registerTouchWindow(QWindowsWindowFunctions::TouchWindowTou #endif // !Q_OS_WINCE } +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 3e2f488f46..674f0ab00d 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -108,9 +108,6 @@ struct QWindowsWindowData QMargins customMargins; // User-defined, additional frame for NCCALCSIZE HWND hwnd; bool embedded; -#ifndef QT_NO_OPENGL - QSharedPointer<QWindowsStaticOpenGLContext> staticOpenGLContext; -#endif // QT_NO_OPENGL static QWindowsWindowData create(const QWindow *w, const QWindowsWindowData ¶meters, @@ -141,7 +138,8 @@ public: WithinCreate = 0x20000, WithinMaximize = 0x40000, MaximizeToFullScreen = 0x80000, - InputMethodDisabled =0x100000 + InputMethodDisabled = 0x100000, + Compositing = 0x200000 }; QWindowsWindow(QWindow *window, const QWindowsWindowData &data); @@ -255,6 +253,7 @@ public: void *surface(void *nativeConfig); void invalidateSurface() Q_DECL_OVERRIDE; + void aboutToMakeCurrent(); #ifndef Q_OS_WINCE void setAlertState(bool enabled); diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 8e5f35d293..246598677f 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -40,7 +40,8 @@ SOURCES += \ $$PWD/qwindowsservices.cpp \ $$PWD/qwindowsnativeimage.cpp \ $$PWD/qwindowsnativeinterface.cpp \ - $$PWD/qwindowsscaling.cpp + $$PWD/qwindowsscaling.cpp \ + $$PWD/qwindowsopengltester.cpp HEADERS += \ $$PWD/qwindowswindow.h \ @@ -66,9 +67,8 @@ HEADERS += \ $$PWD/qplatformfunctions_wince.h \ $$PWD/qwindowsnativeimage.h \ $$PWD/qwindowsnativeinterface.h \ - $$PWD/qwindowsscaling.h - -!wince: HEADERS += $$PWD/qwindowsopengltester.h + $$PWD/qwindowsscaling.h \ + $$PWD/qwindowsopengltester.h INCLUDEPATH += $$PWD @@ -84,8 +84,7 @@ contains(QT_CONFIG, opengles2) { # Dynamic GL needs both WGL and EGL contains(QT_CONFIG,dynamicgl) { - SOURCES += $$PWD/qwindowseglcontext.cpp \ - $$PWD/qwindowsopengltester.cpp + SOURCES += $$PWD/qwindowseglcontext.cpp HEADERS += $$PWD/qwindowseglcontext.h } diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 5de5b6bb55..9944f54780 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -999,6 +999,8 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event) if (at != -1) { Transaction t = transactions.takeAt(at); + if (t.drag) + t.drag->deleteLater(); // QDragManager *manager = QDragManager::self(); // Window target = current_target; @@ -1186,6 +1188,11 @@ bool QXcbDrag::dndEnable(QXcbWindow *w, bool on) } } +bool QXcbDrag::ownsDragObject() const +{ + return true; +} + QXcbDropData::QXcbDropData(QXcbDrag *d) : QXcbMime(), drag(d) diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 1bca9a036f..b5188fd41c 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -70,7 +70,6 @@ public: virtual QMimeData *platformDropData() Q_DECL_OVERRIDE; - void startDrag() Q_DECL_OVERRIDE; void cancel() Q_DECL_OVERRIDE; void move(const QMouseEvent *me) Q_DECL_OVERRIDE; @@ -87,6 +86,7 @@ public: void handleFinished(const xcb_client_message_event_t *event); bool dndEnable(QXcbWindow *win, bool on); + bool ownsDragObject() const Q_DECL_OVERRIDE; void updatePixmap(); xcb_timestamp_t targetTime() { return target_time; } 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 0e28cf2698..a945b4cc18 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -730,6 +730,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()) @@ -2300,7 +2303,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)); + xcbScreen()->windowShown(this); break; case XEMBED_FOCUS_IN: Qt::FocusReason reason; |