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
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QCORE_MAC_P_H
|
#endif // QCORE_MAC_P_H
|
||||||
|
@ -56,16 +56,6 @@ NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions);
|
|||||||
Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions);
|
Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions);
|
||||||
Qt::DropActions qt_mac_mapNSDragOperations(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);
|
QT_MANGLE_NAMESPACE(QNSView) *qnsview_cast(NSView *view);
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
|
@ -31,6 +31,7 @@ public:
|
|||||||
bool hasCapability(Capability cap) const override;
|
bool hasCapability(Capability cap) const override;
|
||||||
|
|
||||||
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
|
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
|
||||||
|
QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override;
|
||||||
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
|
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const override;
|
||||||
|
|
||||||
#if QT_CONFIG(opengl)
|
#if QT_CONFIG(opengl)
|
||||||
|
@ -150,6 +150,8 @@ bool QIOSIntegration::hasCapability(Capability cap) const
|
|||||||
return false;
|
return false;
|
||||||
case ApplicationState:
|
case ApplicationState:
|
||||||
return true;
|
return true;
|
||||||
|
case ForeignWindows:
|
||||||
|
return true;
|
||||||
default:
|
default:
|
||||||
return QPlatformIntegration::hasCapability(cap);
|
return QPlatformIntegration::hasCapability(cap);
|
||||||
}
|
}
|
||||||
@ -160,6 +162,11 @@ QPlatformWindow *QIOSIntegration::createPlatformWindow(QWindow *window) const
|
|||||||
return new QIOSWindow(window);
|
return new QIOSWindow(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPlatformWindow *QIOSIntegration::createForeignWindow(QWindow *window, WId nativeHandle) const
|
||||||
|
{
|
||||||
|
return new QIOSWindow(window, nativeHandle);
|
||||||
|
}
|
||||||
|
|
||||||
QPlatformBackingStore *QIOSIntegration::createPlatformBackingStore(QWindow *window) const
|
QPlatformBackingStore *QIOSIntegration::createPlatformBackingStore(QWindow *window) const
|
||||||
{
|
{
|
||||||
return new QRhiBackingStore(window);
|
return new QRhiBackingStore(window);
|
||||||
|
@ -21,7 +21,7 @@ class QIOSWindow : public QObject, public QPlatformWindow
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QIOSWindow(QWindow *window);
|
explicit QIOSWindow(QWindow *window, WId nativeHandle = 0);
|
||||||
~QIOSWindow();
|
~QIOSWindow();
|
||||||
|
|
||||||
void setGeometry(const QRect &rect) override;
|
void setGeometry(const QRect &rect) override;
|
||||||
@ -66,7 +66,7 @@ private:
|
|||||||
void applicationStateChanged(Qt::ApplicationState state);
|
void applicationStateChanged(Qt::ApplicationState state);
|
||||||
void applyGeometry(const QRect &rect);
|
void applyGeometry(const QRect &rect);
|
||||||
|
|
||||||
QUIView *m_view;
|
UIView *m_view;
|
||||||
|
|
||||||
QRect m_normalGeometry;
|
QRect m_normalGeometry;
|
||||||
int m_windowLevel;
|
int m_windowLevel;
|
||||||
@ -82,6 +82,8 @@ private:
|
|||||||
QDebug operator<<(QDebug debug, const QIOSWindow *window);
|
QDebug operator<<(QDebug debug, const QIOSWindow *window);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
QT_MANGLE_NAMESPACE(QUIView) *quiview_cast(UIView *view);
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QIOSWINDOW_H
|
#endif // QIOSWINDOW_H
|
||||||
|
@ -29,19 +29,24 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QIOSWindow::QIOSWindow(QWindow *window)
|
QIOSWindow::QIOSWindow(QWindow *window, WId nativeHandle)
|
||||||
: QPlatformWindow(window)
|
: QPlatformWindow(window)
|
||||||
, m_windowLevel(0)
|
, m_windowLevel(0)
|
||||||
{
|
{
|
||||||
|
if (nativeHandle) {
|
||||||
|
m_view = reinterpret_cast<UIView *>(nativeHandle);
|
||||||
|
[m_view retain];
|
||||||
|
} else {
|
||||||
#ifdef Q_OS_IOS
|
#ifdef Q_OS_IOS
|
||||||
if (window->surfaceType() == QSurface::RasterSurface)
|
if (window->surfaceType() == QSurface::RasterSurface)
|
||||||
window->setSurfaceType(QSurface::MetalSurface);
|
window->setSurfaceType(QSurface::MetalSurface);
|
||||||
|
|
||||||
if (window->surfaceType() == QSurface::MetalSurface)
|
if (window->surfaceType() == QSurface::MetalSurface)
|
||||||
m_view = [[QUIMetalView alloc] initWithQIOSWindow:this];
|
m_view = [[QUIMetalView alloc] initWithQIOSWindow:this];
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
m_view = [[QUIView alloc] initWithQIOSWindow:this];
|
m_view = [[QUIView alloc] initWithQIOSWindow:this];
|
||||||
|
}
|
||||||
|
|
||||||
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QIOSWindow::applicationStateChanged);
|
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QIOSWindow::applicationStateChanged);
|
||||||
|
|
||||||
@ -80,7 +85,7 @@ QIOSWindow::~QIOSWindow()
|
|||||||
|
|
||||||
clearAccessibleCache();
|
clearAccessibleCache();
|
||||||
|
|
||||||
m_view.platformWindow = 0;
|
quiview_cast(m_view).platformWindow = 0;
|
||||||
[m_view removeFromSuperview];
|
[m_view removeFromSuperview];
|
||||||
[m_view release];
|
[m_view release];
|
||||||
}
|
}
|
||||||
@ -120,7 +125,7 @@ void QIOSWindow::setVisible(bool visible)
|
|||||||
if (visible && shouldAutoActivateWindow()) {
|
if (visible && shouldAutoActivateWindow()) {
|
||||||
if (!window()->property("_q_showWithoutActivating").toBool())
|
if (!window()->property("_q_showWithoutActivating").toBool())
|
||||||
requestActivateWindow();
|
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
|
// Our window was active/focus window but now hidden, so relinquish
|
||||||
// focus to the next possible window in the stack.
|
// focus to the next possible window in the stack.
|
||||||
NSArray<UIView *> *subviews = m_view.viewController.view.subviews;
|
NSArray<UIView *> *subviews = m_view.viewController.view.subviews;
|
||||||
@ -340,8 +345,11 @@ void QIOSWindow::handleContentOrientationChange(Qt::ScreenOrientation orientatio
|
|||||||
|
|
||||||
void QIOSWindow::applicationStateChanged(Qt::ApplicationState)
|
void QIOSWindow::applicationStateChanged(Qt::ApplicationState)
|
||||||
{
|
{
|
||||||
|
if (isForeignWindow())
|
||||||
|
return;
|
||||||
|
|
||||||
if (window()->isExposed() != isExposed())
|
if (window()->isExposed() != isExposed())
|
||||||
[m_view sendUpdatedExposeEvent];
|
[quiview_cast(m_view) sendUpdatedExposeEvent];
|
||||||
}
|
}
|
||||||
|
|
||||||
qreal QIOSWindow::devicePixelRatio() const
|
qreal QIOSWindow::devicePixelRatio() const
|
||||||
@ -351,7 +359,10 @@ qreal QIOSWindow::devicePixelRatio() const
|
|||||||
|
|
||||||
void QIOSWindow::clearAccessibleCache()
|
void QIOSWindow::clearAccessibleCache()
|
||||||
{
|
{
|
||||||
[m_view clearAccessibleCache];
|
if (isForeignWindow())
|
||||||
|
return;
|
||||||
|
|
||||||
|
[quiview_cast(m_view) clearAccessibleCache];
|
||||||
}
|
}
|
||||||
|
|
||||||
void QIOSWindow::requestUpdate()
|
void QIOSWindow::requestUpdate()
|
||||||
@ -394,6 +405,27 @@ QDebug operator<<(QDebug debug, const QIOSWindow *window)
|
|||||||
}
|
}
|
||||||
#endif // !QT_NO_DEBUG_STREAM
|
#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
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#include "moc_qioswindow.cpp"
|
#include "moc_qioswindow.cpp"
|
||||||
|
Loading…
Reference in New Issue
Block a user