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(),
82 event.getMetaState());
85 m_gestureDetector.setIsLongpressEnabled(
true);
88 registerSafeAreaMarginsListener();
91 void registerSafeAreaMarginsListener()
96 setOnApplyWindowInsetsListener((
view, insets) -> {
97 WindowInsets windowInsets =
view.onApplyWindowInsets(insets);
98 reportSafeAreaMargins(windowInsets, getId());
104 if (isAttachedToWindow()) {
105 WindowInsets insets = getRootWindowInsets();
106 if (insets !=
null) {
107 getRootView().post(() -> reportSafeAreaMargins(insets, getId()));
108 m_firstSafeMarginsDelivered =
true;
111 addOnAttachStateChangeListener(
new View.OnAttachStateChangeListener() {
113 public void onViewAttachedToWindow(View view) {
114 view.removeOnAttachStateChangeListener(this);
115 view.requestApplyInsets();
119 public void onViewDetachedFromWindow(View
view) {}
124 if (!m_firstSafeMarginsDelivered) {
125 ViewTreeObserver.OnPreDrawListener listener =
new ViewTreeObserver.OnPreDrawListener() {
127 public boolean onPreDraw() {
128 if (isAttachedToWindow()) {
129 WindowInsets insets = getRootWindowInsets();
130 if (insets !=
null) {
131 getViewTreeObserver().removeOnPreDrawListener(
this);
132 getRootView().post(() -> reportSafeAreaMargins(insets, getId()));
133 m_firstSafeMarginsDelivered =
true;
138 requestApplyInsets();
143 getViewTreeObserver().addOnPreDrawListener(listener);
146 addOnLayoutChangeListener((
view, l,
t,
r,
b, oldl, oldt, oldr, oldb) -> {
147 WindowInsets insets = getRootWindowInsets();
149 getRootView().post(() -> reportSafeAreaMargins(insets, getId()));
153 @SuppressWarnings(
"deprecation")
154 Insets getSafeInsets(
View view, WindowInsets insets)
156 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
157 int types = WindowInsets.Type.displayCutout() | WindowInsets.Type.systemBars();
158 return insets.getInsets(types);
162 int left = insets.getSystemWindowInsetLeft();
163 int top = insets.getSystemWindowInsetTop();
164 int right = insets.getSystemWindowInsetRight();
165 int bottom = insets.getSystemWindowInsetBottom();
169 DisplayCutout cutout = insets.getDisplayCutout();
170 if (cutout !=
null) {
171 left = Math.max(
left, cutout.getSafeInsetLeft());
172 top = Math.max(
top, cutout.getSafeInsetTop());
173 right = Math.max(
right, cutout.getSafeInsetRight());
181 ActionBar actionBar = ((Activity) getContext()).getActionBar();
182 if (actionBar ==
null || !actionBar.isShowing()) {
183 int topWithoutActionBar = top - actionBarHeight();
184 if (topWithoutActionBar > 0)
185 top = topWithoutActionBar;
191 private void reportSafeAreaMargins(WindowInsets insets,
int id)
193 View rootView = getRootView();
195 int[] rootLocation =
new int[2];
196 rootView.getLocationOnScreen(rootLocation);
197 int rootX = rootLocation[0];
198 int rootY = rootLocation[1];
200 int[] windowLocation =
new int[2];
201 getLocationOnScreen(windowLocation);
202 int windowX = windowLocation[0];
203 int windowY = windowLocation[1];
207 int topOffset = windowY - rootY;
208 int rightOffset = (rootX + rootView.getWidth()) - (windowX + getWidth());
209 int bottomOffset = (rootY + rootView.getHeight()) - (windowY + getHeight());
212 Insets safeInsets = getSafeInsets(rootView, insets);
213 int left = Math.max(0, Math.min(safeInsets.left, safeInsets.left -
leftOffset));
214 int top = Math.max(0, Math.min(safeInsets.top, safeInsets.top - topOffset));
215 int right = Math.max(0, Math.min(safeInsets.right, safeInsets.right -
rightOffset));
216 int bottom = Math.max(0, Math.min(safeInsets.bottom, safeInsets.bottom - bottomOffset));
221 private int actionBarHeight()
223 if (m_actionBarHeight == -1) {
224 TypedArray ta = getContext().getTheme().obtainStyledAttributes(
225 new int[] { android.R.attr.actionBarSize });
227 m_actionBarHeight = ta.getDimensionPixelSize(0, 0);
232 return m_actionBarHeight;
237 QtNative.runAction(() -> setVisibility(visible ?
View.VISIBLE :
View.INVISIBLE));
241 public void onSurfaceChanged(Surface surface)
243 setSurface(getId(), surface);
247 public boolean onTouchEvent(MotionEvent
event)
251 if (!m_editTextFocusInitialized) {
252 m_editTextFocusInitialized =
true;
253 if (m_editText !=
null) {
254 m_editText.setFocusable(
true);
255 m_editText.setFocusableInTouchMode(
true);
259 windowFocusChanged(
true, getId());
260 if (m_editText !=
null && m_inputConnectionListener !=
null)
261 m_inputConnectionListener.onEditTextChanged(m_editText);
263 QtInputDelegate.sendTouchEvent(
event, getId());
264 if (m_gestureDetector !=
null)
265 m_gestureDetector.onTouchEvent(
event);
270 public boolean onTrackballEvent(MotionEvent
event)
272 QtInputDelegate.sendTrackballEvent(
event, getId());
277 public boolean onGenericMotionEvent(MotionEvent
event)
279 return QtInputDelegate.sendGenericMotionEvent(
event, getId());
283 protected void onAttachedToWindow()
285 super.onAttachedToWindow();
286 setOnDragListener(QtDragManager.getInstance());
290 protected void onDetachedFromWindow()
292 QtDragManager.getInstance().onSourceWindowDetached(
this);
293 setOnDragListener(
null);
294 super.onDetachedFromWindow();
300 if (m_parentWindow !=
null)
301 m_parentWindow.removeChildWindow(getId());
305 void createSurface(
final boolean onTop,
306 final int imageDepth,
final boolean isOpaque,
307 final int surfaceContainerType)
309 QtNative.runAction(()-> {
310 if (m_surfaceContainer !=
null)
311 removeView(m_surfaceContainer);
313 if (surfaceContainerType == 0) {
314 m_surfaceContainer =
new QtSurface(getContext(), QtWindow.this,
317 m_surfaceContainer =
new QtTextureView(getContext(), QtWindow.this, isOpaque);
319 m_surfaceContainer.setLayoutParams(
new QtLayout.LayoutParams(
320 ViewGroup.LayoutParams.MATCH_PARENT,
321 ViewGroup.LayoutParams.MATCH_PARENT));
324 addView(m_surfaceContainer, 0);
329 void destroySurface()
331 QtNative.runAction(()-> {
332 if (m_surfaceContainer !=
null) {
333 removeView(m_surfaceContainer);
334 m_surfaceContainer =
null;
340 void setGeometry(
final int x,
final int y,
final int w,
final int h)
342 QtNative.runAction(()-> {
343 if (getContext() instanceof QtActivityBase)
344 setLayoutParams(
new QtLayout.LayoutParams(
w,
h,
x,
y));
348 void addChildWindow(QtWindow
window)
350 QtNative.runAction(()-> {
352 addView(
window, getChildCount());
356 void removeChildWindow(
int id)
358 QtNative.runAction(()-> {
359 if (m_childWindows.containsKey(
id))
360 removeView(m_childWindows.remove(
id));
367 QtNative.runAction(()-> {
368 if (m_nativeView !=
null)
369 removeView(m_nativeView);
372 m_nativeView.setLayoutParams(
new QtLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
373 ViewGroup.LayoutParams.MATCH_PARENT));
374 addView(m_nativeView);
379 void bringChildToFront(
int id)
381 QtNative.runAction(()-> {
384 if (getChildCount() > 0)
385 moveChild(
view, getChildCount() - 1);
391 void bringChildToBack(
int id) {
392 QtNative.runAction(()-> {
401 void removeNativeView()
403 QtNative.runAction(()-> {
404 if (m_nativeView !=
null) {
405 removeView(m_nativeView);
413 if (m_parentWindow == parentWindow)
416 if (m_parentWindow !=
null)
417 m_parentWindow.removeChildWindow(getId());
419 m_parentWindow = parentWindow;
420 if (m_parentWindow !=
null)
421 m_parentWindow.addChildWindow(
this);
425 void updateFocusedEditText()
427 if (m_editText !=
null && m_inputConnectionListener !=
null)
428 m_inputConnectionListener.onEditTextChanged(m_editText);
memberSheet setVisible(index, false)
static const QString context()
Napi::TypedArray TypedArray
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]