|
8 | 8 | import android.view.MenuItem; |
9 | 9 | import android.view.MotionEvent; |
10 | 10 | import android.view.View; |
| 11 | +import android.view.ViewTreeObserver; |
11 | 12 | import android.view.WindowInsets; |
| 13 | +import android.view.WindowInsetsAnimation; |
| 14 | +import android.view.WindowMetrics; |
12 | 15 | import android.view.inputmethod.EditorInfo; |
13 | 16 | import android.view.inputmethod.InputConnection; |
14 | 17 | import android.content.ClipData; |
|
18 | 21 | import android.content.res.TypedArray; |
19 | 22 | import android.graphics.BlendMode; |
20 | 23 | import android.graphics.BlendModeColorFilter; |
| 24 | +import android.graphics.Insets; |
21 | 25 | import android.graphics.PorterDuff; |
22 | 26 | import android.graphics.Rect; |
23 | 27 | import android.graphics.drawable.Drawable; |
|
31 | 35 | import android.widget.ImageView; |
32 | 36 | import android.widget.PopupWindow; |
33 | 37 | import android.view.inputmethod.BaseInputConnection; |
| 38 | +import android.os.Build; |
34 | 39 |
|
35 | 40 | class InputHandle extends ImageView { |
36 | 41 | private PopupWindow mPopupWindow; |
@@ -413,6 +418,87 @@ public void run() { |
413 | 418 | mInputView.setVisibility(View.VISIBLE); |
414 | 419 | } |
415 | 420 | }); |
| 421 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { |
| 422 | + activity.getWindow().getDecorView().getRootView() |
| 423 | + .setWindowInsetsAnimationCallback( |
| 424 | + new WindowInsetsAnimation.Callback( |
| 425 | + WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE) { |
| 426 | + @Override |
| 427 | + public WindowInsets onProgress(WindowInsets insets, |
| 428 | + java.util.List<WindowInsetsAnimation> runningAnimations) { |
| 429 | + mActivity.runOnUiThread(new Runnable() { |
| 430 | + @Override |
| 431 | + public void run() { |
| 432 | + Insets safeAreaInsets = insets.getInsets(WindowInsets.Type.systemBars()); |
| 433 | + Insets keyboardAreaInsets = insets.getInsets(WindowInsets.Type.ime()); |
| 434 | + Rect windowRect = get_view_rect(); |
| 435 | + |
| 436 | + SlintAndroidJavaHelper.setInsets( |
| 437 | + windowRect.top, windowRect.left, |
| 438 | + windowRect.bottom, windowRect.right, |
| 439 | + safeAreaInsets.top, safeAreaInsets.left, |
| 440 | + safeAreaInsets.bottom, safeAreaInsets.right, |
| 441 | + keyboardAreaInsets.top, keyboardAreaInsets.left, |
| 442 | + keyboardAreaInsets.bottom, keyboardAreaInsets.right); |
| 443 | + } |
| 444 | + }); |
| 445 | + return insets; |
| 446 | + } |
| 447 | + }); |
| 448 | + } else { |
| 449 | + activity.getWindow().getDecorView().getRootView().getViewTreeObserver() |
| 450 | + .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { |
| 451 | + @Override |
| 452 | + public void onGlobalLayout() { |
| 453 | + mActivity.runOnUiThread(new Runnable() { |
| 454 | + @Override |
| 455 | + public void run() { |
| 456 | + Rect windowRect = get_view_rect(); |
| 457 | + Rect safeAreaRect = get_safe_area(); |
| 458 | + |
| 459 | + // This is only an approximation, because SDK level < 30 doesn't provide |
| 460 | + // a way to get the keyboard area directly. |
| 461 | + Rect visibleRect = new Rect(); |
| 462 | + mActivity.getWindow().getDecorView().getRootView() |
| 463 | + .getWindowVisibleDisplayFrame(visibleRect); |
| 464 | + int keyboardBottom = windowRect.bottom - visibleRect.bottom; |
| 465 | + int keyboardLeft = windowRect.left - visibleRect.left; |
| 466 | + int keyboardTop = windowRect.top - visibleRect.top; |
| 467 | + int keyboardRight = windowRect.right - visibleRect.right; |
| 468 | + int max = Math.max(keyboardBottom, Math.max(keyboardLeft, |
| 469 | + Math.max(keyboardTop, keyboardRight))); |
| 470 | + |
| 471 | + // only take the largest value (it's probably always going to be bottom) |
| 472 | + if (max == keyboardBottom) { |
| 473 | + keyboardTop = 0; |
| 474 | + keyboardLeft = 0; |
| 475 | + keyboardRight = 0; |
| 476 | + } else if (max == keyboardLeft) { |
| 477 | + keyboardTop = 0; |
| 478 | + keyboardRight = 0; |
| 479 | + keyboardBottom = 0; |
| 480 | + } else if (max == keyboardTop) { |
| 481 | + keyboardLeft = 0; |
| 482 | + keyboardRight = 0; |
| 483 | + keyboardBottom = 0; |
| 484 | + } else { |
| 485 | + keyboardTop = 0; |
| 486 | + keyboardLeft = 0; |
| 487 | + keyboardBottom = 0; |
| 488 | + } |
| 489 | + |
| 490 | + SlintAndroidJavaHelper.setInsets( |
| 491 | + windowRect.top, windowRect.left, |
| 492 | + windowRect.bottom, windowRect.right, |
| 493 | + safeAreaRect.top, safeAreaRect.left, |
| 494 | + safeAreaRect.bottom, safeAreaRect.right, |
| 495 | + keyboardTop, keyboardLeft, |
| 496 | + keyboardBottom, keyboardRight); |
| 497 | + } |
| 498 | + }); |
| 499 | + } |
| 500 | + }); |
| 501 | + } |
416 | 502 | } |
417 | 503 |
|
418 | 504 | public void show_keyboard() { |
@@ -447,6 +533,10 @@ static public native void updateText(String text, int cursorPosition, int anchor |
447 | 533 |
|
448 | 534 | static public native void popupMenuAction(int id); |
449 | 535 |
|
| 536 | + static public native void setInsets(int window_top, int window_left, int window_bottom, int window_right, |
| 537 | + int safe_area_top, int safe_area_left, int safe_area_bottom, int safe_area_right, |
| 538 | + int keyboard_top, int keyboard_left, int keyboard_bottom, int keyboard_right); |
| 539 | + |
450 | 540 | public void set_imm_data(String text, int cursor_position, int anchor_position, int preedit_start, int preedit_end, |
451 | 541 | int cur_x, int cur_y, int anchor_x, int anchor_y, int cursor_height, int input_type, |
452 | 542 | boolean show_cursor_handles) { |
@@ -485,22 +575,39 @@ public int color_scheme() { |
485 | 575 | return nightModeFlags; |
486 | 576 | } |
487 | 577 |
|
488 | | - // Get the geometry of the view minus the system bars and the keyboard |
| 578 | + // Get the size of the window |
489 | 579 | public Rect get_view_rect() { |
490 | | - Rect rect = new Rect(); |
491 | | - mActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect); |
492 | | - // Note: `View.getRootWindowInsets` requires API level 23 or above |
493 | | - WindowInsets insets = mActivity.getWindow().getDecorView().getRootView().getRootWindowInsets(); |
494 | | - if (insets != null) { |
495 | | - int dx = rect.left - insets.getSystemWindowInsetLeft(); |
496 | | - int dy = rect.top - insets.getSystemWindowInsetTop(); |
497 | | - |
498 | | - rect.left -= dx; |
499 | | - rect.right -= dx; |
500 | | - rect.top -= dy; |
501 | | - rect.bottom -= dy; |
| 580 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { |
| 581 | + // On Android 11 and above, we can get the window bounds directly |
| 582 | + WindowMetrics metrics = mActivity.getWindowManager().getCurrentWindowMetrics(); |
| 583 | + return metrics.getBounds(); |
| 584 | + } else { |
| 585 | + View rootView = mActivity.getWindow().getDecorView().getRootView(); |
| 586 | + return new Rect(rootView.getLeft(), rootView.getTop(), rootView.getRight(), rootView.getBottom()); |
| 587 | + } |
| 588 | + } |
| 589 | + |
| 590 | + // On SDK level < 30, returns the inset for the safe area and the keyboard. |
| 591 | + // On SDK level >= 30, returns the inset for the safe area only. |
| 592 | + public Rect get_safe_area() { |
| 593 | + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { |
| 594 | + WindowMetrics metrics = mActivity.getWindowManager().getCurrentWindowMetrics(); |
| 595 | + WindowInsets insets = metrics.getWindowInsets(); |
| 596 | + Insets systemBars = insets.getInsets(WindowInsets.Type.systemBars()); |
| 597 | + return new Rect(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); |
| 598 | + } else { |
| 599 | + View decorView = mActivity.getWindow().getDecorView(); |
| 600 | + // Note: `View.getRootWindowInsets` requires API level 23 or above |
| 601 | + WindowInsets insets = decorView.getRootView().getRootWindowInsets(); |
| 602 | + if (insets != null) { |
| 603 | + return new Rect( |
| 604 | + insets.getStableInsetLeft(), |
| 605 | + insets.getStableInsetTop(), |
| 606 | + insets.getStableInsetRight(), |
| 607 | + insets.getStableInsetBottom()); |
| 608 | + } |
| 609 | + return new Rect(0, 0, 0, 0); |
502 | 610 | } |
503 | | - return rect; |
504 | 611 | } |
505 | 612 |
|
506 | 613 | public void show_action_menu() { |
|
0 commit comments