diff options
Diffstat (limited to 'src/plugins/platforms')
30 files changed, 207 insertions, 98 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm index aaa12c6edb..cc8436dcfe 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm @@ -177,8 +177,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); { Q_UNUSED(notification); [self updateQtColor]; - if (mHelper) - emit mHelper->colorSelected(mQtColor); } - (void)windowWillClose:(NSNotification *)notification diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 31a0a3d600..0375dd85f2 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -589,15 +589,6 @@ void QCocoaFileDialogHelper::QNSOpenSavePanelDelegate_panelClosed(bool accepted) QCocoaMenuBar::resetKnownMenuItemsToQt(); if (accepted) { emit accept(); - - QString filter = selectedNameFilter(); - if (filter.isEmpty()) - emit filterSelected(filter); - - QList<QUrl> files = selectedFiles(); - emit filesSelected(files); - if (files.count() == 1) - emit fileSelected(files.first()); } else { emit reject(); } diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index dfda22d376..dc7dfb788f 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -365,7 +365,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); emit mHelper->reject(); } else { emit mHelper->accept(); - emit mHelper->fontSelected(mHelper->currentFont()); } } } diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm index 24dc8ab42a..04d6d6b806 100644 --- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -137,8 +137,8 @@ void QCocoaInputContext::updateLocale() m_locale = locale; emitLocaleChanged(); } - CFRelease(langRef); } + CFRelease(source); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index 6b80162e4d..b77071536b 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -71,7 +71,7 @@ public: void syncSeparatorsCollapsible(bool enable) Q_DECL_OVERRIDE; - void syncModalState(bool modal); + void propagateEnabledState(bool enabled); void setIcon(const QIcon &icon) Q_DECL_OVERRIDE { Q_UNUSED(icon) } @@ -104,9 +104,10 @@ private: NSMenu *m_nativeMenu; NSMenuItem *m_attachedItem; quintptr m_tag; - bool m_enabled; - bool m_visible; - bool m_isOpen; + bool m_enabled:1; + bool m_parentEnabled:1; + bool m_visible:1; + bool m_isOpen:1; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 32cf9ebc53..4260b17772 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -155,10 +155,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); - (BOOL)validateMenuItem:(NSMenuItem*)menuItem { - if (![menuItem tag]) + QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>(menuItem.tag); + if (!cocoaItem) return YES; - QCocoaMenuItem* cocoaItem = reinterpret_cast<QCocoaMenuItem *>([menuItem tag]); return cocoaItem->isEnabled(); } @@ -256,6 +256,7 @@ QCocoaMenu::QCocoaMenu() : m_attachedItem(0), m_tag(0), m_enabled(true), + m_parentEnabled(true), m_visible(true), m_isOpen(false) { @@ -331,6 +332,8 @@ void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) else if (isOpen() && item->nsItem()) // Someone's adding new items after aboutToShow() was emitted item->menu()->setAttachedItem(item->nsItem()); + item->setParentEnabled(isEnabled()); + if (item->isMerged()) return; @@ -375,6 +378,9 @@ void QCocoaMenu::removeMenuItem(QPlatformMenuItem *menuItem) if (cocoaItem->menuParent() == this) cocoaItem->setMenuParent(0); + // Ignore any parent enabled state + cocoaItem->setParentEnabled(true); + m_menuItems.removeOne(cocoaItem); if (!cocoaItem->isMerged()) { if (m_nativeMenu != [cocoaItem->nsItem() menu]) { @@ -465,13 +471,17 @@ void QCocoaMenu::syncSeparatorsCollapsible(bool enable) void QCocoaMenu::setEnabled(bool enabled) { + if (m_enabled == enabled) + return; m_enabled = enabled; - syncModalState(!m_enabled); + const bool wasParentEnabled = m_parentEnabled; + propagateEnabledState(m_enabled); + m_parentEnabled = wasParentEnabled; // Reset to the parent value } bool QCocoaMenu::isEnabled() const { - return m_attachedItem ? [m_attachedItem isEnabled] : m_enabled; + return m_attachedItem ? [m_attachedItem isEnabled] : m_enabled && m_parentEnabled; } void QCocoaMenu::setVisible(bool visible) @@ -605,20 +615,19 @@ QList<QCocoaMenuItem *> QCocoaMenu::merged() const return result; } -void QCocoaMenu::syncModalState(bool modal) +void QCocoaMenu::propagateEnabledState(bool enabled) { - QMacAutoReleasePool pool; + QMacAutoReleasePool pool; // FIXME Is this still needed for Creator? See 6a0bb4206a2928b83648 - if (!m_enabled) - modal = true; + m_parentEnabled = enabled; + if (!m_enabled && enabled) // Some ancestor was enabled, but this menu is not + return; foreach (QCocoaMenuItem *item, m_menuItems) { - if (item->menu()) { // recurse into submenus - item->menu()->syncModalState(modal); - continue; - } - - item->syncModalState(modal); + if (QCocoaMenu *menu = item->menu()) + menu->propagateEnabledState(enabled); + else + item->setParentEnabled(enabled); } } diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index ded7ab541b..26af0d3f63 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -322,7 +322,7 @@ void QCocoaMenuBar::updateMenuBarImmediately() menu->setMenuParent(mb); // force a sync? mb->syncMenu(menu); - menu->syncModalState(disableForModal); + menu->propagateEnabledState(!disableForModal); } QCocoaMenuLoader *loader = [QCocoaMenuLoader sharedMenuLoader]; diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index 755e793ba3..23f788687c 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -105,10 +105,10 @@ public: NSMenuItem *sync(); void syncMerged(); - void syncModalState(bool modal); + void setParentEnabled(bool enabled); inline bool isMerged() const { return m_merged; } - inline bool isEnabled() const { return m_enabled; } + inline bool isEnabled() const { return m_enabled && m_parentEnabled; } inline bool isSeparator() const { return m_isSeparator; } QCocoaMenu *menu() const { return m_menu; } @@ -121,22 +121,23 @@ private: NSMenuItem *m_native; NSView *m_itemView; QString m_text; - bool m_textSynced; QIcon m_icon; QPointer<QCocoaMenu> m_menu; - bool m_isVisible; - bool m_enabled; - bool m_isSeparator; QFont m_font; MenuRole m_role; MenuRole m_detectedRole; #ifndef QT_NO_SHORTCUT QKeySequence m_shortcut; #endif - bool m_checked; - bool m_merged; quintptr m_tag; int m_iconSize; + bool m_textSynced:1; + bool m_isVisible:1; + bool m_enabled:1; + bool m_parentEnabled:1; + bool m_isSeparator:1; + bool m_checked:1; + bool m_merged:1; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index 450a3915ab..cac166a409 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -92,16 +92,17 @@ NSUInteger keySequenceModifierMask(const QKeySequence &accel) QCocoaMenuItem::QCocoaMenuItem() : m_native(NULL), m_itemView(nil), - m_textSynced(false), m_menu(NULL), + m_role(NoRole), + m_tag(0), + m_iconSize(16), + m_textSynced(false), m_isVisible(true), m_enabled(true), + m_parentEnabled(true), m_isSeparator(false), - m_role(NoRole), m_checked(false), - m_merged(false), - m_tag(0), - m_iconSize(16) + m_merged(false) { } @@ -137,15 +138,23 @@ void QCocoaMenuItem::setMenu(QPlatformMenu *menu) if (menu == m_menu) return; - if (m_menu) { - if (m_menu->menuParent() == this) - m_menu->setMenuParent(0); + if (m_menu && m_menu->menuParent() == this) { + m_menu->setMenuParent(0); + // Free the menu from its parent's influence + m_menu->propagateEnabledState(true); + if (m_native && m_menu->attachedItem() == m_native) + m_menu->setAttachedItem(nil); } QMacAutoReleasePool pool; m_menu = static_cast<QCocoaMenu *>(menu); if (m_menu) { + if (m_native) { + // Skip automatic menu item validation + m_native.action = nil; + } m_menu->setMenuParent(this); + m_menu->propagateEnabledState(isEnabled()); } else { // we previously had a menu, but no longer // clear out our item so the nexy sync() call builds a new one @@ -190,7 +199,11 @@ void QCocoaMenuItem::setChecked(bool isChecked) void QCocoaMenuItem::setEnabled(bool enabled) { - m_enabled = enabled; + if (m_enabled != enabled) { + m_enabled = enabled; + if (m_menu) + m_menu->propagateEnabledState(isEnabled()); + } } void QCocoaMenuItem::setNativeContents(WId item) @@ -405,12 +418,13 @@ void QCocoaMenuItem::syncMerged() [m_native setHidden: !m_isVisible]; } -void QCocoaMenuItem::syncModalState(bool modal) +void QCocoaMenuItem::setParentEnabled(bool enabled) { - if (modal) - [m_native setEnabled:NO]; - else - [m_native setEnabled:YES]; + if (m_parentEnabled != enabled) { + m_parentEnabled = enabled; + if (m_menu) + m_menu->propagateEnabledState(isEnabled()); + } } QPlatformMenuItem::MenuRole QCocoaMenuItem::effectiveRole() const diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 5ec05ec8ce..cd7945641e 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -911,7 +911,7 @@ UIFont *uifont = [UIFont fontWithName:qfont.family().toNSString() size:qfont.pointSize()]; if (!uifont) return [NSDictionary dictionary]; - return [NSDictionary dictionaryWithObject:uifont forKey:UITextInputTextFontKey]; + return [NSDictionary dictionaryWithObject:uifont forKey:NSFontAttributeName]; } #endif diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index 18be3b0ce6..39a4eb81ca 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -364,8 +364,9 @@ void QWindowsFontEngineDirectWrite::recalcAdvances(QGlyphLayout *glyphs, QFontEn glyphIndices.size(), glyphMetrics.data()); if (SUCCEEDED(hr)) { + qreal stretch = fontDef.stretch != QFont::AnyStretch ? fontDef.stretch / 100.0 : 1.0; for (int i = 0; i < glyphs->numGlyphs; ++i) - glyphs->advances[i] = DESIGN_TO_LOGICAL(glyphMetrics[i].advanceWidth); + glyphs->advances[i] = DESIGN_TO_LOGICAL(glyphMetrics[i].advanceWidth * stretch); if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { for (int i = 0; i < glyphs->numGlyphs; ++i) glyphs->advances[i] = glyphs->advances[i].round(); @@ -448,7 +449,7 @@ glyph_metrics_t QWindowsFontEngineDirectWrite::boundingBox(glyph_t g) width, height, advanceWidth, - advanceHeight); + 0); } else { qErrnoWarning("%s: GetDesignGlyphMetrics failed", __FUNCTION__); } @@ -532,7 +533,7 @@ bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, QFixed subPixelPosition, int margin, - const QTransform &xform) + const QTransform &originalTransform) { UINT16 glyphIndex = t; FLOAT glyphAdvance = 0; @@ -551,6 +552,10 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, glyphRun.bidiLevel = 0; glyphRun.glyphOffsets = &glyphOffset; + QTransform xform = originalTransform; + if (fontDef.stretch != 100) + xform.scale(fontDef.stretch / 100.0, 1.0); + DWRITE_MATRIX transform; transform.dx = subPixelPosition.toReal(); transform.dy = 0; @@ -807,10 +812,15 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed subPixelPosition, - const QTransform &matrix, + const QTransform &originalTransform, GlyphFormat format) { Q_UNUSED(format); + + QTransform matrix = originalTransform; + if (fontDef.stretch != 100) + matrix.scale(fontDef.stretch / 100.0, 1.0); + glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance UINT16 glyphIndex = glyph; diff --git a/src/plugins/platforms/windows/qwindowsservices.cpp b/src/plugins/platforms/windows/qwindowsservices.cpp index 6cc56372ec..7f9c9bd205 100644 --- a/src/plugins/platforms/windows/qwindowsservices.cpp +++ b/src/plugins/platforms/windows/qwindowsservices.cpp @@ -54,8 +54,9 @@ enum { debug = 0 }; static inline bool shellExecute(const QUrl &url) { - const QString nativeFilePath = - url.isLocalFile() ? QDir::toNativeSeparators(url.toLocalFile()) : url.toString(QUrl::FullyEncoded); + const QString nativeFilePath = url.isLocalFile() && !url.hasFragment() && !url.hasQuery() + ? QDir::toNativeSeparators(url.toLocalFile()) + : url.toString(QUrl::FullyEncoded); const quintptr result = reinterpret_cast<quintptr>(ShellExecute(0, 0, reinterpret_cast<const wchar_t *>(nativeFilePath.utf16()), diff --git a/src/plugins/platforms/winrt/qwinrtclipboard.cpp b/src/plugins/platforms/winrt/qwinrtclipboard.cpp index 2811f1f018..0a38b3df34 100644 --- a/src/plugins/platforms/winrt/qwinrtclipboard.cpp +++ b/src/plugins/platforms/winrt/qwinrtclipboard.cpp @@ -59,6 +59,7 @@ typedef IEventHandler<IInspectable *> ContentChangedHandler; QT_BEGIN_NAMESPACE QWinRTClipboard::QWinRTClipboard() + : m_mimeData(Q_NULLPTR) { #ifndef Q_OS_WINPHONE QEventDispatcherWinRT::runOnXamlThread([this]() { @@ -103,9 +104,16 @@ QMimeData *QWinRTClipboard::mimeData(QClipboard::Mode mode) const wchar_t *textStr = result.GetRawBuffer(&size); QString text = QString::fromWCharArray(textStr, size); text.replace(QLatin1String("\r\n"), QLatin1String("\n")); - m_mimeData.setText(text); - return &m_mimeData; + if (m_mimeData) { + if (m_mimeData->text() == text) + return m_mimeData; + delete m_mimeData; + } + m_mimeData = new QMimeData(); + m_mimeData->setText(text); + + return m_mimeData; #else // Q_OS_WINPHONE return QPlatformClipboard::mimeData(mode); #endif // Q_OS_WINPHONE @@ -146,7 +154,13 @@ void QWinRTClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) return; #ifndef Q_OS_WINPHONE - const QString text = data->text(); + const bool newData = !m_mimeData || m_mimeData != data; + if (newData) { + if (m_mimeData) + delete m_mimeData; + m_mimeData = data; + } + const QString text = data ? data->text() : QString(); HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, text]() { HRESULT hr; ComPtr<IDataPackage> package; @@ -164,7 +178,6 @@ void QWinRTClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) return S_OK; }); RETURN_VOID_IF_FAILED("Could not set clipboard text."); - emitChanged(mode); #else // Q_OS_WINPHONE QPlatformClipboard::setMimeData(data, mode); #endif // Q_OS_WINPHONE diff --git a/src/plugins/platforms/winrt/qwinrtclipboard.h b/src/plugins/platforms/winrt/qwinrtclipboard.h index f88a92956e..3e6ee109fd 100644 --- a/src/plugins/platforms/winrt/qwinrtclipboard.h +++ b/src/plugins/platforms/winrt/qwinrtclipboard.h @@ -73,7 +73,7 @@ private: #ifndef Q_OS_WINPHONE Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::DataTransfer::IClipboardStatics> m_nativeClipBoard; #endif - QMimeData m_mimeData; + QMimeData *m_mimeData; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp index 3f400e1342..d69c63e9a4 100644 --- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp +++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp @@ -111,6 +111,9 @@ bool QWinRTMessageDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModa Q_D(QWinRTMessageDialogHelper); QSharedPointer<QMessageDialogOptions> options = this->options(); + if (!options.data()) + return false; + const QString informativeText = options->informativeText(); const QString title = options->windowTitle(); const QString text = informativeText.isEmpty() ? options->text() : (options->text() + QLatin1Char('\n') + informativeText); diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index ad32e63cad..ad32c046df 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -763,10 +763,11 @@ void QWinRTScreen::addWindow(QWindow *window) { Q_D(QWinRTScreen); qCDebug(lcQpaWindows) << __FUNCTION__ << window; - if (window == topWindow()) + if (window == topWindow() || window->surfaceClass() == QSurface::Offscreen) return; d->visibleWindows.prepend(window); + updateWindowTitle(window->title()); QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); handleExpose(); QWindowSystemInterface::flushWindowSystemEvents(); @@ -785,7 +786,7 @@ void QWinRTScreen::removeWindow(QWindow *window) if (!d->visibleWindows.removeAll(window)) return; if (wasTopWindow) - QWindowSystemInterface::handleWindowActivated(window, Qt::OtherFocusReason); + QWindowSystemInterface::handleWindowActivated(Q_NULLPTR, Qt::OtherFocusReason); handleExpose(); QWindowSystemInterface::flushWindowSystemEvents(); #if _MSC_VER >= 1900 && !defined(QT_NO_DRAGANDDROP) @@ -807,6 +808,8 @@ void QWinRTScreen::lower(QWindow *window) const bool wasTopWindow = window == topWindow(); if (wasTopWindow && d->visibleWindows.size() == 1) return; + if (window->surfaceClass() == QSurface::Offscreen) + return; d->visibleWindows.removeAll(window); d->visibleWindows.append(window); if (wasTopWindow) @@ -814,15 +817,10 @@ void QWinRTScreen::lower(QWindow *window) handleExpose(); } -void QWinRTScreen::updateWindowTitle() +void QWinRTScreen::updateWindowTitle(const QString &title) { Q_D(QWinRTScreen); - QWindow *window = topWindow(); - if (!window) - return; - - const QString title = window->title(); HStringReference titleRef(reinterpret_cast<LPCWSTR>(title.utf16()), title.length()); HRESULT hr = d->view->put_Title(titleRef.Get()); RETURN_VOID_IF_FAILED("Unable to set window title"); diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index 5cada9726d..0e753b748b 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -109,7 +109,7 @@ public: void raise(QWindow *window); void lower(QWindow *window); - void updateWindowTitle(); + void updateWindowTitle(const QString &title); ABI::Windows::UI::Core::ICoreWindow *coreWindow() const; ABI::Windows::UI::Xaml::IDependencyObject *canvas() const; diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index 606ca22bcd..5b82183d40 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -191,6 +191,8 @@ QWinRTWindow::~QWinRTWindow() }); RETURN_VOID_IF_FAILED("Failed to completely destroy window resources, likely because the application is shutting down"); + d->screen->removeWindow(window()); + if (!d->surface) return; @@ -282,7 +284,9 @@ void QWinRTWindow::setWindowTitle(const QString &title) { Q_D(QWinRTWindow); d->windowTitle = title; - d->screen->updateWindowTitle(); + + if (d->screen->topWindow() == window()) + d->screen->updateWindowTitle(title); } void QWinRTWindow::raise() diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri index 57c8f27d9c..a3813ef993 100644 --- a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri +++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri @@ -3,6 +3,8 @@ QT += core-private gui-private platformsupport-private xcb_qpa_lib-private INCLUDEPATH += $$PWD INCLUDEPATH += $$PWD/../ +load(qt_build_paths) + # needed by Xcursor ... qtConfig(xcb-xlib) { DEFINES += XCB_USE_XLIB diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h index 719d2ace90..926e5e22df 100644 --- a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h @@ -60,6 +60,7 @@ public: virtual bool initialize(QXcbConnection *connection) = 0; virtual bool supportsThreadedOpenGL() const { return false; } + virtual bool supportsSwitchableWidgetComposition() const { return true; } virtual bool handleXcbEvent(xcb_generic_event_t *event, uint responseType); virtual QXcbWindow *createWindow(QWindow *window) const = 0; diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index f97c01f390..77cbdd5fba 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -224,5 +224,26 @@ bool QXcbGlxIntegration::supportsThreadedOpenGL() const return QGLXContext::supportsThreading(); } +bool QXcbGlxIntegration::supportsSwitchableWidgetComposition() const +{ + static bool vendorChecked = false; + static bool isSwitchableWidgetCompositionAvailable = true; + if (!vendorChecked) { + vendorChecked = true; + Display *display = glXGetCurrentDisplay(); +#ifdef XCB_USE_XLIB + if (!display) + display = static_cast<Display *>(m_connection->xlib_display()); +#endif + const char *glxvendor = glXGetClientString(display, GLX_VENDOR); + if (glxvendor) { + if (!strcmp(glxvendor, "Parallels Inc")) + isSwitchableWidgetCompositionAvailable = false; + } + } + + return isSwitchableWidgetCompositionAvailable; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h index 77d3bc55e1..8f04db31b2 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h @@ -60,6 +60,7 @@ public: QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; virtual bool supportsThreadedOpenGL() const Q_DECL_OVERRIDE; + virtual bool supportsSwitchableWidgetComposition() const Q_DECL_OVERRIDE; private: QXcbConnection *m_connection; diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 54c9e30edc..d577d46b96 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -107,6 +107,7 @@ QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input") Q_LOGGING_CATEGORY(lcQpaXInputDevices, "qt.qpa.input.devices") +Q_LOGGING_CATEGORY(lcQpaXInputEvents, "qt.qpa.input.events") Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen") // this event type was added in libxcb 1.10, @@ -1119,7 +1120,8 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) // the rest we need to manage ourselves m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state); m_buttons |= translateMouseButton(ev->detail); - qCDebug(lcQpaXInput, "legacy mouse press, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons)); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "legacy mouse press, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons)); HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); } case XCB_BUTTON_RELEASE: { @@ -1127,15 +1129,17 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) m_keyboard->updateXKBStateFromCore(ev->state); m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state); m_buttons &= ~translateMouseButton(ev->detail); - qCDebug(lcQpaXInput, "legacy mouse release, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons)); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "legacy mouse release, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons)); HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); } case XCB_MOTION_NOTIFY: { xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event; m_keyboard->updateXKBStateFromCore(ev->state); m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state); - qCDebug(lcQpaXInput, "legacy mouse move %d,%d button %d state %X", ev->event_x, ev->event_y, - ev->detail, static_cast<unsigned int>(m_buttons)); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "legacy mouse move %d,%d button %d state %X", ev->event_x, ev->event_y, + ev->detail, static_cast<unsigned int>(m_buttons)); HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 4d903ec8d3..dca32af9b1 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -86,6 +86,7 @@ QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcQpaXInput) Q_DECLARE_LOGGING_CATEGORY(lcQpaXInputDevices) +Q_DECLARE_LOGGING_CATEGORY(lcQpaXInputEvents) Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen) class QXcbVirtualDesktop; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index bda167bce9..1147fc82b2 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -562,8 +562,8 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) case XI_TouchBegin: case XI_TouchUpdate: case XI_TouchEnd: - if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) - qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x", + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x", event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail, fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event); @@ -620,8 +620,8 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo double value; if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value)) continue; - if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) - qCDebug(lcQpaXInput, " valuator %20s value %lf from range %lf -> %lf", + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, " valuator %20s value %lf from range %lf -> %lf", atomName(vci->label).constData(), value, vci->min, vci->max ); if (vci->label == atom(QXcbAtom::RelX)) { nx = valuatorNormalized(value, vci); @@ -751,8 +751,8 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo touchPoint.area = QRectF(x - w/2, y - h/2, w, h); touchPoint.normalPosition = QPointF(nx, ny); - if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) - qCDebug(lcQpaXInput) << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition << + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents) << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition << " area " << touchPoint.area << " pressure " << touchPoint.pressure; QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiDeviceEvent->time, dev->qtTouchDevice, dev->touchPoints.values()); if (touchPoint.state == Qt::TouchPointReleased) @@ -883,8 +883,8 @@ void QXcbConnection::updateScrollingDevice(ScrollingDevice &scrollingDevice, int scrollingDevice.lastScrollPosition.setY(vci->value); } } - if (lcQpaXInput().isDebugEnabled() && lastScrollPosition != scrollingDevice.lastScrollPosition) - qCDebug(lcQpaXInput, "scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId, + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled() && lastScrollPosition != scrollingDevice.lastScrollPosition)) + qCDebug(lcQpaXInputEvents, "scrolling device %d moved from (%f, %f) to (%f, %f)", scrollingDevice.deviceId, lastScrollPosition.x(), lastScrollPosition.y(), scrollingDevice.lastScrollPosition.x(), scrollingDevice.lastScrollPosition.y()); @@ -1117,9 +1117,10 @@ bool QXcbConnection::xi2HandleTabletEvent(const void *event, TabletData *tabletD } // TODO maybe have a hash of tabletData->deviceId to device data so we can // look up the tablet name here, and distinguish multiple tablets - qCDebug(lcQpaXInput, "XI2 proximity change on tablet %d (USB %x): last tool: %x id %x current tool: %x id %x TabletDevice %d", - tabletData->deviceId, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID], - ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], tabletData->tool); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "XI2 proximity change on tablet %d (USB %x): last tool: %x id %x current tool: %x id %x TabletDevice %d", + tabletData->deviceId, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID], + ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], tabletData->tool); } XFree(data); } @@ -1181,8 +1182,8 @@ void QXcbConnection::xi2ReportTabletEvent(const void *event, TabletData *tabletD } } - if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) - qCDebug(lcQpaXInput, "XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d " + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "XI2 event on tablet %d with tool %d type %d seq %d detail %d time %d " "pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf", tabletData->deviceId, tabletData->tool, ev->evtype, ev->sequenceNumber, ev->detail, ev->time, fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 5a89113a4f..802f7b85ce 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -267,9 +267,14 @@ bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const case ForeignWindows: case SyncState: case RasterGLSurface: - case SwitchableWidgetComposition: return true; + case SwitchableWidgetComposition: + { + return m_connections.at(0)->glIntegration() + && m_connections.at(0)->glIntegration()->supportsSwitchableWidgetComposition(); + } + default: return QPlatformIntegration::hasCapability(cap); } } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index a8d401e15b..a3e8da7df8 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -364,6 +364,9 @@ QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &functio if (function == QXcbWindowFunctions::setWmWindowTypeIdentifier()) return QFunctionPointer(QXcbWindowFunctions::SetWmWindowType(QXcbWindow::setWmWindowTypeStatic)); + if (function == QXcbWindowFunctions::setWmWindowRoleIdentifier()) + return QFunctionPointer(QXcbWindowFunctions::SetWmWindowRole(QXcbWindow::setWmWindowRoleStatic)); + if (function == QXcbWindowFunctions::setWmWindowIconTextIdentifier()) return QFunctionPointer(QXcbWindowFunctions::SetWmWindowIconText(QXcbWindow::setWindowIconTextStatic)); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 7500994787..51390bfdae 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -308,6 +308,7 @@ static QWindow *childWindowAt(QWindow *win, const QPoint &p) } static const char *wm_window_type_property_id = "_q_xcb_wm_window_type"; +static const char *wm_window_role_property_id = "_q_xcb_wm_window_role"; QXcbWindow::QXcbWindow(QWindow *window) : QPlatformWindow(window) @@ -590,6 +591,11 @@ void QXcbWindow::create() setOpacity(opacity); if (window()->isTopLevel()) setWindowIcon(window()->icon()); + + if (window()->dynamicPropertyNames().contains(wm_window_role_property_id)) { + QByteArray wmWindowRole = window()->property(wm_window_role_property_id).toByteArray(); + setWmWindowRole(wmWindowRole); + } } QXcbWindow::~QXcbWindow() @@ -1724,6 +1730,14 @@ void QXcbWindow::setWindowIconTextStatic(QWindow *window, const QString &text) static_cast<QXcbWindow *>(window->handle())->setWindowIconText(text); } +void QXcbWindow::setWmWindowRoleStatic(QWindow *window, const QByteArray &role) +{ + if (window->handle()) + static_cast<QXcbWindow *>(window->handle())->setWmWindowRole(role); + else + window->setProperty(wm_window_role_property_id, role); +} + uint QXcbWindow::visualIdStatic(QWindow *window) { if (window && window->handle()) @@ -1889,6 +1903,13 @@ void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types, Qt::W xcb_flush(xcb_connection()); } +void QXcbWindow::setWmWindowRole(const QByteArray &role) +{ + Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + atom(QXcbAtom::WM_WINDOW_ROLE), XCB_ATOM_STRING, 8, + role.size(), role.constData())); +} + void QXcbWindow::setParentRelativeBackPixmapStatic(QWindow *window) { if (window->handle()) @@ -2417,7 +2438,7 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource } const char *sourceName = 0; - if (lcQpaXInput().isDebugEnabled()) { + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) { const QMetaObject *metaObject = qt_getEnumMetaObject(source); const QMetaEnum me = metaObject->enumerator(metaObject->indexOfEnumerator(qt_getEnumName(source))); sourceName = me.valueToKey(source); @@ -2425,17 +2446,20 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource switch (ev->evtype) { case XI_ButtonPress: - qCDebug(lcQpaXInput, "XI2 mouse press, button %d, time %d, source %s", button, ev->time, sourceName); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "XI2 mouse press, button %d, time %d, source %s", button, ev->time, sourceName); conn->setButton(button, true); handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source); break; case XI_ButtonRelease: - qCDebug(lcQpaXInput, "XI2 mouse release, button %d, time %d, source %s", button, ev->time, sourceName); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "XI2 mouse release, button %d, time %d, source %s", button, ev->time, sourceName); conn->setButton(button, false); handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source); break; case XI_Motion: - qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d, time %d, source %s", event_x, event_y, ev->time, sourceName); + if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled())) + qCDebug(lcQpaXInputEvents, "XI2 mouse motion %d,%d, time %d, source %s", event_x, event_y, ev->time, sourceName); handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time, source); break; default: diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index e7190b1733..f62938ba8a 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -151,10 +151,12 @@ public: void updateNetWmUserTime(xcb_timestamp_t timestamp); static void setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes); + static void setWmWindowRoleStatic(QWindow *window, const QByteArray &role); static uint visualIdStatic(QWindow *window); QXcbWindowFunctions::WmWindowTypes wmWindowTypes() const; void setWmWindowType(QXcbWindowFunctions::WmWindowTypes types, Qt::WindowFlags flags); + void setWmWindowRole(const QByteArray &role); static void setWindowIconTextStatic(QWindow *window, const QString &text); diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index 942183877d..3c7badce5f 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -39,6 +39,8 @@ HEADERS = \ qxcbxsettings.h \ qxcbsystemtraytracker.h +load(qt_build_paths) + DEFINES += QT_BUILD_XCB_PLUGIN # needed by Xcursor ... qtConfig(xcb-xlib) { |