diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-03-31 10:03:31 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-03-31 10:03:31 +0200 |
commit | ce9519593a0b3deb99d1dd2529770f7e9fffef92 (patch) | |
tree | c9bca05230dd68f49494240ae930bad1fe0c5956 /src/plugins/platforms | |
parent | 509f77cca28aa3edea5523c5869bae4412ed2ccc (diff) | |
parent | 7baaec17edb06634f1d6235a55c7adbd112cba3e (diff) |
Diffstat (limited to 'src/plugins/platforms')
18 files changed, 141 insertions, 86 deletions
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index e887a4ebdc..cf81f92e47 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -42,6 +42,7 @@ #include "androidjniinput.h" #include "androidjniclipboard.h" #include "androidjnimenu.h" +#include "androiddeadlockprotector.h" #include "qandroidplatformdialoghelpers.h" #include "qandroidplatformintegration.h" #include "qandroidassetsfileenginehandler.h" @@ -595,11 +596,22 @@ static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state } if (state <= Qt::ApplicationInactive) { + // NOTE: sometimes we will receive two consecutive suspended notifications, + // In the second suspended notification, QWindowSystemInterface::flushWindowSystemEvents() + // will deadlock since the dispatcher has been stopped in the first suspended notification. + // To avoid the deadlock we simply return if we found the event dispatcher has been stopped. + if (QAndroidEventDispatcherStopper::instance()->stopped()) + return; + // Don't send timers and sockets events anymore if we are going to hide all windows QAndroidEventDispatcherStopper::instance()->goingToStop(true); QCoreApplication::processEvents(); QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState(state)); - QWindowSystemInterface::flushWindowSystemEvents(); + { + AndroidDeadlockProtector protector; + if (protector.acquire()) + QWindowSystemInterface::flushWindowSystemEvents(); + } if (state == Qt::ApplicationSuspended) QAndroidEventDispatcherStopper::instance()->stopAll(); } else { diff --git a/src/plugins/platforms/android/qandroideventdispatcher.cpp b/src/plugins/platforms/android/qandroideventdispatcher.cpp index b83d148ce8..aecea0d4e1 100644 --- a/src/plugins/platforms/android/qandroideventdispatcher.cpp +++ b/src/plugins/platforms/android/qandroideventdispatcher.cpp @@ -33,6 +33,7 @@ #include "qandroideventdispatcher.h" #include "androidjnimain.h" +#include "androiddeadlockprotector.h" QAndroidEventDispatcher::QAndroidEventDispatcher(QObject *parent) : QUnixEventDispatcherQPA(parent) @@ -78,11 +79,13 @@ void QAndroidEventDispatcher::goingToStop(bool stop) int QAndroidEventDispatcher::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, timespec *timeout) { - if (m_stopRequest.testAndSetAcquire(StopRequest, Stopping)) { - m_semaphore.acquire(); - wakeUp(); + { + AndroidDeadlockProtector protector; + if (protector.acquire() && m_stopRequest.testAndSetAcquire(StopRequest, Stopping)) { + m_semaphore.acquire(); + wakeUp(); + } } - return QUnixEventDispatcherQPA::select(nfds, readfds, writefds, exceptfds, timeout); } diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp index b43c714482..cc2a394d6e 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp @@ -97,11 +97,15 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags if (!str.isEmpty()) m_javaMessageDialog.callMethod<void>("setDetailedText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object()); - for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) { - if ( opt->standardButtons() & i ) { - const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(i); - m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", i, QJNIObjectPrivate::fromString(text).object()); - } + // http://developer.android.com/design/building-blocks/dialogs.html + // dismissive action on the left, affirmative on the right + // There don't seem to be more fine-grained rules, but the OS X layout + // at least conforms to this one rule and makes the rest deterministic. + const int * currentLayout = buttonLayout(Qt::Horizontal, MacLayout); + while (*currentLayout != QPlatformDialogHelper::EOL) { + int role = (*currentLayout & ~QPlatformDialogHelper::Reverse); + addButtons(opt, static_cast<ButtonRole>(role)); + ++currentLayout; } m_javaMessageDialog.callMethod<void>("show", "(J)V", jlong(static_cast<QObject*>(this))); @@ -109,6 +113,17 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags return true; } +void QAndroidPlatformMessageDialogHelper::addButtons(QSharedPointer<QMessageDialogOptions> opt, ButtonRole role) +{ + for (int i = QPlatformDialogHelper::FirstButton; i < QPlatformDialogHelper::LastButton; i<<=1) { + StandardButton b = static_cast<StandardButton>(i); + if (buttonRole(b) == role && (opt->standardButtons() & i)) { + const QString text = QGuiApplicationPrivate::platformTheme()->standardButtonText(b); + m_javaMessageDialog.callMethod<void>("addButton", "(ILjava/lang/String;)V", i, QJNIObjectPrivate::fromString(text).object()); + } + } +} + void QAndroidPlatformMessageDialogHelper::hide() { m_javaMessageDialog.callMethod<void>("hide", "()V"); diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.h b/src/plugins/platforms/android/qandroidplatformdialoghelpers.h index a70468000f..94f01a1835 100644 --- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.h +++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.h @@ -57,6 +57,9 @@ public slots: void dialogResult(int buttonID); private: + void addButtons(QSharedPointer<QMessageDialogOptions> opt, ButtonRole role); + +private: int m_buttonId; QEventLoop m_loop; QJNIObjectPrivate m_javaMessageDialog; diff --git a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp index c951e6f938..9b60ab291c 100644 --- a/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp +++ b/src/plugins/platforms/android/qandroidplatformfontdatabase.cpp @@ -51,10 +51,10 @@ void QAndroidPlatformFontDatabase::populateFontDatabase() qPrintable(fontpath)); } - QDir dir(fontpath, QLatin1String("*.ttf")); - for (int i = 0; i < int(dir.count()); ++i) { - const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); - + QDir dir(fontpath); + QList<QFileInfo> entries = dir.entryInfoList(QStringList() << QStringLiteral("*.ttf") << QStringLiteral("*.otf"), QDir::Files); + for (int i = 0; i < int(entries.count()); ++i) { + const QByteArray file = QFile::encodeName(entries.at(i).absoluteFilePath()); QSupportedWritingSystems supportedWritingSystems; QStringList families = addTTFile(QByteArray(), file, &supportedWritingSystems); diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index 000a47c7b4..f50f552623 100755 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -94,7 +94,6 @@ QT_USE_NAMESPACE QCocoaSystemTrayIcon *systray; NSStatusItem *item; QCocoaMenu *menu; - bool menuVisible; QIcon icon; QT_MANGLE_NAMESPACE(QNSImageView) *imageCell; } @@ -194,8 +193,6 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) m_sys->item->icon = icon; - const bool menuVisible = m_sys->item->menu && m_sys->item->menuVisible; - // The reccomended maximum title bar icon height is 18 points // (device independent pixels). The menu height on past and // current OS X versions is 22 points. Provide some future-proofing @@ -210,9 +207,8 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) // devicePixelRatio for the "best" screen on the system. qreal devicePixelRatio = qApp->devicePixelRatio(); const int maxPixmapHeight = maxImageHeight * devicePixelRatio; - const QIcon::Mode mode = menuVisible ? QIcon::Selected : QIcon::Normal; QSize selectedSize; - Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes(mode))) { + Q_FOREACH (const QSize& size, sortByHeight(icon.availableSizes())) { // Select a pixmap based on the height. We want the largest pixmap // with a height smaller or equal to maxPixmapHeight. The pixmap // may rectangular; assume it has a reasonable size. If there is @@ -226,7 +222,11 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) } } - QPixmap pixmap = icon.pixmap(selectedSize, mode); + // Handle SVG icons, which do not return anything for availableSizes(). + if (!selectedSize.isValid()) + selectedSize = icon.actualSize(QSize(maxPixmapHeight, maxPixmapHeight)); + + QPixmap pixmap = icon.pixmap(selectedSize); // Draw a low-resolution icon if there is not enough pixels for a retina // icon. This prevents showing a small icon on retina displays. @@ -373,9 +373,6 @@ QT_END_NAMESPACE Q_UNUSED(notification); down = NO; - parent->systray->updateIcon(parent->icon); - parent->menuVisible = false; - [self setNeedsDisplay:YES]; } @@ -385,8 +382,6 @@ QT_END_NAMESPACE int clickCount = [mouseEvent clickCount]; [self setNeedsDisplay:YES]; - parent->systray->updateIcon(parent->icon); - if (clickCount == 2) { [self menuTrackingDone:nil]; [parent doubleClickSelector:self]; @@ -442,7 +437,6 @@ QT_END_NAMESPACE if (self) { item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain]; menu = 0; - menuVisible = false; systray = sys; imageCell = [[QNSImageView alloc] initWithParent:self]; [item setView: imageCell]; @@ -486,7 +480,6 @@ QT_END_NAMESPACE selector:@selector(menuTrackingDone:) name:NSMenuDidEndTrackingNotification object:m]; - menuVisible = true; [item popUpStatusItemMenu: m]; } } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index f811bd630f..bc40bbb6ce 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -74,31 +74,6 @@ static bool isMouseEvent(NSEvent *ev) } } -static void selectNextKeyWindow(NSWindow *currentKeyWindow) -{ - if (!currentKeyWindow) - return; - - const QCocoaAutoReleasePool pool; - - if ([[NSApplication sharedApplication] keyWindow] != currentKeyWindow) - return;//currentKeyWindow is not a key window actually. - - NSArray *const windows = [[NSApplication sharedApplication] windows]; - bool startLookup = false; - for (NSWindow *candidate in [windows reverseObjectEnumerator]) { - if (!startLookup) { - if (candidate == currentKeyWindow) - startLookup = true; - } else { - if ([candidate isVisible] && [candidate canBecomeKeyWindow]) { - [candidate makeKeyWindow]; - break; - } - } - } -} - @implementation QNSWindowHelper @synthesize window = _window; @@ -607,9 +582,6 @@ void QCocoaWindow::hide(bool becauseOfAncestor) foreach (QCocoaWindow *childWindow, m_childWindows) childWindow->hide(true); - if (window()->transientParent() && m_nsWindow == [[NSApplication sharedApplication] keyWindow]) - selectNextKeyWindow(m_nsWindow); // Otherwise, Cocoa can do it wrong. - [m_nsWindow orderOut:nil]; } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 0b0dcc4322..3a3a17a474 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -368,6 +368,8 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; // calles, which Qt and Qt applications do not excpect. if (!m_platformWindow->m_inSetGeometry) QWindowSystemInterface::flushWindowSystemEvents(); + else + m_backingStore = QImage(); } } @@ -956,6 +958,7 @@ QT_WARNING_POP if (m_window->flags() & Qt::WindowTransparentForInput) return [super rightMouseDown:theEvent]; m_buttons |= Qt::RightButton; + m_sendUpAsRightButton = true; [self handleMouseEvent:theEvent]; } @@ -973,6 +976,7 @@ QT_WARNING_POP if (m_window->flags() & Qt::WindowTransparentForInput) return [super rightMouseUp:theEvent]; m_buttons &= ~Qt::RightButton; + m_sendUpAsRightButton = false; [self handleMouseEvent:theEvent]; } diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h index f9a55c9940..63c083d233 100644 --- a/src/plugins/platforms/windows/qtwindowsglobal.h +++ b/src/plugins/platforms/windows/qtwindowsglobal.h @@ -57,7 +57,8 @@ enum TouchEventFlag = 0x400000, ClipboardEventFlag = 0x800000, ApplicationEventFlag = 0x1000000, - ThemingEventFlag = 0x2000000 + ThemingEventFlag = 0x2000000, + GenericEventFlag = 0x4000000, // Misc }; enum WindowsEventType // Simplify event types @@ -108,6 +109,7 @@ enum WindowsEventType // Simplify event types CompositionSettingsChanged = ThemingEventFlag + 2, DisplayChangedEvent = 437, SettingChangedEvent = DisplayChangedEvent + 1, + ScrollEvent = GenericEventFlag + 1, ContextMenu = 123, GestureEvent = 124, UnknownEvent = 542 @@ -145,6 +147,8 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI return QtWindows::CursorEvent; case WM_MOUSELEAVE: return QtWindows::MouseEvent; + case WM_HSCROLL: + return QtWindows::ScrollEvent; case WM_MOUSEWHEEL: case WM_MOUSEHWHEEL: return QtWindows::MouseWheelEvent; diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 7264fdcbb6..7d7ea031a5 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1037,6 +1037,12 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return true; } #endif + case QtWindows::ScrollEvent: +#if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) + return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result); +#else + return d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result); +#endif case QtWindows::MouseWheelEvent: case QtWindows::MouseEvent: case QtWindows::LeaveEvent: diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.h b/src/plugins/platforms/windows/qwindowsinputcontext.h index 2f87d7d677..83a39989f6 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.h +++ b/src/plugins/platforms/windows/qwindowsinputcontext.h @@ -73,6 +73,7 @@ public: bool startComposition(HWND hwnd); bool composition(HWND hwnd, LPARAM lParam); bool endComposition(HWND hwnd); + inline bool isComposing() const { return m_compositionContext.isComposing; } int reconvertString(RECONVERTSTRING *reconv); diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 0e26a17223..d47c7df9e0 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -36,6 +36,7 @@ #include "qwindowswindow.h" #include "qwindowsguieventdispatcher.h" #include "qwindowsscaling.h" +#include "qwindowsinputcontext.h" #include <QtGui/QWindow> #include <qpa/qwindowsysteminterface.h> @@ -877,7 +878,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms const int msgType = msg.message; const quint32 scancode = (msg.lParam >> 16) & scancodeBitmask; - const quint32 vk_key = msg.wParam; + quint32 vk_key = msg.wParam; quint32 nModifiers = 0; QWindow *receiver = m_keyGrabber ? m_keyGrabber : window; @@ -1071,6 +1072,8 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms // results, if we map this virtual key-code directly (for eg '?' US layouts). So try // to find the correct key using the current message parameters & keyboard state. if (uch.isNull() && msgType == WM_IME_KEYDOWN) { + if (!QWindowsInputContext::instance()->isComposing()) + vk_key = ImmGetVirtualKey((HWND)window->winId()); BYTE keyState[256]; wchar_t newKey[3] = {0}; GetKeyboardState(keyState); diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index b1ced95a71..db635b602b 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -42,6 +42,7 @@ #include <QtGui/QGuiApplication> #include <QtGui/QScreen> #include <QtGui/QWindow> +#include <QtGui/QCursor> #include <QtCore/QDebug> #include <QtCore/QScopedArrayPointer> @@ -386,6 +387,31 @@ static bool isValidWheelReceiver(QWindow *candidate) return false; } +static void redirectWheelEvent(QWindow *window, const QPoint &globalPos, int delta, + Qt::Orientation orientation, Qt::KeyboardModifiers mods) +{ + // Redirect wheel event to one of the following, in order of preference: + // 1) The window under mouse + // 2) The window receiving the event + // If a window is blocked by modality, it can't get the event. + + QWindow *receiver = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE); + bool handleEvent = true; + if (!isValidWheelReceiver(receiver)) { + receiver = window; + if (!isValidWheelReceiver(receiver)) + handleEvent = false; + } + + if (handleEvent) { + const QPoint posDip = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos) / QWindowsScaling::factor(); + QWindowSystemInterface::handleWheelEvent(receiver, + posDip, globalPos / QWindowsScaling::factor(), + delta / QWindowsScaling::factor(), + orientation, mods); + } +} + bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND, MSG msg, LRESULT *) { @@ -408,27 +434,40 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND, if (msg.message == WM_MOUSEHWHEEL) delta = -delta; - // Redirect wheel event to one of the following, in order of preference: - // 1) The window under mouse - // 2) The window receiving the event - // If a window is blocked by modality, it can't get the event. const QPoint globalPos(GET_X_LPARAM(msg.lParam), GET_Y_LPARAM(msg.lParam)); - QWindow *receiver = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE); - bool handleEvent = true; - if (!isValidWheelReceiver(receiver)) { - receiver = window; - if (!isValidWheelReceiver(receiver)) - handleEvent = false; - } + redirectWheelEvent(window, globalPos, delta, orientation, mods); - if (handleEvent) { - const QPoint posDip = QWindowsGeometryHint::mapFromGlobal(receiver, globalPos) / QWindowsScaling::factor(); - QWindowSystemInterface::handleWheelEvent(receiver, - posDip, globalPos / QWindowsScaling::factor(), - delta / QWindowsScaling::factor(), - orientation, mods); + return true; +} + +bool QWindowsMouseHandler::translateScrollEvent(QWindow *window, HWND, + MSG msg, LRESULT *) +{ + // This is a workaround against some touchpads that send WM_HSCROLL instead of WM_MOUSEHWHEEL. + // We could also handle vertical scroll here but there's no reason to, there's no bug for vertical + // (broken vertical scroll would have been noticed long time ago), so lets keep the change small + // and minimize the chance for regressions. + + int delta = 0; + switch (LOWORD(msg.wParam)) { + case SB_LINELEFT: + delta = 120; + break; + case SB_LINERIGHT: + delta = -120; + break; + case SB_PAGELEFT: + delta = 240; + break; + case SB_PAGERIGHT: + delta = -240; + break; + default: + return false; } + redirectWheelEvent(window, QCursor::pos(), delta, Qt::Horizontal, Qt::NoModifier); + return true; } diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.h b/src/plugins/platforms/windows/qwindowsmousehandler.h index 1bd6fa325a..ce3e6b6fc4 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.h +++ b/src/plugins/platforms/windows/qwindowsmousehandler.h @@ -59,6 +59,8 @@ public: bool translateTouchEvent(QWindow *widget, HWND hwnd, QtWindows::WindowsEventType t, MSG msg, LRESULT *result); + bool translateScrollEvent(QWindow *window, HWND hwnd, + MSG msg, LRESULT *result); static inline Qt::MouseButtons keyStateToMouseButtons(int); static inline Qt::KeyboardModifiers keyStateToModifiers(int); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index fc389ecf15..a43bf53fa3 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -918,7 +918,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) setFlag(OpenGL_ES2); } #endif // QT_NO_OPENGL - updateDropSite(); + updateDropSite(window()->isTopLevel()); registerTouchWindow(); setWindowState(aWindow->windowState()); @@ -996,10 +996,10 @@ void QWindowsWindow::destroyWindow() } } -void QWindowsWindow::updateDropSite() +void QWindowsWindow::updateDropSite(bool topLevel) { bool enabled = false; - if (window()->isTopLevel()) { + if (topLevel) { switch (window()->type()) { case Qt::Window: case Qt::Dialog: @@ -1285,7 +1285,7 @@ void QWindowsWindow::setParent_sys(const QPlatformWindow *parent) if (wasTopLevel != isTopLevel) { setDropSiteEnabled(false); setWindowFlags_sys(window()->flags(), unsigned(isTopLevel ? WindowCreationData::ForceTopLevel : WindowCreationData::ForceChild)); - updateDropSite(); + updateDropSite(isTopLevel); } } } @@ -1539,7 +1539,7 @@ void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags) m_data.flags = flags; if (m_data.hwnd) { m_data = setWindowFlags_sys(flags); - updateDropSite(); + updateDropSite(window()->isTopLevel()); } } // When switching to a frameless window, geometry diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 0089ad07a0..fff90b4b11 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -276,7 +276,7 @@ private: void destroyWindow(); inline bool isDropSiteEnabled() const { return m_dropTarget != 0; } void setDropSiteEnabled(bool enabled); - void updateDropSite(); + void updateDropSite(bool topLevel); void handleGeometryChange(); void handleWindowStateChange(Qt::WindowState state); inline void destroyIcon(); diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 06db4d83ac..c0f5477f82 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -157,7 +157,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI xcb_generic_error_t *error = NULL; if (shm_present) error = xcb_request_check(xcb_connection(), xcb_shm_attach_checked(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false)); - if (!shm_present || error) { + if (!shm_present || error || id == -1) { free(error); shmdt(m_shm_info.shmaddr); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 1406270994..eed8b19013 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -313,11 +313,6 @@ void QXcbWindow::create() return; } - // Determine gravity from initial position. Do not change - // later as it will cause the window to move uncontrollably. - m_gravity = positionIncludesFrame(window()) ? - XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC; - const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER | XCB_CW_EVENT_MASK; const quint32 values[] = { // XCB_CW_BACK_PIXMAP @@ -739,6 +734,9 @@ void QXcbWindow::show() xcb_set_wm_hints(xcb_connection(), m_window, &hints); + m_gravity = positionIncludesFrame(window()) ? + XCB_GRAVITY_NORTH_WEST : XCB_GRAVITY_STATIC; + // update WM_NORMAL_HINTS propagateSizeHints(); |