mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-12-02 08:22:22 +00:00
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.
This commit is contained in:
parent
c6809eb927
commit
c8f49c9276
@ -355,8 +355,8 @@ tiled on the screen at any time.
|
||||
are created. Instead, the system may choose to terminate windows that
|
||||
are not on screen in order to save memory, with the assumption that
|
||||
the program will save its contents to disk and restore them later,
|
||||
when the user asks to open it again. As this is obvious not possible
|
||||
with Emacs, Emacs separates a frame from a system window.
|
||||
when the user asks to open it again. As this is obviously not
|
||||
possible with Emacs, Emacs separates a frame from a system window.
|
||||
|
||||
Each system window created (including the initial window created
|
||||
during Emacs startup) is appended to a list of windows that do not
|
||||
@ -402,15 +402,15 @@ devices.
|
||||
|
||||
@item
|
||||
The @code{alpha}, @code{alpha-background}, @code{z-group},
|
||||
@code{override-redirect}, @code{mouse-color}, @code{cursor-color},
|
||||
@code{cursor-type}, @code{title}, @code{wait-for-wm}, @code{sticky},
|
||||
@code{undecorated} and @code{tool-bar-position} frame parameters
|
||||
(@pxref{Frame Parameters,,, elisp, the Emacs Lisp Reference Manual})
|
||||
are unsupported.
|
||||
@code{override-redirect}, @code{mouse-color}, @code{title},
|
||||
@code{wait-for-wm}, @code{sticky}, @code{undecorated} and
|
||||
@code{tool-bar-position} frame parameters (@pxref{Frame Parameters,,,
|
||||
elisp, the Emacs Lisp Reference Manual}) are unsupported.
|
||||
|
||||
@item
|
||||
The @code{fullscreen} frame parameter is always @code{maximized} for
|
||||
top-level frames.
|
||||
On Android 4.0 and earlier, the @code{fullscreen} frame parameter is
|
||||
always @code{maximized} for top-level frames; on later versions of
|
||||
Android, it can also be @code{fullscreen}.
|
||||
@end itemize
|
||||
|
||||
@cindex selections, android
|
||||
|
@ -26,12 +26,16 @@
|
||||
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<EmacsActivity> ();
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
@ -128,6 +128,9 @@ private class Coordinate
|
||||
events. */
|
||||
public LinkedHashMap<Integer, String> 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 @@ else if (EmacsWindow.this.isMapped)
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -136,6 +136,7 @@ struct android_emacs_window
|
||||
jmethodID swap_buffers;
|
||||
jmethodID toggle_on_screen_keyboard;
|
||||
jmethodID lookup_string;
|
||||
jmethodID set_fullscreen;
|
||||
};
|
||||
|
||||
/* The API level of the current device. */
|
||||
@ -1920,6 +1921,7 @@ android_init_emacs_window (void)
|
||||
FIND_METHOD (toggle_on_screen_keyboard,
|
||||
"toggleOnScreenKeyboard", "(Z)V");
|
||||
FIND_METHOD (lookup_string, "lookupString", "(I)Ljava/lang/String;");
|
||||
FIND_METHOD (set_fullscreen, "setFullscreen", "(Z)V");
|
||||
#undef FIND_METHOD
|
||||
}
|
||||
|
||||
@ -5475,6 +5477,36 @@ android_reset_ic (android_window window, enum android_ic_mode mode)
|
||||
|
||||
|
||||
|
||||
/* Window decoration management functions. */
|
||||
|
||||
/* Make the specified WINDOW fullscreen, i.e. obscure all of the
|
||||
system navigation and status bars. If not FULLSCREEN, make it
|
||||
maximized instead.
|
||||
|
||||
Value is 1 if the system does not support this, else 0. */
|
||||
|
||||
int
|
||||
android_set_fullscreen (android_window window, bool fullscreen)
|
||||
{
|
||||
jobject object;
|
||||
|
||||
/* Android 4.0 and earlier don't support fullscreen windows. */
|
||||
|
||||
if (android_api_level < 16)
|
||||
return 1;
|
||||
|
||||
object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW);
|
||||
|
||||
(*android_java_env)->CallVoidMethod (android_java_env,
|
||||
object,
|
||||
window_class.set_fullscreen,
|
||||
(jboolean) fullscreen);
|
||||
android_exception_check ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#else /* ANDROID_STUBIFY */
|
||||
|
||||
/* X emulation functions for Android. */
|
||||
|
@ -614,6 +614,7 @@ extern int android_wc_lookup_string (android_key_pressed_event *,
|
||||
extern void android_update_ic (android_window, ptrdiff_t, ptrdiff_t,
|
||||
ptrdiff_t, ptrdiff_t);
|
||||
extern void android_reset_ic (android_window, enum android_ic_mode);
|
||||
extern int android_set_fullscreen (android_window, bool);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1792,12 +1792,30 @@ android_make_frame_visible_invisible (struct frame *f, bool visible)
|
||||
static void
|
||||
android_fullscreen_hook (struct frame *f)
|
||||
{
|
||||
/* Explicitly setting fullscreen is not supported on Android. */
|
||||
Lisp_Object wanted;
|
||||
|
||||
if (!FRAME_PARENT_FRAME (f))
|
||||
store_frame_param (f, Qfullscreen, Qmaximized);
|
||||
{
|
||||
/* Explicitly setting fullscreen is not supported on older
|
||||
Android versions. */
|
||||
|
||||
wanted = (f->want_fullscreen == FULLSCREEN_BOTH
|
||||
? Qfullscreen : Qmaximized);
|
||||
|
||||
if (android_set_fullscreen (FRAME_ANDROID_WINDOW (f),
|
||||
EQ (wanted, Qfullscreen)))
|
||||
store_frame_param (f, Qfullscreen, Qmaximized);
|
||||
else
|
||||
store_frame_param (f, Qfullscreen, wanted);
|
||||
}
|
||||
else
|
||||
store_frame_param (f, Qfullscreen, Qnil);
|
||||
{
|
||||
store_frame_param (f, Qfullscreen, Qnil);
|
||||
|
||||
/* If this is a child frame, don't keep it fullscreen
|
||||
anymore. */
|
||||
android_set_fullscreen (FRAME_ANDROID_WINDOW (f), false);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user