summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm22
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm3
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp2
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h10
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp51
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h18
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp11
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp6
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp157
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h9
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp5
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.cpp7
-rw-r--r--src/plugins/platforms/xcb/qxcbmime.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp17
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp45
21 files changed, 356 insertions, 56 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index f8411845dc..d322079cb2 100644
--- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
+++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
@@ -333,6 +333,7 @@ static void cleanupCocoaApplicationDelegate()
&& [reflectionDelegate respondsToSelector:@selector(applicationDidBecomeActive:)])
[reflectionDelegate applicationDidBecomeActive:notification];
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
/*
onApplicationChangedActivation(true);
@@ -356,6 +357,7 @@ static void cleanupCocoaApplicationDelegate()
&& [reflectionDelegate respondsToSelector:@selector(applicationDidResignActive:)])
[reflectionDelegate applicationDidResignActive:notification];
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
/*
onApplicationChangedActivation(false);
@@ -367,6 +369,26 @@ static void cleanupCocoaApplicationDelegate()
*/
}
+- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
+{
+ Q_UNUSED(theApplication);
+ Q_UNUSED(flag);
+ if (reflectionDelegate
+ && [reflectionDelegate respondsToSelector:@selector(applicationShouldHandleReopen:hasVisibleWindows:)])
+ return [reflectionDelegate applicationShouldHandleReopen:theApplication hasVisibleWindows:flag];
+
+ /*
+ true to force delivery of the event even if the application state is already active,
+ because rapp (handle reopen) events are sent each time the dock icon is clicked regardless
+ of the active state of the application or number of visible windows. For example, a browser
+ app that has no windows opened would need the event be to delivered even if it was already
+ active in order to create a new window as per OS X conventions.
+ */
+ QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive, true /*forcePropagate*/);
+
+ return NO;
+}
+
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate
{
[oldDelegate retain];
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index c4398622e8..e7a973e45b 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -405,14 +405,13 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
case MultipleWindows:
case ForeignWindows:
case RasterGLSurface:
+ case ApplicationState:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
}
}
-
-
QPlatformWindow *QCocoaIntegration::createPlatformWindow(QWindow *window) const
{
return new QCocoaWindow(window);
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
index 6c6c516a4e..3f959b859c 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.cpp
@@ -179,7 +179,7 @@ QOffscreenX11GLXContext::QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGL
// Get the basic surface format details
if (d->context)
- qglx_surfaceFormatFromGLXFBConfig(&d->format, x11->display(), config, d->context);
+ qglx_surfaceFormatFromGLXFBConfig(&d->format, x11->display(), config);
// Create a temporary window so that we can make the new context current
d->window = createDummyWindow(x11, config);
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index ee640224cf..3992f2d297 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2013 Samuel Gaist <samuel.gaist@edeltech.ch>
-** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the plugins of the Qt Toolkit.
@@ -117,6 +117,14 @@ enum WindowsEventType // Simplify event types
UnknownEvent = 542
};
+// Matches Process_DPI_Awareness (Windows 8.1 onwards), used for SetProcessDpiAwareness()
+enum ProcessDpiAwareness
+{
+ ProcessDpiUnaware,
+ ProcessSystemDpiAware,
+ ProcessPerMonitorDpiAware
+};
+
} // namespace QtWindows
inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamIn)
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index ead29556b7..ccff2d3e9f 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -247,8 +247,26 @@ void QWindowsShell32DLL::init()
sHGetImageList = (SHGetImageList)library.resolve("SHGetImageList");
}
+QWindowsShcoreDLL::QWindowsShcoreDLL()
+ : getProcessDpiAwareness(0)
+ , setProcessDpiAwareness(0)
+ , getDpiForMonitor(0)
+{
+}
+
+void QWindowsShcoreDLL::init()
+{
+ if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS8_1)
+ return;
+ QSystemLibrary library(QStringLiteral("SHCore"));
+ getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness");
+ setProcessDpiAwareness = (SetProcessDpiAwareness)library.resolve("SetProcessDpiAwareness");
+ getDpiForMonitor = (GetDpiForMonitor)library.resolve("GetDpiForMonitor");
+}
+
QWindowsUser32DLL QWindowsContext::user32dll;
QWindowsShell32DLL QWindowsContext::shell32dll;
+QWindowsShcoreDLL QWindowsContext::shcoredll;
#endif // !Q_OS_WINCE
@@ -299,9 +317,7 @@ QWindowsContextPrivate::QWindowsContextPrivate()
#ifndef Q_OS_WINCE
QWindowsContext::user32dll.init();
QWindowsContext::shell32dll.init();
- // Ensure metrics functions report correct data, QTBUG-30063.
- if (QWindowsContext::user32dll.setProcessDPIAware)
- QWindowsContext::user32dll.setProcessDPIAware();
+ QWindowsContext::shcoredll.init();
if (hasTouchSupport(ver) && QWindowsContext::user32dll.initTouch())
m_systemInfo |= QWindowsContext::SI_SupportsTouch;
@@ -358,6 +374,25 @@ void QWindowsContext::setTabletAbsoluteRange(int a)
#endif
}
+void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness)
+{
+#ifndef Q_OS_WINCE
+ qCDebug(lcQpaWindows) << __FUNCTION__ << dpiAwareness;
+ if (QWindowsContext::shcoredll.isValid()) {
+ const HRESULT hr = QWindowsContext::shcoredll.setProcessDpiAwareness(dpiAwareness);
+ if (FAILED(hr))
+ qWarning() << "SetProcessDpiAwareness failed:" << QWindowsContext::comErrorString(hr);
+ } else {
+ if (dpiAwareness != QtWindows::ProcessDpiUnaware && QWindowsContext::user32dll.setProcessDPIAware) {
+ if (!QWindowsContext::user32dll.setProcessDPIAware())
+ qErrnoWarning("SetProcessDPIAware() failed");
+ }
+ }
+#else // !Q_OS_WINCE
+ Q_UNUSED(dpiAwareness)
+#endif
+}
+
QWindowsContext *QWindowsContext::instance()
{
return m_instance;
@@ -419,9 +454,17 @@ QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL)
&& (type == Qt::Popup || w->property("_q_windowsDropShadow").toBool())) {
style |= CS_DROPSHADOW;
}
- if (type == Qt::Tool || type == Qt::ToolTip || type == Qt::Popup) {
+ switch (type) {
+ case Qt::Tool:
+ case Qt::ToolTip:
+ case Qt::Popup:
style |= CS_SAVEBITS; // Save/restore background
icon = false;
+ break;
+ case Qt::Dialog:
+ if (!(flags & Qt::WindowSystemMenuHint))
+ icon = false; // QTBUG-2027, dialogs without system menu.
+ break;
}
// Create a unique name for the flag combination
QString cname = QStringLiteral("Qt5QWindow");
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index f5dbd072c7..d565a5feab 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -126,6 +126,22 @@ struct QWindowsShell32DLL
SHGetStockIconInfo sHGetStockIconInfo;
SHGetImageList sHGetImageList;
};
+
+// Shell scaling library (Windows 8.1 onwards)
+struct QWindowsShcoreDLL {
+ QWindowsShcoreDLL();
+ void init();
+ inline bool isValid() const { return getProcessDpiAwareness && setProcessDpiAwareness && getDpiForMonitor; }
+
+ typedef HRESULT (WINAPI *GetProcessDpiAwareness)(HANDLE,int);
+ typedef HRESULT (WINAPI *SetProcessDpiAwareness)(int);
+ typedef HRESULT (WINAPI *GetDpiForMonitor)(HMONITOR,int,UINT *,UINT *);
+
+ GetProcessDpiAwareness getProcessDpiAwareness;
+ SetProcessDpiAwareness setProcessDpiAwareness;
+ GetDpiForMonitor getDpiForMonitor;
+};
+
#endif // Q_OS_WINCE
class QWindowsContext
@@ -184,6 +200,7 @@ public:
void setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx);
void setTabletAbsoluteRange(int a);
+ void setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness);
// Returns a combination of SystemInfoFlags
unsigned systemInfo() const;
@@ -197,6 +214,7 @@ public:
#ifndef Q_OS_WINCE
static QWindowsUser32DLL user32dll;
static QWindowsShell32DLL shell32dll;
+ static QWindowsShcoreDLL shcoredll;
#endif
static QByteArray comErrorString(HRESULT hr);
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 78bf833526..aed7ad9c46 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -167,7 +167,8 @@ struct QWindowsIntegrationPrivate
};
static inline unsigned parseOptions(const QStringList &paramList,
- int *tabletAbsoluteRange)
+ int *tabletAbsoluteRange,
+ QtWindows::ProcessDpiAwareness *dpiAwareness)
{
unsigned options = 0;
foreach (const QString &param, paramList) {
@@ -191,6 +192,8 @@ static inline unsigned parseOptions(const QStringList &paramList,
QWindowsContext::verbose = param.right(param.size() - 8).toInt();
} else if (param.startsWith(QLatin1String("tabletabsoluterange="))) {
*tabletAbsoluteRange = param.rightRef(param.size() - 20).toInt();
+ } else if (param.startsWith(QLatin1String("dpiawareness="))) {
+ *dpiAwareness = static_cast<QtWindows::ProcessDpiAwareness>(param.rightRef(param.size() - 13).toInt());
}
}
return options;
@@ -201,9 +204,13 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramL
, m_fontDatabase(0)
{
int tabletAbsoluteRange = -1;
- m_options = parseOptions(paramList, &tabletAbsoluteRange);
+ // Default to per-monitor awareness to avoid being scaled when monitors with different DPI
+ // are connected to Windows 8.1
+ QtWindows::ProcessDpiAwareness dpiAwareness = QtWindows::ProcessPerMonitorDpiAware;
+ m_options = parseOptions(paramList, &tabletAbsoluteRange, &dpiAwareness);
if (tabletAbsoluteRange >= 0)
m_context.setTabletAbsoluteRange(tabletAbsoluteRange);
+ m_context.setProcessDpiAwareness(dpiAwareness);
}
QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index a6e2aabaf0..4d6b822793 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -68,6 +68,21 @@ static inline QDpi deviceDPI(HDC hdc)
return QDpi(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
}
+#ifndef Q_OS_WINCE
+
+static inline QDpi monitorDPI(HMONITOR hMonitor)
+{
+ if (QWindowsContext::shcoredll.isValid()) {
+ UINT dpiX;
+ UINT dpiY;
+ if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, 0, &dpiX, &dpiY)))
+ return QDpi(dpiX, dpiY);
+ }
+ return QDpi(0, 0);
+}
+
+#endif // !Q_OS_WINCE
+
static inline QSizeF deviceSizeMM(const QSize &pixels, const QDpi &dpi)
{
const qreal inchToMM = 25.4;
@@ -110,7 +125,12 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
HDC hdc = CreateDC(info.szDevice, NULL, NULL, NULL);
#endif
if (hdc) {
+#ifndef Q_OS_WINCE
+ const QDpi dpi = monitorDPI(hMonitor);
+ data.dpi = dpi.first ? dpi : deviceDPI(hdc);
+#else
data.dpi = deviceDPI(hdc);
+#endif
data.depth = GetDeviceCaps(hdc, BITSPIXEL);
data.format = data.depth == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
data.physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE));
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index c8eaded38d..2a221e71ca 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -110,6 +110,8 @@ static QByteArray debugWinExStyle(DWORD exStyle)
rc += " WS_EX_CONTEXTHELP";
if (exStyle & WS_EX_LAYERED)
rc += " WS_EX_LAYERED";
+ if (exStyle & WS_EX_DLGMODALFRAME)
+ rc += " WS_EX_DLGMODALFRAME";
return rc;
}
@@ -513,6 +515,10 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
}
if (flags & Qt::WindowSystemMenuHint)
style |= WS_SYSMENU;
+ else if (dialog) {
+ style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
+ exStyle |= WS_EX_DLGMODALFRAME;
+ }
if (flags & Qt::WindowMinimizeButtonHint)
style |= WS_MINIMIZEBOX;
if (shouldShowMaximizeButton(w, flags))
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index f78d3bcc4e..30d5c911e7 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -54,6 +54,7 @@
#include "qglxintegration.h"
#include <QtPlatformSupport/private/qglxconvenience_p.h>
+#include <QtPlatformHeaders/QGLXNativeContext>
#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
#include <dlfcn.h>
@@ -83,31 +84,31 @@ typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXC
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
#endif
-static Window createDummyWindow(QXcbScreen *screen, XVisualInfo *visualInfo)
+static Window createDummyWindow(Display *dpy, XVisualInfo *visualInfo, int screenNumber, Window rootWin)
{
- Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(screen), screen->root(), visualInfo->visual, AllocNone);
+ Colormap cmap = XCreateColormap(dpy, rootWin, visualInfo->visual, AllocNone);
XSetWindowAttributes a;
- a.background_pixel = WhitePixel(DISPLAY_FROM_XCB(screen), screen->screenNumber());
- a.border_pixel = BlackPixel(DISPLAY_FROM_XCB(screen), screen->screenNumber());
+ a.background_pixel = WhitePixel(dpy, screenNumber);
+ a.border_pixel = BlackPixel(dpy, screenNumber);
a.colormap = cmap;
- Window window = XCreateWindow(DISPLAY_FROM_XCB(screen), screen->root(),
+ Window window = XCreateWindow(dpy, rootWin,
0, 0, 100, 100,
0, visualInfo->depth, InputOutput, visualInfo->visual,
CWBackPixel|CWBorderPixel|CWColormap, &a);
#ifndef QT_NO_DEBUG
- XStoreName(DISPLAY_FROM_XCB(screen), window, "Qt GLX dummy window");
+ XStoreName(dpy, window, "Qt GLX dummy window");
#endif
- XFreeColormap(DISPLAY_FROM_XCB(screen), cmap);
+ XFreeColormap(dpy, cmap);
return window;
}
-static Window createDummyWindow(QXcbScreen *screen, GLXFBConfig config)
+static Window createDummyWindow(Display *dpy, GLXFBConfig config, int screenNumber, Window rootWin)
{
- XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config);
+ XVisualInfo *visualInfo = glXGetVisualFromFBConfig(dpy, config);
if (!visualInfo)
qFatal("Could not initialize GLX");
- Window window = createDummyWindow(screen, visualInfo);
+ Window window = createDummyWindow(dpy, visualInfo, screenNumber, rootWin);
XFree(visualInfo);
return window;
}
@@ -160,7 +161,8 @@ static void updateFormatFromContext(QSurfaceFormat &format)
}
}
-QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
+QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share,
+ const QVariant &nativeHandle)
: QPlatformOpenGLContext()
, m_screen(screen)
, m_context(0)
@@ -168,6 +170,15 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
, m_format(format)
, m_isPBufferCurrent(false)
, m_swapInterval(-1)
+ , m_ownsContext(nativeHandle.isNull())
+{
+ if (nativeHandle.isNull())
+ init(screen, share);
+ else
+ init(screen, share, nativeHandle);
+}
+
+void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
{
if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
m_format.setRenderableType(QSurfaceFormat::OpenGL);
@@ -195,7 +206,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
&& (m_format.renderableType() != QSurfaceFormat::OpenGLES || (supportsProfiles && glxExt.contains("GLX_EXT_create_context_es2_profile")))) {
// Try to create an OpenGL context for each known OpenGL version in descending
// order from the requested version.
- const int requestedVersion = format.majorVersion() * 10 + qMin(format.minorVersion(), 9);
+ const int requestedVersion = m_format.majorVersion() * 10 + qMin(m_format.minorVersion(), 9);
QVector<int> glVersions;
if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
@@ -282,10 +293,10 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
// Get the basic surface format details
if (m_context)
- qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(screen), config, m_context);
+ qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(screen), config);
// Create a temporary window so that we can make the new context current
- window = createDummyWindow(screen, config);
+ window = createDummyWindow(DISPLAY_FROM_XCB(screen), config, screen->screenNumber(), screen->root());
} else {
// requesting an OpenGL ES context requires glXCreateContextAttribsARB, so bail out
if (m_format.renderableType() == QSurfaceFormat::OpenGLES)
@@ -303,7 +314,7 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
}
// Create a temporary window so that we can make the new context current
- window = createDummyWindow(screen, visualInfo);
+ window = createDummyWindow(DISPLAY_FROM_XCB(screen), visualInfo, screen->screenNumber(), screen->root());
XFree(visualInfo);
}
@@ -320,9 +331,123 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat
XDestroyWindow(DISPLAY_FROM_XCB(screen), window);
}
+void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle)
+{
+ if (!nativeHandle.canConvert<QGLXNativeContext>()) {
+ qWarning("QGLXContext: Requires a QGLXNativeContext");
+ return;
+ }
+ QGLXNativeContext handle = nativeHandle.value<QGLXNativeContext>();
+ GLXContext context = handle.context();
+ if (!context) {
+ qWarning("QGLXContext: No GLXContext given");
+ return;
+ }
+
+ // Use the provided Display, if available. If not, use our own. It may still work.
+ Display *dpy = handle.display();
+ if (!dpy)
+ dpy = DISPLAY_FROM_XCB(screen);
+
+ // Legacy contexts created using glXCreateContext are created using a visual
+ // and the FBConfig cannot be queried. The only way to adapt these contexts
+ // is to figure out the visual id.
+ XVisualInfo *vinfo = 0;
+ // If the VisualID is provided use it.
+ VisualID vid = handle.visualId();
+ if (!vid) {
+ // In the absence of the VisualID figure it out from the window.
+ Window wnd = handle.window();
+ if (wnd) {
+ XWindowAttributes attrs;
+ XGetWindowAttributes(dpy, wnd, &attrs);
+ vid = XVisualIDFromVisual(attrs.visual);
+ }
+ }
+ if (vid) {
+ XVisualInfo v;
+ v.screen = screen->screenNumber();
+ v.visualid = vid;
+ int n = 0;
+ vinfo = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, &v, &n);
+ if (n < 1) {
+ XFree(vinfo);
+ vinfo = 0;
+ }
+ }
+
+ // For contexts created with an FBConfig using the modern functions providing the
+ // visual or window is not mandatory. Just query the config from the context.
+ GLXFBConfig config = 0;
+ if (!vinfo) {
+ int configId = 0;
+ if (glXQueryContext(dpy, context, GLX_FBCONFIG_ID, &configId) != Success) {
+ qWarning("QGLXContext: Failed to query config from the provided context");
+ return;
+ }
+
+ GLXFBConfig *configs;
+ int numConfigs = 0;
+ static const int attribs[] = { GLX_FBCONFIG_ID, configId, None };
+ configs = glXChooseFBConfig(dpy, screen->screenNumber(), attribs, &numConfigs);
+ if (!configs || numConfigs < 1) {
+ qWarning("QGLXContext: Failed to find config");
+ return;
+ }
+ if (configs && numConfigs > 1) // this is suspicious so warn but let it continue
+ qWarning("QGLXContext: Multiple configs for FBConfig ID %d", configId);
+
+ config = configs[0];
+ }
+
+ Q_ASSERT(vinfo || config);
+
+ int screenNumber = DefaultScreen(dpy);
+ Window window;
+ if (vinfo)
+ window = createDummyWindow(dpy, vinfo, screenNumber, RootWindow(dpy, screenNumber));
+ else
+ window = createDummyWindow(dpy, config, screenNumber, RootWindow(dpy, screenNumber));
+ if (!window) {
+ qWarning("QGLXContext: Failed to create dummy window");
+ return;
+ }
+
+ // Update OpenGL version and buffer sizes in our format.
+ if (!glXMakeCurrent(dpy, window, context)) {
+ qWarning("QGLXContext: Failed to make provided context current");
+ return;
+ }
+ m_format = QSurfaceFormat();
+ m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::DesktopGL
+ ? QSurfaceFormat::OpenGL : QSurfaceFormat::OpenGLES);
+ updateFormatFromContext(m_format);
+ if (vinfo)
+ qglx_surfaceFormatFromVisualInfo(&m_format, dpy, vinfo);
+ else
+ qglx_surfaceFormatFromGLXFBConfig(&m_format, dpy, config);
+ glXMakeCurrent(dpy, 0, 0);
+ XDestroyWindow(dpy, window);
+
+ if (vinfo)
+ XFree(vinfo);
+
+ // Success. Store the context. From this point on isValid() is true.
+ m_context = context;
+
+ if (share)
+ m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
+}
+
QGLXContext::~QGLXContext()
{
- glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context);
+ if (m_ownsContext)
+ glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context);
+}
+
+QVariant QGLXContext::nativeHandle() const
+{
+ return QVariant::fromValue<QGLXNativeContext>(QGLXNativeContext(m_context));
}
bool QGLXContext::makeCurrent(QPlatformSurface *surface)
diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h
index 00bba94ab3..a7787f5f86 100644
--- a/src/plugins/platforms/xcb/qglxintegration.h
+++ b/src/plugins/platforms/xcb/qglxintegration.h
@@ -58,7 +58,8 @@ QT_BEGIN_NAMESPACE
class QGLXContext : public QPlatformOpenGLContext
{
public:
- QGLXContext(QXcbScreen *xd, const QSurfaceFormat &format, QPlatformOpenGLContext *share);
+ QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share,
+ const QVariant &nativeHandle);
~QGLXContext();
bool makeCurrent(QPlatformSurface *surface);
@@ -72,16 +73,22 @@ public:
GLXContext glxContext() const { return m_context; }
+ QVariant nativeHandle() const;
+
static bool supportsThreading();
static void queryDummyContext();
private:
+ void init(QXcbScreen *screen, QPlatformOpenGLContext *share);
+ void init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle);
+
QXcbScreen *m_screen;
GLXContext m_context;
GLXContext m_shareContext;
QSurfaceFormat m_format;
bool m_isPBufferCurrent;
int m_swapInterval;
+ bool m_ownsContext;
static bool m_queriedDummyContext;
static bool m_supportsThreading;
};
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index e7f8510706..3b30274f25 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -135,9 +135,10 @@ protected:
(void)formats(); // trigger update of format list
- QList<xcb_atom_t> atoms;
+ QVector<xcb_atom_t> atoms;
xcb_atom_t *targets = (xcb_atom_t *) format_atoms.data();
int size = format_atoms.size() / sizeof(xcb_atom_t);
+ atoms.reserve(size);
for (int i = 0; i < size; ++i)
atoms.append(targets[i]);
@@ -524,7 +525,7 @@ xcb_atom_t QXcbClipboard::sendTargetsSelection(QMimeData *d, xcb_window_t window
QVector<xcb_atom_t> types;
QStringList formats = QInternalMimeData::formatsHelper(d);
for (int i = 0; i < formats.size(); ++i) {
- QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), formats.at(i));
+ QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), formats.at(i));
for (int j = 0; j < atoms.size(); ++j) {
if (!types.contains(atoms.at(j)))
types.append(atoms.at(j));
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 1933b89a19..1719d8ec6b 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -451,6 +451,7 @@ public:
void setFocusWindow(QXcbWindow *);
QByteArray startupId() const { return m_startupId; }
+ void setStartupId(const QByteArray &nextId) { m_startupId = nextId; }
void clearStartupId() { m_startupId.clear(); }
void grabServer();
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 4f0f57c375..bcadcd1f02 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -183,7 +183,7 @@ void QXcbDrag::startDrag()
QStringList fmts = QXcbMime::formatsHelper(drag()->mimeData());
for (int i = 0; i < fmts.size(); ++i) {
- QList<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
+ QVector<xcb_atom_t> atoms = QXcbMime::mimeAtomsForFormat(connection(), fmts.at(i));
for (int j = 0; j < atoms.size(); ++j) {
if (!drag_types.contains(atoms.at(j)))
drag_types.append(atoms.at(j));
@@ -1211,7 +1211,7 @@ QVariant QXcbDropData::xdndObtainData(const QByteArray &format, QVariant::Type r
return result;
}
- QList<xcb_atom_t> atoms = drag->xdnd_types;
+ QVector<xcb_atom_t> atoms = drag->xdnd_types;
QByteArray encoding;
xcb_atom_t a = mimeAtomForFormat(c, QLatin1String(format), requestedType, atoms, &encoding);
if (a == XCB_NONE)
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index d94c42696f..7b0d337e7c 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -46,7 +46,6 @@
#include <private/qsimpledrag_p.h>
#include <qxcbobject.h>
#include <xcb/xcb.h>
-#include <qlist.h>
#include <qpoint.h>
#include <qrect.h>
#include <qsharedpointer.h>
@@ -127,7 +126,7 @@ private:
// the types in this drop. 100 is no good, but at least it's big.
enum { xdnd_max_type = 100 };
- QList<xcb_atom_t> xdnd_types;
+ QVector<xcb_atom_t> xdnd_types;
// timestamp from XdndPosition and XdndDroptime for retrieving the data
xcb_timestamp_t target_time;
@@ -160,7 +159,7 @@ private:
QPointer<QDrag> drag;
QTime time;
};
- QList<Transaction> transactions;
+ QVector<Transaction> transactions;
int transaction_expiry_timer;
void restartDropExpiryTimer();
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 0bab341914..2d4c523a4b 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -233,7 +233,10 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont
{
QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
#if defined(XCB_USE_GLX)
- return new QGLXContext(screen, context->format(), context->shareHandle());
+ QGLXContext *platformContext = new QGLXContext(screen, context->format(),
+ context->shareHandle(), context->nativeHandle());
+ context->setNativeHandle(platformContext->nativeHandle());
+ return platformContext;
#elif defined(XCB_USE_EGL)
return new QEGLXcbPlatformContext(context->format(), context->shareHandle(),
screen->connection()->egl_display(), screen->connection());
diff --git a/src/plugins/platforms/xcb/qxcbmime.cpp b/src/plugins/platforms/xcb/qxcbmime.cpp
index b205a63267..c0f6745e7f 100644
--- a/src/plugins/platforms/xcb/qxcbmime.cpp
+++ b/src/plugins/platforms/xcb/qxcbmime.cpp
@@ -136,9 +136,10 @@ bool QXcbMime::mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeDa
return ret;
}
-QList<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const QString &format)
+QVector<xcb_atom_t> QXcbMime::mimeAtomsForFormat(QXcbConnection *connection, const QString &format)
{
- QList<xcb_atom_t> atoms;
+ QVector<xcb_atom_t> atoms;
+ atoms.reserve(7);
atoms.append(connection->internAtom(format.toLatin1()));
// special cases for strings
@@ -240,7 +241,7 @@ QVariant QXcbMime::mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a,
}
xcb_atom_t QXcbMime::mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
- const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding)
+ const QVector<xcb_atom_t> &atoms, QByteArray *requestedEncoding)
{
requestedEncoding->clear();
diff --git a/src/plugins/platforms/xcb/qxcbmime.h b/src/plugins/platforms/xcb/qxcbmime.h
index 4a69a35ced..563716a75b 100644
--- a/src/plugins/platforms/xcb/qxcbmime.h
+++ b/src/plugins/platforms/xcb/qxcbmime.h
@@ -59,14 +59,14 @@ public:
QXcbMime();
~QXcbMime();
- static QList<xcb_atom_t> mimeAtomsForFormat(QXcbConnection *connection, const QString &format);
+ static QVector<xcb_atom_t> mimeAtomsForFormat(QXcbConnection *connection, const QString &format);
static QString mimeAtomToString(QXcbConnection *connection, xcb_atom_t a);
static bool mimeDataForAtom(QXcbConnection *connection, xcb_atom_t a, QMimeData *mimeData, QByteArray *data,
xcb_atom_t *atomFormat, int *dataFormat);
static QVariant mimeConvertToFormat(QXcbConnection *connection, xcb_atom_t a, const QByteArray &data, const QString &format,
QVariant::Type requestedType, const QByteArray &encoding);
static xcb_atom_t mimeAtomForFormat(QXcbConnection *connection, const QString &format, QVariant::Type requestedType,
- const QList<xcb_atom_t> &atoms, QByteArray *requestedEncoding);
+ const QVector<xcb_atom_t> &atoms, QByteArray *requestedEncoding);
};
#endif // !(defined(QT_NO_DRAGANDDROP) && defined(QT_NO_CLIPBOARD))
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index b45bd6a82e..37936a9c72 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -225,6 +225,14 @@ void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceStr
return result;
}
+QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource)
+{
+ QByteArray lowerCaseResource = resource.toLower();
+ if (lowerCaseResource == "setstartupid")
+ return NativeResourceForIntegrationFunction(setStartupId);
+ return 0;
+}
+
QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::nativeResourceFunctionForScreen(const QByteArray &resource)
{
const QByteArray lowerCaseResource = resource.toLower();
@@ -287,6 +295,15 @@ void QXcbNativeInterface::setAppUserTime(QScreen* screen, xcb_timestamp_t time)
static_cast<QXcbScreen *>(screen->handle())->connection()->setNetWmUserTime(time);
}
+void QXcbNativeInterface::setStartupId(const char *data)
+{
+ QByteArray startupId(data);
+ QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration());
+ QXcbConnection *defaultConnection = integration->defaultConnection();
+ if (defaultConnection)
+ defaultConnection->setStartupId(startupId);
+}
+
QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource)
{
QByteArray lowerCaseResource = resource.toLower();
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h
index fb1a46014c..cf26aff011 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.h
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h
@@ -77,11 +77,12 @@ public:
QXcbNativeInterface();
void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
- void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context);
- void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen);
- void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window);
+ void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) Q_DECL_OVERRIDE;
+ void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) Q_DECL_OVERRIDE;
+ void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE;
- NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource);
+ NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE;
+ NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE;
NativeResourceForScreenFunction nativeResourceFunctionForScreen(const QByteArray &resource) Q_DECL_OVERRIDE;
inline const QByteArray &genericEventFilterType() const { return m_genericEventFilterType; }
@@ -96,6 +97,7 @@ public:
void *startupId();
void *x11Screen();
void *rootWindow();
+ static void setStartupId(const char *);
static void setAppTime(QScreen *screen, xcb_timestamp_t time);
static void setAppUserTime(QScreen *screen, xcb_timestamp_t time);
static void *eglContextForContext(QOpenGLContext *context);
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
index 141a6cc0cb..17b40a45e1 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.cpp
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
@@ -42,6 +42,7 @@
#include "qxcbxsettings.h"
#include <QtCore/QByteArray>
+#include <QtCore/QtEndian>
#include <X11/extensions/XIproto.h>
@@ -149,47 +150,67 @@ public:
{
if (xSettings.length() < 12)
return;
- // we ignore byteorder for now
- char byteOrder = xSettings.at(1);
- Q_UNUSED(byteOrder);
- uint number_of_settings = *reinterpret_cast<const uint *>(xSettings.mid(8,4).constData());
+ char byteOrder = xSettings.at(0);
+ if (byteOrder != LSBFirst && byteOrder != MSBFirst) {
+ qWarning("%s ByteOrder byte %d not 0 or 1", Q_FUNC_INFO , byteOrder);
+ return;
+ }
+
+#define ADJUST_BO(b, t, x) \
+ ((b == LSBFirst) ? \
+ qFromLittleEndian<t>((const uchar *)(x)) : \
+ qFromBigEndian<t>((const uchar *)(x)))
+#define VALIDATE_LENGTH(x) \
+ if ((size_t)xSettings.length() < (offset + local_offset + 12 + x)) { \
+ qWarning("%s Length %d runs past end of data", Q_FUNC_INFO , x); \
+ return; \
+ }
+ uint number_of_settings = ADJUST_BO(byteOrder, quint32, xSettings.mid(8,4).constData());
const char *data = xSettings.constData() + 12;
size_t offset = 0;
for (uint i = 0; i < number_of_settings; i++) {
int local_offset = 0;
+ VALIDATE_LENGTH(2);
XSettingsType type = static_cast<XSettingsType>(*reinterpret_cast<const quint8 *>(data + offset));
local_offset += 2;
- quint16 name_len = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ VALIDATE_LENGTH(2);
+ quint16 name_len = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
+ VALIDATE_LENGTH(name_len);
QByteArray name(data + offset + local_offset, name_len);
local_offset += round_to_nearest_multiple_of_4(name_len);
- int last_change_serial = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int last_change_serial = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
Q_UNUSED(last_change_serial);
local_offset += 4;
QVariant value;
if (type == XSettingsTypeString) {
- int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
local_offset+=4;
+ VALIDATE_LENGTH(value_length);
QByteArray value_string(data + offset + local_offset, value_length);
value.setValue(value_string);
local_offset += round_to_nearest_multiple_of_4(value_length);
} else if (type == XSettingsTypeInteger) {
- int value_length = *reinterpret_cast<const int *>(data + offset + local_offset);
+ VALIDATE_LENGTH(4);
+ int value_length = ADJUST_BO(byteOrder, qint32, data + offset + local_offset);
local_offset += 4;
value.setValue(value_length);
} else if (type == XSettingsTypeColor) {
- quint16 red = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ VALIDATE_LENGTH(2*4);
+ quint16 red = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 green = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 green = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 blue = *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 blue = ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
- quint16 alpha= *reinterpret_cast<const quint16 *>(data + offset + local_offset);
+ quint16 alpha= ADJUST_BO(byteOrder, quint16, data + offset + local_offset);
local_offset += 2;
QColor color_value(red,green,blue,alpha);
value.setValue(color_value);