mirror of
https://github.com/Julow/Unexpected-Keyboard.git
synced 2025-08-18 16:09:14 +02:00
Compare commits
10 Commits
1.30.1
...
edge-to-ed
Author | SHA1 | Date | |
---|---|---|---|
|
87da258c5b | ||
|
dd99579a90 | ||
|
cc3d2591a7 | ||
|
ede983aef7 | ||
|
d396af9240 | ||
|
185ddcec60 | ||
|
f13af579c1 | ||
|
da957d534b | ||
|
139ff760e0 | ||
|
3162a5abe6 |
@@ -10,11 +10,13 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
<meta-data android:name="android.view.im" android:resource="@xml/method"/>
|
<meta-data android:name="android.view.im" android:resource="@xml/method"/>
|
||||||
</service>
|
</service>
|
||||||
<activity android:name="juloo.keyboard2.SettingsActivity" android:icon="@mipmap/ic_launcher" android:label="@string/settings_activity_label" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true">
|
|
||||||
|
<activity android:name="juloo.keyboard2.SettingsActivity" android:icon="@mipmap/ic_launcher" android:label="@string/settings_activity_label" android:theme="@style/settingsTheme" android:exported="true" android:directBootAware="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name="juloo.keyboard2.LauncherActivity" android:icon="@mipmap/ic_launcher" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true">
|
<activity android:name="juloo.keyboard2.LauncherActivity" android:icon="@mipmap/ic_launcher" android:theme="@style/appTheme" android:exported="true" android:directBootAware="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true">
|
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true" android:fitsSystemWindows="true">
|
||||||
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical">
|
<LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical">
|
||||||
<TextView style="@style/paragraph" android:text="@string/launcher_description"/>
|
<TextView style="@style/paragraph" android:text="@string/launcher_description"/>
|
||||||
<Button style="@style/paragraph" android:text="@string/launcher_button_imesettings" android:onClick="launch_imesettings" android:layout_width="wrap_content"/>
|
<Button style="@style/paragraph" android:text="@string/launcher_button_imesettings" android:onClick="launch_imesettings" android:layout_width="wrap_content"/>
|
||||||
|
@@ -80,4 +80,9 @@
|
|||||||
<item name="android:orientation">horizontal</item>
|
<item name="android:orientation">horizontal</item>
|
||||||
</style>
|
</style>
|
||||||
<style name="appTheme" parent="@android:style/Theme.DeviceDefault.DayNight"/>
|
<style name="appTheme" parent="@android:style/Theme.DeviceDefault.DayNight"/>
|
||||||
|
<style name="settingsTheme" parent="appTheme">
|
||||||
|
<!-- Setting this in the activity theme so it propagate to nested
|
||||||
|
preference screens. -->
|
||||||
|
<item name="android:fitsSystemWindows">true</item>
|
||||||
|
</style>
|
||||||
</resources>
|
</resources>
|
||||||
|
@@ -6,5 +6,9 @@
|
|||||||
<dimen name="emoji_text_size">28dp</dimen>
|
<dimen name="emoji_text_size">28dp</dimen>
|
||||||
<dimen name="clipboard_view_height">300dp</dimen>
|
<dimen name="clipboard_view_height">300dp</dimen>
|
||||||
<dimen name="pref_button_size">28dp</dimen>
|
<dimen name="pref_button_size">28dp</dimen>
|
||||||
<bool name="debug_logs">false</bool> <!-- Will be overwritten automatically by Gradle for the debug build variant -->
|
<!-- Margin needed to accomodate the gesture nav bar on Android 15. Found in
|
||||||
|
[core/res/res/values/dimens.xml]. -->
|
||||||
|
<dimen name="bottom_inset_min">48dp</dimen>
|
||||||
|
<!-- Will be overwritten automatically by Gradle for the debug build variant -->
|
||||||
|
<bool name="debug_logs">false</bool>
|
||||||
</resources>
|
</resources>
|
||||||
|
@@ -84,6 +84,7 @@ public final class Config
|
|||||||
[get_current_layout()] and [set_current_layout()]. */
|
[get_current_layout()] and [set_current_layout()]. */
|
||||||
int current_layout_portrait;
|
int current_layout_portrait;
|
||||||
int current_layout_landscape;
|
int current_layout_landscape;
|
||||||
|
public int bottomInsetMin;
|
||||||
|
|
||||||
private Config(SharedPreferences prefs, Resources res, IKeyEventHandler h)
|
private Config(SharedPreferences prefs, Resources res, IKeyEventHandler h)
|
||||||
{
|
{
|
||||||
@@ -187,6 +188,8 @@ public final class Config
|
|||||||
current_layout_landscape = _prefs.getInt("current_layout_landscape", 0);
|
current_layout_landscape = _prefs.getInt("current_layout_landscape", 0);
|
||||||
circle_sensitivity = Integer.valueOf(_prefs.getString("circle_sensitivity", "2"));
|
circle_sensitivity = Integer.valueOf(_prefs.getString("circle_sensitivity", "2"));
|
||||||
clipboard_history_enabled = _prefs.getBoolean("clipboard_history_enabled", false);
|
clipboard_history_enabled = _prefs.getBoolean("clipboard_history_enabled", false);
|
||||||
|
bottomInsetMin = Utils.is_navigation_bar_gestural(res) ?
|
||||||
|
(int)res.getDimension(R.dimen.bottom_inset_min) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int get_current_layout()
|
public int get_current_layout()
|
||||||
|
@@ -292,6 +292,15 @@ public class Keyboard2 extends InputMethodService
|
|||||||
|
|
||||||
private void updateSoftInputWindowLayoutParams() {
|
private void updateSoftInputWindowLayoutParams() {
|
||||||
final Window window = getWindow().getWindow();
|
final Window window = getWindow().getWindow();
|
||||||
|
// On API >= 30, Keyboard2View behaves as edge-to-edge
|
||||||
|
if (VERSION.SDK_INT >= 30)
|
||||||
|
{
|
||||||
|
WindowManager.LayoutParams wattrs = window.getAttributes();
|
||||||
|
wattrs.layoutInDisplayCutoutMode =
|
||||||
|
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||||
|
// Allow to draw behind system bars
|
||||||
|
wattrs.setFitInsetsTypes(0);
|
||||||
|
}
|
||||||
updateLayoutHeightOf(window, ViewGroup.LayoutParams.MATCH_PARENT);
|
updateLayoutHeightOf(window, ViewGroup.LayoutParams.MATCH_PARENT);
|
||||||
final View inputArea = window.findViewById(android.R.id.inputArea);
|
final View inputArea = window.findViewById(android.R.id.inputArea);
|
||||||
|
|
||||||
|
@@ -42,7 +42,9 @@ public class Keyboard2View extends View
|
|||||||
private Config _config;
|
private Config _config;
|
||||||
|
|
||||||
private float _keyWidth;
|
private float _keyWidth;
|
||||||
private float _bottomMargin;
|
private float _marginRight;
|
||||||
|
private float _marginLeft;
|
||||||
|
private float _marginBottom;
|
||||||
|
|
||||||
private Theme _theme;
|
private Theme _theme;
|
||||||
|
|
||||||
@@ -232,7 +234,7 @@ public class Keyboard2View extends View
|
|||||||
private KeyboardData.Key getKeyAtPosition(float tx, float ty)
|
private KeyboardData.Key getKeyAtPosition(float tx, float ty)
|
||||||
{
|
{
|
||||||
KeyboardData.Row row = getRowAtPosition(ty);
|
KeyboardData.Row row = getRowAtPosition(ty);
|
||||||
float x = _config.horizontal_margin;
|
float x = _marginLeft;
|
||||||
if (row == null || tx < x)
|
if (row == null || tx < x)
|
||||||
return null;
|
return null;
|
||||||
for (KeyboardData.Key key : row.keys)
|
for (KeyboardData.Key key : row.keys)
|
||||||
@@ -256,28 +258,56 @@ public class Keyboard2View extends View
|
|||||||
@Override
|
@Override
|
||||||
public void onMeasure(int wSpec, int hSpec)
|
public void onMeasure(int wSpec, int hSpec)
|
||||||
{
|
{
|
||||||
DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
|
int width;
|
||||||
int width = dm.widthPixels;
|
int insets_left = 0;
|
||||||
_bottomMargin = _config.margin_bottom;
|
int insets_right = 0;
|
||||||
// Compatibility with display cutouts and navigation on the right
|
int insets_bottom = 0;
|
||||||
|
// LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS is set in [Keyboard2#updateSoftInputWindowLayoutParams].
|
||||||
|
// and keyboard is allowed do draw behind status/navigation bars
|
||||||
if (VERSION.SDK_INT >= 30)
|
if (VERSION.SDK_INT >= 30)
|
||||||
{
|
{
|
||||||
WindowMetrics metrics =
|
WindowMetrics metrics =
|
||||||
((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE))
|
((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE))
|
||||||
.getCurrentWindowMetrics();
|
.getCurrentWindowMetrics();
|
||||||
Insets insets = metrics.getWindowInsets().getInsetsIgnoringVisibility(
|
width = metrics.getBounds().width();
|
||||||
WindowInsets.Type.statusBars() | WindowInsets.Type.navigationBars()
|
WindowInsets wi = metrics.getWindowInsets();
|
||||||
| WindowInsets.Type.displayCutout());
|
int insets_types =
|
||||||
width = metrics.getBounds().width() - insets.right - insets.left;
|
WindowInsets.Type.statusBars()
|
||||||
// Starting in API 34, keyboard window has LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
|
| WindowInsets.Type.displayCutout()
|
||||||
if (VERSION.SDK_INT >= 34)
|
| WindowInsets.Type.mandatorySystemGestures()
|
||||||
_bottomMargin += insets.bottom;
|
| WindowInsets.Type.navigationBars();
|
||||||
|
Insets insets = wi.getInsets(insets_types);
|
||||||
|
insets_left = insets.left;
|
||||||
|
insets_right = insets.right;
|
||||||
|
// On API 35, the keyboard is allowed to draw under the
|
||||||
|
// button-navigation bar but on lower APIs, it must be discounted from
|
||||||
|
// the width.
|
||||||
|
if (VERSION.SDK_INT < 35)
|
||||||
|
{
|
||||||
|
Insets nav_insets = wi.getInsets(WindowInsets.Type.navigationBars());
|
||||||
|
width -= nav_insets.left + nav_insets.right;
|
||||||
|
insets_left -= nav_insets.left;
|
||||||
|
insets_right -= nav_insets.right;
|
||||||
|
}
|
||||||
|
// [insets.bottom] doesn't take into account the buttons that appear in
|
||||||
|
// the gesture navigation bar when the IME is showing so ensure a minimum
|
||||||
|
// of margin is added.
|
||||||
|
if (VERSION.SDK_INT >= 35)
|
||||||
|
insets_bottom = Math.max(insets.bottom, _config.bottomInsetMin);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DisplayMetrics dm = getContext().getResources().getDisplayMetrics();
|
||||||
|
width = dm.widthPixels;
|
||||||
}
|
}
|
||||||
int height =
|
int height =
|
||||||
(int)(_config.keyHeight * _keyboard.keysHeight
|
(int)(_config.keyHeight * _keyboard.keysHeight
|
||||||
+ _config.marginTop + _bottomMargin);
|
+ _config.marginTop + _marginBottom);
|
||||||
setMeasuredDimension(width, height);
|
setMeasuredDimension(width, height);
|
||||||
_keyWidth = (width - (_config.horizontal_margin * 2)) / _keyboard.keysWidth;
|
_marginLeft = Math.max(_config.horizontal_margin, insets_left);
|
||||||
|
_marginRight = Math.max(_config.horizontal_margin, insets_right);
|
||||||
|
_marginBottom = _config.margin_bottom + insets_bottom;
|
||||||
|
_keyWidth = (width - _marginLeft - _marginRight) / _keyboard.keysWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -289,10 +319,10 @@ public class Keyboard2View extends View
|
|||||||
{
|
{
|
||||||
// Disable the back-gesture on the keyboard area
|
// Disable the back-gesture on the keyboard area
|
||||||
Rect keyboard_area = new Rect(
|
Rect keyboard_area = new Rect(
|
||||||
left + (int)_config.horizontal_margin,
|
left + (int)_marginLeft,
|
||||||
top + (int)_config.marginTop,
|
top + (int)_config.marginTop,
|
||||||
right - (int)_config.horizontal_margin,
|
right - (int)_marginRight,
|
||||||
bottom - (int)_bottomMargin);
|
bottom - (int)_marginBottom);
|
||||||
setSystemGestureExclusionRects(Arrays.asList(keyboard_area));
|
setSystemGestureExclusionRects(Arrays.asList(keyboard_area));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -327,7 +357,7 @@ public class Keyboard2View extends View
|
|||||||
for (KeyboardData.Row row : _keyboard.rows)
|
for (KeyboardData.Row row : _keyboard.rows)
|
||||||
{
|
{
|
||||||
y += row.shift * _config.keyHeight;
|
y += row.shift * _config.keyHeight;
|
||||||
float x = _config.horizontal_margin + key_horizontal_margin / 2;
|
float x = _marginLeft + key_horizontal_margin / 2;
|
||||||
float keyH = row.height * _config.keyHeight - key_vertical_margin;
|
float keyH = row.height * _config.keyHeight - key_vertical_margin;
|
||||||
for (KeyboardData.Key k : row.keys)
|
for (KeyboardData.Key k : row.keys)
|
||||||
{
|
{
|
||||||
|
@@ -1,8 +1,13 @@
|
|||||||
package juloo.keyboard2;
|
package juloo.keyboard2;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.graphics.Insets;
|
||||||
|
import android.os.Build.VERSION;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.view.View;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
|
import android.view.WindowInsets;
|
||||||
import android.view.WindowManager;
|
import android.view.WindowManager;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
@@ -44,4 +49,14 @@ public final class Utils
|
|||||||
out.append(buff, 0, l);
|
out.append(buff, 0, l);
|
||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Whether the thin gesture-navigation bar is used.
|
||||||
|
https://stackoverflow.com/questions/36514167/how-to-really-get-the-navigation-bar-height-in-android
|
||||||
|
*/
|
||||||
|
public static boolean is_navigation_bar_gestural(Resources res)
|
||||||
|
{
|
||||||
|
// core/java/android/view/WindowManagerPolicyConstants.java
|
||||||
|
int res_id = res.getIdentifier("config_navBarInteractionMode", "integer", "android");
|
||||||
|
return (res_id > 0 && res.getInteger(res_id) == 2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user