iOS: Implement support for QScreen::grabWindow()
Only windows that are part of the application can be grabbed. This excludes the system statusbar and other system overlays, as well as windows of other applications. This is a limitation due to the security model of iOS. There exists APIs to grab a snapshot of the complete screen, but these APIs return a view that can be used as a placeholder e.g. during view transformations, and doesn't match our API that require reading of pixels. Task-number: QTBUG-49944 Change-Id: I8fd5b4c2777be1486f0ff22762d5e9b64c927e70 Reviewed-by: Jake Petroules <jake.petroules@qt.io>
This commit is contained in:
parent
5ad8b3aa32
commit
dc3af6a164
@ -667,6 +667,10 @@ void QScreenPrivate::updatePrimaryOrientation()
|
||||
that are not part of the application, window system frames, and so
|
||||
on.
|
||||
|
||||
\warning Grabbing windows that are not part of the application is
|
||||
not supported on systems such as iOS, where sandboxing/security
|
||||
prevents reading pixels of windows not owned by the application.
|
||||
|
||||
The grabWindow() function grabs pixels from the screen, not from
|
||||
the window, i.e. if there is another window partially or entirely
|
||||
over the one you grab, you get pixels from the overlying window,
|
||||
|
@ -68,6 +68,8 @@ public:
|
||||
Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE;
|
||||
void setOrientationUpdateMask(Qt::ScreenOrientations mask) Q_DECL_OVERRIDE;
|
||||
|
||||
QPixmap grabWindow(WId window, int x, int y, int width, int height) const override;
|
||||
|
||||
UIScreen *uiScreen() const;
|
||||
UIWindow *uiWindow() const;
|
||||
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "quiview.h"
|
||||
|
||||
#include <QtGui/private/qwindow_p.h>
|
||||
#include <private/qcoregraphics_p.h>
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
@ -457,6 +458,38 @@ void QIOSScreen::setOrientationUpdateMask(Qt::ScreenOrientations mask)
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap QIOSScreen::grabWindow(WId window, int x, int y, int width, int height) const
|
||||
{
|
||||
if (window && ![reinterpret_cast<id>(window) isKindOfClass:[UIView class]])
|
||||
return QPixmap();
|
||||
|
||||
UIView *view = window ? reinterpret_cast<UIView *>(window) : m_uiWindow;
|
||||
|
||||
if (width < 0)
|
||||
width = qMax(view.bounds.size.width - x, CGFloat(0));
|
||||
if (height < 0)
|
||||
height = qMax(view.bounds.size.height - y, CGFloat(0));
|
||||
|
||||
CGRect captureRect = [m_uiWindow convertRect:CGRectMake(x, y, width, height) fromView:view];
|
||||
captureRect = CGRectIntersection(captureRect, m_uiWindow.bounds);
|
||||
|
||||
UIGraphicsBeginImageContextWithOptions(captureRect.size, NO, 0.0);
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextTranslateCTM(context, -captureRect.origin.x, -captureRect.origin.y);
|
||||
|
||||
// Draws the complete view hierarchy of m_uiWindow into the given rect, which
|
||||
// needs to be the same aspect ratio as the m_uiWindow's size. Since we've
|
||||
// translated the graphics context, and are potentially drawing into a smaller
|
||||
// context than the full window, the resulting image will be a subsection of the
|
||||
// full screen.
|
||||
[m_uiWindow drawViewHierarchyInRect:m_uiWindow.bounds afterScreenUpdates:NO];
|
||||
|
||||
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
return QPixmap::fromImage(qt_mac_toQImage(screenshot.CGImage));
|
||||
}
|
||||
|
||||
UIScreen *QIOSScreen::uiScreen() const
|
||||
{
|
||||
return m_uiScreen;
|
||||
|
Loading…
Reference in New Issue
Block a user