summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@theqtcompany.com>2015-03-18 15:23:56 +0000
committerThe Qt Project <gerrit-noreply@qt-project.org>2015-03-18 22:27:24 +0000
commitdcf0ececbf167502ac9943c6435bb9ddeeb29d5e (patch)
tree19416d427b84f0a90e0d3028588404a544003734 /src/plugins
parent7aad6b9fd426e05fdfb3892d60432a45e4079887 (diff)
parent198606f6dbca95ba3a170fff387327d8271018cd (diff)
Merge "Merge remote-tracking branch 'origin/5.5' into dev" into refs/staging/dev
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp2
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm12
-rw-r--r--src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm15
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm24
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm5
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm26
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm45
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp21
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp18
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h2
-rw-r--r--src/plugins/platforms/eglfs/eglfs_device_lib.pro2
-rw-r--r--src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp5
-rw-r--r--src/plugins/platforms/eglfs/qeglfsdeviceintegration.h1
-rw-r--r--src/plugins/platforms/eglfs/qeglfsintegration.cpp2
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.cpp5
-rw-r--r--src/plugins/platforms/eglfs/qeglfsscreen.h2
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.h2
-rw-r--r--src/plugins/platforms/ios/qioseventdispatcher.mm20
-rw-r--r--src/plugins/platforms/ios/qiosfiledialog.mm6
-rw-r--r--src/plugins/platforms/ios/qiosfileengineassetslibrary.mm24
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm33
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h10
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm26
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm2
-rw-r--r--src/plugins/platforms/windows/openglblacklists.qrc5
-rw-r--r--src/plugins/platforms/windows/openglblacklists/default.json18
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp33
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp206
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.h6
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsopenglcontext.h2
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp72
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.h3
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h2
-rw-r--r--src/plugins/platforms/windows/windows.pri64
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp296
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h13
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp56
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp131
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h21
-rw-r--r--src/plugins/platforms/xcb/qxcbsessionmanager.cpp2
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp2
55 files changed, 861 insertions, 436 deletions
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index 6e5b81ed36..ab03bfeb04 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -524,7 +524,7 @@ QImage ICOReader::iconAt(int index)
iod->seek(iconEntry.dwImageOffset);
- const QByteArray pngMagic = QByteArray::fromRawData((char*)pngMagicData, sizeof(pngMagicData));
+ const QByteArray pngMagic = QByteArray::fromRawData((const char*)pngMagicData, sizeof(pngMagicData));
const bool isPngImage = (iod->read(pngMagic.size()) == pngMagic);
if (isPngImage) {
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
index ad226989a0..49fa32004e 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
@@ -97,7 +97,7 @@ bool QComposeInputContext::filterEvent(const QEvent *event)
if ((m_tableState & TableGenerator::NoErrors) != TableGenerator::NoErrors)
return false;
- QKeyEvent *keyEvent = (QKeyEvent *)event;
+ const QKeyEvent *keyEvent = (const QKeyEvent *)event;
// should pass only the key presses
if (keyEvent->type() != QEvent::KeyPress) {
return false;
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index d012ede5f9..3737584c4c 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -54,6 +54,7 @@ public:
QImage toImage() const;
void resize (const QSize &size, const QRegion &);
bool scroll(const QRegion &area, int dx, int dy);
+ void beginPaint(const QRegion &region);
qreal getBackingStoreDevicePixelRatio();
private:
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index cddb960197..6a4f7ed8ee 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -96,6 +96,18 @@ bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy)
return true;
}
+void QCocoaBackingStore::beginPaint(const QRegion &region)
+{
+ if (m_qImage.hasAlphaChannel()) {
+ QPainter p(&m_qImage);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ const QVector<QRect> rects = region.rects();
+ const QColor blank = Qt::transparent;
+ for (QVector<QRect>::const_iterator it = rects.begin(), end = rects.end(); it != end; ++it)
+ p.fillRect(*it, blank);
+ }
+}
+
qreal QCocoaBackingStore::getBackingStoreDevicePixelRatio()
{
return m_qImage.devicePixelRatio();
diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
index 933034bb6f..d1802fe4f9 100644
--- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm
@@ -84,20 +84,13 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont)
QFont newFont;
if (cocoaFont) {
int pSize = qRound([cocoaFont pointSize]);
- QString family(QCFString::toQString([cocoaFont familyName]));
- QString typeface(QCFString::toQString([cocoaFont fontName]));
-
- int hyphenPos = typeface.indexOf(QLatin1Char('-'));
- if (hyphenPos != -1) {
- typeface.remove(0, hyphenPos + 1);
- } else {
- typeface = QLatin1String("Normal");
- }
+ QCFType<CTFontDescriptorRef> font(CTFontCopyFontDescriptor((CTFontRef)cocoaFont));
+ QString family(QCFString((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontFamilyNameAttribute)));
+ QString style(QCFString(((CFStringRef)CTFontDescriptorCopyAttribute(font, kCTFontStyleNameAttribute))));
- newFont = QFontDatabase().font(family, typeface, pSize);
+ newFont = QFontDatabase().font(family, style, pSize);
newFont.setUnderline(resolveFont.underline());
newFont.setStrikeOut(resolveFont.strikeOut());
-
}
return newFont;
}
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index 3b79717472..dc9140d990 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -133,6 +133,11 @@ public:
void setToolbar(QWindow *window, NSToolbar *toolbar);
NSToolbar *toolbar(QWindow *window) const;
void clearToolbars();
+
+ void pushPopupWindow(QCocoaWindow *window);
+ QCocoaWindow *popPopupWindow();
+ QCocoaWindow *activePopupWindow() const;
+ QList<QCocoaWindow *> *popupWindowStack();
private:
static QCocoaIntegration *mInstance;
@@ -151,6 +156,7 @@ private:
QScopedPointer<QCocoaKeyMapper> mKeyboardMapper;
QHash<QWindow *, NSToolbar *> mToolbars;
+ QList<QCocoaWindow *> m_popupWindowStack;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index 881b23cd6f..aa33cfd8bc 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -545,4 +545,28 @@ void QCocoaIntegration::clearToolbars()
mToolbars.clear();
}
+void QCocoaIntegration::pushPopupWindow(QCocoaWindow *window)
+{
+ m_popupWindowStack.append(window);
+}
+
+QCocoaWindow *QCocoaIntegration::popPopupWindow()
+{
+ if (m_popupWindowStack.isEmpty())
+ return 0;
+ return m_popupWindowStack.takeLast();
+}
+
+QCocoaWindow *QCocoaIntegration::activePopupWindow() const
+{
+ if (m_popupWindowStack.isEmpty())
+ return 0;
+ return m_popupWindowStack.front();
+}
+
+QList<QCocoaWindow *> *QCocoaIntegration::popupWindowStack()
+{
+ return &m_popupWindowStack;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h
index ad8821ca97..59807deb5a 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.h
+++ b/src/plugins/platforms/cocoa/qcocoamenu.h
@@ -58,6 +58,7 @@ public:
void removeMenuItem(QPlatformMenuItem *menuItem);
void syncMenuItem(QPlatformMenuItem *menuItem);
void setEnabled(bool enabled);
+ bool isEnabled() const;
void setVisible(bool visible);
void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item);
void dismiss();
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index fb11efb689..4fadc2f60a 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -426,6 +426,11 @@ void QCocoaMenu::setEnabled(bool enabled)
syncModalState(!m_enabled);
}
+bool QCocoaMenu::isEnabled() const
+{
+ return [m_nativeItem isEnabled];
+}
+
void QCocoaMenu::setVisible(bool visible)
{
[m_nativeItem setSubmenu:(visible ? m_nativeMenu : nil)];
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index e4794f8674..c87a871ad0 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -262,7 +262,6 @@ public: // for QNSView
bool m_effectivelyMaximized;
Qt::WindowState m_synchedWindowState;
Qt::WindowModality m_windowModality;
- QPointer<QWindow> m_activePopupWindow;
QPointer<QWindow> m_enterLeaveTargetWindow;
bool m_windowUnderMouse;
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index b9a09d03b5..8aed9da9c5 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -455,6 +455,10 @@ QCocoaWindow::~QCocoaWindow()
[m_qtView clearQWindowPointers];
}
+ // While it is unlikely that this window will be in the popup stack
+ // during deletetion we clear any pointers here to make sure.
+ QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
+
foreach (QCocoaWindow *child, m_childWindows) {
[m_nsWindow removeChildWindow:child->m_nsWindow];
child->m_parentCocoaWindow = 0;
@@ -647,17 +651,17 @@ void QCocoaWindow::setVisible(bool visible)
// We need to recreate if the modality has changed as the style mask will need updating
if (m_windowModality != window()->modality())
recreateWindow(parent());
+
+ // Register popup windows. The Cocoa platform plugin will forward mouse events
+ // to them and close them when needed.
+ if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip)
+ QCocoaIntegration::instance()->pushPopupWindow(this);
+
if (parentCocoaWindow) {
// The parent window might have moved while this window was hidden,
// update the window geometry if there is a parent.
setGeometry(window()->geometry());
- // Register popup windows so that the parent window can close them when needed.
- if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip) {
- // qDebug() << "transientParent and popup" << window()->type() << Qt::Popup << (window()->type() & Qt::Popup);
- parentCocoaWindow->m_activePopupWindow = window();
- }
-
if (window()->type() == Qt::Popup) {
// QTBUG-30266: a window should not be resizable while a transient popup is open
// Since this isn't a native popup, the window manager doesn't close the popup when you click outside
@@ -759,8 +763,11 @@ void QCocoaWindow::setVisible(bool visible)
[NSEvent removeMonitor:monitor];
monitor = nil;
}
+
+ if (window()->type() == Qt::Popup)
+ QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
+
if (parentCocoaWindow && window()->type() == Qt::Popup) {
- parentCocoaWindow->m_activePopupWindow = 0;
if (m_resizableTransientParent
&& !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask))
// QTBUG-30266: a window should not be resizable while a transient popup is open
@@ -1177,10 +1184,9 @@ void QCocoaWindow::setEmbeddedInForeignView(bool embedded)
void QCocoaWindow::windowWillMove()
{
// Close any open popups on window move
- if (m_activePopupWindow) {
- QWindowSystemInterface::handleCloseEvent(m_activePopupWindow);
+ while (QCocoaWindow *popup = QCocoaIntegration::instance()->popPopupWindow()) {
+ QWindowSystemInterface::handleCloseEvent(popup->window());
QWindowSystemInterface::flushWindowSystemEvents();
- m_activePopupWindow = 0;
}
}
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 39bd5d486c..1c87b90450 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -699,6 +699,10 @@ QT_WARNING_POP
m_platformWindow->m_forwardWindow = 0;
}
+ // Popups implicitly grap mouse events; forward to the active popup if there is one
+ if (QCocoaWindow *popup = QCocoaIntegration::instance()->activePopupWindow())
+ targetView = popup->contentView();
+
[targetView convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint];
ulong timestamp = [theEvent timestamp] * 1000;
@@ -766,16 +770,39 @@ QT_WARNING_POP
if (m_window->flags() & Qt::WindowTransparentForInput)
return [super mouseDown:theEvent];
m_sendUpAsRightButton = false;
- if (m_platformWindow->m_activePopupWindow) {
- Qt::WindowType type = m_platformWindow->m_activePopupWindow->type();
- QWindowSystemInterface::handleCloseEvent(m_platformWindow->m_activePopupWindow);
- QWindowSystemInterface::flushWindowSystemEvents();
- m_platformWindow->m_activePopupWindow = 0;
- // Consume the mouse event when closing the popup, except for tool tips
- // were it's expected that the event is processed normally.
- if (type != Qt::ToolTip)
- return;
+
+ // Handle any active poup windows; clicking outisde them should close them
+ // all. Don't do anything or clicks inside one of the menus, let Cocoa
+ // handle that case. Note that in practice many windows of the Qt::Popup type
+ // will actually close themselves in this case using logic implemented in
+ // that particular poup type (for example context menus). However, Qt expects
+ // that plain popup QWindows will also be closed, so we implement the logic
+ // here as well.
+ QList<QCocoaWindow *> *popups = QCocoaIntegration::instance()->popupWindowStack();
+ if (!popups->isEmpty()) {
+ // Check if the click is outside all popups.
+ bool inside = false;
+ QPointF qtScreenPoint = qt_mac_flipPoint([self screenMousePoint:theEvent]);
+ for (QList<QCocoaWindow *>::const_iterator it = popups->begin(); it != popups->end(); ++it) {
+ if ((*it)->geometry().contains(qtScreenPoint.toPoint())) {
+ inside = true;
+ break;
+ }
+ }
+ // Close the popups if the click was outside.
+ if (!inside) {
+ Qt::WindowType type = QCocoaIntegration::instance()->activePopupWindow()->window()->type();
+ while (QCocoaWindow *popup = QCocoaIntegration::instance()->popPopupWindow()) {
+ QWindowSystemInterface::handleCloseEvent(popup->window());
+ QWindowSystemInterface::flushWindowSystemEvents();
+ }
+ // Consume the mouse event when closing the popup, except for tool tips
+ // were it's expected that the event is processed normally.
+ if (type != Qt::ToolTip)
+ return;
+ }
}
+
if ([self hasMarkedText]) {
NSInputManager* inputManager = [NSInputManager currentInputManager];
if ([inputManager wantsToHandleMouseEvents]) {
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp
index 30fcf8143f..bafe1e3324 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp
@@ -96,19 +96,19 @@ static const char * const connector_type_names[] = {
"eDP",
};
-static QString nameForConnector(const drmModeConnectorPtr connector)
+static QByteArray nameForConnector(const drmModeConnectorPtr connector)
{
- QString connectorName = "UNKNOWN";
+ QByteArray connectorName("UNKNOWN");
if (connector->connector_type < ARRAY_LENGTH(connector_type_names))
connectorName = connector_type_names[connector->connector_type];
- connectorName += QString::number(connector->connector_type_id);
+ connectorName += QByteArray::number(connector->connector_type_id);
return connectorName;
}
-static bool parseModeline(const QString &s, drmModeModeInfoPtr mode)
+static bool parseModeline(const QByteArray &text, drmModeModeInfoPtr mode)
{
char hsync[16];
char vsync[16];
@@ -120,7 +120,7 @@ static bool parseModeline(const QString &s, drmModeModeInfoPtr mode)
mode->vrefresh = 0;
mode->flags = 0;
- if (sscanf(qPrintable(s), "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
+ if (sscanf(text.constData(), "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s",
&fclock,
&mode->hdisplay,
&mode->hsync_start,
@@ -153,7 +153,7 @@ static bool parseModeline(const QString &s, drmModeModeInfoPtr mode)
QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos)
{
- const QString connectorName = nameForConnector(connector);
+ const QByteArray connectorName = nameForConnector(connector);
const int crtc = crtcForConnector(resources, connector);
if (crtc < 0) {
@@ -165,19 +165,20 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr
QSize configurationSize;
drmModeModeInfo configurationModeline;
- const QString mode = m_integration->outputSettings().value(connectorName).value("mode", "preferred").toString().toLower();
+ const QByteArray mode = m_integration->outputSettings().value(QString::fromUtf8(connectorName))
+ .value(QStringLiteral("mode"), QStringLiteral("preferred")).toByteArray().toLower();
if (mode == "off") {
configuration = OutputConfigOff;
} else if (mode == "preferred") {
configuration = OutputConfigPreferred;
} else if (mode == "current") {
configuration = OutputConfigCurrent;
- } else if (sscanf(qPrintable(mode), "%dx%d", &configurationSize.rwidth(), &configurationSize.rheight()) == 2) {
+ } else if (sscanf(mode.constData(), "%dx%d", &configurationSize.rwidth(), &configurationSize.rheight()) == 2) {
configuration = OutputConfigMode;
} else if (parseModeline(mode, &configurationModeline)) {
configuration = OutputConfigModeline;
} else {
- qWarning("Invalid mode \"%s\" for output %s", qPrintable(mode), qPrintable(connectorName));
+ qWarning("Invalid mode \"%s\" for output %s", mode.constData(), connectorName.constData());
configuration = OutputConfigPreferred;
}
@@ -273,7 +274,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr
}
QEglFSKmsOutput output = {
- connectorName,
+ QString::fromUtf8(connectorName),
connector->connector_id,
crtc_id,
QSizeF(connector->mmWidth, connector->mmHeight),
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp
index 4598f21d92..7bb932cf00 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp
@@ -223,25 +223,25 @@ void QEglFSKmsIntegration::loadConfig()
return;
}
- QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
+ const QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
if (!doc.isObject()) {
qCDebug(qLcEglfsKmsDebug) << "Invalid config file" << json
<< "- no top-level JSON object";
return;
}
- QJsonObject object = doc.object();
+ const QJsonObject object = doc.object();
- m_hwCursor = object.value("hwcursor").toBool(m_hwCursor);
- m_pbuffers = object.value("pbuffers").toBool(m_pbuffers);
- m_devicePath = object.value("device").toString();
+ m_hwCursor = object.value(QStringLiteral("hwcursor")).toBool(m_hwCursor);
+ m_pbuffers = object.value(QStringLiteral("pbuffers")).toBool(m_pbuffers);
+ m_devicePath = object.value(QStringLiteral("device")).toString();
- QJsonArray outputs = object.value("outputs").toArray();
+ const QJsonArray outputs = object.value(QStringLiteral("outputs")).toArray();
for (int i = 0; i < outputs.size(); i++) {
- QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap();
+ const QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap();
- if (outputSettings.contains("name")) {
- QString name = outputSettings.value("name").toString();
+ if (outputSettings.contains(QStringLiteral("name"))) {
+ const QString name = outputSettings.value(QStringLiteral("name")).toString();
if (m_outputSettings.contains(name)) {
qCDebug(qLcEglfsKmsDebug) << "Output" << name << "configured multiple times!";
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp
index a36ce50b76..a27819d1dd 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp
@@ -303,4 +303,10 @@ void QEglFSKmsScreen::restoreMode()
}
}
+qreal QEglFSKmsScreen::refreshRate() const
+{
+ quint32 refresh = m_output.modes[m_output.mode].vrefresh;
+ return refresh > 0 ? refresh : 60;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h
index ed79d00896..16521c7fe0 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h
@@ -83,6 +83,8 @@ public:
QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
+ qreal refreshRate() const Q_DECL_OVERRIDE;
+
QEglFSKmsDevice *device() const { return m_device; }
gbm_surface *surface() const { return m_gbm_surface; }
diff --git a/src/plugins/platforms/eglfs/eglfs_device_lib.pro b/src/plugins/platforms/eglfs/eglfs_device_lib.pro
index d8ce421a69..729290706d 100644
--- a/src/plugins/platforms/eglfs/eglfs_device_lib.pro
+++ b/src/plugins/platforms/eglfs/eglfs_device_lib.pro
@@ -56,4 +56,4 @@ INCLUDEPATH += $$PWD
CONFIG += egl qpa/genericunixfontdatabase
-RESOURCES += $$PWD/cursor.qrc
+!contains(DEFINES, QT_NO_CURSOR): RESOURCES += $$PWD/cursor.qrc
diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp
index 7d1007e7ef..2a46c87862 100644
--- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp
@@ -225,6 +225,11 @@ QImage::Format QEGLDeviceIntegration::screenFormat() const
return screenDepth() == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
}
+qreal QEGLDeviceIntegration::refreshRate() const
+{
+ return q_refreshRateFromFb(framebuffer);
+}
+
QSurfaceFormat QEGLDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const
{
QSurfaceFormat format = inputFormat;
diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h
index 019312e755..260fc313f7 100644
--- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h
+++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h
@@ -77,6 +77,7 @@ public:
virtual Qt::ScreenOrientation orientation() const;
virtual int screenDepth() const;
virtual QImage::Format screenFormat() const;
+ virtual qreal refreshRate() const;
virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const;
virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow,
const QSize &size,
diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
index 2da47db602..d1688df8f5 100644
--- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp
@@ -56,7 +56,9 @@
static void initResources()
{
+#ifndef QT_NO_CURSOR
Q_INIT_RESOURCE(cursor);
+#endif
}
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
index cc2ee80bd3..1b6e2307f8 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp
@@ -93,6 +93,11 @@ QPlatformCursor *QEglFSScreen::cursor() const
return m_cursor;
}
+qreal QEglFSScreen::refreshRate() const
+{
+ return qt_egl_device_integration()->refreshRate();
+}
+
void QEglFSScreen::setPrimarySurface(EGLSurface surface)
{
m_surface = surface;
diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h
index 14ec9682a6..07b6ff63ef 100644
--- a/src/plugins/platforms/eglfs/qeglfsscreen.h
+++ b/src/plugins/platforms/eglfs/qeglfsscreen.h
@@ -60,6 +60,8 @@ public:
QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
+ qreal refreshRate() const Q_DECL_OVERRIDE;
+
EGLSurface primarySurface() const { return m_surface; }
protected:
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.h b/src/plugins/platforms/ios/qioseventdispatcher.h
index 3a6b67f72e..fdaa7e68fe 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.h
+++ b/src/plugins/platforms/ios/qioseventdispatcher.h
@@ -52,7 +52,7 @@ public:
void interruptEventLoopExec();
private:
- uint m_processEventCallsAfterExec;
+ uint m_processEventLevel;
RunLoopObserver<QIOSEventDispatcher> m_runLoopExitObserver;
};
diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm
index f4567f36f4..fc12e83a81 100644
--- a/src/plugins/platforms/ios/qioseventdispatcher.mm
+++ b/src/plugins/platforms/ios/qioseventdispatcher.mm
@@ -422,7 +422,7 @@ QT_USE_NAMESPACE
QIOSEventDispatcher::QIOSEventDispatcher(QObject *parent)
: QEventDispatcherCoreFoundation(parent)
- , m_processEventCallsAfterExec(0)
+ , m_processEventLevel(0)
, m_runLoopExitObserver(this, &QIOSEventDispatcher::handleRunLoopExit, kCFRunLoopExit)
{
}
@@ -439,8 +439,8 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
return false;
}
- if (!m_processEventCallsAfterExec && (flags & QEventLoop::EventLoopExec)) {
- ++m_processEventCallsAfterExec;
+ if (!m_processEventLevel && (flags & QEventLoop::EventLoopExec)) {
+ ++m_processEventLevel;
m_runLoopExitObserver.addToMode(kCFRunLoopCommonModes);
@@ -465,13 +465,9 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo
Q_UNREACHABLE();
}
- if (m_processEventCallsAfterExec)
- ++m_processEventCallsAfterExec;
-
+ ++m_processEventLevel;
bool processedEvents = QEventDispatcherCoreFoundation::processEvents(flags);
-
- if (m_processEventCallsAfterExec)
- --m_processEventCallsAfterExec;
+ --m_processEventLevel;
return processedEvents;
}
@@ -481,7 +477,7 @@ void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity)
Q_UNUSED(activity);
Q_ASSERT(activity == kCFRunLoopExit);
- if (m_processEventCallsAfterExec == 1 && !QThreadData::current()->eventLoops.top()->isRunning()) {
+ if (m_processEventLevel == 1 && !QThreadData::current()->eventLoops.top()->isRunning()) {
qEventDispatcherDebug() << "Root runloop level exited";
interruptEventLoopExec();
}
@@ -489,9 +485,9 @@ void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity)
void QIOSEventDispatcher::interruptEventLoopExec()
{
- Q_ASSERT(m_processEventCallsAfterExec == 1);
+ Q_ASSERT(m_processEventLevel == 1);
- --m_processEventCallsAfterExec;
+ --m_processEventLevel;
m_runLoopExitObserver.removeFromMode(kCFRunLoopCommonModes);
diff --git a/src/plugins/platforms/ios/qiosfiledialog.mm b/src/plugins/platforms/ios/qiosfiledialog.mm
index 1d4298a158..0e12da9d57 100644
--- a/src/plugins/platforms/ios/qiosfiledialog.mm
+++ b/src/plugins/platforms/ios/qiosfiledialog.mm
@@ -60,7 +60,8 @@
{
Q_UNUSED(picker);
NSURL *url = [info objectForKey:UIImagePickerControllerReferenceURL];
- m_fileDialog->selectedFilesChanged(QList<QUrl>() << QUrl::fromNSURL(url));
+ QUrl fileUrl = QUrl::fromLocalFile(QString::fromNSString([url description]));
+ m_fileDialog->selectedFilesChanged(QList<QUrl>() << fileUrl);
emit m_fileDialog->accept();
}
@@ -94,7 +95,8 @@ bool QIOSFileDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality window
Q_UNUSED(windowFlags);
Q_UNUSED(windowModality);
- if (options()->initialDirectory().scheme() == QLatin1String("assets-library")) {
+ QString directory = options()->initialDirectory().toLocalFile();
+ if (directory.startsWith(QLatin1String("assets-library:"))) {
m_viewController = [[QIOSImagePickerController alloc] initWithQIOSFileDialog:this];
UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window
: [UIApplication sharedApplication].keyWindow;
diff --git a/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm b/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm
index c4be7cf4dc..73bfc2a87f 100644
--- a/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm
+++ b/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm
@@ -42,9 +42,9 @@
class QIOSAssetData : public QObject
{
public:
- QIOSAssetData(const QString &fileName, QIOSFileEngineAssetsLibrary *engine)
+ QIOSAssetData(const QString &assetUrl, QIOSFileEngineAssetsLibrary *engine)
: m_asset(0)
- , m_fileName(fileName)
+ , m_assetUrl(assetUrl)
, m_assetLibrary(0)
{
switch ([ALAssetsLibrary authorizationStatus]) {
@@ -71,7 +71,7 @@ public:
// reuse its data. Since QFile is (mostly) reentrant, we need to protect m_currentAssetData
// from being modified by several threads at the same time.
QMutexLocker lock(&g_mutex);
- if (g_currentAssetData && g_currentAssetData->m_fileName == fileName) {
+ if (g_currentAssetData && g_currentAssetData->m_assetUrl == assetUrl) {
m_assetLibrary = [g_currentAssetData->m_assetLibrary retain];
m_asset = [g_currentAssetData->m_asset retain];
return;
@@ -87,7 +87,7 @@ public:
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
- NSURL *url = [NSURL URLWithString:m_fileName.toNSString()];
+ NSURL *url = [NSURL URLWithString:assetUrl.toNSString()];
m_assetLibrary = [[ALAssetsLibrary alloc] init];
[m_assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) {
m_asset = [asset retain];
@@ -117,7 +117,7 @@ public:
ALAsset *m_asset;
private:
- QString m_fileName;
+ QString m_assetUrl;
ALAssetsLibrary *m_assetLibrary;
static QBasicMutex g_mutex;
@@ -143,8 +143,18 @@ QIOSFileEngineAssetsLibrary::~QIOSFileEngineAssetsLibrary()
ALAsset *QIOSFileEngineAssetsLibrary::loadAsset() const
{
- if (!m_data)
- m_data = new QIOSAssetData(m_fileName, const_cast<QIOSFileEngineAssetsLibrary *>(this));
+ if (!m_data) {
+ // QUrl::fromLocalFile() will remove double slashes. Since the asset url is passed around as a file
+ // name in the app (and converted to/from a file url, e.g in QFileDialog), we need to check if we still
+ // have two leading slashes after the scheme, and restore the second slash if not.
+ QString assetUrl = m_fileName;
+ const int index = 16; // "assets-library://"
+ if (assetUrl[index] != QLatin1Char('/'))
+ assetUrl.insert(index, '/');
+
+ m_data = new QIOSAssetData(assetUrl, const_cast<QIOSFileEngineAssetsLibrary *>(this));
+ }
+
return m_data->m_asset;
}
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 22847b0612..a558ebe1f7 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -587,28 +587,27 @@ void QIOSInputContext::update(Qt::InputMethodQueries updatedProperties)
qImDebug() << "fw =" << qApp->focusWindow() << "fo =" << qApp->focusObject();
Qt::InputMethodQueries changedProperties = m_imeState.update(updatedProperties);
- if (changedProperties & (Qt::ImEnabled | Qt::ImHints | Qt::ImPlatformData)) {
- // Changes to enablement or hints require virtual keyboard reconfigure
-
- qImDebug() << "changed IM properties" << changedProperties << "require keyboard reconfigure";
+ if (m_textResponder && changedProperties & (Qt::ImHints | Qt::ImPlatformData)) {
+ qImDebug() << "current IM state requires new text responder";
+ [m_textResponder autorelease];
+ m_textResponder = 0;
+ }
- if (inputMethodAccepted()) {
- qImDebug() << "replacing text responder with new text responder";
- [m_textResponder autorelease];
+ if (inputMethodAccepted()) {
+ if (!m_textResponder) {
+ qImDebug() << "creating new text responder";
m_textResponder = [[QIOSTextInputResponder alloc] initWithInputContext:this];
- [m_textResponder becomeFirstResponder];
- } else if ([UIResponder currentFirstResponder] == m_textResponder) {
- qImDebug() << "IM not enabled, resigning text responder as first responder";
- [m_textResponder resignFirstResponder];
- } else {
- qImDebug() << "IM not enabled. Text responder not first responder. Nothing to do";
}
- } else {
+ if (![m_textResponder isFirstResponder])
+ [m_textResponder becomeFirstResponder];
+
[m_textResponder notifyInputDelegate:changedProperties];
- }
- if (changedProperties & Qt::ImCursorRectangle)
- scrollToCursor();
+ if (changedProperties & Qt::ImCursorRectangle)
+ scrollToCursor();
+ } else if ([m_textResponder isFirstResponder]) {
+ [m_textResponder resignFirstResponder];
+ }
}
bool QIOSInputContext::inputMethodAccepted() const
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index 8a27342d2f..c22c43e455 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -45,8 +45,10 @@ QT_BEGIN_NAMESPACE
class QIOSServices;
-class QIOSIntegration : public QPlatformIntegration, public QPlatformNativeInterface
+class QIOSIntegration : public QPlatformNativeInterface, public QPlatformIntegration
{
+ Q_OBJECT
+
public:
QIOSIntegration();
~QIOSIntegration();
@@ -72,8 +74,6 @@ public:
QAbstractEventDispatcher *createEventDispatcher() const;
QPlatformNativeInterface *nativeInterface() const;
- void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
-
QTouchDevice *touchDevice();
QPlatformAccessibility *accessibility() const Q_DECL_OVERRIDE;
@@ -83,6 +83,10 @@ public:
static QIOSIntegration *instance();
+ // -- QPlatformNativeInterface --
+
+ void *nativeResourceForWindow(const QByteArray &resource, QWindow *window);
+
private:
QPlatformFontDatabase *m_fontDatabase;
QPlatformClipboard *m_clipboard;
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index 9d29b4edf7..fcfd6c7cc8 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -215,11 +215,25 @@ QPlatformTheme *QIOSIntegration::createPlatformTheme(const QString &name) const
return QPlatformIntegration::createPlatformTheme(name);
}
+QTouchDevice *QIOSIntegration::touchDevice()
+{
+ return m_touchDevice;
+}
+
+QPlatformAccessibility *QIOSIntegration::accessibility() const
+{
+ if (!m_accessibility)
+ m_accessibility = new QIOSPlatformAccessibility;
+ return m_accessibility;
+}
+
QPlatformNativeInterface *QIOSIntegration::nativeInterface() const
{
return const_cast<QIOSIntegration *>(this);
}
+// ---------------------------------------------------------
+
void *QIOSIntegration::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
{
if (!window || !window->handle())
@@ -235,16 +249,8 @@ void *QIOSIntegration::nativeResourceForWindow(const QByteArray &resource, QWind
return 0;
}
-QTouchDevice *QIOSIntegration::touchDevice()
-{
- return m_touchDevice;
-}
+// ---------------------------------------------------------
-QPlatformAccessibility *QIOSIntegration::accessibility() const
-{
- if (!m_accessibility)
- m_accessibility = new QIOSPlatformAccessibility;
- return m_accessibility;
-}
+#include "moc_qiosintegration.cpp"
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index 02c3a2d28d..d144b419aa 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -238,7 +238,7 @@
-(BOOL)shouldAutorotate
{
- return m_screen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation;
+ return m_screen && m_screen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation;
}
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_6_0)
diff --git a/src/plugins/platforms/windows/openglblacklists.qrc b/src/plugins/platforms/windows/openglblacklists.qrc
new file mode 100644
index 0000000000..9f0c186c21
--- /dev/null
+++ b/src/plugins/platforms/windows/openglblacklists.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/qt-project.org/windows/openglblacklists">
+ <file alias="default.json">openglblacklists/default.json</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json
new file mode 100644
index 0000000000..0217b79ecf
--- /dev/null
+++ b/src/plugins/platforms/windows/openglblacklists/default.json
@@ -0,0 +1,18 @@
+{
+ "name": "Qt built-in GPU driver blacklist",
+ "version": "5.5",
+ "entries": [
+ {
+ "id": 1,
+ "description": "Desktop OpenGL is unreliable on Intel HD3000/GMA (QTBUG-43263, QTBUG-42240)",
+ "vendor_id": "0x8086",
+ "device_id": [ "0x0A16" ],
+ "os": {
+ "type": "win"
+ },
+ "features": [
+ "disable_desktopgl"
+ ]
+ }
+ ]
+}
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index ebd41d482b..fa355f6201 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -173,7 +173,7 @@ static inline QWindowsSessionManager *platformSessionManager() {
QWindowsUser32DLL::QWindowsUser32DLL() :
setLayeredWindowAttributes(0), updateLayeredWindow(0),
updateLayeredWindowIndirect(0),
- isHungAppWindow(0),
+ isHungAppWindow(0), isTouchWindow(0),
registerTouchWindow(0), unregisterTouchWindow(0),
getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0),
addClipboardFormatListener(0), removeClipboardFormatListener(0)
@@ -202,11 +202,12 @@ void QWindowsUser32DLL::init()
bool QWindowsUser32DLL::initTouch()
{
QSystemLibrary library(QStringLiteral("user32"));
+ isTouchWindow = (IsTouchWindow)(library.resolve("IsTouchWindow"));
registerTouchWindow = (RegisterTouchWindow)(library.resolve("RegisterTouchWindow"));
unregisterTouchWindow = (UnregisterTouchWindow)(library.resolve("UnregisterTouchWindow"));
getTouchInputInfo = (GetTouchInputInfo)(library.resolve("GetTouchInputInfo"));
closeTouchInputHandle = (CloseTouchInputHandle)(library.resolve("CloseTouchInputHandle"));
- return registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && closeTouchInputHandle;
+ return isTouchWindow && registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && closeTouchInputHandle;
}
/*!
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 870a42946d..81f4a36433 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -76,6 +76,7 @@ struct QWindowsUser32DLL
inline void init();
inline bool initTouch();
+ typedef BOOL (WINAPI *IsTouchWindow)(HWND, PULONG);
typedef BOOL (WINAPI *RegisterTouchWindow)(HWND, ULONG);
typedef BOOL (WINAPI *UnregisterTouchWindow)(HWND);
typedef BOOL (WINAPI *GetTouchInputInfo)(HANDLE, UINT, PVOID, int);
@@ -99,6 +100,7 @@ struct QWindowsUser32DLL
IsHungAppWindow isHungAppWindow;
// Touch functions from Windows 7 onwards (also for use with Q_CC_MSVC).
+ IsTouchWindow isTouchWindow;
RegisterTouchWindow registerTouchWindow;
UnregisterTouchWindow unregisterTouchWindow;
GetTouchInputInfo getTouchInputInfo;
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index 74efd49217..7db6abd8ef 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -416,12 +416,15 @@ QWindowsOpenGLContext *QWindowsEGLStaticContext::createContext(QOpenGLContext *c
return new QWindowsEGLContext(this, context->format(), context->shareHandle());
}
-void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig)
+void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig, int *err)
{
+ *err = 0;
EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, (EGLConfig) nativeConfig,
(EGLNativeWindowType) nativeWindow, 0);
- if (surface == EGL_NO_SURFACE)
- qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, libEGL.eglGetError());
+ if (surface == EGL_NO_SURFACE) {
+ *err = libEGL.eglGetError();
+ qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, *err);
+ }
return surface;
}
@@ -578,8 +581,15 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
window->aboutToMakeCurrent();
- EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig));
- Q_ASSERT(eglSurface);
+ int err = 0;
+ EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
+ if (eglSurface == EGL_NO_SURFACE) {
+ if (err == EGL_CONTEXT_LOST) {
+ m_eglContext = EGL_NO_CONTEXT;
+ qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
+ }
+ return false;
+ }
// shortcut: on some GPUs, eglMakeCurrent is not a cheap operation
if (QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() == m_eglContext &&
@@ -597,7 +607,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface)
QWindowsEGLStaticContext::libEGL.eglSwapInterval(m_staticContext->display(), m_swapInterval);
}
} else {
- int err = QWindowsEGLStaticContext::libEGL.eglGetError();
+ err = QWindowsEGLStaticContext::libEGL.eglGetError();
// EGL_CONTEXT_LOST (loss of the D3D device) is not necessarily fatal.
// Qt Quick is able to recover for example.
if (err == EGL_CONTEXT_LOST) {
@@ -625,8 +635,15 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface)
{
QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api);
QWindowsWindow *window = static_cast<QWindowsWindow *>(surface);
- EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig));
- Q_ASSERT(eglSurface);
+ int err = 0;
+ EGLSurface eglSurface = static_cast<EGLSurface>(window->surface(m_eglConfig, &err));
+ if (eglSurface == EGL_NO_SURFACE) {
+ if (err == EGL_CONTEXT_LOST) {
+ m_eglContext = EGL_NO_CONTEXT;
+ qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this;
+ }
+ return;
+ }
bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface);
if (!ok)
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h
index 55f58fac5f..2b249348c3 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.h
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h
@@ -260,7 +260,7 @@ public:
void *moduleHandle() const { return libGLESv2.moduleHandle(); }
QOpenGLContext::OpenGLModuleType moduleType() const { return QOpenGLContext::LibGLES; }
- void *createWindowSurface(void *nativeWindow, void *nativeConfig) Q_DECL_OVERRIDE;
+ void *createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) Q_DECL_OVERRIDE;
void destroyWindowSurface(void *nativeSurface) Q_DECL_OVERRIDE;
QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config, const QSurfaceFormat &referenceFormat);
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index d1ea8a798f..ad75a0bd54 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -336,7 +336,8 @@ static bool addFontToDatabase(const QString &faceName,
uchar charSet,
const TEXTMETRIC *textmetric,
const FONTSIGNATURE *signature,
- int type)
+ int type,
+ bool registerAlias)
{
// the "@family" fonts are just the same as "family". Ignore them.
if (faceName.isEmpty() || faceName.at(0) == QLatin1Char('@') || faceName.startsWith(QLatin1String("WST_")))
@@ -373,7 +374,7 @@ static bool addFontToDatabase(const QString &faceName,
#endif
QString englishName;
- if (ttf && localizedName(faceName))
+ if (registerAlias & ttf && localizedName(faceName))
englishName = getEnglishName(faceName);
QSupportedWritingSystems writingSystems;
@@ -467,64 +468,23 @@ static QByteArray getFntTable(HFONT hfont, uint tag)
#endif
static int QT_WIN_CALLBACK storeFont(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric,
- int type, LPARAM namesSetIn)
+ int type, LPARAM)
{
- typedef QSet<QString> StringSet;
const QString faceName = QString::fromWCharArray(f->elfLogFont.lfFaceName);
const QString fullName = QString::fromWCharArray(f->elfFullName);
const uchar charSet = f->elfLogFont.lfCharSet;
-#ifndef Q_OS_WINCE
const FONTSIGNATURE signature = textmetric->ntmFontSig;
-#else
- FONTSIGNATURE signature;
- QByteArray table;
-
- if (type & TRUETYPE_FONTTYPE) {
- HFONT hfont = CreateFontIndirect(&f->elfLogFont);
- table = getFntTable(hfont, MAKE_TAG('O', 'S', '/', '2'));
- DeleteObject((HGDIOBJ)hfont);
- }
-
- if (table.length() >= 86) {
- // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec
- uchar *tableData = reinterpret_cast<uchar *>(table.data());
-
- signature.fsUsb[0] = qFromBigEndian<quint32>(tableData + 42);
- signature.fsUsb[1] = qFromBigEndian<quint32>(tableData + 46);
- signature.fsUsb[2] = qFromBigEndian<quint32>(tableData + 50);
- signature.fsUsb[3] = qFromBigEndian<quint32>(tableData + 54);
-
- signature.fsCsb[0] = qFromBigEndian<quint32>(tableData + 78);
- signature.fsCsb[1] = qFromBigEndian<quint32>(tableData + 82);
- } else {
- memset(&signature, 0, sizeof(signature));
- }
-#endif
-
// NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is
// identical to a TEXTMETRIC except for the last four members, which we don't use
// anyway
- if (addFontToDatabase(faceName, fullName,
- charSet, (TEXTMETRIC *)textmetric, &signature, type)) {
- reinterpret_cast<StringSet *>(namesSetIn)->insert(faceName + QStringLiteral("::") + fullName);
- }
+ addFontToDatabase(faceName, fullName, charSet, (TEXTMETRIC *)textmetric, &signature, type, false);
// keep on enumerating
return 1;
}
-void QWindowsFontDatabaseFT::populateFontDatabase()
-{
- m_families.clear();
- populate(); // Called multiple times.
- // Work around EnumFontFamiliesEx() not listing the system font, see below.
- const QString sysFontFamily = QGuiApplication::font().family();
- if (!m_families.contains(sysFontFamily))
- populate(sysFontFamily);
-}
-
/*!
\brief Populate font database using EnumFontFamiliesEx().
@@ -533,29 +493,157 @@ void QWindowsFontDatabaseFT::populateFontDatabase()
are only found when specifying the name explicitly.
*/
-void QWindowsFontDatabaseFT::populate(const QString &family)
- {
-
- qCDebug(lcQpaFonts) << __FUNCTION__ << m_families.size() << family;
-
+void QWindowsFontDatabaseFT::populateFamily(const QString &familyName)
+{
+ qCDebug(lcQpaFonts) << familyName;
+ if (familyName.size() >= LF_FACESIZE) {
+ qCWarning(lcQpaFonts) << "Unable to enumerate family '" << familyName << '\'';
+ return;
+ }
HDC dummy = GetDC(0);
LOGFONT lf;
lf.lfCharSet = DEFAULT_CHARSET;
- if (family.size() >= LF_FACESIZE) {
- qWarning("%s: Unable to enumerate family '%s'.",
- __FUNCTION__, qPrintable(family));
- return;
+ familyName.toWCharArray(lf.lfFaceName);
+ lf.lfFaceName[familyName.size()] = 0;
+ lf.lfPitchAndFamily = 0;
+ EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, 0, 0);
+ ReleaseDC(0, dummy);
+}
+
+namespace {
+// Context for enumerating system fonts, records whether the default font has been
+// encountered, which is normally not enumerated.
+struct PopulateFamiliesContext
+{
+ PopulateFamiliesContext(const QString &f) : systemDefaultFont(f), seenSystemDefaultFont(false) {}
+
+ QString systemDefaultFont;
+ bool seenSystemDefaultFont;
+};
+} // namespace
+
+#ifndef Q_OS_WINCE
+
+// Delayed population of font families
+
+static int QT_WIN_CALLBACK populateFontFamilies(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *tm, int, LPARAM lparam)
+{
+ // the "@family" fonts are just the same as "family". Ignore them.
+ const wchar_t *faceNameW = f->elfLogFont.lfFaceName;
+ if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) {
+ // Register only font families for which a font file exists for delayed population
+ const QString faceName = QString::fromWCharArray(faceNameW);
+ const FontKey *key = findFontKey(faceName);
+ if (!key) {
+ key = findFontKey(QString::fromWCharArray(f->elfFullName));
+ if (!key && (tm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE) && localizedName(faceName))
+ key = findFontKey(getEnglishName(faceName));
+ }
+ if (key) {
+ QPlatformFontDatabase::registerFontFamily(faceName);
+ PopulateFamiliesContext *context = reinterpret_cast<PopulateFamiliesContext *>(lparam);
+ if (!context->seenSystemDefaultFont && faceName == context->systemDefaultFont)
+ context->seenSystemDefaultFont = true;
+
+ // Register current font's english name as alias
+ const bool ttf = (tm->ntmTm.tmPitchAndFamily & TMPF_TRUETYPE);
+ if (ttf && localizedName(faceName)) {
+ const QString englishName = getEnglishName(faceName);
+ if (!englishName.isEmpty()) {
+ QPlatformFontDatabase::registerAliasToFontFamily(faceName, englishName);
+ // Check whether the system default font name is an alias of the current font family name,
+ // as on Chinese Windows, where the system font "SimSun" is an alias to a font registered under a local name
+ if (!context->seenSystemDefaultFont && englishName == context->systemDefaultFont)
+ context->seenSystemDefaultFont = true;
+ }
+ }
+ }
}
+ return 1; // continue
+}
- wmemcpy(lf.lfFaceName, reinterpret_cast<const wchar_t*>(family.utf16()),
- family.size() + 1);
+void QWindowsFontDatabaseFT::populateFontDatabase()
+{
+ HDC dummy = GetDC(0);
+ LOGFONT lf;
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfFaceName[0] = 0;
lf.lfPitchAndFamily = 0;
+ PopulateFamiliesContext context(QWindowsFontDatabase::systemDefaultFont().family());
+ EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)populateFontFamilies, reinterpret_cast<LPARAM>(&context), 0);
+ ReleaseDC(0, dummy);
+ // Work around EnumFontFamiliesEx() not listing the system font
+ if (!context.seenSystemDefaultFont)
+ QPlatformFontDatabase::registerFontFamily(context.systemDefaultFont);
+}
+
+#else // !Q_OS_WINCE
+
+// Non-delayed population of fonts (Windows CE).
+
+static int QT_WIN_CALLBACK populateFontCe(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textmetric,
+ int type, LPARAM lparam)
+{
+ // the "@family" fonts are just the same as "family". Ignore them.
+ const wchar_t *faceNameW = f->elfLogFont.lfFaceName;
+ if (faceNameW[0] && faceNameW[0] != L'@' && wcsncmp(faceNameW, L"WST_", 4)) {
+ const uchar charSet = f->elfLogFont.lfCharSet;
+
+ FONTSIGNATURE signature;
+ QByteArray table;
+
+ if (type & TRUETYPE_FONTTYPE) {
+ HFONT hfont = CreateFontIndirect(&f->elfLogFont);
+ table = getFntTable(hfont, MAKE_TAG('O', 'S', '/', '2'));
+ DeleteObject((HGDIOBJ)hfont);
+ }
+
+ if (table.length() >= 86) {
+ // See also qfontdatabase_mac.cpp, offsets taken from OS/2 table in the TrueType spec
+ uchar *tableData = reinterpret_cast<uchar *>(table.data());
+
+ signature.fsUsb[0] = qFromBigEndian<quint32>(tableData + 42);
+ signature.fsUsb[1] = qFromBigEndian<quint32>(tableData + 46);
+ signature.fsUsb[2] = qFromBigEndian<quint32>(tableData + 50);
+ signature.fsUsb[3] = qFromBigEndian<quint32>(tableData + 54);
+
+ signature.fsCsb[0] = qFromBigEndian<quint32>(tableData + 78);
+ signature.fsCsb[1] = qFromBigEndian<quint32>(tableData + 82);
+ } else {
+ memset(&signature, 0, sizeof(signature));
+ }
- EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont,
- (LPARAM)&m_families, 0);
+ // NEWTEXTMETRICEX is a NEWTEXTMETRIC, which according to the documentation is
+ // identical to a TEXTMETRIC except for the last four members, which we don't use
+ // anyway
+ const QString faceName = QString::fromWCharArray(f->elfLogFont.lfFaceName);
+ if (addFontToDatabase(faceName, QString::fromWCharArray(f->elfFullName),
+ charSet, (TEXTMETRIC *)textmetric, &signature, type, true)) {
+ PopulateFamiliesContext *context = reinterpret_cast<PopulateFamiliesContext *>(lparam);
+ if (!context->seenSystemDefaultFont && faceName == context->systemDefaultFont)
+ context->seenSystemDefaultFont = true;
+ }
+ }
+ // keep on enumerating
+ return 1;
+}
+
+void QWindowsFontDatabaseFT::populateFontDatabase()
+{
+ LOGFONT lf;
+ lf.lfCharSet = DEFAULT_CHARSET;
+ HDC dummy = GetDC(0);
+ lf.lfFaceName[0] = 0;
+ lf.lfPitchAndFamily = 0;
+ PopulateFamiliesContext context(QWindowsFontDatabase::systemDefaultFont().family());
+ EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)populateFontCe, reinterpret_cast<LPARAM>(&context), 0);
ReleaseDC(0, dummy);
+ // Work around EnumFontFamiliesEx() not listing the system font, see below.
+ if (!context.seenSystemDefaultFont)
+ populateFamily(context.systemDefaultFont);
}
+#endif // Q_OS_WINCE
QFontEngine * QWindowsFontDatabaseFT::fontEngine(const QFontDef &fontDef, void *handle)
{
@@ -592,7 +680,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
- << script << result << m_families;
+ << script << result;
return result;
}
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
index 7552458a9f..ad5c005ffa 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h
@@ -44,6 +44,7 @@ class QWindowsFontDatabaseFT : public QBasicFontDatabase
{
public:
void populateFontDatabase();
+ void populateFamily(const QString &familyName) Q_DECL_OVERRIDE;
QFontEngine *fontEngine(const QFontDef &fontDef, void *handle);
QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference);
@@ -51,11 +52,6 @@ public:
QString fontDir() const Q_DECL_OVERRIDE;
QFont defaultFont() const Q_DECL_OVERRIDE;
-
-private:
- void populate(const QString &family = QString());
-
- QSet<QString> m_families;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index ca28b822e4..c25b90e98c 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -194,10 +194,10 @@ void QWindowsFontEngine::getCMap()
_faceId.index = 0;
if(cmap) {
OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc);
- designToDevice = QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight);
+ designToDevice = QFixed((int)otm->otmEMSquare)/QFixed::fromReal(fontDef.pixelSize);
unitsPerEm = otm->otmEMSquare;
x_height = (int)otm->otmsXHeight;
- loadKerningPairs(designToDevice);
+ loadKerningPairs(QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight));
_faceId.filename = QFile::encodeName(QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName)));
lineWidth = otm->otmsUnderscoreSize;
fsType = otm->otmfsType;
@@ -361,7 +361,7 @@ glyph_t QWindowsFontEngine::glyphIndex(uint ucs4) const
HGDIOBJ QWindowsFontEngine::selectDesignFont() const
{
LOGFONT f = m_logfont;
- f.lfHeight = unitsPerEm;
+ f.lfHeight = -unitsPerEm;
f.lfWidth = 0;
HFONT designFont = CreateFontIndirect(&f);
return SelectObject(m_fontEngineData->hdc, designFont);
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 9fd18a1ef4..1041ecf44d 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -79,9 +79,7 @@
# include "qwindowsglcontext.h"
#endif
-#ifndef Q_OS_WINCE
-# include "qwindowsopengltester.h"
-#endif
+#include "qwindowsopengltester.h"
QT_BEGIN_NAMESPACE
@@ -209,6 +207,10 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramL
: m_options(0)
, m_fontDatabase(0)
{
+#ifndef Q_OS_WINCE
+ Q_INIT_RESOURCE(openglblacklists);
+#endif
+
static bool dpiAwarenessSet = false;
int tabletAbsoluteRange = -1;
// Default to per-monitor awareness to avoid being scaled when monitors with different DPI
diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h
index 8ebcb83a08..2c52c58829 100644
--- a/src/plugins/platforms/windows/qwindowsopenglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h
@@ -56,7 +56,7 @@ public:
// If the windowing system interface needs explicitly created window surfaces (like EGL),
// reimplement these.
- virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/) { return 0; }
+ virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, int * /*err*/) { return 0; }
virtual void destroyWindowSurface(void * /*nativeSurface*/) { }
private:
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index ba4c95544e..67548a0836 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -42,14 +42,16 @@
#include <QtCore/QFileInfo>
#include <QtCore/QStandardPaths>
#include <QtCore/QLibraryInfo>
+#include <QtCore/QHash>
+#ifndef QT_NO_OPENGL
#include <private/qopengl_p.h>
+#endif
#ifndef Q_OS_WINCE
# include <QtCore/qt_windows.h>
# include <private/qsystemlibrary_p.h>
# include <d3d9.h>
-# include <GL/gl.h>
#endif
QT_BEGIN_NAMESPACE
@@ -206,56 +208,62 @@ static inline QString resolveBugListFile(const QString &fileName)
return QStandardPaths::locate(QStandardPaths::ConfigLocation, fileName);
}
-static void readDriverBugList(const GpuDescription &gpu,
- QWindowsOpenGLTester::Renderers *result)
+typedef QHash<QOpenGLConfig::Gpu, QWindowsOpenGLTester::Renderers> SupportedRenderersCache;
+Q_GLOBAL_STATIC(SupportedRenderersCache, supportedRenderersCache)
+
+#endif // !Q_OS_WINCE
+
+QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly)
{
- const char bugListFileVar[] = "QT_OPENGL_BUGLIST";
- if (!qEnvironmentVariableIsSet(bugListFileVar))
- return;
- const QString fileName = resolveBugListFile(QFile::decodeName(qgetenv(bugListFileVar)));
- if (fileName.isEmpty())
- return;
+ Q_UNUSED(gpu)
+#ifndef Q_OS_WINCE
QOpenGLConfig::Gpu qgpu;
qgpu.deviceId = gpu.deviceId;
qgpu.vendorId = gpu.vendorId;
qgpu.driverVersion = gpu.driverVersion;
- const QSet<QString> features = QOpenGLConfig::gpuFeatures(qgpu, fileName);
+ SupportedRenderersCache *srCache = supportedRenderersCache();
+ SupportedRenderersCache::const_iterator it = srCache->find(qgpu);
+ if (it != srCache->cend())
+ return *it;
+
+ QWindowsOpenGLTester::Renderers result(QWindowsOpenGLTester::AngleRendererD3d11
+ | QWindowsOpenGLTester::AngleRendererD3d9
+ | QWindowsOpenGLTester::AngleRendererD3d11Warp
+ | QWindowsOpenGLTester::SoftwareRasterizer);
+
+ if (!glesOnly && testDesktopGL())
+ result |= QWindowsOpenGLTester::DesktopGl;
+
+ QSet<QString> features;
+ const char bugListFileVar[] = "QT_OPENGL_BUGLIST";
+ if (qEnvironmentVariableIsSet(bugListFileVar)) {
+ const QString fileName = resolveBugListFile(QFile::decodeName(qgetenv(bugListFileVar)));
+ if (!fileName.isEmpty())
+ features = QOpenGLConfig::gpuFeatures(qgpu, fileName);
+ } else {
+ features = QOpenGLConfig::gpuFeatures(qgpu, QStringLiteral(":/qt-project.org/windows/openglblacklists/default.json"));
+ }
+ qCDebug(lcQpaGl) << "GPU features:" << features;
+
if (features.contains(QStringLiteral("disable_desktopgl"))) { // Qt-specific
qCWarning(lcQpaGl) << "Disabling Desktop GL: " << gpu;
- *result &= ~QWindowsOpenGLTester::DesktopGl;
+ result &= ~QWindowsOpenGLTester::DesktopGl;
}
if (features.contains(QStringLiteral("disable_angle"))) { // Qt-specific keyword
qCWarning(lcQpaGl) << "Disabling ANGLE: " << gpu;
- *result &= ~QWindowsOpenGLTester::GlesMask;
+ result &= ~QWindowsOpenGLTester::GlesMask;
} else {
if (features.contains(QStringLiteral("disable_d3d11"))) { // standard keyword
qCWarning(lcQpaGl) << "Disabling D3D11: " << gpu;
- *result &= ~QWindowsOpenGLTester::AngleRendererD3d11;
+ result &= ~QWindowsOpenGLTester::AngleRendererD3d11;
}
if (features.contains(QStringLiteral("disable_d3d9"))) { // Qt-specific
qCWarning(lcQpaGl) << "Disabling D3D9: " << gpu;
- *result &= ~QWindowsOpenGLTester::AngleRendererD3d9;
+ result &= ~QWindowsOpenGLTester::AngleRendererD3d9;
}
}
-}
-#endif // !Q_OS_WINCE
-
-static inline QWindowsOpenGLTester::Renderers
- detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly)
-{
- Q_UNUSED(gpu)
-#ifndef Q_OS_WINCE
- // Add checks for card types with known issues here.
- QWindowsOpenGLTester::Renderers result(QWindowsOpenGLTester::AngleRendererD3d11
- | QWindowsOpenGLTester::AngleRendererD3d9
- | QWindowsOpenGLTester::AngleRendererD3d11Warp
- | QWindowsOpenGLTester::SoftwareRasterizer);
-
- if (!glesOnly && QWindowsOpenGLTester::testDesktopGL())
- result |= QWindowsOpenGLTester::DesktopGl;
-
- readDriverBugList(gpu, &result);
+ srCache->insert(qgpu, result);
return result;
#else // !Q_OS_WINCE
return QWindowsOpenGLTester::Gles;
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h
index 7b6164946e..748885542d 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.h
+++ b/src/plugins/platforms/windows/qwindowsopengltester.h
@@ -80,9 +80,12 @@ public:
static Renderer requestedGlesRenderer();
static Renderer requestedRenderer();
+
static Renderers supportedGlesRenderers();
static Renderers supportedRenderers();
+private:
+ static QWindowsOpenGLTester::Renderers detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly);
static bool testDesktopGL();
};
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 4cf8fcf4da..2fd0f12c26 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -2259,14 +2259,14 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
}
}
-void *QWindowsWindow::surface(void *nativeConfig)
+void *QWindowsWindow::surface(void *nativeConfig, int *err)
{
#ifdef QT_NO_OPENGL
return 0;
#else
if (!m_surface) {
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
- m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig);
+ m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, err);
}
return m_surface;
@@ -2294,6 +2294,12 @@ void QWindowsWindow::registerTouchWindow(QWindowsWindowFunctions::TouchWindowTou
#ifndef Q_OS_WINCE
if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch)
&& window()->type() != Qt::ForeignWindow) {
+ ULONG touchFlags = 0;
+ const bool ret = QWindowsContext::user32dll.isTouchWindow(m_data.hwnd, &touchFlags);
+ // Return if it is not a touch window or the flags are already set by a hook
+ // such as HCBT_CREATEWND
+ if (!ret || touchFlags != 0)
+ return;
if (QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, (ULONG)touchTypes))
setFlag(TouchRegistered);
else
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index f0b04fbc47..0089ad07a0 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -248,7 +248,7 @@ public:
bool isEnabled() const;
void setWindowIcon(const QIcon &icon);
- void *surface(void *nativeConfig);
+ void *surface(void *nativeConfig, int *err);
void invalidateSurface() Q_DECL_OVERRIDE;
void aboutToMakeCurrent();
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index 246598677f..e3880a2646 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -118,71 +118,15 @@ contains(QT_CONFIG,dynamicgl) {
RESOURCES += $$PWD/cursors.qrc
}
+!wince*: RESOURCES += $$PWD/openglblacklists.qrc
+
contains(QT_CONFIG, freetype) {
DEFINES *= QT_NO_FONTCONFIG
- QT_FREETYPE_DIR = $$QT_SOURCE_TREE/src/3rdparty/freetype
-
+ include($$QT_SOURCE_TREE/src/3rdparty/freetype.pri)
HEADERS += \
$$PWD/qwindowsfontdatabase_ft.h
SOURCES += \
- $$PWD/qwindowsfontdatabase_ft.cpp \
- $$QT_FREETYPE_DIR/src/base/ftbase.c \
- $$QT_FREETYPE_DIR/src/base/ftbbox.c \
- $$QT_FREETYPE_DIR/src/base/ftdebug.c \
- $$QT_FREETYPE_DIR/src/base/ftglyph.c \
- $$QT_FREETYPE_DIR/src/base/ftinit.c \
- $$QT_FREETYPE_DIR/src/base/ftmm.c \
- $$QT_FREETYPE_DIR/src/base/fttype1.c \
- $$QT_FREETYPE_DIR/src/base/ftsynth.c \
- $$QT_FREETYPE_DIR/src/base/ftbitmap.c \
- $$QT_FREETYPE_DIR/src/bdf/bdf.c \
- $$QT_FREETYPE_DIR/src/cache/ftcache.c \
- $$QT_FREETYPE_DIR/src/cff/cff.c \
- $$QT_FREETYPE_DIR/src/cid/type1cid.c \
- $$QT_FREETYPE_DIR/src/gzip/ftgzip.c \
- $$QT_FREETYPE_DIR/src/pcf/pcf.c \
- $$QT_FREETYPE_DIR/src/pfr/pfr.c \
- $$QT_FREETYPE_DIR/src/psaux/psaux.c \
- $$QT_FREETYPE_DIR/src/pshinter/pshinter.c \
- $$QT_FREETYPE_DIR/src/psnames/psmodule.c \
- $$QT_FREETYPE_DIR/src/raster/raster.c \
- $$QT_FREETYPE_DIR/src/sfnt/sfnt.c \
- $$QT_FREETYPE_DIR/src/smooth/smooth.c \
- $$QT_FREETYPE_DIR/src/truetype/truetype.c \
- $$QT_FREETYPE_DIR/src/type1/type1.c \
- $$QT_FREETYPE_DIR/src/type42/type42.c \
- $$QT_FREETYPE_DIR/src/winfonts/winfnt.c \
- $$QT_FREETYPE_DIR/src/lzw/ftlzw.c\
- $$QT_FREETYPE_DIR/src/otvalid/otvalid.c\
- $$QT_FREETYPE_DIR/src/otvalid/otvbase.c\
- $$QT_FREETYPE_DIR/src/otvalid/otvgdef.c\
- $$QT_FREETYPE_DIR/src/otvalid/otvjstf.c\
- $$QT_FREETYPE_DIR/src/otvalid/otvcommn.c\
- $$QT_FREETYPE_DIR/src/otvalid/otvgpos.c\
- $$QT_FREETYPE_DIR/src/otvalid/otvgsub.c\
- $$QT_FREETYPE_DIR/src/otvalid/otvmod.c\
- $$QT_FREETYPE_DIR/src/autofit/afangles.c\
- $$QT_FREETYPE_DIR/src/autofit/afglobal.c\
- $$QT_FREETYPE_DIR/src/autofit/aflatin.c\
- $$QT_FREETYPE_DIR/src/autofit/afmodule.c\
- $$QT_FREETYPE_DIR/src/autofit/afdummy.c\
- $$QT_FREETYPE_DIR/src/autofit/afhints.c\
- $$QT_FREETYPE_DIR/src/autofit/afloader.c\
- $$QT_FREETYPE_DIR/src/autofit/autofit.c
-
- SOURCES += $$QT_FREETYPE_DIR/src/base/ftsystem.c
-
-
- INCLUDEPATH += \
- $$QT_FREETYPE_DIR/src \
- $$QT_FREETYPE_DIR/include
-
- TR_EXCLUDE += $$QT_FREETYPE_DIR/*
-
- DEFINES += FT2_BUILD_LIBRARY
- contains(QT_CONFIG, system-zlib) {
- DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB
- }
+ $$PWD/qwindowsfontdatabase_ft.cpp
} else:contains(QT_CONFIG, system-freetype) {
include($$QT_SOURCE_TREE/src/platformsupport/fontdatabases/basic/basic.pri)
HEADERS += \
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index d4f1c6ae48..2c0a7a11cc 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -97,7 +97,7 @@ protected:
that->format_atoms = m_clipboard->getDataInFormat(modeAtom, m_clipboard->atom(QXcbAtom::TARGETS));
if (format_atoms.size() > 0) {
- xcb_atom_t *targets = (xcb_atom_t *) format_atoms.data();
+ const xcb_atom_t *targets = (const xcb_atom_t *) format_atoms.data();
int size = format_atoms.size() / sizeof(xcb_atom_t);
for (int i = 0; i < size; ++i) {
@@ -128,7 +128,7 @@ protected:
(void)formats(); // trigger update of format list
QVector<xcb_atom_t> atoms;
- xcb_atom_t *targets = (xcb_atom_t *) format_atoms.data();
+ const xcb_atom_t *targets = (const 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)
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 7ec5851737..11ff313144 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -51,6 +51,7 @@
#include <QAbstractEventDispatcher>
#include <QTimer>
#include <QByteArray>
+#include <QScopedPointer>
#include <algorithm>
@@ -116,8 +117,29 @@ static int ioErrorHandler(Display *dpy)
}
#endif
-QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& newScreens,
- int screenNumber, xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output)
+QXcbScreen* QXcbConnection::findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc)
+{
+ foreach (QXcbScreen *screen, m_screens) {
+ if (screen->root() == rootWindow && screen->crtc() == crtc)
+ return screen;
+ }
+
+ return 0;
+}
+
+QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output)
+{
+ foreach (QXcbScreen *screen, m_screens) {
+ if (screen->root() == rootWindow && screen->output() == output)
+ return screen;
+ }
+
+ return 0;
+}
+
+QXcbScreen* QXcbConnection::createScreen(int screenNumber, xcb_screen_t* xcbScreen,
+ xcb_randr_output_t outputId,
+ xcb_randr_get_output_info_reply_t *output)
{
QString name;
if (output)
@@ -130,23 +152,147 @@ QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& newScreens,
displayName.truncate(dotPos);
name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(screenNumber);
}
- foreach (QXcbScreen* scr, m_screens)
- if (scr->name() == name && scr->root() == xcbScreen->root)
- return scr;
- QXcbScreen *ret = new QXcbScreen(this, xcbScreen, output, name, screenNumber);
- newScreens << ret;
- return ret;
+
+ return new QXcbScreen(this, xcbScreen, outputId, output, name, screenNumber);
+}
+
+bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
+{
+ xcb_generic_error_t *error = 0;
+ xcb_randr_get_output_primary_cookie_t primaryCookie =
+ xcb_randr_get_output_primary(xcb_connection(), rootWindow);
+ 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);
+ error = NULL;
+ }
+ const bool isPrimary = primary ? (primary->output == output) : false;
+
+ return isPrimary;
+}
+
+xcb_screen_t* QXcbConnection::xcbScreenForRootWindow(xcb_window_t rootWindow, int *xcbScreenNumber)
+{
+ xcb_screen_iterator_t xcbScreenIter = xcb_setup_roots_iterator(m_setup);
+ for (; xcbScreenIter.rem; xcb_screen_next(&xcbScreenIter)) {
+ if (xcbScreenIter.data->root == rootWindow) {
+ if (xcbScreenNumber)
+ *xcbScreenNumber = xcb_setup_roots_length(m_setup) - xcbScreenIter.rem;
+ return xcbScreenIter.data;
+ }
+ }
+
+ return 0;
}
/*!
\brief Synchronizes the screen list, adds new screens, removes deleted ones
*/
-void QXcbConnection::updateScreens()
+void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
+{
+ if (event->subCode == XCB_RANDR_NOTIFY_CRTC_CHANGE) {
+ xcb_randr_crtc_change_t crtc = event->u.cc;
+ xcb_screen_t *xcbScreen = xcbScreenForRootWindow(crtc.window);
+ if (!xcbScreen)
+ // Not for us
+ return;
+
+ qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc;
+ QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc);
+ // Only update geometry when there's a valid mode on the CRTC
+ // CRTC with node mode could mean that output has been disabled, and we'll
+ // get RRNotifyOutputChange notification for that.
+ if (screen && crtc.mode) {
+ screen->updateGeometry(QRect(crtc.x, crtc.y, crtc.width, crtc.height), crtc.rotation);
+ if (screen->mode() != crtc.mode)
+ screen->updateRefreshRate(crtc.mode);
+ }
+
+ } else if (event->subCode == XCB_RANDR_NOTIFY_OUTPUT_CHANGE) {
+ xcb_randr_output_change_t output = event->u.oc;
+ int xcbScreenNumber = 0;
+ xcb_screen_t *xcbScreen = xcbScreenForRootWindow(output.window, &xcbScreenNumber);
+ if (!xcbScreen)
+ // Not for us
+ return;
+
+ QXcbScreen *screen = findScreenForOutput(output.window, output.output);
+ qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_OUTPUT_CHANGE:" << output.output;
+
+ if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) {
+ qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected";
+
+ // Known screen removed -> delete it
+ m_screens.removeOne(screen);
+ foreach (QXcbScreen *otherScreen, m_screens)
+ otherScreen->removeVirtualSibling((QPlatformScreen *) screen);
+
+ QXcbIntegration::instance()->destroyScreen(screen);
+
+ // QTBUG-40174, QTBUG-42985: If there are no outputs, then there must be
+ // no QScreen instances; a Qt application can survive this situation, and
+ // start rendering again later when there is a screen again.
+
+ } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) {
+ // New XRandR output is available and it's enabled
+ if (output.crtc != XCB_NONE && output.mode != XCB_NONE) {
+ xcb_randr_get_output_info_cookie_t outputInfoCookie =
+ xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp);
+ QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
+ xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
+
+ screen = createScreen(xcbScreenNumber, xcbScreen, output.output, outputInfo.data());
+ qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
+
+ screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
+ foreach (QXcbScreen *otherScreen, m_screens)
+ if (otherScreen->root() == output.window)
+ otherScreen->addVirtualSibling(screen);
+ m_screens << screen;
+ QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+ }
+ // else ignore disabled screens
+ } else if (screen) {
+ // Screen has been disabled -> remove
+ if (output.crtc == XCB_NONE && output.mode == XCB_NONE) {
+ qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
+ m_screens.removeOne(screen);
+ foreach (QXcbScreen *otherScreen, m_screens)
+ otherScreen->removeVirtualSibling((QPlatformScreen *) screen);
+ QXcbIntegration::instance()->destroyScreen(screen);
+ } else {
+ // Just update existing screen
+ screen->updateGeometry(output.config_timestamp);
+ const bool wasPrimary = screen->isPrimary();
+ screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
+ if (screen->mode() != output.mode)
+ screen->updateRefreshRate(output.mode);
+
+ // If the screen became primary, reshuffle the order in QGuiApplicationPrivate
+ // TODO: add a proper mechanism for updating primary screen
+ if (!wasPrimary && screen->isPrimary()) {
+ QScreen *realScreen = static_cast<QPlatformScreen*>(screen)->screen();
+ QGuiApplicationPrivate::screen_list.removeOne(realScreen);
+ QGuiApplicationPrivate::screen_list.prepend(realScreen);
+ m_screens.removeOne(screen);
+ m_screens.prepend(screen);
+ }
+ qCDebug(lcQpaScreen) << "output has changed" << screen;
+ }
+ }
+ if (!m_screens.isEmpty())
+ qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
+ else
+ qCDebug(lcQpaScreen) << "no outputs";
+ }
+}
+
+void QXcbConnection::initializeScreens()
{
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
int xcbScreenNumber = 0; // screen number in the xcb sense
- QList<QXcbScreen *> activeScreens;
- QList<QXcbScreen *> newScreens;
QXcbScreen* primaryScreen = NULL;
while (it.rem) {
// Each "screen" in xcb terminology is a virtual desktop,
@@ -161,59 +307,73 @@ void QXcbConnection::updateScreens()
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);
- xcb_randr_get_output_primary_reply_t *primary =
- xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error);
+ QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary(
+ xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
if (!primary || error) {
- qWarning("QXcbConnection: Failed to get the primary output of the screen");
+ qWarning("failed to get the primary output of the screen");
free(error);
} else {
- xcb_randr_get_screen_resources_reply_t *resources =
- xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error);
+ QScopedPointer<xcb_randr_get_screen_resources_reply_t, QScopedPointerPodDeleter> resources(
+ xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error));
if (!resources || error) {
- qWarning("QXcbConnection: Failed to get the screen resources");
+ qWarning("failed to get the screen resources");
free(error);
} else {
xcb_timestamp_t timestamp = resources->config_timestamp;
- outputCount = xcb_randr_get_screen_resources_outputs_length(resources);
- xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources);
+ 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++) {
- xcb_randr_get_output_info_reply_t *output =
+ 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);
+ 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 connected", qPrintable(
- QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output),
- xcb_randr_get_output_info_name_length(output))));
+ 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 = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen, output);
+ QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data());
siblings << screen;
- activeScreens << screen;
++connectedOutputCount;
+ 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());
}
}
- free(output);
}
}
- free(resources);
}
- free(primary);
}
foreach (QPlatformScreen* s, siblings)
((QXcbScreen*)s)->setVirtualSiblings(siblings);
@@ -221,47 +381,7 @@ void QXcbConnection::updateScreens()
++xcbScreenNumber;
} // for each xcb screen
- QXcbIntegration *integration = QXcbIntegration::instance();
-
- // Rebuild screen list, ensuring primary screen is always in front,
- // both in the QXcbConnection::m_screens list as well as in the
- // QGuiApplicationPrivate::screen_list list, which gets updated via
- // - screen added: integration->screenAdded()
- // - screen removed: integration->destroyScreen
-
- // Gather screens to delete
- QList<QXcbScreen*> screensToDelete;
- for (int i = m_screens.count() - 1; i >= 0; --i) {
- if (!activeScreens.contains(m_screens[i])) {
- screensToDelete.append(m_screens.takeAt(i));
- }
- }
-
- // If there is a new primary screen, add that one first
- if (newScreens.contains(primaryScreen)) {
- newScreens.removeOne(primaryScreen);
- m_screens.prepend(primaryScreen);
- qCDebug(lcQpaScreen) << "adding as primary" << primaryScreen;
- integration->screenAdded(primaryScreen, true);
- }
-
- // Add the remaining new screens
- foreach (QXcbScreen* screen, newScreens) {
- m_screens.append(screen);
- qCDebug(lcQpaScreen) << "adding" << screen;
- integration->screenAdded(screen);
- }
-
- // Delete the old screens, now that the new ones were added
- // and we are sure that there is at least one screen available
- foreach (QXcbScreen* screen, screensToDelete) {
- qCDebug(lcQpaScreen) << "removing" << screen;
- integration->destroyScreen(screen);
- }
-
- // Ensure that the primary screen is first in m_screens too
- // (in case the assignment of primary was the only change,
- // without adding or removing screens)
+ // Ensure the primary screen is first in the list
if (primaryScreen) {
Q_ASSERT(!m_screens.isEmpty());
if (m_screens.first() != primaryScreen) {
@@ -270,13 +390,15 @@ void QXcbConnection::updateScreens()
}
}
+ // Push the screens to QApplication
+ QXcbIntegration *integration = QXcbIntegration::instance();
+ foreach (QXcbScreen* screen, m_screens) {
+ qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
+ integration->screenAdded(screen, screen->isPrimary());
+ }
+
if (!m_screens.isEmpty())
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
- else
- // QTBUG-40174, QTBUG-42985: If there are no outputs, then there must be
- // no QScreen instances; a Qt application can survive this situation, and
- // start rendering again later when there is a screen again.
- qCDebug(lcQpaScreen) << "xcb connection has no outputs";
}
QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName)
@@ -343,7 +465,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
m_netWmUserTime = XCB_CURRENT_TIME;
initializeXRandr();
- updateScreens();
+ initializeScreens();
if (m_screens.isEmpty())
qFatal("QXcbConnection: no screens available");
@@ -943,14 +1065,14 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
m_clipboard->handleXFixesSelectionRequest((xcb_xfixes_selection_notify_event_t *)event);
#endif
handled = true;
+ } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) {
+ updateScreens((xcb_randr_notify_event_t *)event);
+ handled = true;
} else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) {
- updateScreens();
xcb_randr_screen_change_notify_event_t *change_event = (xcb_randr_screen_change_notify_event_t *)event;
foreach (QXcbScreen *s, m_screens) {
- if (s->root() == change_event->root ) {
+ if (s->root() == change_event->root )
s->handleScreenChange(change_event);
- s->updateRefreshRate();
- }
}
handled = true;
#ifndef QT_NO_XKB
@@ -1178,7 +1300,8 @@ xcb_timestamp_t QXcbConnection::getTimestamp()
xcb_window_t QXcbConnection::rootWindow()
{
- return primaryScreen()->root();
+ QXcbScreen *s = primaryScreen();
+ return s ? s->root() : 0;
}
#ifdef XCB_USE_XLIB
@@ -1653,6 +1776,17 @@ void QXcbConnection::initializeXRandr()
has_randr_extension = false;
}
free(xrandr_query);
+
+ xcb_screen_iterator_t rootIter = xcb_setup_roots_iterator(m_setup);
+ for (; rootIter.rem; xcb_screen_next(&rootIter)) {
+ xcb_randr_select_input(xcb_connection(),
+ rootIter.data->root,
+ XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE |
+ XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE |
+ XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE |
+ XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY
+ );
+ }
}
void QXcbConnection::initializeXShape()
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 97c2590708..4c014bc6e2 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -35,6 +35,7 @@
#define QXCBCONNECTION_H
#include <xcb/xcb.h>
+#include <xcb/randr.h>
#include "qxcbexport.h"
#include <QHash>
@@ -495,9 +496,15 @@ private:
void initializeXShape();
void initializeXKB();
void handleClientMessageEvent(const xcb_client_message_event_t *event);
- QXcbScreen* findOrCreateScreen(QList<QXcbScreen *>& newScreens, int screenNumber,
- xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output = NULL);
- void updateScreens();
+ QXcbScreen* createScreen(int screenNumber, xcb_screen_t* xcbScreen,
+ xcb_randr_output_t outputId = XCB_NONE,
+ xcb_randr_get_output_info_reply_t *output = 0);
+ QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc);
+ QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output);
+ xcb_screen_t* xcbScreenForRootWindow(xcb_window_t rootWindow, int *xcbScreenNumber = 0);
+ bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
+ void initializeScreens();
+ void updateScreens(const xcb_randr_notify_event_t *event);
void handleButtonPress(xcb_generic_event_t *event);
void handleButtonRelease(xcb_generic_event_t *event);
void handleMotionNotify(xcb_generic_event_t *event);
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index a375128288..75ffaa37bb 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -93,13 +93,21 @@ QXcbNativeInterface::QXcbNativeInterface() :
void QXcbNativeInterface::beep() // For QApplication::beep()
{
- QPlatformScreen *screen = QGuiApplication::primaryScreen()->handle();
+ QScreen *priScreen = QGuiApplication::primaryScreen();
+ if (!priScreen)
+ return;
+ QPlatformScreen *screen = priScreen->handle();
+ if (!screen)
+ return;
xcb_connection_t *connection = static_cast<QXcbScreen *>(screen)->xcb_connection();
xcb_bell(connection, 0);
}
static inline QXcbSystemTrayTracker *systemTrayTracker(const QScreen *s)
{
+ if (!s)
+ return Q_NULLPTR;
+
return static_cast<const QXcbScreen *>(s->handle())->connection()->systemTrayTracker();
}
@@ -179,6 +187,9 @@ void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resour
case AtspiBus:
result = atspiBus();
break;
+ case Connection:
+ result = connection();
+ break;
default:
break;
}
@@ -355,16 +366,25 @@ QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &functio
void *QXcbNativeInterface::appTime(const QXcbScreen *screen)
{
+ if (!screen)
+ return Q_NULLPTR;
+
return reinterpret_cast<void *>(quintptr(screen->connection()->time()));
}
void *QXcbNativeInterface::appUserTime(const QXcbScreen *screen)
{
+ if (!screen)
+ return Q_NULLPTR;
+
return reinterpret_cast<void *>(quintptr(screen->connection()->netWmUserTime()));
}
void *QXcbNativeInterface::getTimestamp(const QXcbScreen *screen)
{
+ if (!screen)
+ return Q_NULLPTR;
+
return reinterpret_cast<void *>(quintptr(screen->connection()->getTimestamp()));
}
@@ -400,10 +420,16 @@ void *QXcbNativeInterface::display()
#ifdef XCB_USE_XLIB
QXcbIntegration *integration = QXcbIntegration::instance();
QXcbConnection *defaultConnection = integration->defaultConnection();
- return defaultConnection->xlib_display();
-#else
- return 0;
+ if (defaultConnection)
+ return defaultConnection->xlib_display();
#endif
+ return Q_NULLPTR;
+}
+
+void *QXcbNativeInterface::connection()
+{
+ QXcbIntegration *integration = QXcbIntegration::instance();
+ return integration->defaultConnection()->xcb_connection();
}
void *QXcbNativeInterface::atspiBus()
@@ -429,12 +455,16 @@ void *QXcbNativeInterface::atspiBus()
void QXcbNativeInterface::setAppTime(QScreen* screen, xcb_timestamp_t time)
{
- static_cast<QXcbScreen *>(screen->handle())->connection()->setTime(time);
+ if (screen) {
+ static_cast<QXcbScreen *>(screen->handle())->connection()->setTime(time);
+ }
}
void QXcbNativeInterface::setAppUserTime(QScreen* screen, xcb_timestamp_t time)
{
- static_cast<QXcbScreen *>(screen->handle())->connection()->setNetWmUserTime(time);
+ if (screen) {
+ static_cast<QXcbScreen *>(screen->handle())->connection()->setNetWmUserTime(time);
+ }
}
void QXcbNativeInterface::setStartupId(const char *data)
@@ -450,9 +480,11 @@ QXcbScreen *QXcbNativeInterface::qPlatformScreenForWindow(QWindow *window)
{
QXcbScreen *screen;
if (window) {
- screen = static_cast<QXcbScreen *>(window->screen()->handle());
+ QScreen *qs = window->screen();
+ screen = static_cast<QXcbScreen *>(qs ? qs->handle() : Q_NULLPTR);
} else {
- screen = static_cast<QXcbScreen *>(QGuiApplication::primaryScreen()->handle());
+ QScreen *qs = QGuiApplication::primaryScreen();
+ screen = static_cast<QXcbScreen *>(qs ? qs->handle() : Q_NULLPTR);
}
return screen;
}
@@ -461,23 +493,23 @@ void *QXcbNativeInterface::displayForWindow(QWindow *window)
{
#if defined(XCB_USE_XLIB)
QXcbScreen *screen = qPlatformScreenForWindow(window);
- return screen->connection()->xlib_display();
+ return screen ? screen->connection()->xlib_display() : Q_NULLPTR;
#else
Q_UNUSED(window);
- return 0;
+ return Q_NULLPTR;
#endif
}
void *QXcbNativeInterface::connectionForWindow(QWindow *window)
{
QXcbScreen *screen = qPlatformScreenForWindow(window);
- return screen->xcb_connection();
+ return screen ? screen->xcb_connection() : Q_NULLPTR;
}
void *QXcbNativeInterface::screenForWindow(QWindow *window)
{
QXcbScreen *screen = qPlatformScreenForWindow(window);
- return screen->screen();
+ return screen ? screen->screen() : Q_NULLPTR;
}
void QXcbNativeInterface::addHandler(QXcbNativeInterfaceHandler *handler)
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h
index 054c0ec2b5..f88b710864 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.h
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h
@@ -100,6 +100,7 @@ public:
void *rootWindow();
void *display();
void *atspiBus();
+ void *connection();
static void setStartupId(const char *);
static void setAppTime(QScreen *screen, xcb_timestamp_t time);
static void setAppUserTime(QScreen *screen, xcb_timestamp_t time);
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 78ced43af8..383adf9734 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -48,10 +48,15 @@
QT_BEGIN_NAMESPACE
QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
- xcb_randr_get_output_info_reply_t *output, const QString &outputName, int number)
+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
+ QString outputName, int number)
: QXcbObject(connection)
, m_screen(scr)
+ , m_output(outputId)
, m_crtc(output ? output->crtc : 0)
+ , m_mode(XCB_NONE)
+ , m_primary(false)
+ , m_rotation(XCB_RANDR_ROTATION_ROTATE_0)
, m_outputName(outputName)
, m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
, m_virtualSize(scr->width_in_pixels, scr->height_in_pixels)
@@ -67,11 +72,20 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
, m_antialiasingEnabled(-1)
, m_xSettings(0)
{
- if (connection->hasXRandr())
+ if (connection->hasXRandr()) {
xcb_randr_select_input(xcb_connection(), screen()->root, true);
-
- updateGeometry(output ? output->timestamp : 0);
- updateRefreshRate();
+ xcb_randr_get_crtc_info_cookie_t crtcCookie =
+ xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, output ? output->timestamp : 0);
+ xcb_randr_get_crtc_info_reply_t *crtc =
+ xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL);
+ if (crtc) {
+ updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation);
+ updateRefreshRate(crtc->mode);
+ free(crtc);
+ }
+ } else {
+ updateGeometry(output ? output->timestamp : 0);
+ }
const int dpr = int(devicePixelRatio());
// On VNC, it can be that physical size is unknown while
@@ -352,9 +366,15 @@ QPlatformCursor *QXcbScreen::cursor() const
*/
void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event)
{
- updateGeometry(change_event->config_timestamp);
+ // No need to do anything when screen rotation did not change - if any
+ // xcb output geometry has changed, we will get RRCrtcChangeNotify and
+ // RROutputChangeNotify events next
+ if (change_event->rotation == m_rotation)
+ return;
- switch (change_event->rotation) {
+ m_rotation = change_event->rotation;
+ updateGeometry(change_event->timestamp);
+ switch (m_rotation) {
case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal
m_orientation = Qt::LandscapeOrientation;
m_virtualSize.setWidth(change_event->width);
@@ -406,35 +426,37 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan
void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
{
- QRect xGeometry;
- QRect xAvailableGeometry;
+ xcb_randr_get_crtc_info_cookie_t crtcCookie =
+ xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp);
+ xcb_randr_get_crtc_info_reply_t *crtc =
+ xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL);
+ if (crtc) {
+ updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation);
+ free(crtc);
+ }
+}
- if (connection()->hasXRandr()) {
- xcb_randr_get_crtc_info_reply_t *crtc = xcb_randr_get_crtc_info_reply(xcb_connection(),
- xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp), NULL);
- if (crtc) {
- xGeometry = QRect(crtc->x, crtc->y, crtc->width, crtc->height);
- xAvailableGeometry = xGeometry;
- switch (crtc->rotation) {
- case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal
- m_orientation = Qt::LandscapeOrientation;
- m_sizeMillimeters = m_outputSizeMillimeters;
- break;
- case XCB_RANDR_ROTATION_ROTATE_90: // xrandr --rotate left
- m_orientation = Qt::PortraitOrientation;
- m_sizeMillimeters = m_outputSizeMillimeters.transposed();
- break;
- case XCB_RANDR_ROTATION_ROTATE_180: // xrandr --rotate inverted
- m_orientation = Qt::InvertedLandscapeOrientation;
- m_sizeMillimeters = m_outputSizeMillimeters;
- break;
- case XCB_RANDR_ROTATION_ROTATE_270: // xrandr --rotate right
- m_orientation = Qt::InvertedPortraitOrientation;
- m_sizeMillimeters = m_outputSizeMillimeters.transposed();
- break;
- }
- free(crtc);
- }
+void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation)
+{
+ QRect xGeometry = geom;
+ QRect xAvailableGeometry = xGeometry;
+ switch (rotation) {
+ case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal
+ m_orientation = Qt::LandscapeOrientation;
+ m_sizeMillimeters = m_outputSizeMillimeters;
+ break;
+ case XCB_RANDR_ROTATION_ROTATE_90: // xrandr --rotate left
+ m_orientation = Qt::PortraitOrientation;
+ m_sizeMillimeters = m_outputSizeMillimeters.transposed();
+ break;
+ case XCB_RANDR_ROTATION_ROTATE_180: // xrandr --rotate inverted
+ m_orientation = Qt::InvertedLandscapeOrientation;
+ m_sizeMillimeters = m_outputSizeMillimeters;
+ break;
+ case XCB_RANDR_ROTATION_ROTATE_270: // xrandr --rotate right
+ m_orientation = Qt::InvertedPortraitOrientation;
+ m_sizeMillimeters = m_outputSizeMillimeters.transposed();
+ break;
}
xcb_get_property_reply_t * workArea =
@@ -463,31 +485,38 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
m_geometry = QRect(xGeometry.topLeft()/dpr, xGeometry.size()/dpr);
m_nativeGeometry = QRect(xGeometry.topLeft(), xGeometry.size());
m_availableGeometry = QRect(xAvailableGeometry.topLeft()/dpr, xAvailableGeometry.size()/dpr);
-
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);
}
-void QXcbScreen::updateRefreshRate()
+void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode)
{
if (!connection()->hasXRandr())
return;
- int rate = m_refreshRate;
-
- xcb_randr_get_screen_info_reply_t *screenInfoReply =
- xcb_randr_get_screen_info_reply(xcb_connection(), xcb_randr_get_screen_info_unchecked(xcb_connection(), m_screen->root), 0);
-
- if (screenInfoReply) {
- rate = screenInfoReply->rate;
- free(screenInfoReply);
- }
-
- if (rate == m_refreshRate)
+ if (m_mode == mode)
return;
- m_refreshRate = rate;
+ // we can safely use get_screen_resources_current here, because in order to
+ // get here, we must have called get_screen_resources before
+ xcb_randr_get_screen_resources_current_cookie_t resourcesCookie =
+ xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), m_screen->root);
+ xcb_randr_get_screen_resources_current_reply_t *resources =
+ xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, NULL);
+ if (resources) {
+ xcb_randr_mode_info_iterator_t modesIter =
+ xcb_randr_get_screen_resources_current_modes_iterator(resources);
+ for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) {
+ xcb_randr_mode_info_t *modeInfo = modesIter.data;
+ if (modeInfo->id == mode) {
+ m_refreshRate = modeInfo->dot_clock / (modeInfo->htotal * modeInfo->vtotal);
+ m_mode = mode;
+ break;
+ }
+ }
- QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), rate);
+ free(resources);
+ QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), m_refreshRate);
+ }
}
QPixmap QXcbScreen::grabWindow(WId window, int x, int y, int width, int height) const
@@ -703,7 +732,7 @@ Q_XCB_EXPORT QDebug operator<<(QDebug debug, const QXcbScreen *screen)
{
const QDebugStateSaver saver(debug);
debug.nospace();
- debug << "QXcbScreen(" << (void *)screen;
+ debug << "QXcbScreen(" << (const void *)screen;
if (screen) {
debug << fixed << qSetRealNumberPrecision(1);
debug << ", name=" << screen->name();
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 53ad413541..3f228465f2 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -58,7 +58,8 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
{
public:
QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen,
- xcb_randr_get_output_info_reply_t *output, const QString &outputName, int number);
+ xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
+ QString outputName, int number);
~QXcbScreen();
QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
@@ -80,11 +81,19 @@ public:
Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_orientation; }
QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; }
void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; }
+ void removeVirtualSibling(QPlatformScreen *s) { m_siblings.removeOne(s); }
+ void addVirtualSibling(QPlatformScreen *s) { ((QXcbScreen *) s)->isPrimary() ? m_siblings.prepend(s) : m_siblings.append(s); }
+
+ void setPrimary(bool primary) { m_primary = primary; }
+ bool isPrimary() const { return m_primary; }
int screenNumber() const { return m_number; }
xcb_screen_t *screen() const { return m_screen; }
xcb_window_t root() const { return m_screen->root; }
+ xcb_randr_output_t output() const { return m_output; }
+ xcb_randr_crtc_t crtc() const { return m_crtc; }
+ xcb_randr_mode_t mode() const { return m_mode; }
xcb_window_t clientLeader() const { return m_clientLeader; }
@@ -98,8 +107,9 @@ public:
QString name() const Q_DECL_OVERRIDE { return m_outputName; }
void handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event);
- void updateGeometry(xcb_timestamp_t timestamp);
- void updateRefreshRate();
+ void updateGeometry(const QRect &geom, uint8_t rotation);
+ void updateGeometry(xcb_timestamp_t timestamp = XCB_TIME_CURRENT_TIME);
+ void updateRefreshRate(xcb_randr_mode_t mode);
void readXResources();
@@ -117,7 +127,12 @@ private:
void sendStartupMessage(const QByteArray &message) const;
xcb_screen_t *m_screen;
+ xcb_randr_output_t m_output;
xcb_randr_crtc_t m_crtc;
+ xcb_randr_mode_t m_mode;
+ bool m_primary;
+ uint8_t m_rotation;
+
QString m_outputName;
QSizeF m_outputSizeMillimeters;
QSizeF m_sizeMillimeters;
diff --git a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
index 33e67a14b1..328b72234a 100644
--- a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
+++ b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp
@@ -125,7 +125,7 @@ static void sm_setProperty(const QString &name, const QString &value)
QByteArray v = value.toUtf8();
SmPropValue prop;
prop.length = v.length();
- prop.value = (SmPointer) v.constData();
+ prop.value = (SmPointer) const_cast<char *>(v.constData());
sm_setProperty(name.toLatin1().data(), SmARRAY8, 1, &prop);
}
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 6d2f5276b3..0dde679a7a 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1372,6 +1372,8 @@ void QXcbWindow::setParent(const QPlatformWindow *parent)
xcb_parent_id = qXcbParent->xcb_window();
m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow;
} else {
+ if (!xcbScreen())
+ return;
xcb_parent_id = xcbScreen()->root();
m_embedded = false;
}