diff options
Diffstat (limited to 'src/plugins/platforms')
89 files changed, 1657 insertions, 763 deletions
diff --git a/src/plugins/platforms/android/androidplatformplugin.cpp b/src/plugins/platforms/android/androidplatformplugin.cpp index ea7a3c397a..245691e79f 100644 --- a/src/plugins/platforms/android/androidplatformplugin.cpp +++ b/src/plugins/platforms/android/androidplatformplugin.cpp @@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE class QAndroidPlatformIntegrationPlugin: public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "android.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "android.json") public: QPlatformIntegration *create(const QString &key, const QStringList ¶mList); }; diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp index 88bc4a653a..5c8406ca03 100644 --- a/src/plugins/platforms/android/qandroidinputcontext.cpp +++ b/src/plugins/platforms/android/qandroidinputcontext.cpp @@ -176,6 +176,8 @@ static jstring getSelectedText(JNIEnv *env, jobject /*thiz*/, jint flags) #ifdef QT_DEBUG_ANDROID_IM_PROTOCOL qDebug() << "@@@ GETSEL" << text; #endif + if (text.isEmpty()) + return 0; return env->NewString(reinterpret_cast<const jchar *>(text.constData()), jsize(text.length())); } diff --git a/src/plugins/platforms/cocoa/main.mm b/src/plugins/platforms/cocoa/main.mm index ed139b98b2..e6c1ed79b2 100644 --- a/src/plugins/platforms/cocoa/main.mm +++ b/src/plugins/platforms/cocoa/main.mm @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE class QCocoaIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "cocoa.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "cocoa.json") public: QPlatformIntegration *create(const QString&, const QStringList&); }; diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h index 48d7efe174..36943a563e 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h @@ -51,6 +51,7 @@ public: virtual ~QCocoaFileDialogHelper(); void exec(); + void execModalForWindow(QWindow *parent); bool defaultNameFilterDisables() const; diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 93ee4e8624..fad3f28053 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -253,17 +253,22 @@ static QString strippedText(QString s) || [self panel:nil shouldShowFilename:filepath]; [self updateProperties]; - QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder(); [mSavePanel setDirectoryURL: [NSURL fileURLWithPath:mCurrentDir]]; [mSavePanel setNameFieldStringValue:selectable ? QCFString::toNSString(info.fileName()) : @""]; NSWindow *nsparent = static_cast<NSWindow *>(qGuiApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parent)); + qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); + QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder(); + [mSavePanel beginSheetModalForWindow:nsparent completionHandler:^(NSInteger result){ - mReturnCode = result; - if (mHelper) - mHelper->QNSOpenSavePanelDelegate_panelClosed(result == NSOKButton); + [[NSApplication sharedApplication] stopModalWithCode:result]; }]; + + mReturnCode = [[NSApplication sharedApplication] runModalForWindow:nsparent]; + QAbstractEventDispatcher::instance()->interrupt(); + if (mHelper) + mHelper->QNSOpenSavePanelDelegate_panelClosed(mReturnCode == NSOKButton); } - (BOOL)isHiddenFile:(NSString *)filename isDir:(BOOL)isDir @@ -705,14 +710,15 @@ void QCocoaFileDialogHelper::createNSOpenSavePanelDelegate() bool QCocoaFileDialogHelper::showCocoaFilePanel(Qt::WindowModality windowModality, QWindow *parent) { + Q_UNUSED(parent) + createNSOpenSavePanelDelegate(); if (!mDelegate) return false; if (windowModality == Qt::NonModal) [mDelegate showModelessPanel]; - else if (windowModality == Qt::WindowModal && parent) - [mDelegate showWindowModalSheet:parent]; - // no need to show a Qt::ApplicationModal dialog here, since it will be done in _q_platformRunNativeAppModalPanel() + // no need to show a Qt::ApplicationModal dialog here, since it will be done in exec; + // Qt::WindowModal will be done in execModalForWindow. return true; } @@ -744,6 +750,14 @@ void QCocoaFileDialogHelper::exec() } +void QCocoaFileDialogHelper::execModalForWindow(QWindow *parent) +{ + if (!parent) + return exec(); + + [mDelegate showWindowModalSheet:parent]; +} + bool QCocoaFileDialogHelper::defaultNameFilterDisables() const { return true; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index b9ffecd3b0..eb231f064e 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -80,7 +80,7 @@ QT_END_NAMESPACE } - (id) initWithMenu:(QCocoaMenu*) m; -- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier; +- (NSMenuItem *)findItem:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier; @end @@ -151,11 +151,20 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); // Change the private unicode keys to the ones used in setting the "Key Equivalents" NSString *characters = qt_mac_removePrivateUnicode([event characters]); - if ([self hasShortcut:menu - forKey:characters - // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ... - forModifiers:([event modifierFlags] & (NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask)) - ]) { + // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ... + const NSUInteger mask = NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask; + if (NSMenuItem *menuItem = [self findItem:menu forKey:characters forModifiers:([event modifierFlags] & mask)]) { + if (!menuItem.target) { + // This item was modified by QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder + // and it looks like we're running a modal session for NSOpenPanel/NSSavePanel. + // QCocoaFileDialogHelper is actually the only place we use this and we run NSOpenPanel modal + // (modal sheet, window modal, application modal). + // Whatever the current first responder is, let's give it a chance + // and do not touch the Qt's focusObject (which is different from some native view + // having a focus inside NSSave/OpenPanel. + return YES; + } + QObject *object = qApp->focusObject(); if (object) { QChar ch; @@ -193,22 +202,23 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); return NO; } -- (BOOL)hasShortcut:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier +- (NSMenuItem *)findItem:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier { for (NSMenuItem *item in [menu itemArray]) { if (![item isEnabled] || [item isHidden] || [item isSeparatorItem]) continue; - if ([item hasSubmenu] - && [self hasShortcut:[item submenu] forKey:key forModifiers:modifier]) - return YES; + if ([item hasSubmenu]) { + if (NSMenuItem *nested = [self findItem:[item submenu] forKey:key forModifiers:modifier]) + return nested; + } NSString *menuKey = [item keyEquivalent]; if (menuKey && NSOrderedSame == [menuKey compare:key] && modifier == [item keyEquivalentModifierMask]) - return YES; + return item; } - return NO; + return nil; } @end diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.h b/src/plugins/platforms/cocoa/qcocoaprintdevice.h index 2133900048..3ac112781f 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.h +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.h @@ -60,13 +60,8 @@ class QCocoaPrintDevice : public QPlatformPrintDevice public: QCocoaPrintDevice(); explicit QCocoaPrintDevice(const QString &id); - QCocoaPrintDevice(const QCocoaPrintDevice &other); virtual ~QCocoaPrintDevice(); - QCocoaPrintDevice *clone(); - - bool operator==(const QCocoaPrintDevice &other) const; - bool isValid() const Q_DECL_OVERRIDE; bool isDefault() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm index b92ec31a11..4d319e149b 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm @@ -96,24 +96,6 @@ QCocoaPrintDevice::QCocoaPrintDevice(const QString &id) } } -QCocoaPrintDevice::QCocoaPrintDevice(const QCocoaPrintDevice &other) - : QPlatformPrintDevice(other), - m_printer(0), - m_session(0), - m_ppd(0) -{ - m_printer = other.m_printer; - PMRetain(m_printer); - m_session = other.m_session; - PMRetain(m_session); - m_macPapers = other.m_macPapers; - foreach (PMPaper paper, m_macPapers.values()) - PMRetain(paper); - openPpdFile(); - m_customMargins = other.m_customMargins; - m_printableMargins = other.m_printableMargins; -} - QCocoaPrintDevice::~QCocoaPrintDevice() { if (m_ppd) @@ -127,16 +109,6 @@ QCocoaPrintDevice::~QCocoaPrintDevice() PMRelease(m_printer); } -QCocoaPrintDevice *QCocoaPrintDevice::clone() -{ - return new QCocoaPrintDevice(*this); -} - -bool QCocoaPrintDevice::operator==(const QCocoaPrintDevice &other) const -{ - return (m_id == other.m_id); -} - bool QCocoaPrintDevice::isValid() const { return m_printer ? true : false; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 8af0a71bc1..fdc8b2d9ad 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -415,7 +415,7 @@ QCocoaWindow::~QCocoaWindow() if (m_isNSWindowChild) { if (m_parentCocoaWindow) m_parentCocoaWindow->removeChildWindow(this); - } else if (parent()) { + } else if ([m_contentView superview]) { [m_contentView removeFromSuperview]; } @@ -435,7 +435,9 @@ QCocoaWindow::~QCocoaWindow() // 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); + if (QCocoaIntegration::instance()) { + QCocoaIntegration::instance()->popupWindowStack()->removeAll(this); + } foreach (QCocoaWindow *child, m_childWindows) { [m_nsWindow removeChildWindow:child->m_nsWindow]; @@ -449,7 +451,13 @@ QCocoaWindow::~QCocoaWindow() QSurfaceFormat QCocoaWindow::format() const { - return window()->requestedFormat(); + QSurfaceFormat format = window()->requestedFormat(); + + // Upgrade the default surface format to include an alpha channel. The default RGB format + // causes Cocoa to spend an unreasonable amount of time converting it to RGBA internally. + if (format == QSurfaceFormat()) + format.setAlphaBufferSize(8); + return format; } void QCocoaWindow::setGeometry(const QRect &rectIn) @@ -688,8 +696,10 @@ void QCocoaWindow::setVisible(bool visible) && [m_nsWindow isKindOfClass:[NSPanel class]]) { [(NSPanel *)m_nsWindow setWorksWhenModal:YES]; if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) { - monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDown handler:^(NSEvent *) { - QWindowSystemInterface::handleMouseEvent(window(), QPointF(-1, -1), QPointF(window()->framePosition() - QPointF(1, 1)), Qt::LeftButton); + monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) { + QPointF localPoint = qt_mac_flipPoint([NSEvent mouseLocation]); + QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint, + cocoaButton2QtButton([e buttonNumber])); }]; } } @@ -789,9 +799,22 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags) if (flags & Qt::FramelessWindowHint) return styleMask; if ((type & Qt::Popup) == Qt::Popup) { - if (!windowIsPopupType(type)) - styleMask = (NSUtilityWindowMask | NSResizableWindowMask | NSClosableWindowMask | - NSMiniaturizableWindowMask | NSTitledWindowMask); + if (!windowIsPopupType(type)) { + styleMask = NSUtilityWindowMask; + if (!(flags & Qt::CustomizeWindowHint)) { + styleMask |= NSResizableWindowMask | NSClosableWindowMask | + NSMiniaturizableWindowMask | NSTitledWindowMask; + } else { + if (flags & Qt::WindowMaximizeButtonHint) + styleMask |= NSResizableWindowMask; + if (flags & Qt::WindowTitleHint) + styleMask |= NSTitledWindowMask; + if (flags & Qt::WindowCloseButtonHint) + styleMask |= NSClosableWindowMask; + if (flags & Qt::WindowMinimizeButtonHint) + styleMask |= NSMiniaturizableWindowMask; + } + } } else { if (type == Qt::Window && !(flags & Qt::CustomizeWindowHint)) { styleMask = (NSResizableWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSTitledWindowMask); @@ -1235,7 +1258,9 @@ QCocoaGLContext *QCocoaWindow::currentContext() const void QCocoaWindow::recreateWindow(const QPlatformWindow *parentWindow) { bool wasNSWindowChild = m_isNSWindowChild; - m_isNSWindowChild = parentWindow && (window()->property("_q_platform_MacUseNSWindow").toBool()); + BOOL requestNSWindowChild = qt_mac_resolveOption(NO, window(), "_q_platform_MacUseNSWindow", + "QT_MAC_USE_NSWINDOW"); + m_isNSWindowChild = parentWindow && requestNSWindowChild; bool needsNSWindow = m_isNSWindowChild || !parentWindow; QCocoaWindow *oldParentCocoaWindow = m_parentCocoaWindow; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index df4ebec88b..c71c9f0680 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1849,41 +1849,9 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin return NO; } -- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender +- (void)updateCursorFromDragResponse:(QPlatformDragQtResponse)response drag:(QCocoaDrag *)drag { - return [self handleDrag : sender]; -} - -- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender -{ - return [self handleDrag : sender]; -} - -// Sends drag update to Qt, return the action -- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender -{ - NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; - QPoint qt_windowPoint(windowPoint.x, windowPoint.y); - Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]); - - QWindow *target = findEventTargetWindow(m_window); - if (!target) - return NSDragOperationNone; - - // update these so selecting move/copy/link works - QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers: [[NSApp currentEvent] modifierFlags]]; - - QPlatformDragQtResponse response(false, Qt::IgnoreAction, QRect()); - if ([sender draggingSource] != nil) { - QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); - response = QWindowSystemInterface::handleDrag(target, nativeDrag->platformDropData(), mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed); - } else { - QCocoaDropData mimeData([sender draggingPasteboard]); - response = QWindowSystemInterface::handleDrag(target, &mimeData, mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed); - } - - QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); - const QPixmap pixmapCursor = nativeDrag->currentDrag()->dragCursor(response.acceptedAction()); + const QPixmap pixmapCursor = drag->currentDrag()->dragCursor(response.acceptedAction()); NSCursor *nativeCursor = nil; if (pixmapCursor.isNull()) { @@ -1923,6 +1891,41 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin )); CGEventPost(kCGHIDEventTap, moveEvent); CFRelease(moveEvent); +} + +- (NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender +{ + return [self handleDrag : sender]; +} + +- (NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender +{ + return [self handleDrag : sender]; +} + +// Sends drag update to Qt, return the action +- (NSDragOperation)handleDrag:(id <NSDraggingInfo>)sender +{ + NSPoint windowPoint = [self convertPoint: [sender draggingLocation] fromView: nil]; + QPoint qt_windowPoint(windowPoint.x, windowPoint.y); + Qt::DropActions qtAllowed = qt_mac_mapNSDragOperations([sender draggingSourceOperationMask]); + + QWindow *target = findEventTargetWindow(m_window); + if (!target) + return NSDragOperationNone; + + // update these so selecting move/copy/link works + QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers: [[NSApp currentEvent] modifierFlags]]; + + QPlatformDragQtResponse response(false, Qt::IgnoreAction, QRect()); + if ([sender draggingSource] != nil) { + QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag(); + response = QWindowSystemInterface::handleDrag(target, nativeDrag->platformDropData(), mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed); + [self updateCursorFromDragResponse:response drag:nativeDrag]; + } else { + QCocoaDropData mimeData([sender draggingPasteboard]); + response = QWindowSystemInterface::handleDrag(target, &mimeData, mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed); + } return qt_mac_mapDropAction(response.acceptedAction()); } diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index a2285d8a4f..cb3e6e2cc5 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -49,7 +49,7 @@ QMacPrintEngine::QMacPrintEngine(QPrinter::PrinterMode mode) : QPaintEngine(*(ne { Q_D(QMacPrintEngine); d->mode = mode; - d->m_printDevice = new QCocoaPrintDevice(QCocoaPrinterSupport().defaultPrintDeviceId()); + d->m_printDevice.reset(new QCocoaPrintDevice(QCocoaPrinterSupport().defaultPrintDeviceId())); d->m_pageLayout.setPageSize(d->m_printDevice->defaultPageSize()); d->initialize(); } @@ -557,7 +557,7 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va id = QCocoaPrinterSupport().defaultPrintDeviceId(); else if (!QCocoaPrinterSupport().availablePrintDeviceIds().contains(id)) break; - d->m_printDevice = new QCocoaPrintDevice(id); + d->m_printDevice.reset(new QCocoaPrintDevice(id)); PMPrinter printer = d->m_printDevice->macPrinter(); PMRetain(printer); PMSessionSetCurrentPMPrinter(d->session(), printer); diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h index 6a795a55d8..494fb5b9d1 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -116,7 +116,7 @@ class QMacPrintEnginePrivate : public QPaintEnginePrivate public: QPrinter::PrinterMode mode; QPrinter::PrinterState state; - QSharedDataPointer<QCocoaPrintDevice> m_printDevice; + QSharedPointer<QCocoaPrintDevice> m_printDevice; QPageLayout m_pageLayout; NSPrintInfo *printInfo; PMResolution resolution; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index d439196dc1..16c05329de 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -358,10 +358,10 @@ public: } else if (path.isRect() && (q->state()->matrix.type() <= QTransform::TxScale)) { const qreal * const points = path.points(); D2D_RECT_F rect = { - points[0], // left - points[1], // top - points[2], // right, - points[5] // bottom + FLOAT(points[0]), // left + FLOAT(points[1]), // top + FLOAT(points[2]), // right, + FLOAT(points[5]) // bottom }; dc()->PushAxisAlignedClip(rect, antialiasMode()); @@ -918,13 +918,13 @@ public: DWRITE_GLYPH_RUN glyphRun = { fontFace, // IDWriteFontFace *fontFace; - fontDef.pixelSize, // FLOAT fontEmSize; - numGlyphs, // UINT32 glyphCount; + FLOAT(fontDef.pixelSize), // FLOAT fontEmSize; + UINT32(numGlyphs), // UINT32 glyphCount; glyphIndices, // const UINT16 *glyphIndices; glyphAdvances, // const FLOAT *glyphAdvances; glyphOffsets, // const DWRITE_GLYPH_OFFSET *glyphOffsets; FALSE, // BOOL isSideways; - rtl ? 1 : 0 // UINT32 bidiLevel; + rtl ? 1u : 0u // UINT32 bidiLevel; }; const bool antiAlias = bool((q->state()->renderHints & QPainter::TextAntialiasing) @@ -1393,8 +1393,8 @@ void QWindowsDirect2DPaintEngine::drawEllipse(const QRectF &r) D2D1_ELLIPSE ellipse = { to_d2d_point_2f(p), - r.width() / 2.0, - r.height() / 2.0 + FLOAT(r.width() / 2.0), + FLOAT(r.height() / 2.0) }; if (d->brush.brush) @@ -1421,8 +1421,8 @@ void QWindowsDirect2DPaintEngine::drawEllipse(const QRect &r) D2D1_ELLIPSE ellipse = { to_d2d_point_2f(p), - r.width() / 2.0, - r.height() / 2.0 + FLOAT(r.width() / 2.0), + FLOAT(r.height() / 2.0) }; if (d->brush.brush) diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp index ab4be67bbe..e4cc163b9e 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformplugin.cpp @@ -41,7 +41,7 @@ QT_BEGIN_NAMESPACE class QWindowsDirect2DIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "direct2d.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "direct2d.json") public: QPlatformIntegration *create(const QString&, const QStringList&); }; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp index e762eab711..ba23526447 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp @@ -163,7 +163,7 @@ void QWindowsDirect2DWindow::present(const QRegion ®ion) const SIZE size = { bounds.width(), bounds.height() }; const POINT ptDst = { bounds.x(), bounds.y() }; const POINT ptSrc = { 0, 0 }; - const BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255.0 * opacity(), AC_SRC_ALPHA }; + const BLENDFUNCTION blend = { AC_SRC_OVER, 0, BYTE(255.0 * opacity()), AC_SRC_ALPHA }; const QRect r = region.boundingRect(); const RECT dirty = { r.left(), r.top(), r.left() + r.width(), r.top() + r.height() }; UPDATELAYEREDWINDOWINFO info = { sizeof(UPDATELAYEREDWINDOWINFO), NULL, diff --git a/src/plugins/platforms/directfb/main.cpp b/src/plugins/platforms/directfb/main.cpp index 3faa7c9a8b..4308a164ae 100644 --- a/src/plugins/platforms/directfb/main.cpp +++ b/src/plugins/platforms/directfb/main.cpp @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE class QDirectFbIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "directfb.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "directfb.json") public: QPlatformIntegration *create(const QString&, const QStringList&); }; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp index cd92c49ff1..fe47c947b4 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -87,8 +88,11 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen) QEglFSKmsCursor::~QEglFSKmsCursor() { - drmModeSetCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0, 0); - drmModeMoveCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0); + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { + QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen); + drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); + drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0); + } gbm_bo_destroy(m_bo); m_bo = Q_NULLPTR; @@ -143,10 +147,15 @@ void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window) gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.byteCount()); uint32_t handle = gbm_bo_get_handle(m_bo).u32; - int status = drmModeSetCursor(m_screen->device()->fd(), m_screen->output().crtc_id, handle, - m_cursorSize.width(), m_cursorSize.height()); - if (status != 0) - qWarning("Could not set cursor: %d", status); + + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { + QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen); + + int status = drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, handle, + m_cursorSize.width(), m_cursorSize.height()); + if (status != 0) + qWarning("Could not set cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), status); + } } #endif // QT_NO_CURSOR @@ -157,12 +166,17 @@ QPoint QEglFSKmsCursor::pos() const void QEglFSKmsCursor::setPos(const QPoint &pos) { - QPoint adjustedPos = pos - m_cursorImage.hotspot(); - int ret = drmModeMoveCursor(m_screen->device()->fd(), m_screen->output().crtc_id, adjustedPos.x(), adjustedPos.y()); - if (ret == 0) { - m_pos = pos; - } else { - qWarning("Failed to move cursor: %d", ret); + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { + QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen); + QPoint origin = kmsScreen->geometry().topLeft(); + QPoint localPos = pos - origin; + QPoint adjustedPos = localPos - m_cursorImage.hotspot(); + + int ret = drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, adjustedPos.x(), adjustedPos.y()); + if (ret == 0) + m_pos = pos; + else + qWarning("Failed to move cursor on screen %s: %d", kmsScreen->name().toLatin1().constData(), ret); } } @@ -176,8 +190,11 @@ void QEglFSKmsCursor::initCursorAtlas() QFile file(QString::fromUtf8(json)); if (!file.open(QFile::ReadOnly)) { - drmModeSetCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0, 0); - drmModeMoveCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0); + Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) { + QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen); + drmModeSetCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0, 0); + drmModeMoveCursor(kmsScreen->device()->fd(), kmsScreen->output().crtc_id, 0, 0); + } m_visible = false; return; } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp index bafe1e3324..18a66e34f5 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -308,6 +309,7 @@ QEglFSKmsDevice::QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QStrin , m_gbm_device(Q_NULLPTR) , m_crtc_allocator(0) , m_connector_allocator(0) + , m_globalCursor(Q_NULLPTR) { } @@ -347,6 +349,10 @@ void QEglFSKmsDevice::close() qt_safe_close(m_dri_fd); m_dri_fd = -1; } + + if (m_globalCursor) + m_globalCursor->deleteLater(); + m_globalCursor = Q_NULLPTR; } void QEglFSKmsDevice::createScreens() @@ -357,6 +363,8 @@ void QEglFSKmsDevice::createScreens() return; } + QEglFSKmsScreen *primaryScreen = Q_NULLPTR; + QList<QPlatformScreen *> siblings; QPoint pos(0, 0); QEglFSIntegration *integration = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration()); @@ -369,12 +377,24 @@ void QEglFSKmsDevice::createScreens() if (screen) { integration->addScreen(screen); pos.rx() += screen->geometry().width(); + siblings << screen; + + if (!primaryScreen) + primaryScreen = screen; } drmModeFreeConnector(connector); } drmModeFreeResources(resources); + + if (!m_integration->separateScreens()) { + Q_FOREACH (QPlatformScreen *screen, siblings) + static_cast<QEglFSKmsScreen *>(screen)->setVirtualSiblings(siblings); + + if (primaryScreen) + m_globalCursor = new QEglFSKmsCursor(primaryScreen); + } } gbm_device *QEglFSKmsDevice::device() const @@ -387,6 +407,11 @@ int QEglFSKmsDevice::fd() const return m_dri_fd; } +QPlatformCursor *QEglFSKmsDevice::globalCursor() const +{ + return m_globalCursor; +} + void QEglFSKmsDevice::handleDrmEvent() { drmEventContext drmEvent = { diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h index 29a1332c9a..23fca934e5 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -34,6 +35,7 @@ #ifndef QEGLFSKMSDEVICE_H #define QEGLFSKMSDEVICE_H +#include "qeglfskmscursor.h" #include "qeglfskmsintegration.h" #include <xf86drm.h> @@ -57,6 +59,8 @@ public: gbm_device *device() const; int fd() const; + QPlatformCursor *globalCursor() const; + void handleDrmEvent(); private: @@ -70,6 +74,8 @@ private: quint32 m_crtc_allocator; quint32 m_connector_allocator; + QEglFSKmsCursor *m_globalCursor; + int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector); QEglFSKmsScreen *screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp index 7bb932cf00..45224ccb87 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -60,6 +61,7 @@ QEglFSKmsIntegration::QEglFSKmsIntegration() : m_device(Q_NULLPTR) , m_hwCursor(true) , m_pbuffers(false) + , m_separateScreens(false) {} void QEglFSKmsIntegration::platformInit() @@ -203,6 +205,11 @@ bool QEglFSKmsIntegration::hwCursor() const return m_hwCursor; } +bool QEglFSKmsIntegration::separateScreens() const +{ + return m_separateScreens; +} + QMap<QString, QVariantMap> QEglFSKmsIntegration::outputSettings() const { return m_outputSettings; @@ -235,6 +242,7 @@ void QEglFSKmsIntegration::loadConfig() 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(); + m_separateScreens = object.value(QStringLiteral("separateScreens")).toBool(m_separateScreens); const QJsonArray outputs = object.value(QStringLiteral("outputs")).toArray(); for (int i = 0; i < outputs.size(); i++) { @@ -254,6 +262,7 @@ void QEglFSKmsIntegration::loadConfig() qCDebug(qLcEglfsKmsDebug) << "Configuration:\n" << "\thwcursor:" << m_hwCursor << "\n" << "\tpbuffers:" << m_pbuffers << "\n" + << "\tseparateScreens:" << m_separateScreens << "\n" << "\toutputs:" << m_outputSettings; } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h index 9a160d2570..edb6906a4b 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -65,6 +66,7 @@ public: bool supportsPBuffers() const Q_DECL_OVERRIDE; bool hwCursor() const; + bool separateScreens() const; QMap<QString, QVariantMap> outputSettings() const; private: @@ -73,6 +75,7 @@ private: QEglFSKmsDevice *m_device; bool m_hwCursor; bool m_pbuffers; + bool m_separateScreens; QString m_devicePath; QMap<QString, QVariantMap> m_outputSettings; }; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp index a27819d1dd..5e49c224a0 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -120,6 +121,7 @@ QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration, , m_cursor(Q_NULLPTR) , m_interruptHandler(new QEglFSKmsInterruptHandler(this)) { + m_siblings << this; } QEglFSKmsScreen::~QEglFSKmsScreen() @@ -185,6 +187,9 @@ QString QEglFSKmsScreen::name() const QPlatformCursor *QEglFSKmsScreen::cursor() const { if (m_integration->hwCursor()) { + if (!m_integration->separateScreens()) + return m_device->globalCursor(); + if (m_cursor.isNull()) { QEglFSKmsScreen *that = const_cast<QEglFSKmsScreen *>(this); that->m_cursor.reset(new QEglFSKmsCursor(that)); diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h index 16521c7fe0..4c1b0d02ad 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h @@ -1,5 +1,6 @@ /**************************************************************************** ** +** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com> ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** @@ -85,6 +86,10 @@ public: qreal refreshRate() const Q_DECL_OVERRIDE; + QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; } + void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; } + + QEglFSKmsIntegration *integration() const { return m_integration; } QEglFSKmsDevice *device() const { return m_device; } gbm_surface *surface() const { return m_gbm_surface; } @@ -110,6 +115,8 @@ private: QPoint m_pos; QScopedPointer<QEglFSKmsCursor> m_cursor; + QList<QPlatformScreen *> m_siblings; + struct FrameBuffer { FrameBuffer() : fb(0) {} uint32_t fb; diff --git a/src/plugins/platforms/eglfs/qeglfsmain.cpp b/src/plugins/platforms/eglfs/qeglfsmain.cpp index 4aae7118ac..89b2f20569 100644 --- a/src/plugins/platforms/eglfs/qeglfsmain.cpp +++ b/src/plugins/platforms/eglfs/qeglfsmain.cpp @@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE class QEglFSIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "eglfs.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "eglfs.json") public: QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 30fdce9fd3..c0d51c94a5 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -35,6 +35,7 @@ #include <qpa/qwindowsysteminterface.h> #include <qpa/qplatformintegration.h> #include <private/qguiapplication_p.h> +#include <QtGui/private/qopenglcontext_p.h> #include <QtGui/QOpenGLContext> #include <QtPlatformSupport/private/qeglplatformcursor_p.h> #include <QtPlatformSupport/private/qeglconvenience_p.h> @@ -106,6 +107,7 @@ void QEglFSWindow::create() if (isRaster()) { QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance()); + context->setShareContext(qt_gl_global_share_context()); context->setFormat(m_format); context->setScreen(window()->screen()); if (!context->create()) diff --git a/src/plugins/platforms/haiku/main.h b/src/plugins/platforms/haiku/main.h index fbf0bee527..9889109c7e 100644 --- a/src/plugins/platforms/haiku/main.h +++ b/src/plugins/platforms/haiku/main.h @@ -38,7 +38,7 @@ QT_BEGIN_NAMESPACE class QHaikuIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "haiku.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "haiku.json") public: QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/ios/plugin.mm b/src/plugins/platforms/ios/plugin.mm index 41fe712f60..e68e1dfd6f 100644 --- a/src/plugins/platforms/ios/plugin.mm +++ b/src/plugins/platforms/ios/plugin.mm @@ -40,7 +40,7 @@ QT_BEGIN_NAMESPACE class QIOSIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "ios.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "ios.json") public: QPlatformIntegration *create(const QString&, const QStringList&); }; diff --git a/src/plugins/platforms/ios/qiosbackingstore.h b/src/plugins/platforms/ios/qiosbackingstore.h index 68c77d9900..5d2ae429f1 100644 --- a/src/plugins/platforms/ios/qiosbackingstore.h +++ b/src/plugins/platforms/ios/qiosbackingstore.h @@ -39,6 +39,8 @@ QT_BEGIN_NAMESPACE class QOpenGLPaintDevice; +class QOpenGLFramebufferObject; +class QOffscreenSurface; class QIOSBackingStore : public QPlatformBackingStore { @@ -49,13 +51,19 @@ public: QPaintDevice *paintDevice(); void beginPaint(const QRegion &); + void endPaint(); void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); void resize(const QSize &size, const QRegion &staticContents); + GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const; + + void makeCurrent(); private: QOpenGLContext *m_context; QOpenGLPaintDevice *m_device; + QOpenGLFramebufferObject *m_fbo; + QOffscreenSurface *m_surface; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosbackingstore.mm b/src/plugins/platforms/ios/qiosbackingstore.mm index acec95b0d3..875d06dc80 100644 --- a/src/plugins/platforms/ios/qiosbackingstore.mm +++ b/src/plugins/platforms/ios/qiosbackingstore.mm @@ -36,41 +36,117 @@ #include <QtGui/QOpenGLContext> #include <QtGui/QOpenGLPaintDevice> +#include <QtGui/QOpenGLFramebufferObject> +#include <QtGui/QOffscreenSurface> +#include <QtGui/private/qwindow_p.h> #include <QtDebug> +class QIOSPaintDevice : public QOpenGLPaintDevice +{ +public: + QIOSPaintDevice(QIOSBackingStore *backingStore) : m_backingStore(backingStore) { } + void ensureActiveTarget() Q_DECL_OVERRIDE; + +private: + QIOSBackingStore *m_backingStore; +}; + +void QIOSPaintDevice::ensureActiveTarget() +{ + m_backingStore->makeCurrent(); +} + QIOSBackingStore::QIOSBackingStore(QWindow *window) : QPlatformBackingStore(window) , m_context(new QOpenGLContext) , m_device(0) + , m_fbo(0) + , m_surface(0) { QSurfaceFormat fmt = window->requestedFormat(); - fmt.setDepthBufferSize(16); - fmt.setStencilBufferSize(8); + // Due to sharing QIOSContext redirects our makeCurrent on window() attempts to + // the global share context. Hence it is essential to have a compatible format. + fmt.setDepthBufferSize(QSurfaceFormat::defaultFormat().depthBufferSize()); + fmt.setStencilBufferSize(QSurfaceFormat::defaultFormat().stencilBufferSize()); + + if (fmt.depthBufferSize() == 0) + qWarning("No depth in default format, expect rendering errors"); - // Needed to prevent QOpenGLContext::makeCurrent() from failing - window->setSurfaceType(QSurface::OpenGLSurface); + if (window->surfaceType() == QSurface::RasterSurface) + window->setSurfaceType(QSurface::OpenGLSurface); m_context->setFormat(fmt); m_context->setScreen(window->screen()); + Q_ASSERT(QOpenGLContext::globalShareContext()); + m_context->setShareContext(QOpenGLContext::globalShareContext()); m_context->create(); } QIOSBackingStore::~QIOSBackingStore() { + delete m_fbo; + delete m_surface; delete m_context; delete m_device; } +void QIOSBackingStore::makeCurrent() +{ + QSurface *surface = m_surface ? m_surface : static_cast<QSurface *>(window()); + if (!m_context->makeCurrent(surface)) + qWarning("QIOSBackingStore: makeCurrent() failed"); + if (m_fbo) + m_fbo->bind(); +} + void QIOSBackingStore::beginPaint(const QRegion &) { - m_context->makeCurrent(window()); + if (qt_window_private(window())->compositing) { + if (!m_fbo) { + delete m_device; + m_device = 0; + } + if (!m_surface) { + m_surface = new QOffscreenSurface; + m_surface->setFormat(m_context->format()); + m_surface->create(); + } + if (!m_context->makeCurrent(m_surface)) + qWarning("QIOSBackingStore: Failed to make offscreen surface current"); + const QSize size = window()->size() * window()->devicePixelRatio(); + if (m_fbo && m_fbo->size() != size) { + delete m_fbo; + m_fbo = 0; + } + if (!m_fbo) + m_fbo = new QOpenGLFramebufferObject(size, QOpenGLFramebufferObject::CombinedDepthStencil); + } else if (m_fbo) { + delete m_fbo; + m_fbo = 0; + delete m_surface; + m_surface = 0; + delete m_device; + m_device = 0; + } + + makeCurrent(); + + if (!m_device) + m_device = new QIOSPaintDevice(this); +} + +void QIOSBackingStore::endPaint() +{ + if (m_fbo) { + m_fbo->release(); + glFlush(); + } } QPaintDevice *QIOSBackingStore::paintDevice() { - if (!m_device) - m_device = new QOpenGLPaintDevice; + Q_ASSERT(m_device); // Keep paint device size and device pixel ratio in sync with window qreal devicePixelRatio = window()->devicePixelRatio(); @@ -82,6 +158,8 @@ QPaintDevice *QIOSBackingStore::paintDevice() void QIOSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { + Q_ASSERT(!qt_window_private(window)->compositing); + Q_UNUSED(region); Q_UNUSED(offset); @@ -111,4 +189,21 @@ void QIOSBackingStore::resize(const QSize &size, const QRegion &staticContents) qWarning() << "QIOSBackingStore needs to have the same size as its window"; } +GLuint QIOSBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const +{ + Q_ASSERT(qt_window_private(window())->compositing); + Q_UNUSED(dirtyRegion); + + if (flags) + *flags = TextureFlip; + + if (!m_fbo) + return 0; + + if (textureSize) + *textureSize = m_fbo->size(); + + return m_fbo->texture(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qioscontext.mm b/src/plugins/platforms/ios/qioscontext.mm index c7541fc51b..fe0ca33c13 100644 --- a/src/plugins/platforms/ios/qioscontext.mm +++ b/src/plugins/platforms/ios/qioscontext.mm @@ -116,7 +116,8 @@ static QString fboStatusString(GLenum status) bool QIOSContext::makeCurrent(QPlatformSurface *surface) { - Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface); + Q_ASSERT(surface && (surface->surface()->surfaceType() == QSurface::OpenGLSurface + || surface->surface()->surfaceType() == QSurface::RasterGLSurface)); [EAGLContext setCurrentContext:m_eaglContext]; @@ -141,7 +142,8 @@ void QIOSContext::doneCurrent() void QIOSContext::swapBuffers(QPlatformSurface *surface) { - Q_ASSERT(surface && surface->surface()->surfaceType() == QSurface::OpenGLSurface); + Q_ASSERT(surface && (surface->surface()->surfaceType() == QSurface::OpenGLSurface + || surface->surface()->surfaceType() == QSurface::RasterGLSurface)); if (surface->surface()->surfaceClass() == QSurface::Offscreen) return; // Nothing to do diff --git a/src/plugins/platforms/ios/qiosfileengineassetslibrary.h b/src/plugins/platforms/ios/qiosfileengineassetslibrary.h index 043e101a21..37bbc7bf23 100644 --- a/src/plugins/platforms/ios/qiosfileengineassetslibrary.h +++ b/src/plugins/platforms/ios/qiosfileengineassetslibrary.h @@ -55,10 +55,17 @@ public: QString fileName(FileName file) const Q_DECL_OVERRIDE; void setFileName(const QString &file) Q_DECL_OVERRIDE; QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const Q_DECL_OVERRIDE; + +#ifndef QT_NO_FILESYSTEMITERATOR + Iterator *beginEntryList(QDir::Filters filters, const QStringList &filterNames) Q_DECL_OVERRIDE; + Iterator *endEntryList() Q_DECL_OVERRIDE; +#endif + void setError(QFile::FileError error, const QString &str) { QAbstractFileEngine::setError(error, str); } private: QString m_fileName; + QString m_assetUrl; qint64 m_offset; mutable QIOSAssetData *m_data; diff --git a/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm b/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm index 73bfc2a87f..44a7901160 100644 --- a/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm +++ b/src/plugins/platforms/ios/qiosfileengineassetslibrary.mm @@ -38,6 +38,145 @@ #include <QtCore/QTimer> #include <QtCore/private/qcoreapplication_p.h> +#include <QtCore/qurl.h> +#include <QtCore/qset.h> +#include <QtCore/qthreadstorage.h> + +static QThreadStorage<QString> g_iteratorCurrentUrl; +static QThreadStorage<QPointer<QIOSAssetData> > g_assetDataCache; + +static const int kBufferSize = 10; +static ALAsset *kNoAsset = 0; + +static void ensureAuthorizationDialogNotBlocked() +{ + if ([ALAssetsLibrary authorizationStatus] != ALAuthorizationStatusNotDetermined) + return; + if (static_cast<QCoreApplicationPrivate *>(QObjectPrivate::get(qApp))->in_exec) + return; + + // Since authorization status has not been determined, the user will be asked + // to authorize the app. But since main has not finished, the dialog will be held + // back until the launch completes. To avoid a dead-lock below, we start an event + // loop to complete the launch. + QEventLoop loop; + QTimer::singleShot(1, &loop, &QEventLoop::quit); + loop.exec(); +} + +// ------------------------------------------------------------------------- + +class QIOSAssetEnumerator +{ +public: + QIOSAssetEnumerator(ALAssetsLibrary *assetsLibrary, ALAssetsGroupType type) + : m_semWriteAsset(dispatch_semaphore_create(kBufferSize)) + , m_semReadAsset(dispatch_semaphore_create(0)) + , m_stop(false) + , m_assetsLibrary([assetsLibrary retain]) + , m_type(type) + , m_buffer(QVector<ALAsset *>(kBufferSize)) + , m_readIndex(0) + , m_writeIndex(0) + , m_nextAssetReady(false) + { + ensureAuthorizationDialogNotBlocked(); + startEnumerate(); + } + + ~QIOSAssetEnumerator() + { + m_stop = true; + + // Flush and autorelease remaining assets in the buffer + while (hasNext()) + next(); + + // Documentation states that we need to balance out calls to 'wait' + // and 'signal'. Since the enumeration function always will be one 'wait' + // ahead, we need to signal m_semProceedToNextAsset one last time. + dispatch_semaphore_signal(m_semWriteAsset); + dispatch_release(m_semReadAsset); + dispatch_release(m_semWriteAsset); + + [m_assetsLibrary autorelease]; + } + + bool hasNext() + { + if (!m_nextAssetReady) { + dispatch_semaphore_wait(m_semReadAsset, DISPATCH_TIME_FOREVER); + m_nextAssetReady = true; + } + return m_buffer[m_readIndex] != kNoAsset; + } + + ALAsset *next() + { + Q_ASSERT(m_nextAssetReady); + Q_ASSERT(m_buffer[m_readIndex]); + + ALAsset *asset = [m_buffer[m_readIndex] autorelease]; + dispatch_semaphore_signal(m_semWriteAsset); + + m_readIndex = (m_readIndex + 1) % kBufferSize; + m_nextAssetReady = false; + return asset; + } + +private: + dispatch_semaphore_t m_semWriteAsset; + dispatch_semaphore_t m_semReadAsset; + std::atomic_bool m_stop; + + ALAssetsLibrary *m_assetsLibrary; + ALAssetsGroupType m_type; + QVector<ALAsset *> m_buffer; + int m_readIndex; + int m_writeIndex; + bool m_nextAssetReady; + + void writeAsset(ALAsset *asset) + { + dispatch_semaphore_wait(m_semWriteAsset, DISPATCH_TIME_FOREVER); + m_buffer[m_writeIndex] = [asset retain]; + dispatch_semaphore_signal(m_semReadAsset); + m_writeIndex = (m_writeIndex + 1) % kBufferSize; + } + + void startEnumerate() + { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ + [m_assetsLibrary enumerateGroupsWithTypes:m_type usingBlock:^(ALAssetsGroup *group, BOOL *stopEnumerate) { + + if (!group) { + writeAsset(kNoAsset); + return; + } + + if (m_stop) { + *stopEnumerate = true; + return; + } + + [group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stopEnumerate) { + Q_UNUSED(index); + if (!asset || ![[asset valueForProperty:ALAssetPropertyType] isEqual:ALAssetTypePhoto]) + return; + + writeAsset(asset); + *stopEnumerate = m_stop; + }]; + } failureBlock:^(NSError *error) { + NSLog(@"QIOSFileEngine: %@", error); + writeAsset(kNoAsset); + }]; + }); + } + +}; + +// ------------------------------------------------------------------------- class QIOSAssetData : public QObject { @@ -47,35 +186,17 @@ public: , m_assetUrl(assetUrl) , m_assetLibrary(0) { - switch ([ALAssetsLibrary authorizationStatus]) { - case ALAuthorizationStatusRestricted: - case ALAuthorizationStatusDenied: - engine->setError(QFile::PermissionsError, QLatin1String("Unauthorized access")); - return; - case ALAuthorizationStatusNotDetermined: - if (!static_cast<QCoreApplicationPrivate *>(QObjectPrivate::get(qApp))->in_exec) { - // Since authorization status has not been determined, the user will be asked - // to authorize the app. But since main has not finished, the dialog will be held - // back until the launch completes. To avoid a dead-lock below, we start an event - // loop to complete the launch. - QEventLoop loop; - QTimer::singleShot(1, &loop, &QEventLoop::quit); - loop.exec(); - } - break; - default: - if (g_currentAssetData) { - // It's a common pattern that QFiles pointing to the same path are created and destroyed - // several times during a single event loop cycle. To avoid loading the same asset - // over and over, we check if the last loaded asset has not been destroyed yet, and try to - // 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_assetUrl == assetUrl) { - m_assetLibrary = [g_currentAssetData->m_assetLibrary retain]; - m_asset = [g_currentAssetData->m_asset retain]; - return; - } + ensureAuthorizationDialogNotBlocked(); + + if (QIOSAssetData *assetData = g_assetDataCache.localData()) { + // It's a common pattern that QFiles pointing to the same path are created and destroyed + // several times during a single event loop cycle. To avoid loading the same asset + // over and over, we check if the last loaded asset has not been destroyed yet, and try to + // reuse its data. + if (assetData->m_assetUrl == assetUrl) { + m_assetLibrary = [assetData->m_assetLibrary retain]; + m_asset = [assetData->m_asset retain]; + return; } } @@ -90,6 +211,26 @@ public: NSURL *url = [NSURL URLWithString:assetUrl.toNSString()]; m_assetLibrary = [[ALAssetsLibrary alloc] init]; [m_assetLibrary assetForURL:url resultBlock:^(ALAsset *asset) { + + if (!asset) { + // When an asset couldn't be loaded, chances are that it belongs to ALAssetsGroupPhotoStream. + // Such assets can be stored in the cloud and might need to be downloaded first. Unfortunately, + // forcing that to happen is hidden behind private APIs ([ALAsset requestDefaultRepresentation]). + // As a work-around, we search for it instead, since that will give us a pointer to the asset. + QIOSAssetEnumerator e(m_assetLibrary, ALAssetsGroupPhotoStream); + while (e.hasNext()) { + ALAsset *a = e.next(); + QString url = QUrl::fromNSURL([a valueForProperty:ALAssetPropertyAssetURL]).toString(); + if (url == assetUrl) { + asset = a; + break; + } + } + } + + if (!asset) + engine->setError(QFile::OpenError, QLatin1String("could not open image")); + m_asset = [asset retain]; dispatch_semaphore_signal(semaphore); } failureBlock:^(NSError *error) { @@ -101,17 +242,15 @@ public: dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); dispatch_release(semaphore); - QMutexLocker lock(&g_mutex); - g_currentAssetData = this; + g_assetDataCache.setLocalData(this); } ~QIOSAssetData() { - QMutexLocker lock(&g_mutex); [m_assetLibrary release]; [m_asset release]; - if (this == g_currentAssetData) - g_currentAssetData = 0; + if (g_assetDataCache.localData() == this) + g_assetDataCache.setLocalData(0); } ALAsset *m_asset; @@ -119,21 +258,67 @@ public: private: QString m_assetUrl; ALAssetsLibrary *m_assetLibrary; +}; + +// ------------------------------------------------------------------------- - static QBasicMutex g_mutex; - static QPointer<QIOSAssetData> g_currentAssetData; +#ifndef QT_NO_FILESYSTEMITERATOR + +class QIOSFileEngineIteratorAssetsLibrary : public QAbstractFileEngineIterator +{ +public: + QIOSAssetEnumerator *m_enumerator; + + QIOSFileEngineIteratorAssetsLibrary( + QDir::Filters filters, const QStringList &nameFilters) + : QAbstractFileEngineIterator(filters, nameFilters) + , m_enumerator(new QIOSAssetEnumerator([[[ALAssetsLibrary alloc] init] autorelease], ALAssetsGroupAll)) + { + } + + ~QIOSFileEngineIteratorAssetsLibrary() + { + delete m_enumerator; + g_iteratorCurrentUrl.setLocalData(QString()); + } + + QString next() Q_DECL_OVERRIDE + { + // Cache the URL that we are about to return, since QDir will immediately create a + // new file engine on the file and ask if it exists. Unless we do this, we end up + // creating a new ALAsset just to verify its existence, which will be especially + // costly for assets belonging to ALAssetsGroupPhotoStream. + ALAsset *asset = m_enumerator->next(); + QString url = QUrl::fromNSURL([asset valueForProperty:ALAssetPropertyAssetURL]).toString(); + g_iteratorCurrentUrl.setLocalData(url); + return url; + } + + bool hasNext() const Q_DECL_OVERRIDE + { + return m_enumerator->hasNext(); + } + + QString currentFileName() const Q_DECL_OVERRIDE + { + return g_iteratorCurrentUrl.localData(); + } + + QFileInfo currentFileInfo() const + { + return QFileInfo(currentFileName()); + } }; -QBasicMutex QIOSAssetData::g_mutex; -QPointer<QIOSAssetData> QIOSAssetData::g_currentAssetData = 0; +#endif // ------------------------------------------------------------------------- QIOSFileEngineAssetsLibrary::QIOSFileEngineAssetsLibrary(const QString &fileName) - : m_fileName(fileName) - , m_offset(0) + : m_offset(0) , m_data(0) { + setFileName(fileName); } QIOSFileEngineAssetsLibrary::~QIOSFileEngineAssetsLibrary() @@ -143,18 +328,8 @@ QIOSFileEngineAssetsLibrary::~QIOSFileEngineAssetsLibrary() ALAsset *QIOSFileEngineAssetsLibrary::loadAsset() const { - 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)); - } - + if (!m_data) + m_data = new QIOSAssetData(m_assetUrl, const_cast<QIOSFileEngineAssetsLibrary *>(this)); return m_data->m_asset; } @@ -179,15 +354,21 @@ bool QIOSFileEngineAssetsLibrary::close() QAbstractFileEngine::FileFlags QIOSFileEngineAssetsLibrary::fileFlags(QAbstractFileEngine::FileFlags type) const { QAbstractFileEngine::FileFlags flags = 0; - if (!loadAsset()) + const bool isDir = (m_assetUrl == QLatin1String("assets-library://")); + const bool exists = isDir || m_assetUrl == g_iteratorCurrentUrl.localData() || loadAsset(); + + if (!exists) return flags; if (type & FlagsMask) flags |= ExistsFlag; - if (type & PermsMask) - flags |= ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm; + if (type & PermsMask) { + ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus]; + if (status != ALAuthorizationStatusRestricted && status != ALAuthorizationStatusDenied) + flags |= ReadOwnerPerm | ReadUserPerm | ReadGroupPerm | ReadOtherPerm; + } if (type & TypesMask) - flags |= FileType; + flags |= isDir ? DirectoryType : FileType; return flags; } @@ -245,11 +426,32 @@ void QIOSFileEngineAssetsLibrary::setFileName(const QString &file) if (m_data) close(); m_fileName = file; + // 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 ensure that m_assetUrl ends up being valid. + int index = file.indexOf(QLatin1String("asset.JPG?")); + if (index == -1) + m_assetUrl = QLatin1String("assets-library://"); + else + m_assetUrl = QLatin1String("assets-library://asset/") + file.mid(index); } QStringList QIOSFileEngineAssetsLibrary::entryList(QDir::Filters filters, const QStringList &filterNames) const { - Q_UNUSED(filters); - Q_UNUSED(filterNames); - return QStringList(); + return QAbstractFileEngine::entryList(filters, filterNames); +} + +#ifndef QT_NO_FILESYSTEMITERATOR + +QAbstractFileEngine::Iterator *QIOSFileEngineAssetsLibrary::beginEntryList( + QDir::Filters filters, const QStringList &filterNames) +{ + return new QIOSFileEngineIteratorAssetsLibrary(filters, filterNames); } + +QAbstractFileEngine::Iterator *QIOSFileEngineAssetsLibrary::endEntryList() +{ + return 0; +} + +#endif diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index 986fef7725..b4050b8f62 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -77,6 +77,15 @@ QIOSIntegration::QIOSIntegration() "'applicationDidFinishLaunching' inside your UIApplication delegate.\n"); } + // The backingstore needs a global share context in order to support composition in + // QPlatformBackingStore. + qApp->setAttribute(Qt::AA_ShareOpenGLContexts, true); + // And that context must match the format used for the backingstore's context. + QSurfaceFormat fmt; + fmt.setDepthBufferSize(16); + fmt.setStencilBufferSize(8); + QSurfaceFormat::setDefaultFormat(fmt); + // Set current directory to app bundle folder QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String])); @@ -137,6 +146,8 @@ bool QIOSIntegration::hasCapability(Capability cap) const return false; case ApplicationState: return true; + case RasterGLSurface: + return true; default: return QPlatformIntegration::hasCapability(cap); } diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm index 777a3c12c5..80fba00ffb 100644 --- a/src/plugins/platforms/ios/qioswindow.mm +++ b/src/plugins/platforms/ios/qioswindow.mm @@ -119,7 +119,8 @@ void QIOSWindow::setVisible(bool visible) } if (visible && shouldAutoActivateWindow()) { - requestActivateWindow(); + if (!window()->property("_q_showWithoutActivating").toBool()) + requestActivateWindow(); } else if (!visible && [m_view isActiveWindow]) { // Our window was active/focus window but now hidden, so relinquish // focus to the next possible window in the stack. @@ -145,6 +146,9 @@ void QIOSWindow::setVisible(bool visible) bool QIOSWindow::shouldAutoActivateWindow() const { + if (![m_view canBecomeFirstResponder]) + return false; + // We don't want to do automatic window activation for popup windows // that are unlikely to contain editable controls (to avoid hiding // the keyboard while the popup is showing) diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 3039b89a1a..c6ef843b9f 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -77,7 +77,7 @@ if (QIOSIntegration::instance()->debugWindowManagement()) { static CGFloat hue = 0.0; CGFloat lastHue = hue; - for (CGFloat diff = 0; diff < 0.1 || diff > 0.9; diff = fabsf(hue - lastHue)) + for (CGFloat diff = 0; diff < 0.1 || diff > 0.9; diff = fabs(hue - lastHue)) hue = drand48(); #define colorWithBrightness(br) \ @@ -194,7 +194,7 @@ - (BOOL)canBecomeFirstResponder { - return YES; + return !(m_qioswindow->window()->flags() & Qt::WindowDoesNotAcceptFocus); } - (BOOL)becomeFirstResponder @@ -280,6 +280,12 @@ // ------------------------------------------------------------------------- +-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event +{ + if (m_qioswindow->window()->flags() & Qt::WindowTransparentForInput) + return NO; + return [super pointInside:point withEvent:event]; +} - (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state { diff --git a/src/plugins/platforms/kms/main.cpp b/src/plugins/platforms/kms/main.cpp index 8683a9c8d1..565ac7a7d4 100644 --- a/src/plugins/platforms/kms/main.cpp +++ b/src/plugins/platforms/kms/main.cpp @@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE class QKmsIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "kms.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "kms.json") public: QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; diff --git a/src/plugins/platforms/linuxfb/main.cpp b/src/plugins/platforms/linuxfb/main.cpp index 046ee913d8..ba70984073 100644 --- a/src/plugins/platforms/linuxfb/main.cpp +++ b/src/plugins/platforms/linuxfb/main.cpp @@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE class QLinuxFbIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "linuxfb.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "linuxfb.json") public: QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; diff --git a/src/plugins/platforms/minimal/main.cpp b/src/plugins/platforms/minimal/main.cpp index 4c746a85f2..98babf6876 100644 --- a/src/plugins/platforms/minimal/main.cpp +++ b/src/plugins/platforms/minimal/main.cpp @@ -40,7 +40,7 @@ QT_BEGIN_NAMESPACE class QMinimalIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "minimal.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "minimal.json") public: QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; diff --git a/src/plugins/platforms/minimalegl/main.cpp b/src/plugins/platforms/minimalegl/main.cpp index 7ee14ae5ff..52ab3ad689 100644 --- a/src/plugins/platforms/minimalegl/main.cpp +++ b/src/plugins/platforms/minimalegl/main.cpp @@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE class QMinimalEglIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "minimalegl.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "minimalegl.json") public: QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; diff --git a/src/plugins/platforms/offscreen/main.cpp b/src/plugins/platforms/offscreen/main.cpp index 64a0586036..363f2afcc3 100644 --- a/src/plugins/platforms/offscreen/main.cpp +++ b/src/plugins/platforms/offscreen/main.cpp @@ -40,7 +40,7 @@ QT_BEGIN_NAMESPACE class QOffscreenIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "offscreen.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "offscreen.json") public: QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; diff --git a/src/plugins/platforms/openwfd/main.cpp b/src/plugins/platforms/openwfd/main.cpp index d28ab945fa..b0403bc533 100644 --- a/src/plugins/platforms/openwfd/main.cpp +++ b/src/plugins/platforms/openwfd/main.cpp @@ -38,7 +38,7 @@ QT_BEGIN_NAMESPACE class QOpenWFDIntegrationPlugin : public QPlatformIntegrationPlugin { - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid) public: QPlatformIntegration *create(const QString&, const QStringList&); }; diff --git a/src/plugins/platforms/qnx/main.h b/src/plugins/platforms/qnx/main.h index 5e69ee3889..955bef471c 100644 --- a/src/plugins/platforms/qnx/main.h +++ b/src/plugins/platforms/qnx/main.h @@ -38,7 +38,7 @@ QT_BEGIN_NAMESPACE class QQnxIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "qnx.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "qnx.json") public: QPlatformIntegration *create(const QString&, const QStringList&); }; diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 99c44c69ef..5ed8d30e67 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -102,7 +102,7 @@ HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitName(/* [retval][out HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][out] */ BSTR *version) { - *version = ::SysAllocString(QT_UNICODE_LITERAL(QT_VERSION_STR)); + *version = ::SysAllocString(TEXT(QT_VERSION_STR)); return S_OK; } diff --git a/src/plugins/platforms/windows/main.cpp b/src/plugins/platforms/windows/main.cpp index 5bdcbef01e..29bb9562e3 100644 --- a/src/plugins/platforms/windows/main.cpp +++ b/src/plugins/platforms/windows/main.cpp @@ -97,7 +97,7 @@ QT_BEGIN_NAMESPACE class QWindowsIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "windows.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "windows.json") public: QPlatformIntegration *create(const QString&, const QStringList&, int &, char **); }; diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 0184877fdd..06c9985cac 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -39,7 +39,6 @@ #include <QtGui/QOpenGLContext> #if defined(QT_OPENGL_ES_2_ANGLE) || defined(QT_OPENGL_DYNAMIC) -# define EGL_EGLEXT_PROTOTYPES # include <QtANGLE/EGL/eglext.h> #endif @@ -137,7 +136,6 @@ bool QWindowsLibEGL::init() eglGetError = RESOLVE((EGLint (EGLAPIENTRY *)(void)), eglGetError); eglGetDisplay = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLNativeDisplayType)), eglGetDisplay); - eglGetPlatformDisplayEXT = RESOLVE((EGLDisplay (EGLAPIENTRY *)(EGLenum platform, void *native_display, const EGLint *attrib_list)), eglGetPlatformDisplayEXT); eglInitialize = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, EGLint *, EGLint *)), eglInitialize); eglTerminate = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay)), eglTerminate); eglChooseConfig = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)), eglChooseConfig); @@ -156,7 +154,15 @@ bool QWindowsLibEGL::init() eglSwapBuffers = RESOLVE((EGLBoolean (EGLAPIENTRY *)(EGLDisplay , EGLSurface)), eglSwapBuffers); eglGetProcAddress = RESOLVE((__eglMustCastToProperFunctionPointerType (EGLAPIENTRY * )(const char *)), eglGetProcAddress); - return eglGetError && eglGetDisplay && eglInitialize; + if (!eglGetError || !eglGetDisplay || !eglInitialize || !eglGetProcAddress) + return false; + + eglGetPlatformDisplayEXT = 0; +#ifdef EGL_ANGLE_platform_angle + eglGetPlatformDisplayEXT = reinterpret_cast<EGLDisplay (EGLAPIENTRY *)(EGLenum, void *, const EGLint *)>(eglGetProcAddress("eglGetPlatformDisplayEXT")); +#endif + + return true; } #if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) @@ -360,7 +366,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: EGLDisplay display = EGL_NO_DISPLAY; EGLint major = 0; EGLint minor = 0; -#ifdef EGL_ANGLE_platform_angle_opengl +#ifdef EGL_ANGLE_platform_angle if (libEGL.eglGetPlatformDisplayEXT && (preferredType & QWindowsOpenGLTester::AngleBackendMask)) { const EGLint anglePlatformAttributes[][5] = { @@ -384,7 +390,7 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester: } } } -#else // EGL_ANGLE_platform_angle_opengl +#else // EGL_ANGLE_platform_angle Q_UNUSED(preferredType) #endif if (display == EGL_NO_DISPLAY) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h index 2b249348c3..d8302c97a7 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.h +++ b/src/plugins/platforms/windows/qwindowseglcontext.h @@ -46,7 +46,6 @@ struct QWindowsLibEGL EGLint (EGLAPIENTRY * eglGetError)(void); EGLDisplay (EGLAPIENTRY * eglGetDisplay)(EGLNativeDisplayType display_id); - EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list); EGLBoolean (EGLAPIENTRY * eglInitialize)(EGLDisplay dpy, EGLint *major, EGLint *minor); EGLBoolean (EGLAPIENTRY * eglTerminate)(EGLDisplay dpy); EGLBoolean (EGLAPIENTRY * eglChooseConfig)(EGLDisplay dpy, const EGLint *attrib_list, @@ -74,6 +73,8 @@ struct QWindowsLibEGL EGLBoolean (EGLAPIENTRY * eglSwapBuffers)(EGLDisplay dpy, EGLSurface surface); __eglMustCastToProperFunctionPointerType (EGLAPIENTRY * eglGetProcAddress)(const char *procname); + EGLDisplay (EGLAPIENTRY * eglGetPlatformDisplayEXT)(EGLenum platform, void *native_display, const EGLint *attrib_list); + private: #if !defined(QT_STATIC) || defined(QT_OPENGL_DYNAMIC) void *resolve(const char *name); diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index 9691156403..6e58c55bbe 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -34,6 +34,7 @@ #include "qwindowsnativeinterface.h" #include "qwindowswindow.h" #include "qwindowscontext.h" +#include "qwindowsfontdatabase.h" #include "qwindowsopenglcontext.h" #include "qwindowsopengltester.h" #include "qwindowsintegration.h" @@ -222,6 +223,11 @@ int QWindowsNativeInterface::registerMimeType(const QString &mimeType) return QWindowsMime::registerMimeType(mimeType); } +QFont QWindowsNativeInterface::logFontToQFont(const void *logFont, int verticalDpi) +{ + return QWindowsFontDatabase::LOGFONT_to_QFont(*reinterpret_cast<const LOGFONT *>(logFont), verticalDpi); +} + QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &function) const { if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier()) diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index be8418b769..97839ae1ae 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -34,6 +34,7 @@ #ifndef QWINDOWSNATIVEINTERFACE_H #define QWINDOWSNATIVEINTERFACE_H +#include <QtGui/qfont.h> #include <QtGui/qpa/qplatformnativeinterface.h> QT_BEGIN_NAMESPACE @@ -77,6 +78,7 @@ public: Q_INVOKABLE void registerWindowsMime(void *mimeIn); Q_INVOKABLE void unregisterWindowsMime(void *mime); Q_INVOKABLE int registerMimeType(const QString &mimeType); + Q_INVOKABLE QFont logFontToQFont(const void *logFont, int verticalDpi); bool asyncExpose() const; void setAsyncExpose(bool value); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 923040fd71..543c08135f 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -438,6 +438,8 @@ QDebug operator<<(QDebug debug, const WindowCreationData &d) // Fix top level window flags in case only the type flags are passed. static inline void fixTopLevelWindowFlags(Qt::WindowFlags &flags) { + // Not supported on Windows, also do correction when it is set. + flags &= ~Qt::WindowFullscreenButtonHint; switch (flags) { case Qt::Window: flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinimizeButtonHint diff --git a/src/plugins/platforms/winrt/main.cpp b/src/plugins/platforms/winrt/main.cpp index 1398c52e96..d1cf08887f 100644 --- a/src/plugins/platforms/winrt/main.cpp +++ b/src/plugins/platforms/winrt/main.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** @@ -40,7 +43,7 @@ QT_BEGIN_NAMESPACE class QWinRTIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "winrt.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "winrt.json") public: QStringList keys() const; diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp index b55551e820..dcf8239538 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.cpp +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h index 69bd3c397c..20b27a3865 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.h +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtcursor.cpp b/src/plugins/platforms/winrt/qwinrtcursor.cpp index 1adb2bb89f..94ce23bd2c 100644 --- a/src/plugins/platforms/winrt/qwinrtcursor.cpp +++ b/src/plugins/platforms/winrt/qwinrtcursor.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** @@ -46,7 +49,7 @@ using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::UI::Core; using namespace ABI::Windows::Foundation; -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class QWinRTCursorPrivate { @@ -155,3 +158,6 @@ QPoint QWinRTCursor::pos() const coreWindow->get_PointerPosition(&point); return QPoint(point.X, point.Y); } + +QT_END_NAMESPACE + diff --git a/src/plugins/platforms/winrt/qwinrtcursor.h b/src/plugins/platforms/winrt/qwinrtcursor.h index 4245faab6f..9c9b9e93ef 100644 --- a/src/plugins/platforms/winrt/qwinrtcursor.h +++ b/src/plugins/platforms/winrt/qwinrtcursor.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** @@ -36,7 +39,7 @@ #include <qpa/qplatformcursor.h> -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class QWinRTCursorPrivate; class QWinRTCursor : public QPlatformCursor @@ -54,4 +57,6 @@ private: Q_DECLARE_PRIVATE(QWinRTCursor) }; +QT_END_NAMESPACE + #endif // QWINRTCURSOR_H diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp index fd90582119..42ffe8f716 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** @@ -33,6 +36,9 @@ #include "qwinrteglcontext.h" +#define EGL_EGLEXT_PROTOTYPES +#include "EGL/eglext.h" + QT_BEGIN_NAMESPACE QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config) @@ -40,6 +46,17 @@ QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGL { } +void QWinRTEGLContext::swapBuffers(QPlatformSurface *surface) +{ +#ifdef Q_OS_WINPHONE + const QSize size = surface->surface()->size(); + eglPostSubBufferNV(eglDisplay(), eglSurfaceForPlatformSurface(surface), + 0, 0, size.width(), size.height()); +#else + eglSwapBuffers(eglDisplay(), eglSurfaceForPlatformSurface(surface)); +#endif +} + EGLSurface QWinRTEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) { if (surface->surface()->surfaceClass() == QSurface::Window) { diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.h b/src/plugins/platforms/winrt/qwinrteglcontext.h index bec9c19089..958d623c4c 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.h +++ b/src/plugins/platforms/winrt/qwinrteglcontext.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** @@ -43,6 +46,7 @@ class QWinRTEGLContext : public QEGLPlatformContext public: explicit QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config); + void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE; QFunctionPointer getProcAddress(const QByteArray &procName) Q_DECL_OVERRIDE; protected: diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp index 7f77b79660..716681c905 100644 --- a/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp +++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrteventdispatcher.h b/src/plugins/platforms/winrt/qwinrteventdispatcher.h index 35e637eba5..ecbdde34bd 100644 --- a/src/plugins/platforms/winrt/qwinrteventdispatcher.h +++ b/src/plugins/platforms/winrt/qwinrteventdispatcher.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp index 417befeb63..e1b2a07d5f 100644 --- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp +++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h index 13abf6e2b8..51b79c84ef 100644 --- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h +++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp index 719bb18dd6..858cb841b9 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp +++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.h b/src/plugins/platforms/winrt/qwinrtfileengine.h index 983338f2e2..86721d8578 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.h +++ b/src/plugins/platforms/winrt/qwinrtfileengine.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** @@ -36,8 +39,6 @@ #include <private/qabstractfileengine_p.h> -QT_BEGIN_NAMESPACE - namespace ABI { namespace Windows { namespace Storage { @@ -46,6 +47,8 @@ namespace ABI { } } +QT_BEGIN_NAMESPACE + class QWinRTFileEngineHandlerPrivate; class QWinRTFileEngineHandler : public QAbstractFileEngineHandler { diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp index 15767c2805..09edea52e7 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** @@ -46,6 +49,71 @@ using namespace Microsoft::WRL; QT_BEGIN_NAMESPACE +// Based on unicode range tables at http://www.microsoft.com/typography/otspec/os2.htm#ur +static QFontDatabase::WritingSystem writingSystemFromUnicodeRange(const DWRITE_UNICODE_RANGE &range) +{ + if (range.first >= 0x0000 && range.last <= 0x007F) + return QFontDatabase::Latin; + if (range.first >= 0x0370 && range.last <= 0x03FF) + return QFontDatabase::Greek; + if (range.first >= 0x0400 && range.last <= 0x04FF) + return QFontDatabase::Cyrillic; + if (range.first >= 0x0530 && range.last <= 0x058F) + return QFontDatabase::Armenian; + if (range.first >= 0x0590 && range.last <= 0x05FF) + return QFontDatabase::Hebrew; + if (range.first >= 0x0600 && range.last <= 0x06FF) + return QFontDatabase::Arabic; + if (range.first >= 0x0700 && range.last <= 0x074F) + return QFontDatabase::Syriac; + if (range.first >= 0x0780 && range.last <= 0x07BF) + return QFontDatabase::Thaana; + if (range.first >= 0x0900 && range.last <= 0x097F) + return QFontDatabase::Devanagari; + if (range.first >= 0x0980 && range.last <= 0x09FF) + return QFontDatabase::Bengali; + if (range.first >= 0x0A00 && range.last <= 0x0A7F) + return QFontDatabase::Gurmukhi; + if (range.first >= 0x0A80 && range.last <= 0x0AFF) + return QFontDatabase::Gujarati; + if (range.first >= 0x0B00 && range.last <= 0x0B7F) + return QFontDatabase::Oriya; + if (range.first >= 0x0B80 && range.last <= 0x0BFF) + return QFontDatabase::Tamil; + if (range.first >= 0x0C00 && range.last <= 0x0C7F) + return QFontDatabase::Telugu; + if (range.first >= 0x0C80 && range.last <= 0x0CFF) + return QFontDatabase::Kannada; + if (range.first >= 0x0D00 && range.last <= 0x0D7F) + return QFontDatabase::Malayalam; + if (range.first >= 0x0D80 && range.last <= 0x0DFF) + return QFontDatabase::Sinhala; + if (range.first >= 0x0E00 && range.last <= 0x0E7F) + return QFontDatabase::Thai; + if (range.first >= 0x0E80 && range.last <= 0x0EFF) + return QFontDatabase::Lao; + if (range.first >= 0x0F00 && range.last <= 0x0FFF) + return QFontDatabase::Tibetan; + if (range.first >= 0x1000 && range.last <= 0x109F) + return QFontDatabase::Myanmar; + if (range.first >= 0x10A0 && range.last <= 0x10FF) + return QFontDatabase::Georgian; + if (range.first >= 0x1780 && range.last <= 0x17FF) + return QFontDatabase::Khmer; + if (range.first >= 0x4E00 && range.last <= 0x9FFF) + return QFontDatabase::SimplifiedChinese; + if (range.first >= 0xAC00 && range.last <= 0xD7AF) + return QFontDatabase::Korean; + if (range.first >= 0x1680 && range.last <= 0x169F) + return QFontDatabase::Ogham; + if (range.first >= 0x16A0 && range.last <= 0x16FF) + return QFontDatabase::Runic; + if (range.first >= 0x07C0 && range.last <= 0x07FF) + return QFontDatabase::Nko; + + return QFontDatabase::Other; +} + QString QWinRTFontDatabase::fontDir() const { QString fontDirectory = QBasicFontDatabase::fontDir(); @@ -260,17 +328,27 @@ void QWinRTFontDatabase::populateFamily(const QString &familyName) const bool fixedPitch = fontFace->IsMonospacedFont(); - quint32 unicodeRange[4]; + // Get writing systems from unicode ranges quint32 actualRangeCount; - hr = fontFace->GetUnicodeRanges( - 2, reinterpret_cast<DWRITE_UNICODE_RANGE *>(unicodeRange), &actualRangeCount); - if (FAILED(hr) && hr != E_NOT_SUFFICIENT_BUFFER) { // Ignore insufficient buffer; we only need 4 indices + hr = fontFace->GetUnicodeRanges(0, nullptr, &actualRangeCount); + Q_ASSERT(hr == E_NOT_SUFFICIENT_BUFFER); + QVector<DWRITE_UNICODE_RANGE> unicodeRanges(actualRangeCount); + hr = fontFace->GetUnicodeRanges(actualRangeCount, unicodeRanges.data(), &actualRangeCount); + if (FAILED(hr)) { qWarning("Unable to get font unicode range: %s", qPrintable(qt_error_string(hr))); continue; } - quint32 codePageRange[2] = { 0, 0 }; - QSupportedWritingSystems writingSystems = - QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); + QSupportedWritingSystems writingSystems; + for (quint32 i = 0; i < actualRangeCount; ++i) { + const QFontDatabase::WritingSystem writingSystem = writingSystemFromUnicodeRange(unicodeRanges.at(i)); + writingSystems.setSupported(writingSystem); + } + if (writingSystems.supported(QFontDatabase::SimplifiedChinese)) { + writingSystems.setSupported(QFontDatabase::TraditionalChinese); + writingSystems.setSupported(QFontDatabase::Japanese); + } + if (writingSystems.supported(QFontDatabase::Latin)) + writingSystems.setSupported(QFontDatabase::Vietnamese); IDWriteFontFile *fontFile; hr = fontFace->GetFiles(&fileCount, &fontFile); diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h index cde81baa44..7b3f402c13 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** @@ -36,12 +39,14 @@ #include <QtPlatformSupport/private/qbasicfontdatabase_p.h> -QT_BEGIN_NAMESPACE - #ifdef QT_WINRT_USE_DWRITE struct IDWriteFontFile; struct IDWriteFontFamily; +#endif +QT_BEGIN_NAMESPACE + +#ifdef QT_WINRT_USE_DWRITE struct FontDescription { quint32 index; diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp index f0de578db6..c94b53ef1c 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.h b/src/plugins/platforms/winrt/qwinrtinputcontext.h index 761908a9cb..ce7fbabf49 100644 --- a/src/plugins/platforms/winrt/qwinrtinputcontext.h +++ b/src/plugins/platforms/winrt/qwinrtinputcontext.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 015ebaadb5..70ee6dbe6a 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index 1ec44cd46a..bbd6c1e41b 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp index c5d3634523..4fc1fea626 100644 --- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp +++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h index fc510fe34e..2f473a05f7 100644 --- a/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h +++ b/src/plugins/platforms/winrt/qwinrtmessagedialoghelper.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index c4512b4d2d..1d36bb31f6 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h index cbef9543a9..d34ce75748 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.h +++ b/src/plugins/platforms/winrt/qwinrtscreen.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtservices.cpp b/src/plugins/platforms/winrt/qwinrtservices.cpp index 1faa3945a7..cb04f670d2 100644 --- a/src/plugins/platforms/winrt/qwinrtservices.cpp +++ b/src/plugins/platforms/winrt/qwinrtservices.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtservices.h b/src/plugins/platforms/winrt/qwinrtservices.h index 0262a2ab83..585eb2f010 100644 --- a/src/plugins/platforms/winrt/qwinrtservices.h +++ b/src/plugins/platforms/winrt/qwinrtservices.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** @@ -37,7 +40,7 @@ #include <qpa/qplatformservices.h> #include <QtCore/QScopedPointer> -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE class QWinRTServicesPrivate; class QWinRTServices : public QPlatformServices @@ -54,4 +57,6 @@ private: Q_DECLARE_PRIVATE(QWinRTServices) }; +QT_END_NAMESPACE + #endif // QWINRTSERVICES_H diff --git a/src/plugins/platforms/winrt/qwinrttheme.cpp b/src/plugins/platforms/winrt/qwinrttheme.cpp index c42368cc87..a0fa2798a8 100644 --- a/src/plugins/platforms/winrt/qwinrttheme.cpp +++ b/src/plugins/platforms/winrt/qwinrttheme.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrttheme.h b/src/plugins/platforms/winrt/qwinrttheme.h index 73dcd6cdf4..2e159cbd55 100644 --- a/src/plugins/platforms/winrt/qwinrttheme.h +++ b/src/plugins/platforms/winrt/qwinrttheme.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp index b96f4255c2..adc5dfb776 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.cpp +++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h index eee95d6bd3..3cfe346ab2 100644 --- a/src/plugins/platforms/winrt/qwinrtwindow.h +++ b/src/plugins/platforms/winrt/qwinrtwindow.h @@ -5,7 +5,7 @@ ** ** This file is part of the plugins of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL3$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the @@ -16,16 +16,19 @@ ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. ** ** $QT_END_LICENSE$ ** diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro b/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro index 29b6d1d2f7..9de0476810 100644 --- a/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro +++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs -contains(QT_CONFIG, egl):contains(QT_CONFIG, egl_x11) { +contains(QT_CONFIG, egl): contains(QT_CONFIG, egl_x11): contains(QT_CONFIG, opengl) { SUBDIRS += xcb_egl } diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h index c71c668f31..74c117582a 100644 --- a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h @@ -57,7 +57,9 @@ public: virtual bool handleXcbEvent(xcb_generic_event_t *event, uint responseType); virtual QXcbWindow *createWindow(QWindow *window) const = 0; +#ifndef QT_NO_OPENGL virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const = 0; +#endif virtual QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const = 0; virtual QXcbNativeInterfaceHandler *nativeInterfaceHandler() const { return Q_NULLPTR; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 5d32eb7614..78282d1415 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -70,7 +70,6 @@ #endif #if defined(XCB_USE_XINPUT2) -#include <X11/extensions/XInput2.h> #include <X11/extensions/XI2proto.h> #endif @@ -457,6 +456,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , m_focusWindow(0) , m_systemTrayTracker(0) , m_glIntegration(Q_NULLPTR) + , m_xiGrab(false) { #ifdef XCB_USE_XLIB Display *dpy = XOpenDisplay(m_displayName.constData()); @@ -909,7 +909,7 @@ static Qt::MouseButtons translateMouseButtons(int s) return ret; } -static Qt::MouseButton translateMouseButton(xcb_button_t s) +Qt::MouseButton QXcbConnection::translateMouseButton(xcb_button_t s) { switch (s) { case 1: return Qt::LeftButton; @@ -944,39 +944,6 @@ static Qt::MouseButton translateMouseButton(xcb_button_t s) } } -void QXcbConnection::handleButtonPress(xcb_generic_event_t *ev) -{ - xcb_button_press_event_t *event = (xcb_button_press_event_t *)ev; - - // the event explicitly contains the state of the three first buttons, - // the rest we need to manage ourselves - m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state); - m_buttons |= translateMouseButton(event->detail); - qCDebug(lcQpaXInput, "xcb: pressed mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons)); -} - -void QXcbConnection::handleButtonRelease(xcb_generic_event_t *ev) -{ - xcb_button_release_event_t *event = (xcb_button_release_event_t *)ev; - - // the event explicitly contains the state of the three first buttons, - // the rest we need to manage ourselves - m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state); - m_buttons &= ~translateMouseButton(event->detail); - qCDebug(lcQpaXInput, "xcb: released mouse button %d, button state %X", event->detail, static_cast<unsigned int>(m_buttons)); -} - -void QXcbConnection::handleMotionNotify(xcb_generic_event_t *ev) -{ - xcb_motion_notify_event_t *event = (xcb_motion_notify_event_t *)ev; - - m_buttons = (m_buttons & ~0x7) | translateMouseButtons(event->state); -#ifdef Q_XCB_DEBUG - qCDebug(lcQpaXInput, "xcb: moved mouse to %4d, %4d; button state %X", - event->event_x, event->event_y, static_cast<unsigned int>(m_buttons)); -#endif -} - #ifndef QT_NO_XKB namespace { typedef union { @@ -1018,18 +985,35 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) switch (response_type) { case XCB_EXPOSE: HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); - case XCB_BUTTON_PRESS: - m_keyboard->updateXKBStateFromCore(((xcb_button_press_event_t *)event)->state); - handleButtonPress(event); + + // press/release/motion is only delivered here when XI 2.2+ is _not_ in use + case XCB_BUTTON_PRESS: { + xcb_button_press_event_t *ev = (xcb_button_press_event_t *)event; + m_keyboard->updateXKBStateFromCore(ev->state); + // the event explicitly contains the state of the three first buttons, + // the rest we need to manage ourselves + m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state); + m_buttons |= translateMouseButton(ev->detail); + qCDebug(lcQpaXInput, "legacy mouse press, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons)); HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); - case XCB_BUTTON_RELEASE: - m_keyboard->updateXKBStateFromCore(((xcb_button_release_event_t *)event)->state); - handleButtonRelease(event); + } + case XCB_BUTTON_RELEASE: { + xcb_button_release_event_t *ev = (xcb_button_release_event_t *)event; + m_keyboard->updateXKBStateFromCore(ev->state); + m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state); + m_buttons &= ~translateMouseButton(ev->detail); + qCDebug(lcQpaXInput, "legacy mouse release, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons)); HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); - case XCB_MOTION_NOTIFY: - m_keyboard->updateXKBStateFromCore(((xcb_motion_notify_event_t *)event)->state); - handleMotionNotify(event); + } + case XCB_MOTION_NOTIFY: { + xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event; + m_keyboard->updateXKBStateFromCore(ev->state); + m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state); + qCDebug(lcQpaXInput, "legacy mouse move %d,%d button %d state %X", ev->event_x, ev->event_y, + ev->detail, static_cast<unsigned int>(m_buttons)); HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); + } + case XCB_CONFIGURE_NOTIFY: HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); case XCB_MAP_NOTIFY: @@ -1090,6 +1074,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) break; #if defined(XCB_USE_XINPUT2) case XCB_GE_GENERIC: + // Here the windowEventListener is invoked from xi2HandleEvent() if (m_xi2Enabled) xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event)); break; @@ -1931,6 +1916,12 @@ void QXcbConnection::initializeXKB() #endif } +bool QXcbConnection::xi2MouseEvents() const +{ + static bool mouseViaXI2 = !qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE"); + return mouseViaXI2; +} + #if defined(XCB_USE_XINPUT2) static int xi2ValuatorOffset(unsigned char *maskPtr, int maskLen, int number) { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 466492ce42..0191b0e1ef 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -69,7 +69,8 @@ #endif #endif struct XInput2TouchDeviceData; -#endif +#endif // XCB_USE_XINPUT2 + struct xcb_randr_get_output_info_reply_t; //#define Q_XCB_DEBUG @@ -347,6 +348,7 @@ public: virtual void handleFocusInEvent(const xcb_focus_in_event_t *) {} virtual void handleFocusOutEvent(const xcb_focus_out_event_t *) {} virtual void handlePropertyNotifyEvent(const xcb_property_notify_event_t *) {} + virtual void handleXIMouseEvent(xcb_ge_event_t *) {} virtual QXcbWindow *toWindow() { return 0; } }; @@ -413,14 +415,14 @@ public: void xi2Select(xcb_window_t window); #endif #ifdef XCB_USE_XINPUT21 - bool isUsingXInput21() const { return m_xi2Enabled && m_xi2Minor >= 1; } + bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; } #else - bool isUsingXInput21() const { return false; } + bool isAtLeastXI21() const { return false; } #endif #ifdef XCB_USE_XINPUT22 - bool isUsingXInput22() const { return m_xi2Enabled && m_xi2Minor >= 2; } + bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; } #else - bool isUsingXInput22() const { return false; } + bool isAtLeastXI22() const { return false; } #endif void sync(); @@ -457,7 +459,9 @@ public: xcb_timestamp_t getTimestamp(); + void setButton(Qt::MouseButton button, bool down) { if (down) m_buttons |= button; else m_buttons &= ~button; } Qt::MouseButtons buttons() const { return m_buttons; } + Qt::MouseButton translateMouseButton(xcb_button_t s); QXcbWindow *focusWindow() const { return m_focusWindow; } void setFocusWindow(QXcbWindow *); @@ -479,12 +483,19 @@ public: void handleEnterEvent(const xcb_enter_notify_event_t *); #endif +#ifdef XCB_USE_XINPUT22 + bool xi2SetMouseGrabEnabled(xcb_window_t w, bool grab); +#endif + Qt::MouseButton xiToQtMouseButton(uint32_t b); + QXcbEventReader *eventReader() const { return m_reader; } bool canGrab() const { return m_canGrabServer; } QXcbGlIntegration *glIntegration() const { return m_glIntegration; } + bool xi2MouseEvents() const; + protected: bool event(QEvent *e) Q_DECL_OVERRIDE; @@ -512,9 +523,6 @@ private: 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); bool m_xi2Enabled; int m_xi2Minor; @@ -527,6 +535,9 @@ private: void xi2HandleHierachyEvent(void *event); void xi2HandleDeviceChangedEvent(void *event); int m_xiOpCode, m_xiEventBase, m_xiErrorBase; +#ifdef XCB_USE_XINPUT22 + void xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow); +#endif // XCB_USE_XINPUT22 #ifndef QT_NO_TABLETEVENT struct TabletData { TabletData() : deviceId(0), pointerType(QTabletEvent::UnknownPointer), @@ -546,10 +557,10 @@ private: }; QHash<int, ValuatorClassInfo> valuatorInfo; }; - bool xi2HandleTabletEvent(void *event, TabletData *tabletData); + bool xi2HandleTabletEvent(void *event, TabletData *tabletData, QXcbWindowEventListener *eventListener); void xi2ReportTabletEvent(TabletData &tabletData, void *event); QVector<TabletData> m_tabletData; -#endif +#endif // !QT_NO_TABLETEVENT struct ScrollingDevice { ScrollingDevice() : deviceId(0), verticalIndex(0), horizontalIndex(0), orientations(0), legacyOrientations(0) { } int deviceId; @@ -562,9 +573,7 @@ private: void updateScrollingDevice(ScrollingDevice& scrollingDevice, int num_classes, void *classes); void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice); QHash<int, ScrollingDevice> m_scrollingDevices; -#endif // XCB_USE_XINPUT2 -#if defined(XCB_USE_XINPUT2) static bool xi2GetValuatorValueIfSet(void *event, int valuatorNum, double *value); static bool xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event, int opCode); #endif @@ -636,6 +645,7 @@ private: QByteArray m_startupId; QXcbSystemTrayTracker *m_systemTrayTracker; QXcbGlIntegration *m_glIntegration; + bool m_xiGrab; friend class QXcbEventReader; }; diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index d1b3ead11c..c7784ddb48 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -43,7 +43,6 @@ #include <X11/extensions/XInput2.h> #include <X11/extensions/XI2proto.h> -#define FINGER_MAX_WIDTH_MM 10 struct XInput2TouchDeviceData { XInput2TouchDeviceData() @@ -175,9 +174,11 @@ void QXcbConnection::xi2SetupDevices() case XIKeyClass: qCDebug(lcQpaXInputDevices) << " it's a keyboard"; break; +#ifdef XCB_USE_XINPUT22 case XITouchClass: // will be handled in deviceForId() break; +#endif default: qCDebug(lcQpaXInputDevices) << " has class" << devices[i].classes[c]->type; break; @@ -274,34 +275,37 @@ void QXcbConnection::xi2Select(xcb_window_t window) unsigned char *xiBitMask = reinterpret_cast<unsigned char *>(&bitMask); #ifdef XCB_USE_XINPUT22 - if (isUsingXInput22()) { + if (isAtLeastXI22()) { bitMask |= XI_TouchBeginMask; bitMask |= XI_TouchUpdateMask; bitMask |= XI_TouchEndMask; + bitMask |= XI_PropertyEventMask; // for tablets + if (xi2MouseEvents()) { + // We want both mouse and touch through XI2 if touch is supported (>= 2.2). + // The plain xcb press and motion events will not be delivered after this. + bitMask |= XI_ButtonPressMask; + bitMask |= XI_ButtonReleaseMask; + bitMask |= XI_MotionMask; + qCDebug(lcQpaXInput, "XInput 2.2: Selecting press/release/motion events in addition to touch"); + } XIEventMask mask; mask.mask_len = sizeof(bitMask); mask.mask = xiBitMask; - if (!m_touchDevices.isEmpty()) { - // If we select for touch events on the master pointer, XInput2 - // will not synthesize mouse events. This means Qt must do it, - // which is also preferable, since Qt can control better when - // to do so. - mask.deviceid = XIAllMasterDevices; - Status result = XISelectEvents(xDisplay, window, &mask, 1); - if (result != Success) - qCDebug(lcQpaXInput, "XInput 2.2: failed to select touch events, window %x, result %d", window, result); - } + // When xi2MouseEvents() is true (the default), pointer emulation for touch and tablet + // events will get disabled. This is preferable for touch, as Qt Quick handles touch events + // directly while for others QtGui synthesizes mouse events, not so much for tablets. For + // the latter we will synthesize the events ourselves. + mask.deviceid = XIAllMasterDevices; + Status result = XISelectEvents(xDisplay, window, &mask, 1); + if (result != Success) + qCDebug(lcQpaXInput, "XInput 2.2: failed to select pointer/touch events, window %x, result %d", window, result); } #endif // XCB_USE_XINPUT22 + const bool pointerSelected = isAtLeastXI22() && xi2MouseEvents(); QSet<int> tabletDevices; #ifndef QT_NO_TABLETEVENT - // For each tablet, select some additional event types. - // Press, motion, etc. events must never be selected for _all_ devices - // as that would render the standard XCB_MOTION_NOTIFY and - // similar handlers useless and we have no intention to infect - // all the pure xcb code with Xlib-based XI2. - if (!m_tabletData.isEmpty()) { + if (!m_tabletData.isEmpty() && !pointerSelected) { unsigned int tabletBitMask; unsigned char *xiTabletBitMask = reinterpret_cast<unsigned char *>(&tabletBitMask); QVector<XIEventMask> xiEventMask(m_tabletData.count()); @@ -322,7 +326,8 @@ void QXcbConnection::xi2Select(xcb_window_t window) #ifdef XCB_USE_XINPUT21 // Enable each scroll device - if (!m_scrollingDevices.isEmpty()) { + if (!m_scrollingDevices.isEmpty() && !pointerSelected) { + // Only when XI2 mouse events are not enabled, otherwise motion and release are selected already. QVector<XIEventMask> xiEventMask(m_scrollingDevices.size()); unsigned int scrollBitMask; unsigned char *xiScrollBitMask = reinterpret_cast<unsigned char *>(&scrollBitMask); @@ -359,8 +364,8 @@ void QXcbConnection::xi2Select(xcb_window_t window) XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id) { XInput2TouchDeviceData *dev = Q_NULLPTR; - QHash<int, XInput2TouchDeviceData*>::const_iterator devIt = m_touchDevices.find(id); - if ( devIt != m_touchDevices.end() ) { + QHash<int, XInput2TouchDeviceData*>::const_iterator devIt = m_touchDevices.constFind(id); + if (devIt != m_touchDevices.cend()) { dev = devIt.value(); } else { int nrDevices = 0; @@ -424,7 +429,7 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id) dev->size.width() > 10000 || dev->size.height() > 10000) dev->size = QSizeF(130, 110); } - if (!isUsingXInput22() || type == QTouchDevice::TouchPad) + if (!isAtLeastXI22() || type == QTouchDevice::TouchPad) caps |= QTouchDevice::MouseEmulation; if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) { @@ -446,9 +451,9 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id) } #if defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT) -static qreal fixed1616ToReal(FP1616 val) +static inline qreal fixed1616ToReal(FP1616 val) { - return (qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF; + return qreal(val) / 0x10000; } #endif // defined(XCB_USE_XINPUT21) || !defined(QT_NO_TABLETEVENT) @@ -467,163 +472,280 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event) { if (xi2PrepareXIGenericDeviceEvent(event, m_xiOpCode)) { xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event); + int sourceDeviceId = xiEvent->deviceid; // may be the master id + xXIDeviceEvent *xiDeviceEvent = 0; + QXcbWindowEventListener *eventListener = 0; - if (xiEvent->evtype == XI_HierarchyChanged) { + switch (xiEvent->evtype) { + case XI_ButtonPress: + case XI_ButtonRelease: + case XI_Motion: + case XI_TouchBegin: + case XI_TouchUpdate: + case XI_TouchEnd: + { + xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event); + eventListener = windowEventListenerFromId(xiDeviceEvent->event); + if (eventListener) { + long result = 0; + if (eventListener->handleGenericEvent(reinterpret_cast<xcb_generic_event_t *>(event), &result)) + return; + } + sourceDeviceId = xiDeviceEvent->sourceid; // use the actual device id instead of the master + break; + } + case XI_HierarchyChanged: xi2HandleHierachyEvent(xiEvent); return; - } - if (xiEvent->evtype == XI_DeviceChanged) { + case XI_DeviceChanged: xi2HandleDeviceChangedEvent(xiEvent); return; + default: + break; } #ifndef QT_NO_TABLETEVENT for (int i = 0; i < m_tabletData.count(); ++i) { - if (m_tabletData.at(i).deviceId == xiEvent->deviceid) { - if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i])) + if (m_tabletData.at(i).deviceId == sourceDeviceId) { + if (xi2HandleTabletEvent(xiEvent, &m_tabletData[i], eventListener)) return; } } #endif // QT_NO_TABLETEVENT #ifdef XCB_USE_XINPUT21 - QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(xiEvent->deviceid); + QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(sourceDeviceId); if (device != m_scrollingDevices.end()) xi2HandleScrollEvent(xiEvent, device.value()); #endif // XCB_USE_XINPUT21 #ifdef XCB_USE_XINPUT22 - if (xiEvent->evtype == XI_TouchBegin || xiEvent->evtype == XI_TouchUpdate || xiEvent->evtype == XI_TouchEnd) { - xXIDeviceEvent* xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(event); - if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) - qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f", - event->event_type, xiEvent->sequenceNumber, xiDeviceEvent->detail, - fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), - fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y) ); - - if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) { - XInput2TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid); - Q_ASSERT(dev); - const bool firstTouch = m_touchPoints.isEmpty(); - if (xiEvent->evtype == XI_TouchBegin) { - QWindowSystemInterface::TouchPoint tp; - tp.id = xiDeviceEvent->detail % INT_MAX; - tp.state = Qt::TouchPointPressed; - tp.pressure = -1.0; - m_touchPoints[tp.id] = tp; - } - QWindowSystemInterface::TouchPoint &touchPoint = m_touchPoints[xiDeviceEvent->detail]; - qreal x = fixed1616ToReal(xiDeviceEvent->root_x); - qreal y = fixed1616ToReal(xiDeviceEvent->root_y); - qreal nx = -1.0, ny = -1.0, w = 0.0, h = 0.0; - QXcbScreen* screen = m_screens.at(0); - for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) { - XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i]; - if (classinfo->type == XIValuatorClass) { - XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo); - int n = vci->number; - double value; - if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value)) - continue; - if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) - qCDebug(lcQpaXInput, " valuator %20s value %lf from range %lf -> %lf", - atomName(vci->label).constData(), value, vci->min, vci->max ); - if (vci->label == atom(QXcbAtom::RelX)) { - nx = valuatorNormalized(value, vci); - } else if (vci->label == atom(QXcbAtom::RelY)) { - ny = valuatorNormalized(value, vci); - } else if (vci->label == atom(QXcbAtom::AbsX)) { - nx = valuatorNormalized(value, vci); - } else if (vci->label == atom(QXcbAtom::AbsY)) { - ny = valuatorNormalized(value, vci); - } else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) { - nx = valuatorNormalized(value, vci); - } else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) { - ny = valuatorNormalized(value, vci); - } else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) { - // Convert the value within its range as a fraction of a finger's max (contact patch) - // width in mm, and from there to pixels depending on screen resolution - w = valuatorNormalized(value, vci) * FINGER_MAX_WIDTH_MM * - screen->geometry().width() / screen->physicalSize().width(); - } else if (vci->label == atom(QXcbAtom::AbsMTTouchMinor)) { - h = valuatorNormalized(value, vci) * FINGER_MAX_WIDTH_MM * - screen->geometry().height() / screen->physicalSize().height(); - } else if (vci->label == atom(QXcbAtom::AbsMTPressure) || - vci->label == atom(QXcbAtom::AbsPressure)) { - touchPoint.pressure = valuatorNormalized(value, vci); - } - } - } - // If any value was not updated, use the last-known value. - if (nx == -1.0) { - x = touchPoint.area.center().x(); - nx = x / screen->geometry().width(); - } - if (ny == -1.0) { - y = touchPoint.area.center().y(); - ny = y / screen->geometry().height(); - } - if (xiEvent->evtype != XI_TouchEnd) { - if (w == 0.0) - w = touchPoint.area.width(); - if (h == 0.0) - h = touchPoint.area.height(); - } - - switch (xiEvent->evtype) { - case XI_TouchBegin: - if (firstTouch) { - dev->firstPressedPosition = QPointF(x, y); - dev->firstPressedNormalPosition = QPointF(nx, ny); - } - dev->pointPressedPosition.insert(touchPoint.id, QPointF(x, y)); - break; - case XI_TouchUpdate: - if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) { - qreal dx = (nx - dev->firstPressedNormalPosition.x()) * - dev->size.width() * screen->geometry().width() / screen->physicalSize().width(); - qreal dy = (ny - dev->firstPressedNormalPosition.y()) * - dev->size.height() * screen->geometry().height() / screen->physicalSize().height(); - x = dev->firstPressedPosition.x() + dx; - y = dev->firstPressedPosition.y() + dy; - touchPoint.state = Qt::TouchPointMoved; - } else if (touchPoint.area.center() != QPoint(x, y)) { - touchPoint.state = Qt::TouchPointMoved; - dev->pointPressedPosition[touchPoint.id] = QPointF(x, y); - } - break; - case XI_TouchEnd: - touchPoint.state = Qt::TouchPointReleased; - if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) { - qreal dx = (nx - dev->firstPressedNormalPosition.x()) * - dev->size.width() * screen->geometry().width() / screen->physicalSize().width(); - qreal dy = (ny - dev->firstPressedNormalPosition.y()) * - dev->size.width() * screen->geometry().width() / screen->physicalSize().width(); - x = dev->firstPressedPosition.x() + dx; - y = dev->firstPressedPosition.y() + dy; - } - dev->pointPressedPosition.remove(touchPoint.id); - } - touchPoint.area = QRectF(x - w/2, y - h/2, w, h); - touchPoint.normalPosition = QPointF(nx, ny); + if (xiDeviceEvent) { + switch (xiDeviceEvent->evtype) { + case XI_ButtonPress: + case XI_ButtonRelease: + case XI_Motion: + if (xi2MouseEvents() && eventListener) + eventListener->handleXIMouseEvent(event); + break; + case XI_TouchBegin: + case XI_TouchUpdate: + case XI_TouchEnd: if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) - qCDebug(lcQpaXInput) << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition << - " area " << touchPoint.area << " pressure " << touchPoint.pressure; - QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiEvent->time, dev->qtTouchDevice, m_touchPoints.values()); - if (touchPoint.state == Qt::TouchPointReleased) - // If a touchpoint was released, we can forget it, because the ID won't be reused. - m_touchPoints.remove(touchPoint.id); - else - // Make sure that we don't send TouchPointPressed/Moved in more than one QTouchEvent - // with this touch point if the next XI2 event is about a different touch point. - touchPoint.state = Qt::TouchPointStationary; + qCDebug(lcQpaXInput, "XI2 touch event type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f on window %x", + event->event_type, xiDeviceEvent->sequenceNumber, xiDeviceEvent->detail, + fixed1616ToReal(xiDeviceEvent->event_x), fixed1616ToReal(xiDeviceEvent->event_y), + fixed1616ToReal(xiDeviceEvent->root_x), fixed1616ToReal(xiDeviceEvent->root_y),xiDeviceEvent->event); + if (QXcbWindow *platformWindow = platformWindowFromId(xiDeviceEvent->event)) + xi2ProcessTouch(xiDeviceEvent, platformWindow); + break; } } #endif // XCB_USE_XINPUT22 } } +#ifdef XCB_USE_XINPUT22 +void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow) +{ + xXIDeviceEvent *xiDeviceEvent = static_cast<xXIDeviceEvent *>(xiDevEvent); + XInput2TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid); + Q_ASSERT(dev); + const bool firstTouch = m_touchPoints.isEmpty(); + if (xiDeviceEvent->evtype == XI_TouchBegin) { + QWindowSystemInterface::TouchPoint tp; + tp.id = xiDeviceEvent->detail % INT_MAX; + tp.state = Qt::TouchPointPressed; + tp.pressure = -1.0; + m_touchPoints[tp.id] = tp; + } + QWindowSystemInterface::TouchPoint &touchPoint = m_touchPoints[xiDeviceEvent->detail]; + qreal x = fixed1616ToReal(xiDeviceEvent->root_x); + qreal y = fixed1616ToReal(xiDeviceEvent->root_y); + qreal nx = -1.0, ny = -1.0, d = 0.0; + QXcbScreen* screen = m_screens.at(0); + for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) { + XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i]; + if (classinfo->type == XIValuatorClass) { + XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo); + int n = vci->number; + double value; + if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value)) + continue; + if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) + qCDebug(lcQpaXInput, " valuator %20s value %lf from range %lf -> %lf", + atomName(vci->label).constData(), value, vci->min, vci->max ); + if (vci->label == atom(QXcbAtom::RelX)) { + nx = valuatorNormalized(value, vci); + } else if (vci->label == atom(QXcbAtom::RelY)) { + ny = valuatorNormalized(value, vci); + } else if (vci->label == atom(QXcbAtom::AbsX)) { + nx = valuatorNormalized(value, vci); + } else if (vci->label == atom(QXcbAtom::AbsY)) { + ny = valuatorNormalized(value, vci); + } else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) { + nx = valuatorNormalized(value, vci); + } else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) { + ny = valuatorNormalized(value, vci); + } else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) { + d = valuatorNormalized(value, vci) * screen->geometry().width(); + } else if (vci->label == atom(QXcbAtom::AbsMTPressure) || + vci->label == atom(QXcbAtom::AbsPressure)) { + touchPoint.pressure = valuatorNormalized(value, vci); + } + } + } + // If any value was not updated, use the last-known value. + if (nx == -1.0) { + x = touchPoint.area.center().x(); + nx = x / screen->geometry().width(); + } + if (ny == -1.0) { + y = touchPoint.area.center().y(); + ny = y / screen->geometry().height(); + } + if (xiDeviceEvent->evtype != XI_TouchEnd) { + if (d == 0.0) + d = touchPoint.area.width(); + } + + switch (xiDeviceEvent->evtype) { + case XI_TouchBegin: + if (firstTouch) { + dev->firstPressedPosition = QPointF(x, y); + dev->firstPressedNormalPosition = QPointF(nx, ny); + } + dev->pointPressedPosition.insert(touchPoint.id, QPointF(x, y)); + + // Touches must be accepted when we are grabbing touch events. Otherwise the entire sequence + // will get replayed when the grab ends. + if (m_xiGrab) { + // XIAllowTouchEvents deadlocks with libXi < 1.7.4 (this has nothing to do with the XI2 versions like 2.2) + // http://lists.x.org/archives/xorg-devel/2014-July/043059.html +#ifndef LIBXI_MAJOR + static bool allowTouchWarningShown = false; + if (!allowTouchWarningShown) { + allowTouchWarningShown = true; + qWarning("Skipping XIAllowTouchEvents() because it was not possible to detect libXi version at build time." + " Minimum libXi version required is 1.7.4." + " Expect issues with touch behavior."); + } +#elif LIBXI_MAJOR == 1 && (LIBXI_MINOR < 7 || (LIBXI_MINOR == 7 && LIBXI_PATCH < 4)) + static bool allowTouchWarningShown = false; + if (!allowTouchWarningShown) { + allowTouchWarningShown = true; + qWarning("Skipping XIAllowTouchEvents() due to not having libXi >= 1.7.4." + " libXi version at build time was %d.%d.%d." + " Expect issues with touch behavior.", LIBXI_MAJOR, LIBXI_MINOR, LIBXI_PATCH); + } +#else + XIAllowTouchEvents(static_cast<Display *>(m_xlib_display), xiDeviceEvent->deviceid, + xiDeviceEvent->detail, xiDeviceEvent->event, XIAcceptTouch); +#endif + } + break; + case XI_TouchUpdate: + if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) { + qreal dx = (nx - dev->firstPressedNormalPosition.x()) * + dev->size.width() * screen->geometry().width() / screen->physicalSize().width(); + qreal dy = (ny - dev->firstPressedNormalPosition.y()) * + dev->size.height() * screen->geometry().height() / screen->physicalSize().height(); + x = dev->firstPressedPosition.x() + dx; + y = dev->firstPressedPosition.y() + dy; + touchPoint.state = Qt::TouchPointMoved; + } else if (touchPoint.area.center() != QPoint(x, y)) { + touchPoint.state = Qt::TouchPointMoved; + dev->pointPressedPosition[touchPoint.id] = QPointF(x, y); + } + break; + case XI_TouchEnd: + touchPoint.state = Qt::TouchPointReleased; + if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad && dev->pointPressedPosition.value(touchPoint.id) == QPointF(x, y)) { + qreal dx = (nx - dev->firstPressedNormalPosition.x()) * + dev->size.width() * screen->geometry().width() / screen->physicalSize().width(); + qreal dy = (ny - dev->firstPressedNormalPosition.y()) * + dev->size.width() * screen->geometry().width() / screen->physicalSize().width(); + x = dev->firstPressedPosition.x() + dx; + y = dev->firstPressedPosition.y() + dy; + } + dev->pointPressedPosition.remove(touchPoint.id); + } + touchPoint.area = QRectF(x - d/2, y - d/2, d, d); + touchPoint.normalPosition = QPointF(nx, ny); + + if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) + qCDebug(lcQpaXInput) << " touchpoint " << touchPoint.id << " state " << touchPoint.state << " pos norm " << touchPoint.normalPosition << + " area " << touchPoint.area << " pressure " << touchPoint.pressure; + QWindowSystemInterface::handleTouchEvent(platformWindow->window(), xiDeviceEvent->time, dev->qtTouchDevice, m_touchPoints.values()); + if (touchPoint.state == Qt::TouchPointReleased) + // If a touchpoint was released, we can forget it, because the ID won't be reused. + m_touchPoints.remove(touchPoint.id); + else + // Make sure that we don't send TouchPointPressed/Moved in more than one QTouchEvent + // with this touch point if the next XI2 event is about a different touch point. + touchPoint.state = Qt::TouchPointStationary; +} + +bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab) +{ + if (grab && !canGrab()) + return false; + + int num_devices = 0; + Display *xDisplay = static_cast<Display *>(xlib_display()); + XIDeviceInfo *info = XIQueryDevice(xDisplay, XIAllMasterDevices, &num_devices); + if (!info) + return false; + + XIEventMask evmask; + unsigned char mask[XIMaskLen(XI_LASTEVENT)]; + evmask.mask = mask; + evmask.mask_len = sizeof(mask); + memset(mask, 0, sizeof(mask)); + evmask.deviceid = XIAllMasterDevices; + + XISetMask(mask, XI_ButtonPress); + XISetMask(mask, XI_ButtonRelease); + XISetMask(mask, XI_Motion); + XISetMask(mask, XI_TouchBegin); + XISetMask(mask, XI_TouchUpdate); + XISetMask(mask, XI_TouchEnd); + + bool grabbed = true; + for (int i = 0; i < num_devices; i++) { + int id = info[i].deviceid, n = 0; + XIDeviceInfo *deviceInfo = XIQueryDevice(xDisplay, id, &n); + if (deviceInfo) { + const bool grabbable = deviceInfo->use != XIMasterKeyboard; + XIFreeDeviceInfo(deviceInfo); + if (!grabbable) + continue; + } + if (!grab) { + Status result = XIUngrabDevice(xDisplay, id, CurrentTime); + if (result != Success) { + grabbed = false; + qCDebug(lcQpaXInput, "XInput 2.2: failed to ungrab events for device %d (result %d)", id, result); + } + } else { + Status result = XIGrabDevice(xDisplay, id, w, CurrentTime, None, XIGrabModeAsync, + XIGrabModeAsync, False, &evmask); + if (result != Success) { + grabbed = false; + qCDebug(lcQpaXInput, "XInput 2.2: failed to grab events for device %d on window %x (result %d)", id, w, result); + } + } + } + + XIFreeDeviceInfo(info); + + m_xiGrab = grabbed; + + return grabbed; +} +#endif // XCB_USE_XINPUT22 + void QXcbConnection::xi2HandleHierachyEvent(void *event) { xXIHierarchyEvent *xiEvent = reinterpret_cast<xXIHierarchyEvent *>(event); @@ -792,7 +914,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin #endif // XCB_USE_XINPUT21 } -static Qt::MouseButton xiToQtMouseButton(uint32_t b) { +Qt::MouseButton QXcbConnection::xiToQtMouseButton(uint32_t b) +{ switch (b) { case 1: return Qt::LeftButton; case 2: return Qt::MiddleButton; @@ -839,20 +962,29 @@ static QTabletEvent::TabletDevice toolIdToTabletDevice(quint32 toolId) { } #ifndef QT_NO_TABLETEVENT -bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData) +bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData, QXcbWindowEventListener *eventListener) { bool handled = true; Display *xDisplay = static_cast<Display *>(m_xlib_display); xXIGenericDeviceEvent *xiEvent = static_cast<xXIGenericDeviceEvent *>(event); + xXIDeviceEvent *xiDeviceEvent = reinterpret_cast<xXIDeviceEvent *>(xiEvent); + +#ifdef XCB_USE_XINPUT22 + // Synthesize mouse events since otherwise there are no mouse events from + // the pen on the XI 2.2+ path. + if (xi2MouseEvents() && eventListener) + eventListener->handleXIMouseEvent(reinterpret_cast<xcb_ge_event_t *>(event)); +#endif + switch (xiEvent->evtype) { case XI_ButtonPress: { - Qt::MouseButton b = xiToQtMouseButton(reinterpret_cast<xXIDeviceEvent *>(event)->detail); + Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail); tabletData->buttons |= b; xi2ReportTabletEvent(*tabletData, xiEvent); break; } case XI_ButtonRelease: { - Qt::MouseButton b = xiToQtMouseButton(reinterpret_cast<xXIDeviceEvent *>(event)->detail); + Qt::MouseButton b = xiToQtMouseButton(xiDeviceEvent->detail); tabletData->buttons ^= b; xi2ReportTabletEvent(*tabletData, xiEvent); break; @@ -915,7 +1047,7 @@ bool QXcbConnection::xi2HandleTabletEvent(void *event, TabletData *tabletData) // TODO maybe have a hash of tabletData->deviceId to device data so we can // look up the tablet name here, and distinguish multiple tablets qCDebug(lcQpaXInput, "XI2 proximity change on tablet %d (USB %x): last tool: %x id %x current tool: %x id %x TabletDevice %d", - ev->deviceid, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID], + tabletData->deviceId, ptr[_WACSER_USB_ID], ptr[_WACSER_LAST_TOOL_SERIAL], ptr[_WACSER_LAST_TOOL_ID], ptr[_WACSER_TOOL_SERIAL], ptr[_WACSER_TOOL_ID], tabletData->tool); } XFree(data); @@ -979,7 +1111,7 @@ void QXcbConnection::xi2ReportTabletEvent(TabletData &tabletData, void *event) if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled())) qCDebug(lcQpaXInput, "XI2 event on tablet %d with tool %d type %d seq %d detail %d pos %6.1f, %6.1f root pos %6.1f, %6.1f buttons 0x%x pressure %4.2lf tilt %d, %d rotation %6.2lf", - ev->deviceid, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail, + tabletData.deviceId, tabletData.tool, ev->evtype, ev->sequenceNumber, ev->detail, fixed1616ToReal(ev->event_x), fixed1616ToReal(ev->event_y), fixed1616ToReal(ev->root_x), fixed1616ToReal(ev->root_y), (int)tabletData.buttons, pressure, xTilt, yTilt, rotation); diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp index 5a7c2cef83..f3bffd2998 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -47,6 +47,12 @@ #include <stdio.h> #include <X11/keysym.h> +#ifdef XCB_USE_XINPUT22 +#include <X11/extensions/XI2proto.h> +#undef KeyPress +#undef KeyRelease +#endif + #ifndef XK_ISO_Left_Tab #define XK_ISO_Left_Tab 0xFE20 #endif @@ -791,6 +797,31 @@ void QXcbKeyboard::updateXKBStateFromCore(quint16 state) } } +void QXcbKeyboard::updateXKBStateFromXI(void *modInfo, void *groupInfo) +{ +#ifdef XCB_USE_XINPUT22 + if (m_config && !connection()->hasXKB()) { + xXIModifierInfo *mods = static_cast<xXIModifierInfo *>(modInfo); + xXIGroupInfo *group = static_cast<xXIGroupInfo *>(groupInfo); + const xkb_state_component newState = xkb_state_update_mask(xkb_state, + mods->base_mods, + mods->latched_mods, + mods->locked_mods, + group->base_group, + group->latched_group, + group->locked_group); + + if ((newState & XKB_STATE_LAYOUT_EFFECTIVE) == XKB_STATE_LAYOUT_EFFECTIVE) { + //qWarning("TODO: Support KeyboardLayoutChange on QPA (QTBUG-27681)"); + } + } +#else + Q_UNUSED(modInfo); + Q_UNUSED(groupInfo); + Q_ASSERT(false); // this can't be +#endif +} + quint32 QXcbKeyboard::xkbModMask(quint16 state) { quint32 xkb_mask = 0; diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h index 2281674e2f..d2e37d624c 100644 --- a/src/plugins/platforms/xcb/qxcbkeyboard.h +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -68,6 +68,7 @@ public: void updateXKBMods(); quint32 xkbModMask(quint16 state); void updateXKBStateFromCore(quint16 state); + void updateXKBStateFromXI(void *modInfo, void *groupInfo); #ifndef QT_NO_XKB // when XKEYBOARD is present on the X server int coreDeviceId() const { return core_device_id; } diff --git a/src/plugins/platforms/xcb/qxcbmain.cpp b/src/plugins/platforms/xcb/qxcbmain.cpp index 0c3e8b5cd3..4a07b66491 100644 --- a/src/plugins/platforms/xcb/qxcbmain.cpp +++ b/src/plugins/platforms/xcb/qxcbmain.cpp @@ -39,7 +39,7 @@ QT_BEGIN_NAMESPACE class QXcbIntegrationPlugin : public QPlatformIntegrationPlugin { Q_OBJECT - Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "xcb.json") + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "xcb.json") public: QPlatformIntegration *create(const QString&, const QStringList&, int &, char **) Q_DECL_OVERRIDE; }; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 076cc1aa80..d2da137591 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -97,6 +97,7 @@ #if defined(XCB_USE_XINPUT2) #include <X11/extensions/XInput2.h> +#include <X11/extensions/XI2proto.h> #endif #define XCOORD_MAX 16383 @@ -2167,16 +2168,17 @@ void QXcbWindow::handleUnmapNotifyEvent(const xcb_unmap_notify_event_t *event) } } -void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) +void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y, + int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp) { - const bool isWheel = event->detail >= 4 && event->detail <= 7; + const bool isWheel = detail >= 4 && detail <= 7; if (!isWheel && window() != QGuiApplication::focusWindow()) { QWindow *w = static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver(); if (!(w->flags() & Qt::WindowDoesNotAcceptFocus)) w->requestActivate(); } - updateNetWmUserTime(event->time); + updateNetWmUserTime(timestamp); if (m_embedded) { if (window() != QGuiApplication::focusWindow()) { @@ -2187,53 +2189,125 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) } } const int dpr = int(devicePixelRatio()); - QPoint local(event->event_x/dpr, event->event_y/dpr); - QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y)); - - Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); + QPoint local(event_x / dpr, event_y / dpr); + QPoint global = xcbScreen()->mapFromNative(QPoint(root_x, root_y)); if (isWheel) { - if (!connection()->isUsingXInput21()) { + if (!connection()->isAtLeastXI21()) { // Logic borrowed from qapplication_x11.cpp - int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1); - bool hor = (((event->detail == 4 || event->detail == 5) + int delta = 120 * ((detail == 4 || detail == 6) ? 1 : -1); + bool hor = (((detail == 4 || detail == 5) && (modifiers & Qt::AltModifier)) - || (event->detail == 6 || event->detail == 7)); + || (detail == 6 || detail == 7)); - QWindowSystemInterface::handleWheelEvent(window(), event->time, + QWindowSystemInterface::handleWheelEvent(window(), timestamp, local, global, delta, hor ? Qt::Horizontal : Qt::Vertical, modifiers); } return; } - handleMouseEvent(event->time, local, global, modifiers); + handleMouseEvent(timestamp, local, global, modifiers); } -void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event) +void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x, int root_y, + int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp) { const int dpr = int(devicePixelRatio()); - QPoint local(event->event_x/dpr, event->event_y/dpr); - QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y)); - Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); + QPoint local(event_x / dpr, event_y / dpr); + QPoint global = xcbScreen()->mapFromNative(QPoint(root_x, root_y)); - if (event->detail >= 4 && event->detail <= 7) { + if (detail >= 4 && detail <= 7) { // mouse wheel, handled in handleButtonPressEvent() return; } - handleMouseEvent(event->time, local, global, modifiers); + handleMouseEvent(timestamp, local, global, modifiers); } -void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) +void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y, + Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp) { - const int dpr = int(devicePixelRatio()); - QPoint local(event->event_x/dpr, event->event_y/dpr); if (!xcbScreen()) return; - QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y)); + const int dpr = int(devicePixelRatio()); + QPoint local(event_x / dpr, event_y / dpr); + QPoint global = xcbScreen()->mapFromNative(QPoint(root_x, root_y)); + handleMouseEvent(timestamp, local, global, modifiers); +} + +// Handlers for plain xcb events. Used only when XI 2.2 or newer is not available. +void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) +{ Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); + handleButtonPressEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->detail, + modifiers, event->time); +} - handleMouseEvent(event->time, local, global, modifiers); +void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event) +{ + Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); + handleButtonReleaseEvent(event->event_x, event->event_y, event->root_x, event->root_y, event->detail, + modifiers, event->time); +} + +void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) +{ + Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state); + handleMotionNotifyEvent(event->event_x, event->event_y, event->root_x, event->root_y, modifiers, event->time); +} + +#ifdef XCB_USE_XINPUT22 +static inline int fixed1616ToInt(FP1616 val) +{ + return int((qreal(val >> 16)) + (val & 0xFFFF) / (qreal)0xFFFF); +} +#endif + +// With XI 2.2+ press/release/motion comes here instead of the above handlers. +void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event) +{ +#ifdef XCB_USE_XINPUT22 + QXcbConnection *conn = connection(); + xXIDeviceEvent *ev = reinterpret_cast<xXIDeviceEvent *>(event); + const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective_mods); + const int event_x = fixed1616ToInt(ev->event_x); + const int event_y = fixed1616ToInt(ev->event_y); + const int root_x = fixed1616ToInt(ev->root_x); + const int root_y = fixed1616ToInt(ev->root_y); + + conn->keyboard()->updateXKBStateFromXI(&ev->mods, &ev->group); + + const Qt::MouseButton button = conn->xiToQtMouseButton(ev->detail); + + if (ev->buttons_len > 0) { + unsigned char *buttonMask = (unsigned char *) &ev[1]; + for (int i = 1; i <= 15; ++i) + conn->setButton(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i)); + } + + switch (ev->evtype) { + case XI_ButtonPress: + qCDebug(lcQpaXInput, "XI2 mouse press, button %d", button); + conn->setButton(button, true); + handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time); + break; + case XI_ButtonRelease: + qCDebug(lcQpaXInput, "XI2 mouse release, button %d", button); + conn->setButton(button, false); + handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time); + break; + case XI_Motion: + qCDebug(lcQpaXInput, "XI2 mouse motion %d,%d", event_x, event_y); + handleMotionNotifyEvent(event_x, event_y, root_x, root_y, modifiers, ev->time); + break; + default: + qWarning() << "Unrecognized XI2 mouse event" << ev->evtype; + break; + } +#else + Q_UNUSED(event); + Q_ASSERT(false); // this can't be +#endif } QXcbWindow *QXcbWindow::toWindow() { return this; } @@ -2417,6 +2491,10 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab) bool QXcbWindow::setMouseGrabEnabled(bool grab) { +#ifdef XCB_USE_XINPUT22 + if (connection()->xi2MouseEvents()) + return connection()->xi2SetMouseGrabEnabled(m_window, grab); +#endif if (grab && !connection()->canGrab()) return false; diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 52e8ac1459..07019223c8 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -132,6 +132,7 @@ public: void handleFocusInEvent(const xcb_focus_in_event_t *event) Q_DECL_OVERRIDE; void handleFocusOutEvent(const xcb_focus_out_event_t *event) Q_DECL_OVERRIDE; void handlePropertyNotifyEvent(const xcb_property_notify_event_t *event) Q_DECL_OVERRIDE; + void handleXIMouseEvent(xcb_ge_event_t *) Q_DECL_OVERRIDE; QXcbWindow *toWindow() Q_DECL_OVERRIDE; @@ -210,6 +211,15 @@ protected: void doFocusIn(); void doFocusOut(); + void handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y, + int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp); + + void handleButtonReleaseEvent(int event_x, int event_y, int root_x, int root_y, + int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp); + + void handleMotionNotifyEvent(int event_x, int event_y, int root_x, int root_y, + Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp); + xcb_window_t m_window; QXcbScreen *m_xcbScreen; diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index fd704dd904..12987567ff 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -59,6 +59,11 @@ contains(QT_CONFIG, xcb-xlib) { DEFINES += XCB_USE_XINPUT2 SOURCES += qxcbconnection_xi2.cpp LIBS += -lXi + !isEmpty(QMAKE_LIBXI_VERSION_MAJOR) { + DEFINES += LIBXI_MAJOR=$$QMAKE_LIBXI_VERSION_MAJOR \ + LIBXI_MINOR=$$QMAKE_LIBXI_VERSION_MINOR \ + LIBXI_PATCH=$$QMAKE_LIBXI_VERSION_PATCH + } } } |