diff options
author | Liang Qi <liang.qi@qt.io> | 2017-09-26 16:08:55 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2017-09-26 16:14:54 +0200 |
commit | aadfe7d634de04519102c5827ca885dc2e2199c9 (patch) | |
tree | d92db346ca95332b177036a53f1f6beb2e24fb74 /src/plugins | |
parent | 4b6c1448047362b8c38d265e6414f0e3e59b8d37 (diff) | |
parent | a732e16d5fd9dbf8a0289fec9f948b12e9ba2c19 (diff) |
Merge remote-tracking branch 'origin/5.10' into dev
Conflicts:
src/gui/kernel/qguiapplication.cpp
src/platformsupport/input/libinput/qlibinputpointer.cpp
src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h
src/plugins/platforms/cocoa/qcocoawindow.h
src/testlib/qtestsystem.h
Change-Id: I5975ffb3261c2dd82fe02ec4e57df7c0950226c5
Diffstat (limited to 'src/plugins')
35 files changed, 839 insertions, 693 deletions
diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp index a9e1b655a1..379e428cb0 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.cpp @@ -137,6 +137,17 @@ bool QIBusPlatformInputContext::isValid() const return d->valid && d->busConnected; } +bool QIBusPlatformInputContext::hasCapability(Capability capability) const +{ + switch (capability) { + case QPlatformInputContext::HiddenTextCapability: + return false; // QTBUG-40691, do not show IME on desktop for password entry fields. + default: + break; + } + return true; +} + void QIBusPlatformInputContext::invokeAction(QInputMethod::Action a, int) { if (!d->busConnected) diff --git a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h index aab161c954..f78c99e2bd 100644 --- a/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h +++ b/src/plugins/platforminputcontexts/ibus/qibusplatforminputcontext.h @@ -95,6 +95,7 @@ public: void update(Qt::InputMethodQueries) override; bool filterEvent(const QEvent *event) override; QLocale locale() const override; + bool hasCapability(Capability capability) const override; public Q_SLOTS: void commitText(const QDBusVariant &text); diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 1e6ea70161..6ac5021ea9 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -75,12 +75,12 @@ qtConfig(opengl.*) { RESOURCES += qcocoaresources.qrc -LIBS += -framework AppKit -framework Carbon -framework IOKit -lcups +LIBS += -framework AppKit -framework Carbon -framework IOKit -framework QuartzCore -lcups QT += \ core-private gui-private \ accessibility_support-private clipboard_support-private theme_support-private \ - fontdatabase_support-private graphics_support-private cgl_support-private + fontdatabase_support-private graphics_support-private CONFIG += no_app_extension_api_only diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 61f44e37d1..1f39d787be 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -79,7 +79,15 @@ void QCocoaBackingStore::beginPaint(const QRegion ®ion) void QCocoaBackingStore::endPaint() { QRasterBackingStore::endPaint(); - m_cgImage = m_image.toCGImage(); + + // Prevent potentially costly color conversion by assiging the display + // color space to the backingstore image. + NSView *view = static_cast<QCocoaWindow *>(window()->handle())->view(); + CGColorSpaceRef displayColorSpace = view.window.screen.colorSpace.CGColorSpace; + QCFType<CGImageRef> displayColorSpaceImage = + CGImageCreateCopyWithColorSpace(m_image.toCGImage(), displayColorSpace); + + m_cgImage = displayColorSpaceImage; } #if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) @@ -190,14 +198,15 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo // Create temporary image to use for blitting, without copying image data NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:m_cgImage size:NSZeroSize] autorelease]; - if ([topLevelView hasMask]) { - // FIXME: Implement via NSBezierPath and addClip - CGRect boundingRect = region.boundingRect().toCGRect(); - QCFType<CGImageRef> subMask = CGImageCreateWithImageInRect([topLevelView maskImage], boundingRect); - CGContextClipToMask(graphicsContext.CGContext, boundingRect, subMask); + QRegion clippedRegion = region; + for (QWindow *w = window; w; w = w->parent()) { + if (!w->mask().isEmpty()) { + clippedRegion &= w == window ? w->mask() + : w->mask().translated(window->mapFromGlobal(w->mapToGlobal(QPoint(0, 0)))); + } } - for (const QRect &viewLocalRect : region) { + for (const QRect &viewLocalRect : clippedRegion) { QPoint backingStoreOffset = viewLocalRect.topLeft() + offset; QRect backingStoreRect(backingStoreOffset * devicePixelRatio, viewLocalRect.size() * devicePixelRatio); if (graphicsContext.flipped) // Flip backingStoreRect to match graphics context @@ -225,6 +234,12 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo #endif } + QCocoaWindow *topLevelCocoaWindow = static_cast<QCocoaWindow *>(topLevelWindow->handle()); + if (Q_UNLIKELY(topLevelCocoaWindow->m_needsInvalidateShadow)) { + [topLevelView.window invalidateShadow]; + topLevelCocoaWindow->m_needsInvalidateShadow = false; + } + // ------------------------------------------------------------------------- if (shouldHandleViewLockManually) @@ -234,9 +249,6 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo redrawRoundedBottomCorners([view convertRect:region.boundingRect().toCGRect() toView:nil]); [view.window flushWindow]; } - - // FIXME: Tie to changing window flags and/or mask instead - [view invalidateWindowShadowIfNeeded]; } /* diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 9e688f4d1b..75ac348802 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -42,7 +42,6 @@ #include "qcocoahelpers.h" #include <qdebug.h> #include <QtCore/private/qcore_mac_p.h> -#include <QtCglSupport/private/cglconvenience_p.h> #include <QtPlatformHeaders/qcocoanativecontext.h> #include <dlfcn.h> @@ -154,7 +153,7 @@ QCocoaGLContext::QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLCo QMacAutoReleasePool pool; // For the SG Canvas render thread // create native context for the requested pixel format and share - NSOpenGLPixelFormat *pixelFormat = static_cast <NSOpenGLPixelFormat *>(qcgl_createNSOpenGLPixelFormat(m_format)); + NSOpenGLPixelFormat *pixelFormat = createNSOpenGLPixelFormat(m_format); m_shareContext = share ? static_cast<QCocoaGLContext *>(share)->nsOpenGLContext() : nil; m_context = [[NSOpenGLContext alloc] initWithFormat:pixelFormat shareContext:m_shareContext]; @@ -202,7 +201,6 @@ QVariant QCocoaGLContext::nativeHandle() const return QVariant::fromValue<QCocoaNativeContext>(QCocoaNativeContext(m_context)); } -// Match up with createNSOpenGLPixelFormat! QSurfaceFormat QCocoaGLContext::format() const { return m_format; @@ -362,7 +360,64 @@ void QCocoaGLContext::update() NSOpenGLPixelFormat *QCocoaGLContext::createNSOpenGLPixelFormat(const QSurfaceFormat &format) { - return static_cast<NSOpenGLPixelFormat *>(qcgl_createNSOpenGLPixelFormat(format)); + QVector<NSOpenGLPixelFormatAttribute> attrs; + + if (format.swapBehavior() == QSurfaceFormat::DoubleBuffer + || format.swapBehavior() == QSurfaceFormat::DefaultSwapBehavior) + attrs.append(NSOpenGLPFADoubleBuffer); + else if (format.swapBehavior() == QSurfaceFormat::TripleBuffer) + attrs.append(NSOpenGLPFATripleBuffer); + + + // Select OpenGL profile + attrs << NSOpenGLPFAOpenGLProfile; + if (format.profile() == QSurfaceFormat::CoreProfile) { + if (format.version() >= qMakePair(4, 1)) + attrs << NSOpenGLProfileVersion4_1Core; + else if (format.version() >= qMakePair(3, 2)) + attrs << NSOpenGLProfileVersion3_2Core; + else + attrs << NSOpenGLProfileVersionLegacy; + } else { + attrs << NSOpenGLProfileVersionLegacy; + } + + if (format.depthBufferSize() > 0) + attrs << NSOpenGLPFADepthSize << format.depthBufferSize(); + if (format.stencilBufferSize() > 0) + attrs << NSOpenGLPFAStencilSize << format.stencilBufferSize(); + if (format.alphaBufferSize() > 0) + attrs << NSOpenGLPFAAlphaSize << format.alphaBufferSize(); + if ((format.redBufferSize() > 0) && + (format.greenBufferSize() > 0) && + (format.blueBufferSize() > 0)) { + const int colorSize = format.redBufferSize() + + format.greenBufferSize() + + format.blueBufferSize(); + attrs << NSOpenGLPFAColorSize << colorSize << NSOpenGLPFAMinimumPolicy; + } + + if (format.samples() > 0) { + attrs << NSOpenGLPFAMultisample + << NSOpenGLPFASampleBuffers << (NSOpenGLPixelFormatAttribute) 1 + << NSOpenGLPFASamples << (NSOpenGLPixelFormatAttribute) format.samples(); + } + + if (format.stereo()) + attrs << NSOpenGLPFAStereo; + + attrs << NSOpenGLPFAAllowOfflineRenderers; + + QByteArray useLayer = qgetenv("QT_MAC_WANTS_LAYER"); + if (!useLayer.isEmpty() && useLayer.toInt() > 0) { + // Disable the software rendering fallback. This makes compositing + // OpenGL and raster NSViews using Core Animation layers possible. + attrs << NSOpenGLPFANoRecovery; + } + + attrs << 0; + + return [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs.constData()]; } NSOpenGLContext *QCocoaGLContext::nsOpenGLContext() const diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 1f4f9cd276..7810733255 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -223,7 +223,7 @@ ReturnType qt_msgSendSuper(id receiver, SEL selector, Args... args) typedef ReturnType (*SuperFn)(objc_super *, SEL, Args...); SuperFn superFn = reinterpret_cast<SuperFn>(objc_msgSendSuper); - objc_super sup = { receiver, class_getSuperclass(object_getClass(receiver)) }; + objc_super sup = { receiver, [receiver superclass] }; return superFn(&sup, selector, args...); } @@ -236,7 +236,7 @@ ReturnType qt_msgSendSuper_stret(id receiver, SEL selector, Args... args) typedef void (*SuperStretFn)(ReturnType *, objc_super *, SEL, Args...); SuperStretFn superStretFn = reinterpret_cast<SuperStretFn>(objc_msgSendSuper_stret); - objc_super sup = { receiver, class_getSuperclass(object_getClass(receiver)) }; + objc_super sup = { receiver, [receiver superclass] }; ReturnType ret; superStretFn(&ret, &sup, selector, args...); return ret; diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm index 9e3d747cd7..9221099a57 100644 --- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -124,7 +124,22 @@ void QCocoaInputContext::connectSignals() void QCocoaInputContext::focusObjectChanged(QObject *focusObject) { Q_UNUSED(focusObject); - mWindow = QGuiApplication::focusWindow(); + if (mWindow == QGuiApplication::focusWindow()) { + if (!mWindow) + return; + + QCocoaWindow *window = static_cast<QCocoaWindow *>(mWindow->handle()); + QNSView *view = qnsview_cast(window->view()); + if (!view) + return; + + if (NSTextInputContext *ctxt = [NSTextInputContext currentInputContext]) { + [ctxt discardMarkedText]; + [view cancelComposingText]; + } + } else { + mWindow = QGuiApplication::focusWindow(); + } } void QCocoaInputContext::updateLocale() diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.h b/src/plugins/platforms/cocoa/qcocoakeymapper.h index 4ba615efeb..a75e275077 100644 --- a/src/plugins/platforms/cocoa/qcocoakeymapper.h +++ b/src/plugins/platforms/cocoa/qcocoakeymapper.h @@ -91,8 +91,6 @@ public: private: QCFType<TISInputSourceRef> currentInputSource; - QLocale keyboardInputLocale; - Qt::LayoutDirection keyboardInputDirection; enum { NullMode, UnicodeMode, OtherMode } keyboard_mode; union { const UCKeyboardLayout *unicode; diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm index 5fa062bbe0..80140505d1 100644 --- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm +++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm @@ -376,18 +376,7 @@ bool QCocoaKeyMapper::updateKeyboard() } currentInputSource = source; keyboard_dead = 0; - CFStringRef iso639Code; - CFArrayRef array = static_cast<CFArrayRef>(TISGetInputSourceProperty(currentInputSource, kTISPropertyInputSourceLanguages)); - iso639Code = static_cast<CFStringRef>(CFArrayGetValueAtIndex(array, 0)); // Actually a RFC3066bis, but it's close enough - - if (iso639Code) { - keyboardInputLocale = QLocale(QString::fromCFString(iso639Code)); - keyboardInputDirection = keyboardInputLocale.textDirection(); - } else { - keyboardInputLocale = QLocale::c(); - keyboardInputDirection = Qt::LeftToRight; - } return true; } diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index edefe7bd9a..36655dffab 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -86,6 +86,7 @@ QCocoaMenuBar::~QCocoaMenuBar() // the menu bar was updated qDeleteAll(children()); updateMenuBarImmediately(); + resetKnownMenuItemsToQt(); } } @@ -306,16 +307,9 @@ void QCocoaMenuBar::resetKnownMenuItemsToQt() foreach (QCocoaMenuBar *mb, static_menubars) { foreach (QCocoaMenu *m, mb->m_menus) { foreach (QCocoaMenuItem *i, m->items()) { - switch (i->effectiveRole()) { - case QPlatformMenuItem::CutRole: - case QPlatformMenuItem::CopyRole: - case QPlatformMenuItem::PasteRole: - case QPlatformMenuItem::SelectAllRole: + if (i->effectiveRole() >= QPlatformMenuItem::ApplicationSpecificRole) { [i->nsItem() setTarget:m->nsMenu().delegate]; [i->nsItem() setAction:@selector(itemFired:)]; - break; - default: - break; } } } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 7f5a87ea3d..1244b46620 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -123,6 +123,7 @@ public: bool isForeignWindow() const override; + void requestUpdate() override; void requestActivateWindow() override; WId winId() const override; @@ -174,8 +175,6 @@ public: void setMenubar(QCocoaMenuBar *mb); QCocoaMenuBar *menubar() const; - NSCursor *effectiveWindowCursor() const; - void applyEffectiveWindowCursor(); void setWindowCursor(NSCursor *cursor); void registerTouch(bool enable); @@ -257,7 +256,8 @@ public: // for QNSView QCocoaGLContext *m_glContext; #endif QCocoaMenuBar *m_menubar; - NSCursor *m_windowCursor; + + bool m_needsInvalidateShadow; bool m_hasModalSession; bool m_frameStrutEventsEnabled; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index e906f0fd1c..63ee8c10ac 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -57,6 +57,7 @@ #include <QtGui/private/qhighdpiscaling_p.h> #include <AppKit/AppKit.h> +#include <QuartzCore/QuartzCore.h> #include <QDebug> @@ -149,7 +150,7 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle) , m_glContext(0) #endif , m_menubar(0) - , m_windowCursor(0) + , m_needsInvalidateShadow(false) , m_hasModalSession(false) , m_frameStrutEventsEnabled(false) , m_isExposed(false) @@ -228,7 +229,6 @@ QCocoaWindow::~QCocoaWindow() [m_view release]; [m_nsWindow release]; - [m_windowCursor release]; } QSurfaceFormat QCocoaWindow::format() const @@ -323,6 +323,12 @@ void QCocoaWindow::setVisible(bool visible) // We need to recreate if the modality has changed as the style mask will need updating recreateWindowIfNeeded(); + // We didn't send geometry changes during creation, as that would have confused + // Qt, which expects a show-event to be sent before any resize events. But now + // that the window is made visible, we know that the show-event has been sent + // so we can send the geometry change. FIXME: Get rid of this workaround. + handleGeometryChange(); + // Register popup windows. The Cocoa platform plugin will forward mouse events // to them and close them when needed. if (window()->type() == Qt::Popup || window()->type() == Qt::ToolTip) @@ -693,7 +699,7 @@ bool QCocoaWindow::isOpaque() const bool translucent = window()->format().alphaBufferSize() > 0 || window()->opacity() < 1 - || [qnsview_cast(m_view) hasMask] + || !window()->mask().isEmpty() || (surface()->supportsOpenGL() && openglSourfaceOrder == -1); return !translucent; } @@ -743,17 +749,40 @@ void QCocoaWindow::setOpacity(qreal level) return; m_view.window.alphaValue = level; - m_view.window.opaque = isOpaque(); } void QCocoaWindow::setMask(const QRegion ®ion) { qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setMask" << window() << region; - if (isContentView()) - m_view.window.backgroundColor = !region.isEmpty() ? [NSColor clearColor] : nil; - [qnsview_cast(m_view) setMaskRegion:®ion]; - m_view.window.opaque = isOpaque(); + if (m_view.layer) { + if (!region.isEmpty()) { + QCFType<CGMutablePathRef> maskPath = CGPathCreateMutable(); + for (const QRect &r : region) + CGPathAddRect(maskPath, nullptr, r.toCGRect()); + CAShapeLayer *maskLayer = [CAShapeLayer layer]; + maskLayer.path = maskPath; + m_view.layer.mask = maskLayer; + } else { + m_view.layer.mask = nil; + } + } + + if (isContentView()) { + // Setting the mask requires invalidating the NSWindow shadow, but that needs + // to happen after the backingstore has been redrawn, so that AppKit can pick + // up the new window shape based on the backingstore content. Doing a display + // directly here is not an option, as the window might not be exposed at this + // time, and so would not result in an updated backingstore. + m_needsInvalidateShadow = true; + [m_view setNeedsDisplay:YES]; + + // FIXME: [NSWindow invalidateShadow] has no effect when in layer-backed mode, + // so if the mask is changed after the initial mask is applied, it will not + // result in any visual change to the shadow. This is an Apple bug, and there + // may be ways to work around it, such as calling setFrame on the window to + // trigger some internal invalidation, but that needs more research. + } } bool QCocoaWindow::setKeyboardGrabEnabled(bool grab) @@ -1067,6 +1096,15 @@ void QCocoaWindow::handleExposeEvent(const QRegion ®ion) && !region.isEmpty() && !m_view.hiddenOrHasHiddenAncestor; + + QWindowPrivate *windowPrivate = qt_window_private(window()); + if (m_isExposed && windowPrivate->updateRequestPending) { + // FIXME: Should this logic for expose events be in QGuiApplication? + qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleExposeEvent" << window() << region << "as update request"; + windowPrivate->deliverUpdateRequest(); + return; + } + qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed(); QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(window(), region); } @@ -1237,6 +1275,12 @@ void QCocoaWindow::recreateWindowIfNeeded() updateNSToolbar(); } +void QCocoaWindow::requestUpdate() +{ + qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::requestUpdate" << window(); + [m_view setNeedsDisplay:YES]; +} + void QCocoaWindow::requestActivateWindow() { NSWindow *window = [m_view window]; @@ -1312,11 +1356,6 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel) nsWindow.restorable = NO; nsWindow.level = windowLevel(flags); - if (!isOpaque()) { - nsWindow.backgroundColor = [NSColor clearColor]; - nsWindow.opaque = NO; - } - if (shouldBePanel) { // Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set nsWindow.hidesOnDeactivate = ((type & Qt::Tool) == Qt::Tool) && !alwaysShowToolWindow(); @@ -1515,51 +1554,19 @@ QCocoaMenuBar *QCocoaWindow::menubar() const return m_menubar; } -// Finds the effective cursor for this window by walking up the -// ancestor chain (including this window) until a set cursor is -// found. Returns nil if there is not set cursor. -NSCursor *QCocoaWindow::effectiveWindowCursor() const -{ - - if (m_windowCursor) - return m_windowCursor; - if (!QPlatformWindow::parent()) - return nil; - return static_cast<QCocoaWindow *>(QPlatformWindow::parent())->effectiveWindowCursor(); -} - -// Applies the cursor as returned by effectiveWindowCursor(), handles -// the special no-cursor-set case by setting the arrow cursor. -void QCocoaWindow::applyEffectiveWindowCursor() -{ - NSCursor *effectiveCursor = effectiveWindowCursor(); - if (effectiveCursor) { - [effectiveCursor set]; - } else { - // We wold like to _unset_ the cursor here; but there is no such - // API. Fall back to setting the default arrow cursor. - [[NSCursor arrowCursor] set]; - } -} - void QCocoaWindow::setWindowCursor(NSCursor *cursor) { - if (m_windowCursor == cursor) + // Setting a cursor in a foreign view is not supported + if (isForeignWindow()) return; - // Setting a cursor in a foregin view is not supported. - if (isForeignWindow()) + QNSView *view = qnsview_cast(m_view); + if (cursor == view.cursor) return; - [m_windowCursor release]; - m_windowCursor = cursor; - [m_windowCursor retain]; + view.cursor = cursor; - // The installed view tracking area (see QNSView updateTrackingAreas) will - // handle cursor updates on mouse enter/leave. Handle the case where the - // mouse is on the this window by changing the cursor immediately. - if (m_windowUnderMouse) - applyEffectiveWindowCursor(); + [m_view.window invalidateCursorRectsForView:m_view]; } void QCocoaWindow::registerTouch(bool enable) diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm index f0ea3b1e66..79f8af7783 100644 --- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm +++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm @@ -39,10 +39,14 @@ #include "qmultitouch_mac_p.h" #include "qcocoahelpers.h" +#include <private/qtouchdevice_p.h> QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcInputDevices, "qt.qpa.input.devices") + QHash<qint64, QCocoaTouch*> QCocoaTouch::_currentTouches; +QHash<quint64, QTouchDevice*> QCocoaTouch::_touchDevices; QPointF QCocoaTouch::_screenReferencePos; QPointF QCocoaTouch::_trackpadReferencePos; int QCocoaTouch::_idAssignmentCount = 0; @@ -209,4 +213,19 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch) return touchPoints.values(); } +QTouchDevice *QCocoaTouch::getTouchDevice(QTouchDevice::DeviceType type, quint64 id) +{ + QTouchDevice *ret = _touchDevices.value(id); + if (!ret) { + ret = new QTouchDevice; + ret->setType(type); + ret->setCapabilities(QTouchDevice::Position | QTouchDevice::NormalizedPosition | QTouchDevice::MouseEmulation); + QWindowSystemInterface::registerTouchDevice(ret); + _touchDevices.insert(id, ret); + qCDebug(lcInputDevices) << "touch device" << id << "of type" << type + << "registered as Qt device" << QTouchDevicePrivate::get(ret)->id; + } + return ret; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac_p.h b/src/plugins/platforms/cocoa/qmultitouch_mac_p.h index 77af86c9c7..044bcd1882 100644 --- a/src/plugins/platforms/cocoa/qmultitouch_mac_p.h +++ b/src/plugins/platforms/cocoa/qmultitouch_mac_p.h @@ -66,8 +66,10 @@ class QCocoaTouch public: static QList<QWindowSystemInterface::TouchPoint> getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch); static void setMouseInDraggingState(bool inDraggingState); + static QTouchDevice *getTouchDevice(QTouchDevice::DeviceType type, quint64 id); private: + static QHash<quint64, QTouchDevice*> _touchDevices; static QHash<qint64, QCocoaTouch*> _currentTouches; static QPointF _screenReferencePos; static QPointF _trackpadReferencePos; diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index dcf8cf677a..f8903725a6 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -57,15 +57,13 @@ QT_END_NAMESPACE Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); @interface QT_MANGLE_NAMESPACE(QNSView) : NSView <NSTextInputClient> { - QRegion m_maskRegion; - CGImageRef m_maskImage; - bool m_shouldInvalidateWindowShadow; QPointer<QCocoaWindow> m_platformWindow; NSTrackingArea *m_trackingArea; Qt::MouseButtons m_buttons; Qt::MouseButtons m_acceptedMouseDowns; Qt::MouseButtons m_frameStrutButtons; QString m_composingText; + QPointer<QObject> m_composingFocusObject; bool m_sendKeyEvent; QStringList *currentCustomDragTypes; bool m_dontOverrideCtrlLMB; @@ -85,23 +83,22 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); QSet<quint32> m_acceptedKeyDowns; } +@property (nonatomic, retain) NSCursor *cursor; + - (id)init; - (id)initWithCocoaWindow:(QCocoaWindow *)platformWindow; #ifndef QT_NO_OPENGL - (void)setQCocoaGLContext:(QCocoaGLContext *)context; #endif -- (void)setMaskRegion:(const QRegion *)region; -- (CGImageRef)maskImage; -- (void)invalidateWindowShadowIfNeeded; - (void)drawRect:(NSRect)dirtyRect; - (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification; - (void)viewDidHide; - (void)removeFromSuperview; +- (void)cancelComposingText; - (BOOL)isFlipped; - (BOOL)acceptsFirstResponder; - (BOOL)becomeFirstResponder; -- (BOOL)hasMask; - (BOOL)isOpaque; - (void)convertFromScreen:(NSPoint)mouseLocation toWindowPoint:(QPointF *)qtWindowPoint andScreenPoint:(QPointF *)qtScreenPoint; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 924173b4c5..643d3b3a30 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -53,6 +53,7 @@ #include <QtCore/qsysinfo.h> #include <private/qguiapplication_p.h> #include <private/qcoregraphics_p.h> +#include <private/qwindow_p.h> #include "qcocoabackingstore.h" #ifndef QT_NO_OPENGL #include "qcocoaglcontext.h" @@ -69,8 +70,6 @@ Q_LOGGING_CATEGORY(lcQpaGestures, "qt.qpa.input.gestures") #endif Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") -static QTouchDevice *touchDevice = 0; - @interface QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) : NSObject { QNSView *view; @@ -113,7 +112,7 @@ static QTouchDevice *touchDevice = 0; - (void)cursorUpdate:(NSEvent *)theEvent { - [self cursorUpdate:theEvent]; + [view cursorUpdate:theEvent]; } @end @@ -128,8 +127,6 @@ static QTouchDevice *touchDevice = 0; - (id) init { if (self = [super initWithFrame:NSZeroRect]) { - m_maskImage = 0; - m_shouldInvalidateWindowShadow = false; m_buttons = Qt::NoButton; m_acceptedMouseDowns = Qt::NoButton; m_frameStrutButtons = Qt::NoButton; @@ -147,28 +144,19 @@ static QTouchDevice *touchDevice = 0; m_scrolling = false; m_updatingDrag = false; m_currentlyInterpretedKeyEvent = 0; - - if (!touchDevice) { - touchDevice = new QTouchDevice; - touchDevice->setType(QTouchDevice::TouchPad); - touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::NormalizedPosition | QTouchDevice::MouseEmulation); - QWindowSystemInterface::registerTouchDevice(touchDevice); - } - m_isMenuView = false; self.focusRingType = NSFocusRingTypeNone; + self.cursor = nil; } return self; } - (void)dealloc { - CGImageRelease(m_maskImage); if (m_trackingArea) { [self removeTrackingArea:m_trackingArea]; [m_trackingArea release]; } - m_maskImage = 0; [m_inputSource release]; [[NSNotificationCenter defaultCenter] removeObserver:self]; [m_mouseMoveHelper release]; @@ -304,11 +292,6 @@ static QTouchDevice *touchDevice = 0; [super removeFromSuperview]; } -- (BOOL) hasMask -{ - return !m_maskRegion.isEmpty(); -} - - (BOOL) isOpaque { if (!m_platformWindow) @@ -316,48 +299,6 @@ static QTouchDevice *touchDevice = 0; return m_platformWindow->isOpaque(); } -- (void) setMaskRegion:(const QRegion *)region -{ - m_shouldInvalidateWindowShadow = true; - m_maskRegion = *region; - if (m_maskImage) - CGImageRelease(m_maskImage); - if (region->isEmpty()) { - m_maskImage = 0; - return; - } - - const QRect &rect = region->boundingRect(); - QImage tmp(rect.size(), QImage::Format_RGB32); - tmp.fill(Qt::white); - QPainter p(&tmp); - p.setClipRegion(*region); - p.fillRect(rect, Qt::black); - p.end(); - QImage maskImage = QImage(rect.size(), QImage::Format_Indexed8); - for (int y=0; y<rect.height(); ++y) { - const uint *src = (const uint *) tmp.constScanLine(y); - uchar *dst = maskImage.scanLine(y); - for (int x=0; x<rect.width(); ++x) { - dst[x] = src[x] & 0xff; - } - } - m_maskImage = qt_mac_toCGImageMask(maskImage); -} - -- (CGImageRef)maskImage -{ - return m_maskImage; -} - -- (void)invalidateWindowShadowIfNeeded -{ - if (m_shouldInvalidateWindowShadow && m_platformWindow->isContentView()) { - [m_platformWindow->nativeWindow() invalidateShadow]; - m_shouldInvalidateWindowShadow = false; - } -} - - (void)drawRect:(NSRect)dirtyRect { Q_UNUSED(dirtyRect); @@ -382,6 +323,17 @@ static QTouchDevice *touchDevice = 0; #endif m_platformWindow->handleExposeEvent(exposedRegion); + + // A call to QWindow::requestUpdate was issued during the expose event, but + // AppKit will reset the needsDisplay state of the view after completing the + // current display cycle, so we need to defer the request to redisplay. + // FIXME: Perhaps this should be a trigger to enable CADisplayLink? + if (qt_window_private(m_platformWindow->window())->updateRequestPending) { + qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:] deferring setNeedsDisplay"; + dispatch_async(dispatch_get_main_queue (), ^{ + [self setNeedsDisplay:YES]; + }); + } } - (BOOL)wantsUpdateLayer @@ -614,7 +566,8 @@ static QTouchDevice *touchDevice = 0; Q_UNUSED(qtScreenPoint); // Maintain masked state for the button for use by MouseDragged and MouseUp. - const bool masked = [self hasMask] && !m_maskRegion.contains(qtWindowPoint.toPoint()); + QRegion mask = m_platformWindow->window()->mask(); + const bool masked = !mask.isEmpty() && !mask.contains(qtWindowPoint.toPoint()); if (masked) m_acceptedMouseDowns &= ~button; else @@ -712,8 +665,8 @@ static QTouchDevice *touchDevice = 0; [self convertFromScreen:[self screenMousePoint:theEvent] toWindowPoint:&qtWindowPoint andScreenPoint:&qtScreenPoint]; Q_UNUSED(qtScreenPoint); - const bool masked = [self hasMask] && !m_maskRegion.contains(qtWindowPoint.toPoint()); - + QRegion mask = m_platformWindow->window()->mask(); + const bool masked = !mask.isEmpty() && !mask.contains(qtWindowPoint.toPoint()); // Maintain masked state for the button for use by MouseDragged and Up. if (masked) m_acceptedMouseDowns &= ~Qt::LeftButton; @@ -826,8 +779,16 @@ static QTouchDevice *touchDevice = 0; - (void)cursorUpdate:(NSEvent *)theEvent { - Q_UNUSED(theEvent); - m_platformWindow->applyEffectiveWindowCursor(); + qCDebug(lcQpaCocoaWindow) << "[QNSView cursorUpdate:]" << self.cursor; + + // Note: We do not get this callback when moving from a subview that + // uses the legacy cursorRect API, so the cursor is reset to the arrow + // cursor. See rdar://34183708 + + if (self.cursor) + [self.cursor set]; + else + [super cursorUpdate:theEvent]; } - (void)mouseMovedImpl:(NSEvent *)theEvent @@ -1094,8 +1055,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const NSTimeInterval timestamp = [event timestamp]; const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points; - QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, touchDevice, points); + qCDebug(lcQpaTouch) << "touchesBeganWithEvent" << points << "from device" << hex << [event deviceID]; + QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } - (void)touchesMovedWithEvent:(NSEvent *)event @@ -1105,8 +1066,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const NSTimeInterval timestamp = [event timestamp]; const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points; - QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, touchDevice, points); + qCDebug(lcQpaTouch) << "touchesMovedWithEvent" << points << "from device" << hex << [event deviceID]; + QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } - (void)touchesEndedWithEvent:(NSEvent *)event @@ -1116,8 +1077,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const NSTimeInterval timestamp = [event timestamp]; const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points; - QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, touchDevice, points); + qCDebug(lcQpaTouch) << "touchesEndedWithEvent" << points << "from device" << hex << [event deviceID]; + QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } - (void)touchesCancelledWithEvent:(NSEvent *)event @@ -1127,8 +1088,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const NSTimeInterval timestamp = [event timestamp]; const QList<QWindowSystemInterface::TouchPoint> points = QCocoaTouch::getCurrentTouchPointList(event, [self shouldSendSingleTouch]); - qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points; - QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, touchDevice, points); + qCDebug(lcQpaTouch) << "touchesCancelledWithEvent" << points << "from device" << hex << [event deviceID]; + QWindowSystemInterface::handleTouchEvent(m_platformWindow->window(), timestamp * 1000, QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), points); } #ifndef QT_NO_GESTURES @@ -1158,12 +1119,12 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) if ([self handleGestureAsBeginEnd:event]) return; - qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification]; + qCDebug(lcQpaGestures) << "magnifyWithEvent" << [event magnification] << "from device" << hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), timestamp, Qt::ZoomNativeGesture, + QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::ZoomNativeGesture, [event magnification], windowPoint, screenPoint); } @@ -1173,12 +1134,12 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) return; static bool zoomIn = true; - qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn; + qCDebug(lcQpaGestures) << "smartMagnifyWithEvent" << zoomIn << "from device" << hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), timestamp, Qt::SmartZoomNativeGesture, + QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::SmartZoomNativeGesture, zoomIn ? 1.0f : 0.0f, windowPoint, screenPoint); zoomIn = !zoomIn; } @@ -1195,7 +1156,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) QPointF windowPoint; QPointF screenPoint; [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), timestamp, Qt::RotateNativeGesture, + QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::RotateNativeGesture, -[event rotation], windowPoint, screenPoint); } @@ -1204,7 +1165,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) if (!m_platformWindow) return; - qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY]; + qCDebug(lcQpaGestures) << "swipeWithEvent" << [event deltaX] << [event deltaY] << "from device" << hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; @@ -1220,7 +1181,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) else if ([event deltaY] == -1) angle = 270.0f; - QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), timestamp, Qt::SwipeNativeGesture, + QWindowSystemInterface::handleGestureEventWithRealValue(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::SwipeNativeGesture, angle, windowPoint, screenPoint); } @@ -1233,8 +1194,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) QPointF windowPoint; QPointF screenPoint; [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint; - QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), timestamp, Qt::BeginNativeGesture, + qCDebug(lcQpaGestures) << "beginGestureWithEvent @" << windowPoint << "from device" << hex << [event deviceID]; + QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::BeginNativeGesture, windowPoint, screenPoint); } @@ -1243,12 +1204,12 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) if (!m_platformWindow) return; - qCDebug(lcQpaGestures) << "endGestureWithEvent"; + qCDebug(lcQpaGestures) << "endGestureWithEvent" << "from device" << hex << [event deviceID]; const NSTimeInterval timestamp = [event timestamp]; QPointF windowPoint; QPointF screenPoint; [self convertFromScreen:[self screenMousePoint:event] toWindowPoint:&windowPoint andScreenPoint:&screenPoint]; - QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), timestamp, Qt::EndNativeGesture, + QWindowSystemInterface::handleGestureEvent(m_platformWindow->window(), QCocoaTouch::getTouchDevice(QTouchDevice::TouchPad, [event deviceID]), timestamp, Qt::EndNativeGesture, windowPoint, screenPoint); } #endif // QT_NO_GESTURES @@ -1377,10 +1338,16 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) QChar ch = QChar::ReplacementCharacter; int keyCode = Qt::Key_unknown; - if ([characters length] != 0) { + + // If a dead key occurs as a result of pressing a key combination then + // characters will have 0 length, but charactersIgnoringModifiers will + // have a valid character in it. This enables key combinations such as + // ALT+E to be used as a shortcut with an English keyboard even though + // pressing ALT+E will give a dead key while doing normal text input. + if ([characters length] != 0 || [charactersIgnoringModifiers length] != 0) { if (((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0)) ch = QChar([charactersIgnoringModifiers characterAtIndex:0]); - else + else if ([characters length] != 0) ch = QChar([characters characterAtIndex:0]); keyCode = [self convertKeyCode:ch]; } @@ -1573,6 +1540,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) } m_composingText.clear(); + m_composingFocusObject = nullptr; } - (void) setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange @@ -1627,6 +1595,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) m_composingText = preeditString; if (QObject *fo = m_platformWindow->window()->focusObject()) { + m_composingFocusObject = fo; QInputMethodQueryEvent queryEvent(Qt::ImEnabled); if (QCoreApplication::sendEvent(fo, &queryEvent)) { if (queryEvent.value(Qt::ImEnabled).toBool()) { @@ -1639,6 +1608,25 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) } } +- (void)cancelComposingText +{ + if (m_composingText.isEmpty()) + return; + + if (m_composingFocusObject) { + QInputMethodQueryEvent queryEvent(Qt::ImEnabled); + if (QCoreApplication::sendEvent(m_composingFocusObject, &queryEvent)) { + if (queryEvent.value(Qt::ImEnabled).toBool()) { + QInputMethodEvent e; + QCoreApplication::sendEvent(m_composingFocusObject, &e); + } + } + } + + m_composingText.clear(); + m_composingFocusObject = nullptr; +} + - (void) unmarkText { if (!m_composingText.isEmpty()) { @@ -1654,6 +1642,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) } } m_composingText.clear(); + m_composingFocusObject = nullptr; } - (BOOL) hasMarkedText diff --git a/src/plugins/platforms/cocoa/qnswindow.h b/src/plugins/platforms/cocoa/qnswindow.h index ac9cbb978f..1258fddb31 100644 --- a/src/plugins/platforms/cocoa/qnswindow.h +++ b/src/plugins/platforms/cocoa/qnswindow.h @@ -58,6 +58,8 @@ QT_FORWARD_DECLARE_CLASS(QCocoaWindow) - (void)sendEvent:(NSEvent*)theEvent; - (void)closeAndRelease; - (void)dealloc; +- (BOOL)isOpaque; +- (NSColor *)backgroundColor; @property (nonatomic, readonly) QCocoaWindow *platformWindow; @end diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm index e5ddd3ca0f..513c7f22b5 100644 --- a/src/plugins/platforms/cocoa/qnswindow.mm +++ b/src/plugins/platforms/cocoa/qnswindow.mm @@ -153,6 +153,28 @@ static bool isMouseEvent(NSEvent *ev) return canBecomeMain; } +- (BOOL)isOpaque +{ + return self.platformWindow ? + self.platformWindow->isOpaque() : qt_objcDynamicSuper(); +} + +/*! + Borderless windows need a transparent background + + Technically windows with NSTexturedBackgroundWindowMask (such + as windows with unified toolbars) need to draw the textured + background of the NSWindow, and can't have a transparent + background, but as NSBorderlessWindowMask is 0, you can't + have a window with NSTexturedBackgroundWindowMask that is + also borderless. +*/ +- (NSColor *)backgroundColor +{ + return self.styleMask == NSBorderlessWindowMask + ? [NSColor clearColor] : qt_objcDynamicSuper(); +} + - (void)sendEvent:(NSEvent*)theEvent { // We might get events for a NSWindow after the corresponding platform diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp index 64d0d9b515..2e84915c80 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp @@ -63,83 +63,12 @@ private: QAtomicInt running; -static Qt::MouseButtons translateMouseButtons(int s) -{ - Qt::MouseButtons ret = 0; - if (s & XCB_BUTTON_MASK_1) - ret |= Qt::LeftButton; - if (s & XCB_BUTTON_MASK_2) - ret |= Qt::MidButton; - if (s & XCB_BUTTON_MASK_3) - ret |= Qt::RightButton; - return ret; -} - -static Qt::MouseButton translateMouseButton(xcb_button_t s) -{ - switch (s) { - case 1: return Qt::LeftButton; - case 2: return Qt::MidButton; - case 3: return Qt::RightButton; - // Button values 4-7 were already handled as Wheel events, and won't occur here. - case 8: return Qt::BackButton; // Also known as Qt::ExtraButton1 - case 9: return Qt::ForwardButton; // Also known as Qt::ExtraButton2 - case 10: return Qt::ExtraButton3; - case 11: return Qt::ExtraButton4; - case 12: return Qt::ExtraButton5; - case 13: return Qt::ExtraButton6; - case 14: return Qt::ExtraButton7; - case 15: return Qt::ExtraButton8; - case 16: return Qt::ExtraButton9; - case 17: return Qt::ExtraButton10; - case 18: return Qt::ExtraButton11; - case 19: return Qt::ExtraButton12; - case 20: return Qt::ExtraButton13; - case 21: return Qt::ExtraButton14; - case 22: return Qt::ExtraButton15; - case 23: return Qt::ExtraButton16; - case 24: return Qt::ExtraButton17; - case 25: return Qt::ExtraButton18; - case 26: return Qt::ExtraButton19; - case 27: return Qt::ExtraButton20; - case 28: return Qt::ExtraButton21; - case 29: return Qt::ExtraButton22; - case 30: return Qt::ExtraButton23; - case 31: return Qt::ExtraButton24; - default: return Qt::NoButton; - } -} - void EventReader::run() { - Qt::MouseButtons buttons; - xcb_generic_event_t *event = nullptr; while (running.load() && (event = xcb_wait_for_event(m_integration->connection()))) { uint response_type = event->response_type & ~0x80; switch (response_type) { - case XCB_BUTTON_PRESS: { - xcb_button_press_event_t *press = (xcb_button_press_event_t *)event; - QPoint p(press->event_x, press->event_y); - buttons = (buttons & ~0x7) | translateMouseButtons(press->state); - buttons |= translateMouseButton(press->detail); - QWindowSystemInterface::handleMouseEvent(0, press->time, p, p, buttons); - break; - } - case XCB_BUTTON_RELEASE: { - xcb_button_release_event_t *release = (xcb_button_release_event_t *)event; - QPoint p(release->event_x, release->event_y); - buttons = (buttons & ~0x7) | translateMouseButtons(release->state); - buttons &= ~translateMouseButton(release->detail); - QWindowSystemInterface::handleMouseEvent(0, release->time, p, p, buttons); - break; - } - case XCB_MOTION_NOTIFY: { - xcb_motion_notify_event_t *motion = (xcb_motion_notify_event_t *)event; - QPoint p(motion->event_x, motion->event_y); - QWindowSystemInterface::handleMouseEvent(0, motion->time, p, p, buttons); - break; - } case XCB_CLIENT_MESSAGE: { xcb_client_message_event_t *client = (xcb_client_message_event_t *) event; const xcb_atom_t *atoms = m_integration->atoms(); diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index f49f81912e..cf7680529a 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -372,7 +372,7 @@ static bool rootLevelRunLoopIntegration() // We treat applicationWillTerminate as SIGTERM, even if it can't be ignored, // and follow the bash convention of encoding the signal number in the upper // four bits of the exit code (exit(3) will only pass on the lower 8 bits). -static const char kApplicationWillTerminateExitCode = SIGTERM | 0x80; +static const char kApplicationWillTerminateExitCode = char(SIGTERM | 0x80); + (void)applicationWillTerminate { diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm index 58b2b36b49..9d05b792c2 100644 --- a/src/plugins/platforms/ios/qiosmessagedialog.mm +++ b/src/plugins/platforms/ios/qiosmessagedialog.mm @@ -39,7 +39,6 @@ #import <UIKit/UIKit.h> -#include <QtCore/qoperatingsystemversion.h> #include <QtGui/qwindow.h> #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> @@ -109,8 +108,7 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win Q_UNUSED(windowFlags); if (m_alertController // Ensure that the dialog is not showing already || !options() // Some message dialogs don't have options (QErrorMessage) - || windowModality == Qt::NonModal // We can only do modal dialogs - || QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) // API limitation + || windowModality == Qt::NonModal) // We can only do modal dialogs return false; m_alertController = [[UIAlertController diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 3514bf63bb..e8854a4c4b 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -45,7 +45,6 @@ #include "qiosapplicationdelegate.h" #include "qiosviewcontroller.h" #include "quiview.h" -#include <QtCore/qoperatingsystemversion.h> #include <QtGui/private/qwindow_p.h> #include <private/qcoregraphics_p.h> @@ -275,14 +274,6 @@ void QIOSScreen::updateProperties() if (m_uiScreen == [UIScreen mainScreen]) { Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation(UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation)); - if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { - // On iOS < 8.0 the UIScreen geometry is always in portait, and the system applies - // the screen rotation to the root view-controller's view instead of directly to the - // screen, like iOS 8 and above does. - m_geometry = mapBetween(Qt::PortraitOrientation, statusBarOrientation, m_geometry); - m_availableGeometry = transformBetween(Qt::PortraitOrientation, statusBarOrientation, m_geometry).mapRect(m_availableGeometry); - } - QIOSViewController *qtViewController = [m_uiWindow.rootViewController isKindOfClass:[QIOSViewController class]] ? static_cast<QIOSViewController *>(m_uiWindow.rootViewController) : nil; @@ -302,20 +293,15 @@ void QIOSScreen::updateProperties() #endif if (m_geometry != previousGeometry) { - QRectF physicalGeometry; - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 8)) { - // We can't use the primaryOrientation of screen(), as we haven't reported the new geometry yet - Qt::ScreenOrientation primaryOrientation = m_geometry.width() >= m_geometry.height() ? - Qt::LandscapeOrientation : Qt::PortraitOrientation; - - // On iPhone 6+ devices, or when display zoom is enabled, the render buffer is scaled - // before being output on the physical display. We have to take this into account when - // computing the physical size. Note that unlike the native bounds, the physical size - // follows the primary orientation of the screen. - physicalGeometry = mapBetween(nativeOrientation(), primaryOrientation, QRectF::fromCGRect(m_uiScreen.nativeBounds).toRect()); - } else { - physicalGeometry = QRectF(0, 0, m_geometry.width() * devicePixelRatio(), m_geometry.height() * devicePixelRatio()); - } + // We can't use the primaryOrientation of screen(), as we haven't reported the new geometry yet + Qt::ScreenOrientation primaryOrientation = m_geometry.width() >= m_geometry.height() ? + Qt::LandscapeOrientation : Qt::PortraitOrientation; + + // On iPhone 6+ devices, or when display zoom is enabled, the render buffer is scaled + // before being output on the physical display. We have to take this into account when + // computing the physical size. Note that unlike the native bounds, the physical size + // follows the primary orientation of the screen. + const QRectF physicalGeometry = mapBetween(nativeOrientation(), primaryOrientation, QRectF::fromCGRect(m_uiScreen.nativeBounds).toRect()); static const qreal millimetersPerInch = 25.4; m_physicalSize = physicalGeometry.size() / m_physicalDpi * millimetersPerInch; diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm index 034c1bba08..fe3c29d037 100644 --- a/src/plugins/platforms/ios/qiostextinputoverlay.mm +++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm @@ -229,12 +229,6 @@ static void executeBlockWithoutAnimation(Block block) borderLayer.cornerRadius = cornerRadius; borderLayer.borderColor = [[UIColor lightGrayColor] CGColor]; [self addSublayer:borderLayer]; - - if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 7)) { - // [UIView snapshotViewAfterScreenUpdates:] is available since iOS 7.0. - // Just silently ignore showing the loupe for older versions. - self.hidden = YES; - } } return self; @@ -278,9 +272,6 @@ static void executeBlockWithoutAnimation(Block block) - (void)display { - if (QOperatingSystemVersion::current() < QOperatingSystemVersion(QOperatingSystemVersion::IOS, 7)) - return; - // Take a snapshow of the target view, magnify the area around the focal // point, and add the snapshow layer as a child of the container layer // to make it look like a loupe. Then place this layer at the position of diff --git a/src/plugins/platforms/vnc/qvncintegration.cpp b/src/plugins/platforms/vnc/qvncintegration.cpp index 8516e994f5..1e2cf6292c 100644 --- a/src/plugins/platforms/vnc/qvncintegration.cpp +++ b/src/plugins/platforms/vnc/qvncintegration.cpp @@ -52,9 +52,6 @@ #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatforminputcontextfactory_p.h> #include <private/qinputdevicemanager_p_p.h> -#if QT_CONFIG(libinput) -#include <QtInputSupport/private/qlibinputhandler_p.h> -#endif #include <QtCore/QRegularExpression> diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json index 69f4a54d05..d1e9f85247 100644 --- a/src/plugins/platforms/windows/openglblacklists/default.json +++ b/src/plugins/platforms/windows/openglblacklists/default.json @@ -126,6 +126,21 @@ "features": [ "disable_desktopgl" ] - } + }, + { + "id": 11, + "description": "Intel driver version 8.15.10.1749 causes GPU process hangs (QTBUG-56360)", + "vendor_id": "0x8086", + "os": { + "type": "win" + }, + "driver_version": { + "op": "=", + "value": "8.15.10.1749" + }, + "features": [ + "disable_desktopgl", "disable_d3d11", "disable_d3d9" + ] + } ] } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 2848bb4a4e..45d6b50162 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -65,6 +65,7 @@ #include <qpa/qwindowsysteminterface.h> #include <qpa/qplatformnativeinterface.h> #include <QtGui/QGuiApplication> +#include <QtGui/QOpenGLContext> #include <QtCore/QSet> #include <QtCore/QHash> @@ -867,6 +868,18 @@ static inline bool resizeOnDpiChanged(const QWindow *w) return result; } +static bool shouldHaveNonClientDpiScaling(const QWindow *window) +{ + return QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS10 + && window->isTopLevel() + && !window->property(QWindowsWindow::embeddedNativeParentHandleProperty).isValid() +#if QT_CONFIG(opengl) // /QTBUG-62901, EnableNonClientDpiScaling has problems with GL + && (window->surfaceType() != QSurface::OpenGLSurface + || QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) +#endif + ; +} + /*! \brief Main windows procedure registered for windows. @@ -988,10 +1001,8 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, d->m_creationContext->obtainedGeometry.moveTo(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); return true; case QtWindows::NonClientCreate: - if (QSysInfo::windowsVersion() >= QSysInfo::WV_WINDOWS10 && d->m_creationContext->window->isTopLevel() - && !d->m_creationContext->window->property(QWindowsWindow::embeddedNativeParentHandleProperty).isValid()) { + if (shouldHaveNonClientDpiScaling(d->m_creationContext->window)) enableNonClientDpiScaling(msg.hwnd); - } return false; case QtWindows::CalculateSize: return QWindowsGeometryHint::handleCalculateSize(d->m_creationContext->customMargins, msg, result); diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 857db7a65c..aa6454ef63 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -44,7 +44,7 @@ # include "qwindowsclipboard.h" #endif #include "qwindowsintegration.h" -#include "qwindowsole.h" +#include "qwindowsdropdataobject.h" #include <QtCore/qt_windows.h> #include "qwindowswindow.h" #include "qwindowsmousehandler.h" @@ -673,7 +673,7 @@ Qt::DropAction QWindowsDrag::drag(QDrag *drag) QWindowsDrag::m_canceled = false; QWindowsOleDropSource *windowDropSource = new QWindowsOleDropSource(this); windowDropSource->createCursors(); - QWindowsOleDataObject *dropDataObject = new QWindowsOleDataObject(dropData); + QWindowsDropDataObject *dropDataObject = new QWindowsDropDataObject(dropData); const Qt::DropActions possibleActions = drag->supportedActions(); const DWORD allowedEffects = translateToWinDragEffects(possibleActions); qCDebug(lcQpaMime) << '>' << __FUNCTION__ << "possible Actions=0x" diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp new file mode 100644 index 0000000000..bd532ab70e --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 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-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwindowsdropdataobject.h" + +#include <QtCore/QUrl> +#include <QtCore/QMimeData> + +QT_BEGIN_NAMESPACE + +/*! + \class QWindowsDropDataObject + \brief QWindowsOleDataObject subclass specialized for handling Drag&Drop. + + Only allows "text/uri-list" data to be exported as CF_HDROP, to allow dropped + files to be attached to Office applications (instead of adding an URL link). + + \internal + \ingroup qt-lighthouse-win +*/ + +QWindowsDropDataObject::QWindowsDropDataObject(QMimeData *mimeData) : + QWindowsOleDataObject(mimeData) +{ +} + +QWindowsDropDataObject::~QWindowsDropDataObject() +{ +} + +STDMETHODIMP +QWindowsDropDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium) +{ + if (shouldIgnore(pformatetc)) + return ResultFromScode(DATA_E_FORMATETC); + + return QWindowsOleDataObject::GetData(pformatetc, pmedium); +} + +STDMETHODIMP +QWindowsDropDataObject::QueryGetData(LPFORMATETC pformatetc) +{ + if (shouldIgnore(pformatetc)) + return ResultFromScode(DATA_E_FORMATETC); + + return QWindowsOleDataObject::QueryGetData(pformatetc); +} + +// If the data is text/uri-list for local files, tell we can only export it as CF_HDROP. +bool QWindowsDropDataObject::shouldIgnore(LPFORMATETC pformatetc) const +{ + QMimeData *dropData = mimeData(); + + if (dropData && dropData->hasFormat(QStringLiteral("text/uri-list")) && (pformatetc->cfFormat != CF_HDROP)) { + QList<QUrl> urls = dropData->urls(); + return std::any_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); }); + } + + return false; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.h b/src/plugins/platforms/windows/qwindowsdropdataobject.h new file mode 100644 index 0000000000..5ef72c9336 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsdropdataobject.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 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-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSDROPDATAOBJECT_H +#define QWINDOWSDROPDATAOBJECT_H + +#include "qwindowsole.h" + +QT_BEGIN_NAMESPACE + +class QWindowsDropDataObject : public QWindowsOleDataObject +{ +public: + explicit QWindowsDropDataObject(QMimeData *mimeData); + virtual ~QWindowsDropDataObject(); + + // overridden IDataObject methods + STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium); + STDMETHOD(QueryGetData)(LPFORMATETC pformatetc); + +private: + bool shouldIgnore(LPFORMATETC pformatetc) const; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSDROPDATAOBJECT_H diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 3ecd164c74..b7790a66e3 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -19,6 +19,7 @@ SOURCES += \ $$PWD/qwindowskeymapper.cpp \ $$PWD/qwindowsmousehandler.cpp \ $$PWD/qwindowsole.cpp \ + $$PWD/qwindowsdropdataobject.cpp \ $$PWD/qwindowsmime.cpp \ $$PWD/qwindowsinternalmimedata.cpp \ $$PWD/qwindowscursor.cpp \ @@ -41,6 +42,7 @@ HEADERS += \ $$PWD/qwindowsmousehandler.h \ $$PWD/qtwindowsglobal.h \ $$PWD/qwindowsole.h \ + $$PWD/qwindowsdropdataobject.h \ $$PWD/qwindowsmime.h \ $$PWD/qwindowsinternalmimedata.h \ $$PWD/qwindowscursor.h \ diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 16762cf6d6..05585ba07c 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -74,10 +74,18 @@ #include <qgroupbox.h> #include <qhash.h> #include <qheaderview.h> +#if QT_CONFIG(lineedit) #include <qlineedit.h> +#endif +#if QT_CONFIG(mainwindow) #include <qmainwindow.h> +#endif +#if QT_CONFIG(mdiarea) #include <qmdisubwindow.h> +#endif +#if QT_CONFIG(menubar) #include <qmenubar.h> +#endif #include <qpaintdevice.h> #include <qpainter.h> #include <qpixmapcache.h> @@ -95,7 +103,9 @@ #if QT_CONFIG(scrollbar) #include <qscrollbar.h> #endif +#if QT_CONFIG(sizegrip) #include <qsizegrip.h> +#endif #include <qstyleoption.h> #include <qtoolbar.h> #if QT_CONFIG(toolbutton) @@ -327,6 +337,40 @@ static bool setupScroller(NSScroller *scroller, const QStyleOptionSlider *sb) return true; } +static bool setupSlider(NSSlider *slider, const QStyleOptionSlider *sl) +{ + if (sl->minimum >= sl->maximum) + return false; + + slider.frame = sl->rect.toCGRect(); + slider.minValue = sl->minimum; + slider.maxValue = sl->maximum; + slider.intValue = sl->sliderPosition; + slider.enabled = sl->state & QStyle::State_Enabled; + if (sl->tickPosition != QSlider::NoTicks) { + // Set numberOfTickMarks, but TicksBothSides will be treated differently + int interval = sl->tickInterval; + if (interval == 0) { + interval = sl->pageStep; + if (interval == 0) + interval = sl->singleStep; + if (interval == 0) + interval = 1; // return false? + } + slider.numberOfTickMarks = 1 + ((sl->maximum - sl->minimum) / interval); + + const bool ticksAbove = sl->tickPosition == QSlider::TicksAbove; + if (sl->orientation == Qt::Horizontal) + slider.tickMarkPosition = ticksAbove ? NSTickMarkAbove : NSTickMarkBelow; + else + slider.tickMarkPosition = ticksAbove ? NSTickMarkLeft : NSTickMarkRight; + } else { + slider.numberOfTickMarks = 0; + } + + return true; +} + static bool isInMacUnifiedToolbarArea(QWindow *window, int windowY) { QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); @@ -656,7 +700,6 @@ const int macItemFrame = 2; // menu item frame width const int macItemHMargin = 3; // menu item hor text margin const int macRightBorder = 12; // right border on mac const ThemeWindowType QtWinType = kThemeDocumentWindow; // Window type we use for QTitleBar. -QPixmap *qt_mac_backgroundPattern = 0; // stores the standard widget background. /***************************************************************************** QMacCGStyle utility functions @@ -799,17 +842,17 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg else if (qobject_cast<const QProgressBar *>(widg)) ct = QStyle::CT_ProgressBar; #endif -#ifndef QT_NO_LINEEDIT +#if QT_CONFIG(lineedit) else if (qobject_cast<const QLineEdit *>(widg)) ct = QStyle::CT_LineEdit; #endif else if (qobject_cast<const QHeaderView *>(widg)) ct = QStyle::CT_HeaderSection; -#ifndef QT_NO_MENUBAR +#if QT_CONFIG(menubar) else if (qobject_cast<const QMenuBar *>(widg)) ct = QStyle::CT_MenuBar; #endif -#ifndef QT_NO_SIZEGRIP +#if QT_CONFIG(sizegrip) else if (qobject_cast<const QSizeGrip *>(widg)) ct = QStyle::CT_SizeGrip; #endif @@ -897,7 +940,7 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg gbi.size = sz == QStyleHelper::SizeSmall ? kHIThemeGrowBoxSizeSmall : kHIThemeGrowBoxSizeNormal; if (HIThemeGetGrowBoxBounds(&p, &gbi, &r) == noErr) { int width = 0; -#ifndef QT_NO_MDIAREA +#if QT_CONFIG(mdiarea) if (widg && qobject_cast<QMdiSubWindow *>(widg->parentWidget())) width = r.size.width; #endif @@ -1085,7 +1128,7 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS return QStyleHelper::SizeLarge; } -#ifndef QT_NO_MAINWINDOW +#if QT_CONFIG(mainwindow) if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) { //if (small.width() != -1 || small.height() != -1) return QStyleHelper::SizeSmall; @@ -1732,7 +1775,7 @@ void QMacStylePrivate::drawCombobox(const CGRect &outerBounds, const HIThemeButt void QMacStylePrivate::drawTableHeader(const CGRect &outerBounds, bool drawTopBorder, bool drawLeftBorder, const HIThemeButtonDrawInfo &bdi, QPainter *p) { - static SInt32 headerHeight = qt_mac_aqua_get_metric(ListHeaderHeight); + static int headerHeight = qt_mac_aqua_get_metric(ListHeaderHeight); QPixmap buffer; QString key = QString(QLatin1String("$qt_tableh%1-%2-%3")).arg(int(bdi.state)).arg(int(bdi.adornment)).arg(int(bdi.value)); @@ -1788,69 +1831,6 @@ void QMacStylePrivate::drawTableHeader(const CGRect &outerBounds, p->translate(-outerBounds.origin.x, -outerBounds.origin.y); } -void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider, - HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) const -{ - Q_UNUSED(cc); - memset(tdi, 0, sizeof(HIThemeTrackDrawInfo)); // We don't get it all for some reason or another... - tdi->version = qt_mac_hitheme_version; - tdi->reserved = 0; - tdi->filler1 = 0; - switch (aquaSizeConstrain(slider, needToRemoveMe)) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - tdi->kind = kThemeMediumSlider; - break; - case QStyleHelper::SizeMini: - tdi->kind = kThemeMiniSlider; - break; - case QStyleHelper::SizeSmall: - tdi->kind = kThemeSmallSlider; - break; - } - - bool usePlainKnob = slider->tickPosition == QSlider::NoTicks - || slider->tickPosition == QSlider::TicksBothSides; - - tdi->bounds = slider->rect.toCGRect(); - // Fix min and max positions. HITheme seems confused when it comes to rendering - // a slider at those positions. We give it a hand by extending and offsetting - // the slider range accordingly. See also comment for CC_Slider in drawComplexControl() - tdi->min = 0; - if (slider->orientation == Qt::Horizontal) - tdi->max = 10 * slider->rect.width(); - else - tdi->max = 10 * slider->rect.height(); - - int range = slider->maximum - slider->minimum; - if (range == 0) { - tdi->value = 0; - } else if (usePlainKnob || slider->orientation == Qt::Horizontal) { - int endsCorrection = usePlainKnob ? 25 : 10; - tdi->value = (tdi->max + 2 * endsCorrection) * (slider->sliderPosition - slider->minimum) / range - endsCorrection; - } else { - tdi->value = (tdi->max + 30) * (slider->sliderPosition - slider->minimum) / range - 20; - } - - tdi->attributes = kThemeTrackShowThumb; - if (slider->upsideDown) - tdi->attributes |= kThemeTrackRightToLeft; - if (slider->orientation == Qt::Horizontal) { - tdi->attributes |= kThemeTrackHorizontal; - } - - tdi->enableState = (slider->state & QStyle::State_Enabled) ? kThemeTrackActive - : kThemeTrackDisabled; - if (slider->state & QStyle::QStyle::State_HasFocus) - tdi->attributes |= kThemeTrackHasFocus; - if (usePlainKnob) - tdi->trackInfo.slider.thumbDir = kThemeThumbPlain; - else if (slider->tickPosition == QSlider::TicksAbove) - tdi->trackInfo.slider.thumbDir = kThemeThumbUpward; - else - tdi->trackInfo.slider.thumbDir = kThemeThumbDownward; -} - QMacStylePrivate::QMacStylePrivate() : backingStoreNSView(nil) { @@ -1963,11 +1943,11 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const // at construction time, and it cannot be changed later. bv = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)]; else if (widget.first == QCocoaHorizontalSlider) - bv = [[NSSlider alloc] init]; + bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]; else if (widget.first == QCocoaVerticalSlider) // Cocoa sets the orientation from the view's frame // at construction time, and it cannot be changed later. - bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 10, 100)]; + bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)]; else bv = [[NSButton alloc] init]; @@ -2289,79 +2269,10 @@ QMacStyle::~QMacStyle() [[NSNotificationCenter defaultCenter] removeObserver:d->receiver]; [d->receiver release]; - - delete qt_mac_backgroundPattern; - qt_mac_backgroundPattern = 0; } -/*! \internal - Generates the standard widget background pattern. -*/ -QPixmap QMacStylePrivate::generateBackgroundPattern() const +void QMacStyle::polish(QPalette &) { - QMacAutoReleasePool pool; - QPixmap px(4, 4); - QMacCGContext cg(&px); - HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationNormal); - const CGRect cgRect = CGRectMake(0, 0, px.width(), px.height()); - CGContextFillRect(cg, cgRect); - return px; -} - -/*! \internal - Fills the given \a rect with the pattern stored in \a brush. As an optimization, - HIThemeSetFill us used directly if we are filling with the standard background. -*/ -void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush) -{ -#if 0 - QPoint dummy; - const QPaintDevice *target = painter->device(); - const QPaintDevice *redirected = QPainter::redirected(target, &dummy); - //const bool usePainter = redirected && redirected != target; - - if (!usePainter && qt_mac_backgroundPattern - && qt_mac_backgroundPattern->cacheKey() == brush.texture().cacheKey()) { - - painter->setClipRegion(rgn); - - QMacCGContext cg(target); - CGContextSaveGState(cg); - HIThemeSetFill(kThemeBrushDialogBackgroundActive, 0, cg, kHIThemeOrientationInverted); - - for (const QRect &rect : rgn) { - // Anchor the pattern to the top so it stays put when the window is resized. - CGContextSetPatternPhase(cg, CGSizeMake(rect.width(), rect.height())); - CGRect mac_rect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); - CGContextFillRect(cg, mac_rect); - } - - CGContextRestoreGState(cg); - } else { -#endif - const QRect rect(rgn.boundingRect()); - painter->setClipRegion(rgn); - painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); -// } -} - -void QMacStyle::polish(QPalette &pal) -{ - Q_D(QMacStyle); - if (!qt_mac_backgroundPattern) { - if (!qApp) - return; - qt_mac_backgroundPattern = new QPixmap(d->generateBackgroundPattern()); - } - - - QCFString theme; - const OSErr err = CopyThemeIdentifier(&theme); - if (err == noErr && CFStringCompare(theme, kThemeAppearanceAquaGraphite, 0) == kCFCompareEqualTo) { - pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(240, 240, 240)); - } else { - pal.setBrush(QPalette::All, QPalette::AlternateBase, QColor(237, 243, 254)); - } } void QMacStyle::polish(QApplication *) @@ -2374,7 +2285,7 @@ void QMacStyle::unpolish(QApplication *) void QMacStyle::polish(QWidget* w) { -#ifndef QT_NO_MENU +#if QT_CONFIG(menu) if (qobject_cast<QMenu*>(w) #if QT_CONFIG(combobox) || qobject_cast<QComboBoxPrivateContainer *>(w) @@ -2433,7 +2344,7 @@ void QMacStyle::polish(QWidget* w) void QMacStyle::unpolish(QWidget* w) { if ( -#ifndef QT_NO_MENU +#if QT_CONFIG(menu) qobject_cast<QMenu*>(w) && #endif !w->testAttribute(Qt::WA_SetPalette)) { @@ -2483,7 +2394,7 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW { Q_D(const QMacStyle); const int controlSize = getControlSize(opt, widget); - SInt32 ret = 0; + int ret = 0; switch (metric) { case PM_TabCloseIndicatorWidth: @@ -2541,7 +2452,7 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW ret = 15; // I hate having magic numbers in here... break; case PM_DefaultFrameWidth: -#ifndef QT_NO_MAINWINDOW +#if QT_CONFIG(mainwindow) if (widget && (widget->isWindow() || !widget->parentWidget() || (qobject_cast<const QMainWindow*>(widget->parentWidget()) && static_cast<QMainWindow *>(widget->parentWidget())->centralWidget() == widget)) @@ -2679,7 +2590,7 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW break; case PM_ScrollBarExtent: { const QStyleHelper::WidgetSizePolicy size = d->effectiveAquaSizeConstrain(opt, widget); - ret = static_cast<SInt32>([NSScroller + ret = static_cast<int>([NSScroller scrollerWidthForControlSize:static_cast<NSControlSize>(size) scrollerStyle:[NSScroller preferredScrollerStyle]]); break; } @@ -2861,7 +2772,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w { QMacAutoReleasePool pool; - SInt32 ret = 0; + int ret = 0; switch (sh) { case SH_Slider_SnapToValue: case SH_PrintDialog_RightAlignButtons: @@ -3154,7 +3065,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w opt->rect.width(), opt->rect.height() - 8); HIThemeMenuDrawInfo mdi; mdi.version = 0; -#ifndef QT_NO_MENU +#if QT_CONFIG(menu) if (w && qobject_cast<QMenu *>(w->parentWidget())) mdi.menuType = kThemeMenuTypeHierarchical; else @@ -3570,7 +3481,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai HIThemeFrameDrawInfo fdi; fdi.version = qt_mac_hitheme_version; fdi.state = tds; - SInt32 frame_size; + int frame_size; fdi.kind = frame->features & QStyleOptionFrame::Rounded ? kHIThemeFrameTextFieldRound : kHIThemeFrameTextFieldSquare; frame_size = qt_mac_aqua_get_metric(EditTextFrameOutset); @@ -3605,7 +3516,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit). // Focus frame is drawn outside the rectangle passed in the option-rect. if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(opt)) { -#ifndef QT_NO_LINEEDIT +#if QT_CONFIG(lineedit) if ((opt->state & State_HasFocus) && !qobject_cast<const QLineEdit*>(w)) { int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin); int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin); @@ -4683,7 +4594,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter // the title bar. The following code fills the toolBar area with transparent pixels // to make that gradient visible. if (w) { -#ifndef QT_NO_MAINWINDOW +#if QT_CONFIG(mainwindow) if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window())) { if (toolBar && toolBar->toolBarArea == Qt::TopToolBarArea && mainWindow->unifiedTitleAndToolBarOnMac()) { @@ -4700,7 +4611,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter QPoint windowToolbarEnd = w->mapTo(w->window(), opt->rect.bottomLeft()); bool isEndOfUnifiedArea = !isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowToolbarEnd.y() + 1); if (isEndOfUnifiedArea) { - SInt32 margin; + int margin; margin = qt_mac_aqua_get_metric(SeparatorSize); CGRect separatorRect = CGRectMake(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin); HIThemeSeparatorDrawInfo separatorDrawInfo; @@ -5271,6 +5182,11 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex case CC_ScrollBar: if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { + const bool drawTrack = sb->subControls & SC_ScrollBarGroove; + const bool drawKnob = sb->subControls & SC_ScrollBarSlider; + if (!drawTrack && !drawKnob) + break; + const bool isHorizontal = sb->orientation == Qt::Horizontal; if (opt && opt->styleObject && !QMacStylePrivate::scrollBars.contains(opt->styleObject)) @@ -5390,49 +5306,53 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex CGContextSetAlpha(cg, opacity); } - // Draw the track when hovering. Expand by shifting the track rect. - if (!isTransient || opt->activeSubControls || wasActive) { - CGRect trackRect = scroller.bounds; - if (isHorizontal) - trackRect.origin.y += expandOffset; - else - trackRect.origin.x += expandOffset; - [scroller drawKnobSlotInRect:trackRect highlight:NO]; + if (drawTrack) { + // Draw the track when hovering. Expand by shifting the track rect. + if (!isTransient || opt->activeSubControls || wasActive) { + CGRect trackRect = scroller.bounds; + if (isHorizontal) + trackRect.origin.y += expandOffset; + else + trackRect.origin.x += expandOffset; + [scroller drawKnobSlotInRect:trackRect highlight:NO]; + } } - if (shouldExpand) { - // -[NSScroller drawKnob] is not useful here because any scaling applied - // will only be used to draw the hi-DPI artwork. And even if did scale, - // the stretched knob would look wrong, actually. So we need to draw the - // scroller manually when it's being hovered. - const CGFloat scrollerWidth = [NSScroller scrollerWidthForControlSize:scroller.controlSize scrollerStyle:scroller.scrollerStyle]; - const CGFloat knobWidth = knobWidths[cocoaSize] * expandScale; - // Cocoa can help get the exact knob length in the current orientation - const CGRect scrollerKnobRect = CGRectInset([scroller rectForPart:NSScrollerKnob], 1, 1); - const CGFloat knobLength = isHorizontal ? scrollerKnobRect.size.width : scrollerKnobRect.size.height; - const CGFloat knobPos = isHorizontal ? scrollerKnobRect.origin.x : scrollerKnobRect.origin.y; - const CGFloat knobOffset = qRound((scrollerWidth + expandOffset - knobWidth) / 2.0); - const CGFloat knobRadius = knobWidth / 2.0; - CGRect knobRect; - if (isHorizontal) - knobRect = CGRectMake(knobPos, knobOffset, knobLength, knobWidth); - else - knobRect = CGRectMake(knobOffset, knobPos, knobWidth, knobLength); - QCFType<CGPathRef> knobPath = CGPathCreateWithRoundedRect(knobRect, knobRadius, knobRadius, nullptr); - CGContextAddPath(cg, knobPath); - CGContextSetAlpha(cg, 0.5); - CGContextSetFillColorWithColor(cg, NSColor.blackColor.CGColor); - CGContextFillPath(cg); - } else { - [scroller drawKnob]; - - if (!isTransient && opt->activeSubControls) { - // The knob should appear darker (going from 0.76 down to 0.49). - // But no blending mode can help darken enough in a single pass, - // so we resort to drawing the knob twice with a small help from - // blending. This brings the gray level to a close enough 0.53. - CGContextSetBlendMode(cg, kCGBlendModePlusDarker); + if (drawKnob) { + if (shouldExpand) { + // -[NSScroller drawKnob] is not useful here because any scaling applied + // will only be used to draw the hi-DPI artwork. And even if did scale, + // the stretched knob would look wrong, actually. So we need to draw the + // scroller manually when it's being hovered. + const CGFloat scrollerWidth = [NSScroller scrollerWidthForControlSize:scroller.controlSize scrollerStyle:scroller.scrollerStyle]; + const CGFloat knobWidth = knobWidths[cocoaSize] * expandScale; + // Cocoa can help get the exact knob length in the current orientation + const CGRect scrollerKnobRect = CGRectInset([scroller rectForPart:NSScrollerKnob], 1, 1); + const CGFloat knobLength = isHorizontal ? scrollerKnobRect.size.width : scrollerKnobRect.size.height; + const CGFloat knobPos = isHorizontal ? scrollerKnobRect.origin.x : scrollerKnobRect.origin.y; + const CGFloat knobOffset = qRound((scrollerWidth + expandOffset - knobWidth) / 2.0); + const CGFloat knobRadius = knobWidth / 2.0; + CGRect knobRect; + if (isHorizontal) + knobRect = CGRectMake(knobPos, knobOffset, knobLength, knobWidth); + else + knobRect = CGRectMake(knobOffset, knobPos, knobWidth, knobLength); + QCFType<CGPathRef> knobPath = CGPathCreateWithRoundedRect(knobRect, knobRadius, knobRadius, nullptr); + CGContextAddPath(cg, knobPath); + CGContextSetAlpha(cg, 0.5); + CGContextSetFillColorWithColor(cg, NSColor.blackColor.CGColor); + CGContextFillPath(cg); + } else { [scroller drawKnob]; + + if (!isTransient && opt->activeSubControls) { + // The knob should appear darker (going from 0.76 down to 0.49). + // But no blending mode can help darken enough in a single pass, + // so we resort to drawing the knob twice with a small help from + // blending. This brings the gray level to a close enough 0.53. + CGContextSetBlendMode(cg, kCGBlendModePlusDarker); + [scroller drawKnob]; + } } } @@ -5443,152 +5363,124 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex } break; case CC_Slider: - if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { - const bool isHorizontal = slider->orientation == Qt::Horizontal; + if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { + const bool isHorizontal = sl->orientation == Qt::Horizontal; + const auto cs = d->effectiveAquaSizeConstrain(opt, widget); + const auto cw = QCocoaWidget(isHorizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider, cs); + auto *slider = static_cast<NSSlider *>(d->cocoaControl(cw)); + if (!setupSlider(slider, sl)) + break; + const bool hasTicks = sl->tickPosition != QSlider::NoTicks; + const bool hasDoubleTicks = sl->tickPosition == QSlider::TicksBothSides; + const bool drawKnob = sl->subControls & SC_SliderHandle; + const bool drawBar = sl->subControls & SC_SliderGroove; + const bool drawTicks = sl->subControls & SC_SliderTickmarks; + const bool isPressed = sl->state & State_Sunken; + + CGPoint pressPoint; + if (isPressed) { + const CGRect knobRect = [slider.cell knobRectFlipped:NO]; + pressPoint.x = CGRectGetMidX(knobRect); + pressPoint.y = CGRectGetMidY(knobRect); + [slider.cell startTrackingAt:pressPoint inView:slider]; + } - HIThemeTrackDrawInfo tdi; - d->getSliderInfo(cc, slider, &tdi, widget); - if (slider->state & State_Sunken) { - if (cc == CC_Slider) { - if (slider->activeSubControls == SC_SliderHandle) - tdi.trackInfo.slider.pressState = kThemeThumbPressed; - else if (slider->activeSubControls == SC_SliderGroove) - tdi.trackInfo.slider.pressState = kThemeLeftTrackPressed; + d->drawNSViewInRect(cw, slider, opt->rect, p, widget != 0, ^(CGContextRef ctx, const CGRect &rect) { + if (isHorizontal && sl->upsideDown) { + CGContextTranslateCTM(ctx, rect.size.width, 0); + CGContextScaleCTM(ctx, -1, 1); } - } - CGRect macRect; - bool tracking = slider->sliderPosition == slider->sliderValue; - if (!tracking) { - // Small optimization, the same as q->subControlRect - QCFType<HIShapeRef> shape; - HIThemeGetTrackThumbShape(&tdi, &shape); - HIShapeGetBounds(shape, &macRect); - tdi.value = slider->sliderValue; - } - if (!(slider->subControls & SC_SliderHandle)) - tdi.attributes &= ~kThemeTrackShowThumb; - if (!(slider->subControls & SC_SliderGroove)) - tdi.attributes |= kThemeTrackHideTrack; - - // Fix min and max positions. (See also getSliderInfo() - // for the slider values adjustments.) - // HITheme seems to have forgotten how to render - // a slide at those positions, leaving a gap between - // the knob and the ends of the track. - // We fix this by rendering the track first, and then - // the knob on top. However, in order to not clip the - // knob, we reduce the the drawing rect for the track. - CGRect bounds = tdi.bounds; - if (isHorizontal) { - tdi.bounds.size.width -= 2; - tdi.bounds.origin.x += 1; - if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) - tdi.bounds.origin.y -= 2; - else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) - tdi.bounds.origin.y += 3; - } else { - tdi.bounds.size.height -= 2; - tdi.bounds.origin.y += 1; - if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right - tdi.bounds.origin.x -= 4; - else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left - tdi.bounds.origin.x += 2; - } + if (hasDoubleTicks) { + // This ain't HIG kosher: eye-proved constants + if (isHorizontal) + CGContextTranslateCTM(ctx, 0, 4); + else + CGContextTranslateCTM(ctx, 1, 0); + } - // Yosemite demands its blue progress track when no tickmarks are present - if (!(slider->subControls & SC_SliderTickmarks)) { - QCocoaWidgetKind sliderKind = slider->orientation == Qt::Horizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider; - QCocoaWidget cw = QCocoaWidget(sliderKind, QStyleHelper::SizeLarge); - NSSlider *sl = (NSSlider *)d->cocoaControl(cw); - sl.minValue = slider->minimum; - sl.maxValue = slider->maximum; - sl.intValue = slider->sliderValue; - sl.enabled = slider->state & QStyle::State_Enabled; - d->drawNSViewInRect(cw, sl, opt->rect, p, widget != 0, ^(CGContextRef ctx, const CGRect &rect) { - const bool isSierraOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra; - if (slider->upsideDown) { - if (isHorizontal) { - CGContextTranslateCTM(ctx, rect.size.width, 0); - CGContextScaleCTM(ctx, -1, 1); - } - } else if (!isHorizontal && !isSierraOrLater) { - CGContextTranslateCTM(ctx, 0, rect.size.height); - CGContextScaleCTM(ctx, 1, -1); - } - const bool shouldFlip = isHorizontal || (slider->upsideDown && isSierraOrLater); - [sl.cell drawBarInside:NSRectFromCGRect(tdi.bounds) flipped:shouldFlip]; - // No need to restore the CTM later, the context has been saved - // and will be restored at the end of drawNSViewInRect() - }); - tdi.attributes |= kThemeTrackHideTrack; - - tdi.bounds = bounds; - } + // Since the GC is flipped, upsideDown means *not* inverted when vertical. + const bool verticalFlip = !isHorizontal && !sl->upsideDown; // FIXME: && !isSierraOrLater - if (slider->subControls & SC_SliderTickmarks) { - - CGRect bounds; - // As part of fixing the min and max positions, - // we need to adjust the tickmarks as well - bounds = tdi.bounds; - if (slider->orientation == Qt::Horizontal) { - tdi.bounds.size.width += 2; - tdi.bounds.origin.x -= 1; - if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) - tdi.bounds.origin.y -= 2; - } else { - tdi.bounds.size.height += 3; - tdi.bounds.origin.y -= 3; - tdi.bounds.origin.y += 1; - if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left - tdi.bounds.origin.x -= 2; - } +#if 0 + // FIXME: Sadly, this part doesn't work. It seems to somehow polute the + // NSSlider's internal state and, when we need to use the "else" part, + // the slider's frame is not in sync with its cell dimensions. + const bool drawAllParts = drawKnob && drawBar && (!hasTicks || drawTicks); + if (drawAllParts && !hasDoubleTicks && (!verticalFlip || drawTicks)) { + // Draw eveything at once if we're going to, except for inverted vertical + // sliders which need to be drawn part by part because of the shadow below + // the knob. Same for two-sided tickmarks. + if (verticalFlip && drawTicks) { + // Since tickmarks are always rendered symmetrically, a vertically + // flipped slider with tickmarks only needs to get its value flipped. + slider.intValue = slider.maxValue - slider.intValue + slider.minValue; + } + [slider drawRect:CGRectZero]; + } else +#endif + { + [slider calcSize]; + NSSliderCell *cell = slider.cell; + + const int numberOfTickMarks = slider.numberOfTickMarks; + // This ain't HIG kosher: force tick-less bar position. + if (hasDoubleTicks) + slider.numberOfTickMarks = 0; + + const CGRect barRect = [cell barRectFlipped:hasTicks]; + if (drawBar) { + // This ain't HIG kosher: force unfilled bar look. + if (hasDoubleTicks) + slider.numberOfTickMarks = numberOfTickMarks; + [cell drawBarInside:barRect flipped:!verticalFlip]; + } - int interval = slider->tickInterval; - if (interval == 0) { - interval = slider->pageStep; - if (interval == 0) - interval = slider->singleStep; - if (interval == 0) - interval = 1; - } - int numMarks = 1 + ((slider->maximum - slider->minimum) / interval); - - if (tdi.trackInfo.slider.thumbDir == kThemeThumbPlain) { - // They asked for both, so we'll give it to them. - tdi.trackInfo.slider.thumbDir = kThemeThumbDownward; - HIThemeDrawTrackTickMarks(&tdi, numMarks, - cg, - kHIThemeOrientationNormal); - tdi.trackInfo.slider.thumbDir = kThemeThumbUpward; - // 10.10 and above need a slight shift - if (slider->orientation == Qt::Vertical) - tdi.bounds.origin.x -= 2; - HIThemeDrawTrackTickMarks(&tdi, numMarks, - cg, - kHIThemeOrientationNormal); - // Reset to plain thumb to be drawn further down - tdi.trackInfo.slider.thumbDir = kThemeThumbPlain; - } else { - HIThemeDrawTrackTickMarks(&tdi, numMarks, - cg, - kHIThemeOrientationNormal); - } + if (hasTicks && drawTicks) { + if (!drawBar && hasDoubleTicks) + slider.numberOfTickMarks = numberOfTickMarks; - tdi.bounds = bounds; - } + [cell drawTickMarks]; - HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg, - kHIThemeOrientationNormal); + if (hasDoubleTicks) { + // This ain't HIG kosher: just slap a set of tickmarks on each side, like we used to. + CGAffineTransform tickMarksFlip; + const CGRect tickMarkRect = [cell rectOfTickMarkAtIndex:0]; + if (isHorizontal) { + tickMarksFlip = CGAffineTransformMakeTranslation(0, rect.size.height - tickMarkRect.size.height - 3); + tickMarksFlip = CGAffineTransformScale(tickMarksFlip, 1, -1); + } else { + tickMarksFlip = CGAffineTransformMakeTranslation(rect.size.width - tickMarkRect.size.width / 2, 0); + tickMarksFlip = CGAffineTransformScale(tickMarksFlip, -1, 1); + } + CGContextConcatCTM(ctx, tickMarksFlip); + [cell drawTickMarks]; + CGContextConcatCTM(ctx, CGAffineTransformInvert(tickMarksFlip)); + } + } + + if (drawKnob) { + // This ain't HIG kosher: force round knob look. + if (hasDoubleTicks) + slider.numberOfTickMarks = 0; + // Draw the knob in the symmetrical position instead of flipping. + if (verticalFlip) + slider.intValue = slider.maxValue - slider.intValue + slider.minValue; + [cell drawKnob]; + } + } + }); + + if (isPressed) + [slider.cell stopTracking:pressPoint at:pressPoint inView:slider mouseIsUp:NO]; } break; -#ifndef QT_NO_SPINBOX +#if QT_CONFIG(spinbox) case CC_SpinBox: if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { - SInt32 frame_size; + int frame_size; frame_size = qt_mac_aqua_get_metric(EditTextFrameOutset); QRect lineeditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget); @@ -5618,15 +5510,16 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex const bool downPressed = sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken); const CGFloat x = CGRectGetMidX(newRect); const CGFloat y = upPressed ? -3 : 3; // FIXME Weird coordinate shift going on + const CGPoint pressPoint = CGPointMake(x, y); // Pretend we're pressing the mouse on the right button. Unfortunately, NSStepperCell has no // API to highlight a specific button. The highlighted property works only on the down button. if (upPressed || downPressed) - [cell startTrackingAt:CGPointMake(x, y) inView:d->backingStoreNSView]; + [cell startTrackingAt:pressPoint inView:d->backingStoreNSView]; [cell drawWithFrame:newRect inView:d->backingStoreNSView]; if (upPressed || downPressed) - [cell stopTracking:CGPointMake(x, y) at:CGPointMake(x, y) inView:d->backingStoreNSView mouseIsUp:NO]; + [cell stopTracking:pressPoint at:pressPoint inView:d->backingStoreNSView mouseIsUp:NO]; d->restoreNSGraphicsContext(cg); } @@ -5941,16 +5834,28 @@ QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, } break; case CC_Slider: - if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { - HIThemeTrackDrawInfo tdi; - d->getSliderInfo(cc, slider, &tdi, widget); - ControlPartCode part; - CGPoint pos = CGPointMake(pt.x(), pt.y()); - if (HIThemeHitTestTrack(&tdi, &pos, &part)) { - if (part == kControlPageUpPart || part == kControlPageDownPart) - sc = SC_SliderGroove; - else - sc = SC_SliderHandle; + if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { + if (!sl->rect.contains(pt)) + break; + + const bool hasTicks = sl->tickPosition != QSlider::NoTicks; + const bool isHorizontal = sl->orientation == Qt::Horizontal; + const auto cs = d->effectiveAquaSizeConstrain(opt, widget); + const auto cw = QCocoaWidget(isHorizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider, cs); + auto *slider = static_cast<NSSlider *>(d->cocoaControl(cw)); + if (!setupSlider(slider, sl)) + break; + + [slider calcSize]; + NSSliderCell *cell = slider.cell; + const auto barRect = QRectF::fromCGRect([cell barRectFlipped:hasTicks]); + const auto knobRect = QRectF::fromCGRect([cell knobRectFlipped:NO]); + if (knobRect.contains(pt)) { + sc = SC_SliderHandle; + } else if (barRect.contains(pt)) { + sc = SC_SliderGroove; + } else if (hasTicks) { + sc = SC_SliderTickmarks; } } break; @@ -6078,30 +5983,51 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op } break; case CC_Slider: - if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { - HIThemeTrackDrawInfo tdi; - d->getSliderInfo(cc, slider, &tdi, widget); - CGRect macRect; - QCFType<HIShapeRef> shape; + if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) { + const bool hasTicks = sl->tickPosition != QSlider::NoTicks; + const bool isHorizontal = sl->orientation == Qt::Horizontal; + const auto cs = d->effectiveAquaSizeConstrain(opt, widget); + const auto cw = QCocoaWidget(isHorizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider, cs); + auto *slider = static_cast<NSSlider *>(d->cocoaControl(cw)); + if (!setupSlider(slider, sl)) + break; + + [slider calcSize]; + NSSliderCell *cell = slider.cell; if (sc == SC_SliderHandle) { - HIThemeGetTrackThumbShape(&tdi, &shape); - HIShapeGetBounds(shape, &macRect); + ret = QRectF::fromCGRect([cell knobRectFlipped:NO]).toRect(); + if (isHorizontal) { + ret.setTop(sl->rect.top()); + ret.setBottom(sl->rect.bottom()); + } else { + ret.setLeft(sl->rect.left()); + ret.setRight(sl->rect.right()); + } } else if (sc == SC_SliderGroove) { - HIThemeGetTrackBounds(&tdi, &macRect); + ret = QRectF::fromCGRect([cell barRectFlipped:hasTicks]).toRect(); + } else if (hasTicks && sc == SC_SliderTickmarks) { + const auto tickMarkRect = QRectF::fromCGRect([cell rectOfTickMarkAtIndex:0]); + if (isHorizontal) + ret = QRect(sl->rect.left(), tickMarkRect.top(), sl->rect.width(), tickMarkRect.height()); + else + ret = QRect(tickMarkRect.left(), sl->rect.top(), tickMarkRect.width(), sl->rect.height()); } - // FIXME No SC_SliderTickmarks? - ret = QRectF::fromCGRect(macRect).toRect(); - - // Tweak: the dark line between the sub/add line buttons belong to only one of the buttons - // when doing hit-testing, but both of them have to repaint it. Extend the rect to cover - // the line in the cases where HIThemeGetTrackPartBounds returns a rect that doesn't. - if (slider->orientation == Qt::Horizontal) { - if (slider->direction == Qt::LeftToRight && sc == SC_ScrollBarSubLine) - ret.adjust(0, 0, 1, 0); - else if (slider->direction == Qt::RightToLeft && sc == SC_ScrollBarAddLine) - ret.adjust(-1, 0, 1, 0); - } else if (sc == SC_ScrollBarAddLine) { - ret.adjust(0, -1, 0, 1); + + // Invert if needed and extend to the actual bounds of the slider + if (isHorizontal) { + if (sl->upsideDown) { + ret = QRect(sl->rect.right() - ret.right(), sl->rect.top(), ret.width(), sl->rect.height()); + } else { + ret.setTop(sl->rect.top()); + ret.setBottom(sl->rect.bottom()); + } + } else { + if (!sl->upsideDown) { + ret = QRect(sl->rect.left(), sl->rect.bottom() - ret.bottom(), sl->rect.width(), ret.height()); + } else { + ret.setLeft(sl->rect.left()); + ret.setRight(sl->rect.right()); + } } } break; @@ -6274,7 +6200,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op } } break; -#ifndef QT_NO_SPINBOX +#if QT_CONFIG(spinbox) case CC_SpinBox: if (const QStyleOptionSpinBox *spin = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { QStyleHelper::WidgetSizePolicy aquaSize = d->effectiveAquaSizeConstrain(spin, widget); @@ -6385,7 +6311,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, bool useAquaGuideline = true; switch (ct) { -#ifndef QT_NO_SPINBOX +#if QT_CONFIG(spinbox) case CT_SpinBox: if (const QStyleOptionSpinBox *vopt = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) { // Add button + frame widths @@ -6749,7 +6675,7 @@ bool QMacStyle::event(QEvent *e) QWidget *top = f->parentWidget(); while (top && !top->isWindow() && !(top->windowType() == Qt::SubWindow)) top = top->parentWidget(); -#ifndef QT_NO_MAINWINDOW +#if QT_CONFIG(mainwindow) if (qobject_cast<QMainWindow *>(top)) { QWidget *central = static_cast<QMainWindow *>(top)->centralWidget(); for (const QWidget *par = f; par; par = par->parentWidget()) { diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index b453e3c2d7..399edd82d4 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -74,13 +74,19 @@ #include <qhash.h> #include <qheaderview.h> #include <qlayout.h> +#if QT_CONFIG(lineedit) #include <qlineedit.h> +#endif #if QT_CONFIG(listview) #include <qlistview.h> #endif +#if QT_CONFIG(mainwindow) #include <qmainwindow.h> +#endif #include <qmap.h> +#if QT_CONFIG(menubar) #include <qmenubar.h> +#endif #include <qpaintdevice.h> #include <qpainter.h> #include <qpixmapcache.h> @@ -95,8 +101,12 @@ #if QT_CONFIG(rubberband) #include <qrubberband.h> #endif +#if QT_CONFIG(sizegrip) #include <qsizegrip.h> +#endif +#if QT_CONFIG(spinbox) #include <qspinbox.h> +#endif #if QT_CONFIG(splitter) #include <qsplitter.h> #endif @@ -146,11 +156,11 @@ QT_BEGIN_NAMESPACE /* AHIG: - Apple Human Interface Guidelines - http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/ + macOS Human Interface Guidelines + https://developer.apple.com/macos/human-interface-guidelines/overview/themes/ Builder: - Apple Interface Builder v. 3.1.1 + Interface Builder in Xcode 8 or later */ // this works as long as we have at most 16 different control types @@ -246,7 +256,6 @@ public: void initHIThemePushButton(const QStyleOptionButton *btn, const QWidget *widget, const ThemeDrawState tds, HIThemeButtonDrawInfo *bdi) const; - QPixmap generateBackgroundPattern() const; void setAutoDefaultButton(QObject *button) const; diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp index 60a5c25b1f..9e6880098f 100644 --- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp +++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp @@ -1173,7 +1173,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } } break; -#ifndef QT_NO_MENU +#if QT_CONFIG(menu) case CE_MenuItem: if (const QStyleOptionMenuItem *menuitem = qstyleoption_cast<const QStyleOptionMenuItem *>(option)) { // windows always has a check column, regardless whether we have an icon or not @@ -1331,7 +1331,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption } } break; -#endif // QT_NO_MENU +#endif // QT_CONFIG(menu) case CE_HeaderSection: if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) { partId = HP_HEADERITEM; @@ -1772,7 +1772,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle } } break; -#ifndef QT_NO_SPINBOX +#if QT_CONFIG(spinbox) case CC_SpinBox: if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { @@ -1830,7 +1830,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle } } break; -#endif // QT_NO_SPINBOX +#endif // QT_CONFIG(spinbox) default: QWindowsXPStyle::drawComplexControl(control, option, painter, widget); break; @@ -1869,7 +1869,7 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption sz.setHeight(minimumHeight); } return sz; -#ifndef QT_NO_MENUBAR +#if QT_CONFIG(menubar) case CT_MenuBarItem: if (!sz.isEmpty()) sz += QSize(windowsItemHMargin * 5 + 1, 5); @@ -2290,11 +2290,11 @@ void QWindowsVistaStyle::polish(QApplication *app) void QWindowsVistaStyle::polish(QWidget *widget) { QWindowsXPStyle::polish(widget); -#ifndef QT_NO_LINEEDIT +#if QT_CONFIG(lineedit) if (qobject_cast<QLineEdit*>(widget)) widget->setAttribute(Qt::WA_Hover); else -#endif // QT_NO_LINEEDIT +#endif // QT_CONFIG(lineedit) if (qobject_cast<QGroupBox*>(widget)) widget->setAttribute(Qt::WA_Hover); else if (qobject_cast<QCommandLinkButton*>(widget)) { @@ -2351,11 +2351,11 @@ void QWindowsVistaStyle::unpolish(QWidget *widget) d->stopAnimation(widget); -#ifndef QT_NO_LINEEDIT +#if QT_CONFIG(lineedit) if (qobject_cast<QLineEdit*>(widget)) widget->setAttribute(Qt::WA_Hover, false); else -#endif // QT_NO_LINEEDIT +#endif // QT_CONFIG(lineedit) if (qobject_cast<QGroupBox*>(widget)) widget->setAttribute(Qt::WA_Hover, false); else if (qobject_cast<QMessageBox *> (widget)) { diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h b/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h index a6744ff915..b649426811 100644 --- a/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h +++ b/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h @@ -65,12 +65,16 @@ #include <qpushbutton.h> #endif #include <qradiobutton.h> +#if QT_CONFIG(lineedit) #include <qlineedit.h> +#endif #include <qgroupbox.h> #if QT_CONFIG(toolbutton) #include <qtoolbutton.h> #endif +#if QT_CONFIG(spinbox) #include <qspinbox.h> +#endif #include <qtoolbar.h> #if QT_CONFIG(combobox) #include <qcombobox.h> diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp index 9880edf0b4..0a47ccf68a 100644 --- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp +++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp @@ -68,11 +68,15 @@ #include <qscrollbar.h> #endif #include <qheaderview.h> +#if QT_CONFIG(spinbox) #include <qspinbox.h> +#endif #if QT_CONFIG(listview) #include <qlistview.h> #endif +#if QT_CONFIG(stackedwidget) #include <qstackedwidget.h> +#endif #if QT_CONFIG(pushbutton) #include <qpushbutton.h> #endif @@ -379,10 +383,10 @@ bool QWindowsXPStylePrivate::isLineEditBaseColorSet(const QStyleOption *option, // Since spin box includes a line edit we need to resolve the palette mask also from // the parent, as while the color is always correct on the palette supplied by panel, // the mask can still be empty. If either mask specifies custom base color, use that. -#ifndef QT_NO_SPINBOX +#if QT_CONFIG(spinbox) if (const QAbstractSpinBox *spinbox = qobject_cast<QAbstractSpinBox*>(widget->parentWidget())) resolveMask |= spinbox->palette().resolve(); -#endif // QT_NO_SPINBOX +#endif // QT_CONFIG(spinbox) } return (resolveMask & (1 << QPalette::Base)) != 0; } @@ -1167,10 +1171,10 @@ void QWindowsXPStyle::polish(QWidget *widget) || qobject_cast<QScrollBar*>(widget) || qobject_cast<QSlider*>(widget) || qobject_cast<QHeaderView*>(widget) -#ifndef QT_NO_SPINBOX +#if QT_CONFIG(spinbox) || qobject_cast<QAbstractSpinBox*>(widget) || qobject_cast<QSpinBox*>(widget) -#endif // QT_NO_SPINBOX +#endif // QT_CONFIG(spinbox) ) { widget->setAttribute(Qt::WA_Hover); } @@ -1242,10 +1246,10 @@ void QWindowsXPStyle::unpolish(QWidget *widget) || qobject_cast<QScrollBar*>(widget) || qobject_cast<QSlider*>(widget) || qobject_cast<QHeaderView*>(widget) -#ifndef QT_NO_SPINBOX +#if QT_CONFIG(spinbox) || qobject_cast<QAbstractSpinBox*>(widget) || qobject_cast<QSpinBox*>(widget) -#endif // QT_NO_SPINBOX +#endif // QT_CONFIG(spinbox) ) { widget->setAttribute(Qt::WA_Hover, false); } @@ -2511,7 +2515,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo flags |= State_MouseOver; switch (cc) { -#ifndef QT_NO_SPINBOX +#if QT_CONFIG(spinbox) case CC_SpinBox: if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) { @@ -2563,7 +2567,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } } break; -#endif // QT_NO_SPINBOX +#endif // QT_CONFIG(spinbox) #if QT_CONFIG(combobox) case CC_ComboBox: if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) @@ -2726,7 +2730,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } break; -#ifndef QT_NO_SLIDER +#if QT_CONFIG(slider) case CC_Slider: if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) { @@ -3178,7 +3182,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } break; -#ifndef QT_NO_MDIAREA +#if QT_CONFIG(mdiarea) case CC_MdiControls: { QRect buttonRect; @@ -3234,7 +3238,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo } } break; -#endif //QT_NO_MDIAREA +#endif // QT_CONFIG(mdiarea) #if QT_CONFIG(dial) case CC_Dial: if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option)) @@ -3574,7 +3578,7 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl } } break; -#ifndef QT_NO_MDIAREA +#if QT_CONFIG(mdiarea) case CC_MdiControls: { int numSubControls = 0; @@ -3611,7 +3615,7 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl rect = QRect(offset, 0, buttonWidth, option->rect.height()); break; } -#endif // QT_NO_MDIAREA +#endif // QT_CONFIG(mdiarea) default: rect = visualRect(option->direction, option->rect, @@ -3665,7 +3669,7 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt case CT_Menu: sz += QSize(1, 0); break; -#ifndef QT_NO_MENUBAR +#if QT_CONFIG(menubar) case CT_MenuBarItem: if (!sz.isEmpty()) sz += QSize(windowsItemHMargin * 5 + 1, 6); |