diff options
Diffstat (limited to 'src/plugins/platforms')
39 files changed, 351 insertions, 138 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index fd0f4529cc..7f022da4c3 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -67,7 +67,7 @@ QPaintDevice *QCocoaBackingStore::paintDevice() #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle()); - if (cocoaWindow && cocoaWindow->m_contentView) { + if (cocoaWindow && cocoaWindow->m_contentView && [cocoaWindow->m_contentView window]) { scaleFactor = int([[cocoaWindow->m_contentView window] backingScaleFactor]); } } diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index d8bb72dd45..faea417f0f 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -251,6 +251,7 @@ static QString strippedText(QString s) [mSavePanel setDirectoryURL:selectable ? [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath())] : [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.path())]]; + [mSavePanel setNameFieldStringValue:selectable ? QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.fileName()) : nil]; // Call processEvents in case the event dispatcher has been interrupted, and needs to do // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will @@ -277,6 +278,7 @@ static QString strippedText(QString s) [self updateProperties]; [mSavePanel setDirectoryURL:selectable ? [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.filePath())] : [NSURL fileURLWithPath:QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.path())]]; + [mSavePanel setNameFieldStringValue:selectable ? QT_PREPEND_NAMESPACE(QCFString::toNSString)(info.fileName()) : nil]; NSWindow *nsparent = static_cast<NSWindow *>(qGuiApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parent)); [mSavePanel beginSheetModalForWindow:nsparent completionHandler:^(NSInteger result){ diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 51beaa97f5..c801d9d926 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -156,8 +156,9 @@ public: } }; -CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); +CGContextRef qt_mac_cg_context(QPaintDevice *pdev); CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy); +QImage qt_mac_toQImage(CGImageRef image); QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 08024b7bc6..dc43666bb6 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -714,35 +714,38 @@ QString qt_mac_removeAmpersandEscapes(QString s) \warning This function is only available on Mac OS X. \warning This function is duplicated in qmacstyle_mac.mm */ -CGContextRef qt_mac_cg_context(const QPaintDevice *pdev) +CGContextRef qt_mac_cg_context(QPaintDevice *pdev) { - if (pdev->devType() == QInternal::Pixmap) { - const QPixmap *pm = static_cast<const QPixmap*>(pdev); - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); - uint flags = kCGImageAlphaPremultipliedFirst; - flags |= kCGBitmapByteOrder32Host; - CGContextRef ret = 0; + // In Qt 5, QWidget and QPixmap (and QImage) paint devices are all QImages under the hood. + QImage *image = 0; + if (pdev->devType() == QInternal::Image) { + image = static_cast<QImage *>(pdev); + } else if (pdev->devType() == QInternal::Pixmap) { + const QPixmap *pm = static_cast<const QPixmap*>(pdev); QPlatformPixmap *data = const_cast<QPixmap *>(pm)->data_ptr().data(); if (data && data->classId() == QPlatformPixmap::RasterClass) { - QImage *image = data->buffer(); - ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(), - 8, image->bytesPerLine(), colorspace, flags); + image = data->buffer(); } else { qDebug() << "qt_mac_cg_context: Unsupported pixmap class"; } - - CGContextTranslateCTM(ret, 0, pm->height()); - CGContextScaleCTM(ret, 1, -1); - return ret; } else if (pdev->devType() == QInternal::Widget) { - //CGContextRef ret = static_cast<CGContextRef>(static_cast<const QWidget *>(pdev)->macCGHandle()); - ///CGContextRetain(ret); - //return ret; + // TODO test: image = static_cast<QImage *>(static_cast<const QWidget *>(pdev)->backingStore()->paintDevice()); qDebug() << "qt_mac_cg_context: not implemented: Widget class"; - return 0; } - return 0; + + if (!image) + return 0; // Context type not supported. + + CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); + uint flags = kCGImageAlphaPremultipliedFirst; + flags |= kCGBitmapByteOrder32Host; + CGContextRef ret = 0; + ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(), + 8, image->bytesPerLine(), colorspace, flags); + CGContextTranslateCTM(ret, 0, image->height()); + CGContextScaleCTM(ret, 1, -1); + return ret; } CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy) @@ -836,4 +839,18 @@ CGImageRef qt_mac_toCGImage(const QImage &qImage, bool isMask, uchar **dataCopy) return cgImage; } +QImage qt_mac_toQImage(CGImageRef image) +{ + const size_t w = CGImageGetWidth(image), + h = CGImageGetHeight(image); + QImage ret(w, h, QImage::Format_ARGB32_Premultiplied); + ret.fill(Qt::transparent); + CGRect rect = CGRectMake(0, 0, w, h); + CGContextRef ctx = qt_mac_cg_context(&ret); + qt_mac_drawCGImage(ctx, &rect, image); + CGContextRelease(ctx); + return ret; +} + + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 34e8fb61e2..9506f86238 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -42,6 +42,8 @@ #ifndef QCOCOANATIVEINTERFACE_H #define QCOCOANATIVEINTERFACE_H +#include <ApplicationServices/ApplicationServices.h> + #include <qpa/qplatformnativeinterface.h> QT_BEGIN_NAMESPACE @@ -49,6 +51,7 @@ QT_BEGIN_NAMESPACE class QWidget; class QPlatformPrinterSupport; class QPrintEngine; +class QPlatformMenu; class QCocoaNativeInterface : public QPlatformNativeInterface { @@ -92,6 +95,13 @@ private: static void addToMimeList(void *macPasteboardMime); static void removeFromMimeList(void *macPasteboardMime); static void registerDraggedTypes(const QStringList &types); + + // Dock menu support + static void setDockMenu(QPlatformMenu *platformMenu); + + // QImage <-> CGImage conversion functions + static CGImageRef qImageToCGImage(const QImage &image); + static QImage cgImageToQImage(CGImageRef image); }; #endif // QCOCOANATIVEINTERFACE_H diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 08084b5200..bd3a909137 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -42,8 +42,10 @@ #include "qcocoanativeinterface.h" #include "qcocoaglcontext.h" #include "qcocoawindow.h" +#include "qcocoamenu.h" #include "qcocoamenubar.h" #include "qmacmime.h" +#include "qcocoahelpers.h" #include <qbytearray.h> #include <qwindow.h> @@ -60,6 +62,8 @@ #include <qpa/qplatformprintersupport.h> #endif +#include <Cocoa/Cocoa.h> + QT_BEGIN_NAMESPACE QCocoaNativeInterface::QCocoaNativeInterface() @@ -103,6 +107,12 @@ QPlatformNativeInterface::NativeResourceForIntegrationFunction QCocoaNativeInter return NativeResourceForIntegrationFunction(QCocoaNativeInterface::removeFromMimeList); if (resource.toLower() == "registerdraggedtypes") return NativeResourceForIntegrationFunction(QCocoaNativeInterface::registerDraggedTypes); + if (resource.toLower() == "setdockmenu") + return NativeResourceForIntegrationFunction(QCocoaNativeInterface::setDockMenu); + if (resource.toLower() == "qimagetocgimage") + return NativeResourceForIntegrationFunction(QCocoaNativeInterface::qImageToCGImage); + if (resource.toLower() == "cgimagetoqimage") + return NativeResourceForIntegrationFunction(QCocoaNativeInterface::cgImageToQImage); return 0; } @@ -170,4 +180,23 @@ void QCocoaNativeInterface::registerDraggedTypes(const QStringList &types) qt_mac_registerDraggedTypes(types); } +void QCocoaNativeInterface::setDockMenu(QPlatformMenu *platformMenu) +{ + QCocoaMenu *cocoaPlatformMenu = static_cast<QCocoaMenu *>(platformMenu); + NSMenu *menu = cocoaPlatformMenu->nsMenu(); + // setDockMenu seems to be undocumented, but this is what Qt 4 did. + [NSApp setDockMenu: menu]; +} + +CGImageRef QCocoaNativeInterface::qImageToCGImage(const QImage &image) +{ + return qt_mac_toCGImage(image, false, 0); +} + +QImage QCocoaNativeInterface::cgImageToQImage(CGImageRef image) +{ + return qt_mac_toQImage(image); +} + + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 0845ab8e94..beaa50da6d 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -53,6 +53,7 @@ #include "qcocoamenuitem.h" #include "qcocoamenu.h" #include "qcocoamenubar.h" +#include "qcocoahelpers.h" #include <QtCore/qfileinfo.h> #include <QtGui/private/qguiapplication_p.h> @@ -137,9 +138,6 @@ const QFont *QCocoaTheme::font(Font type) const return m_fonts.value(type, 0); } -// Defined in qpaintengine_mac.mm -extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); - //! \internal QPixmap qt_mac_convert_iconref(const IconRef icon, int width, int height) { diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 66c4deb366..291c688915 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -49,7 +49,8 @@ #include "qcocoaglcontext.h" #include "qnsview.h" -class QT_PREPEND_NAMESPACE(QCocoaWindow); + +QT_FORWARD_DECLARE_CLASS(QCocoaWindow) @interface QNSWindow : NSWindow { @public QCocoaWindow *m_cocoaPlatformWindow; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index a3d0bc6e54..56ca2e0b14 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -301,9 +301,11 @@ void QCocoaWindow::setVisible(bool visible) [m_nsWindow orderFront: nil]; } - // We want the events to properly reach the popup and dialog - if (window()->type() == Qt::Popup || window()->type() == Qt::Dialog) + // We want the events to properly reach the popup, dialog, and tool + if ((window()->type() == Qt::Popup || window()->type() == Qt::Dialog || window()->type() == Qt::Tool) + && [m_nsWindow isKindOfClass:[NSPanel class]]) { [(NSPanel *)m_nsWindow setWorksWhenModal:YES]; + } } } else { [m_contentView setHidden:NO]; @@ -717,6 +719,11 @@ NSWindow * QCocoaWindow::createNSWindow() createdWindow = window; } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 + if ([createdWindow respondsToSelector:@selector(setRestorable:)]) + [createdWindow setRestorable: NO]; +#endif + NSInteger level = windowLevel(flags); [createdWindow setLevel:level]; m_windowModality = window()->modality(); @@ -837,11 +844,9 @@ QCocoaMenuBar *QCocoaWindow::menubar() const qreal QCocoaWindow::devicePixelRatio() const { - if (!m_nsWindow) - return 1.0; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) { - return qreal([m_nsWindow backingScaleFactor]); + return qreal([[m_contentView window] backingScaleFactor]); } else #endif { diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm index 6fcf4d5746..95143fd8ea 100644 --- a/src/plugins/platforms/cocoa/qmacclipboard.mm +++ b/src/plugins/platforms/cocoa/qmacclipboard.mm @@ -135,7 +135,7 @@ OSStatus QMacPasteboard::promiseKeeper(PasteboardRef paste, PasteboardItemID id, } if (!promise.itemId && flavorAsQString == QLatin1String("com.trolltech.qt.MimeTypeName")) { - // we have promised this data, but wont be able to convert, so return null data. + // we have promised this data, but won't be able to convert, so return null data. // This helps in making the application/x-qt-mime-type-name hidden from normal use. QByteArray ba; QCFType<CFDataRef> data = CFDataCreate(0, (UInt8*)ba.constData(), ba.size()); diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 82fde6221d..c23d924993 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1047,7 +1047,7 @@ static QTouchDevice *touchDevice = 0; - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint { - // We dont support cursor movements using mouse while composing. + // We don't support cursor movements using mouse while composing. Q_UNUSED(aPoint); return NSNotFound; } diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index a5382c5ef6..54019372bc 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -109,7 +109,7 @@ bool QMacPrintEngine::end() if (d->state == QPrinter::Aborted) return true; // I was just here a function call ago :) if (d->paintEngine->type() == QPaintEngine::CoreGraphics) { - // We dont need the paint engine to call restoreGraphicsState() + // We don't need the paint engine to call restoreGraphicsState() static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->stackCount = 0; static_cast<QCoreGraphicsPaintEngine*>(d->paintEngine)->d_func()->hd = 0; } diff --git a/src/plugins/platforms/openwfd/qopenwfdport.cpp b/src/plugins/platforms/openwfd/qopenwfdport.cpp index 72137b91bc..14b499f7cf 100644 --- a/src/plugins/platforms/openwfd/qopenwfdport.cpp +++ b/src/plugins/platforms/openwfd/qopenwfdport.cpp @@ -125,7 +125,7 @@ void QOpenWFDPort::attach() } if (mPipeline == WFD_INVALID_HANDLE) { - qWarning("Failed to create pipeline and cant bind it to port"); + qWarning("Failed to create pipeline and can't bind it to port"); } WFDint geomerty[] = { 0, 0, mPixelSize.width(), mPixelSize.height() }; diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp index aa748fc852..1c2ec23fa9 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.cpp +++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp @@ -150,13 +150,13 @@ QQnxGLContext::QQnxGLContext(QOpenGLContext *glContext) // Select EGL config based on requested window format m_eglConfig = q_configFromGLFormat(ms_eglDisplay, format); if (m_eglConfig == 0) { - qFatal("QQNXQBBWindow: failed to find EGL config"); + qFatal("QQnxGLContext: failed to find EGL config"); } m_eglContext = eglCreateContext(ms_eglDisplay, m_eglConfig, EGL_NO_CONTEXT, contextAttrs()); if (m_eglContext == EGL_NO_CONTEXT) { checkEGLError("eglCreateContext"); - qFatal("QQNXQBBWindow: failed to create EGL context, err=%d", eglGetError()); + qFatal("QQnxGLContext: failed to create EGL context, err=%d", eglGetError()); } // Query/cache window format of selected EGL config @@ -184,13 +184,13 @@ void QQnxGLContext::initialize() ms_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); if (ms_eglDisplay == EGL_NO_DISPLAY) { checkEGLError("eglGetDisplay"); - qFatal("QQNXQBBWindow: failed to obtain EGL display"); + qFatal("QQnxGLContext: failed to obtain EGL display"); } EGLBoolean eglResult = eglInitialize(ms_eglDisplay, 0, 0); if (eglResult != EGL_TRUE) { checkEGLError("eglInitialize"); - qFatal("QQNXQBBWindow: failed to initialize EGL display, err=%d", eglGetError()); + qFatal("QQnxGLContext: failed to initialize EGL display, err=%d", eglGetError()); } } @@ -217,7 +217,7 @@ bool QQnxGLContext::makeCurrent(QPlatformSurface *surface) // Set current rendering API EGLBoolean eglResult = eglBindAPI(EGL_OPENGL_ES_API); if (eglResult != EGL_TRUE) { - qFatal("QQNXQBBWindow: failed to set EGL API, err=%d", eglGetError()); + qFatal("QQnxGLContext: failed to set EGL API, err=%d", eglGetError()); } if (m_newSurfaceRequested.testAndSetOrdered(true, false)) { diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp index 30ca8a5c48..0d8f430c73 100644 --- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp +++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.cpp @@ -42,6 +42,8 @@ #include "qqnxinputcontext_imf.h" #include "qqnxeventthread.h" #include "qqnxabstractvirtualkeyboard.h" +#include "qqnxintegration.h" +#include "qqnxscreen.h" #include <QtGui/QGuiApplication> #include <QtGui/QInputMethodEvent> @@ -645,12 +647,13 @@ static bool imfAvailable() QT_BEGIN_NAMESPACE -QQnxInputContext::QQnxInputContext(QQnxAbstractVirtualKeyboard &keyboard): +QQnxInputContext::QQnxInputContext(QQnxIntegration *integration, QQnxAbstractVirtualKeyboard &keyboard) : QPlatformInputContext(), m_lastCaretPos(0), m_isComposing(false), m_inputPanelVisible(false), m_inputPanelLocale(QLocale::c()), + m_integration(integration), m_virtualKeyboad(keyboard) { qInputContextDebug() << Q_FUNC_INFO; @@ -857,6 +860,13 @@ bool QQnxInputContext::filterEvent( const QEvent *event ) } } +QRectF QQnxInputContext::keyboardRect() const +{ + QRect screenGeometry = m_integration->primaryDisplay()->geometry(); + return QRectF(screenGeometry.x(), screenGeometry.height() - m_virtualKeyboard.height(), + screenGeometry.width(), m_virtualKeyboard.height()); +} + void QQnxInputContext::reset() { qInputContextDebug() << Q_FUNC_INFO; diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_imf.h b/src/plugins/platforms/qnx/qqnxinputcontext_imf.h index 72c52300bb..1980a99ed9 100644 --- a/src/plugins/platforms/qnx/qqnxinputcontext_imf.h +++ b/src/plugins/platforms/qnx/qqnxinputcontext_imf.h @@ -54,21 +54,24 @@ QT_BEGIN_NAMESPACE class QQnxAbstractVirtualKeyboard; +class QQnxIntegration; class QQnxInputContext : public QPlatformInputContext { Q_OBJECT public: - explicit QQnxInputContext(QQnxAbstractVirtualKeyboard &keyboard); + explicit QQnxInputContext(QQnxIntegration *integration, QQnxAbstractVirtualKeyboard &keyboard); ~QQnxInputContext(); bool isValid() const; bool filterEvent(const QEvent *event); + QRectF keyboardRect() const; void reset(); void update(Qt::InputMethodQueries); bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap); + void showInputPanel(); void hideInputPanel(); bool isInputPanelVisible() const; @@ -125,6 +128,7 @@ private: QString m_composingText; bool m_inputPanelVisible; QLocale m_inputPanelLocale; + QQnxIntegration *m_integration; QQnxAbstractVirtualKeyboard &m_virtualKeyboad; }; diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp index 23d1f75539..71b925357a 100644 --- a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp +++ b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.cpp @@ -41,6 +41,8 @@ #include "qqnxinputcontext_noimf.h" #include "qqnxabstractvirtualkeyboard.h" +#include "qqnxintegration.h" +#include "qqnxscreen.h" #include <QtCore/QDebug> #include <QtGui/QGuiApplication> @@ -53,12 +55,14 @@ QT_BEGIN_NAMESPACE -QQnxInputContext::QQnxInputContext(QQnxAbstractVirtualKeyboard &keyboard) : +QQnxInputContext::QQnxInputContext(QQnxIntegration *integration, QQnxAbstractVirtualKeyboard &keyboard) : QPlatformInputContext(), m_inputPanelVisible(false), m_inputPanelLocale(QLocale::c()), + m_integration(integration), m_virtualKeyboard(keyboard) { + connect(&keyboard, SIGNAL(heightChanged(int)), this, SLOT(keyboardHeightChanged())); connect(&keyboard, SIGNAL(visibilityChanged(bool)), this, SLOT(keyboardVisibilityChanged(bool))); connect(&keyboard, SIGNAL(localeChanged(QLocale)), this, SLOT(keyboardLocaleChanged(QLocale))); keyboardVisibilityChanged(keyboard.isVisible()); @@ -105,6 +109,13 @@ bool QQnxInputContext::filterEvent( const QEvent *event ) } +QRectF QQnxInputContext::keyboardRect() const +{ + QRect screenGeometry = m_integration->primaryDisplay()->geometry(); + return QRectF(screenGeometry.x(), screenGeometry.height() - m_virtualKeyboard.height(), + screenGeometry.width(), m_virtualKeyboard.height()); +} + bool QQnxInputContext::handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap) { Q_UNUSED(flags); @@ -137,6 +148,11 @@ QLocale QQnxInputContext::locale() const return m_inputPanelLocale; } +void QQnxInputContext::keyboardHeightChanged() +{ + emitKeyboardRectChanged(); +} + void QQnxInputContext::keyboardVisibilityChanged(bool visible) { qInputContextDebug() << Q_FUNC_INFO << "visible=" << visible; diff --git a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.h b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.h index c037b6afd0..1ecf7cc94e 100644 --- a/src/plugins/platforms/qnx/qqnxinputcontext_noimf.h +++ b/src/plugins/platforms/qnx/qqnxinputcontext_noimf.h @@ -49,18 +49,20 @@ QT_BEGIN_NAMESPACE class QQnxAbstractVirtualKeyboard; +class QQnxIntegration; class QQnxInputContext : public QPlatformInputContext { Q_OBJECT public: - explicit QQnxInputContext(QQnxAbstractVirtualKeyboard &keyboard); + explicit QQnxInputContext(QQnxIntegration *integration, QQnxAbstractVirtualKeyboard &keyboard); ~QQnxInputContext(); bool isValid() const; void reset(); bool filterEvent( const QEvent *event ); + QRectF keyboardRect() const; bool handleKeyboardEvent(int flags, int sym, int mod, int scan, int cap); void showInputPanel(); @@ -71,6 +73,7 @@ public: void setFocusObject(QObject *object); private Q_SLOTS: + void keyboardHeightChanged(); void keyboardVisibilityChanged(bool visible); void keyboardLocaleChanged(const QLocale &locale); @@ -79,6 +82,7 @@ private: bool m_inputPanelVisible; QLocale m_inputPanelLocale; + QQnxIntegration *m_integration; QQnxAbstractVirtualKeyboard &m_virtualKeyboard; }; diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index bff4dbdc2a..f3cfdab9c6 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -214,7 +214,7 @@ QQnxIntegration::QQnxIntegration() #if defined(QQNX_PPS) // Set up the input context - m_inputContext = new QQnxInputContext(*m_virtualKeyboard); + m_inputContext = new QQnxInputContext(this, *m_virtualKeyboard); #endif } @@ -446,6 +446,11 @@ void QQnxIntegration::createDisplays() qFatal("QQnxIntegration: failed to query display count, errno=%d", errno); } + if (displayCount < 1) { + // Never happens, even if there's no display, libscreen returns 1 + qFatal("QQnxIntegration: displayCount=%d", displayCount); + } + // Get all displays errno = 0; screen_display_t *displays = (screen_display_t *)alloca(sizeof(screen_display_t) * displayCount); @@ -454,7 +459,11 @@ void QQnxIntegration::createDisplays() qFatal("QQnxIntegration: failed to query displays, errno=%d", errno); } - for (int i=0; i<displayCount; i++) { + // If it's primary, we create a QScreen for it even if it's not attached + // since Qt will dereference QGuiApplication::primaryScreen() + createDisplay(displays[0], /*isPrimary=*/true); + + for (int i=1; i<displayCount; i++) { int isAttached = 0; result = screen_get_display_property_iv(displays[i], SCREEN_PROPERTY_ATTACHED, &isAttached); if (result != 0) { @@ -468,7 +477,7 @@ void QQnxIntegration::createDisplays() } qIntegrationDebug() << Q_FUNC_INFO << "Creating screen for display" << i; - createDisplay(displays[i], i==0); + createDisplay(displays[i], /*isPrimary=*/false); } // of displays iteration } diff --git a/src/plugins/platforms/qnx/qqnxrootwindow.cpp b/src/plugins/platforms/qnx/qqnxrootwindow.cpp index ee05e00394..b01d468647 100644 --- a/src/plugins/platforms/qnx/qqnxrootwindow.cpp +++ b/src/plugins/platforms/qnx/qqnxrootwindow.cpp @@ -57,7 +57,7 @@ static const int MAGIC_ZORDER_FOR_NO_NAV = 10; -QQnxRootWindow::QQnxRootWindow(QQnxScreen *screen) +QQnxRootWindow::QQnxRootWindow(const QQnxScreen *screen) : m_screen(screen), m_window(0), m_windowGroupName() diff --git a/src/plugins/platforms/qnx/qqnxrootwindow.h b/src/plugins/platforms/qnx/qqnxrootwindow.h index f9f1dc0810..aae1563c95 100644 --- a/src/plugins/platforms/qnx/qqnxrootwindow.h +++ b/src/plugins/platforms/qnx/qqnxrootwindow.h @@ -54,7 +54,7 @@ class QQnxScreen; class QQnxRootWindow { public: - QQnxRootWindow(QQnxScreen *screen); + QQnxRootWindow(const QQnxScreen *screen); ~QQnxRootWindow(); screen_window_t nativeHandle() const { return m_window; } @@ -71,7 +71,7 @@ public: private: void createWindowGroup(); - QQnxScreen *m_screen; + const QQnxScreen *m_screen; screen_window_t m_window; QByteArray m_windowGroupName; }; diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp index 5450f086e9..fc8b3bb167 100644 --- a/src/plugins/platforms/qnx/qqnxscreen.cpp +++ b/src/plugins/platforms/qnx/qqnxscreen.cpp @@ -107,7 +107,6 @@ static QSize determineScreenSize(screen_display_t display, bool primaryScreen) { QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display, bool primaryScreen) : m_screenContext(screenContext), m_display(display), - m_rootWindow(), m_primaryScreen(primaryScreen), m_posted(false), m_keyboardHeight(0), @@ -147,10 +146,6 @@ QQnxScreen::QQnxScreen(screen_context_t screenContext, screen_display_t display, m_currentPhysicalSize = m_initialPhysicalSize = screenSize; else m_currentPhysicalSize = m_initialPhysicalSize = screenSize.transposed(); - - // We only create the root window if we are the primary display. - if (primaryScreen) - m_rootWindow = QSharedPointer<QQnxRootWindow>(new QQnxRootWindow(this)); } QQnxScreen::~QQnxScreen() @@ -252,8 +247,8 @@ void QQnxScreen::setRotation(int rotation) // Check if rotation changed if (m_currentRotation != rotation) { // Update rotation of root window - if (m_rootWindow) - m_rootWindow->setRotation(rotation); + if (rootWindow()) + rootWindow()->setRotation(rotation); const QRect previousScreenGeometry = geometry(); @@ -269,16 +264,16 @@ void QQnxScreen::setRotation(int rotation) // Resize root window if we've rotated 90 or 270 from previous orientation if (isOrthogonal(m_currentRotation, rotation)) { qScreenDebug() << Q_FUNC_INFO << "resize, size =" << m_currentGeometry.size(); - if (m_rootWindow) - m_rootWindow->resize(m_currentGeometry.size()); + if (rootWindow()) + rootWindow()->resize(m_currentGeometry.size()); if (m_primaryScreen) resizeWindows(previousScreenGeometry); } else { // TODO: Find one global place to flush display updates // Force immediate display update if no geometry changes required - if (m_rootWindow) - m_rootWindow->flush(); + if (rootWindow()) + rootWindow()->flush(); } // Save new rotation @@ -495,8 +490,8 @@ void QQnxScreen::onWindowPost(QQnxWindow *window) // post app window (so navigator will show it) after first child window // has posted; this only needs to happen once as the app window's content // never changes - if (!m_posted && m_rootWindow) { - m_rootWindow->post(); + if (!m_posted && rootWindow()) { + rootWindow()->post(); m_posted = true; } } @@ -582,4 +577,13 @@ void QQnxScreen::deactivateWindowGroup(const QByteArray &id) QWindowSystemInterface::handleWindowActivated(0); } +QSharedPointer<QQnxRootWindow> QQnxScreen::rootWindow() const +{ + // We only create the root window if we are the primary display. + if (m_primaryScreen && !m_rootWindow) + m_rootWindow = QSharedPointer<QQnxRootWindow>(new QQnxRootWindow(this)); + + return m_rootWindow; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxscreen.h b/src/plugins/platforms/qnx/qqnxscreen.h index 682f681cd3..39cd4159d1 100644 --- a/src/plugins/platforms/qnx/qqnxscreen.h +++ b/src/plugins/platforms/qnx/qqnxscreen.h @@ -80,7 +80,7 @@ public: int nativeFormat() const { return (depth() == 32) ? SCREEN_FORMAT_RGBA8888 : SCREEN_FORMAT_RGB565; } screen_display_t nativeDisplay() const { return m_display; } screen_context_t nativeContext() const { return m_screenContext; } - const char *windowGroupName() const { return m_rootWindow->groupName().constData(); } + const char *windowGroupName() const { return rootWindow()->groupName().constData(); } QQnxWindow *findWindow(screen_window_t windowHandle); @@ -93,7 +93,7 @@ public: void onWindowPost(QQnxWindow *window); - QSharedPointer<QQnxRootWindow> rootWindow() const { return m_rootWindow; } + QSharedPointer<QQnxRootWindow> rootWindow() const; QPlatformCursor *cursor() const; @@ -116,8 +116,8 @@ private: screen_context_t m_screenContext; screen_display_t m_display; - QSharedPointer<QQnxRootWindow> m_rootWindow; - bool m_primaryScreen; + mutable QSharedPointer<QQnxRootWindow> m_rootWindow; + const bool m_primaryScreen; bool m_posted; int m_initialRotation; diff --git a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp index 4b1cc4fdac..2d3c7608bf 100644 --- a/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxscreeneventhandler.cpp @@ -42,6 +42,7 @@ #include "qqnxscreeneventhandler.h" #include "qqnxintegration.h" #include "qqnxkeytranslator.h" +#include "qqnxscreen.h" #include <QDebug> #include <QGuiApplication> @@ -489,9 +490,18 @@ void QQnxScreenEventHandler::handleDisplayEvent(screen_event_t event) m_qnxIntegration->createDisplay(nativeDisplay, false /* not primary, we assume */); } } else if (!isAttached) { - // libscreen display is deactivated, let's remove the QQnxScreen / QScreen - qScreenEventDebug() << "removing display"; - m_qnxIntegration->removeDisplay(screen); + // We never remove the primary display, the qpa plugin doesn't support that and it crashes. + // To support it, this would be needed: + // - Adjust all qnx qpa code which uses screens + // - Make QWidgetBackingStore not dereference a null paint device + // - Create platform resources ( QQnxWindow ) for all QWindow because they would be deleted + // when you delete the screen + + if (!screen->isPrimaryScreen()) { + // libscreen display is deactivated, let's remove the QQnxScreen / QScreen + qScreenEventDebug() << "removing display"; + m_qnxIntegration->removeDisplay(screen); + } } } diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 7cc2b2aeb0..c23902014c 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -577,9 +577,10 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long QRect rect; if (varID.lVal) { - QAIPointer child = QAIPointer(accessible->child(varID.lVal - 1)); - if (child->isValid()) - rect = child->rect(); + QAIPointer child(childPointer(varID)); + if (!child) + return E_FAIL; + rect = child->rect(); } else { rect = accessible->rect(); } diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index 792eaf0fdc..b40aefa225 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -88,11 +88,8 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion, QWindowsWindow *rw = QWindowsWindow::baseWindowOf(window); #ifndef Q_OS_WINCE - if (rw->format().hasAlpha() && (window->flags() & Qt::FramelessWindowHint)) { - const long wl = GetWindowLong(rw->handle(), GWL_EXSTYLE); - if ((wl & WS_EX_LAYERED) == 0) - SetWindowLong(rw->handle(), GWL_EXSTYLE, wl | WS_EX_LAYERED); - + const Qt::WindowFlags flags = window->flags(); + if ((flags & Qt::FramelessWindowHint) && QWindowsWindow::setWindowLayered(rw->handle(), flags, rw->format().hasAlpha(), rw->opacity())) { QRect r = window->frameGeometry(); QPoint frameOffset(window->frameMargins().left(), window->frameMargins().top()); QRect dirtyRect = br.translated(offset + frameOffset); @@ -101,7 +98,6 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion, POINT ptDst = {r.x(), r.y()}; POINT ptSrc = {0, 0}; BLENDFUNCTION blend = {AC_SRC_OVER, 0, (BYTE)(255.0 * rw->opacity()), AC_SRC_ALPHA}; - if (QWindowsContext::user32dll.updateLayeredWindowIndirect) { RECT dirty = {dirtyRect.x(), dirtyRect.y(), dirtyRect.x() + dirtyRect.width(), dirtyRect.y() + dirtyRect.height()}; diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index c658a1814f..a6709dffb3 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -869,8 +869,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, #endif #ifndef QT_NO_CONTEXTMENU case QtWindows::ContextMenu: - handleContextMenuEvent(platformWindow->window(), msg); - return true; + return handleContextMenuEvent(platformWindow->window(), msg); #endif default: break; @@ -904,7 +903,7 @@ void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et, } #ifndef QT_NO_CONTEXTMENU -void QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg) +bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg) { bool mouseTriggered = false; QPoint globalPos; @@ -914,10 +913,23 @@ void QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg) globalPos.setX(msg.pt.x); globalPos.setY(msg.pt.y); pos = QWindowsGeometryHint::mapFromGlobal(msg.hwnd, globalPos); + + RECT clientRect; + if (GetClientRect(msg.hwnd, &clientRect)) { + if (pos.x() < (int)clientRect.left || pos.x() >= (int)clientRect.right || + pos.y() < (int)clientRect.top || pos.y() >= (int)clientRect.bottom) + { + // This is the case that user has right clicked in the window's caption, + // We should call DefWindowProc() to display a default shortcut menu + // instead of sending a Qt window system event. + return false; + } + } } QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos, QWindowsKeyMapper::queryKeyboardModifiers()); + return true; } #endif diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index bfe56ed246..1fe71e3aff 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -192,7 +192,7 @@ public: private: void handleFocusEvent(QtWindows::WindowsEventType et, QWindowsWindow *w); #ifndef QT_NO_CONTEXTMENU - void handleContextMenuEvent(QWindow *window, const MSG &msg); + bool handleContextMenuEvent(QWindow *window, const MSG &msg); #endif void unregisterWindowClasses(); diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 4f9698b21b..5b2a3acbae 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -39,6 +39,7 @@ ** ****************************************************************************/ +#ifndef QT_NO_CURSOR #include "qwindowscursor.h" #include "qwindowscontext.h" #include "qwindowswindow.h" @@ -527,3 +528,5 @@ HCURSOR QWindowsWindowCursor::handle() const } QT_END_NAMESPACE + +#endif // !QT_NO_CURSOR diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index a71ee2f9ed..c2ddb912f1 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -247,7 +247,7 @@ static bool addFontToDatabase(QString familyName, const QString &scriptName, value = fontCache.value(faceName); - //Fallback if we havent cached the font yet or the font got removed/renamed iterate again over all fonts + //Fallback if we haven't cached the font yet or the font got removed/renamed iterate again over all fonts if (value.isEmpty() || !QFile::exists(value)) { QSettings settings(QSettings::SystemScope, QStringLiteral("Qt-Project"), QStringLiteral("Qtbase")); settings.beginGroup(QStringLiteral("CEFontCache")); diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 3c6fcca813..30e0478e64 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -59,8 +59,10 @@ #include "qwindowsguieventdispatcher.h" #ifndef QT_NO_CLIPBOARD # include "qwindowsclipboard.h" +# ifndef QT_NO_DRAGANDDROP +# include "qwindowsdrag.h" +# endif #endif -#include "qwindowsdrag.h" #include "qwindowsinputcontext.h" #include "qwindowskeymapper.h" # ifndef QT_NO_ACCESSIBILITY @@ -108,6 +110,9 @@ public: Q_INVOKABLE void *createMessageWindow(const QString &classNameTemplate, const QString &windowName, void *eventProc) const; + + Q_INVOKABLE QString registerWindowClass(const QString &classNameIn, void *eventProc) const; + bool asyncExpose() const; void setAsyncExpose(bool value); @@ -223,6 +228,15 @@ void *QWindowsNativeInterface::createMessageWindow(const QString &classNameTempl return hwnd; } +/*! + \brief Registers a unique window class with a callback function based on \a classNameIn. +*/ + +QString QWindowsNativeInterface::registerWindowClass(const QString &classNameIn, void *eventProc) const +{ + return QWindowsContext::instance()->registerWindowClass(classNameIn, (WNDPROC)eventProc); +} + bool QWindowsNativeInterface::asyncExpose() const { return QWindowsContext::instance()->asyncExpose(); @@ -291,8 +305,10 @@ struct QWindowsIntegrationPrivate QWindowsNativeInterface m_nativeInterface; #ifndef QT_NO_CLIPBOARD QWindowsClipboard m_clipboard; -#endif +# ifndef QT_NO_DRAGANDDROP QWindowsDrag m_drag; +# endif +#endif QWindowsGuiEventDispatcher *m_eventDispatcher; #if defined(QT_OPENGL_ES_2) QEGLStaticContextPtr m_staticEGLContext; @@ -559,12 +575,13 @@ QPlatformClipboard * QWindowsIntegration::clipboard() const { return &d->m_clipboard; } -#endif // !QT_NO_CLIPBOARD - +# ifndef QT_NO_DRAGANDDROP QPlatformDrag *QWindowsIntegration::drag() const { return &d->m_drag; } +# endif // !QT_NO_DRAGANDDROP +#endif // !QT_NO_CLIPBOARD QPlatformInputContext * QWindowsIntegration::inputContext() const { diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index 2593c3b946..24dc01f0bd 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -75,8 +75,10 @@ public: virtual QAbstractEventDispatcher *guiThreadEventDispatcher() const; #ifndef QT_NO_CLIPBOARD virtual QPlatformClipboard *clipboard() const; -#endif +# ifndef QT_NO_DRAGANDDROP virtual QPlatformDrag *drag() const; +# endif +#endif !QT_NO_CLIPBOARD virtual QPlatformInputContext *inputContext() const; #ifndef QT_NO_ACCESSIBILITY virtual QPlatformAccessibility *accessibility() const; diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 9bb16793cc..f616972aa0 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -168,8 +168,10 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) // Return the cursor to be shared by all screens (virtual desktop). static inline QSharedPointer<QWindowsCursor> sharedCursor() { +#ifndef QT_NO_CURSOR if (const QScreen *primaryScreen = QGuiApplication::primaryScreen()) return static_cast<const QWindowsScreen *>(primaryScreen->handle())->windowsCursor(); +#endif return QSharedPointer<QWindowsCursor>(new QWindowsCursor); } @@ -182,7 +184,10 @@ static inline QSharedPointer<QWindowsCursor> sharedCursor() */ QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) : - m_data(data), m_cursor(sharedCursor()) + m_data(data) +#ifndef QT_NO_CURSOR + ,m_cursor(sharedCursor()) +#endif { } @@ -250,7 +255,11 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags) QWindow *QWindowsScreen::windowUnderMouse(unsigned flags) { +#ifndef QT_NO_CURSOR return QWindowsScreen::windowAt(QWindowsCursor::mousePosition(), flags); +#else + return 0; +#endif } QWindowsScreen *QWindowsScreen::screenOf(const QWindow *w) diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 7da1a4d207..216973125b 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -79,7 +79,9 @@ struct QWindowsScreenData class QWindowsScreen : public QPlatformScreen { public: +#ifndef QT_NO_CURSOR typedef QSharedPointer<QWindowsCursor> WindowsCursorPtr; +#endif explicit QWindowsScreen(const QWindowsScreenData &data); @@ -106,14 +108,20 @@ public: inline void handleChanges(const QWindowsScreenData &newData); +#ifndef QT_NO_CURSOR QPlatformCursor *cursor() const { return m_cursor.data(); } const WindowsCursorPtr &windowsCursor() const { return m_cursor; } +#else + QPlatformCursor *cursor() const { return 0; } +#endif // !QT_NO_CURSOR const QWindowsScreenData &data() const { return m_data; } private: QWindowsScreenData m_data; +#ifndef QT_NO_CURSOR const WindowsCursorPtr m_cursor; +#endif }; class QWindowsScreenManager diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 9391929c41..d565420f4f 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -44,7 +44,9 @@ #include "qwindowscontext.h" #include "qwindowsdrag.h" #include "qwindowsscreen.h" -#include "qwindowscursor.h" +#ifdef QT_NO_CURSOR +# include "qwindowscursor.h" +#endif #ifdef QT_OPENGL_ES_2 # include "qwindowseglcontext.h" @@ -209,22 +211,42 @@ static bool shouldShowMaximizeButton(Qt::WindowFlags flags) return flags & Qt::WindowMaximizeButtonHint; } -static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, qreal level) +// Set the WS_EX_LAYERED flag on a HWND if required. This is required for +// translucent backgrounds, not fully opaque windows and for +// Qt::WindowTransparentForInput (in combination with WS_EX_TRANSPARENT). +bool QWindowsWindow::setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity) +{ +#ifndef Q_OS_WINCE // maybe needs revisiting WS_EX_LAYERED + const LONG exStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + const bool needsLayered = (flags & Qt::WindowTransparentForInput) + || (hasAlpha && (flags & Qt::FramelessWindowHint)) || opacity < 1.0; + const bool isLayered = (exStyle & WS_EX_LAYERED); + if (needsLayered != isLayered) { + if (needsLayered) { + SetWindowLong(hwnd, GWL_EXSTYLE, exStyle | WS_EX_LAYERED); + } else { + SetWindowLong(hwnd, GWL_EXSTYLE, exStyle & ~WS_EX_LAYERED); + } + } + return needsLayered; +#else // !Q_OS_WINCE + Q_UNUSED(hwnd); + Q_UNUSED(flags); + Q_UNUSED(hasAlpha); + Q_UNUSED(opacity); + return false; +#endif // Q_OS_WINCE +} + +static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal level) { -#ifdef Q_OS_WINCE // maybe needs revisit WS_EX_LAYERED +#ifdef Q_OS_WINCE // WINCE does not support that feature and microsoft explicitly warns to use those calls Q_UNUSED(hwnd); Q_UNUSED(flags); + Q_UNUSED(hasAlpha); Q_UNUSED(level); #else - const long wl = GetWindowLong(hwnd, GWL_EXSTYLE); - const bool isOpaque = level == 1.0 && !(flags & Qt::WindowTransparentForInput); - - if (isOpaque) { - if (wl & WS_EX_LAYERED) - SetWindowLong(hwnd, GWL_EXSTYLE, wl & ~WS_EX_LAYERED); - } else { - if ((wl & WS_EX_LAYERED) == 0) - SetWindowLong(hwnd, GWL_EXSTYLE, wl | WS_EX_LAYERED); + if (QWindowsWindow::setWindowLayered(hwnd, flags, hasAlpha, level)) { if (flags & Qt::FramelessWindowHint) { BLENDFUNCTION blend = {AC_SRC_OVER, 0, (BYTE)(255.0 * level), AC_SRC_ALPHA}; QWindowsContext::user32dll.updateLayeredWindow(hwnd, NULL, NULL, NULL, NULL, NULL, 0, &blend, ULW_ALPHA); @@ -271,7 +293,7 @@ struct WindowCreationData WindowCreationData() : parentHandle(0), type(Qt::Widget), style(0), exStyle(0), topLevel(false), popup(false), dialog(false), desktop(false), - tool(false), embedded(false) {} + tool(false), embedded(false), hasAlpha(false) {} void fromWindow(const QWindow *w, const Qt::WindowFlags flags, unsigned creationFlags = 0); inline WindowData create(const QWindow *w, const WindowData &data, QString title) const; @@ -290,6 +312,7 @@ struct WindowCreationData bool desktop; bool tool; bool embedded; + bool hasAlpha; }; QDebug operator<<(QDebug debug, const WindowCreationData &d) @@ -308,6 +331,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag unsigned creationFlags) { isGL = w->surfaceType() == QWindow::OpenGLSurface; + hasAlpha = w->format().hasAlpha(); flags = flagsIn; // Sometimes QWindow doesn't have a QWindow parent but does have a native parent window, @@ -321,10 +345,12 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag if (creationFlags & ForceChild) { topLevel = false; - } else if (creationFlags & ForceTopLevel) { - topLevel = true; + } else if (embedded) { + // Embedded native windows (for example Active X server windows) are by + // definition never toplevel, even though they do not have QWindow parents. + topLevel = false; } else { - topLevel = w->isTopLevel(); + topLevel = (creationFlags & ForceTopLevel) ? true : w->isTopLevel(); } if (topLevel && flags == 1) { @@ -530,7 +556,7 @@ void WindowCreationData::initialize(HWND hwnd, bool frameChange, qreal opacityLe EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED); } - setWindowOpacity(hwnd, flags, opacityLevel); + setWindowOpacity(hwnd, flags, hasAlpha, opacityLevel); } else { // child. SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, swpFlags); } @@ -770,8 +796,10 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) : break; } } +#ifndef Q_OS_WINCE if (QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch) QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, 0); +#endif // !Q_OS_WINCE setWindowState(aWindow->windowState()); const qreal opacity = qt_window_private(aWindow)->opacity; if (!qFuzzyCompare(opacity, qreal(1.0))) @@ -780,8 +808,10 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const WindowData &data) : QWindowsWindow::~QWindowsWindow() { +#ifndef Q_OS_WINCE if (QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch) QWindowsContext::user32dll.unregisterTouchWindow(m_data.hwnd); +#endif // !Q_OS_WINCE destroyWindow(); destroyIcon(); } @@ -811,7 +841,7 @@ void QWindowsWindow::destroyWindow() ShowWindow(handle, SW_SHOW); } } -#endif +#endif // !Q_OS_WINCE if (m_data.hwnd != GetDesktopWindow()) DestroyWindow(m_data.hwnd); QWindowsContext::instance()->removeWindow(m_data.hwnd); @@ -821,21 +851,29 @@ void QWindowsWindow::destroyWindow() void QWindowsWindow::registerDropSite() { +#ifndef QT_NO_CLIPBOARD +# ifndef QT_NO_DRAGANDDROP if (m_data.hwnd && !m_dropTarget) { m_dropTarget = new QWindowsOleDropTarget(window()); RegisterDragDrop(m_data.hwnd, m_dropTarget); CoLockObjectExternal(m_dropTarget, true, true); } +# endif // !QT_NO_DRAGANDDROP +#endif // !QT_NO_CLIPBOARD } void QWindowsWindow::unregisterDropSite() { +#ifndef QT_NO_CLIPBOARD +# ifndef QT_NO_DRAGANDDROP if (m_data.hwnd && m_dropTarget) { m_dropTarget->Release(); CoLockObjectExternal(m_dropTarget, false, true); RevokeDragDrop(m_data.hwnd); m_dropTarget = 0; } +# endif // !QT_NO_DRAGANDDROP +#endif // !QT_NO_CLIPBOARD } // Returns topmost QWindowsWindow ancestor even if there are embedded windows in the chain. @@ -1231,18 +1269,7 @@ void QWindowsWindow::setWindowTitle(const QString &title) if (QWindowsContext::verboseWindows) qDebug() << __FUNCTION__ << this << window() <<title; if (m_data.hwnd) { - - QString fullTitle = title; - if (QGuiApplicationPrivate::displayName) { - // Append display name, if set. - if (!fullTitle.isEmpty()) - fullTitle += QStringLiteral(" - "); - fullTitle += *QGuiApplicationPrivate::displayName; - } else if (fullTitle.isEmpty()) { - // Don't let the window title be completely empty, use the app name as fallback. - fullTitle = QCoreApplication::applicationName(); - } - + const QString fullTitle = formatWindowTitle(title, QStringLiteral(" - ")); SetWindowText(m_data.hwnd, (const wchar_t*)fullTitle.utf16()); } } @@ -1508,7 +1535,7 @@ void QWindowsWindow::setOpacity(qreal level) if (m_opacity != level) { m_opacity = level; if (m_data.hwnd) - setWindowOpacity(m_data.hwnd, m_data.flags, level); + setWindowOpacity(m_data.hwnd, m_data.flags, window()->format().hasAlpha(), level); } } @@ -1671,12 +1698,14 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const void QWindowsWindow::applyCursor() { +#ifndef QT_NO_CURSOR if (m_cursor.isNull()) { // Recurse up to parent with non-null cursor. if (const QWindow *p = window()->parent()) QWindowsWindow::baseWindowOf(p)->applyCursor(); } else { SetCursor(m_cursor.handle()); } +#endif } // Check whether to apply a new cursor. Either the window in question is @@ -1698,6 +1727,7 @@ static inline bool applyNewCursor(const QWindow *w) void QWindowsWindow::setCursor(const QWindowsWindowCursor &c) { +#ifndef QT_NO_CURSOR if (c.handle() != m_cursor.handle()) { const bool apply = applyNewCursor(window()); if (QWindowsContext::verboseWindows) @@ -1707,6 +1737,7 @@ void QWindowsWindow::setCursor(const QWindowsWindowCursor &c) if (apply) applyCursor(); } +#endif } /*! diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 9dc8c170e7..8fe5cbe17b 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -223,13 +223,17 @@ public: static inline void *userDataOf(HWND hwnd); static inline void setUserDataOf(HWND hwnd, void *ud); + static bool setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, qreal opacity); + HDC getDC(); void releaseDC(); #ifndef Q_OS_WINCE // maybe available on some SDKs revisit WM_GETMINMAXINFO void getSizeHints(MINMAXINFO *mmi) const; #endif +#ifndef QT_NO_CURSOR QWindowsWindowCursor cursor() const { return m_cursor; } +#endif void setCursor(const QWindowsWindowCursor &c); void applyCursor(); @@ -275,7 +279,9 @@ private: HDC m_hdc; Qt::WindowState m_windowState; qreal m_opacity; +#ifndef QT_NO_CURSOR QWindowsWindowCursor m_cursor; +#endif QWindowsOleDropTarget *m_dropTarget; unsigned m_savedStyle; QRect m_savedFrameGeometry; diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro index 7f73465135..ff162e2d41 100644 --- a/src/plugins/platforms/windows/windows.pro +++ b/src/plugins/platforms/windows/windows.pro @@ -45,7 +45,6 @@ SOURCES += \ qwindowsguieventdispatcher.cpp \ qwindowsole.cpp \ qwindowsmime.cpp \ - qwindowsdrag.cpp \ qwindowsinternalmimedata.cpp \ qwindowscursor.cpp \ qwindowsinputcontext.cpp \ @@ -69,7 +68,6 @@ HEADERS += \ qtwindows_additional.h \ qwindowsole.h \ qwindowsmime.h \ - qwindowsdrag.h \ qwindowsinternalmimedata.h \ qwindowscursor.h \ array.h \ @@ -94,6 +92,16 @@ contains(QT_CONFIG, opengles2) { HEADERS += qwindowsclipboard.h } +# drag and drop on windows only works if a clipboard is available +!contains( DEFINES, QT_NO_DRAGANDDROP ) { + !win32:SOURCES += qwindowsdrag.cpp + !win32:HEADERS += qwindowsdrag.h + win32:!contains( DEFINES, QT_NO_CLIPBOARD ) { + HEADERS += qwindowsdrag.h + SOURCES += qwindowsdrag.cpp + } +} + # Enable access to HB_Face in harfbuzz includes included by qfontengine_p.h. DEFINES *= QT_COMPILES_IN_HARFBUZZ diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index 80fcbbebc6..23bec15b48 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -305,14 +305,24 @@ QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlat // If asking for OpenGL 3.2 or newer we should also specify a profile if (m_format.majorVersion() > 3 || (m_format.majorVersion() == 3 && m_format.minorVersion() > 1)) { - if (m_format.profile() == QSurfaceFormat::CoreProfile) { - contextAttributes << GLX_CONTEXT_FLAGS_ARB << GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB - << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - } else { + if (m_format.profile() == QSurfaceFormat::CoreProfile) + contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + else contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; - } } + int flags = 0; + + if (m_format.testOption(QSurfaceFormat::DebugContext)) + flags |= GLX_CONTEXT_DEBUG_BIT_ARB; + + // A forward-compatible context may be requested for 3.0 and later + if (m_format.majorVersion() >= 3 && !m_format.testOption(QSurfaceFormat::DeprecatedFunctions)) + flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + + if (flags != 0) + contextAttributes << GLX_CONTEXT_FLAGS_ARB << flags; + contextAttributes << None; m_context = glXCreateContextAttribsARB(DISPLAY_FROM_XCB(screen), config, m_shareContext, true, contextAttributes.data()); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index a8957d5810..c0ddf5c0ae 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1125,18 +1125,8 @@ void QXcbWindow::setParent(const QPlatformWindow *parent) void QXcbWindow::setWindowTitle(const QString &title) { - QString fullTitle = title; - if (QGuiApplicationPrivate::displayName) { - // Append display name, if set. - if (!fullTitle.isEmpty()) - fullTitle += QString::fromUtf8(" \xe2\x80\x94 "); // unicode character U+2014, EM DASH - fullTitle += *QGuiApplicationPrivate::displayName; - } else if (fullTitle.isEmpty()) { - // Don't let the window title be completely empty, use the app name as fallback. - fullTitle = QCoreApplication::applicationName(); - } + const QString fullTitle = formatWindowTitle(title, QString::fromUtf8(" \xe2\x80\x94 ")); // unicode character U+2014, EM DASH const QByteArray ba = fullTitle.toUtf8(); - Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, |