iOS: Add support for foreign windows
Task-number: QTBUG-116183 Pick-to: 6.6 Change-Id: Ia92ee2d15f2e91a326ad342237fb0a83305c019f Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
parent
199570e3b1
commit
17e7d98626
@ -441,6 +441,20 @@ private:
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
#ifdef __OBJC__
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_pointer<T>::value, T>::type
|
||||
qt_objc_cast(id object)
|
||||
{
|
||||
if ([object isKindOfClass:[typename std::remove_pointer<T>::type class]])
|
||||
return static_cast<T>(object);
|
||||
|
||||
return nil;
|
||||
}
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QCORE_MAC_P_H
|
||||
|
@ -56,16 +56,6 @@ NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions);
|
||||
Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions);
|
||||
Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions);
|
||||
|
||||
template <typename T>
|
||||
typename std::enable_if<std::is_pointer<T>::value, T>::type
|
||||
qt_objc_cast(id object)
|
||||
{
|
||||
if ([object isKindOfClass:[typename std::remove_pointer<T>::type class]])
|
||||
return static_cast<T>(object);
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
QT_MANGLE_NAMESPACE(QNSView) *qnsview_cast(NSView *view);
|
||||
|
||||
// Misc
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
bool hasCapability(Capability cap) const override;
|
||||
|
||||
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
|
||||
QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override;
|
||||
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
|
||||
|
||||
#if QT_CONFIG(opengl)
|
||||
|
@ -150,6 +150,8 @@ bool QIOSIntegration::hasCapability(Capability cap) const
|
||||
return false;
|
||||
case ApplicationState:
|
||||
return true;
|
||||
case ForeignWindows:
|
||||
return true;
|
||||
default:
|
||||
return QPlatformIntegration::hasCapability(cap);
|
||||
}
|
||||
@ -160,6 +162,11 @@ QPlatformWindow *QIOSIntegration::createPlatformWindow(QWindow *window) const
|
||||
return new QIOSWindow(window);
|
||||
}
|
||||
|
||||
QPlatformWindow *QIOSIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
|
||||
{
|
||||
return new QIOSWindow(window, nativeHandle);
|
||||
}
|
||||
|
||||
QPlatformBackingStore *QIOSIntegration::createPlatformBackingStore(QWindow *window) const
|
||||
{
|
||||
return new QRhiBackingStore(window);
|
||||
|
@ -21,7 +21,7 @@ class QIOSWindow : public QObject, public QPlatformWindow
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QIOSWindow(QWindow *window);
|
||||
explicit QIOSWindow(QWindow *window, WId nativeHandle = 0);
|
||||
~QIOSWindow();
|
||||
|
||||
void setGeometry(const QRect &rect) override;
|
||||
@ -66,7 +66,7 @@ private:
|
||||
void applicationStateChanged(Qt::ApplicationState state);
|
||||
void applyGeometry(const QRect &rect);
|
||||
|
||||
QUIView *m_view;
|
||||
UIView *m_view;
|
||||
|
||||
QRect m_normalGeometry;
|
||||
int m_windowLevel;
|
||||
@ -82,6 +82,8 @@ private:
|
||||
QDebug operator<<(QDebug debug, const QIOSWindow *window);
|
||||
#endif
|
||||
|
||||
QT_MANGLE_NAMESPACE(QUIView) *quiview_cast(UIView *view);
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QIOSWINDOW_H
|
||||
|
@ -29,19 +29,24 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QIOSWindow::QIOSWindow(QWindow *window)
|
||||
QIOSWindow::QIOSWindow(QWindow *window, WId nativeHandle)
|
||||
: QPlatformWindow(window)
|
||||
, m_windowLevel(0)
|
||||
{
|
||||
if (nativeHandle) {
|
||||
m_view = reinterpret_cast<UIView *>(nativeHandle);
|
||||
[m_view retain];
|
||||
} else {
|
||||
#ifdef Q_OS_IOS
|
||||
if (window->surfaceType() == QSurface::RasterSurface)
|
||||
window->setSurfaceType(QSurface::MetalSurface);
|
||||
if (window->surfaceType() == QSurface::RasterSurface)
|
||||
window->setSurfaceType(QSurface::MetalSurface);
|
||||
|
||||
if (window->surfaceType() == QSurface::MetalSurface)
|
||||
m_view = [[QUIMetalView alloc] initWithQIOSWindow:this];
|
||||
else
|
||||
if (window->surfaceType() == QSurface::MetalSurface)
|
||||
m_view = [[QUIMetalView alloc] initWithQIOSWindow:this];
|
||||
else
|
||||
#endif
|
||||
m_view = [[QUIView alloc] initWithQIOSWindow:this];
|
||||
m_view = [[QUIView alloc] initWithQIOSWindow:this];
|
||||
}
|
||||
|
||||
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QIOSWindow::applicationStateChanged);
|
||||
|
||||
@ -80,7 +85,7 @@ QIOSWindow::~QIOSWindow()
|
||||
|
||||
clearAccessibleCache();
|
||||
|
||||
m_view.platformWindow = 0;
|
||||
quiview_cast(m_view).platformWindow = 0;
|
||||
[m_view removeFromSuperview];
|
||||
[m_view release];
|
||||
}
|
||||
@ -120,7 +125,7 @@ void QIOSWindow::setVisible(bool visible)
|
||||
if (visible && shouldAutoActivateWindow()) {
|
||||
if (!window()->property("_q_showWithoutActivating").toBool())
|
||||
requestActivateWindow();
|
||||
} else if (!visible && [m_view isActiveWindow]) {
|
||||
} else if (!visible && [quiview_cast(m_view) isActiveWindow]) {
|
||||
// Our window was active/focus window but now hidden, so relinquish
|
||||
// focus to the next possible window in the stack.
|
||||
NSArray<UIView *> *subviews = m_view.viewController.view.subviews;
|
||||
@ -340,8 +345,11 @@ void QIOSWindow::handleContentOrientationChange(Qt::ScreenOrientation orientatio
|
||||
|
||||
void QIOSWindow::applicationStateChanged(Qt::ApplicationState)
|
||||
{
|
||||
if (isForeignWindow())
|
||||
return;
|
||||
|
||||
if (window()->isExposed() != isExposed())
|
||||
[m_view sendUpdatedExposeEvent];
|
||||
[quiview_cast(m_view) sendUpdatedExposeEvent];
|
||||
}
|
||||
|
||||
qreal QIOSWindow::devicePixelRatio() const
|
||||
@ -351,7 +359,10 @@ qreal QIOSWindow::devicePixelRatio() const
|
||||
|
||||
void QIOSWindow::clearAccessibleCache()
|
||||
{
|
||||
[m_view clearAccessibleCache];
|
||||
if (isForeignWindow())
|
||||
return;
|
||||
|
||||
[quiview_cast(m_view) clearAccessibleCache];
|
||||
}
|
||||
|
||||
void QIOSWindow::requestUpdate()
|
||||
@ -394,6 +405,27 @@ QDebug operator<<(QDebug debug, const QIOSWindow *window)
|
||||
}
|
||||
#endif // !QT_NO_DEBUG_STREAM
|
||||
|
||||
/*!
|
||||
Returns the view cast to a QUIview if possible.
|
||||
|
||||
If the view is not a QUIview, nil is returned, which is safe to
|
||||
send messages to, effectively making [quiview_cast(view) message]
|
||||
a no-op.
|
||||
|
||||
For extra verbosity and clearer code, please consider checking
|
||||
that the platform window is not a foreign window before using
|
||||
this cast, via QPlatformWindow::isForeignWindow().
|
||||
|
||||
Do not use this method solely to check for foreign windows, as
|
||||
that will make the code harder to read for people not working
|
||||
primarily on iOS, who do not know the difference between the
|
||||
UIView and QUIView cases.
|
||||
*/
|
||||
QUIView *quiview_cast(UIView *view)
|
||||
{
|
||||
return qt_objc_cast<QUIView *>(view);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "moc_qioswindow.cpp"
|
||||
|
Loading…
Reference in New Issue
Block a user