From 97355881a855c5d2503f7e518c1e30fc03f88d4e Mon Sep 17 00:00:00 2001 From: Matej Drobnič Date: Thu, 22 May 2025 23:54:13 +0200 Subject: Better support for foldable devices (#982) * Add AndroidX WindowManager unfortunately, this seems to be the only way to get fold state, native Android APIs are internal. To add this, we need to update some dependencies, raise java version and raise compile SDK. * adds separate layouts and separate layout settings for folded and unfolded state of the device. The affected settings are: + the margin bottom settings + the horizontal margin settings + the keyboard height settings * Update shell.nix --- srcs/juloo.keyboard2/FoldStateTracker.java | 62 ++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 srcs/juloo.keyboard2/FoldStateTracker.java (limited to 'srcs/juloo.keyboard2/FoldStateTracker.java') diff --git a/srcs/juloo.keyboard2/FoldStateTracker.java b/srcs/juloo.keyboard2/FoldStateTracker.java new file mode 100644 index 0000000..60933c9 --- /dev/null +++ b/srcs/juloo.keyboard2/FoldStateTracker.java @@ -0,0 +1,62 @@ +package juloo.keyboard2; + +import android.content.Context; +import android.content.pm.PackageManager; +import androidx.window.java.layout.WindowInfoTrackerCallbackAdapter; +import androidx.window.layout.DisplayFeature; +import androidx.window.layout.FoldingFeature; +import androidx.window.layout.WindowInfoTracker; +import androidx.window.layout.WindowLayoutInfo; + +import androidx.core.util.Consumer; + + +public class FoldStateTracker { + private final Consumer _innerListener; + private final WindowInfoTrackerCallbackAdapter _windowInfoTracker; + private FoldingFeature _foldingFeature = null; + private Runnable _changedCallback = null; + public FoldStateTracker(Context context) { + _windowInfoTracker = + new WindowInfoTrackerCallbackAdapter(WindowInfoTracker.getOrCreate(context)); + _innerListener = new LayoutStateChangeCallback(); + _windowInfoTracker.addWindowLayoutInfoListener(context, Runnable::run, _innerListener); + } + + public static boolean isFoldableDevice(Context context) { + return context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_SENSOR_HINGE_ANGLE); + } + + public boolean isUnfolded() { + // FoldableFeature is only present when the device is unfolded. Otherwise, it's removed. + // A weird decision from Google, but that's how it works: + // https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:window/window/src/main/java/androidx/window/layout/adapter/sidecar/SidecarAdapter.kt;l=187?q=SidecarAdapter + + return _foldingFeature != null; + } + + public void close() { + _windowInfoTracker.removeWindowLayoutInfoListener(_innerListener); + } + + public void setChangedCallback(Runnable _changedCallback) { + this._changedCallback = _changedCallback; + } + + class LayoutStateChangeCallback implements Consumer { + @Override + public void accept(WindowLayoutInfo newLayoutInfo) { + FoldingFeature old = _foldingFeature; + _foldingFeature = null; + for (DisplayFeature feature: newLayoutInfo.getDisplayFeatures()) { + if (feature instanceof FoldingFeature) { + _foldingFeature = (FoldingFeature) feature; + } + } + + if (old != _foldingFeature && _changedCallback != null) { + _changedCallback.run(); + } + } + } +} -- cgit v1.2.3