diff options
Diffstat (limited to 'src/plugins/platforms')
33 files changed, 307 insertions, 152 deletions
diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp index 4d741807d0..9d6d4003f7 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.cpp @@ -46,6 +46,8 @@ #include <QtCore/qdebug.h> #include <qpa/qwindowsysteminterface.h> +#include <QtGui/private/qopenglcontext_p.h> + QT_BEGIN_NAMESPACE QAndroidOpenGLContext::QAndroidOpenGLContext(const QAndroidPlatformIntegration *integration, @@ -75,4 +77,17 @@ void QAndroidOpenGLContext::swapBuffers(QPlatformSurface *surface) } } +bool QAndroidOpenGLContext::makeCurrent(QPlatformSurface *surface) +{ + bool ret = QEglFSContext::makeCurrent(surface); + + const char *rendererString = reinterpret_cast<const char *>(glGetString(GL_RENDERER)); + if (rendererString != 0 && qstrncmp(rendererString, "Android Emulator", 16) == 0) { + QOpenGLContextPrivate *ctx_d = QOpenGLContextPrivate::get(context()); + ctx_d->workaround_missingPrecisionQualifiers = true; + } + + return ret; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.h b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.h index c4c5a430ad..c419ae8392 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.h +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglcontext.h @@ -58,6 +58,7 @@ public: EGLenum eglApi = EGL_OPENGL_ES_API); void swapBuffers(QPlatformSurface *surface); + bool makeCurrent(QPlatformSurface *surface); private: const QAndroidPlatformIntegration *m_platformIntegration; diff --git a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp index b1a2231ff5..2eac8d248c 100644 --- a/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp +++ b/src/plugins/platforms/android/src/opengl/qandroidopenglplatformwindow.cpp @@ -69,7 +69,6 @@ void QAndroidOpenGLPlatformWindow::invalidateSurface() { QWindowSystemInterface::handleExposeEvent(window(), QRegion()); // Obscure event QWindowSystemInterface::flushWindowSystemEvents(); - QEglFSWindow::invalidateSurface(); m_window = 0; m_surface = 0; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 2ac9a5dac9..9a661ffe5a 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -594,6 +594,7 @@ void QCocoaEventDispatcherPrivate::temporarilyStopAllModalSessions() if (info.session) { [NSApp endModalSession:info.session]; info.session = 0; + [(NSWindow*) info.nswindow release]; } } currentModalSessionCached = 0; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index 7224ee2ff8..59fda96dff 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -84,6 +84,8 @@ public: inline NSMenuItem *nsMenuItem() const { return m_nativeItem; } + inline bool isVisible() const { return m_visible; } + virtual QPlatformMenuItem *menuItemAt(int position) const; virtual QPlatformMenuItem *menuItemForTag(quintptr tag) const; @@ -100,6 +102,7 @@ private: NSMenuItem *m_nativeItem; NSObject *m_delegate; bool m_enabled; + bool m_visible; quintptr m_tag; QCocoaMenuBar *m_menuBar; }; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index bd406ee176..f9e033d21b 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -216,6 +216,7 @@ QT_BEGIN_NAMESPACE QCocoaMenu::QCocoaMenu() : m_enabled(true), + m_visible(true), m_tag(0), m_menuBar(0) { @@ -421,6 +422,7 @@ void QCocoaMenu::setEnabled(bool enabled) void QCocoaMenu::setVisible(bool visible) { [m_nativeItem setSubmenu:(visible ? m_nativeMenu : nil)]; + m_visible = visible; } void QCocoaMenu::showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item) diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index 8d1ca88b8e..ddfa9fff96 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -149,15 +149,17 @@ void QCocoaMenuBar::syncMenu(QPlatformMenu *menu) Q_FOREACH (QCocoaMenuItem *item, cocoaMenu->items()) cocoaMenu->syncMenuItem(item); - // If the NSMenu has no visble items, or only separators, we should hide it - // on the menubar. This can happen after syncing the menu items since they - // can be moved to other menus. BOOL shouldHide = YES; - for (NSMenuItem *item in [cocoaMenu->nsMenu() itemArray]) - if (![item isSeparatorItem] && ![item isHidden]) { - shouldHide = NO; - break; - } + if (cocoaMenu->isVisible()) { + // If the NSMenu has no visble items, or only separators, we should hide it + // on the menubar. This can happen after syncing the menu items since they + // can be moved to other menus. + for (NSMenuItem *item in [cocoaMenu->nsMenu() itemArray]) + if (![item isSeparatorItem] && ![item isHidden]) { + shouldHide = NO; + break; + } + } [cocoaMenu->nsMenuItem() setHidden:shouldHide]; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 057eb7e144..86f12e0e5f 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -267,7 +267,6 @@ void QCocoaWindow::setGeometry(const QRect &rect) #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG qDebug() << "QCocoaWindow::setGeometry" << this << rect; #endif - QPlatformWindow::setGeometry(rect); setCocoaGeometry(rect); } @@ -275,8 +274,10 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) { QCocoaAutoReleasePool pool; - if (m_contentViewIsEmbedded) + if (m_contentViewIsEmbedded) { + QPlatformWindow::setGeometry(rect); return; + } if (m_nsWindow) { NSRect bounds = qt_mac_flipRect(rect, window()); @@ -284,6 +285,8 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) } else { [m_contentView setFrame : NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; } + + // will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm) } void QCocoaWindow::setVisible(bool visible) @@ -420,11 +423,13 @@ NSInteger QCocoaWindow::windowLevel(Qt::WindowFlags flags) if (type == Qt::ToolTip) windowLevel = NSScreenSaverWindowLevel; - // A window should be in at least the same level as its parent. - const QWindow * const transientParent = window()->transientParent(); - const QCocoaWindow * const transientParentWindow = transientParent ? static_cast<QCocoaWindow *>(transientParent->handle()) : 0; - if (transientParentWindow) - windowLevel = qMax([transientParentWindow->m_nsWindow level], windowLevel); + // Any "special" window should be in at least the same level as its parent. + if (type != Qt::Window) { + const QWindow * const transientParent = window()->transientParent(); + const QCocoaWindow * const transientParentWindow = transientParent ? static_cast<QCocoaWindow *>(transientParent->handle()) : 0; + if (transientParentWindow) + windowLevel = qMax([transientParentWindow->m_nsWindow level], windowLevel); + } return windowLevel; } @@ -481,6 +486,9 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) [m_nsWindow setStyleMask:styleMask]; [m_nsWindow setLevel:level]; setWindowShadow(flags); + if (!(styleMask & NSBorderlessWindowMask)) { + setWindowTitle(window()->title()); + } } m_windowFlags = flags; @@ -999,7 +1007,12 @@ qreal QCocoaWindow::devicePixelRatio() const { #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - return qreal([[m_contentView window] backingScaleFactor]); + NSWindow* window = [m_contentView window]; + if (window) { + return qreal([window backingScaleFactor]); + } else { + return 1.0; + } } else #endif { diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 66a1b95ad8..4505f8b8cf 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -285,6 +285,10 @@ static QTouchDevice *touchDevice = 0; Qt::WindowState newState = notificationName == NSWindowDidMiniaturizeNotification ? Qt::WindowMinimized : Qt::WindowNoState; [self notifyWindowStateChanged:newState]; + // NSWindowDidOrderOnScreenAndFinishAnimatingNotification is private API, and not + // emitted in 10.6, so we bring back the old behavior for that case alone. + if (newState == Qt::WindowNoState && QSysInfo::QSysInfo::MacintoshVersion == QSysInfo::MV_10_6) + m_platformWindow->exposeWindow(); } else if ([notificationName isEqualToString: @"NSWindowDidOrderOffScreenNotification"]) { m_platformWindow->obscureWindow(); } else if ([notificationName isEqualToString: @"NSWindowDidOrderOnScreenAndFinishAnimatingNotification"]) { @@ -872,13 +876,13 @@ static QTouchDevice *touchDevice = 0; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if ([theEvent respondsToSelector:@selector(scrollingDeltaX)]) { NSEventPhase phase = [theEvent phase]; - if (phase == NSEventPhaseBegan) { + if (phase == NSEventPhaseBegan || phase == NSEventPhaseNone) { currentWheelModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]]; } QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers); - if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled) { + if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled || phase == NSEventPhaseNone) { currentWheelModifiers = Qt::NoModifier; } } else @@ -967,7 +971,7 @@ static QTouchDevice *touchDevice = 0; if (m_sendKeyEvent && m_composingText.isEmpty()) QWindowSystemInterface::handleExtendedKeyEvent(m_window, timestamp, QEvent::Type(eventType), keyCode, modifiers, - nativeScanCode, nativeVirtualKey, nativeModifiers, text); + nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat]); m_sendKeyEvent = false; } @@ -1036,7 +1040,7 @@ static QTouchDevice *touchDevice = 0; timestamp, (lastKnownModifiers & mac_mask) ? QEvent::KeyRelease : QEvent::KeyPress, modifier_key_symbols[i].qt_code, - qmodifiers); + qmodifiers ^ [QNSView convertKeyModifiers:mac_mask]); } } diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp index 1898cde886..e09154bb59 100644 --- a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp +++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp @@ -79,6 +79,9 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo makeCurrent(); + QRectF sr = window->screen()->geometry(); + glViewport(0, 0, sr.width(), sr.height()); + #ifdef QEGL_EXTRA_DEBUG qWarning("QEglBackingStore::flush %p", window); #endif @@ -120,7 +123,6 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo }; QRectF r = window->geometry(); - QRectF sr = window->screen()->geometry(); GLfloat x1 = (r.left() / sr.width()) * 2 - 1; GLfloat x2 = (r.right() / sr.width()) * 2 - 1; @@ -192,8 +194,6 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo void QEglFSBackingStore::makeCurrent() { - // needed to prevent QOpenGLContext::makeCurrent() from failing - window()->setSurfaceType(QSurface::OpenGLSurface); (static_cast<QEglFSWindow *>(window()->handle()))->create(); m_context->makeCurrent(window()); } diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 98c54e0ee0..28ce8c8a33 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -53,12 +53,12 @@ QEglFSWindow::QEglFSWindow(QWindow *w) : QPlatformWindow(w) , m_surface(0) , m_window(0) + , has_window(false) { - static int serialNo = 0; - m_winid = ++serialNo; #ifdef QEGL_EXTRA_DEBUG - qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_winid)); + qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_window)); #endif + w->setSurfaceType(QSurface::OpenGLSurface); } QEglFSWindow::~QEglFSWindow() @@ -68,7 +68,7 @@ QEglFSWindow::~QEglFSWindow() void QEglFSWindow::create() { - if (m_window) + if (has_window) return; setWindowState(Qt::WindowFullScreen); @@ -90,7 +90,7 @@ void QEglFSWindow::create() void QEglFSWindow::invalidateSurface() { // Native surface has been deleted behind our backs - m_window = 0; + has_window = false; if (m_surface != 0) { EGLDisplay display = (static_cast<QEglFSScreen *>(window()->screen()->handle()))->display(); eglDestroySurface(display, m_surface); @@ -103,6 +103,7 @@ void QEglFSWindow::resetSurface() EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display(); m_window = QEglFSHooks::hooks()->createNativeWindow(QEglFSHooks::hooks()->screenSize(), m_format); + has_window = true; m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL); if (m_surface == EGL_NO_SURFACE) { EGLint error = eglGetError(); @@ -119,9 +120,9 @@ void QEglFSWindow::destroy() m_surface = 0; } - if (m_window) { + if (has_window) { QEglFSHooks::hooks()->destroyNativeWindow(m_window); - m_window = 0; + has_window = false; } } @@ -141,7 +142,7 @@ void QEglFSWindow::setWindowState(Qt::WindowState) WId QEglFSWindow::winId() const { - return m_winid; + return WId(m_window); } QSurfaceFormat QEglFSWindow::format() const diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index 67a64973ce..0997f80e74 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -73,9 +73,9 @@ protected: EGLNativeWindowType m_window; private: - WId m_winid; EGLConfig m_config; QSurfaceFormat m_format; + bool has_window; }; QT_END_NAMESPACE #endif // QEGLFSWINDOW_H diff --git a/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp b/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp index cb245f2e5c..db6e5d94da 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp +++ b/src/plugins/platforms/minimalegl/qminimaleglbackingstore.cpp @@ -80,9 +80,6 @@ void QMinimalEglBackingStore::flush(QWindow *window, const QRegion ®ion, cons void QMinimalEglBackingStore::beginPaint(const QRegion &) { - // needed to prevent QOpenGLContext::makeCurrent() from failing - window()->setSurfaceType(QSurface::OpenGLSurface); - m_context->makeCurrent(window()); m_device = new QOpenGLPaintDevice(window()->size()); } diff --git a/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp b/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp index 13640b73d6..956b5470e5 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp +++ b/src/plugins/platforms/minimalegl/qminimaleglwindow.cpp @@ -58,6 +58,7 @@ QMinimalEglWindow::QMinimalEglWindow(QWindow *w) if (w->geometry() != screenGeometry) { QWindowSystemInterface::handleGeometryChange(w, screenGeometry); } + w->setSurfaceType(QSurface::OpenGLSurface); } void QMinimalEglWindow::setGeometry(const QRect &) diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 92664826ab..377ca32e64 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -2,7 +2,9 @@ TEMPLATE = subdirs android:!android-no-sdk: SUBDIRS += android -SUBDIRS += minimal offscreen +SUBDIRS += minimal + +!win32|contains(QT_CONFIG, freetype):SUBDIRS += offscreen contains(QT_CONFIG, xcb) { SUBDIRS += xcb diff --git a/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp b/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp index d94d3c092a..e723e32301 100644 --- a/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp +++ b/src/plugins/platforms/qnx/qqnxbpseventfilter.cpp @@ -221,9 +221,14 @@ bool QQnxBpsEventFilter::handleNavigatorEvent(bps_event_t *event) break; case NAVIGATOR_WINDOW_THUMBNAIL: m_navigatorEventHandler->handleWindowGroupStateChanged(id, Qt::WindowMinimized); +#if defined(Q_OS_BLACKBERRY_TABLET) + m_navigatorEventHandler->handleWindowGroupActivated(id); +#endif break; case NAVIGATOR_WINDOW_INVISIBLE: +#if defined(Q_OS_BLACKBERRY_TABLET) m_navigatorEventHandler->handleWindowGroupDeactivated(id); +#endif break; } diff --git a/src/plugins/platforms/qnx/qqnxrootwindow.cpp b/src/plugins/platforms/qnx/qqnxrootwindow.cpp index ff5866d1b7..b3f5c87176 100644 --- a/src/plugins/platforms/qnx/qqnxrootwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxrootwindow.cpp @@ -188,35 +188,8 @@ void QQnxRootWindow::makeTranslucent() int result; errno = 0; - result = screen_destroy_window_buffers(m_window); - if (result != 0) { - qFatal("QQnxRootWindow: failed to destroy window buffer, errno=%d", errno); - } - - QRect geometry = m_screen->geometry(); - errno = 0; - int val[2]; - val[0] = geometry.width(); - val[1] = geometry.height(); - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_BUFFER_SIZE, val); - if (result != 0) { - qFatal("QQnxRootWindow: failed to set window buffer size, errno=%d", errno); - } - - errno = 0; - result = screen_create_window_buffers(m_window, 1); - if (result != 0) { - qFatal("QQNX: failed to create window buffer, errno=%d", errno); - } - - // Install an alpha channel on the root window. - // - // This is necessary in order to avoid interfering with any particular - // toplevel widget's QQnxWindow window instance from showing transparent - // if it desires. - errno = 0; - val[0] = SCREEN_TRANSPARENCY_SOURCE_OVER; - result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, val); + const int val = SCREEN_TRANSPARENCY_DISCARD; + result = screen_set_window_property_iv(m_window, SCREEN_PROPERTY_TRANSPARENCY, &val); if (result != 0) { qFatal("QQnxRootWindow: failed to set window transparency, errno=%d", errno); } diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp index 5aa1c970fd..fb8e8075ad 100644 --- a/src/plugins/platforms/qnx/qqnxwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxwindow.cpp @@ -418,15 +418,27 @@ QQnxBuffer &QQnxWindow::renderBuffer() // Get all buffers available for rendering errno = 0; screen_buffer_t buffers[MAX_BUFFER_COUNT]; - const int result = screen_get_window_property_pv(m_window, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)buffers); + int result = screen_get_window_property_pv(m_window, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)buffers); if (result != 0) qFatal("QQnxWindow: failed to query window buffers, errno=%d", errno); - // Wrap each buffer + // Wrap each buffer and clear for (int i = 0; i < MAX_BUFFER_COUNT; ++i) { m_buffers[i] = QQnxBuffer(buffers[i]); + + // Clear Buffer + errno = 0; + int bg[] = { SCREEN_BLIT_COLOR, 0x00000000, SCREEN_BLIT_END }; + result = screen_fill(m_screen->nativeContext(), buffers[i], bg); + if (result != 0) + qFatal("QQnxWindow: failed to clear window buffer, errno=%d", errno); } + errno = 0; + result = screen_flush_blits(m_screen->nativeContext(), 0); + if (result != 0) + qFatal("QQnxWindow: failed to flush blits, errno=%d", errno); + // Use the first available render buffer m_currentBufferIndex = 0; m_previousBufferIndex = -1; diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h index ae48887a80..238817e85c 100644 --- a/src/plugins/platforms/windows/qtwindowsglobal.h +++ b/src/plugins/platforms/windows/qtwindowsglobal.h @@ -88,6 +88,7 @@ enum WindowsEventType // Simplify event types CursorEvent = MouseEventFlag + 3, TouchEvent = TouchEventFlag + 1, NonClientMouseEvent = NonClientEventFlag + MouseEventFlag + 1, + NonClientHitTest = NonClientEventFlag + 2, KeyEvent = KeyEventFlag + 1, KeyDownEvent = KeyEventFlag + KeyDownEventFlag + 1, InputMethodKeyEvent = InputMethodEventFlag + KeyEventFlag + 1, @@ -142,6 +143,10 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI return QtWindows::ResizeEvent; case WM_NCCALCSIZE: return QtWindows::CalculateSize; +#ifndef Q_OS_WINCE + case WM_NCHITTEST: + return QtWindows::NonClientHitTest; +#endif // !Q_OS_WINCE case WM_GETMINMAXINFO: return QtWindows::QuerySizeHints; case WM_KEYDOWN: // keyboard event diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 7c6e82d0dc..5114e9d524 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -819,7 +819,9 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return true;// maybe available on some SDKs revisit WM_NCCALCSIZE case QtWindows::CalculateSize: return QWindowsGeometryHint::handleCalculateSize(platformWindow->customMargins(), msg, result); -#endif + case QtWindows::NonClientHitTest: + return platformWindow->handleNonClientHitTest(QPoint(msg.pt.x, msg.pt.y), result); +#endif // !Q_OS_WINCE case QtWindows::ExposeEvent: return platformWindow->handleWmPaint(hwnd, message, wParam, lParam); case QtWindows::NonClientMouseEvent: @@ -853,10 +855,15 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::CloseEvent: QWindowSystemInterface::handleCloseEvent(platformWindow->window()); return true; - case QtWindows::ThemeChanged: // ### fixme: Compress these events? + case QtWindows::ThemeChanged: { + // Switch from Aero to Classic changes margins. + const Qt::WindowFlags flags = platformWindow->window()->flags(); + if ((flags & Qt::WindowType_Mask) != Qt::Desktop && !(flags & Qt::FramelessWindowHint)) + platformWindow->setFlag(QWindowsWindow::FrameDirty); if (QWindowsTheme *theme = QWindowsTheme::instance()) theme->windowsThemeChanged(platformWindow->window()); return true; + } #ifndef Q_OS_WINCE case QtWindows::ActivateWindowEvent: if (platformWindow->testFlag(QWindowsWindow::BlockedByModal)) diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 33bed61398..27a7044868 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -2103,7 +2103,7 @@ QPlatformDialogHelper *createHelper(QPlatformTheme::DialogType type) || QSysInfo::windowsVersion() <= QSysInfo::WV_2003) { return new QWindowsXpFileDialogHelper(); } - if (QSysInfo::windowsVersion() > QSysInfo::WV_XP) + if (QSysInfo::windowsVersion() > QSysInfo::WV_2003) return new QWindowsFileDialogHelper(); #else return new QWindowsFileDialogHelper(); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index fc2ba454df..754d7a0288 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -395,6 +395,8 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co return true; case MultipleWindows: return true; + case ForeignWindows: + return true; default: return QPlatformIntegration::hasCapability(cap); } diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index f616972aa0..530ebc38b7 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -98,35 +98,39 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM WindowsScreenDataList *result = reinterpret_cast<WindowsScreenDataList *>(p); QWindowsScreenData data; data.geometry = QRect(QPoint(info.rcMonitor.left, info.rcMonitor.top), QPoint(info.rcMonitor.right - 1, info.rcMonitor.bottom - 1)); + data.name = QString::fromWCharArray(info.szDevice); + if (data.name == QLatin1String("WinDisc")) { + data.flags |= QWindowsScreenData::LockScreen; + } else { #ifdef Q_OS_WINCE - //Windows CE, just supports one Display and expects to get only DISPLAY, - //instead of DISPLAY0 and so on, which are passed by info.szDevice - HDC hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); + //Windows CE, just supports one Display and expects to get only DISPLAY, + //instead of DISPLAY0 and so on, which are passed by info.szDevice + HDC hdc = CreateDC(TEXT("DISPLAY"), NULL, NULL, NULL); #else - HDC hdc = CreateDC(info.szDevice, NULL, NULL, NULL); + HDC hdc = CreateDC(info.szDevice, NULL, NULL, NULL); #endif - if (hdc) { - data.dpi = deviceDPI(hdc); - data.depth = GetDeviceCaps(hdc, BITSPIXEL); - data.format = data.depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32; - data.physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE)); - const int refreshRate = GetDeviceCaps(hdc, VREFRESH); - if (refreshRate > 1) // 0,1 means heardware default. - data.refreshRateHz = refreshRate; - DeleteDC(hdc); - } else { - qWarning("%s: Unable to obtain handle for monitor '%s', defaulting to %g DPI.", - __FUNCTION__, qPrintable(QString::fromWCharArray(info.szDevice)), - data.dpi.first); - } + if (hdc) { + data.dpi = deviceDPI(hdc); + data.depth = GetDeviceCaps(hdc, BITSPIXEL); + data.format = data.depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32; + data.physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE)); + const int refreshRate = GetDeviceCaps(hdc, VREFRESH); + if (refreshRate > 1) // 0,1 means hardware default. + data.refreshRateHz = refreshRate; + DeleteDC(hdc); + } else { + qWarning("%s: Unable to obtain handle for monitor '%s', defaulting to %g DPI.", + __FUNCTION__, qPrintable(QString::fromWCharArray(info.szDevice)), + data.dpi.first); + } // CreateDC() failed + } // not lock screen data.geometry = QRect(QPoint(info.rcMonitor.left, info.rcMonitor.top), QPoint(info.rcMonitor.right - 1, info.rcMonitor.bottom - 1)); data.availableGeometry = QRect(QPoint(info.rcWork.left, info.rcWork.top), QPoint(info.rcWork.right - 1, info.rcWork.bottom - 1)); data.orientation = data.geometry.height() > data.geometry.width() ? Qt::PortraitOrientation : Qt::LandscapeOrientation; // EnumDisplayMonitors (as opposed to EnumDisplayDevices) enumerates only // virtual desktop screens. - data.name = QString::fromWCharArray(info.szDevice); - data.flags = QWindowsScreenData::VirtualDesktop; + data.flags |= QWindowsScreenData::VirtualDesktop; if (info.dwFlags & MONITORINFOF_PRIMARY) { data.flags |= QWindowsScreenData::PrimaryScreen; // QPlatformIntegration::screenAdded() documentation specifies that first @@ -162,6 +166,8 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) nospace << " primary"; if (d.flags & QWindowsScreenData::VirtualDesktop) nospace << " virtual desktop"; + if (d.flags & QWindowsScreenData::LockScreen) + nospace << " lock screen"; return dbg; } @@ -392,7 +398,8 @@ static inline int indexOfMonitor(const QList<QWindowsScreenData> &screenData, bool QWindowsScreenManager::handleScreenChanges() { // Look for changed monitors, add new ones - const WindowsScreenDataList newDataList = monitorData(); + WindowsScreenDataList newDataList = monitorData(); + const bool lockScreen = newDataList.size() == 1 && (newDataList.front().flags & QWindowsScreenData::LockScreen); foreach (const QWindowsScreenData &newData, newDataList) { const int existingIndex = indexOfMonitor(m_screens, newData.name); if (existingIndex != -1) { @@ -405,14 +412,17 @@ bool QWindowsScreenManager::handleScreenChanges() qDebug() << "New Monitor: " << newData; } // exists } // for new screens. - // Remove deleted ones. - for (int i = m_screens.size() - 1; i >= 0; --i) { - if (indexOfMonitor(newDataList, m_screens.at(i)->data().name) == -1) { - if (QWindowsContext::verboseWindows) - qDebug() << "Removing Monitor: " << m_screens.at(i) ->data(); - delete m_screens.takeAt(i); - } // not found - } // for existing screens + // Remove deleted ones but keep main monitors if we get only the + // temporary lock screen to avoid window recreation (QTBUG-33062). + if (!lockScreen) { + for (int i = m_screens.size() - 1; i >= 0; --i) { + if (indexOfMonitor(newDataList, m_screens.at(i)->data().name) == -1) { + if (QWindowsContext::verboseWindows) + qDebug() << "Removing Monitor: " << m_screens.at(i) ->data(); + delete m_screens.takeAt(i); + } // not found + } // for existing screens + } // not lock screen return true; } diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 216973125b..930814a17d 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -59,7 +59,8 @@ struct QWindowsScreenData enum Flags { PrimaryScreen = 0x1, - VirtualDesktop = 0x2 + VirtualDesktop = 0x2, + LockScreen = 0x4 // Temporary screen existing during user change, etc. }; QWindowsScreenData(); diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 844e46eec5..0fcd20f7bb 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -226,7 +226,6 @@ static inline QPalette menuPalette(const QPalette &systemPalette) const QColor menuColor(getSysColor(COLOR_MENU)); const QColor menuTextColor(getSysColor(COLOR_MENUTEXT)); const QColor disabled(getSysColor(COLOR_GRAYTEXT)); - const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false); // we might need a special color group for the result. result.setColor(QPalette::Active, QPalette::Button, menuColor); result.setColor(QPalette::Active, QPalette::Text, menuTextColor); @@ -235,6 +234,7 @@ static inline QPalette menuPalette(const QPalette &systemPalette) result.setColor(QPalette::Disabled, QPalette::WindowText, disabled); result.setColor(QPalette::Disabled, QPalette::Text, disabled); #ifndef Q_OS_WINCE + const bool isFlat = booleanSystemParametersInfo(SPI_GETFLATMENU, false); result.setColor(QPalette::Disabled, QPalette::Highlight, getSysColor(isFlat ? COLOR_MENUHILIGHT : COLOR_HIGHLIGHT)); #else diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 6549b9da3e..ace18ddf5b 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -485,6 +485,18 @@ QWindowsWindow::WindowData qDebug().nospace() << "Created desktop window " << w << result.hwnd; return result; } + if ((flags & Qt::WindowType_Mask) == Qt::ForeignWindow) { + result.hwnd = reinterpret_cast<HWND>(w->winId()); + Q_ASSERT(result.hwnd); + const LONG_PTR style = GetWindowLongPtr(result.hwnd, GWL_STYLE); + const LONG_PTR exStyle = GetWindowLongPtr(result.hwnd, GWL_EXSTYLE); + result.geometry = frameGeometry(result.hwnd, !GetParent(result.hwnd)); + result.frame = QWindowsGeometryHint::frame(style, exStyle); + result.embedded = false; + if (QWindowsContext::verboseWindows) + qDebug() << "Foreign window: " << w << result.hwnd << result.geometry << result.frame; + return result; + } const HINSTANCE appinst = (HINSTANCE)GetModuleHandle(0); @@ -894,7 +906,7 @@ void QWindowsWindow::destroyWindow() } } #endif // !Q_OS_WINCE - if (m_data.hwnd != GetDesktopWindow()) + if (m_data.hwnd != GetDesktopWindow() && window()->type() != Qt::ForeignWindow) DestroyWindow(m_data.hwnd); context->removeWindow(m_data.hwnd); m_data.hwnd = 0; @@ -1408,14 +1420,27 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state) handleHidden(); QWindowSystemInterface::flushWindowSystemEvents(); // Tell QQuickWindow to stop rendering now. break; - case Qt::WindowNoState: + case Qt::WindowNoState: { // QTBUG-17548: We send expose events when receiving WM_Paint, but for - // layered windows, we won't receive any WM_Paint. - if (GetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE) & WS_EX_LAYERED) { - fireExpose(QRegion(0, 0, window()->width(), window()->height())); - if (!QWindowsContext::instance()->asyncExpose()) - QWindowSystemInterface::flushWindowSystemEvents(); + // layered windows and transient children, we won't receive any WM_Paint. + QWindow *w = window(); + bool exposeEventsSent = false; + if (isLayered()) { + fireExpose(QRegion(0, 0, w->width(), w->height())); + exposeEventsSent = true; } + foreach (QWindow *child, QGuiApplication::allWindows()) { + if (child != w && child->isVisible() && child->transientParent() == w) { + QWindowsWindow *platformWindow = QWindowsWindow::baseWindowOf(child); + if (platformWindow->isLayered()) { + platformWindow->fireExpose(QRegion(0, 0, child->width(), child->height())); + exposeEventsSent = true; + } + } + } + if (exposeEventsSent && !QWindowsContext::instance()->asyncExpose()) + QWindowSystemInterface::flushWindowSystemEvents(); + } break; default: break; @@ -1796,8 +1821,50 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const if (QWindowsContext::verboseWindows) qDebug() << __FUNCTION__ << window() << *mmi; } + +bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *result) const +{ + // QTBUG-32663, suppress resize cursor for fixed size windows. + const QWindow *w = window(); + if (!w->isTopLevel() // Task 105852, minimized windows need to respond to user input. + || (m_windowState != Qt::WindowNoState && m_windowState != Qt::WindowActive) + || (m_data.flags & Qt::FramelessWindowHint)) { + return false; + } + const QSize minimumSize = w->minimumSize(); + if (minimumSize.isEmpty()) + return false; + const QSize maximumSize = w->maximumSize(); + const bool fixedWidth = minimumSize.width() == maximumSize.width(); + const bool fixedHeight = minimumSize.height() == maximumSize.height(); + if (!fixedWidth && !fixedHeight) + return false; + const QPoint localPos = w->mapFromGlobal(globalPos); + const QSize size = w->size(); + if (fixedHeight) { + if (localPos.y() >= size.height()) { + *result = HTBORDER; // Unspecified border, no resize cursor. + return true; + } + if (localPos.y() < 0) { + const QMargins margins = frameMargins(); + const int topResizeBarPos = margins.left() - margins.top(); + if (localPos.y() < topResizeBarPos) { + *result = HTCAPTION; // Extend caption over top resize bar, let's user move the window. + return true; + } + } + } + if (fixedWidth && (localPos.x() < 0 || localPos.x() >= size.width())) { + *result = HTBORDER; // Unspecified border, no resize cursor. + return true; + } + return false; +} + #endif // !Q_OS_WINCE +#ifndef QT_NO_CURSOR // Return the default cursor (Arrow) from QWindowsCursor's cache. static inline QWindowsWindowCursor defaultCursor(const QWindow *w) { @@ -1808,6 +1875,24 @@ static inline QWindowsWindowCursor defaultCursor(const QWindow *w) return QWindowsWindowCursor(Qt::ArrowCursor); } +// Check whether to apply a new cursor. Either the window in question is +// currently under mouse, or it is the parent of the window under mouse and +// there is no other window with an explicitly set cursor in-between. +static inline bool applyNewCursor(const QWindow *w) +{ + const QWindow *underMouse = QWindowsContext::instance()->windowUnderMouse(); + if (underMouse == w) + return true; + for (const QWindow *p = underMouse; p ; p = p->parent()) { + if (p == w) + return true; + if (!QWindowsWindow::baseWindowOf(p)->cursor().isNull()) + return false; + } + return false; +} +#endif // !QT_NO_CURSOR + /*! \brief Applies to cursor property set on the window to the global cursor. @@ -1829,23 +1914,6 @@ void QWindowsWindow::applyCursor() #endif } -// Check whether to apply a new cursor. Either the window in question is -// currently under mouse, or it is the parent of the window under mouse and -// there is no other window with an explicitly set cursor in-between. -static inline bool applyNewCursor(const QWindow *w) -{ - const QWindow *underMouse = QWindowsContext::instance()->windowUnderMouse(); - if (underMouse == w) - return true; - for (const QWindow *p = underMouse; p ; p = p->parent()) { - if (p == w) - return true; - if (!QWindowsWindow::baseWindowOf(p)->cursor().isNull()) - return false; - } - return false; -} - void QWindowsWindow::setCursor(const QWindowsWindowCursor &c) { #ifndef QT_NO_CURSOR diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 996542f92a..afcfa8b821 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -229,12 +229,14 @@ public: static inline void setUserDataOf(HWND hwnd, void *ud); static bool setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity); + bool isLayered() const; HDC getDC(); void releaseDC(); #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO void getSizeHints(MINMAXINFO *mmi) const; -#endif + bool handleNonClientHitTest(const QPoint &globalPos, LRESULT *result) const; +#endif // !Q_OS_WINCE #ifndef QT_NO_CURSOR QWindowsWindowCursor cursor() const { return m_cursor; } @@ -374,6 +376,15 @@ inline void QWindowsWindow::destroyIcon() } } +inline bool QWindowsWindow::isLayered() const +{ +#ifndef Q_OS_WINCE + return GetWindowLongPtr(m_data.hwnd, GWL_EXSTYLE) & WS_EX_LAYERED; +#else + return false; +#endif +} + QT_END_NAMESPACE Q_DECLARE_METATYPE(QMargins) diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 1f2485db0d..dc677cd3be 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -306,6 +306,10 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin Q_XCB_NOOP(connection()); QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle()); + if (!platformWindow) { + qWarning("QXcbBackingStore::flush: QWindow has no platform window (QTBUG-32681)"); + return; + } QVector<QRect> rects = clipped.rects(); for (int i = 0; i < rects.size(); ++i) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 01af23377e..2ce34ea8f2 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -989,8 +989,11 @@ void QXcbEventReader::run() emit eventPending(); } + m_mutex.lock(); for (int i = 0; i < m_events.size(); ++i) free(m_events.at(i)); + m_events.clear(); + m_mutex.unlock(); } void QXcbEventReader::addEvent(xcb_generic_event_t *event) diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 991c82eaaa..799bb387e1 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -309,8 +309,6 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) case XI_TouchUpdate: if (touchPoint.area.center() != QPoint(x, y)) touchPoint.state = Qt::TouchPointMoved; - else - touchPoint.state = Qt::TouchPointStationary; break; case XI_TouchEnd: touchPoint.state = Qt::TouchPointReleased; @@ -323,9 +321,13 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) " area " << touchPoint.area << " pressure " << touchPoint.pressure; #endif QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiEvent->time, dev->qtTouchDevice, m_touchPoints.values()); - // If a touchpoint was released, we can forget it, because the ID won't be reused. if (touchPoint.state == Qt::TouchPointReleased) + // If a touchpoint was released, we can forget it, because the ID won't be reused. m_touchPoints.remove(touchPoint.id); + else + // Make sure that we don't send TouchPointPressed/Moved in more than one QTouchEvent + // with this touch point if the next XI2 event is about a different touch point. + touchPoint.state = Qt::TouchPointStationary; } } #endif diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 38cbfaf183..d1729ed168 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -723,14 +723,14 @@ void QXcbKeyboard::updateXKBState(xcb_xkb_state_notify_event_t *state) if (connection()->hasXKB()) { - xkb_state_component newState; - newState = xkb_state_update_mask(xkb_state, - state->baseMods, - state->latchedMods, - state->lockedMods, - state->baseGroup, - state->latchedGroup, - state->lockedGroup); + const xkb_state_component newState + = xkb_state_update_mask(xkb_state, + state->baseMods, + state->latchedMods, + state->lockedMods, + state->baseGroup, + state->latchedGroup, + state->lockedGroup); if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) { //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)"); @@ -744,17 +744,22 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state) if (!m_config) return; - quint32 modsDepressed, modsLatched, modsLocked; - modsDepressed = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED); - modsLatched = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); - modsLocked = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); - - quint32 xkbMask = xkbModMask(state); - xkb_state_component newState; - newState = xkb_state_update_mask(xkb_state, - modsDepressed & xkbMask, - modsLatched & xkbMask, - modsLocked & xkbMask, + const quint32 modsDepressed = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_DEPRESSED); + const quint32 modsLatched = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED); + const quint32 modsLocked = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED); + const quint32 xkbMask = xkbModMask(state); + + const quint32 latched = modsLatched & xkbMask; + const quint32 locked = modsLocked & xkbMask; + quint32 depressed = modsDepressed & xkbMask; + // set modifiers in depressed if they don't appear in any of the final masks + depressed |= ~(depressed | latched | locked) & xkbMask; + + const xkb_state_component newState + = xkb_state_update_mask(xkb_state, + depressed, + latched, + locked, 0, 0, (state >> 13) & 3); // bits 13 and 14 report the state keyboard group diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 0325338a13..028cd9ab72 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1302,6 +1302,9 @@ QRect QXcbWindow::windowToWmGeometry(QRect r) const r.translate(m_frameMargins.left(), m_frameMargins.top()); } else if (!frameInclusive && m_gravity == XCB_GRAVITY_NORTH_WEST) { r.translate(-m_frameMargins.left(), -m_frameMargins.top()); + } else if (!frameInclusive && m_gravity == XCB_GRAVITY_CENTER) { + r.translate(-(m_frameMargins.left() - m_frameMargins.right())/2, + -(m_frameMargins.top() - m_frameMargins.bottom())/2); } return r; } @@ -1641,7 +1644,8 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event) void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) { - if (window() != QGuiApplication::focusWindow()) { + const bool isWheel = event->detail >= 4 && event->detail <= 7; + if (!isWheel && window() != QGuiApplication::focusWindow()) { QWindow *w = static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver(); if (!(w->flags() & Qt::WindowDoesNotAcceptFocus)) w->requestActivate(); @@ -1663,7 +1667,7 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); - if (event->detail >= 4 && event->detail <= 7) { + if (isWheel) { // Logic borrowed from qapplication_x11.cpp int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1); bool hor = (((event->detail == 4 || event->detail == 5) diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp index c106bd00f8..1423c6262d 100644 --- a/src/plugins/platforms/xcb/qxcbxsettings.cpp +++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp @@ -221,6 +221,7 @@ QXcbXSettings::QXcbXSettings(QXcbScreen *screen) xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(screen->xcb_connection(),atom_cookie,&error); if (error) { qWarning() << Q_FUNC_INFO << "Failed to find XSETTINGS_S atom"; + free(error); return; } xcb_atom_t selection_owner_atom = atom_reply->atom; @@ -233,14 +234,15 @@ QXcbXSettings::QXcbXSettings(QXcbScreen *screen) xcb_get_selection_owner_reply(screen->xcb_connection(), selection_cookie, &error); if (error) { qWarning() << Q_FUNC_INFO << "Failed to get selection owner for XSETTINGS_S atom"; + free(error); return; } d_ptr->x_settings_window = selection_result->owner; + free(selection_result); if (!d_ptr->x_settings_window) { return; } - free(selection_result); const uint32_t event = XCB_CW_EVENT_MASK; const uint32_t event_mask[] = { XCB_EVENT_MASK_STRUCTURE_NOTIFY|XCB_EVENT_MASK_PROPERTY_CHANGE }; |