Skip to content

Commit b56cadf

Browse files
committed
Merge remote-tracking branch 'origin/main' into feature/passkey-support
2 parents bcb728b + 1db0e0a commit b56cadf

5 files changed

Lines changed: 131 additions & 28 deletions

File tree

docs/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ Keepass2Android is a password manager app. It allows to store and retrieve passw
66
The password database file can be synchronized across different devices. This works best using one of the built-in cloud storage options, but can also be performed with third-party apps. Keepass2Android is compatible with KeePass 2.x and KeepassXC on PCs as well as many other KeePass ports for a variety of platforms.
77

88
# Where to get it?
9-
Regular stable releases of Keepass2Android are available on [Google Play](https://play.google.com/store/apps/details?id=keepass2android.keepass2android).
9+
Regular stable releases of Keepass2Android are available on Google Play.
10+
* [Keepass2Android](https://play.google.com/store/apps/details?id=keepass2android.keepass2android)
11+
* [Keepass2Android Offline](https://play.google.com/store/apps/details?id=keepass2android.keepass2android_nonet)
1012

1113
Beta-releases can be obtained by opting in to the [Beta testing channel](https://play.google.com/apps/testing/keepass2android.keepass2android) or [Beta testing channel for Keepass2Android Offline](https://play.google.com/apps/testing/keepass2android.keepass2android_nonet).
1214

src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KP2AKeyboard.java

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import android.media.AudioManager;
3535
import android.net.Uri;
3636
import android.os.Build;
37+
import android.view.WindowInsets;
3738
import android.os.Debug;
3839
import android.os.Handler;
3940
import android.os.Message;
@@ -51,6 +52,7 @@
5152
import android.view.HapticFeedbackConstants;
5253
import android.view.KeyEvent;
5354
import android.view.View;
55+
import android.view.ViewGroup;
5456
import android.view.Window;
5557
import android.view.WindowManager;
5658
import android.view.inputmethod.CompletionInfo;
@@ -543,6 +545,11 @@ public void onConfigurationChanged(Configuration conf) {
543545
mConfigurationChanging = true;
544546
super.onConfigurationChanged(conf);
545547
mConfigurationChanging = false;
548+
// Re-apply nav bar padding after orientation change; post it so the
549+
// new window layout has settled before we read the insets.
550+
mHandler.post(new Runnable() {
551+
@Override public void run() { scheduleApplyNavBarInsetsToInputViewLayout(); }
552+
});
546553
}
547554

548555
@Override
@@ -628,6 +635,7 @@ public void onStartInputView(EditorInfo attribute, boolean restarting) {
628635
checkReCorrectionOnStart();
629636

630637
tryKp2aAutoFill(attribute);
638+
scheduleApplyNavBarInsetsToInputViewLayout();
631639

632640
if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
633641
}
@@ -1036,6 +1044,62 @@ public void setCandidatesViewShown(boolean shown) {
10361044
setCandidatesViewShownInternal(shown, true /* needsInputViewShown */);
10371045
}
10381046

1047+
@Override
1048+
public void onWindowShown() {
1049+
super.onWindowShown();
1050+
scheduleApplyNavBarInsetsToInputViewLayout();
1051+
}
1052+
1053+
private void scheduleApplyNavBarInsetsToInputViewLayout() {
1054+
applyNavBarInsetsToInputViewLayout();
1055+
mHandler.postDelayed(new Runnable() {
1056+
@Override
1057+
public void run() {
1058+
applyNavBarInsetsToInputViewLayout();
1059+
}
1060+
}, 100);
1061+
}
1062+
1063+
private void applyNavBarInsetsToInputViewLayout() {
1064+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) return;
1065+
final View inputView = mKeyboardSwitcher.getInputView();
1066+
if (inputView == null) return;
1067+
1068+
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
1069+
android.view.WindowMetrics metrics = wm.getCurrentWindowMetrics();
1070+
android.graphics.Insets nav =
1071+
metrics.getWindowInsets().getInsets(WindowInsets.Type.navigationBars());
1072+
1073+
android.view.Window win = getWindow() != null ? getWindow().getWindow() : null;
1074+
View decor = win != null ? win.getDecorView() : null;
1075+
int decorWidth = decor != null ? decor.getWidth() : 0;
1076+
int decorHeight = decor != null ? decor.getHeight() : 0;
1077+
int displayWidth = metrics.getBounds().width();
1078+
int displayHeight = metrics.getBounds().height();
1079+
1080+
final int tolerancePx = 2;
1081+
boolean windowAlreadyExcludesHorizontalNav = decorWidth > 0
1082+
&& decorWidth <= (displayWidth - nav.left - nav.right + tolerancePx);
1083+
1084+
int effectiveLeft = windowAlreadyExcludesHorizontalNav ? 0 : nav.left;
1085+
int effectiveRight = windowAlreadyExcludesHorizontalNav ? 0 : nav.right;
1086+
// Do not infer bottom-nav exclusion from decor height: IME windows are naturally
1087+
// shorter than display height, so that heuristic wrongly drops bottom inset.
1088+
int effectiveBottom = nav.bottom;
1089+
1090+
ViewGroup.LayoutParams lp = inputView.getLayoutParams();
1091+
if (lp instanceof ViewGroup.MarginLayoutParams) {
1092+
ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) lp;
1093+
if (mlp.leftMargin != effectiveLeft || mlp.rightMargin != effectiveRight
1094+
|| mlp.bottomMargin != effectiveBottom) {
1095+
mlp.leftMargin = effectiveLeft;
1096+
mlp.rightMargin = effectiveRight;
1097+
mlp.bottomMargin = effectiveBottom;
1098+
inputView.setLayoutParams(mlp);
1099+
}
1100+
}
1101+
}
1102+
10391103
@Override
10401104
public void onComputeInsets(InputMethodService.Insets outInsets) {
10411105
super.onComputeInsets(outInsets);

src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/KeyboardSwitcher.java

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,9 @@
1919
import android.content.SharedPreferences;
2020
import android.content.res.Configuration;
2121
import android.content.res.Resources;
22-
import android.os.Build;
2322
import android.preference.PreferenceManager;
2423
import android.util.Log;
2524
import android.view.InflateException;
26-
import android.view.View;
27-
import android.view.WindowInsets;
2825

2926
import java.lang.ref.SoftReference;
3027
import java.util.Arrays;
@@ -532,27 +529,6 @@ private void changeLatinKeyboardView(int newLayout, boolean forceReset) {
532529
}
533530
}
534531
mInputView.setOnKeyboardActionListener(mInputMethodService);
535-
536-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
537-
mInputView.setOnApplyWindowInsetsListener(new View.OnApplyWindowInsetsListener() {
538-
@Override
539-
public WindowInsets onApplyWindowInsets(View v, WindowInsets insets) {
540-
// Untere Systembar-Höhe holen
541-
int insetBottom = insets.getSystemWindowInsetBottom();
542-
543-
// Padding nur unten anpassen
544-
v.setPadding(
545-
v.getPaddingLeft(),
546-
v.getPaddingTop(),
547-
v.getPaddingRight(),
548-
insetBottom
549-
);
550-
551-
// Insets normal weiterreichen
552-
return insets;
553-
}
554-
});
555-
}
556532

557533
mLayoutId = newLayout;
558534
}

src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboard.java

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,13 @@ public class LatinKeyboard extends Keyboard {
9090
private int mPrefLetterY;
9191
private int mPrefDistance;
9292

93+
private int[] mOriginalKeyX;
94+
private int[] mOriginalKeyWidth;
95+
private int[] mOriginalKeyGap;
96+
private int mOriginalMinWidth = -1;
97+
private int mDynamicMinWidth = -1;
98+
private int[] mAllKeyIndices;
99+
93100
// TODO: generalize for any keyboardId
94101
private boolean mIsBlackSym;
95102

@@ -786,10 +793,52 @@ public int[] getNearestKeys(int x, int y) {
786793
if (mCurrentlyInSpace) {
787794
return mSpaceKeyIndexArray;
788795
} else {
789-
// Avoid dead pixels at edges of the keyboard
790-
return super.getNearestKeys(Math.max(0, Math.min(x, getMinWidth() - 1)),
791-
Math.max(0, Math.min(y, getHeight() - 1)));
796+
// Avoid relying on Keyboard's internal nearest-key grid after dynamic resize,
797+
// as those caches are private and not rebuildable from here.
798+
if (mAllKeyIndices == null || mAllKeyIndices.length != getKeys().size()) {
799+
mAllKeyIndices = new int[getKeys().size()];
800+
for (int i = 0; i < mAllKeyIndices.length; i++) {
801+
mAllKeyIndices[i] = i;
802+
}
803+
}
804+
return mAllKeyIndices;
805+
}
806+
}
807+
808+
@Override
809+
public int getMinWidth() {
810+
return mDynamicMinWidth > 0 ? mDynamicMinWidth : super.getMinWidth();
811+
}
812+
813+
public void resizeToWidth(int newWidth) {
814+
if (newWidth <= 0) return;
815+
final List<Key> keys = getKeys();
816+
if (keys == null || keys.isEmpty()) return;
817+
818+
if (mOriginalKeyX == null || mOriginalKeyX.length != keys.size()) {
819+
mOriginalKeyX = new int[keys.size()];
820+
mOriginalKeyWidth = new int[keys.size()];
821+
mOriginalKeyGap = new int[keys.size()];
822+
mOriginalMinWidth = super.getMinWidth();
823+
for (int i = 0; i < keys.size(); i++) {
824+
Key key = keys.get(i);
825+
mOriginalKeyX[i] = key.x;
826+
mOriginalKeyWidth[i] = key.width;
827+
mOriginalKeyGap[i] = key.gap;
828+
}
829+
}
830+
831+
final int baseWidth = Math.max(1, mOriginalMinWidth);
832+
final float scale = ((float) newWidth) / baseWidth;
833+
int maxRight = 0;
834+
for (int i = 0; i < keys.size(); i++) {
835+
Key key = keys.get(i);
836+
key.x = Math.max(0, Math.round(mOriginalKeyX[i] * scale));
837+
key.width = Math.max(1, Math.round(mOriginalKeyWidth[i] * scale));
838+
key.gap = Math.max(0, Math.round(mOriginalKeyGap[i] * scale));
839+
maxRight = Math.max(maxRight, key.x + key.width);
792840
}
841+
mDynamicMinWidth = Math.max(1, maxRight);
793842
}
794843

795844
private int indexOf(int code) {

src/java/KP2ASoftkeyboard_AS/app/src/main/java/keepass2android/softkeyboard/LatinKeyboardBaseView.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -748,6 +748,18 @@ private void computeProximityThreshold(Keyboard keyboard) {
748748
@Override
749749
public void onSizeChanged(int w, int h, int oldw, int oldh) {
750750
super.onSizeChanged(w, h, oldw, oldh);
751+
if (mKeyboard instanceof LatinKeyboard) {
752+
final int newKeyboardWidth = Math.max(1, w - getPaddingLeft() - getPaddingRight());
753+
((LatinKeyboard)mKeyboard).resizeToWidth(newKeyboardWidth);
754+
mKeys = mKeyDetector.setKeyboard(mKeyboard, -getPaddingLeft(),
755+
-getPaddingTop() + mVerticalCorrection);
756+
for (PointerTracker tracker : mPointerTrackers) {
757+
tracker.setKeyboard(mKeys, mKeyHysteresisDistance);
758+
}
759+
computeProximityThreshold(mKeyboard);
760+
mKeyboardChanged = true;
761+
invalidateAllKeys();
762+
}
751763
// Release the buffer, if any and it will be reallocated on the next draw
752764
mBuffer = null;
753765
}

0 commit comments

Comments
 (0)