summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android/qandroidplatformscreen.cpp
diff options
context:
space:
mode:
authorPiotr Mikolajczyk <piotr.mikolajczyk@qt.io>2021-02-02 06:45:21 +0100
committerVille Voutilainen <ville.voutilainen@qt.io>2021-03-08 08:00:18 +0000
commitbacf9cd04c21c62075087febe0a799ed8d1c5f8c (patch)
treececdec78bc5301a734c63493b71cd8daf2cac0cd /src/plugins/platforms/android/qandroidplatformscreen.cpp
parent4f37cf2ce544dad5b207161536566627b6b0b1ef (diff)
Android: Add grabWindow handling
Draws to a pixmap contents of the requested window. On Android it works only for QtWidgets application. Qml application contents could not be grabbed due to lack of access to the contents of OpenGL framebuffer from QAndroidPlatformScreen Fixes: QTBUG-63275 Pick-to: 5.15 Change-Id: Ief7de1b709387d798138387bb735f4b48cf2928d Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
Diffstat (limited to 'src/plugins/platforms/android/qandroidplatformscreen.cpp')
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp72
1 files changed, 68 insertions, 4 deletions
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 5f8486a7a24..6a838272622 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -302,7 +302,7 @@ int QAndroidPlatformScreen::rasterSurfaces()
return m_rasterSurfaces;
}
-void QAndroidPlatformScreen::doRedraw()
+void QAndroidPlatformScreen::doRedraw(QImage* screenGrabImage)
{
PROFILE_SCOPE;
if (!QtAndroid::activity())
@@ -357,15 +357,14 @@ void QAndroidPlatformScreen::doRedraw()
}
int bpp = 4;
- QImage::Format format = QImage::Format_RGBA8888_Premultiplied;
if (nativeWindowBuffer.format == WINDOW_FORMAT_RGB_565) {
bpp = 2;
- format = QImage::Format_RGB16;
+ m_pixelFormat = QImage::Format_RGB16;
}
QImage screenImage(reinterpret_cast<uchar *>(nativeWindowBuffer.bits)
, nativeWindowBuffer.width, nativeWindowBuffer.height
- , nativeWindowBuffer.stride * bpp , format);
+ , nativeWindowBuffer.stride * bpp , m_pixelFormat);
QPainter compositePainter(&screenImage);
compositePainter.setCompositionMode(QPainter::CompositionMode_Source);
@@ -398,6 +397,31 @@ void QAndroidPlatformScreen::doRedraw()
ret = ANativeWindow_unlockAndPost(m_nativeSurface);
if (ret >= 0)
m_dirtyRect = QRect();
+
+ if (screenGrabImage) {
+ if (screenGrabImage->size() != screenImage.size()) {
+ uchar* bytes = static_cast<uchar*>(malloc(screenImage.height() * screenImage.bytesPerLine()));
+ *screenGrabImage = QImage(bytes, screenImage.width(), screenImage.height(),
+ screenImage.bytesPerLine(), m_pixelFormat,
+ [](void* ptr){ if (ptr) free (ptr);});
+ }
+ memcpy(screenGrabImage->bits(),
+ screenImage.bits(),
+ screenImage.bytesPerLine() * screenImage.height());
+ }
+ m_repaintOccurred = true;
+}
+
+QPixmap QAndroidPlatformScreen::doScreenShot(QRect grabRect)
+{
+ if (!m_repaintOccurred)
+ return QPixmap::fromImage(m_lastScreenshot.copy(grabRect));
+ QRect tmp = m_dirtyRect;
+ m_dirtyRect = geometry();
+ doRedraw(&m_lastScreenshot);
+ m_dirtyRect = tmp;
+ m_repaintOccurred = false;
+ return QPixmap::fromImage(m_lastScreenshot.copy(grabRect));
}
static const int androidLogicalDpi = 72;
@@ -445,4 +469,44 @@ void QAndroidPlatformScreen::releaseSurface()
}
}
+/*!
+ This function is called when Qt needs to be able to grab the content of a window.
+
+ Returns the content of the window specified with the WId handle within the boundaries of
+ QRect(x, y, width, height).
+*/
+QPixmap QAndroidPlatformScreen::grabWindow(WId window, int x, int y, int width, int height) const
+{
+ QRectF screenshotRect(x, y, width, height);
+ QWindow* wnd = 0;
+ if (window)
+ {
+ const auto windowList = qApp->allWindows();
+ for (QWindow *w : windowList)
+ if (w->winId() == window) {
+ wnd = w;
+ break;
+ }
+ }
+ if (wnd) {
+ const qreal factor = logicalDpi().first / androidLogicalDpi; //HighDPI factor;
+ QRectF wndRect = wnd->geometry();
+ if (wnd->parent())
+ wndRect.moveTopLeft(wnd->parent()->mapToGlobal(wndRect.topLeft().toPoint()));
+ if (!qFuzzyCompare(factor, 1))
+ wndRect = QRectF(wndRect.left() * factor, wndRect.top() * factor,
+ wndRect.width() * factor, wndRect.height() * factor);
+
+ if (!screenshotRect.isEmpty()) {
+ screenshotRect.moveTopLeft(wndRect.topLeft() + screenshotRect.topLeft());
+ screenshotRect = screenshotRect.intersected(wndRect);
+ } else {
+ screenshotRect = wndRect;
+ }
+ } else {
+ screenshotRect = screenshotRect.isValid() ? screenshotRect : geometry();
+ }
+ return const_cast<QAndroidPlatformScreen *>(this)->doScreenShot(screenshotRect.toRect());
+}
+
QT_END_NAMESPACE