diff options
Diffstat (limited to 'src/plugins/platforms')
31 files changed, 199 insertions, 62 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 6f99dc458a..e4b52b9454 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -56,8 +56,11 @@ class QCocoaNativeInterface : public QPlatformNativeInterface public: QCocoaNativeInterface(); + void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context); void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window); + static void *cglContextForContext(QOpenGLContext *context); + public Q_SLOTS: void onAppFocusWindowChanged(QWindow *window); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index e5040080ed..7f37b971d7 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -65,6 +65,17 @@ QCocoaNativeInterface::QCocoaNativeInterface() { } +void *QCocoaNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) +{ + if (!context) + return 0; + + if (resourceString.toLower() == "cglcontextobj") + return cglContextForContext(context); + + return 0; +} + void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) { if (!window->handle()) { @@ -109,4 +120,17 @@ void QCocoaNativeInterface::onAppFocusWindowChanged(QWindow *window) QCocoaMenuBar::updateMenuBarImmediately(); } +void *QCocoaNativeInterface::cglContextForContext(QOpenGLContext* context) +{ + if (context) { + QCocoaGLContext *cocoaGLContext = static_cast<QCocoaGLContext *>(context->handle()); + if (cocoaGLContext) { + NSOpenGLContext *nsOpenGLContext = cocoaGLContext->nsOpenGLContext(); + if (nsOpenGLContext) + return [nsOpenGLContext CGLContextObj]; + } + } + return 0; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 4a146767d5..014db378e7 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -98,7 +98,7 @@ public: void setGeometry(const QRect &rect); void setCocoaGeometry(const QRect &rect); void setVisible(bool visible); - Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); + void setWindowFlags(Qt::WindowFlags flags); Qt::WindowState setWindowState(Qt::WindowState state); void setWindowTitle(const QString &title); void setWindowFilePath(const QString &filePath); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 26161b106e..f4a4936c28 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -387,7 +387,7 @@ void QCocoaWindow::setWindowShadow(Qt::WindowFlags flags) [m_nsWindow setHasShadow:(keepShadow ? YES : NO)]; } -Qt::WindowFlags QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) +void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) { if (m_nsWindow) { NSUInteger styleMask = windowStyleMask(flags); @@ -398,7 +398,6 @@ Qt::WindowFlags QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) } m_windowFlags = flags; - return m_windowFlags; } Qt::WindowState QCocoaWindow::setWindowState(Qt::WindowState state) diff --git a/src/plugins/platforms/directfb/qdirectfbwindow.cpp b/src/plugins/platforms/directfb/qdirectfbwindow.cpp index 8b108eeaa2..630e4fd7a2 100644 --- a/src/plugins/platforms/directfb/qdirectfbwindow.cpp +++ b/src/plugins/platforms/directfb/qdirectfbwindow.cpp @@ -140,7 +140,7 @@ void QDirectFbWindow::setVisible(bool visible) QWindowSystemInterface::handleExposeEvent(window(), window()->geometry()); } -Qt::WindowFlags QDirectFbWindow::setWindowFlags(Qt::WindowFlags flags) +void QDirectFbWindow::setWindowFlags(Qt::WindowFlags flags) { switch (flags & Qt::WindowType_Mask) { case Qt::ToolTip: { @@ -154,7 +154,6 @@ Qt::WindowFlags QDirectFbWindow::setWindowFlags(Qt::WindowFlags flags) } m_dfbWindow->SetStackingClass(m_dfbWindow.data(), flags & Qt::WindowStaysOnTopHint ? DWSC_UPPER : DWSC_MIDDLE); - return flags; } void QDirectFbWindow::raise() diff --git a/src/plugins/platforms/directfb/qdirectfbwindow.h b/src/plugins/platforms/directfb/qdirectfbwindow.h index cedd140809..3edee7c6b2 100644 --- a/src/plugins/platforms/directfb/qdirectfbwindow.h +++ b/src/plugins/platforms/directfb/qdirectfbwindow.h @@ -60,7 +60,7 @@ public: void setVisible(bool visible); - Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); + void setWindowFlags(Qt::WindowFlags flags); bool setKeyboardGrabEnabled(bool grab); bool setMouseGrabEnabled(bool grab); void raise(); diff --git a/src/plugins/platforms/qnx/qqnxbuffer.cpp b/src/plugins/platforms/qnx/qqnxbuffer.cpp index ed3ea49d44..9007af7f70 100644 --- a/src/plugins/platforms/qnx/qqnxbuffer.cpp +++ b/src/plugins/platforms/qnx/qqnxbuffer.cpp @@ -88,7 +88,7 @@ QQnxBuffer::QQnxBuffer(screen_buffer_t buffer) if (result != 0) { qFatal("QQNX: failed to query buffer pointer, errno=%d", errno); } - if (dataPtr == NULL) { + if (dataPtr == 0) { qFatal("QQNX: buffer pointer is NULL, errno=%d", errno); } diff --git a/src/plugins/platforms/qnx/qqnxbuffer.h b/src/plugins/platforms/qnx/qqnxbuffer.h index 7788778a4a..d5adeb8d8b 100644 --- a/src/plugins/platforms/qnx/qqnxbuffer.h +++ b/src/plugins/platforms/qnx/qqnxbuffer.h @@ -57,8 +57,8 @@ public: virtual ~QQnxBuffer(); screen_buffer_t nativeBuffer() const { return m_buffer; } - const QImage *image() const { return (m_buffer != NULL) ? &m_image : NULL; } - QImage *image() { return (m_buffer != NULL) ? &m_image : NULL; } + const QImage *image() const { return (m_buffer != 0) ? &m_image : 0; } + QImage *image() { return (m_buffer != 0) ? &m_image : 0; } QRect rect() const { return m_image.rect(); } diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp index 72a967d5e5..30ca8a5c48 100644 --- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp +++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp @@ -571,7 +571,7 @@ spannable_string_t *toSpannableString(const QString &text) spannable_string_t *pString = reinterpret_cast<spannable_string_t *>(malloc(sizeof(spannable_string_t))); pString->str = (wchar_t *)malloc(sizeof(wchar_t) * text.length() + 1); pString->length = text.length(); - pString->spans = NULL; + pString->spans = 0; pString->spans_count = 0; const QChar *pData = text.constData(); @@ -601,7 +601,7 @@ static bool s_imfInitFailed = false; static bool imfAvailable() { - static bool s_imfDisabled = getenv("DISABLE_IMF") != NULL; + static bool s_imfDisabled = getenv("DISABLE_IMF") != 0; static bool s_imfReady = false; if ( s_imfInitFailed || s_imfDisabled) { @@ -611,7 +611,7 @@ static bool imfAvailable() return true; } - if ( p_imf_client_init == NULL ) { + if ( p_imf_client_init == 0 ) { void *handle = dlopen("libinput_client.so.1", 0); if ( handle ) { p_imf_client_init = (int32_t (*)()) dlsym(handle, "imf_client_init"); @@ -632,8 +632,8 @@ static bool imfAvailable() s_imfReady = true; } else { - p_ictrl_open_session = NULL; - p_ictrl_dispatch_event = NULL; + p_ictrl_open_session = 0; + p_ictrl_dispatch_event = 0; s_imfDisabled = true; qCritical() << Q_FUNC_INFO << "libinput_client.so.1 did not contain the correct symbols, library mismatch? IMF services are disabled."; return false; diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp index 6a092f01a0..593bec8458 100644 --- a/src/plugins/platforms/qnx/qqnxscreen.cpp +++ b/src/plugins/platforms/qnx/qqnxscreen.cpp @@ -524,7 +524,7 @@ void QQnxScreen::newWindowCreated(void *window) { Q_ASSERT(thread() == QThread::currentThread()); const screen_window_t windowHandle = reinterpret_cast<screen_window_t>(window); - screen_display_t display = NULL; + screen_display_t display = 0; if (screen_get_window_property_pv(windowHandle, SCREEN_PROPERTY_DISPLAY, (void**)&display) != 0) { qWarning("QQnx: Failed to get screen for window, errno=%d", errno); return; diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index 621440ed53..d8712bf569 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -462,7 +462,7 @@ void QQnxScreenEventHandler::handleCreateEvent(screen_event_t event) void QQnxScreenEventHandler::handleDisplayEvent(screen_event_t event) { - screen_display_t nativeDisplay = NULL; + screen_display_t nativeDisplay = 0; if (screen_get_event_property_pv(event, SCREEN_PROPERTY_DISPLAY, (void **)&nativeDisplay) != 0) { qWarning("QQnx: failed to query display property, errno=%d", errno); return; diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp index 4618b90f81..ab912927bb 100644 --- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp +++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.cpp @@ -130,7 +130,7 @@ bool QQnxVirtualKeyboardPps::connect() m_decoder = new pps_decoder_t; pps_encoder_initialize(m_encoder, false); - pps_decoder_initialize(m_decoder, NULL); + pps_decoder_initialize(m_decoder, 0); errno = 0; m_fd = ::open(ms_PPSPath, O_RDWR); @@ -197,7 +197,7 @@ void QQnxVirtualKeyboardPps::ppsDataReady() m_buffer[nread] = 0; pps_decoder_parse_pps_str(m_decoder, m_buffer); - pps_decoder_push(m_decoder, NULL); + pps_decoder_push(m_decoder, 0); #if defined(QQNXVIRTUALKEYBOARD_DEBUG) pps_decoder_dump_tree(m_decoder, stderr); #endif diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h index 6eb3bdee10..73f963b6b8 100644 --- a/src/plugins/platforms/windows/qtwindowsglobal.h +++ b/src/plugins/platforms/windows/qtwindowsglobal.h @@ -104,6 +104,7 @@ enum WindowsEventType // Simplify event types InputMethodRequest = InputMethodEventFlag + 6, ThemeChanged = ThemingEventFlag + 1, DisplayChangedEvent = 437, + SettingChangedEvent = DisplayChangedEvent + 1, UnknownEvent = 542 }; @@ -184,6 +185,11 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI return QtWindows::FocusInEvent; case WM_KILLFOCUS: return QtWindows::FocusOutEvent; + // Among other things, WM_SETTINGCHANGE happens when the taskbar is moved + // and therefore the "working area" changes. + // http://msdn.microsoft.com/en-us/library/ms695534(v=vs.85).aspx + case WM_SETTINGCHANGE: + return QtWindows::SettingChangedEvent; case WM_DISPLAYCHANGE: return QtWindows::DisplayChangedEvent; case WM_THEMECHANGED: diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 0dade2c49b..98c17deba9 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -331,6 +331,11 @@ bool QWindowsContext::useRTLExtensions() const return d->m_keyMapper.useRTLExtensions(); } +QList<int> QWindowsContext::possibleKeys(const QKeyEvent *e) const +{ + return d->m_keyMapper.possibleKeys(e); +} + void QWindowsContext::setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx) { d->m_creationContext = ctx; @@ -749,6 +754,8 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, #endif case QtWindows::DisplayChangedEvent: return d->m_screenManager.handleDisplayChange(wParam, lParam); + case QtWindows::SettingChangedEvent: + return d->m_screenManager.handleScreenChanges(); default: break; } diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 3f08a742f8..450d6c8f4b 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -60,6 +60,7 @@ class QWindowsMimeConverter; struct QWindowCreationContext; struct QWindowsContextPrivate; class QPoint; +class QKeyEvent; #ifndef Q_OS_WINCE struct QWindowsUser32DLL @@ -170,6 +171,7 @@ public: unsigned systemInfo() const; bool useRTLExtensions() const; + QList<int> possibleKeys(const QKeyEvent *e) const; QWindowsMimeConverter &mimeConverter() const; QWindowsScreenManager &screenManager(); diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 8b3d6749a0..11fd740009 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -560,12 +560,8 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv) // Find the word in the surrounding text. QTextBoundaryFinder bounds(QTextBoundaryFinder::Word, surroundingText); bounds.setPosition(pos); - if (bounds.isAtBoundary()) { - if (QTextBoundaryFinder::EndWord == bounds.boundaryReasons()) - bounds.toPreviousBoundary(); - } else { + if (bounds.position() > 0 && !(bounds.boundaryReasons() & QTextBoundaryFinder::StartOfItem)) bounds.toPreviousBoundary(); - } const int startPos = bounds.position(); bounds.toNextBoundary(); const int endPos = bounds.position(); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 463e01246b..1f26ec5bab 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -447,6 +447,11 @@ Qt::KeyboardModifiers QWindowsIntegration::queryKeyboardModifiers() const return QWindowsKeyMapper::queryKeyboardModifiers(); } +QList<int> QWindowsIntegration::possibleKeys(const QKeyEvent *e) const +{ + return d->m_context.possibleKeys(e); +} + QPlatformNativeInterface *QWindowsIntegration::nativeInterface() const { return &d->m_nativeInterface; diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index fe095cf5d3..49780566dd 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -81,6 +81,7 @@ public: virtual QVariant styleHint(StyleHint hint) const; virtual Qt::KeyboardModifiers queryKeyboardModifiers() const; + virtual QList<int> possibleKeys(const QKeyEvent *e) const; static QWindowsIntegration *instance(); diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index 322d66836a..b57a27acb4 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -1119,4 +1119,30 @@ Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers() return modifiers; } +QList<int> QWindowsKeyMapper::possibleKeys(const QKeyEvent *e) const +{ + QList<int> result; + + KeyboardLayoutItem *kbItem = keyLayout[e->nativeVirtualKey()]; + if (!kbItem) + return result; + + quint32 baseKey = kbItem->qtKey[0]; + Qt::KeyboardModifiers keyMods = e->modifiers(); + if (baseKey == Qt::Key_Return && (e->nativeModifiers() & ExtendedKey)) { + result << int(Qt::Key_Enter + keyMods); + return result; + } + result << int(baseKey + keyMods); // The base key is _always_ valid, of course + + for (int i = 1; i < 9; ++i) { + Qt::KeyboardModifiers neededMods = ModsTbl[i]; + quint32 key = kbItem->qtKey[i]; + if (key && key != baseKey && ((keyMods & neededMods) == neededMods)) + result << int(key + (keyMods & ~neededMods)); + } + + return result; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowskeymapper.h b/src/plugins/platforms/windows/qwindowskeymapper.h index 3a13deb0b6..7b3f18a42d 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.h +++ b/src/plugins/platforms/windows/qwindowskeymapper.h @@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE +class QKeyEvent; class QWindow; struct KeyboardLayoutItem; @@ -70,6 +71,7 @@ public: void setKeyGrabber(QWindow *w) { m_keyGrabber = w; } static Qt::KeyboardModifiers queryKeyboardModifiers(); + QList<int> possibleKeys(const QKeyEvent *e) const; private: bool translateKeyEventInternal(QWindow *receiver, const MSG &msg, bool grab); diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 05a6893aad..0717a8ec60 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -372,7 +372,7 @@ static inline int indexOfMonitor(const QList<QWindowsScreenData> &screenData, ones and propagates resolution changes to QWindowSystemInterface. */ -void QWindowsScreenManager::handleScreenChanges() +bool QWindowsScreenManager::handleScreenChanges() { // Look for changed monitors, add new ones const WindowsScreenDataList newDataList = monitorData(); @@ -396,6 +396,7 @@ void QWindowsScreenManager::handleScreenChanges() delete m_screens.takeAt(i); } // not found } // for existing screens + return true; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 49b62632fc..dfd85f9be4 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -129,7 +129,7 @@ public: delete m_screens.takeLast(); } - void handleScreenChanges(); + bool handleScreenChanges(); bool handleDisplayChange(WPARAM wParam, LPARAM lParam); const WindowsScreenList &screens() const { return m_screens; } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 2335870ea7..f3830eb962 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1178,7 +1178,7 @@ void QWindowsWindow::setWindowTitle(const QString &title) SetWindowText(m_data.hwnd, (const wchar_t*)title.utf16()); } -Qt::WindowFlags QWindowsWindow::setWindowFlags(Qt::WindowFlags flags) +void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags) { if (QWindowsContext::verboseWindows) qDebug() << '>' << __FUNCTION__ << this << window() << "\n from: " @@ -1202,7 +1202,6 @@ Qt::WindowFlags QWindowsWindow::setWindowFlags(Qt::WindowFlags flags) qDebug() << '<' << __FUNCTION__ << "\n returns: " << QWindowsWindow::debugWindowFlags(m_data.flags) << " geometry " << oldGeometry << "->" << newGeometry; - return m_data.flags; } QWindowsWindow::WindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt, diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 4b1792859f..3b7666cf32 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -159,7 +159,7 @@ public: virtual QPoint mapToGlobal(const QPoint &pos) const; virtual QPoint mapFromGlobal(const QPoint &pos) const; - virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); + virtual void setWindowFlags(Qt::WindowFlags flags); virtual Qt::WindowState setWindowState(Qt::WindowState state); HWND handle() const { return m_data.hwnd; } diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index f021ab8b4a..142a8dfcde 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -300,6 +300,9 @@ void QXcbClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) m_timestamp[mode] = XCB_CURRENT_TIME; } + if (connection()->time() == XCB_CURRENT_TIME) + connection()->setTime(connection()->getTimestamp()); + if (data) { newOwner = owner(); diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 401739f7d5..ad9fb1d19c 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -864,6 +864,59 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id) xcb_flush(xcb_connection()); } +namespace +{ + class PropertyNotifyEvent { + public: + PropertyNotifyEvent(xcb_window_t win, xcb_atom_t property) + : window(win), type(XCB_PROPERTY_NOTIFY), atom(property) {} + xcb_window_t window; + int type; + xcb_atom_t atom; + bool checkEvent(xcb_generic_event_t *event) const { + if (!event) + return false; + if ((event->response_type & ~0x80) != type) { + return false; + } else { + xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event; + if ((pn->window == window) && (pn->atom == atom)) + return true; + } + return false; + } + }; +} + +xcb_timestamp_t QXcbConnection::getTimestamp() +{ + // send a dummy event to myself to get the timestamp from X server. + xcb_window_t rootWindow = screens().at(primaryScreen())->root(); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_APPEND, rootWindow, atom(QXcbAtom::CLIP_TEMPORARY), + XCB_ATOM_INTEGER, 32, 0, NULL); + + connection()->flush(); + PropertyNotifyEvent checker(rootWindow, atom(QXcbAtom::CLIP_TEMPORARY)); + + xcb_generic_event_t *event = 0; + // lets keep this inside a loop to avoid a possible race condition, where + // reader thread has not yet had the time to acquire the mutex in order + // to add the new set of events to its event queue + while (true) { + connection()->sync(); + if (event = checkEvent(checker)) + break; + } + + xcb_property_notify_event_t *pn = (xcb_property_notify_event_t *)event; + xcb_timestamp_t timestamp = pn->time; + free(event); + + xcb_delete_property(xcb_connection(), rootWindow, atom(QXcbAtom::CLIP_TEMPORARY)); + + return timestamp; +} + void QXcbConnection::processXcbEvents() { QXcbEventArray *eventqueue = m_reader->lock(); diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 08dd304b3d..8a6c418788 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -319,7 +319,6 @@ public: QByteArray atomName(xcb_atom_t atom); const char *displayName() const { return m_displayName.constData(); } - xcb_connection_t *xcb_connection() const { return m_connection; } const xcb_setup_t *setup() const { return m_setup; } const xcb_format_t *formatForDepth(uint8_t depth) const; @@ -380,6 +379,8 @@ public: bool hasXRandr() const { return has_randr_extension; } bool hasInputShape() const { return has_input_shape; } + xcb_timestamp_t getTimestamp(); + private slots: void processXcbEvents(); diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 1a2de82fd3..5d887cd06d 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -53,6 +53,7 @@ #include <qguiapplication.h> #include <qrect.h> #include <qpainter.h> +#include <qtimer.h> #include <qpa/qwindowsysteminterface.h> @@ -140,8 +141,7 @@ QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c) init(); heartbeat = -1; - - transaction_expiry_timer = -1; + cleanup_timer = -1; } QXcbDrag::~QXcbDrag() @@ -510,17 +510,21 @@ void QXcbDrag::drop(const QMouseEvent *event) if (w && (w->window()->windowType() == Qt::Desktop) /*&& !w->acceptDrops()*/) w = 0; - Transaction t = { connection()->time(), current_target, current_proxy_target, (w ? w->window() : 0), -// current_embedding_widget, - currentDrag() +// current_embeddig_widget, + currentDrag(), + QTime::currentTime() }; transactions.append(t); - restartDropExpiryTimer(); + + // timer is needed only for drops that came from other processes. + if (!t.targetWindow && cleanup_timer == -1) { + cleanup_timer = startTimer(XdndDropTransactionTimeout); + } if (w) { handleDrop(w->window(), &drop); @@ -563,16 +567,6 @@ xcb_atom_t QXcbDrag::toXdndAction(Qt::DropAction a) const } } -// timer used to discard old XdndDrop transactions -enum { XdndDropTransactionTimeout = 5000 }; // 5 seconds - -void QXcbDrag::restartDropExpiryTimer() -{ - if (transaction_expiry_timer != -1) - killTimer(transaction_expiry_timer); - transaction_expiry_timer = startTimer(XdndDropTransactionTimeout); -} - int QXcbDrag::findTransactionByWindow(xcb_window_t window) { int at = -1; @@ -771,8 +765,6 @@ void QXcbDrag::handle_xdnd_position(QWindow *w, const xcb_client_message_event_t response.data.data32[3] = 0; // w, h response.data.data32[4] = toXdndAction(qt_response.acceptedAction()); // action - - if (answerRect.left() < 0) answerRect.setLeft(0); if (answerRect.right() > 4096) @@ -1015,7 +1007,6 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event) if (l[0]) { int at = findTransactionByWindow(l[0]); if (at != -1) { - restartDropExpiryTimer(); Transaction t = transactions.takeAt(at); // QDragManager *manager = QDragManager::self(); @@ -1044,12 +1035,13 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event) // current_proxy_target = proxy_target; // current_embedding_widget = embedding_widget; // manager->object = currentObject; + } else { + qWarning("QXcbDrag::handleFinished - drop data has expired"); } } waiting_for_status = false; } - void QXcbDrag::timerEvent(QTimerEvent* e) { if (e->timerId() == heartbeat && source_sameanswer.isNull()) { @@ -1057,19 +1049,35 @@ void QXcbDrag::timerEvent(QTimerEvent* e) QMouseEvent me(QEvent::MouseMove, pos, pos, pos, Qt::LeftButton, QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); move(&me); - } else if (e->timerId() == transaction_expiry_timer) { + } else if (e->timerId() == cleanup_timer) { + bool stopTimer = true; for (int i = 0; i < transactions.count(); ++i) { const Transaction &t = transactions.at(i); if (t.targetWindow) { - // dnd within the same process, don't delete these + // dnd within the same process, don't delete, these are taken care of + // in handleFinished() continue; } - t.drag->deleteLater(); - transactions.removeAt(i--); - } + QTime currentTime = QTime::currentTime(); + int delta = t.time.msecsTo(currentTime); + if (delta > XdndDropTransactionTimeout) { + /* delete transactions which are older than XdndDropTransactionTimeout. It could mean + one of these: + - client has crashed and as a result we have never received XdndFinished + - showing dialog box on drop event where user's response takes more time than XdndDropTransactionTimeout (QTBUG-14493) + - dnd takes unusually long time to process data + */ + t.drag->deleteLater(); + transactions.removeAt(i--); + } else { + stopTimer = false; + } - killTimer(transaction_expiry_timer); - transaction_expiry_timer = -1; + } + if (stopTimer && cleanup_timer != -1) { + killTimer(cleanup_timer); + cleanup_timer = -1; + } } } @@ -1123,7 +1131,6 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event QDrag *transactionDrag = 0; if (at >= 0) { - restartDropExpiryTimer(); transactionDrag = transactions.at(at).drag; } else if (at == -2) { transactionDrag = currentDrag(); diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index 99c1e2d78f..41d15505ce 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -52,7 +52,7 @@ #include <qsharedpointer.h> #include <qpointer.h> #include <qvector.h> - +#include <qdatetime.h> #include <qpixmap.h> #include <qbackingstore.h> @@ -146,6 +146,10 @@ private: // timer used when target wants "continuous" move messages (eg. scroll) int heartbeat; + // 10 minute timer used to discard old XdndDrop transactions + enum { XdndDropTransactionTimeout = 600000 }; + int cleanup_timer; + QVector<xcb_atom_t> drag_types; struct Transaction @@ -156,6 +160,7 @@ private: QWindow *targetWindow; // QWidget *embedding_widget; QDrag *drag; + QTime time; }; QList<Transaction> transactions; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 64cb9afcc6..cefe1a7786 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -740,7 +740,7 @@ void QXcbWindow::setNetWmStates(NetWmStates states) xcb_flush(xcb_connection()); } -Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags) +void QXcbWindow::setWindowFlags(Qt::WindowFlags flags) { Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); @@ -763,8 +763,6 @@ Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags) setTransparentForMouseEvents(flags & Qt::WindowTransparentForInput); updateDoesNotAcceptFocus(flags & Qt::WindowDoesNotAcceptFocus); - - return flags; } void QXcbWindow::setMotifWindowFlags(Qt::WindowFlags flags) diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index ab18b502be..e2f62401dc 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -81,7 +81,7 @@ public: QMargins frameMargins() const; void setVisible(bool visible); - Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); + void setWindowFlags(Qt::WindowFlags flags); Qt::WindowState setWindowState(Qt::WindowState state); WId winId() const; void setParent(const QPlatformWindow *window); |