8#include <qpa/qwindowsysteminterface.h>
18#include <android/bitmap.h>
19#include <android/native_window_jni.h>
22#include <QtCore/QJniObject>
23#include <QtCore/QJniEnvironment>
24#include <QtGui/QGuiApplication>
25#include <QtGui/QWindow>
26#include <QtGui/private/qwindow_p.h>
31#ifdef QANDROIDPLATFORMSCREEN_DEBUG
35 ScopedProfiler(
const QString &msg)
42 qDebug() << m_msg << m_timer.elapsed();
50# define PROFILE_SCOPE ScopedProfiler ___sp___(__func__)
66 m_availableGeometry = QAndroidPlatformIntegration::m_defaultAvailableGeometry;
67 m_size = QAndroidPlatformIntegration::m_defaultScreenSize;
68 m_physicalSize = QAndroidPlatformIntegration::m_defaultPhysicalSize;
81 &QAndroidPlatformScreen::applicationStateChanged);
83 if (!displayObject.isValid())
86 m_name = displayObject.callObjectMethod<jstring>(
"getName").
toString();
87 m_refreshRate = displayObject.callMethod<jfloat>(
"getRefreshRate");
88 m_displayId = displayObject.callMethod<jint>(
"getDisplayId");
91 const auto displayContext =
context.callMethod<QtJniTypes::Context>(
"createDisplayContext",
92 displayObject.object<QtJniTypes::Display>());
94 const auto sizeObj = QJniObject::callStaticMethod<QtJniTypes::Size>(
95 QtJniTypes::className<QtJniTypes::QtNative>(),
97 displayContext.object<QtJniTypes::Context>(),
98 displayObject.object<QtJniTypes::Display>());
99 m_size =
QSize(sizeObj.callMethod<
int>(
"getWidth"), sizeObj.callMethod<
int>(
"getHeight"));
101 const auto resources = displayContext.callMethod<QtJniTypes::Resources>(
"getResources");
102 const auto metrics = resources.callMethod<QtJniTypes::DisplayMetrics>(
"getDisplayMetrics");
103 const float xdpi =
metrics.getField<
float>(
"xdpi");
104 const float ydpi =
metrics.getField<
float>(
"ydpi");
109 m_physicalSize.setWidth(
qRound(m_size.width() / xdpi * 25.4));
110 m_physicalSize.setHeight(
qRound(m_size.height() / ydpi * 25.4));
112 if (QNativeInterface::QAndroidApplication::sdkVersion() >= 23) {
113 const QJniObject currentMode = displayObject.callObjectMethod<QtJniTypes::DisplayMode>(
"getMode");
114 m_currentMode = currentMode.callMethod<jint>(
"getModeId");
116 const QJniObject supportedModes = displayObject.callObjectMethod<QtJniTypes::DisplayMode[]>(
117 "getSupportedModes");
118 const auto modeArray = jobjectArray(supportedModes.object());
121 const auto size = env->GetArrayLength(modeArray);
122 for (jsize
i = 0;
i <
size; ++
i) {
123 const auto mode = QJniObject::fromLocalRef(env->GetObjectArrayElement(modeArray,
i));
126 mode.callMethod<jint>(
"getPhysicalHeight") },
127 .refreshRate =
mode.callMethod<jfloat>(
"getRefreshRate")
135 if (m_surfaceId != -1) {
137 m_surfaceWaitCondition.
wakeOne();
157 if (
w->geometry().contains(
p,
false) &&
w->window()->isVisible())
183 m_rasterSurfaces.
ref();
200 qWarning() <<
"Failed to remove window";
203 m_rasterSurfaces.
deref();
273 const QRect &availableGeometry)
320 if (oldGeometry.
width() == 0 && oldGeometry.
height() == 0 &&
rect.width() > 0 &&
rect.height() > 0) {
332 if (m_surfaceId != -1) {
341 w->applicationStateChanged(
state);
358 if (platformWindow != 0)
365 return m_rasterSurfaces;
368void QAndroidPlatformScreen::doRedraw(
QImage* screenGrabImage)
380 bool hasVisibleRasterWindows =
false;
383 hasVisibleRasterWindows =
true;
387 if (!hasVisibleRasterWindows) {
389 if (m_surfaceId != -1) {
398 if (m_surfaceId == -1 && m_rasterSurfaces) {
406 if (!m_nativeSurface)
409 ANativeWindow_Buffer nativeWindowBuffer;
410 ARect nativeWindowRect;
417 if ((
ret = ANativeWindow_lock(m_nativeSurface, &nativeWindowBuffer, &nativeWindowRect)) < 0) {
418 qWarning() <<
"ANativeWindow_lock() failed! error=" <<
ret;
423 if (nativeWindowBuffer.format == WINDOW_FORMAT_RGB_565) {
428 QImage screenImage(
reinterpret_cast<uchar *
>(nativeWindowBuffer.bits)
429 , nativeWindowBuffer.width, nativeWindowBuffer.height
430 , nativeWindowBuffer.stride * bpp , m_pixelFormat);
432 QPainter compositePainter(&screenImage);
437 if (!
window->window()->isVisible()
449 visibleRegion -= targetRect;
453 compositePainter.drawImage(targetRect.
topLeft(), backingStore->
toImage(), windowRect);
460 ret = ANativeWindow_unlockAndPost(m_nativeSurface);
464 if (screenGrabImage) {
465 if (screenGrabImage->
size() != screenImage.size()) {
466 uchar* bytes =
static_cast<uchar*
>(malloc(screenImage.height() * screenImage.bytesPerLine()));
467 *screenGrabImage =
QImage(bytes, screenImage.width(), screenImage.height(),
468 screenImage.bytesPerLine(), m_pixelFormat,
469 [](
void*
ptr){ if (ptr) free (ptr);});
471 memcpy(screenGrabImage->
bits(),
473 screenImage.bytesPerLine() * screenImage.height());
475 m_repaintOccurred =
true;
478QPixmap QAndroidPlatformScreen::doScreenShot(
QRect grabRect)
480 if (!m_repaintOccurred)
484 doRedraw(&m_lastScreenshot);
486 m_repaintOccurred =
false;
495 return QDpi(lDpi, lDpi);
505 return QAndroidPlatformIntegration::m_orientation;
510 return QAndroidPlatformIntegration::m_nativeOrientation;
516 if (surface &&
w > 0 &&
h > 0) {
518 m_nativeSurface = ANativeWindow_fromSurface(env, surface);
524 m_surfaceWaitCondition.
wakeOne();
527void QAndroidPlatformScreen::releaseSurface()
529 if (m_nativeSurface) {
530 ANativeWindow_release(m_nativeSurface);
547 const auto windowList =
qApp->allWindows();
556 QRectF wndRect = wnd->geometry();
560 wndRect =
QRectF(wndRect.
left() * factor, wndRect.
top() * factor,
561 wndRect.
width() * factor, wndRect.
height() * factor);
563 if (!screenshotRect.
isEmpty()) {
565 screenshotRect = screenshotRect.
intersected(wndRect);
567 screenshotRect = wndRect;
570 screenshotRect = screenshotRect.
isValid() ? screenshotRect :
geometry();
The QColor class provides colors based on RGB, HSV or CMYK values.
static void postEvent(QObject *receiver, QEvent *event, int priority=Qt::NormalEventPriority)
static QWindowList allWindows()
Returns a list of all the windows in the application.
void applicationStateChanged(Qt::ApplicationState state)
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
QSize size() const
Returns the size of the image, i.e.
uchar * bits()
Returns a pointer to the first pixel data.
@ Format_ARGB32_Premultiplied
qsizetype size() const noexcept
bool removeOne(const AT &t)
const_reference at(qsizetype i) const noexcept
void move(qsizetype from, qsizetype to)
void prepend(rvalue_ref t)
virtual bool event(QEvent *event)
This virtual function receives events to an object and should return true if the event e was recogniz...
The QPainter class performs low-level painting on widgets and other paint devices.
Returns a copy of the pixmap that is transformed using the given transformation transform and transfo...
static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags=Qt::AutoColor)
Converts the given image to a pixmap using the specified flags to control the conversion.
constexpr QPoint toPoint() const
Rounds the coordinates of this point to the nearest integer, and returns a QPoint object with the rou...
\inmodule QtCore\reentrant
\inmodule QtCore\reentrant
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
constexpr qreal height() const noexcept
Returns the height of the rectangle.
constexpr qreal width() const noexcept
Returns the width of the rectangle.
constexpr void moveTopLeft(const QPointF &p) noexcept
Moves the rectangle, leaving the top-left corner at the given position.
constexpr qreal left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr QPointF topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
constexpr QRect toRect() const noexcept
Returns a QRect based on the values of this rectangle.
constexpr qreal top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr bool isValid() const noexcept
Returns true if the rectangle is valid, otherwise returns false.
QRectF intersected(const QRectF &other) const noexcept
\inmodule QtCore\reentrant
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
constexpr QPoint topLeft() const noexcept
Returns the position of the rectangle's top-left corner.
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr QSize size() const noexcept
Returns the size of the rectangle.
constexpr int width() const noexcept
Returns the width of the rectangle.
constexpr QRect translated(int dx, int dy) const noexcept
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis,...
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
The QRegion class specifies a clip region for a painter.
\macro QT_RESTRICTED_CAST_FROM_ASCII
\inmodule QtCore \reentrant
bool wait(QMutex *, QDeadlineTimer=QDeadlineTimer(QDeadlineTimer::Forever))
static void handleScreenGeometryChange(QScreen *screen, const QRect &newGeometry, const QRect &newAvailableGeometry)
static bool handleExposeEvent(QWindow *window, const QRegion ®ion)
static void handleWindowActivated(QWindow *window, Qt::FocusReason r=Qt::OtherFocusReason)
static void handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation newOrientation)
static void handleScreenRefreshRateChange(QScreen *screen, qreal newRefreshRate)
Combined button and popup list for selecting options.
void setActiveTopLevelWindow(QWindow *window)
void destroySurface(int surfaceId)
void setSurfaceGeometry(int surfaceId, const QRect &geometry)
int createSurface(AndroidSurfaceClient *client, const QRect &geometry, bool onTop, int imageDepth)
QtJniTypes::Activity activity()
@ ActiveWindowFocusReason
QRectF fillRect(QRect rect, int background)
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
int qRound(qfloat16 d) noexcept
QPair< qreal, qreal > QDpi
static ControlElement< T > * ptr(QWidget *widget)
#define Q_ARG(Type, data)
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei GLenum const void GLuint GLsizei GLfloat * metrics
GLfloat GLfloat GLfloat GLfloat h
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
QT_BEGIN_NAMESPACE Q_DECLARE_JNI_CLASS(Environment, "android/os/Environment")
Q_DECLARE_JNI_TYPE(File, "Ljava/io/File;")
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
Q_GUI_EXPORT QWindowPrivate * qt_window_private(QWindow *window)
connect(quitButton, &QPushButton::clicked, &app, &QCoreApplication::quit, Qt::QueuedConnection)
char * toString(const MyType &t)
[31]
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
bool contains(const AT &t) const noexcept