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
20 : QPlatformWindow(window), m_nativeQtWindow(nullptr),
21 m_surfaceContainerType(SurfaceContainer::TextureView), m_nativeParentQtWindow(nullptr),
22 m_androidSurfaceObject(nullptr)
23{
24 m_windowFlags = Qt::Widget;
25 m_windowState = Qt::WindowNoState;
26 // the surfaceType is overwritten in QAndroidPlatformOpenGLWindow ctor so let's save
27 // the fact that it's a raster window for now
28 m_isRaster = window->surfaceType() == QSurface::RasterSurface;
29 setWindowState(window->windowStates());
30
31 // the following is in relation to the virtual geometry
32 const bool forceMaximize = m_windowState & (Qt::WindowMaximized | Qt::WindowFullScreen);
33 const QRect nativeScreenGeometry = platformScreen()->availableGeometry();
34 if (forceMaximize) {
35 setGeometry(nativeScreenGeometry);
36 } else {
37 const QRect requestedNativeGeometry = QHighDpi::toNativePixels(window->geometry(), window);
38 const QRect availableDeviceIndependentGeometry = (window->parent())
39 ? window->parent()->geometry()
40 : QHighDpi::fromNativePixels(nativeScreenGeometry, window);
41 // initialGeometry returns in native pixels
42 const QRect finalNativeGeometry = QPlatformWindow::initialGeometry(
43 window, requestedNativeGeometry, availableDeviceIndependentGeometry.width(),
44 availableDeviceIndependentGeometry.height());
45 if (requestedNativeGeometry != finalNativeGeometry)
46 setGeometry(finalNativeGeometry);
47 }
48
49 if (isEmbeddingContainer())
50 return;
51
52 if (parent()) {
53 QAndroidPlatformWindow *androidParent = static_cast<QAndroidPlatformWindow*>(parent());
54 if (!androidParent->isEmbeddingContainer())
55 m_nativeParentQtWindow = androidParent->nativeWindow();
56 }
57
58 m_nativeQtWindow = QJniObject::construct<QtJniTypes::QtWindow>(
59 QNativeInterface::QAndroidApplication::context(),
60 m_nativeParentQtWindow,
62 m_nativeViewId = m_nativeQtWindow.callMethod<jint>("getId");
63
64 if (window->isTopLevel())
65 platformScreen()->addWindow(this);
66
67 static bool ok = false;
68 static const int value = qEnvironmentVariableIntValue("QT_ANDROID_SURFACE_CONTAINER_TYPE", &ok);
69 if (ok) {
70 static const SurfaceContainer type = static_cast<SurfaceContainer>(value);
71 if (type == SurfaceContainer::SurfaceView || type == SurfaceContainer::TextureView)
72 m_surfaceContainerType = type;
73 } else if (platformScreen()->windows().size() <= 1) {
74 // TODO should handle case where this changes at runtime -> need to change existing window
75 // into TextureView (or perhaps not, if the parent window would be SurfaceView, as long as
76 // onTop was false it would stay below the children)
77 m_surfaceContainerType = SurfaceContainer::SurfaceView;
78 }
79 qCDebug(lcQpaWindow) << "Window" << m_nativeViewId << "using surface container type"
80 << static_cast<int>(m_surfaceContainerType);
81}
82
88
89
91{
92 if (m_nativeParentQtWindow.isValid()) {
93 m_nativeParentQtWindow.callMethod<void>("bringChildToBack", nativeViewId());
94 return;
95 }
96 platformScreen()->lower(this);
97}
98
100{
101 if (m_nativeParentQtWindow.isValid()) {
102 m_nativeParentQtWindow.callMethod<void>("bringChildToFront", nativeViewId());
104 return;
105 }
107 platformScreen()->raise(this);
108}
109
111{
113 QRect availableGeometry = platformScreen()->availableGeometry();
114 return QMargins(availableGeometry.left(), availableGeometry.top(),
115 availableGeometry.right(), availableGeometry.bottom());
116 } else {
118 }
119}
120
126
128{
130 return;
131 m_nativeQtWindow.callMethod<void>("setVisible", visible);
132
133 if (visible) {
134 if (window()->isTopLevel()) {
139 } else if (m_windowState & Qt::WindowMaximized) {
140 setGeometry(platformScreen()->availableGeometry());
141 }
143 }
144 } else if (window()->isTopLevel() && window() == qGuiApp->focusWindow()) {
146 }
147
148 QRect availableGeometry = screen()->availableGeometry();
149 if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
151}
152
154{
155 if (m_windowState == state)
156 return;
157
160
161 if (window()->isVisible())
163}
164
166{
167 if (m_windowFlags == flags)
168 return;
169
171}
172
174{
175 return m_windowFlags;
176}
177
179{
180 using namespace QtJniTypes;
181
182 if (window) {
183 auto androidWindow = static_cast<const QAndroidPlatformWindow*>(window);
184 if (androidWindow->isEmbeddingContainer())
185 return;
186 // If we were a top level window, remove from screen
187 if (!m_nativeParentQtWindow.isValid())
189
190 const QtWindow parentWindow = androidWindow->nativeWindow();
191 // If this was a child window of another window, the java method takes care of that
192 m_nativeQtWindow.callMethod<void, QtWindow>("setParent", parentWindow.object());
193 m_nativeParentQtWindow = parentWindow;
194 } else if (QtAndroid::isQtApplication()) {
195 m_nativeQtWindow.callMethod<void, QtWindow>("setParent", nullptr);
197 platformScreen()->addWindow(this);
198 }
199}
200
202{
203 return m_nativeQtWindow.isValid() ? reinterpret_cast<WId>(m_nativeQtWindow.object()) : 0L;
204}
205
207{
208 return static_cast<QAndroidPlatformScreen *>(window()->screen()->handle());
209}
210
212{
213 //shut up warning from default implementation
214}
215
217{
218 // raise() will handle differences between top level and child windows, and requesting focus
219 if (!blockedByModal())
220 raise();
221}
222
236
238{
239 return qApp->applicationState() > Qt::ApplicationHidden
240 && window()->isVisible()
241 && !window()->geometry().isEmpty();
242}
243
253
255{
256 const QRect rect = geometry();
257 jint x = 0, y = 0, w = -1, h = -1;
258 if (!rect.isNull()) {
259 x = rect.x();
260 y = rect.y();
261 w = std::max(rect.width(), 1);
262 h = std::max(rect.height(), 1);
263 }
264
265 const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
266 const bool isOpaque = !format().hasAlpha() && qFuzzyCompare(window()->opacity(), 1.0);
267
268 m_nativeQtWindow.callMethod<void>("createSurface", windowStaysOnTop, x, y, w, h, 32, isOpaque,
270 m_surfaceCreated = true;
271}
272
274{
275 if (m_surfaceCreated) {
276 m_nativeQtWindow.callMethod<void>("destroySurface");
277 m_surfaceCreated = false;
278 }
279}
280
282{
283 if (!m_surfaceCreated)
284 return;
285
286 jint x = 0;
287 jint y = 0;
288 jint w = -1;
289 jint h = -1;
290 if (!geometry.isNull()) {
291 x = geometry.x();
292 y = geometry.y();
293 w = geometry.width();
294 h = geometry.height();
295 }
296 m_nativeQtWindow.callMethod<void>("setGeometry", x, y, w, h);
297}
298
299void QAndroidPlatformWindow::onSurfaceChanged(QtJniTypes::Surface surface)
300{
301 lockSurface();
303 if (m_androidSurfaceObject.isValid()) // wait until we have a valid surface to draw into
306
307 if (m_androidSurfaceObject.isValid()) {
308 // repaint the window, when we have a valid surface
309 sendExpose();
310 }
311}
312
314{
315 QRect availableGeometry = screen()->availableGeometry();
316 if (!geometry().isNull() && !availableGeometry.isNull()) {
318 QRegion(QRect(QPoint(), geometry().size())));
319 }
320}
321
323{
324 QWindow *modalWindow = QGuiApplication::modalWindow();
325 return modalWindow && modalWindow != window();
326}
327
329{
330 // Returns true if the window is a wrapper for a foreign window solely to allow embedding Qt
331 // into a native Android app, in which case we should not try to control it more than we "need" to
332 return !QtAndroid::isQtApplication() && window()->isTopLevel();
333}
334
335void QAndroidPlatformWindow::setSurface(JNIEnv *env, jobject object, jint windowId,
336 QtJniTypes::Surface surface)
337{
338 Q_UNUSED(env)
339 Q_UNUSED(object)
340
341 if (!qGuiApp)
342 return;
343
344 const QList<QWindow*> windows = qGuiApp->allWindows();
345 for (QWindow * window : windows) {
346 if (!window->handle())
347 continue;
348 QAndroidPlatformWindow *platformWindow =
349 static_cast<QAndroidPlatformWindow *>(window->handle());
350 if (platformWindow->nativeViewId() == windowId)
351 platformWindow->onSurfaceChanged(surface);
352 }
353}
354
355void QAndroidPlatformWindow::windowFocusChanged(JNIEnv *env, jobject object,
356 jboolean focus, jint windowId)
357{
358 Q_UNUSED(env)
359 Q_UNUSED(object)
361 Q_ASSERT_X(window, "QAndroidPlatformWindow", "windowFocusChanged event window should exist");
362 if (focus) {
364 } else if (!focus && window == qGuiApp->focusWindow()) {
365 // Clear focus if current window has lost focus
367 }
368}
369
371{
372 if (!env.registerNativeMethods(QtJniTypes::Traits<QtJniTypes::QtWindow>::className(),
373 {
374 Q_JNI_NATIVE_SCOPED_METHOD(setSurface, QAndroidPlatformWindow),
375 Q_JNI_NATIVE_SCOPED_METHOD(windowFocusChanged, QAndroidPlatformWindow)
376 })) {
377 qCCritical(lcQpaWindow) << "RegisterNatives failed for"
378 << QtJniTypes::Traits<QtJniTypes::QtWindow>::className();
379 return false;
380 }
381 return true;
382}
383
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.
QtJniTypes::QtInputDelegate qtInputDelegate()
@ 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
#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]