From a07e77a99a916f5ee65511ffade0f087d72bf8bb Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 4 Nov 2016 11:07:54 +0100 Subject: iOS: fix 'incompatible pointer type' compiler warning Change-Id: I01bb7516a3600dd1dbd71dd6989f541494840abc Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/qiostextresponder.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 6224a6603c..3a888e2bd0 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -619,7 +619,7 @@ - (id)tokenizer { - return [[[UITextInputStringTokenizer alloc] initWithTextInput:id(self)] autorelease]; + return [[[UITextInputStringTokenizer alloc] initWithTextInput:self] autorelease]; } - (UITextPosition *)beginningOfDocument -- cgit v1.2.3 From 91c0afdcbf49939b466a07c0719444c55b6bbe49 Mon Sep 17 00:00:00 2001 From: Richard Moe Gustavsen Date: Fri, 4 Nov 2016 15:09:00 +0100 Subject: iOS: only build nsphotolibrarysupport for iOS The plugin depends on AssetLibrary.framework, which is only available for iOS. Change-Id: Ic7b3c4ffb4d26808d2120e46593cb4e191e2c10b Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/optional/optional.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/ios/optional/optional.pro b/src/plugins/platforms/ios/optional/optional.pro index 5e3421a025..6b4ae1ef5e 100644 --- a/src/plugins/platforms/ios/optional/optional.pro +++ b/src/plugins/platforms/ios/optional/optional.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS = nsphotolibrarysupport +ios: SUBDIRS = nsphotolibrarysupport -- cgit v1.2.3 From 14805de3d9584157fed9da8f8955446d2292846f Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 7 Nov 2016 21:11:09 +0100 Subject: Fix build with -no-feature-cursor Change-Id: I0644342c56facefab611f981690d0c7a2a460e7e Reviewed-by: Laszlo Agocs --- src/plugins/platforms/vnc/qvnc.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/vnc/qvnc.cpp b/src/plugins/platforms/vnc/qvnc.cpp index f386be193d..a45bb1c19c 100644 --- a/src/plugins/platforms/vnc/qvnc.cpp +++ b/src/plugins/platforms/vnc/qvnc.cpp @@ -533,9 +533,11 @@ void QRfbRawEncoder::write() QVncClientCursor::QVncClientCursor() { +#ifndef QT_NO_CURSOR QWindow *w = QGuiApplication::focusWindow(); QCursor c = w ? w->cursor() : QCursor(Qt::ArrowCursor); changeCursor(&c, 0); +#endif } QVncClientCursor::~QVncClientCursor() @@ -582,10 +584,10 @@ void QVncClientCursor::write(QVncClient *client) const socket->write((const char*)bitmap.scanLine(i), width); } -#ifndef QT_NO_CURSOR void QVncClientCursor::changeCursor(QCursor *widgetCursor, QWindow *window) { Q_UNUSED(window); +#ifndef QT_NO_CURSOR const Qt::CursorShape shape = widgetCursor ? widgetCursor->shape() : Qt::ArrowCursor; if (shape == Qt::BitmapCursor) { @@ -599,6 +601,9 @@ void QVncClientCursor::changeCursor(QCursor *widgetCursor, QWindow *window) cursor = *platformImage.image(); hotspot = platformImage.hotspot(); } +#else // !QT_NO_CURSOR + Q_UNUSED(widgetCursor); +#endif for (auto client : clients) client->setDirtyCursor(); } @@ -614,7 +619,6 @@ uint QVncClientCursor::removeClient(QVncClient *client) clients.removeOne(client); return clients.count(); } -#endif QVncServer::QVncServer(QVncScreen *screen, quint16 port) : qvnc_screen(screen) -- cgit v1.2.3 From c6477286525682773ae3739fee53689e225d1b0a Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 7 Nov 2016 21:11:54 +0100 Subject: Fix developer build with -no-feature-cursor Change-Id: I3ec22f212ad68baa788fcea2e7340c2f53bfc8a1 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/xcb/qxcbcursor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp index 4de4be43d1..80fe5a2199 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.cpp +++ b/src/plugins/platforms/xcb/qxcbcursor.cpp @@ -74,6 +74,8 @@ static PtrXcursorLibraryGetDefaultSize ptrXcursorLibraryGetDefaultSize = 0; static xcb_font_t cursorFont = 0; static int cursorCount = 0; +#ifndef QT_NO_CURSOR + static uint8_t cur_blank_bits[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -276,8 +278,6 @@ static const char * const cursorNames[] = { "link" }; -#ifndef QT_NO_CURSOR - QXcbCursorCacheKey::QXcbCursorCacheKey(const QCursor &c) : shape(c.shape()), bitmapCacheKey(0), maskCacheKey(0) { -- cgit v1.2.3 From ae8d3d69d68e7f3da1b0f524e12496387aff26ec Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 1 Nov 2016 15:28:17 -0700 Subject: macOS: Clear event dispatcher interrupt state A pending interrupt of a QEventLoop may interfere with native runModal calls, resulting in Cocoa's main event loop to be stopped unexpectedly. After commit 9ab60b9c processEvents() no longer resets the event dispatcher interrupt flag. Add QCocoaEventDispatcher::clearCurrentThreadCocoa EventDispatcherInterruptFlag(). Use it to clear the interrupt state before calling runModal and variants. Work around the inability to use platform API in the print support code. Change-Id: I52f26f99a63cbb46969db42f65b09a3c3119ad15 Task-number: QTBUG-56746 Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm | 5 +++++ src/plugins/platforms/cocoa/qcocoaeventdispatcher.h | 2 ++ src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm | 13 +++++++++++++ src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 5 +++++ src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm | 5 +++++ src/plugins/platforms/cocoa/qcocoanativeinterface.h | 2 ++ src/plugins/platforms/cocoa/qcocoanativeinterface.mm | 6 ++++++ 7 files changed, 38 insertions(+) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm index 3c924bec94..474e2cdb19 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm @@ -39,6 +39,7 @@ #include #include "qcocoahelpers.h" +#include "qcocoaeventdispatcher.h" #import @@ -318,6 +319,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will // close down during the cleanup. qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); + + // Make sure we don't interrupt the runModalForWindow call. + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + [NSApp runModalForWindow:mColorPanel]; mDialogIsExecuting = false; return (mResultCode == NSOKButton); diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h index 8a2a478a72..569dd3b028 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h @@ -125,6 +125,8 @@ public: void interrupt(); void flush(); + static void clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher); }; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 1cfb3ecff9..09a0e14950 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -960,6 +960,19 @@ void QCocoaEventDispatcher::interrupt() void QCocoaEventDispatcher::flush() { } +// QTBUG-56746: The behavior of processEvents() has been changed to not clear +// the interrupt flag. Use this function to clear it. + void QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag() +{ + QCocoaEventDispatcher *cocoaEventDispatcher = + qobject_cast(QThread::currentThread()->eventDispatcher()); + if (!cocoaEventDispatcher) + return; + QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = + static_cast(QObjectPrivate::get(cocoaEventDispatcher)); + cocoaEventDispatcherPrivate->interrupt = false; +} + QCocoaEventDispatcher::~QCocoaEventDispatcher() { Q_D(QCocoaEventDispatcher); diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 4c1b190b9c..71748ae77f 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -45,6 +45,7 @@ #include "qt_mac_p.h" #include "qcocoahelpers.h" #include "qcocoamenubar.h" +#include "qcocoaeventdispatcher.h" #include #include #include @@ -235,6 +236,10 @@ static QString strippedText(QString s) // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will // close down during the cleanup. qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); + + // Make sure we don't interrupt the runModal call below. + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder(); mReturnCode = [mSavePanel runModal]; QCocoaMenuBar::resetKnownMenuItemsToQt(); diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index 5b27dc1da9..eb800afd47 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -43,6 +43,7 @@ #include #include "qcocoahelpers.h" +#include "qcocoaeventdispatcher.h" #import @@ -313,6 +314,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will // close down during the cleanup. qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers); + + // Make sure we don't interrupt the runModalForWindow call. + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + [NSApp runModalForWindow:mFontPanel]; mDialogIsExecuting = false; return (mResultCode == NSOKButton); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index d018c05635..d6786b9274 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -96,6 +96,8 @@ private: */ Q_INVOKABLE QPixmap defaultBackgroundPixmapForQWizard(); + Q_INVOKABLE void clearCurrentThreadCocoaEventDispatcherInterruptFlag(); + // QMacPastebardMime support. The mac pasteboard void pointers are // QMacPastebardMime instances from the cocoa plugin or qtmacextras // These two classes are kept in sync and can be casted between. diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index baee451903..8534c1c6fb 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -38,6 +38,7 @@ #include "qcocoahelpers.h" #include "qcocoaapplication.h" #include "qcocoaintegration.h" +#include "qcocoaeventdispatcher.h" #include #include @@ -193,6 +194,11 @@ QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard() return QPixmap(); } +void QCocoaNativeInterface::clearCurrentThreadCocoaEventDispatcherInterruptFlag() +{ + QCocoaEventDispatcher::clearCurrentThreadCocoaEventDispatcherInterruptFlag(); +} + void QCocoaNativeInterface::onAppFocusWindowChanged(QWindow *window) { Q_UNUSED(window); -- cgit v1.2.3 From 356f5bbac3a66701e958896f8075bbacc90439df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 25 Oct 2016 08:14:21 +0200 Subject: Cocoa: Make child window cursors work correctly The existing cursor logic had a couple of issues: - It made the faulty assumption that we could not use the NSWindow invalidateCursorRectsForView API for child NSViews. - It used NSWindow invalidateCursorRectsForView and NSView resetCursorRects. This API has been replaced by the more general NSTrackingArea API. - It did not implement falling back to the parent window cursor if the current window has no cursor set. Document that QWindow cursors work the same way as QWidget cursors in that a QWindow with no set cursor will fall back to the parent window cursor. Change the cocoa platform code to use NSTrackingArea exclusively and implement NSView cursorUpdate which sets the cursor. Handle immediate change on QWindow:: setCursor() manually. Add QWindow::effectiveWindowCursor() and applyEffectiveWindowCursor() which finds the correct window cursor. Add a manual test for the child window, child widget, and QWidget::createWindowChild cases. Task-number: QTBUG-33479 Task-number: QTBUG-52023 Change-Id: I0370e11bbadb2da95e8632e61be6228ec2cd5e9d Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoacursor.mm | 9 +++-- src/plugins/platforms/cocoa/qcocoawindow.h | 2 + src/plugins/platforms/cocoa/qcocoawindow.mm | 60 ++++++++++++++++++++--------- src/plugins/platforms/cocoa/qnsview.h | 1 - src/plugins/platforms/cocoa/qnsview.mm | 19 ++------- 5 files changed, 53 insertions(+), 38 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index 8e38181c29..a4c291c14a 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -55,7 +55,7 @@ QCocoaCursor::~QCocoaCursor() void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window) { - NSCursor * cocoaCursor = convertCursor(cursor); + NSCursor *cocoaCursor = convertCursor(cursor); if (QPlatformWindow * platformWindow = window->handle()) static_cast(platformWindow)->setWindowCursor(cocoaCursor); @@ -77,9 +77,12 @@ void QCocoaCursor::setPos(const QPoint &position) CFRelease(e); } -NSCursor *QCocoaCursor::convertCursor(QCursor * cursor) +NSCursor *QCocoaCursor::convertCursor(QCursor *cursor) { - const Qt::CursorShape newShape = cursor ? cursor->shape() : Qt::ArrowCursor; + if (cursor == Q_NULLPTR) + return 0; + + const Qt::CursorShape newShape = cursor->shape(); NSCursor *cocoaCursor; // Check for a suitable built-in NSCursor first: diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 9cf6328281..bf28f83540 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -236,6 +236,8 @@ public: void setMenubar(QCocoaMenuBar *mb); QCocoaMenuBar *menubar() const; + NSCursor *effectiveWindowCursor() const; + void applyEffectiveWindowCursor(); void setWindowCursor(NSCursor *cursor); void registerTouch(bool enable); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 977a5ae657..a18d93b89e 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1645,31 +1645,53 @@ QCocoaMenuBar *QCocoaWindow::menubar() const return m_menubar; } -void QCocoaWindow::setWindowCursor(NSCursor *cursor) +// 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 { - // This function is called (via QCocoaCursor) by Qt to set - // the cursor for this window. It can be called for a window - // that is not currenly under the mouse pointer (for example - // for a popup window.) Qt expects the set cursor to "stick": - // it should be accociated with the window until a different - // cursor is set. - if (m_windowCursor != cursor) { - [m_windowCursor release]; - m_windowCursor = [cursor retain]; - } - // Use the built in cursor rect API if the QCocoaWindow has a NSWindow. - // Othervise, set the cursor if this window is under the mouse. In - // this case QNSView::cursorUpdate will set the cursor as the pointer - // moves. - if (m_nsWindow && m_qtView) { - [m_nsWindow invalidateCursorRectsForView : m_qtView]; + if (m_windowCursor) + return m_windowCursor; + if (!parent()) + return nil; + return static_cast(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 { - if (m_windowUnderMouse) - [cursor set]; + // 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) + return; + + // Setting a cursor in a foregin view is not supported. + if (!m_qtView) + return; + + [m_windowCursor release]; + m_windowCursor = cursor; + [m_windowCursor retain]; + + // 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(); +} + void QCocoaWindow::registerTouch(bool enable) { m_registerTouchCount += enable ? 1 : -1; diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 2d4ad7aad3..9d2b54a321 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -118,7 +118,6 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)mouseMovedImpl:(NSEvent *)theEvent; - (void)mouseEnteredImpl:(NSEvent *)theEvent; - (void)mouseExitedImpl:(NSEvent *)theEvent; -- (void)cursorUpdateImpl:(NSEvent *)theEvent; - (void)rightMouseDown:(NSEvent *)theEvent; - (void)rightMouseDragged:(NSEvent *)theEvent; - (void)rightMouseUp:(NSEvent *)theEvent; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index c67bcfd23b..1ad9b5f327 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -120,7 +120,7 @@ static bool _q_dontOverrideCtrlLMB = false; - (void)cursorUpdate:(NSEvent *)theEvent { - [view cursorUpdateImpl:theEvent]; + [self cursorUpdate:theEvent]; } @end @@ -924,21 +924,10 @@ QT_WARNING_POP [self addTrackingArea:m_trackingArea]; } --(void)cursorUpdateImpl:(NSEvent *)theEvent -{ - Q_UNUSED(theEvent) - // Set the cursor manually if there is no NSWindow. - if (!m_platformWindow->m_nsWindow && m_platformWindow->m_windowCursor) - [m_platformWindow->m_windowCursor set]; - else - [super cursorUpdate:theEvent]; -} - --(void)resetCursorRects +- (void)cursorUpdate:(NSEvent *)theEvent { - // Use the cursor rect API if there is a NSWindow - if (m_platformWindow->m_nsWindow && m_platformWindow->m_windowCursor) - [self addCursorRect:[self visibleRect] cursor:m_platformWindow->m_windowCursor]; + Q_UNUSED(theEvent); + m_platformWindow->applyEffectiveWindowCursor(); } - (void)mouseMovedImpl:(NSEvent *)theEvent -- cgit v1.2.3 From e649eac69a3220be7654ce6428185c83cd885db2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 4 Nov 2016 10:52:36 +0100 Subject: Direct2D QPA: Add #include directives for MinGW D2D support has been partially added to recent versions of MinGW, which one day could make compiling the plugin possible. Change-Id: I53f91c483d3b900698f4424cb6a72f626e32e60b Reviewed-by: Louai Al-Khanji --- src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h b/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h index 97715ad050..34225bba9a 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dhelpers.h @@ -46,6 +46,13 @@ #include #include +#ifdef Q_CC_MINGW +# include +# include +# include +# include +# include +#endif // Q_CC_MINGW #include QT_BEGIN_NAMESPACE -- cgit v1.2.3 From 7d3b291c2252bb737845b923e86c5dbcc9e5ec72 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 9 Nov 2016 10:45:12 +0100 Subject: winrt: Switch default screen image format No need to specify a format with alpha for the screen. Comparing to Windows, Format_ARGB32_Premultiplied was only set in the constructor, but never actually during runtime as detection enforces eith RGB32 or RGB16. Change-Id: I4c2fabbab0d14ee296f9b7e43b02de8a9836d5bb Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index e8e869c04f..6d4edcc8dc 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -625,7 +625,7 @@ int QWinRTScreen::depth() const QImage::Format QWinRTScreen::format() const { - return QImage::Format_ARGB32_Premultiplied; + return QImage::Format_RGB32; } QSizeF QWinRTScreen::physicalSize() const -- cgit v1.2.3 From 95b506cccddcb6d3cba05abe59250862b7ea3999 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 7 Nov 2016 10:33:20 +0100 Subject: fix build with -qt-xcb the include path must be absolute, as otherwise the external module pri will contain a bogus path. amends 9a088e78. Task-number: QTBUG-56934 Change-Id: I701f5778d8c1b5586310b08e7763858460455d63 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/xcb/xcb-static/xcb-static.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro index f3e54813ee..20d8b83e7c 100644 --- a/src/plugins/platforms/xcb/xcb-static/xcb-static.pro +++ b/src/plugins/platforms/xcb/xcb-static/xcb-static.pro @@ -6,7 +6,7 @@ # CONFIG += static -XCB_DIR = ../../../../3rdparty/xcb +XCB_DIR = $$QT_SOURCE_TREE/src/3rdparty/xcb MODULE_INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude INCLUDEPATH += $$XCB_DIR/include/xcb -- cgit v1.2.3 From a192ee0c379cd16512460bc45b1d492078f49aba Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 26 Oct 2016 11:37:24 -0700 Subject: Move WinRT font database to QtFontDatabaseSupport Similar to what we recently did with the Windows font databases. The goal, again, is to add platform font database support for the minimal QPA plugin. Change-Id: Ide5f4ec452c920f169cc31c617cbcf19d8d1764d Reviewed-by: Oswald Buddenhagen Reviewed-by: Oliver Wolff Reviewed-by: Friedemann Kleint Reviewed-by: Maurice Kalinowski --- src/plugins/platforms/winrt/qwinrtfontdatabase.cpp | 491 --------------------- src/plugins/platforms/winrt/qwinrtfontdatabase.h | 79 ---- src/plugins/platforms/winrt/qwinrtintegration.cpp | 2 +- src/plugins/platforms/winrt/winrt.pro | 4 +- 4 files changed, 2 insertions(+), 574 deletions(-) delete mode 100644 src/plugins/platforms/winrt/qwinrtfontdatabase.cpp delete mode 100644 src/plugins/platforms/winrt/qwinrtfontdatabase.h (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp deleted file mode 100644 index d4f2ba1bd6..0000000000 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp +++ /dev/null @@ -1,491 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 "qwinrtfontdatabase.h" - -#include -#include - -#include -#include -#include -#include -using namespace Microsoft::WRL; - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(lcQpaFonts, "qt.qpa.fonts") - -QDebug operator<<(QDebug d, const QFontDef &def) -{ - QDebugStateSaver saver(d); - d.nospace(); - d << "Family=" << def.family << " Stylename=" << def.styleName - << " pointsize=" << def.pointSize << " pixelsize=" << def.pixelSize - << " styleHint=" << def.styleHint << " weight=" << def.weight - << " stretch=" << def.stretch << " hintingPreference=" - << def.hintingPreference; - return d; -} - -// Based on unicode range tables at http://www.microsoft.com/typography/otspec/os2.htm#ur -static QFontDatabase::WritingSystem writingSystemFromUnicodeRange(const DWRITE_UNICODE_RANGE &range) -{ - if (range.first >= 0x0000 && range.last <= 0x007F) - return QFontDatabase::Latin; - if (range.first >= 0x0370 && range.last <= 0x03FF) - return QFontDatabase::Greek; - if (range.first >= 0x0400 && range.last <= 0x04FF) - return QFontDatabase::Cyrillic; - if (range.first >= 0x0530 && range.last <= 0x058F) - return QFontDatabase::Armenian; - if (range.first >= 0x0590 && range.last <= 0x05FF) - return QFontDatabase::Hebrew; - if (range.first >= 0x0600 && range.last <= 0x06FF) - return QFontDatabase::Arabic; - if (range.first >= 0x0700 && range.last <= 0x074F) - return QFontDatabase::Syriac; - if (range.first >= 0x0780 && range.last <= 0x07BF) - return QFontDatabase::Thaana; - if (range.first >= 0x0900 && range.last <= 0x097F) - return QFontDatabase::Devanagari; - if (range.first >= 0x0980 && range.last <= 0x09FF) - return QFontDatabase::Bengali; - if (range.first >= 0x0A00 && range.last <= 0x0A7F) - return QFontDatabase::Gurmukhi; - if (range.first >= 0x0A80 && range.last <= 0x0AFF) - return QFontDatabase::Gujarati; - if (range.first >= 0x0B00 && range.last <= 0x0B7F) - return QFontDatabase::Oriya; - if (range.first >= 0x0B80 && range.last <= 0x0BFF) - return QFontDatabase::Tamil; - if (range.first >= 0x0C00 && range.last <= 0x0C7F) - return QFontDatabase::Telugu; - if (range.first >= 0x0C80 && range.last <= 0x0CFF) - return QFontDatabase::Kannada; - if (range.first >= 0x0D00 && range.last <= 0x0D7F) - return QFontDatabase::Malayalam; - if (range.first >= 0x0D80 && range.last <= 0x0DFF) - return QFontDatabase::Sinhala; - if (range.first >= 0x0E00 && range.last <= 0x0E7F) - return QFontDatabase::Thai; - if (range.first >= 0x0E80 && range.last <= 0x0EFF) - return QFontDatabase::Lao; - if (range.first >= 0x0F00 && range.last <= 0x0FFF) - return QFontDatabase::Tibetan; - if (range.first >= 0x1000 && range.last <= 0x109F) - return QFontDatabase::Myanmar; - if (range.first >= 0x10A0 && range.last <= 0x10FF) - return QFontDatabase::Georgian; - if (range.first >= 0x1780 && range.last <= 0x17FF) - return QFontDatabase::Khmer; - if (range.first >= 0x4E00 && range.last <= 0x9FFF) - return QFontDatabase::SimplifiedChinese; - if (range.first >= 0xAC00 && range.last <= 0xD7AF) - return QFontDatabase::Korean; - if (range.first >= 0x1680 && range.last <= 0x169F) - return QFontDatabase::Ogham; - if (range.first >= 0x16A0 && range.last <= 0x16FF) - return QFontDatabase::Runic; - if (range.first >= 0x07C0 && range.last <= 0x07FF) - return QFontDatabase::Nko; - - return QFontDatabase::Other; -} - -QString QWinRTFontDatabase::fontDir() const -{ - qCDebug(lcQpaFonts) << __FUNCTION__; - QString fontDirectory = QBasicFontDatabase::fontDir(); - if (!QFile::exists(fontDirectory)) { - // Fall back to app directory + fonts, and just app directory after that - const QString applicationDirPath = QCoreApplication::applicationDirPath(); - fontDirectory = applicationDirPath + QLatin1String("/fonts"); - if (!QFile::exists(fontDirectory)) { - if (m_fontFamilies.isEmpty()) - qWarning("No fonts directory found in application package."); - fontDirectory = applicationDirPath; - } - } - return fontDirectory; -} - -QWinRTFontDatabase::~QWinRTFontDatabase() -{ - qCDebug(lcQpaFonts) << __FUNCTION__; - - foreach (IDWriteFontFile *fontFile, m_fonts.keys()) - fontFile->Release(); - - foreach (IDWriteFontFamily *fontFamily, m_fontFamilies) - fontFamily->Release(); -} - -QFont QWinRTFontDatabase::defaultFont() const -{ - return QFont(QStringLiteral("Segoe UI")); -} - -bool QWinRTFontDatabase::fontsAlwaysScalable() const -{ - return true; -} - -void QWinRTFontDatabase::populateFontDatabase() -{ - qCDebug(lcQpaFonts) << __FUNCTION__; - - ComPtr factory; - HRESULT hr = DWriteCreateFactory(DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory1), &factory); - if (FAILED(hr)) { - qWarning("Failed to create DirectWrite factory: %s", qPrintable(qt_error_string(hr))); - QBasicFontDatabase::populateFontDatabase(); - return; - } - - ComPtr fontCollection; - hr = factory->GetSystemFontCollection(&fontCollection); - if (FAILED(hr)) { - qWarning("Failed to open system font collection: %s", qPrintable(qt_error_string(hr))); - QBasicFontDatabase::populateFontDatabase(); - return; - } - - int fontFamilyCount = fontCollection->GetFontFamilyCount(); - for (int i = 0; i < fontFamilyCount; ++i) { - ComPtr fontFamily; - hr = fontCollection->GetFontFamily(i, &fontFamily); - if (FAILED(hr)) { - qWarning("Unable to get font family: %s", qPrintable(qt_error_string(hr))); - continue; - } - - ComPtr names; - hr = fontFamily->GetFamilyNames(&names); - if (FAILED(hr)) { - qWarning("Unable to get font family names: %s", qPrintable(qt_error_string(hr))); - continue; - } - quint32 familyNameLength; - hr = names->GetStringLength(0, &familyNameLength); - if (FAILED(hr)) { - qWarning("Unable to get family name length: %s", qPrintable(qt_error_string(hr))); - continue; - } - QVector familyBuffer(familyNameLength + 1); - hr = names->GetString(0, familyBuffer.data(), familyBuffer.size()); - if (FAILED(hr)) { - qWarning("Unable to create font family name: %s", qPrintable(qt_error_string(hr))); - continue; - } - QString familyName = QString::fromWCharArray(familyBuffer.data(), familyNameLength); - - m_fontFamilies.insert(familyName, fontFamily.Detach()); - - registerFontFamily(familyName); - } - - QBasicFontDatabase::populateFontDatabase(); -} - -void QWinRTFontDatabase::populateFamily(const QString &familyName) -{ - qCDebug(lcQpaFonts) << __FUNCTION__ << familyName; - - IDWriteFontFamily *fontFamily = m_fontFamilies.value(familyName); - if (!fontFamily) { - qWarning("The font family %s was not found.", qPrintable(familyName)); - return; - } - - bool fontRegistered = false; - const int fontCount = fontFamily->GetFontCount(); - for (int j = 0; j < fontCount; ++j) { - ComPtr font; - HRESULT hr = fontFamily->GetFont(j, &font); - if (FAILED(hr)) { - qWarning("Unable to get font: %s", qPrintable(qt_error_string(hr))); - continue; - } - - // Skip simulated faces - if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) - continue; - - ComPtr baseFontFace; - hr = font->CreateFontFace(&baseFontFace); - if (FAILED(hr)) { - qWarning("Unable to create base font face: %s", qPrintable(qt_error_string(hr))); - continue; - } - ComPtr fontFace; - hr = baseFontFace.As(&fontFace); - if (FAILED(hr)) { - qWarning("Unable to create font face: %s", qPrintable(qt_error_string(hr))); - continue; - } - - // We can't deal with multi-file fonts - quint32 fileCount; - hr = fontFace->GetFiles(&fileCount, NULL); - if (FAILED(hr)) { - qWarning("Unable to get font file count: %s", qPrintable(qt_error_string(hr))); - continue; - } - if (fileCount != 1) - continue; - - ComPtr informationalStrings; - BOOL exists; - hr = font->GetInformationalStrings(DWRITE_INFORMATIONAL_STRING_MANUFACTURER, - &informationalStrings, &exists); - if (FAILED(hr)) { - qWarning("Unable to get font foundry: %s", qPrintable(qt_error_string(hr))); - continue; - } - QString foundryName; - if (exists) { - quint32 length; - hr = informationalStrings->GetStringLength(0, &length); - if (FAILED(hr)) - qWarning("Unable to get foundry name length: %s", qPrintable(qt_error_string(hr))); - if (SUCCEEDED(hr)) { - QVector buffer(length + 1); - hr = informationalStrings->GetString(0, buffer.data(), buffer.size()); - if (FAILED(hr)) - qWarning("Unable to get foundry name: %s", qPrintable(qt_error_string(hr))); - if (SUCCEEDED(hr)) - foundryName = QString::fromWCharArray(buffer.data(), length); - } - } - - QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(font->GetWeight()); - - QFont::Style style; - switch (font->GetStyle()) { - default: - case DWRITE_FONT_STYLE_NORMAL: - style = QFont::StyleNormal; - break; - case DWRITE_FONT_STYLE_OBLIQUE: - style = QFont::StyleOblique; - break; - case DWRITE_FONT_STYLE_ITALIC: - style = QFont::StyleItalic; - break; - } - - QFont::Stretch stretch; - switch (font->GetStretch()) { - default: - case DWRITE_FONT_STRETCH_UNDEFINED: - case DWRITE_FONT_STRETCH_NORMAL: - stretch = QFont::Unstretched; - break; - case DWRITE_FONT_STRETCH_ULTRA_CONDENSED: - stretch = QFont::UltraCondensed; - break; - case DWRITE_FONT_STRETCH_EXTRA_CONDENSED: - stretch = QFont::ExtraCondensed; - break; - case DWRITE_FONT_STRETCH_CONDENSED: - stretch = QFont::Condensed; - break; - case DWRITE_FONT_STRETCH_SEMI_CONDENSED: - stretch = QFont::SemiCondensed; - break; - case DWRITE_FONT_STRETCH_SEMI_EXPANDED: - stretch = QFont::SemiExpanded; - break; - case DWRITE_FONT_STRETCH_EXPANDED: - stretch = QFont::Expanded; - break; - case DWRITE_FONT_STRETCH_EXTRA_EXPANDED: - stretch = QFont::ExtraExpanded; - break; - case DWRITE_FONT_STRETCH_ULTRA_EXPANDED: - stretch = QFont::UltraExpanded; - break; - } - - const bool fixedPitch = fontFace->IsMonospacedFont(); - - // Get writing systems from unicode ranges - quint32 actualRangeCount; - hr = fontFace->GetUnicodeRanges(0, nullptr, &actualRangeCount); - Q_ASSERT(hr == E_NOT_SUFFICIENT_BUFFER); - QVector unicodeRanges(actualRangeCount); - hr = fontFace->GetUnicodeRanges(actualRangeCount, unicodeRanges.data(), &actualRangeCount); - if (FAILED(hr)) { - qWarning("Unable to get font unicode range: %s", qPrintable(qt_error_string(hr))); - continue; - } - QSupportedWritingSystems writingSystems; - for (quint32 i = 0; i < actualRangeCount; ++i) { - const QFontDatabase::WritingSystem writingSystem = writingSystemFromUnicodeRange(unicodeRanges.at(i)); - writingSystems.setSupported(writingSystem); - } - if (writingSystems.supported(QFontDatabase::SimplifiedChinese)) { - writingSystems.setSupported(QFontDatabase::TraditionalChinese); - writingSystems.setSupported(QFontDatabase::Japanese); - } - if (writingSystems.supported(QFontDatabase::Latin)) - writingSystems.setSupported(QFontDatabase::Vietnamese); - - IDWriteFontFile *fontFile; - hr = fontFace->GetFiles(&fileCount, &fontFile); - if (FAILED(hr)) { - qWarning("Unable to get font file: %s", qPrintable(qt_error_string(hr))); - continue; - } - - FontDescription description = { fontFace->GetIndex(), QUuid::createUuid().toByteArray() }; - m_fonts.insert(fontFile, description); - registerFont(familyName, QString(), foundryName, weight, style, stretch, - true, true, 0, fixedPitch, writingSystems, fontFile); - fontRegistered = true; - } - - // Always populate something to avoid an assert - if (!fontRegistered) { - registerFont(familyName, QString(), QString(), QFont::Normal, QFont::StyleNormal, - QFont::Unstretched, false, false, 0, false, QSupportedWritingSystems(), 0); - } -} - -QFontEngine *QWinRTFontDatabase::fontEngine(const QFontDef &fontDef, void *handle) -{ - qCDebug(lcQpaFonts) << __FUNCTION__ << "FONTDEF" << fontDef << handle; - - if (!handle) // Happens if a font family population failed - return 0; - - IDWriteFontFile *fontFile = reinterpret_cast(handle); - if (!m_fonts.contains(fontFile)) - return QBasicFontDatabase::fontEngine(fontDef, handle); - - const void *referenceKey; - quint32 referenceKeySize; - HRESULT hr = fontFile->GetReferenceKey(&referenceKey, &referenceKeySize); - if (FAILED(hr)) { - qWarning("Unable to get font file reference key: %s", qPrintable(qt_error_string(hr))); - return 0; - } - - ComPtr loader; - hr = fontFile->GetLoader(&loader); - if (FAILED(hr)) { - qWarning("Unable to get font file loader: %s", qPrintable(qt_error_string(hr))); - return 0; - } - - ComPtr stream; - hr =loader->CreateStreamFromKey(referenceKey, referenceKeySize, &stream); - if (FAILED(hr)) { - qWarning("Unable to get font file stream: %s", qPrintable(qt_error_string(hr))); - return 0; - } - - quint64 fileSize; - hr = stream->GetFileSize(&fileSize); - if (FAILED(hr)) { - qWarning("Unable to get font file size: %s", qPrintable(qt_error_string(hr))); - return 0; - } - - const void *data; - void *context; - hr = stream->ReadFileFragment(&data, 0, fileSize, &context); - if (FAILED(hr)) { - qWarning("Unable to get font file data: %s", qPrintable(qt_error_string(hr))); - return 0; - } - const QByteArray fontData((const char *)data, fileSize); - stream->ReleaseFileFragment(context); - - QFontEngine::FaceId faceId; - const FontDescription description = m_fonts.value(fontFile); - faceId.uuid = description.uuid; - faceId.index = description.index; - const bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); - QFontEngineFT::GlyphFormat format = antialias ? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; - QFontEngineFT *engine = new QFontEngineFT(fontDef); - if (!engine->init(faceId, antialias, format, fontData) || engine->invalid()) { - delete engine; - return 0; - } - - return engine; -} - -QStringList QWinRTFontDatabase::fallbacksForFamily(const QString &family, QFont::Style style, - QFont::StyleHint styleHint, - QChar::Script script) const -{ - Q_UNUSED(style) - Q_UNUSED(styleHint) - Q_UNUSED(script) - - qCDebug(lcQpaFonts) << __FUNCTION__ << family; - - QStringList result; - if (family == QLatin1String("Helvetica")) - result.append(QStringLiteral("Arial")); - result.append(QBasicFontDatabase::fallbacksForFamily(family, style, styleHint, script)); - return result; -} - -void QWinRTFontDatabase::releaseHandle(void *handle) -{ - qCDebug(lcQpaFonts) << __FUNCTION__ << handle; - - if (!handle) - return; - - IDWriteFontFile *fontFile = reinterpret_cast(handle); - if (m_fonts.contains(fontFile)) { - m_fonts.remove(fontFile); - fontFile->Release(); - return; - } - - QBasicFontDatabase::releaseHandle(handle); -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h deleted file mode 100644 index 8fed4a3fa7..0000000000 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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 QWINRTFONTDATABASE_H -#define QWINRTFONTDATABASE_H - -#include -#include - -struct IDWriteFontFile; -struct IDWriteFontFamily; - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(lcQpaFonts) - -struct FontDescription -{ - quint32 index; - QByteArray uuid; -}; - -class QWinRTFontDatabase : public QBasicFontDatabase -{ -public: - QString fontDir() const; - ~QWinRTFontDatabase(); - QFont defaultFont() const Q_DECL_OVERRIDE; - bool fontsAlwaysScalable() const Q_DECL_OVERRIDE; - void populateFontDatabase() Q_DECL_OVERRIDE; - void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; - QStringList fallbacksForFamily(const QString &family, QFont::Style style, - QFont::StyleHint styleHint, QChar::Script script) const Q_DECL_OVERRIDE; - void releaseHandle(void *handle) Q_DECL_OVERRIDE; -private: - QHash m_fonts; - QHash m_fontFamilies; -}; - -QT_END_NAMESPACE - -#endif // QWINRTFONTDATABASE_H diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 7a0c95e6c1..ffc3bbf077 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -45,7 +45,6 @@ #include "qwinrtinputcontext.h" #include "qwinrtservices.h" #include "qwinrteglcontext.h" -#include "qwinrtfontdatabase.h" #include "qwinrttheme.h" #include "qwinrtclipboard.h" #ifndef QT_NO_DRAGANDDROP @@ -56,6 +55,7 @@ #include #include +#include #include #include #include diff --git a/src/plugins/platforms/winrt/winrt.pro b/src/plugins/platforms/winrt/winrt.pro index 8fd2a83a16..be2f5ca7e2 100644 --- a/src/plugins/platforms/winrt/winrt.pro +++ b/src/plugins/platforms/winrt/winrt.pro @@ -8,7 +8,7 @@ QT += \ DEFINES *= QT_NO_CAST_FROM_ASCII __WRL_NO_DEFAULT_LIB__ -LIBS += $$QMAKE_LIBS_CORE -ldwrite -ld3d11 +LIBS += $$QMAKE_LIBS_CORE -ld3d11 SOURCES = \ main.cpp \ @@ -20,7 +20,6 @@ SOURCES = \ qwinrteventdispatcher.cpp \ qwinrtfiledialoghelper.cpp \ qwinrtfileengine.cpp \ - qwinrtfontdatabase.cpp \ qwinrtinputcontext.cpp \ qwinrtintegration.cpp \ qwinrtmessagedialoghelper.cpp \ @@ -39,7 +38,6 @@ HEADERS = \ qwinrteventdispatcher.h \ qwinrtfiledialoghelper.h \ qwinrtfileengine.h \ - qwinrtfontdatabase.h \ qwinrtinputcontext.h \ qwinrtintegration.h \ qwinrtmessagedialoghelper.h \ -- cgit v1.2.3 From 5fcda458721c85f7b4209f418b416ffa5c93936e Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 8 Nov 2016 21:45:07 +0100 Subject: Do not guard tslib with evdev That relation is incorrect. We can have tslib support without evdev. Task-number: QTBUG-54998 Change-Id: I2c09bad73210fa4a13000077480c70365d482e2e Reviewed-by: Eirik Aavitsland --- src/plugins/platforms/eglfs/qeglfsintegration.cpp | 14 ++++++++------ src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp | 14 ++++++++------ 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index c226c0134a..bb62506f33 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -406,15 +406,17 @@ void QEglFSIntegration::createInputHandlers() } #endif -#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) - m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this); - new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this); + bool useTslib = false; #ifndef QT_NO_TSLIB - const bool useTslib = qEnvironmentVariableIntValue("QT_QPA_EGLFS_TSLIB"); + useTslib = qEnvironmentVariableIntValue("QT_QPA_EGLFS_TSLIB"); if (useTslib) new QTsLibMouseHandler(QLatin1String("TsLib"), QString() /* spec */); - else -#endif // QT_NO_TSLIB +#endif + +#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) + m_kbdMgr = new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString() /* spec */, this); + new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString() /* spec */, this); + if (!useTslib) new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this); #endif } diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp index 8c8c8a15ea..3cc0e735ad 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -141,15 +141,17 @@ void QLinuxFbIntegration::createInputHandlers() } #endif -#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) - new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); - new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); + bool useTslib = false; #ifndef QT_NO_TSLIB - const bool useTslib = qEnvironmentVariableIntValue("QT_QPA_FB_TSLIB"); + useTslib = qEnvironmentVariableIntValue("QT_QPA_FB_TSLIB"); if (useTslib) new QTsLibMouseHandler(QLatin1String("TsLib"), QString()); - else -#endif // QT_NO_TSLIB +#endif + +#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) + new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); + new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); + if (!useTslib) new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this); #endif } -- cgit v1.2.3 From 3c2cb87de2554b9c4f6e2080768fe9ede00aeab3 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 7 Nov 2016 09:54:55 +0100 Subject: xcb: Warn and bail out when even the basic, dummy context fails Do not move on to glGet since the behavior is undefined. Task-number: QTBUG-48986 Change-Id: Ifd279635ed1b8441f92697965d15ae3ecb59a7e3 Reviewed-by: Andy Nichols --- .../platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 9bdedcc830..c2b7a562a9 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -672,8 +672,11 @@ void QGLXContext::queryDummyContext() } QOpenGLContext context; - context.create(); - context.makeCurrent(surface.data()); + if (!context.create() || !context.makeCurrent(surface.data())) { + qWarning("QGLXContext: Failed to create dummy context"); + m_supportsThreading = false; + return; + } m_supportsThreading = true; -- cgit v1.2.3 From c214379156e4c75dcfe59cf73d69b912f4293303 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Mon, 14 Nov 2016 10:49:35 +0100 Subject: winrt: Fix definition of GL_GLEXT_PROTOTYPES in qwinrtbackingstore We have to make sure that GL_GLEXT_RPOTOTYPES is defined when qplatformbackingstore.h is included. Without the definition glBlitFramebufferANGLE will not be set and compilation might fail. Task-number: QTBUG-57083 Change-Id: I4cacaf4c2851913b3437ebd1f0f2956d0f400553 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/winrt/qwinrtbackingstore.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/winrt/qwinrtbackingstore.h b/src/plugins/platforms/winrt/qwinrtbackingstore.h index ce99718548..41b27debcc 100644 --- a/src/plugins/platforms/winrt/qwinrtbackingstore.h +++ b/src/plugins/platforms/winrt/qwinrtbackingstore.h @@ -40,6 +40,7 @@ #ifndef QWINRTBACKINGSTORE_H #define QWINRTBACKINGSTORE_H +#define GL_GLEXT_PROTOTYPES #include #include #include -- cgit v1.2.3 From 291eba6f8099a0fec8fbd9cf8a1fb67e5c9f4f8d Mon Sep 17 00:00:00 2001 From: Palo Kisa Date: Mon, 7 Nov 2016 18:27:17 +0100 Subject: QClipboard: Fix emitting changed() in XCB In XCB environment the QClipboard::changed() was not delivered if the QClipboard::clear() was issued by other Qt app/process. If the QClipboard::clear() is used, then the owner in xcb_xfixes_selection_notify_event_t is XCB_NONE, so we need make the decission to handle this event by the selection_timestamp and our m_timestamp[mode]. Task-number: QTBUG-56972 Change-Id: If4c486ac02223eac506465cac7ff1a07bd02a187 Reviewed-by: Lars Knoll --- src/plugins/platforms/xcb/qxcbclipboard.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index d44ebae8f7..40abef4e50 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -723,8 +723,10 @@ void QXcbClipboard::handleXFixesSelectionRequest(xcb_xfixes_selection_notify_eve if (mode > QClipboard::Selection) return; - // here we care only about the xfixes events that come from non Qt processes - if (event->owner != XCB_NONE && event->owner != owner()) { + // Note1: Here we care only about the xfixes events that come from other processes. + // Note2: If the QClipboard::clear() is issued, event->owner is XCB_NONE, + // so we check selection_timestamp to not handle our own QClipboard::clear(). + if (event->owner != owner() && event->selection_timestamp > m_timestamp[mode]) { if (!m_xClipboard[mode]) { m_xClipboard[mode].reset(new QXcbClipboardMime(mode, this)); } else { -- cgit v1.2.3 From 246fe271878dbe586b5f3222a78d67dfecd1ca83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 11 Nov 2016 08:01:29 +0100 Subject: Cocoa: Make dictation via speech recognition work Returning NSNotFound from the NSTextInputClient selectedRange implementation when there is no selection prevents dictation from activating (for unknown reasons). Return an empty {0, 0} range instead. Text input methods such as Pinyin still work after this change. [ChangeLog][macOS] Speech to text dictation now works for Qt text input. Change-Id: Ibf1729bdd271e8ed5ce3c9d2a0373c8ab3613d8e Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qnsview.mm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 1ad9b5f327..50dda52a7b 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1783,9 +1783,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) - (NSRange) selectedRange { - NSRange selectedRange = {NSNotFound, 0}; - selectedRange.location = NSNotFound; - selectedRange.length = 0; + NSRange selectedRange = {0, 0}; QObject *fo = QGuiApplication::focusObject(); if (!fo) -- cgit v1.2.3 From 71d21ed500a20f3fbabb000243cef1168893c9d5 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 4 Nov 2016 09:55:04 +0100 Subject: Fix image format conversion QImage::convertToFormat() returns the converted image. Change-Id: Icfd3ff43e04939e6b92c7fa94e5e0af60f633385 Reviewed-by: Andy Nichols --- src/plugins/platforms/mirclient/qmirclientcursor.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/mirclient/qmirclientcursor.cpp b/src/plugins/platforms/mirclient/qmirclientcursor.cpp index 83ea116c11..a0da3fdd77 100644 --- a/src/plugins/platforms/mirclient/qmirclientcursor.cpp +++ b/src/plugins/platforms/mirclient/qmirclientcursor.cpp @@ -167,7 +167,7 @@ void QMirClientCursor::configureMirCursorWithPixmapQCursor(MirSurface *surface, QImage image = cursor.pixmap().toImage(); if (image.format() != QImage::Format_ARGB32) { - image.convertToFormat(QImage::Format_ARGB32); + image = image.convertToFormat(QImage::Format_ARGB32); } MirBufferStream *bufferStream = mir_connection_create_buffer_stream_sync(mConnection, -- cgit v1.2.3 From e71cf692179732080a7bf75dc1bcbcefd4f94f0b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 14 Nov 2016 20:57:16 +0100 Subject: fix directfb build 60985aa42 converted the QT_CONFIG use, not taking into account that the feature isn't actually known to the configure system - it's coming directly from the makespec. so revert that hunk (until we have a better integration between makespecs and configure). Task-number: QTBUG-57039 Change-Id: Iaf57b5f5339250055f1c378e091da3ab3fcd4292 Reviewed-by: Jake Petroules --- src/plugins/platforms/directfb/directfb.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/directfb/directfb.pro b/src/plugins/platforms/directfb/directfb.pro index 406b89e3b2..4e95aebe35 100644 --- a/src/plugins/platforms/directfb/directfb.pro +++ b/src/plugins/platforms/directfb/directfb.pro @@ -27,7 +27,7 @@ HEADERS = qdirectfbintegration.h \ qdirectfbeglhooks.h # ### port the GL context -qtConfig(directfb_egl) { +contains(QT_CONFIG, directfb_egl) { HEADERS += qdirectfb_egl.h SOURCES += qdirectfb_egl.cpp DEFINES += DIRECTFB_GL_EGL -- cgit v1.2.3 From 27aeeac6eeb11150b505f8ffde6e87e157c22c90 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 24 Oct 2016 14:07:33 -0700 Subject: Cocoa Dialog Helpers: Refactor OK-Cancel buttons view Since virtually all the logic is shared between QNSColorPanelDelegate and QNSFontPanelDelegate, we extract the added buttons and layouting logic and move it into its own class. This requires the two afore mentioned Objective C classes to satisfy the QNSPanelDelegate protocol. Change-Id: Ie26e758f5db71920896d930a4f3644b51a1ce3fa Reviewed-by: Timur Pocheptsov --- .../platforms/cocoa/qcocoacolordialoghelper.mm | 119 +++---------------- .../platforms/cocoa/qcocoafontdialoghelper.mm | 126 ++------------------- src/plugins/platforms/cocoa/qcocoahelpers.h | 23 ++++ src/plugins/platforms/cocoa/qcocoahelpers.mm | 114 +++++++++++++++++++ 4 files changed, 163 insertions(+), 219 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm index 3a5a0c8e78..60c4c1a8ca 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm @@ -50,31 +50,13 @@ QT_USE_NAMESPACE -static NSButton *macCreateButton(const char *text, NSView *superview) -{ - static const NSRect buttonFrameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } }; - - NSButton *button = [[NSButton alloc] initWithFrame:buttonFrameRect]; - [button setButtonType:NSMomentaryLightButton]; - [button setBezelStyle:NSRoundedBezelStyle]; - [button setTitle:(NSString*)(CFStringRef)QCFString( - QPlatformTheme::removeMnemonics(QCoreApplication::translate("QPlatformTheme", text)))]; - [[button cell] setFont:[NSFont systemFontOfSize: - [NSFont systemFontSizeForControlSize:NSRegularControlSize]]]; - [superview addSubview:button]; - return button; -} - -@class QT_MANGLE_NAMESPACE(QNSColorPanelDelegate); - -@interface QT_MANGLE_NAMESPACE(QNSColorPanelDelegate) : NSObject +@interface QT_MANGLE_NAMESPACE(QNSColorPanelDelegate) : NSObject { @public NSColorPanel *mColorPanel; QCocoaColorDialogHelper *mHelper; NSView *mStolenContentView; - NSButton *mOkButton; - NSButton *mCancelButton; + QNSPanelContentsWrapper *mPanelButtons; QColor mQtColor; NSInteger mResultCode; BOOL mDialogIsExecuting; @@ -82,7 +64,6 @@ static NSButton *macCreateButton(const char *text, NSView *superview) BOOL mClosingDueToKnownButton; }; - (void)restoreOriginalContentView; -- (void)relayout; - (void)updateQtColor; - (void)finishOffWithCode:(NSInteger)code; @end @@ -97,8 +78,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); mColorPanel = [NSColorPanel sharedColorPanel]; mHelper = 0; mStolenContentView = 0; - mOkButton = 0; - mCancelButton = 0; + mPanelButtons = nil; mResultCode = NSCancelButton; mDialogIsExecuting = false; mResultSet = false; @@ -142,23 +122,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); [mColorPanel setContentView:0]; // create a new content view and add the stolen one as a subview - NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } }; - NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect]; - [ourContentView addSubview:mStolenContentView]; - - // create OK and Cancel buttons and add these as subviews - mOkButton = macCreateButton("&OK", ourContentView); - mCancelButton = macCreateButton("Cancel", ourContentView); - - [mColorPanel setContentView:ourContentView]; - [mColorPanel setDefaultButtonCell:[mOkButton cell]]; - [self relayout]; - - [mOkButton setAction:@selector(onOkClicked)]; - [mOkButton setTarget:self]; - - [mCancelButton setAction:@selector(onCancelClicked)]; - [mCancelButton setTarget:self]; + mPanelButtons = [[QNSPanelContentsWrapper alloc] initWithPanelDelegate:self]; + [mPanelButtons addSubview:mStolenContentView]; + mColorPanel.contentView = mPanelButtons; + mColorPanel.defaultButtonCell = mPanelButtons.okButton.cell; } } @@ -167,12 +134,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); [mColorPanel close]; } -- (void)windowDidResize:(NSNotification *)notification -{ - Q_UNUSED(notification); - [self relayout]; -} - - (void)colorChanged:(NSNotification *)notification { Q_UNUSED(notification); @@ -182,7 +143,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); - (void)windowWillClose:(NSNotification *)notification { Q_UNUSED(notification); - if (mCancelButton && mHelper && !mClosingDueToKnownButton) { + if (mPanelButtons && mHelper && !mClosingDueToKnownButton) { mClosingDueToKnownButton = true; // prevent repeating emit emit mHelper->reject(); } @@ -191,68 +152,16 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); - (void)restoreOriginalContentView { if (mStolenContentView) { - NSView *ourContentView = [mColorPanel contentView]; - // return stolen stuff to its rightful owner [mStolenContentView removeFromSuperview]; [mColorPanel setContentView:mStolenContentView]; - [mOkButton release]; - [mCancelButton release]; - [ourContentView release]; - mOkButton = 0; - mCancelButton = 0; - mStolenContentView = 0; + [mStolenContentView release]; + mStolenContentView = nil; + [mPanelButtons release]; + mPanelButtons = nil; } } -- (void)relayout -{ - if (!mOkButton) - return; - - NSRect rect = [[mStolenContentView superview] frame]; - - // should a priori be kept in sync with qfontdialog_mac.mm - const CGFloat ButtonMinWidth = 78.0; // 84.0 for Carbon - const CGFloat ButtonMinHeight = 32.0; - const CGFloat ButtonSpacing = 0.0; - const CGFloat ButtonTopMargin = 0.0; - const CGFloat ButtonBottomMargin = 7.0; - const CGFloat ButtonSideMargin = 9.0; - - [mOkButton sizeToFit]; - NSSize okSizeHint = [mOkButton frame].size; - - [mCancelButton sizeToFit]; - NSSize cancelSizeHint = [mCancelButton frame].size; - - const CGFloat ButtonWidth = qMin(qMax(ButtonMinWidth, - qMax(okSizeHint.width, cancelSizeHint.width)), - CGFloat((rect.size.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5)); - const CGFloat ButtonHeight = qMax(ButtonMinHeight, - qMax(okSizeHint.height, cancelSizeHint.height)); - - NSRect okRect = { { rect.size.width - ButtonSideMargin - ButtonWidth, - ButtonBottomMargin }, - { ButtonWidth, ButtonHeight } }; - [mOkButton setFrame:okRect]; - [mOkButton setNeedsDisplay:YES]; - - NSRect cancelRect = { { okRect.origin.x - ButtonSpacing - ButtonWidth, - ButtonBottomMargin }, - { ButtonWidth, ButtonHeight } }; - [mCancelButton setFrame:cancelRect]; - [mCancelButton setNeedsDisplay:YES]; - - const CGFloat Y = ButtonBottomMargin + ButtonHeight + ButtonTopMargin; - NSRect stolenCVRect = { { 0.0, Y }, - { rect.size.width, rect.size.height - Y } }; - [mStolenContentView setFrame:stolenCVRect]; - [mStolenContentView setNeedsDisplay:YES]; - - [[mStolenContentView superview] setNeedsDisplay:YES]; -} - - (void)onOkClicked { mClosingDueToKnownButton = true; @@ -263,7 +172,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); - (void)onCancelClicked { - if (mOkButton) { + if (mPanelButtons) { mClosingDueToKnownButton = true; [mColorPanel close]; mQtColor = QColor(); @@ -335,7 +244,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSColorPanelDelegate); - (BOOL)windowShouldClose:(id)window { Q_UNUSED(window); - if (!mOkButton) + if (!mPanelButtons) [self updateQtColor]; if (mDialogIsExecuting) { [self finishOffWithCode:NSCancelButton]; diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index 0be931b54f..e565f3b5b1 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -58,33 +58,6 @@ typedef float CGFloat; // Should only not be defined on 32-bit platforms QT_USE_NAMESPACE -// should a priori be kept in sync with qcolordialog_mac.mm -const CGFloat ButtonMinWidth = 78.0; -const CGFloat ButtonMinHeight = 32.0; -const CGFloat ButtonSpacing = 0.0; -const CGFloat ButtonTopMargin = 0.0; -const CGFloat ButtonBottomMargin = 7.0; -const CGFloat ButtonSideMargin = 9.0; - -// looks better with some margins -const CGFloat DialogTopMargin = 7.0; -const CGFloat DialogSideMargin = 9.0; - -static NSButton *macCreateButton(const char *text, NSView *superview) -{ - static const NSRect buttonFrameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } }; - - NSButton *button = [[NSButton alloc] initWithFrame:buttonFrameRect]; - [button setButtonType:NSMomentaryLightButton]; - [button setBezelStyle:NSRoundedBezelStyle]; - [button setTitle:(NSString*)(CFStringRef)QCFString( - QPlatformTheme::removeMnemonics(QCoreApplication::translate("QDialogButtonBox", text)))]; - [[button cell] setFont:[NSFont systemFontOfSize: - [NSFont systemFontSizeForControlSize:NSRegularControlSize]]]; - [superview addSubview:button]; - return button; -} - static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) { QFont newFont; @@ -103,22 +76,19 @@ static QFont qfontForCocoaFont(NSFont *cocoaFont, const QFont &resolveFont) @class QT_MANGLE_NAMESPACE(QNSFontPanelDelegate); -@interface QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) : NSObject +@interface QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) : NSObject { @public NSFontPanel *mFontPanel; QCocoaFontDialogHelper *mHelper; NSView *mStolenContentView; - NSButton *mOkButton; - NSButton *mCancelButton; + QNSPanelContentsWrapper *mPanelButtons; QFont mQtFont; NSInteger mResultCode; BOOL mDialogIsExecuting; BOOL mResultSet; }; - (void)restoreOriginalContentView; -- (void)relayout; -- (void)relayoutToContentSize:(NSSize)frameSize; - (void)updateQtFont; - (void)changeFont:(id)sender; - (void)finishOffWithCode:(NSInteger)code; @@ -134,8 +104,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); mFontPanel = [NSFontPanel sharedFontPanel]; mHelper = 0; mStolenContentView = 0; - mOkButton = 0; - mCancelButton = 0; + mPanelButtons = 0; mResultCode = NSCancelButton; mDialogIsExecuting = false; mResultSet = false; @@ -173,23 +142,11 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); [mFontPanel setContentView:0]; // create a new content view and add the stolen one as a subview - NSRect frameRect = { { 0.0, 0.0 }, { 0.0, 0.0 } }; - NSView *ourContentView = [[NSView alloc] initWithFrame:frameRect]; - [ourContentView addSubview:mStolenContentView]; - - // create OK and Cancel buttons and add these as subviews - mOkButton = macCreateButton("&OK", ourContentView); - mCancelButton = macCreateButton("Cancel", ourContentView); - - [mFontPanel setContentView:ourContentView]; - [mFontPanel setDefaultButtonCell:[mOkButton cell]]; - [self relayoutToContentSize:[[mStolenContentView superview] frame].size]; - - [mOkButton setAction:@selector(onOkClicked)]; - [mOkButton setTarget:self]; - - [mCancelButton setAction:@selector(onCancelClicked)]; - [mCancelButton setTarget:self]; + mPanelButtons = [[QNSPanelContentsWrapper alloc] initWithPanelDelegate:self]; + [mPanelButtons addSubview:mStolenContentView]; + mPanelButtons.panelContentsMargins = NSEdgeInsetsMake(0, 0, 7, 0); + mFontPanel.contentView = mPanelButtons; + mFontPanel.defaultButtonCell = mPanelButtons.okButton.cell; } } @@ -198,77 +155,18 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); [mFontPanel close]; } -- (void)windowDidResize:(NSNotification *)notification -{ - Q_UNUSED(notification); - [self relayout]; -} - - (void)restoreOriginalContentView { if (mStolenContentView) { - NSView *ourContentView = [mFontPanel contentView]; - // return stolen stuff to its rightful owner [mStolenContentView removeFromSuperview]; [mFontPanel setContentView:mStolenContentView]; - [mOkButton release]; - [mCancelButton release]; - [ourContentView release]; - mOkButton = 0; - mCancelButton = 0; mStolenContentView = 0; + [mPanelButtons release]; + mPanelButtons = nil; } } -- (void)relayout -{ - if (!mOkButton) - return; - - [self relayoutToContentSize:[[mStolenContentView superview] frame].size]; -} - -- (void)relayoutToContentSize:(NSSize)frameSize -{ - Q_ASSERT(mOkButton); - - [mOkButton sizeToFit]; - NSSize okSizeHint = [mOkButton frame].size; - - [mCancelButton sizeToFit]; - NSSize cancelSizeHint = [mCancelButton frame].size; - - const CGFloat ButtonWidth = qMin(qMax(ButtonMinWidth, - qMax(okSizeHint.width, cancelSizeHint.width)), - CGFloat((frameSize.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5)); - const CGFloat ButtonHeight = qMax(ButtonMinHeight, - qMax(okSizeHint.height, cancelSizeHint.height)); - - const CGFloat X = DialogSideMargin; - const CGFloat Y = ButtonBottomMargin + ButtonHeight + ButtonTopMargin; - - NSRect okRect = { { frameSize.width - ButtonSideMargin - ButtonWidth, - ButtonBottomMargin }, - { ButtonWidth, ButtonHeight } }; - [mOkButton setFrame:okRect]; - [mOkButton setNeedsDisplay:YES]; - - NSRect cancelRect = { { okRect.origin.x - ButtonSpacing - ButtonWidth, - ButtonBottomMargin }, - { ButtonWidth, ButtonHeight } }; - [mCancelButton setFrame:cancelRect]; - [mCancelButton setNeedsDisplay:YES]; - - NSRect stolenCVRect = { { X, Y }, - { frameSize.width - X - X, frameSize.height - Y - DialogTopMargin } }; - [mStolenContentView setFrame:stolenCVRect]; - [mStolenContentView setNeedsDisplay:YES]; - - [[mStolenContentView superview] setNeedsDisplay:YES]; -} - - - (void)onOkClicked { [mFontPanel close]; @@ -277,7 +175,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); - (void)onCancelClicked { - if (mOkButton) { + if (mPanelButtons) { [mFontPanel close]; mQtFont = QFont(); [self finishOffWithCode:NSCancelButton]; @@ -332,7 +230,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSFontPanelDelegate); - (BOOL)windowShouldClose:(id)window { Q_UNUSED(window); - if (!mOkButton) + if (!mPanelButtons) [self updateQtFont]; if (mDialogIsExecuting) { [self finishOffWithCode:NSCancelButton]; diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 1b038a6b5e..a2e0876073 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -158,7 +158,30 @@ T qt_mac_resolveOption(const T &fallback, QWindow *window, const QByteArray &pro // return default value. return fallback; } + QT_END_NAMESPACE +@protocol QT_MANGLE_NAMESPACE(QNSPanelDelegate) +@required +- (void)onOkClicked; +- (void)onCancelClicked; +@end + +@interface QT_MANGLE_NAMESPACE(QNSPanelContentsWrapper) : NSView + +@property (nonatomic, readonly) NSButton *okButton; +@property (nonatomic, readonly) NSButton *cancelButton; +@property (nonatomic, readonly) NSView *panelContents; // ARC: unretained, make it weak +@property (nonatomic, assign) NSEdgeInsets panelContentsMargins; + +- (instancetype)initWithPanelDelegate:(id)panelDelegate; +- (void)dealloc; + +- (NSButton *)createButtonWithTitle:(const char *)title; +- (void)layout; +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSPanelContentsWrapper); + #endif //QCOCOAHELPERS_H diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index c57567bdd6..01fbb7bad2 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -300,3 +300,117 @@ QString qt_mac_removeAmpersandEscapes(QString s) } QT_END_NAMESPACE + +/*! \internal + + This NSView derived class is used to add OK/Cancel + buttons to NSColorPanel and NSFontPanel. It replaces + the panel's content view, while reparenting the former + content view into itself. It also takes care of setting + the target-action for the OK/Cancel buttons and making + sure the layout is consistent. + */ +@implementation QNSPanelContentsWrapper + +- (instancetype)initWithPanelDelegate:(id)panelDelegate +{ + if ((self = [super initWithFrame:NSZeroRect])) { + // create OK and Cancel buttons and add these as subviews + _okButton = [self createButtonWithTitle:"&OK"]; + _okButton.action = @selector(onOkClicked); + _okButton.target = panelDelegate; + + _cancelButton = [self createButtonWithTitle:"Cancel"]; + _cancelButton.action = @selector(onCancelClicked); + _cancelButton.target = panelDelegate; + + _panelContents = nil; + + _panelContentsMargins = NSEdgeInsetsMake(0, 0, 0, 0); + } + + return self; +} + +- (void)dealloc +{ + [_okButton release]; + _okButton = nil; + [_cancelButton release]; + _cancelButton = nil; + + _panelContents = nil; + + [super dealloc]; +} + +- (NSButton *)createButtonWithTitle:(const char *)title +{ + NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect]; + button.buttonType = NSMomentaryLightButton; + button.bezelStyle = NSRoundedBezelStyle; + const QString &cleanTitle = QPlatformTheme::removeMnemonics(QCoreApplication::translate("QDialogButtonBox", title)); + // FIXME: Not obvious, from Cocoa's documentation, that QString::toNSString() makes a deep copy + button.title = (NSString *)cleanTitle.toCFString(); + ((NSButtonCell *)button.cell).font = + [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]; + [self addSubview:button]; + return button; +} + +- (void)layout +{ + static const CGFloat ButtonMinWidth = 78.0; // 84.0 for Carbon + static const CGFloat ButtonMinHeight = 32.0; + static const CGFloat ButtonSpacing = 0.0; + static const CGFloat ButtonTopMargin = 0.0; + static const CGFloat ButtonBottomMargin = 7.0; + static const CGFloat ButtonSideMargin = 9.0; + + NSSize frameSize = self.frame.size; + + [self.okButton sizeToFit]; + NSSize okSizeHint = self.okButton.frame.size; + + [self.cancelButton sizeToFit]; + NSSize cancelSizeHint = self.cancelButton.frame.size; + + const CGFloat buttonWidth = qMin(qMax(ButtonMinWidth, + qMax(okSizeHint.width, cancelSizeHint.width)), + CGFloat((frameSize.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5)); + const CGFloat buttonHeight = qMax(ButtonMinHeight, + qMax(okSizeHint.height, cancelSizeHint.height)); + + NSRect okRect = { { frameSize.width - ButtonSideMargin - buttonWidth, + ButtonBottomMargin }, + { buttonWidth, buttonHeight } }; + self.okButton.frame = okRect; + self.okButton.needsDisplay = YES; + + NSRect cancelRect = { { okRect.origin.x - ButtonSpacing - buttonWidth, + ButtonBottomMargin }, + { buttonWidth, buttonHeight } }; + self.cancelButton.frame = cancelRect; + self.cancelButton.needsDisplay = YES; + + // The third view should be the original panel contents. Cache it. + if (!self.panelContents) + for (NSView *view in self.subviews) + if (view != self.okButton && view != self.cancelButton) { + _panelContents = view; + break; + } + + const CGFloat buttonBoxHeight = ButtonBottomMargin + buttonHeight + ButtonTopMargin; + const NSRect panelContentsFrame = NSMakeRect( + self.panelContentsMargins.left, + buttonBoxHeight + self.panelContentsMargins.bottom, + frameSize.width - (self.panelContentsMargins.left + self.panelContentsMargins.right), + frameSize.height - buttonBoxHeight - (self.panelContentsMargins.top + self.panelContentsMargins.bottom)); + self.panelContents.frame = panelContentsFrame; + self.panelContents.needsDisplay = YES; + + self.needsDisplay = YES; +} + +@end -- cgit v1.2.3 From 3e3b22adeb5267d47ad9aedce9fef816e91197e9 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 15 Nov 2016 13:09:01 +0100 Subject: winrt: Fix ill-constructed loop That loop could never have worked properly. Identified by analyze compile switch. Change-Id: I5e987dc9f5c57d3ffbcf054b7b417b506c02e7e1 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtfileengine.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp index 53e7ebd30d..557c13cf63 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp +++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp @@ -92,7 +92,7 @@ public: } firstDot = fileName.size(); - for (int i = lastSeparator; i > fileName.size(); ++i) { + for (int i = lastSeparator; i < fileName.size(); ++i) { if (fileName.at(i).unicode() == '.') { firstDot = i; break; -- cgit v1.2.3 From 7912ac5d672bef9ab46d05a11fc71cb6ed68acf7 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 15 Nov 2016 13:10:10 +0100 Subject: winrt: move to range based loop Change-Id: I0694adcff9b591eecf1025074e8b1c478484bd74 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp index 038a6d32e8..417dbdc1db 100644 --- a/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp +++ b/src/plugins/platforms/winrt/qwinrtfiledialoghelper.cpp @@ -195,8 +195,8 @@ static bool initializeOpenPickerOptions(T *picker, const QSharedPointer> filters; hr = picker->get_FileTypeFilter(&filters); RETURN_FALSE_IF_FAILED("Failed to get file type filters list"); - foreach (const QString &namedFilter, options->nameFilters()) { - foreach (const QString &filter, QPlatformFileDialogHelper::cleanFilterList(namedFilter)) { + for (const QString &namedFilter : options->nameFilters()) { + for (const QString &filter : QPlatformFileDialogHelper::cleanFilterList(namedFilter)) { // Remove leading star const int offset = (filter.length() > 1 && filter.startsWith(QLatin1Char('*'))) ? 1 : 0; HStringReference filterRef(reinterpret_cast(filter.utf16() + offset), @@ -419,13 +419,15 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit ComPtr *>> choices; hr = picker->get_FileTypeChoices(&choices); RETURN_FALSE_IF_FAILED("Failed to get file extension choices"); - foreach (const QString &namedFilter, dialogOptions->nameFilters()) { + const QStringList nameFilters = dialogOptions->nameFilters(); + for (const QString &namedFilter : nameFilters) { ComPtr> entry = Make(); - foreach (const QString &filter, QPlatformFileDialogHelper::cleanFilterList(namedFilter)) { + const QStringList cleanFilter = QPlatformFileDialogHelper::cleanFilterList(namedFilter); + for (const QString &filter : cleanFilter) { // Remove leading star - const int offset = (filter.length() > 1 && filter.startsWith(QLatin1Char('*'))) ? 1 : 0; - HStringReference filterRef(reinterpret_cast(filter.utf16() + offset), - filter.length() - offset); + const int starOffset = (filter.length() > 1 && filter.startsWith(QLatin1Char('*'))) ? 1 : 0; + HStringReference filterRef(reinterpret_cast(filter.utf16() + starOffset), + filter.length() - starOffset); hr = entry->Append(filterRef.Get()); if (FAILED(hr)) { qWarning("Failed to add named file filter \"%s\": %s", -- cgit v1.2.3 From 3e5e2cd3bd1271ce886fe5b97fe07dffb2631cc6 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 15 Nov 2016 13:48:39 +0100 Subject: winrt: Do not shadow variable Change-Id: I70fc9254bfdfe42bf0e8d379537eb60b21be8275 Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtdrag.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp index 055aacbf56..89ebf7d26f 100644 --- a/src/plugins/platforms/winrt/qwinrtdrag.cpp +++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp @@ -322,9 +322,9 @@ QVariant QWinRTInternalMimeData::retrieveData_sys(const QString &mimetype, QVari hr = res.As(&propertyValue); if (SUCCEEDED(hr)) { // We need to check which type of custom data we are receiving - PropertyType type; - propertyValue->get_Type(&type); - switch (type) { + PropertyType propertyType; + propertyValue->get_Type(&propertyType); + switch (propertyType) { case PropertyType_UInt8: { quint8 v; hr = propertyValue->GetUInt8(&v); @@ -410,7 +410,7 @@ QVariant QWinRTInternalMimeData::retrieveData_sys(const QString &mimetype, QVari return S_OK; } default: - qCDebug(lcQpaMime) << "Unknown property type dropped:" << type; + qCDebug(lcQpaMime) << "Unknown property type dropped:" << propertyType; } return S_OK; } -- cgit v1.2.3 From e8a41ed8668437eb6ad406ddabf4141fd66a85d2 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 2 Nov 2016 17:37:43 -0700 Subject: QCocoaMenu: Force NSMenuValidation when syncing items When a menu item's enabled state changes after -[QCocoaMenuDelegate menuWillOpen:] is invoked, i.e., during or after QMenu::aboutToShow() is emitted, that state change may not be taken into account. This is because the automatic menu validation, upon which Qt relies, is not made aware of any such change. By calling -[NSMenu update] when syncing the QPA menu item, we induce Cocoa to invoke -[QCocoaMenuDelegate validateMenuItem:] and ensure that previously synced items, whose state may have changed, will be properly updated. This, however, has a small side effect, namely that menu-holding items will also go through the automatic menu enabling path and may appear disabled since, until now, they were not properly configured. In order to solve this, we set the action on those items as well, and make sure that both of QCocoaMenuDelegate's relevant methods, validateMenuItem: and itemFired:, properly process menu-holding items. Menurama manual test updated accordingly. Change-Id: I62f955538b8be09b8494ea0ce87fca7910148d38 Task-number: QTBUG-56850 Reviewed-by: Timur Pocheptsov --- src/plugins/platforms/cocoa/qcocoamenu.mm | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'src/plugins/platforms') diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 566363e01f..88ffd48538 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -147,6 +147,10 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); - (void) itemFired:(NSMenuItem*) item { QCocoaMenuItem *cocoaItem = reinterpret_cast([item tag]); + // Menu-holding items also get a target to play nicely + // with NSMenuValidation but should not trigger. + if (cocoaItem->menu()) + return; QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData); QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]]; static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated); @@ -156,7 +160,8 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); - (BOOL)validateMenuItem:(NSMenuItem*)menuItem { QCocoaMenuItem *cocoaItem = reinterpret_cast(menuItem.tag); - if (!cocoaItem) + // Menu-holding items are always enabled, as it's conventional in Cocoa + if (!cocoaItem || cocoaItem->menu()) return YES; return cocoaItem->isEnabled(); @@ -327,9 +332,9 @@ void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem * void QCocoaMenu::insertNative(QCocoaMenuItem *item, QCocoaMenuItem *beforeItem) { item->nsItem().target = m_nativeMenu.delegate; - if (!item->menu()) - [item->nsItem() setAction:@selector(itemFired:)]; - else if (isOpen() && item->nsItem()) // Someone's adding new items after aboutToShow() was emitted + item->nsItem().action = @selector(itemFired:); + // Someone's adding new items after aboutToShow() was emitted + if (isOpen() && item->menu() && item->nsItem()) item->menu()->setAttachedItem(item->nsItem()); item->setParentEnabled(isEnabled()); @@ -425,6 +430,10 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem) QCocoaMenuItem* beforeItem = itemOrNull(m_menuItems.indexOf(cocoaItem) + 1); insertNative(cocoaItem, beforeItem); + } else { + // Force NSMenuValidation to kick in. This is needed e.g. + // when an item's enabled state changes after menuWillOpen: + [m_nativeMenu update]; } } -- cgit v1.2.3