From c8f49c9276d34741bfbe7752dd38391c0b8d782b Mon Sep 17 00:00:00 2001 From: Po Lu Date: Sun, 19 Feb 2023 13:17:43 +0800 Subject: Implement `fullscreen' on Android 4.0 and later * doc/emacs/android.texi (Android Windowing): Document what new frame parameters are now supported. * java/org/gnu/emacs/EmacsActivity.java (EmacsActivity): New field `isFullscreen'. (detachWindow, attachWindow): Sync fullscreen state. (onWindowFocusChanged): Add more logging. (onResume): Restore previous fullscreen state. (syncFullscreen): New function. * java/org/gnu/emacs/EmacsWindow.java (EmacsWindow) (setFullscreen): New function. * src/android.c (struct android_emacs_window): Add new method. (android_init_emacs_window): Look up new method. (android_set_fullscreen): New function. * src/androidgui.h: * src/androidterm.c (android_fullscreen_hook): Implement accordingly. --- java/org/gnu/emacs/EmacsActivity.java | 107 +++++++++++++++++++++++++++++++++- java/org/gnu/emacs/EmacsWindow.java | 26 +++++++++ 2 files changed, 130 insertions(+), 3 deletions(-) (limited to 'java/org/gnu') diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java index 3156a144a0f..7e09e608984 100644 --- a/java/org/gnu/emacs/EmacsActivity.java +++ b/java/org/gnu/emacs/EmacsActivity.java @@ -26,12 +26,16 @@ import java.util.ArrayList; import android.app.Activity; import android.content.Context; import android.content.Intent; -import android.os.Bundle; import android.os.Build; +import android.os.Bundle; import android.util.Log; -import android.widget.FrameLayout; -import android.widget.FrameLayout.LayoutParams; import android.view.Menu; +import android.view.View; +import android.view.Window; +import android.view.WindowInsets; +import android.view.WindowInsetsController; +import android.widget.FrameLayout.LayoutParams; +import android.widget.FrameLayout; public class EmacsActivity extends Activity implements EmacsWindowAttachmentManager.WindowConsumer @@ -56,6 +60,9 @@ public class EmacsActivity extends Activity /* Whether or not this activity is paused. */ private boolean isPaused; + /* Whether or not this activity is fullscreen. */ + private boolean isFullscreen; + static { focusedActivities = new ArrayList (); @@ -104,6 +111,8 @@ public class EmacsActivity extends Activity public void detachWindow () { + syncFullscreenWith (null); + if (window == null) Log.w (TAG, "detachWindow called, but there is no window"); else @@ -131,6 +140,8 @@ public class EmacsActivity extends Activity throw new IllegalStateException ("trying to attach window when one" + " already exists"); + syncFullscreenWith (child); + /* Record and attach the view. */ window = child; @@ -230,6 +241,9 @@ public class EmacsActivity extends Activity public void onWindowFocusChanged (boolean isFocused) { + Log.d (TAG, ("onWindowFocusChanged: " + + (isFocused ? "YES" : "NO"))); + if (isFocused && !focusedActivities.contains (this)) { focusedActivities.add (this); @@ -257,6 +271,9 @@ public class EmacsActivity extends Activity { isPaused = false; + /* Update the window insets. */ + syncFullscreenWith (window); + EmacsWindowAttachmentManager.MANAGER.noticeDeiconified (this); super.onResume (); } @@ -279,4 +296,88 @@ public class EmacsActivity extends Activity super.onContextMenuClosed (menu); } + + @SuppressWarnings ("deprecation") + public void + syncFullscreenWith (EmacsWindow emacsWindow) + { + WindowInsetsController controller; + Window window; + int behavior, flags; + View view; + + if (emacsWindow != null) + isFullscreen = emacsWindow.fullscreen; + else + isFullscreen = false; + + /* On Android 11 or later, use the window insets controller to + control whether or not the view is fullscreen. */ + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) + { + window = getWindow (); + + /* If there is no attached window, return immediately. */ + if (window == null) + return; + + behavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; + controller = window.getInsetsController (); + controller.setSystemBarsBehavior (behavior); + + if (isFullscreen) + controller.hide (WindowInsets.Type.statusBars () + | WindowInsets.Type.navigationBars ()); + else + controller.show (WindowInsets.Type.statusBars () + | WindowInsets.Type.navigationBars ()); + + return; + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) + { + /* On Android 4.1 or later, use `setSystemUiVisibility'. */ + + window = getWindow (); + + if (window == null) + return; + + view = window.getDecorView (); + + if (isFullscreen) + { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) + /* This flag means that Emacs will be full screen, but + the system will cancel the full screen state upon + switching to another program. */ + view.setSystemUiVisibility (View.SYSTEM_UI_FLAG_FULLSCREEN); + else + { + /* These flags means that Emacs will be full screen as + long as the state flag is set. */ + flags = 0; + flags |= View.SYSTEM_UI_FLAG_FULLSCREEN; + flags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; + flags |= View.SYSTEM_UI_FLAG_IMMERSIVE; + flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY; + view.setSystemUiVisibility (flags); + } + } + else + view.setSystemUiVisibility (View.SYSTEM_UI_FLAG_VISIBLE); + } + } + + @Override + public void + onAttachedToWindow () + { + super.onAttachedToWindow (); + + /* Update the window insets. */ + syncFullscreenWith (window); + } }; diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 0eca35cec61..90fc4c44198 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -128,6 +128,9 @@ public class EmacsWindow extends EmacsHandleObject events. */ public LinkedHashMap eventStrings; + /* Whether or not this window is fullscreen. */ + public boolean fullscreen; + public EmacsWindow (short handle, final EmacsWindow parent, int x, int y, int width, int height, boolean overrideRedirect) @@ -1179,4 +1182,27 @@ public class EmacsWindow extends EmacsHandleObject return any; } + + public void + setFullscreen (final boolean isFullscreen) + { + EmacsService.SERVICE.runOnUiThread (new Runnable () { + @Override + public void + run () + { + EmacsActivity activity; + Object tem; + + fullscreen = isFullscreen; + tem = getAttachedConsumer (); + + if (tem != null) + { + activity = (EmacsActivity) getAttachedConsumer (); + activity.syncFullscreenWith (EmacsWindow.this); + } + } + }); + } }; -- cgit v1.2.1