summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm4
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm16
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.h1
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm30
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm3
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp4
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h8
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp80
-rw-r--r--src/plugins/platforms/windows/qwindowsinputcontext.cpp2
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp9
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp19
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp3
-rw-r--r--src/plugins/platforms/windows/windows.pri2
-rw-r--r--src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp64
-rw-r--r--src/plugins/platforms/winrt/qwinrtfileengine.cpp36
-rw-r--r--src/plugins/platforms/winrt/qwinrtfileengine.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp60
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp140
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp76
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h2
25 files changed, 417 insertions, 171 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 867526ff52..09a4c95469 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -37,6 +37,7 @@
#include "qcocoaautoreleasepool.h"
#include <QtCore/QtDebug>
+#include <QtCore/qmetaobject.h>
#include <QtCore/private/qthread_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include "qcocoaapplication.h"
@@ -124,7 +125,8 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate);
QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([item tag]);
QScopedLoopLevelCounter loopLevelCounter(QGuiApplicationPrivate::instance()->threadData);
QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]];
- cocoaItem->activated();
+ static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated);
+ activatedSignal.invoke(cocoaItem, Qt::QueuedConnection);
}
- (BOOL)validateMenuItem:(NSMenuItem*)menuItem
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index e395c832f1..7cd4280f5e 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -46,6 +46,7 @@
#include <QtGui/private/qguiapplication_p.h>
+#include <qoffscreensurface.h>
#include <qpa/qplatformoffscreensurface.h>
#include <QtPlatformSupport/private/qcoretextfontdatabase_p.h>
@@ -158,9 +159,22 @@ QPlatformOpenGLContext *QIOSIntegration::createPlatformOpenGLContext(QOpenGLCont
return new QIOSContext(context);
}
+class QIOSOffscreenSurface : public QPlatformOffscreenSurface
+{
+public:
+ QIOSOffscreenSurface(QOffscreenSurface *offscreenSurface) : QPlatformOffscreenSurface(offscreenSurface) {}
+
+ QSurfaceFormat format() const Q_DECL_OVERRIDE
+ {
+ Q_ASSERT(offscreenSurface());
+ return offscreenSurface()->requestedFormat();
+ }
+ bool isValid() const Q_DECL_OVERRIDE { return true; }
+};
+
QPlatformOffscreenSurface *QIOSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
{
- return new QPlatformOffscreenSurface(surface);
+ return new QIOSOffscreenSurface(surface);
}
QAbstractEventDispatcher *QIOSIntegration::createEventDispatcher() const
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h
index 971a474673..dffbf7dc27 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.h
+++ b/src/plugins/platforms/ios/qiosviewcontroller.h
@@ -45,6 +45,7 @@ class QIOSScreen;
// UIViewController
@property (nonatomic, assign) BOOL prefersStatusBarHidden;
@property (nonatomic, assign) UIStatusBarAnimation preferredStatusBarUpdateAnimation;
+@property (nonatomic, assign) UIStatusBarStyle preferredStatusBarStyle;
@end
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 9abd105d94..6667ec3dd8 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -245,6 +245,7 @@
// Status bar may be initially hidden at startup through Info.plist
self.prefersStatusBarHidden = infoPlistValue(@"UIStatusBarHidden", false);
self.preferredStatusBarUpdateAnimation = UIStatusBarAnimationNone;
+ self.preferredStatusBarStyle = UIStatusBarStyle(infoPlistValue(@"UIStatusBarStyle", UIStatusBarStyleDefault));
m_focusWindowChangeConnection = QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() {
[self updateProperties];
@@ -423,6 +424,22 @@
UIApplication *uiApplication = [UIApplication sharedApplication];
+ // -------------- Status bar style and visbility ---------------
+
+ UIStatusBarStyle oldStatusBarStyle = self.preferredStatusBarStyle;
+ if (focusWindow->flags() & Qt::MaximizeUsingFullscreenGeometryHint)
+ self.preferredStatusBarStyle = UIStatusBarStyleDefault;
+ else
+ self.preferredStatusBarStyle = QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0 ?
+ UIStatusBarStyleLightContent : UIStatusBarStyleBlackTranslucent;
+
+ if (self.preferredStatusBarStyle != oldStatusBarStyle) {
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0)
+ [self setNeedsStatusBarAppearanceUpdate];
+ else
+ [uiApplication setStatusBarStyle:self.preferredStatusBarStyle];
+ }
+
bool currentStatusBarVisibility = self.prefersStatusBarHidden;
self.prefersStatusBarHidden = focusWindow->windowState() == Qt::WindowFullScreen;
@@ -484,18 +501,5 @@
}
}
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
-- (UIStatusBarStyle)preferredStatusBarStyle
-{
- // Since we don't place anything behind the status bare by default, we
- // end up with a black area, so we have to enable the white text mode
- // of the iOS7 statusbar.
- return UIStatusBarStyleLightContent;
-
- // FIXME: Try to detect the content underneath the statusbar and choose
- // an appropriate style, and/or expose Qt APIs to control the style.
-}
-#endif
-
@end
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 95a4c28246..777a3c12c5 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -244,7 +244,8 @@ void QIOSWindow::setWindowState(Qt::WindowState state)
applyGeometry(m_normalGeometry);
break;
case Qt::WindowMaximized:
- applyGeometry(screen()->availableGeometry());
+ applyGeometry(window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint ?
+ screen()->geometry() : screen()->availableGeometry());
break;
case Qt::WindowFullScreen:
applyGeometry(screen()->geometry());
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index fa355f6201..7264fdcbb6 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -225,8 +225,10 @@ bool QWindowsUser32DLL::initTouch()
QWindowsShell32DLL::QWindowsShell32DLL()
: sHCreateItemFromParsingName(0)
+ , sHGetKnownFolderIDList(0)
, sHGetStockIconInfo(0)
, sHGetImageList(0)
+ , sHCreateItemFromIDList(0)
{
}
@@ -234,8 +236,10 @@ void QWindowsShell32DLL::init()
{
QSystemLibrary library(QStringLiteral("shell32"));
sHCreateItemFromParsingName = (SHCreateItemFromParsingName)(library.resolve("SHCreateItemFromParsingName"));
+ sHGetKnownFolderIDList = (SHGetKnownFolderIDList)(library.resolve("SHGetKnownFolderIDList"));
sHGetStockIconInfo = (SHGetStockIconInfo)library.resolve("SHGetStockIconInfo");
sHGetImageList = (SHGetImageList)library.resolve("SHGetImageList");
+ sHCreateItemFromIDList = (SHCreateItemFromIDList)library.resolve("SHCreateItemFromIDList");
}
QWindowsShcoreDLL::QWindowsShcoreDLL()
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 81f4a36433..d2a3481b28 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -41,6 +41,10 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QLoggingCategory>
+#define STRICT_TYPED_ITEMIDS
+#include <shlobj.h>
+#include <shlwapi.h>
+
struct IBindCtx;
struct _SHSTOCKICONINFO;
@@ -120,12 +124,16 @@ struct QWindowsShell32DLL
inline void init();
typedef HRESULT (WINAPI *SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **);
+ typedef HRESULT (WINAPI *SHGetKnownFolderIDList)(const GUID &, DWORD, HANDLE, PIDLIST_ABSOLUTE *);
typedef HRESULT (WINAPI *SHGetStockIconInfo)(int , int , _SHSTOCKICONINFO *);
typedef HRESULT (WINAPI *SHGetImageList)(int, REFIID , void **);
+ typedef HRESULT (WINAPI *SHCreateItemFromIDList)(PCIDLIST_ABSOLUTE, REFIID, void **);
SHCreateItemFromParsingName sHCreateItemFromParsingName;
+ SHGetKnownFolderIDList sHGetKnownFolderIDList;
SHGetStockIconInfo sHGetStockIconInfo;
SHGetImageList sHGetImageList;
+ SHCreateItemFromIDList sHCreateItemFromIDList;
};
// Shell scaling library (Windows 8.1 onwards)
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index 3b47829402..3284795fc1 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -58,16 +58,14 @@
#include <QtCore/QExplicitlySharedDataPointer>
#include <QtCore/QMutex>
#include <QtCore/QMutexLocker>
+#include <QtCore/QUuid>
+#include <QtCore/QRegularExpression>
#include <QtCore/private/qsystemlibrary_p.h>
#include <algorithm>
#include "qtwindows_additional.h"
-#define STRICT_TYPED_ITEMIDS
-#include <shlobj.h>
-#include <shlwapi.h>
-
// #define USE_NATIVE_COLOR_DIALOG /* Testing purposes only */
#ifdef Q_CC_MINGW /* Add missing declarations for MinGW */
@@ -873,8 +871,8 @@ public:
virtual void setWindowTitle(const QString &title);
inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::AcceptMode acceptMode, QFileDialogOptions::FileDialogOptions options);
- inline void setDirectory(const QString &directory);
- inline void updateDirectory() { setDirectory(m_data.directory().toLocalFile()); }
+ inline void setDirectory(const QUrl &directory);
+ inline void updateDirectory() { setDirectory(m_data.directory()); }
inline QString directory() const;
virtual void doExec(HWND owner = 0);
virtual void setNameFilters(const QStringList &f);
@@ -916,7 +914,7 @@ protected:
static QList<QUrl> libraryItemFolders(IShellItem *item);
static QString libraryItemDefaultSaveFolder(IShellItem *item);
static int itemPaths(IShellItemArray *items, QList<QUrl> *fileResult = 0);
- static IShellItem *shellItem(const QString &path);
+ static IShellItem *shellItem(const QUrl &url);
const QWindowsFileDialogSharedData &data() const { return m_data; }
QWindowsFileDialogSharedData &data() { return m_data; }
@@ -976,25 +974,58 @@ void QWindowsNativeFileDialogBase::setWindowTitle(const QString &title)
m_fileDialog->SetTitle(reinterpret_cast<const wchar_t *>(title.utf16()));
}
-IShellItem *QWindowsNativeFileDialogBase::shellItem(const QString &path)
+IShellItem *QWindowsNativeFileDialogBase::shellItem(const QUrl &url)
{
#ifndef Q_OS_WINCE
- if (QWindowsContext::shell32dll.sHCreateItemFromParsingName) {
- IShellItem *result = 0;
- const QString native = QDir::toNativeSeparators(path);
+ if (url.isLocalFile()) {
+ if (!QWindowsContext::shell32dll.sHCreateItemFromParsingName)
+ return Q_NULLPTR;
+ IShellItem *result = Q_NULLPTR;
+ const QString native = QDir::toNativeSeparators(url.toLocalFile());
const HRESULT hr =
- QWindowsContext::shell32dll.sHCreateItemFromParsingName(reinterpret_cast<const wchar_t *>(native.utf16()),
- NULL, IID_IShellItem,
- reinterpret_cast<void **>(&result));
- if (SUCCEEDED(hr))
- return result;
+ QWindowsContext::shell32dll.sHCreateItemFromParsingName(reinterpret_cast<const wchar_t *>(native.utf16()),
+ NULL, IID_IShellItem,
+ reinterpret_cast<void **>(&result));
+ if (FAILED(hr)) {
+ qErrnoWarning("%s: SHCreateItemFromParsingName(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
+ return Q_NULLPTR;
+ }
+ return result;
+ } else if (url.scheme() == QLatin1String("clsid")) {
+ if (!QWindowsContext::shell32dll.sHGetKnownFolderIDList || !QWindowsContext::shell32dll.sHCreateItemFromIDList)
+ return Q_NULLPTR;
+ // Support for virtual folders via GUID
+ // (see https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx)
+ // specified as "clsid:<GUID>" (without '{', '}').
+ IShellItem *result = Q_NULLPTR;
+ const QUuid uuid(url.path());
+ if (uuid.isNull()) {
+ qWarning() << __FUNCTION__ << ": Invalid CLSID: " << url.path();
+ return Q_NULLPTR;
+ }
+ PIDLIST_ABSOLUTE idList;
+ HRESULT hr = QWindowsContext::shell32dll.sHGetKnownFolderIDList(uuid, 0, 0, &idList);
+ if (FAILED(hr)) {
+ qErrnoWarning("%s: SHGetKnownFolderIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
+ return Q_NULLPTR;
+ }
+ hr = QWindowsContext::shell32dll.sHCreateItemFromIDList(idList, IID_IShellItem, reinterpret_cast<void **>(&result));
+ CoTaskMemFree(idList);
+ if (FAILED(hr)) {
+ qErrnoWarning("%s: SHCreateItemFromIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
+ return Q_NULLPTR;
+ }
+ return result;
+ } else {
+ qWarning() << __FUNCTION__ << ": Unhandled scheme: " << url.scheme();
}
+#else // !Q_OS_WINCE
+ Q_UNUSED(url)
#endif
- qErrnoWarning("%s: SHCreateItemFromParsingName(%s)) failed", __FUNCTION__, qPrintable(path));
return 0;
}
-void QWindowsNativeFileDialogBase::setDirectory(const QString &directory)
+void QWindowsNativeFileDialogBase::setDirectory(const QUrl &directory)
{
if (!directory.isEmpty()) {
if (IShellItem *psi = QWindowsNativeFileDialogBase::shellItem(directory)) {
@@ -1284,9 +1315,20 @@ void QWindowsNativeFileDialogBase::setLabelText(QFileDialogOptions::DialogLabel
}
}
+static inline bool isClsid(const QString &s)
+{
+ // detect "374DE290-123F-4565-9164-39C4925E467B".
+ static const QRegularExpression pattern(QLatin1String("[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{8}"));
+ Q_ASSERT(pattern.isValid());
+ return pattern.match(s).hasMatch();
+}
+
void QWindowsNativeFileDialogBase::selectFile(const QString &fileName) const
{
- m_fileDialog->SetFileName((wchar_t*)fileName.utf16());
+ // Hack to prevent CLSIDs from being set as file name due to
+ // QFileDialogPrivate::initialSelection() being QString-based.
+ if (!isClsid(fileName))
+ m_fileDialog->SetFileName((wchar_t*)fileName.utf16());
}
// Return the index of the selected filter, accounting for QFileDialog
diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
index 689e06281f..0cce171340 100644
--- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp
@@ -189,7 +189,7 @@ void QWindowsInputContext::reset()
if (!m_compositionContext.hwnd)
return;
qCDebug(lcQpaInputMethods) << __FUNCTION__;
- if (m_compositionContext.isComposing && m_compositionContext.focusObject.isNull()) {
+ if (m_compositionContext.isComposing && !m_compositionContext.focusObject.isNull()) {
QInputMethodEvent event;
if (!m_compositionContext.composition.isEmpty())
event.setCommitString(m_compositionContext.composition);
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 13260edc82..d8ccccdf45 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -166,11 +166,6 @@ static bool qt_write_dibv5(QDataStream &s, QImage image)
if (s.status() != QDataStream::Ok)
return false;
- DWORD colorSpace[3] = {0x00ff0000,0x0000ff00,0x000000ff};
- d->write(reinterpret_cast<const char*>(colorSpace), sizeof(colorSpace));
- if (s.status() != QDataStream::Ok)
- return false;
-
if (image.format() != QImage::Format_ARGB32)
image = image.convertToFormat(QImage::Format_ARGB32);
@@ -255,10 +250,6 @@ static bool qt_read_dibv5(QDataStream &s, QImage &image)
}
image.setDotsPerMeterX(bi.bV5XPelsPerMeter);
image.setDotsPerMeterY(bi.bV5YPelsPerMeter);
- // read color table
- DWORD colorSpace[3];
- if (d->read((char *)colorSpace, sizeof(colorSpace)) != sizeof(colorSpace))
- return false;
red_shift = calc_shift(red_mask);
green_shift = calc_shift(green_mask);
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index 67548a0836..f5065a22b8 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -208,15 +208,22 @@ static inline QString resolveBugListFile(const QString &fileName)
return QStandardPaths::locate(QStandardPaths::ConfigLocation, fileName);
}
+# ifndef QT_NO_OPENGL
typedef QHash<QOpenGLConfig::Gpu, QWindowsOpenGLTester::Renderers> SupportedRenderersCache;
Q_GLOBAL_STATIC(SupportedRenderersCache, supportedRenderersCache)
+# endif
#endif // !Q_OS_WINCE
QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly)
{
Q_UNUSED(gpu)
-#ifndef Q_OS_WINCE
+ Q_UNUSED(glesOnly)
+#if defined(QT_NO_OPENGL)
+ return 0;
+#elif defined(Q_OS_WINCE)
+ return QWindowsOpenGLTester::Gles;
+#else
QOpenGLConfig::Gpu qgpu;
qgpu.deviceId = gpu.deviceId;
qgpu.vendorId = gpu.vendorId;
@@ -265,9 +272,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c
srCache->insert(qgpu, result);
return result;
-#else // !Q_OS_WINCE
- return QWindowsOpenGLTester::Gles;
-#endif
+#endif // !Q_OS_WINCE && !QT_NO_OPENGL
}
QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedGlesRenderers()
@@ -288,7 +293,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers()
bool QWindowsOpenGLTester::testDesktopGL()
{
-#ifndef Q_OS_WINCE
+#if !defined(QT_NO_OPENGL) && !defined(Q_OS_WINCE)
HMODULE lib = 0;
HWND wnd = 0;
HDC dc = 0;
@@ -414,9 +419,9 @@ cleanup:
// No FreeLibrary. Some implementations, Mesa in particular, deadlock when trying to unload.
return result;
-#else // !Q_OS_WINCE
+#else
return false;
-#endif
+#endif // !QT_NO_OPENGL && !Q_OS_WINCE
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index fc389ecf15..b1208d9793 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -2265,6 +2265,7 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
void *QWindowsWindow::surface(void *nativeConfig, int *err)
{
#ifdef QT_NO_OPENGL
+ Q_UNUSED(nativeConfig)
return 0;
#else
if (!m_surface) {
@@ -2278,11 +2279,13 @@ void *QWindowsWindow::surface(void *nativeConfig, int *err)
void QWindowsWindow::invalidateSurface()
{
+#ifndef QT_NO_OPENGL
if (m_surface) {
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
staticOpenGLContext->destroyWindowSurface(m_surface);
m_surface = 0;
}
+#endif // QT_NO_OPENGL
}
void QWindowsWindow::setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes)
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index e3880a2646..a0460630a7 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -122,7 +122,7 @@ contains(QT_CONFIG,dynamicgl) {
contains(QT_CONFIG, freetype) {
DEFINES *= QT_NO_FONTCONFIG
- include($$QT_SOURCE_TREE/src/3rdparty/freetype.pri)
+ include($$QT_SOURCE_TREE/src/3rdparty/freetype_dependency.pri)
HEADERS += \
$$PWD/qwindowsfontdatabase_ft.h
SOURCES += \
diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
index 6cd99c38ef..417befeb63 100644
--- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp
@@ -298,42 +298,48 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
return false;
}
- ComPtr<IMap<HSTRING, IVector<HSTRING> *>> choices;
- hr = picker->get_FileTypeChoices(&choices);
- RETURN_FALSE_IF_FAILED("Failed to get file extension choices");
- foreach (const QString &namedFilter, dialogOptions->nameFilters()) {
- ComPtr<IVector<HSTRING>> entry = Make<WindowsStringVector>();
- foreach (const QString &filter, QPlatformFileDialogHelper::cleanFilterList(namedFilter)) {
- // Remove leading star
- const int offset = (filter.length() > 1 && filter.startsWith(QLatin1Char('*'))) ? 1 : 0;
- HStringReference filterRef(reinterpret_cast<const wchar_t *>(filter.utf16() + offset),
- filter.length() - offset);
- hr = entry->Append(filterRef.Get());
- if (FAILED(hr)) {
- qWarning("Failed to add named file filter \"%s\": %s",
- qPrintable(filter), qPrintable(qt_error_string(hr)));
+ if (!dialogOptions->nameFilters().isEmpty()) {
+ ComPtr<IMap<HSTRING, IVector<HSTRING> *>> choices;
+ hr = picker->get_FileTypeChoices(&choices);
+ RETURN_FALSE_IF_FAILED("Failed to get file extension choices");
+ foreach (const QString &namedFilter, dialogOptions->nameFilters()) {
+ ComPtr<IVector<HSTRING>> entry = Make<WindowsStringVector>();
+ foreach (const QString &filter, QPlatformFileDialogHelper::cleanFilterList(namedFilter)) {
+ // Remove leading star
+ const int offset = (filter.length() > 1 && filter.startsWith(QLatin1Char('*'))) ? 1 : 0;
+ HStringReference filterRef(reinterpret_cast<const wchar_t *>(filter.utf16() + offset),
+ filter.length() - offset);
+ hr = entry->Append(filterRef.Get());
+ if (FAILED(hr)) {
+ qWarning("Failed to add named file filter \"%s\": %s",
+ qPrintable(filter), qPrintable(qt_error_string(hr)));
+ }
}
+ const int offset = namedFilter.indexOf(QLatin1String(" ("));
+ const QString filterTitle = namedFilter.mid(0, offset);
+ HStringReference namedFilterRef(reinterpret_cast<const wchar_t *>(filterTitle.utf16()),
+ filterTitle.length());
+ boolean replaced;
+ hr = choices->Insert(namedFilterRef.Get(), entry.Get(), &replaced);
+ RETURN_FALSE_IF_FAILED("Failed to insert file extension choice entry");
}
- const int offset = namedFilter.indexOf(QLatin1String(" ("));
- const QString filterTitle = offset > 0 ? namedFilter.left(offset) : filterTitle;
- HStringReference namedFilterRef(reinterpret_cast<const wchar_t *>(filterTitle.utf16()),
- filterTitle.length());
- boolean replaced;
- hr = choices->Insert(namedFilterRef.Get(), entry.Get(), &replaced);
- RETURN_FALSE_IF_FAILED("Failed to insert file extension choice entry");
}
const QString suffix = dialogOptions->defaultSuffix();
- HStringReference nativeSuffix(reinterpret_cast<const wchar_t *>(suffix.utf16()),
- suffix.length());
- hr = picker->put_DefaultFileExtension(nativeSuffix.Get());
- RETURN_FALSE_IF_FAILED("Failed to set default file extension");
+ if (!suffix.isEmpty()) {
+ HStringReference nativeSuffix(reinterpret_cast<const wchar_t *>(suffix.utf16()),
+ suffix.length());
+ hr = picker->put_DefaultFileExtension(nativeSuffix.Get());
+ RETURN_FALSE_IF_FAILED("Failed to set default file extension");
+ }
const QString suggestedName = QFileInfo(d->saveFileName.toLocalFile()).fileName();
- HStringReference nativeSuggestedName(reinterpret_cast<const wchar_t *>(suggestedName.utf16()),
- suggestedName.length());
- hr = picker->put_SuggestedFileName(nativeSuggestedName.Get());
- RETURN_FALSE_IF_FAILED("Failed to set suggested file name");
+ if (!suggestedName.isEmpty()) {
+ HStringReference nativeSuggestedName(reinterpret_cast<const wchar_t *>(suggestedName.utf16()),
+ suggestedName.length());
+ hr = picker->put_SuggestedFileName(nativeSuggestedName.Get());
+ RETURN_FALSE_IF_FAILED("Failed to set suggested file name");
+ }
ComPtr<IAsyncOperation<StorageFile *>> op;
hr = picker->PickSaveFileAsync(&op);
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
index f4e307eb07..719bb18dd6 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
@@ -70,7 +70,7 @@ class QWinRTFileEnginePrivate
{
public:
QWinRTFileEnginePrivate(const QString &fileName, IStorageItem *file)
- : fileName(fileName), file(file)
+ : fileName(fileName), file(file), openMode(QIODevice::NotOpen)
{
HRESULT hr;
hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(),
@@ -101,6 +101,7 @@ public:
int firstDot;
ComPtr<IStorageItem> file;
ComPtr<IRandomAccessStream> stream;
+ QIODevice::OpenMode openMode;
qint64 pos;
@@ -203,6 +204,8 @@ bool QWinRTFileEngine::open(QIODevice::OpenMode openMode)
hr = QWinRTFunctions::await(op, d->stream.GetAddressOf());
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::OpenError, false);
+ d->openMode = openMode;
+
return SUCCEEDED(hr);
}
@@ -220,9 +223,33 @@ bool QWinRTFileEngine::close()
hr = closable->Close();
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::UnspecifiedError, false);
d->stream.Reset();
+ d->openMode = QIODevice::NotOpen;
return SUCCEEDED(hr);
}
+bool QWinRTFileEngine::flush()
+{
+ Q_D(QWinRTFileEngine);
+
+ if (!d->stream)
+ return false;
+
+ if (!(d->openMode & QIODevice::WriteOnly))
+ return true;
+
+ ComPtr<IOutputStream> stream;
+ HRESULT hr = d->stream.As(&stream);
+ RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, false);
+ ComPtr<IAsyncOperation<bool>> flushOp;
+ hr = stream->FlushAsync(&flushOp);
+ RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, false);
+ boolean flushed;
+ hr = QWinRTFunctions::await(flushOp, &flushed);
+ RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, false);
+
+ return true;
+}
+
qint64 QWinRTFileEngine::size() const
{
Q_D(const QWinRTFileEngine);
@@ -484,13 +511,6 @@ qint64 QWinRTFileEngine::write(const char *data, qint64 maxlen)
hr = QWinRTFunctions::await(op, &length);
RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1);
- ComPtr<IAsyncOperation<bool>> flushOp;
- hr = stream->FlushAsync(&flushOp);
- RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1);
- boolean flushed;
- hr = QWinRTFunctions::await(flushOp, &flushed);
- RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::WriteError, -1);
-
return qint64(length);
}
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.h b/src/plugins/platforms/winrt/qwinrtfileengine.h
index 30357759fb..983338f2e2 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.h
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.h
@@ -71,6 +71,7 @@ public:
bool open(QIODevice::OpenMode openMode) Q_DECL_OVERRIDE;
bool close() Q_DECL_OVERRIDE;
+ bool flush() Q_DECL_OVERRIDE;
qint64 size() const Q_DECL_OVERRIDE;
qint64 pos() const Q_DECL_OVERRIDE;
bool seek(qint64 pos) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index ce2329724a..06db4d83ac 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -303,21 +303,30 @@ QXcbBackingStore::~QXcbBackingStore()
QPaintDevice *QXcbBackingStore::paintDevice()
{
- return m_image ? m_image->image() : 0;
+ if (!m_image)
+ return 0;
+ return m_rgbImage.isNull() ? m_image->image() : &m_rgbImage;
}
void QXcbBackingStore::beginPaint(const QRegion &region)
{
if (!m_image)
return;
- const int dpr = int(m_image->image()->devicePixelRatio());
- QRegion xRegion = dpr == 1 ? region : QTransform::fromScale(dpr,dpr).map(region);
- m_image->preparePaint(xRegion);
+
+ int dpr = int(m_image->image()->devicePixelRatio());
+ const int windowDpr = int(window()->devicePixelRatio());
+ if (windowDpr != dpr) {
+ resize(window()->size(), QRegion());
+ dpr = int(m_image->image()->devicePixelRatio());
+ }
+
+ m_paintRegion = dpr == 1 ? region : QTransform::fromScale(dpr,dpr).map(region);
+ m_image->preparePaint(m_paintRegion);
if (m_image->image()->hasAlphaChannel()) {
- QPainter p(m_image->image());
+ QPainter p(paintDevice());
p.setCompositionMode(QPainter::CompositionMode_Source);
- const QVector<QRect> rects = xRegion.rects();
+ const QVector<QRect> rects = m_paintRegion.rects();
const QColor blank = Qt::transparent;
for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
p.fillRect(*it, blank);
@@ -325,6 +334,24 @@ void QXcbBackingStore::beginPaint(const QRegion &region)
}
}
+void QXcbBackingStore::endPaint()
+{
+ QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window()->handle());
+ if (!platformWindow || !platformWindow->imageNeedsRgbSwap())
+ return;
+
+ // Slow path: the paint device was m_rgbImage. Now copy with swapping red
+ // and blue into m_image.
+ const QVector<QRect> rects = m_paintRegion.rects();
+ if (rects.isEmpty())
+ return;
+ QPainter p(m_image->image());
+ for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
+ const QRect rect = *it;
+ p.drawImage(rect.topLeft(), m_rgbImage.copy(rect).rgbSwapped());
+ }
+}
+
#ifndef QT_NO_OPENGL
QImage QXcbBackingStore::toImage() const
{
@@ -342,7 +369,15 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
if (!m_image || m_image->size().isEmpty())
return;
- QSize imageSize = m_image->size();
+ const int dpr = int(window->devicePixelRatio());
+
+#ifndef QT_NO_DEBUG
+ const int imageDpr = int(m_image->image()->devicePixelRatio());
+ if (dpr != imageDpr)
+ qWarning() << "QXcbBackingStore::flush() wrong devicePixelRatio for backingstore image" << dpr << imageDpr;
+#endif
+
+ QSize imageSize = m_image->size() / dpr; //because we multiply with the DPR later
QRegion clipped = region;
clipped &= QRect(0, 0, window->width(), window->height());
@@ -361,8 +396,6 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
return;
}
- const int dpr = int(window->devicePixelRatio());
-
QVector<QRect> rects = clipped.rects();
for (int i = 0; i < rects.size(); ++i) {
QRect rect = QRect(rects.at(i).topLeft() * dpr, rects.at(i).size() * dpr);
@@ -399,8 +432,7 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &)
{
const int dpr = int(window()->devicePixelRatio());
const QSize xSize = size * dpr;
-
- if (m_image && xSize == m_image->size())
+ if (m_image && xSize == m_image->size() && dpr == m_image->image()->devicePixelRatio())
return;
Q_XCB_NOOP(connection());
@@ -415,6 +447,12 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &)
delete m_image;
m_image = new QXcbShmImage(screen, xSize, win->depth(), win->imageFormat());
m_image->image()->setDevicePixelRatio(dpr);
+ // Slow path for bgr888 VNC: Create an additional image, paint into that and
+ // swap R and B while copying to m_image after each paint.
+ if (win->imageNeedsRgbSwap()) {
+ m_rgbImage = QImage(xSize, win->imageFormat());
+ m_rgbImage.setDevicePixelRatio(dpr);
+ }
Q_XCB_NOOP(connection());
}
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h
index 248542719b..b58a32d313 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.h
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.h
@@ -65,9 +65,12 @@ public:
bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE;
void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
+ void endPaint() Q_DECL_OVERRIDE;
private:
QXcbShmImage *m_image;
+ QRegion m_paintRegion;
+ QImage m_rgbImage;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index 2c0a7a11cc..248d1b4bbb 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -749,7 +749,8 @@ void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_eve
m_xClipboard[mode]->reset();
}
emitChanged(mode);
- } else if (event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_CLIENT_CLOSE)
+ } else if (event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_CLIENT_CLOSE ||
+ event->subtype == XCB_XFIXES_SELECTION_EVENT_SELECTION_WINDOW_DESTROY)
emitChanged(mode);
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 0ca141526e..706b9c8e48 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -306,71 +306,88 @@ void QXcbConnection::initializeScreens()
int connectedOutputCount = 0;
if (has_randr_extension) {
xcb_generic_error_t *error = NULL;
- xcb_randr_get_output_primary_cookie_t primaryCookie =
- xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root);
- // TODO: RRGetScreenResources has to be called on each X display at least once before
- // RRGetScreenResourcesCurrent can be used - we can't know if we are the first application
- // to do so or not, so we always call the slower version here. Ideally we should share some
- // global flag (an atom on root window maybe) that at least other Qt apps would understand
- // and could call RRGetScreenResourcesCurrent here, speeding up start.
- xcb_randr_get_screen_resources_cookie_t resourcesCookie =
- xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root);
- QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary(
- xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
- if (!primary || error) {
- qWarning("failed to get the primary output of the screen");
+ // RRGetScreenResourcesCurrent is fast but it may return nothing if the
+ // configuration is not initialized wrt to the hardware. We should call
+ // RRGetScreenResources in this case.
+ QScopedPointer<xcb_randr_get_screen_resources_reply_t, QScopedPointerPodDeleter> resources;
+ xcb_randr_get_screen_resources_current_cookie_t resourcesCookie =
+ xcb_randr_get_screen_resources_current(xcb_connection(), xcbScreen->root);
+ QScopedPointer<xcb_randr_get_screen_resources_current_reply_t, QScopedPointerPodDeleter> resources_current(
+ xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, &error));
+ if (!resources_current || error) {
+ qWarning("failed to get the current screen resources");
free(error);
} else {
- QScopedPointer<xcb_randr_get_screen_resources_reply_t, QScopedPointerPodDeleter> resources(
- xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error));
- if (!resources || error) {
- qWarning("failed to get the screen resources");
- free(error);
+ xcb_timestamp_t timestamp;
+ xcb_randr_output_t *outputs = Q_NULLPTR;
+ outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
+ if (outputCount) {
+ timestamp = resources_current->config_timestamp;
+ outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data());
} else {
- xcb_timestamp_t timestamp = resources->config_timestamp;
- outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data());
- xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources.data());
-
- for (int i = 0; i < outputCount; i++) {
- QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
- xcb_randr_get_output_info_reply(xcb_connection(),
- xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL));
-
- // Invalid, disconnected or disabled output
- if (output == NULL)
- continue;
-
- if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) {
- qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable(
- QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()),
- xcb_randr_get_output_info_name_length(output.data()))));
- continue;
- }
+ xcb_randr_get_screen_resources_cookie_t resourcesCookie =
+ xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root);
+ resources.reset(xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error));
+ if (!resources || error) {
+ qWarning("failed to get the screen resources");
+ free(error);
+ } else {
+ timestamp = resources->config_timestamp;
+ outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data());
+ outputs = xcb_randr_get_screen_resources_outputs(resources.data());
+ }
+ }
- if (output->crtc == XCB_NONE) {
- qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable(
- QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()),
- xcb_randr_get_output_info_name_length(output.data()))));
- continue;
- }
+ if (outputCount) {
+ xcb_randr_get_output_primary_cookie_t primaryCookie =
+ xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root);
+ QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary(
+ xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
+ if (!primary || error) {
+ qWarning("failed to get the primary output of the screen");
+ free(error);
+ } else {
+ for (int i = 0; i < outputCount; i++) {
+ QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
+ xcb_randr_get_output_info_reply(xcb_connection(),
+ xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL));
+
+ // Invalid, disconnected or disabled output
+ if (output == NULL)
+ continue;
+
+ if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) {
+ qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable(
+ QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()),
+ xcb_randr_get_output_info_name_length(output.data()))));
+ continue;
+ }
+
+ if (output->crtc == XCB_NONE) {
+ qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable(
+ QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()),
+ xcb_randr_get_output_info_name_length(output.data()))));
+ continue;
+ }
- QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data());
- siblings << screen;
- ++connectedOutputCount;
- hasOutputs = true;
- m_screens << screen;
-
- // There can be multiple outputs per screen, use either
- // the first or an exact match. An exact match isn't
- // always available if primary->output is XCB_NONE
- // or currently disconnected output.
- if (m_primaryScreenNumber == xcbScreenNumber) {
- if (!primaryScreen || (primary && outputs[i] == primary->output)) {
- if (primaryScreen)
- primaryScreen->setPrimary(false);
- primaryScreen = screen;
- primaryScreen->setPrimary(true);
- siblings.prepend(siblings.takeLast());
+ QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data());
+ siblings << screen;
+ ++connectedOutputCount;
+ hasOutputs = true;
+ m_screens << screen;
+
+ // There can be multiple outputs per screen, use either
+ // the first or an exact match. An exact match isn't
+ // always available if primary->output is XCB_NONE
+ // or currently disconnected output.
+ if (m_primaryScreenNumber == xcbScreenNumber) {
+ if (!primaryScreen || (primary && outputs[i] == primary->output)) {
+ if (primaryScreen)
+ primaryScreen->setPrimary(false);
+ primaryScreen = screen;
+ primaryScreen->setPrimary(true);
+ siblings.prepend(siblings.takeLast());
+ }
}
}
}
@@ -1120,7 +1137,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
}
}
- if (!handled)
+ if (!handled && m_glIntegration)
handled = m_glIntegration->handleXcbEvent(event, response_type);
if (handled)
@@ -1463,6 +1480,7 @@ static const char * xcb_atomnames = {
"WM_STATE\0"
"WM_CHANGE_STATE\0"
"WM_CLASS\0"
+ "WM_NAME\0"
// Session management
"WM_CLIENT_LEADER\0"
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 4c014bc6e2..1190e7c2b0 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -107,6 +107,7 @@ namespace QXcbAtom {
WM_STATE,
WM_CHANGE_STATE,
WM_CLASS,
+ WM_NAME,
// Session management
WM_CLIENT_LEADER,
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index e3a04c1d7b..8dd27ec9c5 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -53,6 +53,12 @@ typedef int (*PtrXcursorLibrarySetTheme)(void *, const char *);
typedef int (*PtrXcursorLibraryGetDefaultSize)(void *);
#ifdef XCB_USE_XLIB
+#include <X11/Xlib.h>
+enum {
+ XCursorShape = CursorShape
+};
+#undef CursorShape
+
static PtrXcursorLibraryLoadCursor ptrXcursorLibraryLoadCursor = 0;
static PtrXcursorLibraryGetTheme ptrXcursorLibraryGetTheme = 0;
static PtrXcursorLibrarySetTheme ptrXcursorLibrarySetTheme = 0;
@@ -552,6 +558,12 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
}
if (cursor)
return cursor;
+ if (!cursor && cursorId) {
+ cursor = XCreateFontCursor(DISPLAY_FROM_XCB(this), cursorId);
+ if (cursor)
+ return cursor;
+ }
+
#endif
// Non-standard X11 cursors are created from bitmaps
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 258359d20f..2547e537a7 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -186,9 +186,9 @@ QXcbIntegration::~QXcbIntegration()
QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const
{
+ QXcbScreen *screen = static_cast<QXcbScreen *>(window->screen()->handle());
+ QXcbGlIntegration *glIntegration = screen->connection()->glIntegration();
if (window->type() != Qt::Desktop) {
- QXcbScreen *screen = static_cast<QXcbScreen *>(window->screen()->handle());
- QXcbGlIntegration *glIntegration = screen->connection()->glIntegration();
if (glIntegration) {
QXcbWindow *xcbWindow = glIntegration->createWindow(window);
xcbWindow->create();
@@ -196,7 +196,8 @@ QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const
}
}
- Q_ASSERT(window->type() == Qt::Desktop || !window->supportsOpenGL());
+ Q_ASSERT(window->type() == Qt::Desktop || !window->supportsOpenGL()
+ || (!glIntegration && window->surfaceType() == QSurface::RasterGLSurface)); // for VNC
QXcbWindow *xcbWindow = new QXcbWindow(window);
xcbWindow->create();
return xcbWindow;
@@ -374,6 +375,8 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
// X11 always has support for windows, but the
// window manager could prevent it (e.g. matchbox)
return false;
+ case QPlatformIntegration::ReplayMousePressOutsidePopup:
+ return false;
default:
break;
}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index eabebffdab..0b38def63b 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -87,6 +87,7 @@
#include <qpa/qplatformbackingstore.h>
#include <qpa/qwindowsysteminterface.h>
+#include <QTextCodec>
#include <stdio.h>
#ifdef XCB_USE_XLIB
@@ -156,6 +157,11 @@ static inline QPoint dpr_ceil(const QPoint &p, int dpr)
return QPoint((p.x() + dpr - 1) / dpr, (p.y() + dpr - 1) / dpr);
}
+static inline QSize dpr_ceil(const QSize &s, int dpr)
+{
+ return QSize((s.width() + dpr - 1) / dpr, (s.height() + dpr - 1) / dpr);
+}
+
static inline QRect mapExposeFromNative(const QRect &xRect, int dpr)
{
return QRect(dpr_floor(xRect.topLeft(), dpr), dpr_ceil(xRect.bottomRight(), dpr));
@@ -163,7 +169,7 @@ static inline QRect mapExposeFromNative(const QRect &xRect, int dpr)
static inline QRect mapGeometryFromNative(const QRect &xRect, int dpr)
{
- return QRect(xRect.topLeft() / dpr, xRect.bottomRight() / dpr);
+ return QRect(xRect.topLeft() / dpr, dpr_ceil(xRect.size(), dpr));
}
// Returns \c true if we should set WM_TRANSIENT_FOR on \a w
@@ -178,8 +184,10 @@ static inline bool isTransient(const QWindow *w)
|| w->type() == Qt::Popup;
}
-static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask)
+static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, quint32 blue_mask, bool *rgbSwap)
{
+ if (rgbSwap)
+ *rgbSwap = false;
switch (depth) {
case 32:
if (blue_mask == 0xff)
@@ -188,6 +196,11 @@ static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, q
return QImage::Format_A2BGR30_Premultiplied;
if (blue_mask == 0x3ff)
return QImage::Format_A2RGB30_Premultiplied;
+ if (red_mask == 0xff) {
+ if (rgbSwap)
+ *rgbSwap = true;
+ return QImage::Format_ARGB32_Premultiplied;
+ }
break;
case 30:
if (red_mask == 0x3ff)
@@ -198,6 +211,11 @@ static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, q
case 24:
if (blue_mask == 0xff)
return QImage::Format_RGB32;
+ if (red_mask == 0xff) {
+ if (rgbSwap)
+ *rgbSwap = true;
+ return QImage::Format_RGB32;
+ }
break;
case 16:
if (blue_mask == 0x1f)
@@ -227,6 +245,48 @@ static inline bool positionIncludesFrame(QWindow *w)
return qt_window_private(w)->positionPolicy == QWindowPrivate::WindowFrameInclusive;
}
+#ifdef XCB_USE_XLIB
+static inline XTextProperty* qstringToXTP(Display *dpy, const QString& s)
+{
+ #include <X11/Xatom.h>
+
+ static XTextProperty tp = { 0, 0, 0, 0 };
+ static bool free_prop = true; // we can't free tp.value in case it references
+ // the data of the static QByteArray below.
+ if (tp.value) {
+ if (free_prop)
+ XFree(tp.value);
+ tp.value = 0;
+ free_prop = true;
+ }
+
+ static const QTextCodec* mapper = QTextCodec::codecForLocale();
+ int errCode = 0;
+ if (mapper) {
+ QByteArray mapped = mapper->fromUnicode(s);
+ char* tl[2];
+ tl[0] = mapped.data();
+ tl[1] = 0;
+ errCode = XmbTextListToTextProperty(dpy, tl, 1, XStdICCTextStyle, &tp);
+ if (errCode < 0)
+ qDebug("XmbTextListToTextProperty result code %d", errCode);
+ }
+ if (!mapper || errCode < 0) {
+ mapper = QTextCodec::codecForName("latin1");
+ if (!mapper || !mapper->canEncode(s))
+ return Q_NULLPTR;
+ static QByteArray qcs;
+ qcs = s.toLatin1();
+ tp.value = (uchar*)qcs.data();
+ tp.encoding = XA_STRING;
+ tp.format = 8;
+ tp.nitems = qcs.length();
+ free_prop = false;
+ }
+ return &tp;
+}
+#endif // XCB_USE_XLIB
+
static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
QXcbWindow::QXcbWindow(QWindow *window)
@@ -292,7 +352,7 @@ void QXcbWindow::create()
m_depth = platformScreen->screen()->root_depth;
m_visualId = platformScreen->screen()->root_visual;
const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId);
- m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask);
+ m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
connection()->addWindowEventListener(m_window, this);
return;
}
@@ -364,7 +424,7 @@ void QXcbWindow::create()
if (visualInfo) {
m_depth = visualInfo->depth;
- m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask);
+ m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask, &m_imageRgbSwap);
Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), xcb_parent_id, visualInfo->visual, AllocNone);
XSetWindowAttributes a;
@@ -417,7 +477,7 @@ void QXcbWindow::create()
}
const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId);
- m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask);
+ m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
Q_XCB_CALL(xcb_create_window(xcb_connection(),
m_depth,
@@ -1407,6 +1467,12 @@ void QXcbWindow::setWindowTitle(const QString &title)
8,
ba.length(),
ba.constData()));
+
+#ifdef XCB_USE_XLIB
+ XTextProperty *text = qstringToXTP(DISPLAY_FROM_XCB(this), title);
+ if (text)
+ XSetWMName(DISPLAY_FROM_XCB(this), m_window, text);
+#endif
xcb_flush(xcb_connection());
}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index cd3c091973..2442e6c4e3 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -114,6 +114,7 @@ public:
xcb_window_t xcb_window() const { return m_window; }
uint depth() const { return m_depth; }
QImage::Format imageFormat() const { return m_imageFormat; }
+ bool imageNeedsRgbSwap() const { return m_imageRgbSwap; }
bool handleGenericEvent(xcb_generic_event_t *event, long *result) Q_DECL_OVERRIDE;
@@ -205,6 +206,7 @@ protected:
uint m_depth;
QImage::Format m_imageFormat;
+ bool m_imageRgbSwap;
xcb_sync_int64_t m_syncValue;
xcb_sync_counter_t m_syncCounter;