4package org.qtproject.qt.android;
6import android.annotation.SuppressLint;
7import android.app.ActionBar;
8import android.app.Activity;
9import android.content.Context;
10import android.content.res.TypedArray;
11import android.graphics.Insets;
13import android.view.DisplayCutout;
14import android.view.GestureDetector;
15import android.view.MotionEvent;
16import android.view.Surface;
17import android.view.View;
18import android.view.ViewGroup;
19import android.view.ViewTreeObserver;
20import android.view.Window;
21import android.view.WindowInsets;
22import android.view.WindowInsetsController;
23import android.os.Build;
25import java.util.HashMap;
27@SuppressLint(
"ViewConstructor")
29 private View m_surfaceContainer;
30 private View m_nativeView;
31 private final HashMap<Integer, QtWindow> m_childWindows =
new HashMap<>();
32 private QtWindow m_parentWindow;
33 private GestureDetector m_gestureDetector;
34 private final QtEditText m_editText;
35 private boolean m_editTextFocusInitialized =
false;
37 private boolean m_firstSafeMarginsDelivered =
false;
38 private int m_actionBarHeight = -1;
40 private static native
void setSurface(
int windowId, Surface surface);
41 private static native
void safeAreaMarginsChanged(Insets insets,
int id);
42 static native
void windowFocusChanged(
boolean hasFocus,
int id);
45 QtWindow(
Context context,
boolean isForeignWindow, QtWindow parentWindow,
46 QtInputConnection.QtInputConnectionListener listener)
49 setId(View.generateViewId());
50 m_inputConnectionListener = listener;
52 setFocusableInTouchMode(
true);
53 setDefaultFocusHighlightEnabled(
false);
54 setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
63 if (!isForeignWindow &&
context instanceof Activity) {
65 m_editText =
new QtEditText(
context, listener);
66 m_editText.setFocusable(
false);
67 m_editText.setFocusableInTouchMode(
false);
68 m_editText.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO);
69 LayoutParams layoutParams =
new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
70 ViewGroup.LayoutParams.WRAP_CONTENT);
71 QtNative.runAction(() -> addView(m_editText, layoutParams));
78 new GestureDetector(
context,
new GestureDetector.SimpleOnGestureListener() {
80 public void onLongPress(MotionEvent event) {
81 QtInputDelegate.longPress(getId(), (int) event.getX(), (int) event.getY());
84 m_gestureDetector.setIsLongpressEnabled(
true);
87 registerSafeAreaMarginsListener();
90 void registerSafeAreaMarginsListener()
95 setOnApplyWindowInsetsListener((
view, insets) -> {
96 WindowInsets windowInsets =
view.onApplyWindowInsets(insets);
97 reportSafeAreaMargins(windowInsets, getId());
103 if (isAttachedToWindow()) {
104 WindowInsets insets = getRootWindowInsets();
105 if (insets !=
null) {
106 getRootView().post(() -> reportSafeAreaMargins(insets, getId()));
107 m_firstSafeMarginsDelivered =
true;
110 addOnAttachStateChangeListener(
new View.OnAttachStateChangeListener() {
112 public void onViewAttachedToWindow(View view) {
113 view.removeOnAttachStateChangeListener(this);
114 view.requestApplyInsets();
118 public void onViewDetachedFromWindow(View
view) {}
123 if (!m_firstSafeMarginsDelivered) {
124 ViewTreeObserver.OnPreDrawListener listener =
new ViewTreeObserver.OnPreDrawListener() {
126 public boolean onPreDraw() {
127 if (isAttachedToWindow()) {
128 WindowInsets insets = getRootWindowInsets();
129 if (insets !=
null) {
130 getViewTreeObserver().removeOnPreDrawListener(
this);
131 getRootView().post(() -> reportSafeAreaMargins(insets, getId()));
132 m_firstSafeMarginsDelivered =
true;
137 requestApplyInsets();
142 getViewTreeObserver().addOnPreDrawListener(listener);
145 addOnLayoutChangeListener((
view, l,
t,
r,
b, oldl, oldt, oldr, oldb) -> {
146 WindowInsets insets = getRootWindowInsets();
148 getRootView().post(() -> reportSafeAreaMargins(insets, getId()));
152 @SuppressWarnings(
"deprecation")
153 Insets getSafeInsets(
View view, WindowInsets insets)
155 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
156 int types = WindowInsets.Type.displayCutout() | WindowInsets.Type.systemBars();
157 return insets.getInsets(types);
161 int left = insets.getSystemWindowInsetLeft();
162 int top = insets.getSystemWindowInsetTop();
163 int right = insets.getSystemWindowInsetRight();
164 int bottom = insets.getSystemWindowInsetBottom();
168 DisplayCutout cutout = insets.getDisplayCutout();
169 if (cutout !=
null) {
170 left = Math.max(
left, cutout.getSafeInsetLeft());
171 top = Math.max(
top, cutout.getSafeInsetTop());
172 right = Math.max(
right, cutout.getSafeInsetRight());
180 ActionBar actionBar = ((Activity) getContext()).getActionBar();
181 if (actionBar ==
null || !actionBar.isShowing()) {
182 int topWithoutActionBar = top - actionBarHeight();
183 if (topWithoutActionBar > 0)
184 top = topWithoutActionBar;
190 private void reportSafeAreaMargins(WindowInsets insets,
int id)
192 View rootView = getRootView();
194 int[] rootLocation =
new int[2];
195 rootView.getLocationOnScreen(rootLocation);
196 int rootX = rootLocation[0];
197 int rootY = rootLocation[1];
199 int[] windowLocation =
new int[2];
200 getLocationOnScreen(windowLocation);
201 int windowX = windowLocation[0];
202 int windowY = windowLocation[1];
206 int topOffset = windowY - rootY;
207 int rightOffset = (rootX + rootView.getWidth()) - (windowX + getWidth());
208 int bottomOffset = (rootY + rootView.getHeight()) - (windowY + getHeight());
211 Insets safeInsets = getSafeInsets(rootView, insets);
212 int left = Math.max(0, Math.min(safeInsets.left, safeInsets.left -
leftOffset));
213 int top = Math.max(0, Math.min(safeInsets.top, safeInsets.top - topOffset));
214 int right = Math.max(0, Math.min(safeInsets.right, safeInsets.right -
rightOffset));
215 int bottom = Math.max(0, Math.min(safeInsets.bottom, safeInsets.bottom - bottomOffset));
220 private int actionBarHeight()
222 if (m_actionBarHeight == -1) {
223 TypedArray ta = getContext().getTheme().obtainStyledAttributes(
224 new int[] { android.R.attr.actionBarSize });
226 m_actionBarHeight = ta.getDimensionPixelSize(0, 0);
231 return m_actionBarHeight;
236 QtNative.runAction(() -> setVisibility(visible ?
View.VISIBLE :
View.INVISIBLE));
240 public void onSurfaceChanged(Surface surface)
242 setSurface(getId(), surface);
246 public boolean onTouchEvent(MotionEvent
event)
250 if (!m_editTextFocusInitialized) {
251 m_editTextFocusInitialized =
true;
252 m_editText.setFocusable(
true);
253 m_editText.setFocusableInTouchMode(
true);
256 windowFocusChanged(
true, getId());
257 if (m_editText !=
null && m_inputConnectionListener !=
null)
258 m_inputConnectionListener.onEditTextChanged(m_editText);
260 QtInputDelegate.sendTouchEvent(
event, getId());
261 m_gestureDetector.onTouchEvent(
event);
266 public boolean onTrackballEvent(MotionEvent
event)
268 QtInputDelegate.sendTrackballEvent(
event, getId());
273 public boolean onGenericMotionEvent(MotionEvent
event)
275 return QtInputDelegate.sendGenericMotionEvent(
event, getId());
281 if (m_parentWindow !=
null)
282 m_parentWindow.removeChildWindow(getId());
286 void createSurface(
final boolean onTop,
287 final int imageDepth,
final boolean isOpaque,
288 final int surfaceContainerType)
290 QtNative.runAction(()-> {
291 if (m_surfaceContainer !=
null)
292 removeView(m_surfaceContainer);
294 if (surfaceContainerType == 0) {
295 m_surfaceContainer =
new QtSurface(getContext(), QtWindow.this,
298 m_surfaceContainer =
new QtTextureView(getContext(), QtWindow.this, isOpaque);
300 m_surfaceContainer.setLayoutParams(
new QtLayout.LayoutParams(
301 ViewGroup.LayoutParams.MATCH_PARENT,
302 ViewGroup.LayoutParams.MATCH_PARENT));
305 addView(m_surfaceContainer, 0);
310 void destroySurface()
312 QtNative.runAction(()-> {
313 if (m_surfaceContainer !=
null) {
314 removeView(m_surfaceContainer);
315 m_surfaceContainer =
null;
321 void setGeometry(
final int x,
final int y,
final int w,
final int h)
323 QtNative.runAction(()-> {
324 if (getContext() instanceof QtActivityBase)
325 setLayoutParams(
new QtLayout.LayoutParams(
w,
h,
x,
y));
329 void addChildWindow(QtWindow
window)
331 QtNative.runAction(()-> {
333 addView(
window, getChildCount());
337 void removeChildWindow(
int id)
339 QtNative.runAction(()-> {
340 if (m_childWindows.containsKey(
id))
341 removeView(m_childWindows.remove(
id));
348 QtNative.runAction(()-> {
349 if (m_nativeView !=
null)
350 removeView(m_nativeView);
353 m_nativeView.setLayoutParams(
new QtLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
354 ViewGroup.LayoutParams.MATCH_PARENT));
355 addView(m_nativeView);
360 void bringChildToFront(
int id)
362 QtNative.runAction(()-> {
365 if (getChildCount() > 0)
366 moveChild(
view, getChildCount() - 1);
372 void bringChildToBack(
int id) {
373 QtNative.runAction(()-> {
382 void removeNativeView()
384 QtNative.runAction(()-> {
385 if (m_nativeView !=
null) {
386 removeView(m_nativeView);
394 if (m_parentWindow == parentWindow)
397 if (m_parentWindow !=
null)
398 m_parentWindow.removeChildWindow(getId());
400 m_parentWindow = parentWindow;
401 if (m_parentWindow !=
null)
402 m_parentWindow.addChildWindow(
this);
406 void updateFocusedEditText()
408 if (m_editText !=
null && m_inputConnectionListener !=
null)
409 m_inputConnectionListener.onEditTextChanged(m_editText);
memberSheet setVisible(index, false)
static const QString context()
static const double leftOffset
static const double rightOffset
GLboolean GLboolean GLboolean b
GLint GLint GLint GLint GLint x
GLfloat GLfloat GLfloat w
[0]
GLdouble GLdouble GLdouble GLdouble top
GLfloat GLfloat GLfloat GLfloat h
static bool onTop(QWaylandQuickShellSurfaceItem *surf)
file setParent(multiPart)
if(foo.startsWith("("+type+") 0x")) ... QString hello("hello")
[0]