From cf827f2167d7ca122541cc17307e2b8133ec3af4 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Wed, 9 Mar 2016 23:16:29 +0100 Subject: Ported Qt 4 fix when getting an invalid native key on Windows Task-number: QTBUG-36061 Change-Id: Ibde65735d861af4e1ef768e9e4314d30fed534a1 Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowskeymapper.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 5790341dbf..403ac6ecfb 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -1247,7 +1247,12 @@ QList QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const { QList result; - const KeyboardLayoutItem &kbItem = keyLayout[e->nativeVirtualKey()]; + + const quint32 nativeVirtualKey = e->nativeVirtualKey(); + if (nativeVirtualKey > 255) + return result; + + const KeyboardLayoutItem &kbItem = keyLayout[nativeVirtualKey]; if (!kbItem.exists) return result; -- cgit v1.2.3 From 0c51277bb84d816963cae1a3274722753acbf167 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 8 Mar 2016 15:36:09 +0100 Subject: winrt: add logging to QWinRTScreen Task-number: QTBUG-38114 Change-Id: Id653487a03ca2920c46cf16e45f28677a69fa570 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 4c4d553b2d..831586538f 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -39,8 +39,10 @@ #include "qwinrtbackingstore.h" #include "qwinrtinputcontext.h" #include "qwinrtcursor.h" +#include "qwinrtwindow.h" #include +#include #include #include #include @@ -469,6 +471,7 @@ QWinRTScreen::QWinRTScreen() : d_ptr(new QWinRTScreenPrivate) { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__; d->orientation = Qt::PrimaryOrientation; d->touchDevice = Q_NULLPTR; @@ -553,6 +556,7 @@ QWinRTScreen::QWinRTScreen() QWinRTScreen::~QWinRTScreen() { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__ << this; // Unregister callbacks HRESULT hr; @@ -697,6 +701,8 @@ Xaml::IDependencyObject *QWinRTScreen::canvas() const void QWinRTScreen::setStatusBarVisibility(bool visible, QWindow *window) { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__ << window << visible; + const Qt::WindowFlags windowType = window->flags() & Qt::WindowType_Mask; if (!window || (windowType != Qt::Window && windowType != Qt::Dialog)) return; @@ -768,6 +774,7 @@ QWindow *QWinRTScreen::topWindow() const void QWinRTScreen::addWindow(QWindow *window) { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__ << window; if (window == topWindow()) return; @@ -785,6 +792,7 @@ void QWinRTScreen::addWindow(QWindow *window) void QWinRTScreen::removeWindow(QWindow *window) { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__ << window; #ifdef Q_OS_WINPHONE if (window->visibility() == QWindow::Minimized) @@ -1131,6 +1139,7 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs * hr = d->coreWindow->get_Bounds(&size); RETURN_OK_IF_FAILED("Failed to get window bounds"); d->logicalSize = QSizeF(size.Width, size.Height); + qCDebug(lcQpaWindows) << __FUNCTION__ << d->logicalSize; QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry()); QPlatformScreen::resizeMaximizedWindows(); handleExpose(); @@ -1140,6 +1149,7 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs * HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args) { Q_D(QWinRTScreen); + qCDebug(lcQpaWindows) << __FUNCTION__; CoreWindowActivationState activationState; args->get_WindowActivationState(&activationState); @@ -1159,6 +1169,8 @@ HRESULT QWinRTScreen::onActivated(ICoreWindow *, IWindowActivatedEventArgs *args HRESULT QWinRTScreen::onClosed(ICoreWindow *, ICoreWindowEventArgs *) { + qCDebug(lcQpaWindows) << __FUNCTION__; + foreach (QWindow *w, QGuiApplication::topLevelWindows()) QWindowSystemInterface::handleCloseEvent(w); return S_OK; @@ -1170,6 +1182,7 @@ HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *, IVisibilityChangedEvent boolean visible; HRESULT hr = args ? args->get_Visible(&visible) : d->coreWindow->get_Visible(&visible); RETURN_OK_IF_FAILED("Failed to get visibility."); + qCDebug(lcQpaWindows) << __FUNCTION__ << visible; QWindowSystemInterface::handleApplicationStateChanged(visible ? Qt::ApplicationActive : Qt::ApplicationHidden); if (visible) handleExpose(); @@ -1179,7 +1192,7 @@ HRESULT QWinRTScreen::onVisibilityChanged(ICoreWindow *, IVisibilityChangedEvent HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable *) { Q_D(QWinRTScreen); - + qCDebug(lcQpaWindows) << __FUNCTION__; DisplayOrientations displayOrientation; HRESULT hr = d->displayInformation->get_CurrentOrientation(&displayOrientation); RETURN_OK_IF_FAILED("Failed to get current orientations."); @@ -1187,6 +1200,7 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable * Qt::ScreenOrientation newOrientation = static_cast(static_cast(qtOrientationsFromNative(displayOrientation))); if (d->orientation != newOrientation) { d->orientation = newOrientation; + qCDebug(lcQpaWindows) << " New orientation:" << newOrientation; #ifdef Q_OS_WINPHONE onSizeChanged(nullptr, nullptr); #endif @@ -1211,6 +1225,8 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *) hr = d->displayInformation->get_ResolutionScale(&resolutionScale); d->scaleFactor = qreal(resolutionScale) / 100; #endif + qCDebug(lcQpaWindows) << __FUNCTION__ << "Scale Factor:" << d->scaleFactor; + RETURN_OK_IF_FAILED("Failed to get scale factor"); FLOAT dpi; @@ -1225,6 +1241,8 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *) hr = d->displayInformation->get_RawDpiY(&dpi); RETURN_OK_IF_FAILED("Failed to get y raw DPI."); d->physicalDpi.second = dpi ? dpi : 96.0; + qCDebug(lcQpaWindows) << __FUNCTION__ << "Logical DPI:" << d->logicalDpi + << "Physical DPI:" << d->physicalDpi; return S_OK; } @@ -1232,12 +1250,14 @@ HRESULT QWinRTScreen::onDpiChanged(IDisplayInformation *, IInspectable *) #ifdef Q_OS_WINPHONE HRESULT QWinRTScreen::onStatusBarShowing(IStatusBar *, IInspectable *) { + qCDebug(lcQpaWindows) << __FUNCTION__; onSizeChanged(nullptr, nullptr); return S_OK; } HRESULT QWinRTScreen::onStatusBarHiding(IStatusBar *, IInspectable *) { + qCDebug(lcQpaWindows) << __FUNCTION__; onSizeChanged(nullptr, nullptr); return S_OK; } -- cgit v1.2.3 From 1929e48bba631465c256265a2ed31128e7217aca Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 8 Mar 2016 15:39:36 +0100 Subject: winrt: Fix painting glitches when orientation changes In addition to handling the pure rotation enforce a size change as well. This way content is redrawn for the correct orientation. It was done for Windows Phone 8.1 already, we only need to extent this to Windows 10. Task-number: QTBUG-50336 Change-Id: I6b3b964f44b631757ea856331c50f53c39ed9ec3 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 831586538f..2410848cde 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -1201,7 +1201,7 @@ HRESULT QWinRTScreen::onOrientationChanged(IDisplayInformation *, IInspectable * if (d->orientation != newOrientation) { d->orientation = newOrientation; qCDebug(lcQpaWindows) << " New orientation:" << newOrientation; -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) onSizeChanged(nullptr, nullptr); #endif QWindowSystemInterface::handleScreenOrientationChange(screen(), d->orientation); -- cgit v1.2.3 From a2d58025b63d43a843bf14138221086f25c280f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Thu, 10 Mar 2016 12:50:52 +0100 Subject: Cocoa: Improve native view lifetime accuracy. Ideally all native NSWindows and NSViews owned by QCocoaWindow should be deallocated during the QCocoaWindow destructor. In reality this does not always happen since Cocoa is free to hold references to the views after Qt releases its reference. We can help Cocoa clean up: - Clear the first responder for the NSWindow under the ~QCocoaWndow() autoreleasepool. - Use an autoreleasepool to clean up temp objects from [NSWindow orderFront:] immediately. Together this makes the QNSView lifetime be contained by the QCocoaWindow lifetime, at least for simple QWindow usage. It also fixes the observed memory leak reported in QTBUG-51766 Change-Id: Idd224f54ebd6f61f274461a204ff30c666b22768 Task-number: QTBUG-51766 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoawindow.mm | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 00cb43c940..e4cd57a115 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -409,6 +409,7 @@ QCocoaWindow::~QCocoaWindow() #endif QMacAutoReleasePool pool; + [m_nsWindow makeFirstResponder:nil]; [m_nsWindow setContentView:nil]; [m_nsWindow.helper detachFromPlatformWindow]; if (m_isNSWindowChild) { @@ -990,7 +991,15 @@ void QCocoaWindow::raise() [parentNSWindow removeChildWindow:m_nsWindow]; [parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove]; } else { - [m_nsWindow orderFront: m_nsWindow]; + { + // Clean up autoreleased temp objects from orderFront immediately. + // Failure to do so has been observed to cause leaks also beyond any outer + // autorelease pool (for example around a complete QWindow + // construct-show-raise-hide-delete cyle), counter to expected autoreleasepool + // behavior. + QMacAutoReleasePool pool; + [m_nsWindow orderFront: m_nsWindow]; + } static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS"); if (raiseProcess) { ProcessSerialNumber psn; -- cgit v1.2.3 From c4886ca42732feb51648985b741a8113382a6fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Mon, 14 Mar 2016 09:52:09 +0100 Subject: Cocoa: Fix crash on screen disconnect. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintain virtual siblings list on screen deletion. QCocoaIntegration::updateScreens() has a loop which will delete all non-current QScreen objects using QPlatformIntegration::destroyScreen(). destroyScreen() vill eventually call QWindowPrivate:: setTopLevelScreen() which accesses the virtual siblings list for the deleted screen. This can cause a stale pointer access if the virtual screen list is not up to date, especially when disconnecting two screens at the same time. Change-Id: Ia6b9d01edf8e5eea25b64604a2b3b28b173125f7 Task-number: QTBUG-48275 Reviewed-by: Timur Pocheptsov Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 6bec6b191d..91d4b2706b 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -422,14 +422,18 @@ void QCocoaIntegration::updateScreens() } siblings << screen; } + + // Set virtual siblings list. All screens in mScreens are siblings, because we ignored the + // mirrors. Note that some of the screens we update the siblings list for here may be deleted + // below, but update anyway to keep the to-be-deleted screens out of the siblings list. + foreach (QCocoaScreen* screen, mScreens) + screen->setVirtualSiblings(siblings); + // Now the leftovers in remainingScreens are no longer current, so we can delete them. foreach (QCocoaScreen* screen, remainingScreens) { mScreens.removeOne(screen); destroyScreen(screen); } - // All screens in mScreens are siblings, because we ignored the mirrors. - foreach (QCocoaScreen* screen, mScreens) - screen->setVirtualSiblings(siblings); } QCocoaScreen *QCocoaIntegration::screenAtIndex(int index) -- cgit v1.2.3 From 1dcc53f6faf53a2994c6b9fe329d35fdaf61c06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 11 Mar 2016 12:48:11 +0100 Subject: Compile with -no-opengl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QCocoaBackingstore::toImage() can only be Q_DECL_OVERRIDE if QPlatformBackingStore::toImage() is present, which it isn’t for NO_OPENGL builds. Change-Id: Ib116f40fd26defb29a8d520d3e3fb104d8da8d57 Task-number: QTBUG-51694 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoabackingstore.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index 5a199de4a5..934f68ad18 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -51,7 +51,11 @@ public: QPaintDevice *paintDevice() Q_DECL_OVERRIDE; void flush(QWindow *widget, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; +#ifndef QT_NO_OPENGL QImage toImage() const Q_DECL_OVERRIDE; +#else + QImage toImage() const; // No QPlatformBackingStore::toImage() for NO_OPENGL builds. +#endif void resize (const QSize &size, const QRegion &) Q_DECL_OVERRIDE; bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE; void beginPaint(const QRegion ®ion) Q_DECL_OVERRIDE; -- cgit v1.2.3 From 6c53f2528c86fb72f19951a799f0afaa02ad4490 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 14 Mar 2016 10:07:20 +0100 Subject: xcb: Initialize all xcb_client_message_event_t members before use Change-Id: I01e4b69b138fd19fc7e67751d93adebc1326b2f9 Reviewed-by: Orgad Shaneh --- src/plugins/platforms/xcb/qxcbdrag.cpp | 6 ++++++ src/plugins/platforms/xcb/qxcbscreen.cpp | 1 + src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp | 2 +- src/plugins/platforms/xcb/qxcbwindow.cpp | 5 +++++ 4 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index aa6445d2da..f5cc87394b 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -423,6 +423,7 @@ void QXcbDrag::move(const QPoint &globalPos) xcb_client_message_event_t enter; enter.response_type = XCB_CLIENT_MESSAGE; + enter.sequence = 0; enter.window = target; enter.format = 32; enter.type = atom(QXcbAtom::XdndEnter); @@ -451,6 +452,7 @@ void QXcbDrag::move(const QPoint &globalPos) xcb_client_message_event_t move; move.response_type = XCB_CLIENT_MESSAGE; + move.sequence = 0; move.window = target; move.format = 32; move.type = atom(QXcbAtom::XdndPosition); @@ -479,6 +481,7 @@ void QXcbDrag::drop(const QPoint &globalPos) xcb_client_message_event_t drop; drop.response_type = XCB_CLIENT_MESSAGE; + drop.sequence = 0; drop.window = current_target; drop.format = 32; drop.type = atom(QXcbAtom::XdndDrop); @@ -740,6 +743,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message xcb_client_message_event_t response; response.response_type = XCB_CLIENT_MESSAGE; + response.sequence = 0; response.window = xdnd_dragsource; response.format = 32; response.type = atom(QXcbAtom::XdndStatus); @@ -886,6 +890,7 @@ void QXcbDrag::send_leave() xcb_client_message_event_t leave; leave.response_type = XCB_CLIENT_MESSAGE; + leave.sequence = 0; leave.window = current_target; leave.format = 32; leave.type = atom(QXcbAtom::XdndLeave); @@ -956,6 +961,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e xcb_client_message_event_t finished; finished.response_type = XCB_CLIENT_MESSAGE; + finished.sequence = 0; finished.window = xdnd_dragsource; finished.format = 32; finished.type = atom(QXcbAtom::XdndFinished); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 1a90f824fc..f74244e13c 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -361,6 +361,7 @@ void QXcbScreen::sendStartupMessage(const QByteArray &message) const ev.response_type = XCB_CLIENT_MESSAGE; ev.format = 8; ev.type = connection()->atom(QXcbAtom::_NET_STARTUP_INFO_BEGIN); + ev.sequence = 0; ev.window = rootWindow; int sent = 0; int length = message.length() + 1; // include NUL byte diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp index 1f217e8de7..49c0440a3c 100644 --- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp +++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp @@ -94,9 +94,9 @@ xcb_window_t QXcbSystemTrayTracker::locateTrayWindow(const QXcbConnection *conne void QXcbSystemTrayTracker::requestSystemTrayWindowDock(xcb_window_t window) const { xcb_client_message_event_t trayRequest; - memset(&trayRequest, 0, sizeof(trayRequest)); trayRequest.response_type = XCB_CLIENT_MESSAGE; trayRequest.format = 32; + trayRequest.sequence = 0; trayRequest.window = m_trayWindow; trayRequest.type = m_trayAtom; trayRequest.data.data32[0] = XCB_CURRENT_TIME; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index cd1774fed7..a0b1ddb434 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1224,6 +1224,7 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two) event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; + event.sequence = 0; event.window = m_window; event.type = atom(QXcbAtom::_NET_WM_STATE); event.data.data32[0] = set ? 1 : 0; @@ -1265,6 +1266,7 @@ void QXcbWindow::setWindowState(Qt::WindowState state) event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; + event.sequence = 0; event.window = m_window; event.type = atom(QXcbAtom::WM_CHANGE_STATE); event.data.data32[0] = XCB_WM_STATE_ICONIC; @@ -1660,6 +1662,7 @@ void QXcbWindow::requestActivateWindow() event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; + event.sequence = 0; event.window = m_window; event.type = atom(QXcbAtom::_NET_ACTIVE_WINDOW); event.data.data32[0] = 1; @@ -2608,6 +2611,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) xcb_client_message_event_t xev; xev.response_type = XCB_CLIENT_MESSAGE; xev.type = moveResize; + xev.sequence = 0; xev.window = xcb_window(); xev.format = 32; const QPoint globalPos = window()->mapToGlobal(pos); @@ -2636,6 +2640,7 @@ void QXcbWindow::sendXEmbedMessage(xcb_window_t window, quint32 message, event.response_type = XCB_CLIENT_MESSAGE; event.format = 32; + event.sequence = 0; event.window = window; event.type = atom(QXcbAtom::_XEMBED); event.data.data32[0] = connection()->time(); -- cgit v1.2.3 From b8e8c6ad5caf06c5865ed8ce163515f8e538ca7b Mon Sep 17 00:00:00 2001 From: Jochen Seemann Date: Wed, 25 Nov 2015 18:47:37 +0100 Subject: winrt: enable cross-platform high DPI scaling Task-number: QTBUG-46615 Change-Id: I7f75bc7da35b9330753130338a06feb49533061c Reviewed-by: Andrew Knight Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 6 ++++++ src/plugins/platforms/winrt/qwinrtscreen.h | 1 + 2 files changed, 7 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 2410848cde..47e68ae0af 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -635,6 +635,12 @@ QDpi QWinRTScreen::logicalDpi() const return QDpi(d->logicalDpi, d->logicalDpi); } +qreal QWinRTScreen::pixelDensity() const +{ + Q_D(const QWinRTScreen); + return qRound(d->logicalDpi / 96); +} + qreal QWinRTScreen::scaleFactor() const { Q_D(const QWinRTScreen); diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index 0043b2cfa3..ac9db9bfef 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -93,6 +93,7 @@ public: QImage::Format format() const Q_DECL_OVERRIDE; QSizeF physicalSize() const Q_DECL_OVERRIDE; QDpi logicalDpi() const Q_DECL_OVERRIDE; + qreal pixelDensity() const Q_DECL_OVERRIDE; qreal scaleFactor() const; QPlatformCursor *cursor() const Q_DECL_OVERRIDE; Qt::KeyboardModifiers keyboardModifiers() const; -- cgit v1.2.3 From 09acf326dbc6b7b67f21a360be8c91605ce47f1e Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 17 Feb 2016 16:33:22 -0800 Subject: QCocoaMenu: Decouple NSMenuItem from NSMenu While Cocoa requires an NSMenu to be coupled to an NSMenuItem (just as Qt requires a QMenu to be coupled to a QAction), making that a hard coupling comes with some limitations. This is because Cocoa won't allow the NSMenu object to be simultaneously coupled to more than one NSMenuItem and, similarly, an NSMenuItem can only be added to a single parent NSMenu. Therefore, it becomes difficult to share one QMenu between two different QMenuBars in different windows, or to use a QMenu as context menu while being accessible from the menu bar. Previous solutions to circumvent those limitations were less than ideal (see 119882714f87ffeb6945fdb2d02997ae125ff50c for the QMenuBar shared QMenu issue). Other workarounds that relied on that hard coupling, like 996054f5e65bc676aaea0743c2eacec51918e4aa, also added gratuitous complexity. In this patch, we break that hard NSMenuItem-NSMenu coupling, and we replace it with a temporary, looser coupling. As a consequence, * QCocoaMenu only contains and manages a NSMenu instance, removing the previously used NSMenuItem. It gets a temporarily attached NSMenuItem instead. * QCocoaMenuItem gains a safe pointer to its QCocoaMenu property removing the necessity containingMenuItem() in QCocoaMenu. * QCocoaMenuBar manages its own NSMenuItems. With this setup, we bind the NSMenu to its parent NSMenuItem at the last moment. In QCocoaMenuBar, when we call updateMenuBarImmediately(). In QCocoaMenu, we use the delegate's -[QCocoaMenuDelegate menu: updateItem:atIndex:shouldCancel:] method which is called when Cocoa is about to display the NSMenu. Note: There's still one use case we don't support, which is sharing a toplevel QMenuBar menu. This is because Cocoa's menu bar requires each of its menu items to have a submenu assigned, and therefore we can't rely on that last moment assignment. Task-number: QTBUG-34160 Task-number: QTBUG-31342 Task-number: QTBUG-41587 Change-Id: I92bdb444c680789c78e43fe0b585dc6661770281 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoamenu.h | 13 +-- src/plugins/platforms/cocoa/qcocoamenu.mm | 78 +++++++++-------- src/plugins/platforms/cocoa/qcocoamenubar.h | 6 +- src/plugins/platforms/cocoa/qcocoamenubar.mm | 115 ++++++++++++++------------ src/plugins/platforms/cocoa/qcocoamenuitem.h | 3 +- src/plugins/platforms/cocoa/qcocoamenuitem.mm | 17 ---- 6 files changed, 111 insertions(+), 121 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index eccc5230b5..5064d89585 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -75,8 +75,6 @@ public: inline NSMenu *nsMenu() const { return m_nativeMenu; } - inline NSMenuItem *nsMenuItem() const - { return m_nativeItem; } inline bool isVisible() const { return m_visible; } @@ -85,11 +83,9 @@ public: QList items() const; QList merged() const; - void setMenuBar(QCocoaMenuBar *menuBar); - QCocoaMenuBar *menuBar() const; - void setContainingMenuItem(QCocoaMenuItem *menuItem); - QCocoaMenuItem *containingMenuItem() const; + void setAttachedItem(NSMenuItem *item); + NSMenuItem *attachedItem() const; private: QCocoaMenuItem *itemOrNull(int index) const; @@ -97,13 +93,10 @@ private: QList m_menuItems; NSMenu *m_nativeMenu; - NSMenuItem *m_nativeItem; - NSObject *m_delegate; + NSMenuItem *m_attachedItem; bool m_enabled; bool m_visible; quintptr m_tag; - QCocoaMenuBar *m_menuBar; - QCocoaMenuItem *m_containingMenuItem; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index ad491855ff..21a3799859 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -96,6 +96,28 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); return self; } +- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu +{ + Q_ASSERT(m_menu->nsMenu() == menu); + return m_menu->items().count(); +} + +- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel +{ + Q_UNUSED(index); + Q_ASSERT(m_menu->nsMenu() == menu); + if (shouldCancel) { + // TODO detach all submenus + return NO; + } + + QCocoaMenuItem *menuItem = reinterpret_cast(item.tag); + if (m_menu->items().contains(menuItem)) { + if (QCocoaMenu *itemSubmenu = menuItem->menu()) + itemSubmenu->setAttachedItem(item); + } + return YES; +} - (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item { @@ -228,20 +250,16 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); QT_BEGIN_NAMESPACE QCocoaMenu::QCocoaMenu() : + m_attachedItem(0), m_enabled(true), m_visible(true), - m_tag(0), - m_menuBar(0), - m_containingMenuItem(0) + m_tag(0) { QMacAutoReleasePool pool; - m_delegate = [[QCocoaMenuDelegate alloc] initWithMenu:this]; - m_nativeItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; m_nativeMenu = [[NSMenu alloc] initWithTitle:@"Untitled"]; [m_nativeMenu setAutoenablesItems:YES]; - m_nativeMenu.delegate = (QCocoaMenuDelegate *) m_delegate; - [m_nativeItem setSubmenu:m_nativeMenu]; + m_nativeMenu.delegate = [[QCocoaMenuDelegate alloc] initWithMenu:this]; } QCocoaMenu::~QCocoaMenu() @@ -251,14 +269,11 @@ QCocoaMenu::~QCocoaMenu() SET_COCOA_MENU_ANCESTOR(item, 0); } - if (m_containingMenuItem) - m_containingMenuItem->clearMenu(this); - QMacAutoReleasePool pool; - [m_nativeItem setSubmenu:nil]; + NSObject *delegate = m_nativeMenu.delegate; + m_nativeMenu.delegate = nil; + [delegate release]; [m_nativeMenu release]; - [m_delegate release]; - [m_nativeItem release]; } void QCocoaMenu::setText(const QString &text) @@ -266,7 +281,6 @@ void QCocoaMenu::setText(const QString &text) QMacAutoReleasePool pool; QString stripped = qt_mac_removeAmpersandEscapes(text); [m_nativeMenu setTitle:QCFString::toNSString(stripped)]; - [m_nativeItem setTitle:QCFString::toNSString(stripped)]; } void QCocoaMenu::setMinimumWidth(int width) @@ -307,17 +321,13 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem * void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) { - [item->nsItem() setTarget:m_delegate]; + item->nsItem().target = m_nativeMenu.delegate; if (!item->menu()) [item->nsItem() setAction:@selector(itemFired:)]; if (item->isMerged()) return; - if ([item->nsItem() menu]) { - qWarning("Menu item is already in a menu, remove it from the other menu first before inserting"); - return; - } // if the item we're inserting before is merged, skip along until // we find a non-merged real item to insert ahead of. while (beforeItem && beforeItem->isMerged()) { @@ -445,12 +455,11 @@ void QCocoaMenu::setEnabled(bool enabled) bool QCocoaMenu::isEnabled() const { - return [m_nativeItem isEnabled]; + return m_attachedItem ? [m_attachedItem isEnabled] : m_enabled; } void QCocoaMenu::setVisible(bool visible) { - [m_nativeItem setSubmenu:(visible ? m_nativeMenu : nil)]; m_visible = visible; } @@ -587,8 +596,6 @@ void QCocoaMenu::syncModalState(bool modal) if (!m_enabled) modal = true; - [m_nativeItem setEnabled:!modal]; - foreach (QCocoaMenuItem *item, m_menuItems) { if (item->menu()) { // recurse into submenus item->menu()->syncModalState(modal); @@ -599,25 +606,24 @@ void QCocoaMenu::syncModalState(bool modal) } } -void QCocoaMenu::setMenuBar(QCocoaMenuBar *menuBar) +void QCocoaMenu::setAttachedItem(NSMenuItem *item) { - m_menuBar = menuBar; - SET_COCOA_MENU_ANCESTOR(this, menuBar); -} + if (item == m_attachedItem) + return; -QCocoaMenuBar *QCocoaMenu::menuBar() const -{ - return m_menuBar; -} + if (m_attachedItem) + m_attachedItem.submenu = nil; + + m_attachedItem = item; + + if (m_attachedItem) + m_attachedItem.submenu = m_nativeMenu; -void QCocoaMenu::setContainingMenuItem(QCocoaMenuItem *menuItem) -{ - m_containingMenuItem = menuItem; } -QCocoaMenuItem *QCocoaMenu::containingMenuItem() const +NSMenuItem *QCocoaMenu::attachedItem() const { - return m_containingMenuItem; + return m_attachedItem; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h index d5f75abf34..e84da7aeb0 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.h +++ b/src/plugins/platforms/cocoa/qcocoamenubar.h @@ -71,10 +71,10 @@ private: static QCocoaMenuBar *findGlobalMenubar(); bool shouldDisable(QCocoaWindow *active) const; - void insertNativeMenu(QCocoaMenu *menu, QCocoaMenu *beforeMenu); - void removeNativeMenu(QCocoaMenu *menu); - QList m_menus; + NSMenuItem *nativeItemForMenu(QCocoaMenu *menu) const; + + QList > m_menus; NSMenu *m_nativeMenu; QCocoaWindow *m_window; }; diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index 1a516f874b..ac4d29fc52 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -51,7 +51,6 @@ static inline QCocoaMenuLoader *getMenuLoader() return [NSApp QT_MANGLE_NAMESPACE(qt_qcocoamenuLoader)]; } - QCocoaMenuBar::QCocoaMenuBar() : m_window(0) { @@ -68,11 +67,20 @@ QCocoaMenuBar::~QCocoaMenuBar() #ifdef QT_COCOA_ENABLE_MENU_DEBUG qDebug() << "~QCocoaMenuBar" << this; #endif + foreach (QCocoaMenu *menu, m_menus) { + if (!menu) + continue; + NSMenuItem *item = nativeItemForMenu(menu); + if (menu->attachedItem() == item) + menu->setAttachedItem(nil); + } + [m_nativeMenu release]; static_menubars.removeOne(this); if (m_window && m_window->menubar() == this) { m_window->setMenubar(0); + // Delete the children first so they do not cause // the native menu items to be hidden after // the menu bar was updated @@ -81,24 +89,6 @@ QCocoaMenuBar::~QCocoaMenuBar() } } -void QCocoaMenuBar::insertNativeMenu(QCocoaMenu *menu, QCocoaMenu *beforeMenu) -{ - QMacAutoReleasePool pool; - - if (beforeMenu) { - NSUInteger nativeIndex = [m_nativeMenu indexOfItem:beforeMenu->nsMenuItem()]; - [m_nativeMenu insertItem: menu->nsMenuItem() atIndex: nativeIndex]; - } else { - [m_nativeMenu addItem: menu->nsMenuItem()]; - } - - menu->setMenuBar(this); - syncMenu(static_cast(menu)); - if (menu->isVisible()) { - [m_nativeMenu setSubmenu: menu->nsMenu() forItem: menu->nsMenuItem()]; - } -} - void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *before) { QCocoaMenu *menu = static_cast(platformMenu); @@ -107,31 +97,40 @@ void QCocoaMenuBar::insertMenu(QPlatformMenu *platformMenu, QPlatformMenu *befor qDebug() << "QCocoaMenuBar" << this << "insertMenu" << menu << "before" << before; #endif - if (m_menus.contains(menu)) { + if (m_menus.contains(QPointer(menu))) { qWarning("This menu already belongs to the menubar, remove it first"); return; } - if (beforeMenu && !m_menus.contains(beforeMenu)) { + if (beforeMenu && !m_menus.contains(QPointer(beforeMenu))) { qWarning("The before menu does not belong to the menubar"); return; } - m_menus.insert(beforeMenu ? m_menus.indexOf(beforeMenu) : m_menus.size(), menu); - if (!menu->menuBar()) - insertNativeMenu(menu, beforeMenu); - if (m_window && m_window->window()->isActive()) - updateMenuBarImmediately(); -} + int insertionIndex = beforeMenu ? m_menus.indexOf(beforeMenu) : m_menus.size(); + m_menus.insert(insertionIndex, menu); + + { + QMacAutoReleasePool pool; + NSMenuItem *item = [[[NSMenuItem alloc] init] autorelease]; + item.tag = reinterpret_cast(menu); + + if (beforeMenu) { + // QMenuBar::toNSMenu() exposes the native menubar and + // the user could have inserted its own items in there. + // Same remark applies to removeMenu(). + NSMenuItem *beforeItem = nativeItemForMenu(beforeMenu); + NSInteger nativeIndex = [m_nativeMenu indexOfItem:beforeItem]; + [m_nativeMenu insertItem:item atIndex:nativeIndex]; + } else { + [m_nativeMenu addItem:item]; + } + } -void QCocoaMenuBar::removeNativeMenu(QCocoaMenu *menu) -{ - QMacAutoReleasePool pool; + syncMenu(menu); - if (menu->menuBar() == this) - menu->setMenuBar(0); - NSUInteger realIndex = [m_nativeMenu indexOfItem:menu->nsMenuItem()]; - [m_nativeMenu removeItemAtIndex: realIndex]; + if (m_window && m_window->window()->isActive()) + updateMenuBarImmediately(); } void QCocoaMenuBar::removeMenu(QPlatformMenu *platformMenu) @@ -141,8 +140,17 @@ void QCocoaMenuBar::removeMenu(QPlatformMenu *platformMenu) qWarning("Trying to remove a menu that does not belong to the menubar"); return; } + + NSMenuItem *item = nativeItemForMenu(menu); + if (menu->attachedItem() == item) + menu->setAttachedItem(nil); m_menus.removeOne(menu); - removeNativeMenu(menu); + + QMacAutoReleasePool pool; + + // See remark in insertMenu(). + NSInteger nativeIndex = [m_nativeMenu indexOfItem:item]; + [m_nativeMenu removeItemAtIndex:nativeIndex]; } void QCocoaMenuBar::syncMenu(QPlatformMenu *menu) @@ -164,7 +172,16 @@ void QCocoaMenuBar::syncMenu(QPlatformMenu *menu) break; } } - [cocoaMenu->nsMenuItem() setHidden:shouldHide]; + + nativeItemForMenu(cocoaMenu).hidden = shouldHide; +} + +NSMenuItem *QCocoaMenuBar::nativeItemForMenu(QCocoaMenu *menu) const +{ + if (!menu) + return nil; + + return [m_nativeMenu itemWithTag:reinterpret_cast(menu)]; } void QCocoaMenuBar::handleReparent(QWindow *newParentWindow) @@ -291,24 +308,16 @@ void QCocoaMenuBar::updateMenuBarImmediately() qDebug() << "QCocoaMenuBar" << "updateMenuBarImmediately" << cw; #endif bool disableForModal = mb->shouldDisable(cw); - // force a sync? - foreach (QCocoaMenu *m, mb->m_menus) { - mb->syncMenu(m); - m->syncModalState(disableForModal); - } - // reparent shared menu items if necessary. - // We browse the list in reverse order to be sure that the next items are redrawn before the current ones, - // in this way we are sure that "beforeMenu" (see below) is part of the native menu before "m" is redraw - for (int i = mb->m_menus.size() - 1; i >= 0; i--) { - QCocoaMenu *m = mb->m_menus.at(i); - QCocoaMenuBar *menuBar = m->menuBar(); - if (menuBar != mb) { - QCocoaMenu *beforeMenu = i < (mb->m_menus.size() - 1) ? mb->m_menus.at(i + 1) : 0; - if (menuBar) - menuBar->removeNativeMenu(m); - mb->insertNativeMenu(m, beforeMenu); - } + foreach (QCocoaMenu *menu, mb->m_menus) { + if (!menu) + continue; + NSMenuItem *item = mb->nativeItemForMenu(menu); + menu->setAttachedItem(item); + SET_COCOA_MENU_ANCESTOR(menu, mb); + // force a sync? + mb->syncMenu(menu); + menu->syncModalState(disableForModal); } QCocoaMenuLoader *loader = getMenuLoader(); diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index 1cd15e686c..ada4b13df1 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -87,7 +87,6 @@ public: inline bool isSeparator() const { return m_isSeparator; } QCocoaMenu *menu() const { return m_menu; } - void clearMenu(QCocoaMenu *menu); MenuRole effectiveRole() const; private: @@ -99,7 +98,7 @@ private: QString m_text; bool m_textSynced; QIcon m_icon; - QCocoaMenu *m_menu; + QPointer m_menu; bool m_isVisible; bool m_enabled; bool m_isSeparator; diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index 0f551bcd7d..e274448620 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -134,15 +134,12 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu) if (m_menu) { if (COCOA_MENU_ANCESTOR(m_menu) == this) SET_COCOA_MENU_ANCESTOR(m_menu, 0); - if (m_menu->containingMenuItem() == this) - m_menu->setContainingMenuItem(0); } QMacAutoReleasePool pool; m_menu = static_cast(menu); if (m_menu) { SET_COCOA_MENU_ANCESTOR(m_menu, this); - m_menu->setContainingMenuItem(this); } else { // we previously had a menu, but no longer // clear out our item so the nexy sync() call builds a new one @@ -151,12 +148,6 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu) } } -void QCocoaMenuItem::clearMenu(QCocoaMenu *menu) -{ - if (menu == m_menu) - m_menu = 0; -} - void QCocoaMenuItem::setVisible(bool isVisible) { m_isVisible = isVisible; @@ -218,14 +209,6 @@ NSMenuItem *QCocoaMenuItem::sync() m_native = nil; } - if (m_menu) { - if (m_native != m_menu->nsMenuItem()) { - [m_native release]; - m_native = [m_menu->nsMenuItem() retain]; - [m_native setTag:reinterpret_cast(this)]; - } - } - if ((m_role != NoRole && !m_textSynced) || m_merged) { NSMenuItem *mergeItem = nil; QCocoaMenuLoader *loader = getMenuLoader(); -- cgit v1.2.3 From e4cea305ed2ba3c9f580bf9d16c59a1048af0e8a Mon Sep 17 00:00:00 2001 From: David Rosca Date: Wed, 16 Mar 2016 08:35:22 +0100 Subject: xcb: Merge _NET_WM_STATE hints instead of overwriting This makes possible to set custom _NET_WM_STATE hints before showing the window. Change-Id: I86ad3863f7a8b3bb610a31b9af4b02c9d38eb111 Task-number: QTBUG-26978 Reviewed-by: Ilya Kotov Reviewed-by: Shawn Rutledge Reviewed-by: Uli Schlachter --- src/plugins/platforms/xcb/qxcbwindow.cpp | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index a0b1ddb434..f4c455f278 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1091,21 +1091,37 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates() void QXcbWindow::setNetWmStates(NetWmStates states) { QVector atoms; - if (states & NetWmStateAbove) + + xcb_get_property_cookie_t get_cookie = + xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), + XCB_ATOM_ATOM, 0, 1024); + + xcb_get_property_reply_t *reply = + xcb_get_property_reply(xcb_connection(), get_cookie, NULL); + + if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM && reply->value_len > 0) { + const xcb_atom_t *data = static_cast(xcb_get_property_value(reply)); + atoms.resize(reply->value_len); + memcpy((void *)&atoms.first(), (void *)data, reply->value_len * sizeof(xcb_atom_t)); + } + + free(reply); + + if (states & NetWmStateAbove && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_ABOVE))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE)); - if (states & NetWmStateBelow) + if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW)); - if (states & NetWmStateFullScreen) + if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); - if (states & NetWmStateMaximizedHorz) + if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)); - if (states & NetWmStateMaximizedVert) + if (states & NetWmStateMaximizedVert && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)); - if (states & NetWmStateModal) + if (states & NetWmStateModal && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MODAL))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MODAL)); - if (states & NetWmStateStaysOnTop) + if (states & NetWmStateStaysOnTop && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP)); - if (states & NetWmStateDemandsAttention) + if (states & NetWmStateDemandsAttention && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION))) atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)); if (atoms.isEmpty()) { -- cgit v1.2.3