Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qandroidplatformwindow.cpp
Go to the documentation of this file.
1// Copyright (C) 2014 BogDan Vatra <bogdan@kde.org>
2// Copyright (C) 2016 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
8
9#include "androidjnimain.h"
10
11#include <qguiapplication.h>
12#include <qpa/qwindowsysteminterface.h>
13#include <private/qhighdpiscaling_p.h>
14
16
17Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window")
18
19Q_DECLARE_JNI_CLASS(QtInputInterface, "org/qtproject/qt/android/QtInputInterface")
20Q_DECLARE_JNI_CLASS(QtInputConnectionListener,
21 "org/qtproject/qt/android/QtInputConnection$QtInputConnectionListener")
22
24 : QPlatformWindow(window), m_nativeQtWindow(nullptr),
25 m_surfaceContainerType(SurfaceContainer::TextureView), m_nativeParentQtWindow(nullptr),
26 m_androidSurfaceObject(nullptr)
27{
28 m_windowFlags = Qt::Widget;
29 m_windowState = Qt::WindowNoState;
30 // the surfaceType is overwritten in QAndroidPlatformOpenGLWindow ctor so let's save
31 // the fact that it's a raster window for now
32 m_isRaster = window->surfaceType() == QSurface::RasterSurface;
33 setWindowState(window->windowStates());
34
35 // the following is in relation to the virtual geometry
36 const bool forceMaximize = m_windowState & (Qt::WindowMaximized | Qt::WindowFullScreen);
37 const QRect nativeScreenGeometry = platformScreen()->availableGeometry();
38 if (forceMaximize) {
39 setGeometry(nativeScreenGeometry);
40 } else {
41 const QRect requestedNativeGeometry = QHighDpi::toNativePixels(window->geometry(), window);
42 const QRect availableDeviceIndependentGeometry = (window->parent())
43 ? window->parent()->geometry()
44 : QHighDpi::fromNativePixels(nativeScreenGeometry, window);
45 // initialGeometry returns in native pixels
46 const QRect finalNativeGeometry = QPlatformWindow::initialGeometry(
47 window, requestedNativeGeometry, availableDeviceIndependentGeometry.width(),
48 availableDeviceIndependentGeometry.height());
49 if (requestedNativeGeometry != finalNativeGeometry)
50 setGeometry(finalNativeGeometry);
51 }
52
53 if (isEmbeddingContainer())
54 return;
55
56 if (parent()) {
57 QAndroidPlatformWindow *androidParent = static_cast<QAndroidPlatformWindow*>(parent());
58 if (!androidParent->isEmbeddingContainer())
59 m_nativeParentQtWindow = androidParent->nativeWindow();
60 }
61
63 QtJniTypes::QtInputConnectionListener listener =
64 reg->callInterface<QtJniTypes::QtInputInterface, QtJniTypes::QtInputConnectionListener>(
65 "getInputConnectionListener");
66
67 m_nativeQtWindow = QJniObject::construct<QtJniTypes::QtWindow>(
68 QNativeInterface::QAndroidApplication::context(), m_nativeParentQtWindow, listener);
69 m_nativeViewId = m_nativeQtWindow.callMethod<jint>("getId");
70
71 if (window->isTopLevel())
72 platformScreen()->addWindow(this);
73
74 static bool ok = false;
75 static const int value = qEnvironmentVariableIntValue("QT_ANDROID_SURFACE_CONTAINER_TYPE", &ok);
76 if (ok) {
77 static const SurfaceContainer type = static_cast<SurfaceContainer>(value);
78 if (type == SurfaceContainer::SurfaceView || type == SurfaceContainer::TextureView)
79 m_surfaceContainerType = type;
80 } else if (platformScreen()->windows().size() <= 1) {
81 // TODO should handle case where this changes at runtime -> need to change existing window
82 // into TextureView (or perhaps not, if the parent window would be SurfaceView, as long as
83 // onTop was false it would stay below the children)
84 m_surfaceContainerType = SurfaceContainer::SurfaceView;
85 }
86 qCDebug(lcQpaWindow) << "Window" << m_nativeViewId << "using surface container type"
87 << static_cast<int>(m_surfaceContainerType);
88}
89
95
96
98{
99 if (m_nativeParentQtWindow.isValid()) {
100 m_nativeParentQtWindow.callMethod<void>("bringChildToBack", nativeViewId());
101 return;
102 }
103 platformScreen()->lower(this);
104}
105
107{
108 if (m_nativeParentQtWindow.isValid()) {
109 m_nativeParentQtWindow.callMethod<void>("bringChildToFront", nativeViewId());
111 return;
112 }
114 platformScreen()->raise(this);
115}
116
118{
120 QRect availableGeometry = platformScreen()->availableGeometry();
121 return QMargins(availableGeometry.left(), availableGeometry.top(),
122 availableGeometry.right(), availableGeometry.bottom());
123 } else {
125 }
126}
127
133
135{
137 return;
138 m_nativeQtWindow.callMethod<void>("setVisible", visible);
139
140 if (visible) {
141 if (window()->isTopLevel()) {
146 } else if (m_windowState & Qt::WindowMaximized) {
147 setGeometry(platformScreen()->availableGeometry());
148 }
150 }
151 } else if (window()->isTopLevel() && window() == qGuiApp->focusWindow()) {
153 }
154
155 QRect availableGeometry = screen()->availableGeometry();
156 if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
158}
159
161{
162 if (m_windowState == state)
163 return;
164
167
168 if (window()->isVisible())
170}
171
173{
174 if (m_windowFlags == flags)
175 return;
176
178}
179
181{
182 return m_windowFlags;
183}
184
186{
187 using namespace QtJniTypes;
188
189 if (window) {
190 auto androidWindow = static_cast<const QAndroidPlatformWindow*>(window);
191 if (androidWindow->isEmbeddingContainer())
192 return;
193 // If we were a top level window, remove from screen
194 if (!m_nativeParentQtWindow.isValid())
196
197 const QtWindow parentWindow = androidWindow->nativeWindow();
198 // If this was a child window of another window, the java method takes care of that
199 m_nativeQtWindow.callMethod<void, QtWindow>("setParent", parentWindow.object());
200 m_nativeParentQtWindow = parentWindow;
201 } else if (QtAndroid::isQtApplication()) {
202 m_nativeQtWindow.callMethod<void, QtWindow>("setParent", nullptr);
204 platformScreen()->addWindow(this);
205 }
206}
207
209{
210 return m_nativeQtWindow.isValid() ? reinterpret_cast<WId>(m_nativeQtWindow.object()) : 0L;
211}
212
214{
215 return static_cast<QAndroidPlatformScreen *>(window()->screen()->handle());
216}
217
219{
220 //shut up warning from default implementation
221}
222
224{
225 // raise() will handle differences between top level and child windows, and requesting focus
226 if (!blockedByModal())
227 raise();
228}
229
243
245{
246 return qApp->applicationState() > Qt::ApplicationHidden
247 && window()->isVisible()
248 && !window()->geometry().isEmpty();
249}
250
260
262{
263 const QRect rect = geometry();
264 jint x = 0, y = 0, w = -1, h = -1;
265 if (!rect.isNull()) {
266 x = rect.x();
267 y = rect.y();
268 w = std::max(rect.width(), 1);
269 h = std::max(rect.height(), 1);
270 }
271
272 const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
273 const bool isOpaque = !format().hasAlpha() && qFuzzyCompare(window()->opacity(), 1.0);
274
275 m_nativeQtWindow.callMethod<void>("createSurface", windowStaysOnTop, x, y, w, h, 32, isOpaque,
277 m_surfaceCreated = true;
278}
279
281{
282 if (m_surfaceCreated) {
283 m_nativeQtWindow.callMethod<void>("destroySurface");
284 m_surfaceCreated = false;
285 }
286}
287
289{
290 if (!m_surfaceCreated)
291 return;
292
293 jint x = 0;
294 jint y = 0;
295 jint w = -1;
296 jint h = -1;
297 if (!geometry.isNull()) {
298 x = geometry.x();
299 y = geometry.y();
300 w = geometry.width();
301 h = geometry.height();
302 }
303 m_nativeQtWindow.callMethod<void>("setGeometry", x, y, w, h);
304}
305
306void QAndroidPlatformWindow::onSurfaceChanged(QtJniTypes::Surface surface)
307{
308 lockSurface();
310 if (m_androidSurfaceObject.isValid()) // wait until we have a valid surface to draw into
313
314 if (m_androidSurfaceObject.isValid()) {
315 // repaint the window, when we have a valid surface
316 sendExpose();
317 }
318}
319
321{
322 QRect availableGeometry = screen()->availableGeometry();
323 if (!geometry().isNull() && !availableGeometry.isNull()) {
325 QRegion(QRect(QPoint(), geometry().size())));
326 }
327}
328
330{
331 QWindow *modalWindow = QGuiApplication::modalWindow();
332 return modalWindow && modalWindow != window();
333}
334
336{
337 // Returns true if the window is a wrapper for a foreign window solely to allow embedding Qt
338 // into a native Android app, in which case we should not try to control it more than we "need" to
339 return !QtAndroid::isQtApplication() && window()->isTopLevel();
340}
341
342void QAndroidPlatformWindow::setSurface(JNIEnv *env, jobject object, jint windowId,
343 QtJniTypes::Surface surface)
344{
345 Q_UNUSED(env)
346 Q_UNUSED(object)
347
348 if (!qGuiApp)
349 return;
350
351 const QList<QWindow*> windows = qGuiApp->allWindows();
352 for (QWindow * window : windows) {
353 if (!window->handle())
354 continue;
355 QAndroidPlatformWindow *platformWindow =
356 static_cast<QAndroidPlatformWindow *>(window->handle());
357 if (platformWindow->nativeViewId() == windowId)
358 platformWindow->onSurfaceChanged(surface);
359 }
360}
361
362void QAndroidPlatformWindow::windowFocusChanged(JNIEnv *env, jobject object,
363 jboolean focus, jint windowId)
364{
365 Q_UNUSED(env)
366 Q_UNUSED(object)
368 Q_ASSERT_X(window, "QAndroidPlatformWindow", "windowFocusChanged event window should exist");
369 if (focus) {
371 } else if (!focus && window == qGuiApp->focusWindow()) {
372 // Clear focus if current window has lost focus
374 }
375}
376
378{
379 if (!env.registerNativeMethods(QtJniTypes::Traits<QtJniTypes::QtWindow>::className(),
380 {
381 Q_JNI_NATIVE_SCOPED_METHOD(setSurface, QAndroidPlatformWindow),
382 Q_JNI_NATIVE_SCOPED_METHOD(windowFocusChanged, QAndroidPlatformWindow)
383 })) {
384 qCCritical(lcQpaWindow) << "RegisterNatives failed for"
385 << QtJniTypes::Traits<QtJniTypes::QtWindow>::className();
386 return false;
387 }
388 return true;
389}
390
void lower(QAndroidPlatformWindow *window)
void raise(QAndroidPlatformWindow *window)
QRect availableGeometry() const override
Reimplement in subclass to return the pixel geometry of the available space This normally is the desk...
void removeWindow(QAndroidPlatformWindow *window)
void addWindow(QAndroidPlatformWindow *window)
void propagateSizeHints() override
Reimplement to propagate the size hints of the QWindow.
void setNativeGeometry(const QRect &geometry)
virtual void applicationStateChanged(Qt::ApplicationState)
void setWindowFlags(Qt::WindowFlags flags) override
Requests setting the window flags of this surface to flags.
void setWindowState(Qt::WindowStates state) override
Requests setting the window state of this surface to type.
QtJniTypes::QtWindow nativeWindow() const
void onSurfaceChanged(QtJniTypes::Surface surface)
bool isExposed() const override
Returns if this window is exposed in the windowing system.
SurfaceContainer m_surfaceContainerType
QAndroidPlatformScreen * platformScreen() const
Qt::WindowFlags windowFlags() const
void requestActivateWindow() override
Reimplement to let Qt be able to request activation/focus for a window.
static bool registerNatives(QJniEnvironment &env)
QtJniTypes::QtWindow m_nativeParentQtWindow
QtJniTypes::Surface m_androidSurfaceObject
QtJniTypes::QtWindow m_nativeQtWindow
void setVisible(bool visible) override
Reimplemented in subclasses to show the surface if visible is true, and hide it if visible is false.
void setParent(const QPlatformWindow *window) override
This function is called to enable native child window in QPA.
void lower() override
Reimplement to be able to let Qt lower windows to the bottom of the desktop.
WId winId() const override
Reimplement in subclasses to return a handle to the native window.
void raise() override
Reimplement to be able to let Qt raise windows to the top of the desktop.
void setGeometry(const QRect &rect) override
This function is called by Qt whenever a window is moved or resized using the QWindow API.
QMargins safeAreaMargins() const override
The safe area margins of a window represent the area that is safe to place content within,...
static QWindow * modalWindow()
Returns the most recently shown modal window.
\inmodule QtCore
\inmodule QtCore
\inmodule QtCore
Definition qmargins.h:24
virtual QRect availableGeometry() const
Reimplement in subclass to return the pixel geometry of the available space This normally is the desk...
QSurface * surface() const
The QPlatformWindow class provides an abstraction for top-level windows.
virtual void setVisible(bool visible)
Reimplemented in subclasses to show the surface if visible is true, and hide it if visible is false.
QWindow * window() const
Returns the window which belongs to the QPlatformWindow.
QPlatformScreen * screen() const override
Returns the platform screen handle corresponding to this platform window, or null if the window is no...
virtual void setGeometry(const QRect &rect)
This function is called by Qt whenever a window is moved or resized using the QWindow API.
virtual void setWindowState(Qt::WindowStates state)
Requests setting the window state of this surface to type.
virtual QSurfaceFormat format() const override
Returns the actual surface format of the window.
virtual QRect geometry() const
Returns the current geometry of a window.
virtual QMargins safeAreaMargins() const
The safe area margins of a window represent the area that is safe to place content within,...
static QRect initialGeometry(const QWindow *w, const QRect &initialGeometry, int defaultWidth, int defaultHeight, const QScreen **resultingScreenReturn=nullptr)
Helper function to get initial geometry on windowing systems which do not do smart positioning and al...
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr bool isEmpty() const noexcept
Returns true if the rectangle is empty, otherwise returns false.
Definition qrect.h:167
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:164
constexpr int bottom() const noexcept
Returns the y-coordinate of the rectangle's bottom edge.
Definition qrect.h:182
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:176
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:173
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
constexpr int right() const noexcept
Returns the x-coordinate of the rectangle's right edge.
Definition qrect.h:179
The QRegion class specifies a clip region for a painter.
Definition qregion.h:27
QPlatformScreen * handle() const
Get the platform screen handle.
Definition qscreen.cpp:83
@ RasterSurface
Definition qsurface.h:31
static bool flushWindowSystemEvents(QEventLoop::ProcessEventsFlags flags=QEventLoop::AllEvents)
Make Qt Gui process all events on the event queue immediately.
static void handleFocusWindowChanged(QWindow *window, Qt::FocusReason r=Qt::OtherFocusReason)
static void handleGeometryChange(QWindow *window, const QRect &newRect)
static bool handleExposeEvent(QWindow *window, const QRegion &region)
\inmodule QtGui
Definition qwindow.h:63
Qt::WindowFlags flags
the window flags of the window
Definition qwindow.h:79
bool focus
[0]
rect
[4]
else opt state
[0]
T toNativePixels(const T &value, const C *context)
T fromNativePixels(const T &value, const C *context)
Combined button and popup list for selecting options.
AndroidBackendRegister * backendRegister()
@ SYSTEM_UI_VISIBILITY_TRANSLUCENT
@ SYSTEM_UI_VISIBILITY_FULLSCREEN
@ SYSTEM_UI_VISIBILITY_NORMAL
void setSystemUiVisibility(SystemUiVisibility uiVisibility)
QWindow * windowFromId(int windowId)
bool isQtApplication()
@ WindowFullScreen
Definition qnamespace.h:255
@ WindowNoState
Definition qnamespace.h:252
@ WindowMaximized
Definition qnamespace.h:254
ApplicationState
Definition qnamespace.h:262
@ ApplicationHidden
Definition qnamespace.h:264
@ Widget
Definition qnamespace.h:206
@ Popup
Definition qnamespace.h:211
@ Window
Definition qnamespace.h:207
@ WindowStaysOnTopHint
Definition qnamespace.h:233
@ Dialog
Definition qnamespace.h:208
@ Sheet
Definition qnamespace.h:209
@ MaximizeUsingFullscreenGeometryHint
Definition qnamespace.h:237
@ ActiveWindowFocusReason
QT_BEGIN_NAMESPACE Q_DECLARE_JNI_CLASS(QtInputConnectionListener, "org/qtproject/qt/android/QtInputConnection$QtInputConnectionListener") QAndroidPlatformWindow
#define qApp
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
#define qGuiApp
#define Q_LOGGING_CATEGORY(name,...)
#define qCCritical(category,...)
#define qCDebug(category,...)
GLint GLint GLint GLint GLint x
[0]
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei width
GLenum type
GLbitfield flags
GLint y
GLfloat GLfloat GLfloat GLfloat h
#define Q_ASSERT_X(cond, x, msg)
Definition qrandom.cpp:48
Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept
#define Q_UNUSED(x)
edit isVisible()
w setWindowState(w->windowState() ^ Qt::WindowFullScreen)
[0]
aWidget window() -> setWindowTitle("New Window Title")
[2]