From 64ab7489b3d1ee9cc473d900e08f64d45412e1fc Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 19 Sep 2017 10:29:05 -0700 Subject: XCB: also test for Xinerama's presence It's included unconditionally from qxcbconnection.cpp and qxcbscreen.h. Task-number: QTBUG-53537 Change-Id: I6e1fe42ae4b742a7b811fffd14e5d374155660f3 Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/xcb_qpa_lib.pro | 1 - 1 file changed, 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro index 1c76b49650..284711075e 100644 --- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -69,7 +69,6 @@ include(gl_integrations/gl_integrations.pri) !qtConfig(system-xcb) { QMAKE_USE += xcb-static xcb } else { - LIBS += -lxcb-xinerama ### there is no configure test for this! qtConfig(xkb): QMAKE_USE += xcb_xkb qtConfig(xcb-render): QMAKE_USE += xcb_render QMAKE_USE += xcb_syslibs -- cgit v1.2.3 From d25346417238b7dc0fb37359a9b56eff2908a5dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Vr=C3=A1til?= Date: Mon, 18 Sep 2017 22:33:55 +0200 Subject: Only call mysql_library_end() once when using MariaDB MariaDB allows only a single call to mysql_library_end(), all subsequent calls to mysql_library_init() or any other API call will fail. Since QMYSQLDriver calls mysql_library_end() function whenever the refcount drops to 0, this breaks applications that close and reopen database connections. This change registers call to mysql_library_init() via qAddPostRoutine() when compiled against MariaDB, so that we only call it once. Task-number: QTBUG-63108 Change-Id: I22c1f0c5b081216f12596a32748dca25cae919e9 Reviewed-by: Andy Shaw --- src/plugins/sqldrivers/mysql/qsql_mysql.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp index ee439fa33e..6e428fb878 100644 --- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp +++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp @@ -1158,16 +1158,22 @@ static void qLibraryInit() } # endif // MYSQL_VERSION_ID #endif // Q_NO_MYSQL_EMBEDDED + +#ifdef MARIADB_BASE_VERSION + qAddPostRoutine(mysql_server_end); +#endif } static void qLibraryEnd() { -#ifndef Q_NO_MYSQL_EMBEDDED -# if MYSQL_VERSION_ID > 40000 -# if (MYSQL_VERSION_ID >= 40110 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50003 - mysql_library_end(); -# else - mysql_server_end(); +#if !defined(MARIADB_BASE_VERSION) +# if !defined(Q_NO_MYSQL_EMBEDDED) +# if MYSQL_VERSION_ID > 40000 +# if (MYSQL_VERSION_ID >= 40110 && MYSQL_VERSION_ID < 50000) || MYSQL_VERSION_ID >= 50003 + mysql_library_end(); +# else + mysql_server_end(); +# endif # endif # endif #endif -- cgit v1.2.3 From d03dba3f4abf21de842d3f1146d78ca4655c94e2 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 6 Sep 2017 16:22:45 +0200 Subject: Windows QPA: Move function to find screen by HWND to QWindowsScreenManager Task-number: QTBUG-62971 Change-Id: Ida0a8e758723f0f617011a89dc89c266d2506aad Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowsscreen.cpp | 15 +++++++++++++++ src/plugins/platforms/windows/qwindowsscreen.h | 1 + src/plugins/platforms/windows/qwindowswindow.cpp | 16 ++++++++-------- 3 files changed, 24 insertions(+), 8 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 3a4793efcd..cfddb3cc71 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -566,4 +566,19 @@ const QWindowsScreen *QWindowsScreenManager::screenAtDp(const QPoint &p) const return Q_NULLPTR; } +const QWindowsScreen *QWindowsScreenManager::screenForHwnd(HWND hwnd) const +{ + HMONITOR hMonitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL); + if (hMonitor == NULL) + return nullptr; + const auto it = + std::find_if(m_screens.cbegin(), m_screens.cend(), + [hMonitor](const QWindowsScreen *s) + { + return s->data().hMonitor == hMonitor + && (s->data().flags & QWindowsScreenData::VirtualDesktop) != 0; + }); + return it != m_screens.cend() ? *it : nullptr; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index 9a8997326b..7cf73f03af 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -134,6 +134,7 @@ public: const WindowsScreenList &screens() const { return m_screens; } const QWindowsScreen *screenAtDp(const QPoint &p) const; + const QWindowsScreen *screenForHwnd(HWND hwnd) const; private: void removeScreen(int index); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 5e0fd77776..050829e6f5 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1542,15 +1542,15 @@ void QWindowsWindow::handleGeometryChange() fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true); } if (!parent() && previousGeometry.topLeft() != m_data.geometry.topLeft()) { - HMONITOR hMonitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTONULL); QPlatformScreen *currentScreen = screen(); - const auto screens = QWindowsContext::instance()->screenManager().screens(); - auto newScreenIt = std::find_if(screens.begin(), screens.end(), [&](QWindowsScreen *s) { - return s->data().hMonitor == hMonitor - && s->data().flags & QWindowsScreenData::VirtualDesktop; - }); - if (newScreenIt != screens.end() && *newScreenIt != currentScreen) - QWindowSystemInterface::handleWindowScreenChanged(window(), (*newScreenIt)->screen()); + const QWindowsScreen *newScreen = + QWindowsContext::instance()->screenManager().screenForHwnd(m_data.hwnd); + if (newScreen != nullptr && newScreen != currentScreen) { + qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__ + << ' ' << window() << " \"" << currentScreen->name() + << "\"->\"" << newScreen->name() << '"'; + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + } } if (testFlag(SynchronousGeometryChangeEvent)) QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); -- cgit v1.2.3 From f1ec81b543fe1d5090acff298e24faf10a7bac63 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 19 Sep 2017 13:18:49 +0200 Subject: Windows QPA: Detect screen by mouse position when dragging a window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When dragging a window by its border, detect the screen by mouse position to prevent it from oscillating between screens when it resizes. Task-number: QTBUG-62971 Change-Id: I0a4a584ef8ff3bb7288d1abec4de51fb4091dccd Reviewed-by: Oliver Wolff Reviewed-by: Thorbjørn Lund Martsum --- src/plugins/platforms/windows/qtwindowsglobal.h | 6 ++++ src/plugins/platforms/windows/qwindowscontext.cpp | 7 +++++ src/plugins/platforms/windows/qwindowswindow.cpp | 34 +++++++++++++++-------- src/plugins/platforms/windows/qwindowswindow.h | 3 ++ 4 files changed, 39 insertions(+), 11 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h index b2152e7ed4..d2e1309280 100644 --- a/src/plugins/platforms/windows/qtwindowsglobal.h +++ b/src/plugins/platforms/windows/qtwindowsglobal.h @@ -101,6 +101,8 @@ enum WindowsEventType // Simplify event types FocusOutEvent = WindowEventFlag + 18, WhatsThisEvent = WindowEventFlag + 19, DpiChangedEvent = WindowEventFlag + 21, + EnterSizeMoveEvent = WindowEventFlag + 22, + ExitSizeMoveEvent = WindowEventFlag + 23, MouseEvent = MouseEventFlag + 1, MouseWheelEvent = MouseEventFlag + 2, CursorEvent = MouseEventFlag + 3, @@ -274,6 +276,10 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI return QtWindows::DeviceChangeEvent; case WM_DPICHANGED: return QtWindows::DpiChangedEvent; + case WM_ENTERSIZEMOVE: + return QtWindows::EnterSizeMoveEvent; + case WM_EXITSIZEMOVE: + return QtWindows::ExitSizeMoveEvent; default: break; } diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index e6e6ee8b1a..f108be96e7 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1055,6 +1055,13 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result); #endif break; + case QtWindows::EnterSizeMoveEvent: + platformWindow->setFlag(QWindowsWindow::ResizeMoveActive); + return true; + case QtWindows::ExitSizeMoveEvent: + platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive); + platformWindow->checkForScreenChanged(); + return true; case QtWindows::ScrollEvent: #if QT_CONFIG(sessionmanager) return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 050829e6f5..d97ebb7545 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1527,6 +1527,26 @@ void QWindowsWindow::handleResized(int wParam) } } +void QWindowsWindow::checkForScreenChanged() +{ + if (parent()) + return; + + QPlatformScreen *currentScreen = screen(); + const auto &screenManager = QWindowsContext::instance()->screenManager(); + // QTBUG-62971: When dragging a window by its border, detect by mouse position + // to prevent it from oscillating between screens when it resizes + const QWindowsScreen *newScreen = testFlag(ResizeMoveActive) + ? screenManager.screenAtDp(QWindowsCursor::mousePosition()) + : screenManager.screenForHwnd(m_data.hwnd); + if (newScreen != nullptr && newScreen != currentScreen) { + qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__ + << ' ' << window() << " \"" << currentScreen->name() + << "\"->\"" << newScreen->name() << '"'; + QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); + } +} + void QWindowsWindow::handleGeometryChange() { const QRect previousGeometry = m_data.geometry; @@ -1541,17 +1561,9 @@ void QWindowsWindow::handleGeometryChange() && !(m_data.geometry.width() > previousGeometry.width() || m_data.geometry.height() > previousGeometry.height())) { fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true); } - if (!parent() && previousGeometry.topLeft() != m_data.geometry.topLeft()) { - QPlatformScreen *currentScreen = screen(); - const QWindowsScreen *newScreen = - QWindowsContext::instance()->screenManager().screenForHwnd(m_data.hwnd); - if (newScreen != nullptr && newScreen != currentScreen) { - qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__ - << ' ' << window() << " \"" << currentScreen->name() - << "\"->\"" << newScreen->name() << '"'; - QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); - } - } + + checkForScreenChanged(); + if (testFlag(SynchronousGeometryChangeEvent)) QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index aa8ce7e73a..2b447751ba 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -208,6 +208,7 @@ public: Compositing = 0x200000, HasBorderInFullScreen = 0x400000, WithinDpiChanged = 0x800000, + ResizeMoveActive = 0x2000000 }; QWindowsWindow(QWindow *window, const QWindowsWindowData &data); @@ -313,6 +314,8 @@ public: void alertWindow(int durationMs = 0); void stopAlertWindow(); + void checkForScreenChanged(); + static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes); void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch); static void setHasBorderInFullScreenStatic(QWindow *window, bool border); -- cgit v1.2.3 From bc31d2235cbf81c05ef80de723ebc4dc45a89695 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 19 Sep 2017 14:34:55 +0200 Subject: Windows QPA: Call raise() also for SubWindows with WindowStaysOnTopHint QMdiSubWindows may have WindowStaysOnTopHint set. Task-number: QTBUG-63121 Change-Id: I21f80311fdf57e775df895122299bb7beb6ec4e6 Reviewed-by: Joerg Bornemann Reviewed-by: Oliver Wolff --- src/plugins/platforms/windows/qwindowswindow.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index d97ebb7545..bea849383d 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -872,7 +872,9 @@ void QWindowsBaseWindow::hide_sys() // Normal hide, do not activate other window void QWindowsBaseWindow::raise_sys() { qCDebug(lcQpaWindows) << __FUNCTION__ << this << window(); - if (window()->type() == Qt::Popup + const Qt::WindowType type = window()->type(); + if (type == Qt::Popup + || type == Qt::SubWindow // Special case for QTBUG-63121: MDI subwindows with WindowStaysOnTopHint || (window()->flags() & (Qt::WindowStaysOnTopHint | Qt::WindowStaysOnBottomHint)) == 0) { SetWindowPos(handle(), HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } -- cgit v1.2.3 From 113de68543b7d9ea5acf00ea34bf26c92cd0ac56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 11 Sep 2017 13:45:32 +0200 Subject: macOS: Don't send expose event as update request when becoming visible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QGuiApplicationPrivate::processExposeEvent updates the QWindow's exposed state, so we need to call QWindowSystemInterface::handleExposeEvent() when going from non-exposed to exposed. Change-Id: I461b2fb27cd8fd4bdb250d05d47f9af6cb3eb15c Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 63ee8c10ac..1ef02f5274 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1079,6 +1079,8 @@ void QCocoaWindow::handleGeometryChange() void QCocoaWindow::handleExposeEvent(const QRegion ®ion) { + const bool wasExposed = isExposed(); + // Ideally we'd implement isExposed() in terms of these properties, // plus the occlusionState of the NSWindow, and let the expose event // pull the exposed state out when needed. However, when the window @@ -1096,13 +1098,21 @@ 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; + if (windowPrivate->updateRequestPending) { + // We can only deliver update request events when the window is exposed, + // and we also have to make sure we deliver the first expose event after + // becoming exposed as a real expose event, otherwise the exposed state + // of the QWindow is never updated. + // FIXME: Should this logic live in QGuiApplication? + if (wasExposed && m_isExposed) { + qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleExposeEvent" << window() << region << "as update request"; + windowPrivate->deliverUpdateRequest(); + return; + } + + // FIXME: Should we re-trigger setNeedsDisplay in case of !wasExposed && m_isExposed? + // Or possibly send the expose event first, and then the update request? } qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed(); -- cgit v1.2.3 From 49154acde3c2c5f45a50dfd5d011c47db8b761f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 11 Sep 2017 14:04:51 +0200 Subject: macOS: Deliver NSWindow notifications to all windows, not just top level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Child QWindows (or in the case of QWindows embedded in native applications: top level QWindows where the corresponding NSView is a child of another view, so not being the contentView of its window), still need some of the NSWindow notifications to e.g. update their exposed state when the window becomes visible. We make sure to send the notification to all QCococaWindow children of the relevant NSWindow, and let each callback decide if it should only apply to content views. This fixes an issue where a QWindow would never be exposed if the window was a child NSView and added to a NSWindow that was yet to be shown. Change-Id: I7f7df8bc5f4ca3ac553a2c146f8c3229b197c059 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.h | 7 +- src/plugins/platforms/cocoa/qcocoawindow.mm | 117 ++++++++++++++++++---------- 2 files changed, 79 insertions(+), 45 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index c650c86379..a93a391358 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -134,11 +134,12 @@ public: void setEmbeddedInForeignView(bool subwindow); + Q_NOTIFICATION_HANDLER(NSViewFrameDidChangeNotification) void viewDidChangeFrame(); + Q_NOTIFICATION_HANDLER(NSViewGlobalFrameDidChangeNotification) void viewDidChangeGlobalFrame(); + Q_NOTIFICATION_HANDLER(NSWindowWillMoveNotification) void windowWillMove(); Q_NOTIFICATION_HANDLER(NSWindowDidMoveNotification) void windowDidMove(); Q_NOTIFICATION_HANDLER(NSWindowDidResizeNotification) void windowDidResize(); - Q_NOTIFICATION_HANDLER(NSViewFrameDidChangeNotification) void viewDidChangeFrame(); - Q_NOTIFICATION_HANDLER(NSViewGlobalFrameDidChangeNotification) void viewDidChangeGlobalFrame(); Q_NOTIFICATION_HANDLER(NSWindowDidEndLiveResizeNotification) void windowDidEndLiveResize(); Q_NOTIFICATION_HANDLER(NSWindowDidBecomeKeyNotification) void windowDidBecomeKey(); Q_NOTIFICATION_HANDLER(NSWindowDidResignKeyNotification) void windowDidResignKey(); @@ -148,8 +149,8 @@ public: Q_NOTIFICATION_HANDLER(NSWindowDidEnterFullScreenNotification) void windowDidEnterFullScreen(); Q_NOTIFICATION_HANDLER(NSWindowWillExitFullScreenNotification) void windowWillExitFullScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidExitFullScreenNotification) void windowDidExitFullScreen(); - Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidOrderOnScreenAndFinishAnimatingNotification) void windowDidOrderOnScreen(); + Q_NOTIFICATION_HANDLER(NSWindowDidOrderOffScreenNotification) void windowDidOrderOffScreen(); Q_NOTIFICATION_HANDLER(NSWindowDidChangeOcclusionStateNotification) void windowDidChangeOcclusionState(); Q_NOTIFICATION_HANDLER(NSWindowDidChangeScreenNotification) void windowDidChangeScreen(); Q_NOTIFICATION_HANDLER(NSWindowWillCloseNotification) void windowWillClose(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 1ef02f5274..a88ec2b0db 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -97,34 +97,30 @@ static void qRegisterNotificationCallbacks() [center addObserverForName:notificationName.toNSString() object:nil queue:nil usingBlock:^(NSNotification *notification) { - NSView *view = nullptr; + QVarLengthArray cocoaWindows; if ([notification.object isKindOfClass:[NSWindow class]]) { - NSWindow *window = notification.object; - if (!window.contentView) - return; - - view = window.contentView; + NSWindow *nsWindow = notification.object; + for (const QWindow *window : QGuiApplication::allWindows()) { + if (QCocoaWindow *cocoaWindow = static_cast(window->handle())) + if (cocoaWindow->nativeWindow() == nsWindow) + cocoaWindows += cocoaWindow; + } } else if ([notification.object isKindOfClass:[NSView class]]) { - view = notification.object; + if (QNSView *qnsView = qnsview_cast(notification.object)) + cocoaWindows += qnsView.platformWindow; } else { qCWarning(lcQpaCocoaWindow) << "Unhandled notifcation" << notification.name << "for" << notification.object; return; } - Q_ASSERT(view); - - QCocoaWindow *cocoaWindow = nullptr; - if (QNSView *qnsView = qnsview_cast(view)) - cocoaWindow = qnsView.platformWindow; // FIXME: Could be a foreign window, look up by iterating top level QWindows - if (!cocoaWindow) - return; - - if (!method.invoke(cocoaWindow, Qt::DirectConnection)) { - qCWarning(lcQpaCocoaWindow) << "Failed to invoke NSNotification callback for" - << notification.name << "on" << cocoaWindow; + for (QCocoaWindow *cocoaWindow : cocoaWindows) { + if (!method.invoke(cocoaWindow, Qt::DirectConnection)) { + qCWarning(lcQpaCocoaWindow) << "Failed to invoke NSNotification callback for" + << notification.name << "on" << cocoaWindow; + } } }]; } @@ -844,8 +840,32 @@ void QCocoaWindow::setEmbeddedInForeignView(bool embedded) m_nsWindow = 0; } +// ----------------------- NSView notifications ----------------------- + +void QCocoaWindow::viewDidChangeFrame() +{ + handleGeometryChange(); +} + +/*! + Callback for NSViewGlobalFrameDidChangeNotification. + + Posted whenever an NSView object that has attached surfaces (that is, + NSOpenGLContext objects) moves to a different screen, or other cases + where the NSOpenGLContext object needs to be updated. +*/ +void QCocoaWindow::viewDidChangeGlobalFrame() +{ + [m_view setNeedsDisplay:YES]; +} + // ----------------------- NSWindow notifications ----------------------- +// Note: The following notifications are delivered to every QCocoaWindow +// that is a child of the NSWindow that triggered the notification. Each +// callback should make sure to filter out notifications if they do not +// apply to that QCocoaWindow, e.g. if the window is not a content view. + void QCocoaWindow::windowWillMove() { // Close any open popups on window move @@ -854,6 +874,9 @@ void QCocoaWindow::windowWillMove() void QCocoaWindow::windowDidMove() { + if (!isContentView()) + return; + handleGeometryChange(); // Moving a window might bring it out of maximized state @@ -871,30 +894,19 @@ void QCocoaWindow::windowDidResize() handleWindowStateChanged(); } -void QCocoaWindow::viewDidChangeFrame() -{ - handleGeometryChange(); -} - -/*! - Callback for NSViewGlobalFrameDidChangeNotification. - - Posted whenever an NSView object that has attached surfaces (that is, - NSOpenGLContext objects) moves to a different screen, or other cases - where the NSOpenGLContext object needs to be updated. -*/ -void QCocoaWindow::viewDidChangeGlobalFrame() -{ - [m_view setNeedsDisplay:YES]; -} - void QCocoaWindow::windowDidEndLiveResize() { + if (!isContentView()) + return; + handleWindowStateChanged(); } void QCocoaWindow::windowDidBecomeKey() { + if (!isContentView()) + return; + if (isForeignWindow()) return; @@ -911,6 +923,9 @@ void QCocoaWindow::windowDidBecomeKey() void QCocoaWindow::windowDidResignKey() { + if (!isContentView()) + return; + if (isForeignWindow()) return; @@ -927,16 +942,25 @@ void QCocoaWindow::windowDidResignKey() void QCocoaWindow::windowDidMiniaturize() { + if (!isContentView()) + return; + handleWindowStateChanged(); } void QCocoaWindow::windowDidDeminiaturize() { + if (!isContentView()) + return; + handleWindowStateChanged(); } void QCocoaWindow::windowWillEnterFullScreen() { + if (!isContentView()) + return; + // The NSWindow needs to be resizable, otherwise we'll end up with // the normal window geometry, centered in the middle of the screen // on a black background. The styleMask will be reset below. @@ -945,6 +969,9 @@ void QCocoaWindow::windowWillEnterFullScreen() void QCocoaWindow::windowDidEnterFullScreen() { + if (!isContentView()) + return; + Q_ASSERT_X(m_view.window.qt_fullScreen, "QCocoaWindow", "FullScreen category processes window notifications first"); @@ -956,6 +983,9 @@ void QCocoaWindow::windowDidEnterFullScreen() void QCocoaWindow::windowWillExitFullScreen() { + if (!isContentView()) + return; + // The NSWindow needs to be resizable, otherwise we'll end up with // a weird zoom animation. The styleMask will be reset below. m_view.window.styleMask |= NSResizableWindowMask; @@ -963,6 +993,9 @@ void QCocoaWindow::windowWillExitFullScreen() void QCocoaWindow::windowDidExitFullScreen() { + if (!isContentView()) + return; + Q_ASSERT_X(!m_view.window.qt_fullScreen, "QCocoaWindow", "FullScreen category processes window notifications first"); @@ -981,14 +1014,14 @@ void QCocoaWindow::windowDidExitFullScreen() } } -void QCocoaWindow::windowDidOrderOffScreen() +void QCocoaWindow::windowDidOrderOnScreen() { - handleExposeEvent(QRegion()); + [m_view setNeedsDisplay:YES]; } -void QCocoaWindow::windowDidOrderOnScreen() +void QCocoaWindow::windowDidOrderOffScreen() { - [m_view setNeedsDisplay:YES]; + handleExposeEvent(QRegion()); } void QCocoaWindow::windowDidChangeOcclusionState() @@ -1422,15 +1455,15 @@ QRect QCocoaWindow::nativeWindowGeometry() const */ void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState) { + if (!isContentView()) + return; + const Qt::WindowState currentState = windowState(); const Qt::WindowState newState = QWindowPrivate::effectiveState(requestedState); if (newState == currentState) return; - if (!isContentView()) - return; - const NSSize contentSize = m_view.frame.size; if (contentSize.width <= 0 || contentSize.height <= 0) { // If content view width or height is 0 then the window animations will crash so -- cgit v1.2.3 From eb2e984da11d642f191e28456042e6b38ce56647 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 28 Sep 2017 13:44:34 +0200 Subject: macOS: Apply window file path when creating new NSWindow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise QWindow::setFilePath() before create() would have no effect. Change-Id: Ia2171054aa13e21316d525193d330efaf4653dbf Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 1 + 1 file changed, 1 insertion(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index a88ec2b0db..217bfb3602 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1292,6 +1292,7 @@ void QCocoaWindow::recreateWindowIfNeeded() propagateSizeHints(); setWindowFlags(window()->flags()); setWindowTitle(window()->title()); + setWindowFilePath(window()->filePath()); setWindowState(window()->windowState()); } else { // Child windows have no NSWindow, link the NSViews instead. -- cgit v1.2.3 From cbbf843e96de3067e4cb7c0a7b4e59a6c27b10f7 Mon Sep 17 00:00:00 2001 From: Anders Hafreager Date: Thu, 28 Sep 2017 09:11:20 +0200 Subject: macOS: Bail out early when handling shortcut event results in closing window MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When Cmd+W is used to close a window, check if m_platformWindow is still valid before accessing window property. Task-number: QTBUG-63389 Change-Id: I9abda19b8482e7a1fd07b07d8981b6a768e96c2e Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qnsview.mm | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 9207feb5fd..ec9d25fff9 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1559,6 +1559,10 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) if (m_composingText.isEmpty()) { m_sendKeyEvent = !QWindowSystemInterface::handleShortcutEvent(window, timestamp, keyCode, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], 1); + + // Handling a shortcut may result in closing the window + if (!m_platformWindow) + return true; } QObject *fo = m_platformWindow->window()->focusObject(); -- cgit v1.2.3 From 8ea5c401094b78c40c21811c9514462797218ae2 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 26 Sep 2017 13:27:55 -0700 Subject: QWindowsMouseHandler: Add documentation link for bitmask magic Change-Id: I743aef0e15ef42347c5222d0e50577b006483cc4 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/plugins') diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index d21581ba8a..0cabb66bca 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -233,6 +233,7 @@ bool QWindowsMouseHandler::translateMouseEvent(QWindow *window, HWND hwnd, // Check for events synthesized from touch. Lower 7 bits are touch/pen index, bit 8 indicates touch. // However, when tablet support is active, extraInfo is a packet serial number. This is not a problem // since we do not want to ignore mouse events coming from a tablet. + // See https://msdn.microsoft.com/en-us/library/windows/desktop/ms703320.aspx const quint64 extraInfo = quint64(GetMessageExtraInfo()); if ((extraInfo & signatureMask) == miWpSignature) { if (extraInfo & 0x80) { // Bit 7 indicates touch event, else tablet pen. -- cgit v1.2.3 From 7fd3cc3980a25bfbc9c0aca935c2afa90230374a Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Fri, 22 Sep 2017 11:20:54 -0700 Subject: Clean up OS version checks for Apple platforms Convert QSysInfo/QOperatingSystemVersion to __builtin_available where required or possible, or to QOperatingSystemVersion where __builtin_available cannot be used and is not needed (such as negated conditions, which are not supported by that construct). Change-Id: I83c0e7e777605b99ff4d24598bfcccf22126fdda Reviewed-by: Thiago Macieira --- src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm | 2 +- src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm | 2 +- src/plugins/platforms/cocoa/qcocoaintegration.mm | 2 +- src/plugins/platforms/cocoa/qnswindow.mm | 2 +- src/plugins/platforms/ios/qiosintegration.mm | 2 +- src/plugins/platforms/ios/qiostextresponder.mm | 2 +- src/plugins/platforms/ios/quiview.mm | 3 +-- 7 files changed, 7 insertions(+), 8 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 35ac7182af..5392804d62 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -284,7 +284,7 @@ QT_END_NAMESPACE inLaunch = false; if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) { - if (QSysInfo::macVersion() >= QSysInfo::MV_10_12) { + if (__builtin_available(macOS 10.12, *)) { // Move the application window to front to avoid launching behind the terminal. // Ignoring other apps is necessary (we must ignore the terminal), but makes // Qt apps play slightly less nice with other apps when lanching from Finder diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index 9a00eb89b7..fa123550ef 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -163,7 +163,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSOpenSavePanelDelegate); [mSavePanel setDelegate:self]; #if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_11) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::OSXElCapitan) + if (__builtin_available(macOS 10.11, *)) mOpenPanel.accessoryViewDisclosed = YES; #endif diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 7b1e689388..00056f90b9 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -363,7 +363,7 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) // Move the application window to front to make it take focus, also when launching // from the terminal. On 10.12+ this call has been moved to applicationDidFinishLauching // to work around issues with loss of focus at startup. - if (QSysInfo::macVersion() < QSysInfo::MV_10_12) { + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSSierra) { // Ignoring other apps is necessary (we must ignore the terminal), but makes // Qt apps play slightly less nice with other apps when lanching from Finder // (See the activateIgnoringOtherApps docs.) diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm index 513c7f22b5..799704a407 100644 --- a/src/plugins/platforms/cocoa/qnswindow.mm +++ b/src/plugins/platforms/cocoa/qnswindow.mm @@ -232,7 +232,7 @@ static bool isMouseEvent(NSEvent *ev) NSApplication *application = [NSApplication sharedApplication]; #if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra) { + if (__builtin_available(macOS 10.12, *)) { // Unfortunately there's no NSWindowListOrderedBackToFront, // so we have to manually reverse the order using an array. NSMutableArray *windows = [[[NSMutableArray alloc] init] autorelease]; diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index 482f996943..5f114d4762 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -117,7 +117,7 @@ QIOSIntegration::QIOSIntegration() m_touchDevice = new QTouchDevice; m_touchDevice->setType(QTouchDevice::TouchScreen); QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition; - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)) { + if (__builtin_available(iOS 9, *)) { if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) touchCapabilities |= QTouchDevice::Pressure; } diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm index 84946a5c0f..7d48a012dd 100644 --- a/src/plugins/platforms/ios/qiostextresponder.mm +++ b/src/plugins/platforms/ios/qiostextresponder.mm @@ -238,7 +238,7 @@ self.inputAccessoryView = [[[WrapperView alloc] initWithView:accessoryView] autorelease]; #ifndef Q_OS_TVOS - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_9_0) { + if (__builtin_available(iOS 9, *)) { if (platformData.value(kImePlatformDataHideShortcutsBar).toBool()) { // According to the docs, leadingBarButtonGroups/trailingBarButtonGroups should be set to nil to hide the shortcuts bar. // However, starting with iOS 10, the API has been surrounded with NS_ASSUME_NONNULL, which contradicts this and causes diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 5ead4d0bc3..1507ff37f7 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -48,7 +48,6 @@ #include "qiosmenu.h" #endif -#include #include #include #include @@ -294,7 +293,7 @@ QTouchDevice *touchDevice = QIOSIntegration::instance()->touchDevice(); QTouchDevice::Capabilities touchCapabilities = touchDevice->capabilities(); - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 9)) { + if (__builtin_available(iOS 9, *)) { if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) touchCapabilities |= QTouchDevice::Pressure; else -- cgit v1.2.3 From bccbb52b7a96b3cba4dc5c9977792ed0223d5a83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 28 Sep 2017 15:46:45 +0200 Subject: macOS: Tighten up window icon and represented filename handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Window icons on macOS are tied to document windows, and should not show up unless a represented filename has also been set according to the HIG. We follow this, and no longer create a document button based on the window title if one did no exists. We also fall back to using the filename of the file if a title has not been set, including being able to restore this default title after setting a custom title. The icon is no longer reset to nil after setting a QIcon(), which would remove the icon completely, but instead we restore the default behavior of showing the default filetype icon of the file. Finally, the two callbacks in QNSWindowDelegate dealing with the document icon/title popups and drags have been taught to look for spaces in the represented filename. This allows clients who really want the old behavior of setting an icon without caring about the filename to set the filename to a single space character, which will prevent the dropdowna and drag from occurring. The reason for not tying this behavior to the existence of the file in the filesystem is that being able to represent a file that is yet to be saved is a valid usecase. Task-number: QTBUG-63338 Change-Id: I7d4377c6358226fb6058f8c2b3c28588eec77ce5 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.h | 2 -- src/plugins/platforms/cocoa/qcocoawindow.mm | 37 ++++++++++++++---------- src/plugins/platforms/cocoa/qnswindowdelegate.mm | 12 ++++++-- 3 files changed, 32 insertions(+), 19 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index a93a391358..3230c32133 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -285,8 +285,6 @@ public: // for QNSView }; QHash m_contentBorderAreas; // identifer -> uppper/lower QHash m_enabledContentBorderAreas; // identifer -> enabled state (true/false) - - bool m_hasWindowFilePath; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 217bfb3602..8f5b419f2a 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -157,7 +157,6 @@ QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle) , m_drawContentBorderGradient(false) , m_topContentBorderThickness(0) , m_bottomContentBorderThickness(0) - , m_hasWindowFilePath(false) { qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::QCocoaWindow" << window(); @@ -594,6 +593,11 @@ void QCocoaWindow::setWindowTitle(const QString &title) QMacAutoReleasePool pool; m_view.window.title = title.toNSString(); + + if (title.isEmpty() && !window()->filePath().isEmpty()) { + // Clearing the title should restore the default filename + setWindowFilePath(window()->filePath()); + } } void QCocoaWindow::setWindowFilePath(const QString &filePath) @@ -602,9 +606,14 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath) return; QMacAutoReleasePool pool; - QFileInfo fi(filePath); - [m_view.window setRepresentedFilename:fi.exists() ? filePath.toNSString() : @""]; - m_hasWindowFilePath = fi.exists(); + + if (window()->title().isNull()) + [m_view.window setTitleWithRepresentedFilename:filePath.toNSString()]; + else + m_view.window.representedFilename = filePath.toNSString(); + + // Changing the file path may affect icon visibility + setWindowIcon(window()->icon()); } void QCocoaWindow::setWindowIcon(const QIcon &icon) @@ -612,23 +621,21 @@ void QCocoaWindow::setWindowIcon(const QIcon &icon) if (!isContentView()) return; - QMacAutoReleasePool pool; - NSButton *iconButton = [m_view.window standardWindowButton:NSWindowDocumentIconButton]; - if (iconButton == nil) { - if (icon.isNull()) - return; - NSString *title = window()->title().toNSString(); - [m_view.window setRepresentedURL:[NSURL fileURLWithPath:title]]; - iconButton = [m_view.window standardWindowButton:NSWindowDocumentIconButton]; + if (!iconButton) { + // Window icons are only supported on macOS in combination with a document filePath + return; } + + QMacAutoReleasePool pool; + if (icon.isNull()) { - [iconButton setImage:nil]; + NSWorkspace *workspace = [NSWorkspace sharedWorkspace]; + [iconButton setImage:[workspace iconForFile:m_view.window.representedFilename]]; } else { QPixmap pixmap = icon.pixmap(QSize(22, 22)); NSImage *image = static_cast(qt_mac_create_nsimage(pixmap)); - [iconButton setImage:image]; - [image release]; + [iconButton setImage:[image autorelease]]; } } diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm index 1224d138d9..cdecd86dfb 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm @@ -44,6 +44,8 @@ #include #include +static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*")); + @implementation QNSWindowDelegate - (id)initWithQCocoaWindow:(QCocoaWindow *)cocoaWindow @@ -98,7 +100,10 @@ { Q_UNUSED(window); Q_UNUSED(menu); - return m_cocoaWindow && m_cocoaWindow->m_hasWindowFilePath; + + // Only pop up document path if the filename is non-empty. We allow whitespace, to + // allow faking a window icon by setting the file path to a single space character. + return !whitespaceRegex.exactMatch(m_cocoaWindow->window()->filePath()); } - (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard @@ -107,6 +112,9 @@ Q_UNUSED(event); Q_UNUSED(dragImageLocation); Q_UNUSED(pasteboard); - return m_cocoaWindow && m_cocoaWindow->m_hasWindowFilePath; + + // Only allow drag if the filename is non-empty. We allow whitespace, to + // allow faking a window icon by setting the file path to a single space. + return !whitespaceRegex.exactMatch(m_cocoaWindow->window()->filePath()); } @end -- cgit v1.2.3 From 3e2de481617aabb51dd8d635fd1d8d363610ed3f Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Sat, 9 Sep 2017 01:31:27 +0200 Subject: OCI: Clear the cache in the result for a forward only query When the query is forward-only then nextIndex() is always 0, therefore the cache values need to be cleared beforehand so that they are not reused when the next row is retrieved. Task-number: QTBUG-57765 Change-Id: I49e8427b24ec2d932e5b387699ac7f3496e9a48c Reviewed-by: Konstantin Ritt Reviewed-by: Edward Welbourne --- src/plugins/sqldrivers/oci/qsql_oci.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/plugins') diff --git a/src/plugins/sqldrivers/oci/qsql_oci.cpp b/src/plugins/sqldrivers/oci/qsql_oci.cpp index 32d3681a17..a4793351de 100644 --- a/src/plugins/sqldrivers/oci/qsql_oci.cpp +++ b/src/plugins/sqldrivers/oci/qsql_oci.cpp @@ -206,6 +206,7 @@ protected: QVariant lastInsertId() const Q_DECL_OVERRIDE; bool execBatch(bool arrayBind = false) Q_DECL_OVERRIDE; void virtual_hook(int id, void *data) Q_DECL_OVERRIDE; + bool fetchNext() override; }; class QOCIResultPrivate: public QSqlCachedResultPrivate @@ -2097,6 +2098,14 @@ void QOCIResult::virtual_hook(int id, void *data) QSqlCachedResult::virtual_hook(id, data); } +bool QOCIResult::fetchNext() +{ + Q_D(QOCIResult); + if (isForwardOnly()) + d->cache.clear(); + return QSqlCachedResult::fetchNext(); +} + //////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 475243a746461b44cd26c30785b59cfd8fe79aaf Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 1 Sep 2017 15:06:13 -0700 Subject: QMacStyle: Refactor QMacStylePrivate::cocoaControl() That switch following the if looked a bit corny. Also made cocoaCells hash mutable to get rid of the const_cast(this) in QMSP::cocoaCell(). Change-Id: I4facec827409314cf1214152c19efb9688715eb2 Reviewed-by: Jake Petroules --- src/plugins/styles/mac/qmacstyle_mac.mm | 106 ++++++++++++++--------------- src/plugins/styles/mac/qmacstyle_mac_p_p.h | 4 +- 2 files changed, 55 insertions(+), 55 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 05585ba07c..271a2d43e5 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -1922,85 +1922,85 @@ static QCocoaWidget cocoaWidgetFromHIThemeButtonKind(ThemeButtonKind kind) return w; } +static NSButton *makeButton(NSButtonType type, NSBezelStyle style) +{ + NSButton *b = [[NSButton alloc] init]; + b.title = @""; + b.buttonType = type; + b.bezelStyle = style; + return b; +} + NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const { - NSView *bv = cocoaControls[widget]; - if (!bv) { + NSView *bv = cocoaControls.value(widget, nil); - if (widget.first == QCocoaPopupButton - || widget.first == QCocoaPullDownButton) - bv = [[NSPopUpButton alloc] init]; - else if (widget.first == QCocoaComboBox) + if (!bv) { + switch (widget.first) { + case QCocoaCheckBox: + bv = makeButton(NSSwitchButton, NSRegularSquareBezelStyle); + break; + case QCocoaDisclosureButton: + bv = makeButton(NSOnOffButton, NSDisclosureBezelStyle); + break; + case QCocoaPopupButton: + case QCocoaPullDownButton: { + NSPopUpButton *bc = [[NSPopUpButton alloc] init]; + bc.title = @""; + if (widget.first == QCocoaPullDownButton) + bc.pullsDown = YES; + bv = bc; + break; + } + case QCocoaPushButton: + bv = makeButton(NSMomentaryLightButton, NSRoundedBezelStyle); + break; + case QCocoaRadioButton: + bv = makeButton(NSRadioButton, NSRegularSquareBezelStyle); + break; + case QCocoaComboBox: bv = [[NSComboBox alloc] init]; - else if (widget.first == QCocoaProgressIndicator) + break; + case QCocoaProgressIndicator: bv = [[NSProgressIndicator alloc] init]; - else if (widget.first == QCocoaIndeterminateProgressIndicator) + break; + case QCocoaIndeterminateProgressIndicator: bv = [[QIndeterminateProgressIndicator alloc] init]; - else if (widget.first == QCocoaHorizontalScroller) + break; + case QCocoaHorizontalScroller: bv = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]; - else if (widget.first == QCocoaVerticalScroller) + break; + case QCocoaVerticalScroller: // Cocoa sets the orientation from the view's frame // at construction time, and it cannot be changed later. bv = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)]; - else if (widget.first == QCocoaHorizontalSlider) + break; + case QCocoaHorizontalSlider: bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]; - else if (widget.first == QCocoaVerticalSlider) + break; + case 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, 20, 200)]; - else - bv = [[NSButton alloc] init]; - - switch (widget.first) { - case QCocoaDisclosureButton: { - NSButton *bc = (NSButton *)bv; - bc.buttonType = NSOnOffButton; - bc.bezelStyle = NSDisclosureBezelStyle; - break; - } - case QCocoaCheckBox: { - NSButton *bc = (NSButton *)bv; - bc.buttonType = NSSwitchButton; - break; - } - case QCocoaRadioButton: { - NSButton *bc = (NSButton *)bv; - bc.buttonType = NSRadioButton; break; - } - case QCocoaPushButton: { - NSButton *bc = (NSButton *)bv; - bc.buttonType = NSMomentaryLightButton; - bc.bezelStyle = NSRoundedBezelStyle; - break; - } - case QCocoaPullDownButton: { - NSPopUpButton *bc = (NSPopUpButton *)bv; - bc.pullsDown = YES; - break; - } default: break; } - if ([bv isKindOfClass:[NSButton class]]) { - NSButton *bc = (NSButton *)bv; - bc.title = @""; - } - if ([bv isKindOfClass:[NSControl class]]) { - NSCell *bcell = [(NSControl *)bv cell]; + auto *ctrl = static_cast(bv); switch (widget.second) { case QStyleHelper::SizeSmall: - bcell.controlSize = NSSmallControlSize; + ctrl.controlSize = NSSmallControlSize; break; case QStyleHelper::SizeMini: - bcell.controlSize = NSMiniControlSize; + ctrl.controlSize = NSMiniControlSize; break; default: break; } - } else if ([bv isKindOfClass:[NSProgressIndicator class]]) { + } else if (widget.first == QCocoaProgressIndicator || + widget.first == QCocoaIndeterminateProgressIndicator) { auto *pi = static_cast(bv); pi.indeterminate = (widget.first == QCocoaIndeterminateProgressIndicator); switch (widget.second) { @@ -2015,7 +2015,7 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const } } - const_cast(this)->cocoaControls.insert(widget, bv); + cocoaControls.insert(widget, bv); } return bv; @@ -2051,7 +2051,7 @@ NSCell *QMacStylePrivate::cocoaCell(QCocoaWidget widget) const break; } - const_cast(this)->cocoaCells.insert(widget, cell); + cocoaCells.insert(widget, cell); } return cell; diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index 399edd82d4..e65c78a61a 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -283,8 +283,8 @@ public: mutable QPointer focusWidget; QT_MANGLE_NAMESPACE(NotificationReceiver) *receiver; NSView *backingStoreNSView; - QHash cocoaControls; - QHash cocoaCells; + mutable QHash cocoaControls; + mutable QHash cocoaCells; QFont smallSystemFont; QFont miniSystemFont; -- cgit v1.2.3 From d47a467ca6d2457f7ae5c9f53857596dd4455974 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 5 Sep 2017 16:27:36 -0700 Subject: QMacStyle: De-HITheme QGroupBox NSBox is good enough for this and pixel equivalent with the previous HITheme calls. Change-Id: I32b2a1cc8a9cd2a6ef17d1e01032540344808ebc Reviewed-by: Jake Petroules --- src/plugins/styles/mac/qmacstyle_mac.mm | 29 +++++++++++++++++------------ src/plugins/styles/mac/qmacstyle_mac_p_p.h | 1 + 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 271a2d43e5..281f5affed 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -1937,6 +1937,15 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const if (!bv) { switch (widget.first) { + case QCocoaBox: { + NSBox *bc = [[NSBox alloc] init]; + bc.title = @""; + bc.titlePosition = NSNoTitle; + bc.boxType = NSBoxPrimary; + bc.borderType = NSBezelBorder; + bv = bc; + break; + } case QCocoaCheckBox: bv = makeButton(NSSwitchButton, NSRegularSquareBezelStyle); break; @@ -2089,7 +2098,7 @@ void QMacStylePrivate::drawNSViewInRect(QCocoaWidget widget, NSView *view, const CGContextTranslateCTM(ctx, offset.x(), offset.y()); - const CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height()); + const CGRect rect = CGRectMake(qtRect.x(), qtRect.y(), qtRect.width(), qtRect.height()); [backingStoreNSView addSubview:view]; view.frame = rect; @@ -3257,17 +3266,13 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai if (groupBox->features & QStyleOptionFrame::Flat) { QCommonStyle::drawPrimitive(pe, groupBox, p, w); } else { - HIThemeGroupBoxDrawInfo gdi; - gdi.version = qt_mac_hitheme_version; - gdi.state = tds; -#if QT_CONFIG(groupbox) - if (w && qobject_cast(w->parentWidget())) - gdi.kind = kHIThemeGroupBoxKindSecondary; - else -#endif - gdi.kind = kHIThemeGroupBoxKindPrimary; - CGRect cgRect = opt->rect.toCGRect(); - HIThemeDrawGroupBox(&cgRect, &gdi, cg, kHIThemeOrientationNormal); + const auto cw = QCocoaWidget(QCocoaBox, QStyleHelper::SizeDefault); + auto *box = static_cast(d->cocoaControl(cw)); + d->drawNSViewInRect(cw, box, groupBox->rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) { + CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height); + CGContextScaleCTM(ctx, 1, -1); + [box drawRect:rect]; + }); } } break; diff --git a/src/plugins/styles/mac/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h index e65c78a61a..528edfcda1 100644 --- a/src/plugins/styles/mac/qmacstyle_mac_p_p.h +++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h @@ -168,6 +168,7 @@ QT_BEGIN_NAMESPACE #define CT2(c1, c2) ((uint(c1) << 16) | uint(c2)) enum QCocoaWidgetKind { + QCocoaBox, // QGroupBox QCocoaCheckBox, QCocoaComboBox, // Editable QComboBox QCocoaDisclosureButton, // Disclosure triangle, like in QTreeView -- cgit v1.2.3 From b8947e9194f0f88f464448ac51f6a05113d36a33 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 30 Aug 2017 11:53:59 +0700 Subject: QMacStyle: Remove HITheme calls for QSizeGrip That's no longer a thing on macOS. We still keep it around for QMdiSubWindow, but we should support 4-edge resizing there as do native windows. In practice, because of WA_MacOpaqueSizeGrip, we were already rendering the size grip manually instead of relying on HITheme. Change-Id: If613a14f03dc650b457688f3f2f57631b5fb30a3 Reviewed-by: Jake Petroules --- src/plugins/styles/mac/qmacstyle_mac.mm | 77 ++++++++++++++------------------- 1 file changed, 32 insertions(+), 45 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 281f5affed..d9e622c28a 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -928,24 +928,15 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg break; } case QStyle::CT_SizeGrip: + // Not HIG kosher: mimic what we were doing earlier until we support 4-edge resizing in MDI subwindows if (sz == QStyleHelper::SizeLarge || sz == QStyleHelper::SizeSmall) { - CGRect r; - CGPoint p = { 0, 0 }; - HIThemeGrowBoxDrawInfo gbi; - gbi.version = 0; - gbi.state = kThemeStateActive; - gbi.kind = kHIThemeGrowBoxKindNormal; - gbi.direction = QApplication::isRightToLeft() ? kThemeGrowLeft | kThemeGrowDown - : kThemeGrowRight | kThemeGrowDown; - gbi.size = sz == QStyleHelper::SizeSmall ? kHIThemeGrowBoxSizeSmall : kHIThemeGrowBoxSizeNormal; - if (HIThemeGetGrowBoxBounds(&p, &gbi, &r) == noErr) { - int width = 0; + int s = sz == QStyleHelper::SizeSmall ? 16 : 22; // large: pixel measured from HITheme, small: from my hat + int width = 0; #if QT_CONFIG(mdiarea) if (widg && qobject_cast(widg->parentWidget())) - width = r.size.width; + width = s; #endif - ret = QSize(width, r.size.height); - } + ret = QSize(width, s); } break; case QStyle::CT_ComboBox: @@ -4510,39 +4501,35 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter } break; case CE_SizeGrip: { - if (w && w->testAttribute(Qt::WA_MacOpaqueSizeGrip)) { - HIThemeGrowBoxDrawInfo gdi; - gdi.version = qt_mac_hitheme_version; - gdi.state = tds; - gdi.kind = kHIThemeGrowBoxKindNormal; - gdi.direction = kThemeGrowRight | kThemeGrowDown; - gdi.size = kHIThemeGrowBoxSizeNormal; - CGPoint pt = CGPointMake(opt->rect.x(), opt->rect.y()); - HIThemeDrawGrowBox(&pt, &gdi, cg, kHIThemeOrientationNormal); - } else { - // It isn't possible to draw a transparent size grip with the - // native API, so we do it ourselves here. - QPen lineColor = QColor(82, 82, 82, 192); - lineColor.setWidth(1); - p->save(); - p->setRenderHint(QPainter::Antialiasing); - p->setPen(lineColor); - const Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : qApp->layoutDirection(); - const int NumLines = 3; - for (int l = 0; l < NumLines; ++l) { - const int offset = (l * 4 + 3); - QPoint start, end; - if (layoutDirection == Qt::LeftToRight) { - start = QPoint(opt->rect.width() - offset, opt->rect.height() - 1); - end = QPoint(opt->rect.width() - 1, opt->rect.height() - offset); - } else { - start = QPoint(offset, opt->rect.height() - 1); - end = QPoint(1, opt->rect.height() - offset); - } - p->drawLine(start, end); + // This is not HIG kosher: Fall back to the old stuff until we decide what to do. +#ifndef QT_NO_MDIAREA + if (!w || !qobject_cast(w->parentWidget())) +#endif + break; + + if (w->testAttribute(Qt::WA_MacOpaqueSizeGrip)) + p->fillRect(opt->rect, opt->palette.window()); + + QPen lineColor = QColor(82, 82, 82, 192); + lineColor.setWidth(1); + p->save(); + p->setRenderHint(QPainter::Antialiasing); + p->setPen(lineColor); + const Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : qApp->layoutDirection(); + const int NumLines = 3; + for (int l = 0; l < NumLines; ++l) { + const int offset = (l * 4 + 3); + QPoint start, end; + if (layoutDirection == Qt::LeftToRight) { + start = QPoint(opt->rect.width() - offset, opt->rect.height() - 1); + end = QPoint(opt->rect.width() - 1, opt->rect.height() - offset); + } else { + start = QPoint(offset, opt->rect.height() - 1); + end = QPoint(1, opt->rect.height() - offset); } - p->restore(); + p->drawLine(start, end); } + p->restore(); break; } case CE_Splitter: -- cgit v1.2.3 From 5b4cf7af6a492b6ef5b7c718b346b38ddad4c990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 3 Oct 2017 16:55:39 +0200 Subject: macOS: Prevent backingstore image detach during color space assignment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The call to CGImageCreateCopyWithColorSpace took a naked toCGImage(), which left the resulting CGImageRef without a release, causing the extra ref by toCGImage() to never be derefed, and a subsequent detach of the image data on the next paint event. Wrapping the call in a QCFType solves the problem. The code has also been moved directly into QCocoaBackingStore::flush(), as there is no need to keep the CGImageRef a member. A local autorelease pool has been added to QCocoaBackingStore::flush(), so that the NSImage used for blitting the backingstore is released upon exit of the function, thereby releasing the corresponding CGImageRef. Note that for layered mode, the QImage will still detach, as the view's layer.contents property keeps a reference to the image data until being replaced in a subsequent flush. Task-number: QTBUG-63559 Change-Id: I06b9298f65a84deae7cc2eff617ba75c92ec3b87 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoabackingstore.h | 4 --- src/plugins/platforms/cocoa/qcocoabackingstore.mm | 34 ++++++++--------------- 2 files changed, 11 insertions(+), 27 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index 002e5b40a8..a0bc204013 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -52,16 +52,12 @@ public: QCocoaBackingStore(QWindow *window); ~QCocoaBackingStore(); - void beginPaint(const QRegion &) override; - void endPaint() override; - void flush(QWindow *, const QRegion &, const QPoint &) Q_DECL_OVERRIDE; private: bool windowHasUnifiedToolbar() const; QImage::Format format() const Q_DECL_OVERRIDE; void redrawRoundedBottomCorners(CGRect) const; - QCFType m_cgImage; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm index 1f39d787be..57a03905ab 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm @@ -48,7 +48,6 @@ Q_LOGGING_CATEGORY(lcCocoaBackingStore, "qt.qpa.cocoa.backingstore"); QCocoaBackingStore::QCocoaBackingStore(QWindow *window) : QRasterBackingStore(window) - , m_cgImage(nullptr) { } @@ -70,26 +69,6 @@ QImage::Format QCocoaBackingStore::format() const return QRasterBackingStore::format(); } -void QCocoaBackingStore::beginPaint(const QRegion ®ion) -{ - m_cgImage = nullptr; - QRasterBackingStore::beginPaint(region); -} - -void QCocoaBackingStore::endPaint() -{ - QRasterBackingStore::endPaint(); - - // Prevent potentially costly color conversion by assiging the display - // color space to the backingstore image. - NSView *view = static_cast(window()->handle())->view(); - CGColorSpaceRef displayColorSpace = view.window.screen.colorSpace.CGColorSpace; - QCFType displayColorSpaceImage = - CGImageCreateCopyWithColorSpace(m_image.toCGImage(), displayColorSpace); - - m_cgImage = displayColorSpaceImage; -} - #if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12) static const NSCompositingOperation NSCompositingOperationCopy = NSCompositeCopy; static const NSCompositingOperation NSCompositingOperationSourceOver = NSCompositeSourceOver; @@ -111,6 +90,9 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo if (m_image.isNull()) return; + // Use local pool so that any stale image references are cleaned up after flushing + QMacAutoReleasePool pool; + const QWindow *topLevelWindow = this->window(); Q_ASSERT(topLevelWindow->handle() && window->handle()); @@ -128,6 +110,12 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo qCDebug(lcCocoaBackingStore) << "Flushing" << region << "of" << view << qPrintable(targetViewDescription); } + // Prevent potentially costly color conversion by assigning the display color space + // to the backingstore image. This does not copy the underlying image data. + CGColorSpaceRef displayColorSpace = view.window.screen.colorSpace.CGColorSpace; + QCFType cgImage = CGImageCreateCopyWithColorSpace( + QCFType(m_image.toCGImage()), displayColorSpace); + if (view.layer) { // In layer-backed mode, locking focus on a view does not give the right // view transformation, and doesn't give us a graphics context to render @@ -137,7 +125,7 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo // we then directly set the layer's backingstore (content) to our backingstore, // masked to the part of the subview that is relevant. // FIXME: Figure out if there's a way to do partial updates - view.layer.contents = (__bridge id)static_cast(m_cgImage); + view.layer.contents = (__bridge id)static_cast(cgImage); if (view != topLevelView) { view.layer.contentsRect = CGRectApplyAffineTransform( [view convertRect:view.bounds toView:topLevelView], @@ -196,7 +184,7 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo "Focusing the view should give us a current graphics context"); // Create temporary image to use for blitting, without copying image data - NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:m_cgImage size:NSZeroSize] autorelease]; + NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize] autorelease]; QRegion clippedRegion = region; for (QWindow *w = window; w; w = w->parent()) { -- cgit v1.2.3 From 8e70241dccaf5a9e5c79c8d6da5665b881c5914d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 3 Oct 2017 19:24:50 +0200 Subject: Let QPlatformBackingStore handle its own QOpenGLContext MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The resources allocated by QPlatformBackingStore are owned by the class, and should be allocated in a context the class also owns. This removes the asymmetry of having to pass in a context to composeAndFlush, while having to make the same context current before destroying the platform backingstore. The context owned by QPlatformBackingStore is shared with the associated window though a new QWindowPrivate::shareContext() API. The result is that on e.g. iOS, the backingstore does not need to tie the resource allocation of QPlatformBackingStore to the global share context, but can instead tie them to the per-window context, and hence clean them up after each window is closed. Task-number: QTBUG-56653 Change-Id: Ic1bcae50dafeeafaa8d16a7febd83b840ec6367a Reviewed-by: Morten Johan Sørvig Reviewed-by: Laszlo Agocs --- src/plugins/platforms/ios/qiosbackingstore.h | 3 --- src/plugins/platforms/ios/qiosbackingstore.mm | 15 +-------------- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 4 ++-- src/plugins/platforms/xcb/qxcbbackingstore.h | 2 +- 4 files changed, 4 insertions(+), 20 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosbackingstore.h b/src/plugins/platforms/ios/qiosbackingstore.h index 3954347471..e6b890251a 100644 --- a/src/plugins/platforms/ios/qiosbackingstore.h +++ b/src/plugins/platforms/ios/qiosbackingstore.h @@ -55,9 +55,6 @@ public: ~QIOSBackingStore(); void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; - -private: - QOpenGLContext *m_context; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/ios/qiosbackingstore.mm b/src/plugins/platforms/ios/qiosbackingstore.mm index 74229684e3..db4dd81b2e 100644 --- a/src/plugins/platforms/ios/qiosbackingstore.mm +++ b/src/plugins/platforms/ios/qiosbackingstore.mm @@ -55,7 +55,6 @@ QT_BEGIN_NAMESPACE */ QIOSBackingStore::QIOSBackingStore(QWindow *window) : QRasterBackingStore(window) - , m_context(new QOpenGLContext) { // We use the surface both for raster operations and for GL drawing (when // we blit the raster image), so the type needs to cover both use cases. @@ -64,22 +63,10 @@ QIOSBackingStore::QIOSBackingStore(QWindow *window) Q_ASSERT_X(window->surfaceType() != QSurface::OpenGLSurface, "QIOSBackingStore", "QBackingStore on iOS can only be used with raster-enabled surfaces."); - - m_context->setFormat(window->requestedFormat()); - m_context->setScreen(window->screen()); - Q_ASSERT(QOpenGLContext::globalShareContext()); - m_context->setShareContext(QOpenGLContext::globalShareContext()); - m_context->create(); } QIOSBackingStore::~QIOSBackingStore() { - // We're using composeAndFlush from QPlatformBackingStore, which - // need to clean up any textures in its destructor, so make the - // context current and keep it alive until QPlatformBackingStore - // has cleaned up everything. - m_context->makeCurrent(window()); - m_context->deleteLater(); } void QIOSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) @@ -98,7 +85,7 @@ void QIOSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin } static QPlatformTextureList emptyTextureList; - composeAndFlush(window, region, offset, &emptyTextureList, m_context, false); + composeAndFlush(window, region, offset, &emptyTextureList, false); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 17927af3e3..420d1ac7c5 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -600,10 +600,10 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin #ifndef QT_NO_OPENGL void QXcbBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, - QPlatformTextureList *textures, QOpenGLContext *context, + QPlatformTextureList *textures, bool translucentBackground) { - QPlatformBackingStore::composeAndFlush(window, region, offset, textures, context, translucentBackground); + QPlatformBackingStore::composeAndFlush(window, region, offset, textures, translucentBackground); QXcbWindow *platformWindow = static_cast(window->handle()); if (platformWindow->needsSync()) { diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h index 94b5994004..2e8fbfb7fa 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.h +++ b/src/plugins/platforms/xcb/qxcbbackingstore.h @@ -61,7 +61,7 @@ public: void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) override; #ifndef QT_NO_OPENGL void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, - QPlatformTextureList *textures, QOpenGLContext *context, + QPlatformTextureList *textures, bool translucentBackground) override; #endif QImage toImage() const override; -- cgit v1.2.3 From 5ff9d6a470dbcf424f2f43206ab6ab6eb91edcc1 Mon Sep 17 00:00:00 2001 From: Oleg Yadrov Date: Mon, 2 Oct 2017 10:27:10 -0400 Subject: QMacStyle: smooth QMenu corners for real It's been for years that QMenu's rounded corners in qmacstyle_mac were done via QWidget::setMask(QRegion). Unfortunately, QRegion mask does not work well with retina displays and also does not support translucency. That's why in this change we explicitly make QMenu's background transparent and then draw a rectangle with rounded corners in QMacStyle::drawPrimitive(PE_PanelMenu). This not only gives much better result than the mask-based approach, but also de-HIThemes QMenu. As a consequence, QComboBoxPrivateContainer doesn't get any mask from QMacStyle anymore. Therefore, when the mask is empty, we need to paint PE_PanelMenu before invoking QFrame's paint event handler. Made-with: Gabriel de Dietrich Change-Id: Ia9236176113f23b86e45507fa6ddf77236084ce3 Reviewed-by: Oleg Yadrov Reviewed-by: Gabriel de Dietrich --- .../platforms/cocoa/qcocoasystemsettings.mm | 1 - src/plugins/styles/mac/qmacstyle_mac.mm | 92 ++++++++++------------ 2 files changed, 41 insertions(+), 52 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm index 91fb6e973d..7c6f879b18 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm @@ -144,7 +144,6 @@ QHash qt_mac_createRolePalettes() } if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette || mac_widget_colors[i].paletteRole == QPlatformTheme::MenuBarPalette) { - pal.setBrush(QPalette::Background, qt_mac_toQColor([NSColor windowBackgroundColor])); pal.setBrush(QPalette::Highlight, qt_mac_toQColor([NSColor selectedMenuItemColor])); qc = qt_mac_toQColor([NSColor labelColor]); pal.setBrush(QPalette::ButtonText, qc); diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index d9e622c28a..b24ecee102 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -663,14 +663,6 @@ HIMutableShapeRef qt_mac_toHIMutableShape(const QRegion ®ion) return shape; } -QRegion qt_mac_fromHIShapeRef(HIShapeRef shape) -{ - QRegion returnRegion; - //returnRegion.detach(); - HIShapeEnumerate(shape, kHIShapeParseFromTopLeft, qt_mac_shape2QRegionHelper, &returnRegion); - return returnRegion; -} - bool qt_macWindowIsTextured(const QWidget *window) { if (QWindow *w = window->windowHandle()) @@ -2291,24 +2283,7 @@ void QMacStyle::polish(QWidget* w) || qobject_cast(w) #endif ) { - w->setWindowOpacity(0.985); - if (!w->testAttribute(Qt::WA_SetPalette)) { - QPixmap px(64, 64); - px.fill(Qt::white); - HIThemeMenuDrawInfo mtinfo; - mtinfo.version = qt_mac_hitheme_version; - mtinfo.menuType = kThemeMenuTypePopUp; - // HIRect rect = CGRectMake(0, 0, px.width(), px.height()); - // ### - //HIThemeDrawMenuBackground(&rect, &mtinfo, QMacCGContext(&px)), - // kHIThemeOrientationNormal); - QPalette pal = w->palette(); - QBrush background(px); - pal.setBrush(QPalette::All, QPalette::Window, background); - pal.setBrush(QPalette::All, QPalette::Button, background); - w->setPalette(pal); - w->setAttribute(Qt::WA_SetPalette, false); - } + w->setAttribute(Qt::WA_TranslucentBackground, true); } #endif @@ -3023,7 +2998,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w ret = Qt::AlignRight; break; case SH_ComboBox_PopupFrameStyle: - ret = QFrame::NoFrame | QFrame::Plain; + ret = QFrame::NoFrame; break; case SH_MessageBox_TextInteractionFlags: ret = Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard; @@ -3057,27 +3032,6 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w case SH_Menu_FadeOutOnHide: ret = true; break; - case SH_Menu_Mask: - if (opt) { - if (QStyleHintReturnMask *mask = qstyleoption_cast(hret)) { - ret = true; - CGRect menuRect = CGRectMake(opt->rect.x(), opt->rect.y() + 4, - opt->rect.width(), opt->rect.height() - 8); - HIThemeMenuDrawInfo mdi; - mdi.version = 0; -#if QT_CONFIG(menu) - if (w && qobject_cast(w->parentWidget())) - mdi.menuType = kThemeMenuTypeHierarchical; - else -#endif - mdi.menuType = kThemeMenuTypePopUp; - QCFType shape; - HIThemeGetMenuBackgroundShape(&menuRect, &mdi, &shape); - - mask->region = qt_mac_fromHIShapeRef(shape); - } - } - break; case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: ret = true; break; @@ -3587,6 +3541,40 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai break; } + case PE_PanelMenu: { + p->save(); + p->fillRect(opt->rect, Qt::transparent); + p->setPen(Qt::transparent); + p->setBrush(opt->palette.window()); + p->setRenderHint(QPainter::Antialiasing, true); + QPainterPath path; + static const qreal CornerPointOffset = 5.5; + static const qreal CornerControlOffset = 2.1; + QRectF r = opt->rect; + // Top-left corner + path.moveTo(r.left(), r.top() + CornerPointOffset); + path.cubicTo(r.left(), r.top() + CornerControlOffset, + r.left() + CornerControlOffset, r.top(), + r.left() + CornerPointOffset, r.top()); + // Top-right corner + path.lineTo(r.right() - CornerPointOffset, r.top()); + path.cubicTo(r.right() - CornerControlOffset, r.top(), + r.right(), r.top() + CornerControlOffset, + r.right(), r.top() + CornerPointOffset); + // Bottom-right corner + path.lineTo(r.right(), r.bottom() - CornerPointOffset); + path.cubicTo(r.right(), r.bottom() - CornerControlOffset, + r.right() - CornerControlOffset, r.bottom(), + r.right() - CornerPointOffset, r.bottom()); + // Bottom-right corner + path.lineTo(r.left() + CornerPointOffset, r.bottom()); + path.cubicTo(r.left() + CornerControlOffset, r.bottom(), + r.left(), r.bottom() - CornerControlOffset, + r.left(), r.bottom() - CornerPointOffset); + path.lineTo(r.left(), r.top() + CornerPointOffset); + p->drawPath(path); + p->restore(); + } break; default: QCommonStyle::drawPrimitive(pe, opt, p, w); @@ -4269,16 +4257,18 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w); d->drawFocusRing(p, opt->rect, hMargin, vMargin); break; } + case CE_MenuEmptyArea: + // Skip: PE_PanelMenu fills in everything + break; case CE_MenuItem: case CE_MenuHMargin: case CE_MenuVMargin: - case CE_MenuEmptyArea: case CE_MenuTearoff: case CE_MenuScroller: if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { const bool active = mi->state & State_Selected; - const QBrush bg = active ? mi->palette.highlight() : mi->palette.background(); - p->fillRect(mi->rect, bg); + if (active) + p->fillRect(mi->rect, mi->palette.highlight()); const QStyleHelper::WidgetSizePolicy widgetSize = d->aquaSizeConstrain(opt, w); -- cgit v1.2.3 From de3f764be835f43e2128ddb1f8d67b859b06e63e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 5 Oct 2017 17:34:17 +0200 Subject: macOS: Split QCocoaScreen out from qcocoaintegration.mm It's confusing to keep it along with an unrelated class. Let's keep it in its own file like for most other platform plugins. Change-Id: I449ee061ff9fd5dc7ef06cadd633414d6b16358f Reviewed-by: Gabriel de Dietrich --- src/plugins/platforms/cocoa/cocoa.pro | 2 + src/plugins/platforms/cocoa/qcocoaintegration.h | 54 +---- src/plugins/platforms/cocoa/qcocoaintegration.mm | 224 +----------------- src/plugins/platforms/cocoa/qcocoascreen.h | 108 +++++++++ src/plugins/platforms/cocoa/qcocoascreen.mm | 278 +++++++++++++++++++++++ src/plugins/platforms/cocoa/qcocoawindow.mm | 1 + 6 files changed, 391 insertions(+), 276 deletions(-) create mode 100644 src/plugins/platforms/cocoa/qcocoascreen.h create mode 100644 src/plugins/platforms/cocoa/qcocoascreen.mm (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 6ac5021ea9..55a9d76b67 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -2,6 +2,7 @@ TARGET = qcocoa OBJECTIVE_SOURCES += main.mm \ qcocoaintegration.mm \ + qcocoascreen.mm \ qcocoatheme.mm \ qcocoabackingstore.mm \ qcocoawindow.mm \ @@ -36,6 +37,7 @@ OBJECTIVE_SOURCES += main.mm \ SOURCES += messages.cpp HEADERS += qcocoaintegration.h \ + qcocoascreen.h \ qcocoatheme.h \ qcocoabackingstore.h \ qcocoawindow.h \ diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index d3f2079042..8745b6a4e3 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -58,59 +58,7 @@ QT_BEGIN_NAMESPACE -class QCocoaScreen : public QPlatformScreen -{ -public: - QCocoaScreen(int screenIndex); - ~QCocoaScreen(); - - // ---------------------------------------------------- - // Virtual methods overridden from QPlatformScreen - QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE; - QRect geometry() const Q_DECL_OVERRIDE { return m_geometry; } - QRect availableGeometry() const Q_DECL_OVERRIDE { return m_availableGeometry; } - int depth() const Q_DECL_OVERRIDE { return m_depth; } - QImage::Format format() const Q_DECL_OVERRIDE { return m_format; } - qreal devicePixelRatio() const Q_DECL_OVERRIDE; - QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_physicalSize; } - QDpi logicalDpi() const Q_DECL_OVERRIDE { return m_logicalDpi; } - qreal refreshRate() const Q_DECL_OVERRIDE { return m_refreshRate; } - QString name() const Q_DECL_OVERRIDE { return m_name; } - QPlatformCursor *cursor() const Q_DECL_OVERRIDE { return m_cursor; } - QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE; - QList virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; } - QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE; - - // ---------------------------------------------------- - // Additional methods - void setVirtualSiblings(const QList &siblings) { m_siblings = siblings; } - NSScreen *nativeScreen() const; - void updateGeometry(); - - QPointF mapToNative(const QPointF &pos) const { return flipCoordinate(pos); } - QRectF mapToNative(const QRectF &rect) const { return flipCoordinate(rect); } - QPointF mapFromNative(const QPointF &pos) const { return flipCoordinate(pos); } - QRectF mapFromNative(const QRectF &rect) const { return flipCoordinate(rect); } - - static QCocoaScreen *primaryScreen(); - -private: - QPointF flipCoordinate(const QPointF &pos) const; - QRectF flipCoordinate(const QRectF &rect) const; - -public: - int m_screenIndex; - QRect m_geometry; - QRect m_availableGeometry; - QDpi m_logicalDpi; - qreal m_refreshRate; - int m_depth; - QString m_name; - QImage::Format m_format; - QSizeF m_physicalSize; - QCocoaCursor *m_cursor; - QList m_siblings; -}; +class QCocoaScreen; class QCocoaIntegration : public QPlatformIntegration { diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 00056f90b9..61eeeaf436 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -51,6 +51,7 @@ #include "qcocoainputcontext.h" #include "qcocoamimetypes.h" #include "qcocoaaccessibility.h" +#include "qcocoascreen.h" #include #include @@ -78,229 +79,6 @@ QT_BEGIN_NAMESPACE class QCoreTextFontEngine; class QFontEngineFT; -QCocoaScreen::QCocoaScreen(int screenIndex) - : QPlatformScreen(), m_screenIndex(screenIndex), m_refreshRate(60.0) -{ - updateGeometry(); - m_cursor = new QCocoaCursor; -} - -QCocoaScreen::~QCocoaScreen() -{ - delete m_cursor; -} - -NSScreen *QCocoaScreen::nativeScreen() const -{ - NSArray *screens = [NSScreen screens]; - - // Stale reference, screen configuration has changed - if (m_screenIndex < 0 || (NSUInteger)m_screenIndex >= [screens count]) - return nil; - - return [screens objectAtIndex:m_screenIndex]; -} - -/*! - Flips the Y coordinate of the point between quadrant I and IV. - - The native coordinate system on macOS uses quadrant I, with origin - in bottom left, and Qt uses quadrant IV, with origin in top left. - - By flippig the Y coordinate, we can map the position between the - two coordinate systems. -*/ -QPointF QCocoaScreen::flipCoordinate(const QPointF &pos) const -{ - return QPointF(pos.x(), m_geometry.height() - pos.y()); -} - -/*! - Flips the Y coordinate of the rectangle between quadrant I and IV. - - The native coordinate system on macOS uses quadrant I, with origin - in bottom left, and Qt uses quadrant IV, with origin in top left. - - By flippig the Y coordinate, we can map the rectangle between the - two coordinate systems. -*/ -QRectF QCocoaScreen::flipCoordinate(const QRectF &rect) const -{ - return QRectF(flipCoordinate(rect.topLeft() + QPoint(0, rect.height())), rect.size()); -} - -void QCocoaScreen::updateGeometry() -{ - NSScreen *nsScreen = nativeScreen(); - if (!nsScreen) - return; - - // At this point the geometry is in native coordinates, but the size - // is correct, which we take advantage of next when we map the native - // coordinates to the Qt coordinate system. - m_geometry = QRectF::fromCGRect(NSRectToCGRect(nsScreen.frame)).toRect(); - m_availableGeometry = QRectF::fromCGRect(NSRectToCGRect(nsScreen.visibleFrame)).toRect(); - - // The reference screen for the geometry is always the primary screen, but since - // we may be in the process of creating and registering the primary screen, we - // must special-case that and assign it direcly. - QCocoaScreen *primaryScreen = (nsScreen == [[NSScreen screens] firstObject]) ? - this : QCocoaScreen::primaryScreen(); - - m_geometry = primaryScreen->mapFromNative(m_geometry).toRect(); - m_availableGeometry = primaryScreen->mapFromNative(m_availableGeometry).toRect(); - - m_format = QImage::Format_RGB32; - m_depth = NSBitsPerPixelFromDepth([nsScreen depth]); - - NSDictionary *devDesc = [nsScreen deviceDescription]; - CGDirectDisplayID dpy = [[devDesc objectForKey:@"NSScreenNumber"] unsignedIntValue]; - CGSize size = CGDisplayScreenSize(dpy); - m_physicalSize = QSizeF(size.width, size.height); - m_logicalDpi.first = 72; - m_logicalDpi.second = 72; - CGDisplayModeRef displayMode = CGDisplayCopyDisplayMode(dpy); - float refresh = CGDisplayModeGetRefreshRate(displayMode); - CGDisplayModeRelease(displayMode); - if (refresh > 0) - m_refreshRate = refresh; - - // Get m_name (brand/model of the monitor) - NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(dpy), kIODisplayOnlyPreferredName); - NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]]; - if ([localizedNames count] > 0) - m_name = QString::fromUtf8([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]); - [deviceInfo release]; - - QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry()); - QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second); - QWindowSystemInterface::handleScreenRefreshRateChange(screen(), m_refreshRate); -} - -qreal QCocoaScreen::devicePixelRatio() const -{ - QMacAutoReleasePool pool; - NSScreen *nsScreen = nativeScreen(); - return qreal(nsScreen ? [nsScreen backingScaleFactor] : 1.0); -} - -QPlatformScreen::SubpixelAntialiasingType QCocoaScreen::subpixelAntialiasingTypeHint() const -{ - QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint(); - if (type == QPlatformScreen::Subpixel_None) { - // Every OSX machine has RGB pixels unless a peculiar or rotated non-Apple screen is attached - type = QPlatformScreen::Subpixel_RGB; - } - return type; -} - -QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const -{ - NSPoint screenPoint = qt_mac_flipPoint(point); - - // Search (hit test) for the top-level window. [NSWidow windowNumberAtPoint: - // belowWindowWithWindowNumber] may return windows that are not interesting - // to Qt. The search iterates until a suitable window or no window is found. - NSInteger topWindowNumber = 0; - QWindow *window = 0; - do { - // Get the top-most window, below any previously rejected window. - topWindowNumber = [NSWindow windowNumberAtPoint:screenPoint - belowWindowWithWindowNumber:topWindowNumber]; - - // Continue the search if the window does not belong to this process. - NSWindow *nsWindow = [NSApp windowWithWindowNumber:topWindowNumber]; - if (nsWindow == 0) - continue; - - // Continue the search if the window does not belong to Qt. - if (![nsWindow conformsToProtocol:@protocol(QNSWindowProtocol)]) - continue; - - id proto = static_cast >(nsWindow); - QCocoaWindow *cocoaWindow = proto.platformWindow; - if (!cocoaWindow) - continue; - window = cocoaWindow->window(); - - // Continue the search if the window is not a top-level window. - if (!window->isTopLevel()) - continue; - - // Stop searching. The current window is the correct window. - break; - } while (topWindowNumber > 0); - - return window; -} - -QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const -{ - // TODO window should be handled - Q_UNUSED(window) - - const int maxDisplays = 128; // 128 displays should be enough for everyone. - CGDirectDisplayID displays[maxDisplays]; - CGDisplayCount displayCount; - CGRect cgRect; - - if (width < 0 || height < 0) { - // get all displays - cgRect = CGRectInfinite; - } else { - cgRect = CGRectMake(x, y, width, height); - } - const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount); - - if (err && displayCount == 0) - return QPixmap(); - - // calculate pixmap size - QSize windowSize(width, height); - if (width < 0 || height < 0) { - QRect windowRect; - for (uint i = 0; i < displayCount; ++i) { - const CGRect cgRect = CGDisplayBounds(displays[i]); - QRect qRect(cgRect.origin.x, cgRect.origin.y, cgRect.size.width, cgRect.size.height); - windowRect = windowRect.united(qRect); - } - if (width < 0) - windowSize.setWidth(windowRect.width()); - if (height < 0) - windowSize.setHeight(windowRect.height()); - } - - QPixmap windowPixmap(windowSize * devicePixelRatio()); - windowPixmap.fill(Qt::transparent); - - for (uint i = 0; i < displayCount; ++i) { - const CGRect bounds = CGDisplayBounds(displays[i]); - int w = (width < 0 ? bounds.size.width : width) * devicePixelRatio(); - int h = (height < 0 ? bounds.size.height : height) * devicePixelRatio(); - QRect displayRect = QRect(x, y, w, h); - displayRect = displayRect.translated(qRound(-bounds.origin.x), qRound(-bounds.origin.y)); - QCFType image = CGDisplayCreateImageForRect(displays[i], - CGRectMake(displayRect.x(), displayRect.y(), displayRect.width(), displayRect.height())); - QPixmap pix(w, h); - pix.fill(Qt::transparent); - CGRect rect = CGRectMake(0, 0, w, h); - QMacCGContext ctx(&pix); - qt_mac_drawCGImage(ctx, &rect, image); - - QPainter painter(&windowPixmap); - painter.drawPixmap(0, 0, pix); - } - return windowPixmap; -} - -/*! - The screen used as a reference for global window geometry -*/ -QCocoaScreen *QCocoaScreen::primaryScreen() -{ - return static_cast(QGuiApplication::primaryScreen()->handle()); -} - static QCocoaIntegration::Options parseOptions(const QStringList ¶mList) { QCocoaIntegration::Options options; diff --git a/src/plugins/platforms/cocoa/qcocoascreen.h b/src/plugins/platforms/cocoa/qcocoascreen.h new file mode 100644 index 0000000000..eb17efa937 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoascreen.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** 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 QCOCOASCREEN_H +#define QCOCOASCREEN_H + +#include + +#include "qcocoacursor.h" + +#include + +QT_BEGIN_NAMESPACE + +class QCocoaScreen : public QPlatformScreen +{ +public: + QCocoaScreen(int screenIndex); + ~QCocoaScreen(); + + // ---------------------------------------------------- + // Virtual methods overridden from QPlatformScreen + QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE; + QRect geometry() const Q_DECL_OVERRIDE { return m_geometry; } + QRect availableGeometry() const Q_DECL_OVERRIDE { return m_availableGeometry; } + int depth() const Q_DECL_OVERRIDE { return m_depth; } + QImage::Format format() const Q_DECL_OVERRIDE { return m_format; } + qreal devicePixelRatio() const Q_DECL_OVERRIDE; + QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_physicalSize; } + QDpi logicalDpi() const Q_DECL_OVERRIDE { return m_logicalDpi; } + qreal refreshRate() const Q_DECL_OVERRIDE { return m_refreshRate; } + QString name() const Q_DECL_OVERRIDE { return m_name; } + QPlatformCursor *cursor() const Q_DECL_OVERRIDE { return m_cursor; } + QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE; + QList virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; } + QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE; + + // ---------------------------------------------------- + // Additional methods + void setVirtualSiblings(const QList &siblings) { m_siblings = siblings; } + NSScreen *nativeScreen() const; + void updateGeometry(); + + QPointF mapToNative(const QPointF &pos) const { return flipCoordinate(pos); } + QRectF mapToNative(const QRectF &rect) const { return flipCoordinate(rect); } + QPointF mapFromNative(const QPointF &pos) const { return flipCoordinate(pos); } + QRectF mapFromNative(const QRectF &rect) const { return flipCoordinate(rect); } + + static QCocoaScreen *primaryScreen(); + +private: + QPointF flipCoordinate(const QPointF &pos) const; + QRectF flipCoordinate(const QRectF &rect) const; + +public: + int m_screenIndex; + QRect m_geometry; + QRect m_availableGeometry; + QDpi m_logicalDpi; + qreal m_refreshRate; + int m_depth; + QString m_name; + QImage::Format m_format; + QSizeF m_physicalSize; + QCocoaCursor *m_cursor; + QList m_siblings; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm new file mode 100644 index 0000000000..13e5220b6a --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoascreen.mm @@ -0,0 +1,278 @@ +/**************************************************************************** +** +** 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 "qcocoascreen.h" + +#include "qcocoawindow.h" +#include "qcocoahelpers.h" + +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +class QCoreTextFontEngine; +class QFontEngineFT; + +QCocoaScreen::QCocoaScreen(int screenIndex) + : QPlatformScreen(), m_screenIndex(screenIndex), m_refreshRate(60.0) +{ + updateGeometry(); + m_cursor = new QCocoaCursor; +} + +QCocoaScreen::~QCocoaScreen() +{ + delete m_cursor; +} + +NSScreen *QCocoaScreen::nativeScreen() const +{ + NSArray *screens = [NSScreen screens]; + + // Stale reference, screen configuration has changed + if (m_screenIndex < 0 || (NSUInteger)m_screenIndex >= [screens count]) + return nil; + + return [screens objectAtIndex:m_screenIndex]; +} + +/*! + Flips the Y coordinate of the point between quadrant I and IV. + + The native coordinate system on macOS uses quadrant I, with origin + in bottom left, and Qt uses quadrant IV, with origin in top left. + + By flippig the Y coordinate, we can map the position between the + two coordinate systems. +*/ +QPointF QCocoaScreen::flipCoordinate(const QPointF &pos) const +{ + return QPointF(pos.x(), m_geometry.height() - pos.y()); +} + +/*! + Flips the Y coordinate of the rectangle between quadrant I and IV. + + The native coordinate system on macOS uses quadrant I, with origin + in bottom left, and Qt uses quadrant IV, with origin in top left. + + By flippig the Y coordinate, we can map the rectangle between the + two coordinate systems. +*/ +QRectF QCocoaScreen::flipCoordinate(const QRectF &rect) const +{ + return QRectF(flipCoordinate(rect.topLeft() + QPoint(0, rect.height())), rect.size()); +} + +void QCocoaScreen::updateGeometry() +{ + NSScreen *nsScreen = nativeScreen(); + if (!nsScreen) + return; + + // At this point the geometry is in native coordinates, but the size + // is correct, which we take advantage of next when we map the native + // coordinates to the Qt coordinate system. + m_geometry = QRectF::fromCGRect(NSRectToCGRect(nsScreen.frame)).toRect(); + m_availableGeometry = QRectF::fromCGRect(NSRectToCGRect(nsScreen.visibleFrame)).toRect(); + + // The reference screen for the geometry is always the primary screen, but since + // we may be in the process of creating and registering the primary screen, we + // must special-case that and assign it direcly. + QCocoaScreen *primaryScreen = (nsScreen == [[NSScreen screens] firstObject]) ? + this : QCocoaScreen::primaryScreen(); + + m_geometry = primaryScreen->mapFromNative(m_geometry).toRect(); + m_availableGeometry = primaryScreen->mapFromNative(m_availableGeometry).toRect(); + + m_format = QImage::Format_RGB32; + m_depth = NSBitsPerPixelFromDepth([nsScreen depth]); + + NSDictionary *devDesc = [nsScreen deviceDescription]; + CGDirectDisplayID dpy = [[devDesc objectForKey:@"NSScreenNumber"] unsignedIntValue]; + CGSize size = CGDisplayScreenSize(dpy); + m_physicalSize = QSizeF(size.width, size.height); + m_logicalDpi.first = 72; + m_logicalDpi.second = 72; + CGDisplayModeRef displayMode = CGDisplayCopyDisplayMode(dpy); + float refresh = CGDisplayModeGetRefreshRate(displayMode); + CGDisplayModeRelease(displayMode); + if (refresh > 0) + m_refreshRate = refresh; + + // Get m_name (brand/model of the monitor) + NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(dpy), kIODisplayOnlyPreferredName); + NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]]; + if ([localizedNames count] > 0) + m_name = QString::fromUtf8([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]); + [deviceInfo release]; + + QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry()); + QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second); + QWindowSystemInterface::handleScreenRefreshRateChange(screen(), m_refreshRate); +} + +qreal QCocoaScreen::devicePixelRatio() const +{ + QMacAutoReleasePool pool; + NSScreen *nsScreen = nativeScreen(); + return qreal(nsScreen ? [nsScreen backingScaleFactor] : 1.0); +} + +QPlatformScreen::SubpixelAntialiasingType QCocoaScreen::subpixelAntialiasingTypeHint() const +{ + QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint(); + if (type == QPlatformScreen::Subpixel_None) { + // Every OSX machine has RGB pixels unless a peculiar or rotated non-Apple screen is attached + type = QPlatformScreen::Subpixel_RGB; + } + return type; +} + +QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const +{ + NSPoint screenPoint = qt_mac_flipPoint(point); + + // Search (hit test) for the top-level window. [NSWidow windowNumberAtPoint: + // belowWindowWithWindowNumber] may return windows that are not interesting + // to Qt. The search iterates until a suitable window or no window is found. + NSInteger topWindowNumber = 0; + QWindow *window = 0; + do { + // Get the top-most window, below any previously rejected window. + topWindowNumber = [NSWindow windowNumberAtPoint:screenPoint + belowWindowWithWindowNumber:topWindowNumber]; + + // Continue the search if the window does not belong to this process. + NSWindow *nsWindow = [NSApp windowWithWindowNumber:topWindowNumber]; + if (nsWindow == 0) + continue; + + // Continue the search if the window does not belong to Qt. + if (![nsWindow conformsToProtocol:@protocol(QNSWindowProtocol)]) + continue; + + id proto = static_cast >(nsWindow); + QCocoaWindow *cocoaWindow = proto.platformWindow; + if (!cocoaWindow) + continue; + window = cocoaWindow->window(); + + // Continue the search if the window is not a top-level window. + if (!window->isTopLevel()) + continue; + + // Stop searching. The current window is the correct window. + break; + } while (topWindowNumber > 0); + + return window; +} + +QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const +{ + // TODO window should be handled + Q_UNUSED(window) + + const int maxDisplays = 128; // 128 displays should be enough for everyone. + CGDirectDisplayID displays[maxDisplays]; + CGDisplayCount displayCount; + CGRect cgRect; + + if (width < 0 || height < 0) { + // get all displays + cgRect = CGRectInfinite; + } else { + cgRect = CGRectMake(x, y, width, height); + } + const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount); + + if (err && displayCount == 0) + return QPixmap(); + + // calculate pixmap size + QSize windowSize(width, height); + if (width < 0 || height < 0) { + QRect windowRect; + for (uint i = 0; i < displayCount; ++i) { + const CGRect cgRect = CGDisplayBounds(displays[i]); + QRect qRect(cgRect.origin.x, cgRect.origin.y, cgRect.size.width, cgRect.size.height); + windowRect = windowRect.united(qRect); + } + if (width < 0) + windowSize.setWidth(windowRect.width()); + if (height < 0) + windowSize.setHeight(windowRect.height()); + } + + QPixmap windowPixmap(windowSize * devicePixelRatio()); + windowPixmap.fill(Qt::transparent); + + for (uint i = 0; i < displayCount; ++i) { + const CGRect bounds = CGDisplayBounds(displays[i]); + int w = (width < 0 ? bounds.size.width : width) * devicePixelRatio(); + int h = (height < 0 ? bounds.size.height : height) * devicePixelRatio(); + QRect displayRect = QRect(x, y, w, h); + displayRect = displayRect.translated(qRound(-bounds.origin.x), qRound(-bounds.origin.y)); + QCFType image = CGDisplayCreateImageForRect(displays[i], + CGRectMake(displayRect.x(), displayRect.y(), displayRect.width(), displayRect.height())); + QPixmap pix(w, h); + pix.fill(Qt::transparent); + CGRect rect = CGRectMake(0, 0, w, h); + QMacCGContext ctx(&pix); + qt_mac_drawCGImage(ctx, &rect, image); + + QPainter painter(&windowPixmap); + painter.drawPixmap(0, 0, pix); + } + return windowPixmap; +} + +/*! + The screen used as a reference for global window geometry +*/ +QCocoaScreen *QCocoaScreen::primaryScreen() +{ + return static_cast(QGuiApplication::primaryScreen()->handle()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 8f5b419f2a..3b6e55f654 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qcocoawindow.h" #include "qcocoaintegration.h" +#include "qcocoascreen.h" #include "qnswindowdelegate.h" #include "qcocoaeventdispatcher.h" #ifndef QT_NO_OPENGL -- cgit v1.2.3 From 6486a4bd196ca2bf0047ae80e78eee06e5e18e18 Mon Sep 17 00:00:00 2001 From: Lars Schmertmann Date: Thu, 14 Sep 2017 12:47:11 +0200 Subject: Avoid using deprecated APIs on iOS 10.0+ Change-Id: Ic9dc6a24ef793a29c2652ad37bc11120e2e6ceef Reviewed-by: Jake Petroules --- src/plugins/platforms/ios/qiosservices.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/ios/qiosservices.mm b/src/plugins/platforms/ios/qiosservices.mm index 0ecc8e123f..3c44e1d7d6 100644 --- a/src/plugins/platforms/ios/qiosservices.mm +++ b/src/plugins/platforms/ios/qiosservices.mm @@ -55,11 +55,13 @@ bool QIOSServices::openUrl(const QUrl &url) return openDocument(url); NSURL *nsUrl = url.toNSURL(); + UIApplication *application = [UIApplication sharedApplication]; - if (![[UIApplication sharedApplication] canOpenURL:nsUrl]) + if (![application canOpenURL:nsUrl]) return false; - return [[UIApplication sharedApplication] openURL:nsUrl]; + [application openURL:nsUrl options:@{} completionHandler:nil]; + return true; } bool QIOSServices::openDocument(const QUrl &url) -- cgit v1.2.3 From 46eb7d6b70416d99fddcb5a3d59c478da6b36bea Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 10 Oct 2017 14:40:17 +0200 Subject: Windows Vista Style: Draw dock widget title with Qt::TextShowMnemonic Align with the other styles. Task-number: QTBUG-54485 Change-Id: Ic8d008c59f5acf858b8ba6fbea5dd30b8aa9634c Reviewed-by: Andy Shaw --- src/plugins/styles/windowsvista/qwindowsvistastyle.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp index 9e6880098f..078875033f 100644 --- a/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp +++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp @@ -1430,7 +1430,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption verticalTitleBar ? titleRect.height() : titleRect.width()); const int indent = 4; drawItemText(painter, rect.adjusted(indent + 1, 1, -indent - 1, -1), - Qt::AlignLeft | Qt::AlignVCenter, dwOpt->palette, + Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, + dwOpt->palette, dwOpt->state & State_Enabled, titleText, QPalette::WindowText); } -- cgit v1.2.3 From ed9340a926aabcf3bf98091ed0436d6b02dd2c14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 5 Oct 2017 18:01:21 +0200 Subject: macOS: Add support for non-window backed offscreen surfaces The modern approach to offscreen rendering on macOS is via FBOs, which means there's no reason to allocate an NSView and corresponding NSWindow just for that. In the offscreen case the NSOpenGLContext has a nil-view. Change-Id: I2d1d407069af4d5283e6f56fba83db8eaf694ac6 Reviewed-by: Laszlo Agocs --- src/plugins/platforms/cocoa/qcocoaglcontext.mm | 9 +++++++-- src/plugins/platforms/cocoa/qcocoaintegration.h | 1 + src/plugins/platforms/cocoa/qcocoaintegration.mm | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.mm b/src/plugins/platforms/cocoa/qcocoaglcontext.mm index 75ac348802..5ed81a7f1b 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.mm @@ -218,6 +218,9 @@ void QCocoaGLContext::windowWasHidden() void QCocoaGLContext::swapBuffers(QPlatformSurface *surface) { + if (surface->surface()->surfaceClass() == QSurface::Offscreen) + return; // Nothing to do + QWindow *window = static_cast(surface)->window(); setActiveWindow(window); @@ -229,11 +232,13 @@ bool QCocoaGLContext::makeCurrent(QPlatformSurface *surface) Q_ASSERT(surface->surface()->supportsOpenGL()); QMacAutoReleasePool pool; + [m_context makeCurrentContext]; + + if (surface->surface()->surfaceClass() == QSurface::Offscreen) + return true; QWindow *window = static_cast(surface)->window(); setActiveWindow(window); - - [m_context makeCurrentContext]; update(); return true; } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 8745b6a4e3..dc7c5916a3 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -77,6 +77,7 @@ public: bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const Q_DECL_OVERRIDE; + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; #ifndef QT_NO_OPENGL QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; #endif diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 61eeeaf436..dd17848109 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -331,6 +332,24 @@ QPlatformWindow *QCocoaIntegration::createForeignWindow(QWindow *window, WId nat return new QCocoaWindow(window, nativeHandle); } +class QCocoaOffscreenSurface : public QPlatformOffscreenSurface +{ +public: + QCocoaOffscreenSurface(QOffscreenSurface *offscreenSurface) : QPlatformOffscreenSurface(offscreenSurface) {} + + QSurfaceFormat format() const override + { + Q_ASSERT(offscreenSurface()); + return offscreenSurface()->requestedFormat(); + } + bool isValid() const override { return true; } +}; + +QPlatformOffscreenSurface *QCocoaIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + return new QCocoaOffscreenSurface(surface); +} + #ifndef QT_NO_OPENGL QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { -- cgit v1.2.3 From ac35f9c44c0fb3b2f40ae5585c497200b2ba743d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 6 Oct 2017 15:50:29 +0200 Subject: macOS: Mark the widget's container as embedded when placed into NSMenuItem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise we'll end up creating a NSPanel for the QMacNativeWidget which is never closed, even if the backing NSView is moved to a new superview. Ideally this would be based on [NSView viewDidMoveToSuperview] and [NSView viewDidMoveToWindow], with retain/releases of the corresponding NSWindow, but that needs more research, especially as AppKit on macOS 10.13 will always keep a strong reference to the NSWindow. Task-number: QTBUG-63443 Change-Id: I9eec5ea871373d00dedf154600bf7005898cf37a Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoawindow.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/plugins') diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 3b6e55f654..8e5a9268ec 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1240,7 +1240,7 @@ void QCocoaWindow::recreateWindowIfNeeded() if (m_windowModality != window()->modality()) recreateReason |= WindowModalityChanged; - const bool shouldBeContentView = !parentWindow && !m_viewIsEmbedded; + const bool shouldBeContentView = !parentWindow && !(m_viewIsToBeEmbedded || m_viewIsEmbedded); if (isContentView() != shouldBeContentView) recreateReason |= ContentViewChanged; -- cgit v1.2.3