summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/android/qandroidplatformscreen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/android/qandroidplatformscreen.cpp')
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp142
1 files changed, 137 insertions, 5 deletions
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 80757c2135..b2ca70ce45 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -55,6 +55,7 @@
#include <android/native_window_jni.h>
#include <qguiapplication.h>
+#include <QtCore/private/qjnihelpers_p.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
#include <QtGui/private/qwindow_p.h>
@@ -104,6 +105,42 @@ QAndroidPlatformScreen::QAndroidPlatformScreen()
m_physicalSize.setHeight(QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight);
m_physicalSize.setWidth(QAndroidPlatformIntegration::m_defaultPhysicalSizeWidth);
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QAndroidPlatformScreen::applicationStateChanged);
+
+ QJNIObjectPrivate activity(QtAndroid::activity());
+ if (!activity.isValid())
+ return;
+ QJNIObjectPrivate display;
+ if (QtAndroidPrivate::androidSdkVersion() < 30) {
+ display = activity.callObjectMethod("getWindowManager", "()Landroid/view/WindowManager;")
+ .callObjectMethod("getDefaultDisplay", "()Landroid/view/Display;");
+ } else {
+ display = activity.callObjectMethod("getDisplay", "()Landroid/view/Display;");
+ }
+ if (!display.isValid())
+ return;
+ m_name = display.callObjectMethod("getName", "()Ljava/lang/String;").toString();
+ m_refreshRate = display.callMethod<jfloat>("getRefreshRate");
+ if (QtAndroidPrivate::androidSdkVersion() < 23) {
+ m_modes << Mode { .size = m_physicalSize.toSize(), .refreshRate = m_refreshRate };
+ return;
+ }
+ QJNIEnvironmentPrivate env;
+ const jint currentMode = display.callObjectMethod("getMode", "()Landroid/view/Display$Mode;")
+ .callMethod<jint>("getModeId");
+ const auto modes = display.callObjectMethod("getSupportedModes",
+ "()[Landroid/view/Display$Mode;");
+ const auto modesArray = jobjectArray(modes.object());
+ const auto sz = env->GetArrayLength(modesArray);
+ for (jsize i = 0; i < sz; ++i) {
+ auto mode = QJNIObjectPrivate::fromLocalRef(env->GetObjectArrayElement(modesArray, i));
+ if (currentMode == mode.callMethod<jint>("getModeId"))
+ m_currentMode = m_modes.size();
+ m_modes << Mode { .size = QSize { mode.callMethod<jint>("getPhysicalHeight"),
+ mode.callMethod<jint>("getPhysicalWidth") },
+ .refreshRate = mode.callMethod<jfloat>("getRefreshRate") };
+ }
+ if (m_modes.isEmpty())
+ m_modes << Mode { .size = m_physicalSize.toSize(), .refreshRate = m_refreshRate };
}
QAndroidPlatformScreen::~QAndroidPlatformScreen()
@@ -243,6 +280,37 @@ void QAndroidPlatformScreen::setSize(const QSize &size)
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(), availableGeometry());
}
+void QAndroidPlatformScreen::setSizeParameters(const QSize &physicalSize, const QSize &size,
+ const QRect &availableGeometry)
+{
+ // The goal of this method is to set all geometry-related parameters
+ // at the same time and generate only one screen geometry change event.
+ m_physicalSize = physicalSize;
+ m_size = size;
+ // If available geometry has changed, the event will be handled in
+ // setAvailableGeometry. Otherwise we need to explicitly handle it to
+ // retain the behavior, because setSize() does the handling unconditionally.
+ if (m_availableGeometry != availableGeometry) {
+ setAvailableGeometry(availableGeometry);
+ } else {
+ QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), geometry(),
+ this->availableGeometry());
+ }
+}
+
+void QAndroidPlatformScreen::setRefreshRate(qreal refreshRate)
+{
+ if (refreshRate == m_refreshRate)
+ return;
+ m_refreshRate = refreshRate;
+ QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), refreshRate);
+}
+
+void QAndroidPlatformScreen::setOrientation(Qt::ScreenOrientation orientation)
+{
+ QWindowSystemInterface::handleScreenOrientationChange(QPlatformScreen::screen(), orientation);
+}
+
void QAndroidPlatformScreen::setAvailableGeometry(const QRect &rect)
{
QMutexLocker lock(&m_surfaceMutex);
@@ -303,7 +371,7 @@ int QAndroidPlatformScreen::rasterSurfaces()
return m_rasterSurfaces;
}
-void QAndroidPlatformScreen::doRedraw()
+void QAndroidPlatformScreen::doRedraw(QImage* screenGrabImage)
{
PROFILE_SCOPE;
if (!QtAndroid::activity())
@@ -358,15 +426,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);
@@ -399,13 +466,38 @@ 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;
QDpi QAndroidPlatformScreen::logicalDpi() const
{
- qreal lDpi = QtAndroid::scaledDensity() * androidLogicalDpi;
+ qreal lDpi = QtAndroid::pixelDensity() * androidLogicalDpi;
return QDpi(lDpi, lDpi);
}
@@ -446,4 +538,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