From 4de6b187933479ce93b6079f42a485e5868f01a5 Mon Sep 17 00:00:00 2001
From: Po Lu
Date: Tue, 24 Jan 2023 10:34:40 +0800
Subject: Update Android port
* .gitignore: Update with new files. Do not ignore std*.in.h.
* INSTALL.android: Explain how to build Emacs with external
dependencies.
* Makefile.in (xcompile, cross): Rename to `cross'.
(clean_dirs): Clean cross, not xcompile.
* README: Document new directories.
* build-aux/ndk-build-helper-1.mk (build_kind, NDK_SO_NAMES):
* build-aux/ndk-build-helper-2.mk (build_kind, NDK_SO_NAMES):
* build-aux/ndk-build-helper-3.mk (build_kind):
* build-aux/ndk-build-helper-4.mk:
* build-aux/ndk-build-helper.mk (NDK_BUILD_DIR, my-dir):
* build-aux/ndk-module-extract.awk: New files.
* configure.ac: Set up libgif, libwebp, and libpng for
ndk-build.
* cross/ndk-build/Makefile.in (srcdir, NDK_BUILD_ANDROID_MK):
* cross/ndk-build/ndk-build-executable.mk:
* cross/ndk-build/ndk-build-shared-library.mk (eq, objname):
* cross/ndk-build/ndk-build-static-library.mk (eq, objname):
* cross/ndk-build/ndk-build.in (NDK_BUILD_MODULES):
* cross/ndk-build/ndk-build.mk.in (NDK_BUILD_MODULES)
(NDK_BUILD_SHARED):
* cross/ndk-build/ndk-clear-vars.mk:
* cross/ndk-build/ndk-prebuilt-shared-library.mk:
* cross/ndk-build/ndk-prebuilt-static-library.mk: New files.
* doc/emacs/android.texi (Android, Android Environment):
Document clipboard support on Android.
* doc/emacs/emacs.texi (Top): Update menus.
* etc/MACHINES: Document Android.
* java/AndroidManifest.xml.in: Respect new
`--with-android-debug' option.
* java/Makefile.in (CROSS_BINS, CROSS_LIBS): Adjust for rename.
Include ndk-build.mk.:(emacs.apk-in): Depend on shared
libraries. Then, package shared libraries.
* java/org/gnu/emacs/EmacsClipboard.java (EmacsClipboard): New
class.
* java/org/gnu/emacs/EmacsFontDriver.java: Update comment to say
this is unused.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
function `sendExpose'.
* java/org/gnu/emacs/EmacsSdk11Clipboard.java
(EmacsSdk11Clipboard):
* java/org/gnu/emacs/EmacsSdk8Clipboard.java
(EmacsSdk8Clipboard): New classes.
* java/org/gnu/emacs/EmacsView.java (EmacsView, handleDirtyBitmap)
(onDetachedFromWindow): When window is reattached, expose the
frame.
* lib/Makefile.in (VPATH):
(ALL_CFLAGS): Adjust for rename.
* lisp/term/android-win.el (android-clipboard-exists-p)
(android-get-clipboard, android-set-clipboard)
(android-clipboard-owner-p, android-primary-selection)
(android-get-clipboard-1, android-get-primary)
(android-selection-bounds, android-encode-select-string)
(gui-backend-get-selection, gui-backend-selection-exists-p)
(gui-backend-selection-owner-p, gui-backend-set-selection): New
functions.
* m4/ndk-build.m4: New file.
* src/Makefile.in (GIF_CFLAGS, ANDROID_LDFLAGS): New variables.
(EMACS_CFLAGS): Add GIF_CFLAGS. Include
ndk-build.mk.
(libemacs.so): Depend on and link with required
libraries.
* src/android.c (android_check_compressed_file): New function.
(android_open): Work around Android platform bug.
(sendExpose): New function.
(android_readdir): Set d_type if this is a directory.
* src/androidgui.h (enum android_event_type)
(struct android_expose_event, union android_event): Add expose
events.
* src/androidselect.c (struct android_emacs_clipboard)
(android_init_emacs_clipboard, Fandroid_clipboard_owner_p)
(Fandroid_set_clipboard, Fandroid_get_clipboard)
(Fandroid_clipboard_exists_p, init_androidselect)
(syms_of_androidselect): New file.
* src/androidterm.c (handle_one_android_event): Handle
exposures.
* src/androidterm.h: Update prototypes.
* src/emacs.c (android_emacs_init): Initialize androidselect.
---
java/AndroidManifest.xml.in | 5 +-
java/Makefile.in | 30 +++---
java/org/gnu/emacs/EmacsClipboard.java | 44 ++++++++
java/org/gnu/emacs/EmacsFontDriver.java | 3 +
java/org/gnu/emacs/EmacsNative.java | 4 +
java/org/gnu/emacs/EmacsSdk11Clipboard.java | 156 ++++++++++++++++++++++++++++
java/org/gnu/emacs/EmacsSdk8Clipboard.java | 116 +++++++++++++++++++++
java/org/gnu/emacs/EmacsView.java | 23 ++++
8 files changed, 368 insertions(+), 13 deletions(-)
create mode 100644 java/org/gnu/emacs/EmacsClipboard.java
create mode 100644 java/org/gnu/emacs/EmacsSdk11Clipboard.java
create mode 100644 java/org/gnu/emacs/EmacsSdk8Clipboard.java
(limited to 'java')
diff --git a/java/AndroidManifest.xml.in b/java/AndroidManifest.xml.in
index 74f69d2a8e5..c4a9d1f5177 100644
--- a/java/AndroidManifest.xml.in
+++ b/java/AndroidManifest.xml.in
@@ -60,12 +60,13 @@ along with GNU Emacs. If not, see . -->
android:hardwareAccelerated="true"
android:supportsRtl="true"
android:theme="@android:style/Theme"
- android:debuggable="true"
+ android:debuggable="@ANDROID_DEBUGGABLE@"
android:extractNativeLibs="true">
@@ -76,10 +77,12 @@ along with GNU Emacs. If not, see . -->
diff --git a/java/Makefile.in b/java/Makefile.in
index 22c912fdce5..d27775ea3db 100644
--- a/java/Makefile.in
+++ b/java/Makefile.in
@@ -81,21 +81,24 @@ APK_NAME = emacs-$(version)-$(ANDROID_MIN_SDK)-$(ANDROID_ABI).apk
all: $(APK_NAME)
# Binaries to cross-compile.
-CROSS_BINS = ../xcompile/src/android-emacs ../xcompile/lib-src/ctags \
- ../xcompile/lib-src/hexl ../xcompile/lib-src/movemail \
- ../xcompile/lib-src/ebrowse ../xcompile/lib-src/emacsclient
+CROSS_BINS = ../cross/src/android-emacs ../cross/lib-src/ctags \
+ ../cross/lib-src/hexl ../cross/lib-src/movemail \
+ ../cross/lib-src/ebrowse ../cross/lib-src/emacsclient
# Libraries to cross-compile.
-CROSS_LIBS = ../xcompile/src/libemacs.so
+CROSS_LIBS = ../cross/src/libemacs.so
+
+# Third party libraries to compile.
+include $(top_builddir)/cross/ndk-build/ndk-build.mk
.PHONY: $(CROSS_BINS) $(CROSS_LIBS)
-../xcompile/src/android-emacs ../xcompile/src/libemacs.so:
- make -C ../xcompile src/$(notdir $@)
+../cross/src/android-emacs ../cross/src/libemacs.so:
+ make -C ../cross src/$(notdir $@)
-../xcompile/lib-src/hexl ../xcompile/lib-src/movemail \
-../xcompile/lib-src/ctags ../xcompile/lib-src/ebrowse &:
- make -C ../xcompile lib-src/$(notdir $@)
+../cross/lib-src/hexl ../cross/lib-src/movemail \
+../cross/lib-src/ctags ../cross/lib-src/ebrowse &:
+ make -C ../cross lib-src/$(notdir $@)
# This is needed to generate the ``.directory-tree'' file used by the
# Android emulations of readdir and faccessat.
@@ -104,7 +107,7 @@ $(libsrc)/asset-directory-tool:
$(MAKE) -C $(libsrc) $(notdir $@)
emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) $(libsrc)/asset-directory-tool \
- AndroidManifest.xml
+ AndroidManifest.xml $(NDK_BUILD_SHARED)
# Make the working directory for this stuff
rm -rf install_temp
mkdir -p install_temp/lib/$(ANDROID_ABI)
@@ -145,11 +148,13 @@ emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) $(libsrc)/asset-directory-tool \
cp -f $$file install_temp/lib/$(ANDROID_ABI); \
fi \
done
+ $(foreach module,$(NDK_BUILD_SHARED), \
+ cp -f $(module) install_temp/lib/$(ANDROID_ABI))
# Package everything. Specifying the assets on this command line is
# necessary for AAssetManager_getNextFileName to work on old versions
# of Android.
- $(AAPT) package -I "$(ANDROID_JAR)" -F $@ -f -M AndroidManifest.xml \
- -A install_temp/assets
+ $(AAPT) package -I "$(ANDROID_JAR)" -F $@ -f \
+ -M AndroidManifest.xml -A install_temp/assets
pushd install_temp; $(AAPT) add ../$@ `find lib -type f`; popd
rm -rf install_temp
@@ -196,3 +201,4 @@ clean:
find . -name '*.class' -delete
maintainer-clean distclean bootstrap-clean: clean
+ rm -f Makefile ndk-build.mk
diff --git a/java/org/gnu/emacs/EmacsClipboard.java b/java/org/gnu/emacs/EmacsClipboard.java
new file mode 100644
index 00000000000..cd6bcebfe0e
--- /dev/null
+++ b/java/org/gnu/emacs/EmacsClipboard.java
@@ -0,0 +1,44 @@
+/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
+
+Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see . */
+
+package org.gnu.emacs;
+
+import android.os.Build;
+
+/* This class provides helper code for accessing the clipboard,
+ abstracting between the different interfaces on API 8 and 11. */
+
+public abstract class EmacsClipboard
+{
+ public abstract void setClipboard (byte[] bytes);
+ public abstract int ownsClipboard ();
+ public abstract boolean clipboardExists ();
+ public abstract byte[] getClipboard ();
+
+ /* Create the correct kind of clipboard for this system. */
+
+ public static EmacsClipboard
+ makeClipboard ()
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
+ return new EmacsSdk11Clipboard ();
+ else
+ return new EmacsSdk8Clipboard ();
+ }
+};
diff --git a/java/org/gnu/emacs/EmacsFontDriver.java b/java/org/gnu/emacs/EmacsFontDriver.java
index 1d1e6f7b33f..39bda5a456d 100644
--- a/java/org/gnu/emacs/EmacsFontDriver.java
+++ b/java/org/gnu/emacs/EmacsFontDriver.java
@@ -23,6 +23,9 @@ import java.util.List;
import android.os.Build;
+/* This code is mostly unused. See sfntfont-android.c for the code
+ that is actually used. */
+
public abstract class EmacsFontDriver
{
/* Font weights. */
diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java
index 3efdc0cff9a..962538bef7b 100644
--- a/java/org/gnu/emacs/EmacsNative.java
+++ b/java/org/gnu/emacs/EmacsNative.java
@@ -132,6 +132,10 @@ public class EmacsNative
/* Send an ANDROID_CONTEXT_MENU event. */
public static native long sendContextMenu (short window, int menuEventID);
+ /* Send an ANDROID_EXPOSE event. */
+ public static native long sendExpose (short window, int x, int y,
+ int width, int height);
+
static
{
System.loadLibrary ("emacs");
diff --git a/java/org/gnu/emacs/EmacsSdk11Clipboard.java b/java/org/gnu/emacs/EmacsSdk11Clipboard.java
new file mode 100644
index 00000000000..0a725200723
--- /dev/null
+++ b/java/org/gnu/emacs/EmacsSdk11Clipboard.java
@@ -0,0 +1,156 @@
+/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
+
+Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see . */
+
+package org.gnu.emacs;
+
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.ClipData;
+
+import android.util.Log;
+
+import java.io.UnsupportedEncodingException;
+
+/* This class implements EmacsClipboard for Android 3.0 and later
+ systems. */
+
+public class EmacsSdk11Clipboard extends EmacsClipboard
+ implements ClipboardManager.OnPrimaryClipChangedListener
+{
+ private static final String TAG = "EmacsSdk11Clipboard";
+ private ClipboardManager manager;
+ private boolean ownsClipboard;
+ private int clipboardChangedCount;
+ private int monitoredClipboardChangedCount;
+
+ public
+ EmacsSdk11Clipboard ()
+ {
+ String what;
+ Context context;
+
+ what = Context.CLIPBOARD_SERVICE;
+ context = EmacsService.SERVICE;
+ manager
+ = (ClipboardManager) context.getSystemService (what);
+ manager.addPrimaryClipChangedListener (this);
+ }
+
+ @Override
+ public synchronized void
+ onPrimaryClipChanged ()
+ {
+ Log.d (TAG, ("onPrimaryClipChanged: "
+ + monitoredClipboardChangedCount
+ + " " + clipboardChangedCount));
+
+ /* Increment monitoredClipboardChangeCount. If it is now greater
+ than clipboardChangedCount, then Emacs no longer owns the
+ clipboard. */
+ monitoredClipboardChangedCount++;
+
+ if (monitoredClipboardChangedCount > clipboardChangedCount)
+ {
+ ownsClipboard = false;
+
+ /* Reset both values back to 0. */
+ monitoredClipboardChangedCount = 0;
+ clipboardChangedCount = 0;
+ }
+ }
+
+ /* Set the clipboard text to CLIPBOARD, a string in UTF-8
+ encoding. */
+
+ @Override
+ public synchronized void
+ setClipboard (byte[] bytes)
+ {
+ ClipData data;
+ String string;
+
+ try
+ {
+ string = new String (bytes, "UTF-8");
+ data = ClipData.newPlainText ("Emacs", string);
+ manager.setPrimaryClip (data);
+ ownsClipboard = true;
+
+ /* onPrimaryClipChanged will be called again. Use this
+ variable to keep track of how many times the clipboard has
+ been changed. */
+ ++clipboardChangedCount;
+ }
+ catch (UnsupportedEncodingException exception)
+ {
+ Log.w (TAG, "setClipboard: " + exception);
+ }
+ }
+
+ /* Return whether or not Emacs owns the clipboard. Value is 1 if
+ Emacs does, 0 if Emacs does not, and -1 if that information is
+ unavailable. */
+
+ @Override
+ public synchronized int
+ ownsClipboard ()
+ {
+ return ownsClipboard ? 1 : 0;
+ }
+
+ /* Return whether or not clipboard content currently exists. */
+
+ @Override
+ public boolean
+ clipboardExists ()
+ {
+ return manager.hasPrimaryClip ();
+ }
+
+ /* Return the current content of the clipboard, as plain text, or
+ NULL if no content is available. */
+
+ @Override
+ public byte[]
+ getClipboard ()
+ {
+ ClipData clip;
+ CharSequence text;
+ Context context;
+
+ clip = manager.getPrimaryClip ();
+
+ if (clip == null || clip.getItemCount () < 1)
+ return null;
+
+ context = EmacsService.SERVICE;
+
+ try
+ {
+ text = clip.getItemAt (0).coerceToText (context);
+ return text.toString ().getBytes ("UTF-8");
+ }
+ catch (UnsupportedEncodingException exception)
+ {
+ Log.w (TAG, "getClipboard: " + exception);
+ }
+
+ return null;
+ }
+};
diff --git a/java/org/gnu/emacs/EmacsSdk8Clipboard.java b/java/org/gnu/emacs/EmacsSdk8Clipboard.java
new file mode 100644
index 00000000000..34e66912562
--- /dev/null
+++ b/java/org/gnu/emacs/EmacsSdk8Clipboard.java
@@ -0,0 +1,116 @@
+/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
+
+Copyright (C) 2023 Free Software Foundation, Inc.
+
+This file is part of GNU Emacs.
+
+GNU Emacs is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
+
+GNU Emacs is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU Emacs. If not, see . */
+
+package org.gnu.emacs;
+
+/* Importing the entire package avoids the deprecation warning. */
+import android.text.*;
+
+import android.content.Context;
+import android.util.Log;
+
+import java.io.UnsupportedEncodingException;
+
+/* This class implements EmacsClipboard for Android 2.2 and other
+ similarly old systems. */
+
+@SuppressWarnings ("deprecation")
+public class EmacsSdk8Clipboard extends EmacsClipboard
+{
+ private static final String TAG = "EmacsSdk8Clipboard";
+ private ClipboardManager manager;
+
+ public
+ EmacsSdk8Clipboard ()
+ {
+ String what;
+ Context context;
+
+ what = Context.CLIPBOARD_SERVICE;
+ context = EmacsService.SERVICE;
+ manager
+ = (ClipboardManager) context.getSystemService (what);
+ }
+
+ /* Set the clipboard text to CLIPBOARD, a string in UTF-8
+ encoding. */
+
+ @Override
+ public void
+ setClipboard (byte[] bytes)
+ {
+ try
+ {
+ manager.setText (new String (bytes, "UTF-8"));
+ }
+ catch (UnsupportedEncodingException exception)
+ {
+ Log.w (TAG, "setClipboard: " + exception);
+ }
+ }
+
+ /* Return whether or not Emacs owns the clipboard. Value is 1 if
+ Emacs does, 0 if Emacs does not, and -1 if that information is
+ unavailable. */
+
+ @Override
+ public int
+ ownsClipboard ()
+ {
+ return -1;
+ }
+
+ /* Return whether or not clipboard content currently exists. */
+
+ @Override
+ public boolean
+ clipboardExists ()
+ {
+ return manager.hasText ();
+ }
+
+ /* Return the current content of the clipboard, as plain text, or
+ NULL if no content is available. */
+
+ @Override
+ public byte[]
+ getClipboard ()
+ {
+ String string;
+ CharSequence text;
+
+ text = manager.getText ();
+
+ if (text == null)
+ return null;
+
+ string = text.toString ();
+
+ try
+ {
+ return string.getBytes ("UTF-8");
+ }
+ catch (UnsupportedEncodingException exception)
+ {
+ Log.w (TAG, "getClipboard: " + exception);
+ }
+
+ return null;
+ }
+};
diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java
index 74bbb7b3ecc..881cbc363ba 100644
--- a/java/org/gnu/emacs/EmacsView.java
+++ b/java/org/gnu/emacs/EmacsView.java
@@ -99,6 +99,9 @@ public class EmacsView extends ViewGroup
yet responded to. 0 if there is no such outstanding event. */
public long pendingConfigure;
+ /* Whether or not this view is attached to a window. */
+ public boolean isAttachedToWindow;
+
public
EmacsView (EmacsWindow window)
{
@@ -140,6 +143,9 @@ public class EmacsView extends ViewGroup
if (measuredWidth == 0 || measuredHeight == 0)
return;
+ if (!isAttachedToWindow)
+ return;
+
/* If bitmap is the same width and height as the measured width
and height, there is no need to do anything. Avoid allocating
the extra bitmap. */
@@ -547,6 +553,8 @@ public class EmacsView extends ViewGroup
public synchronized void
onDetachedFromWindow ()
{
+ isAttachedToWindow = false;
+
synchronized (this)
{
/* Recycle the bitmap and call GC. */
@@ -559,6 +567,21 @@ public class EmacsView extends ViewGroup
}
}
+ @Override
+ public synchronized void
+ onAttachedToWindow ()
+ {
+ isAttachedToWindow = true;
+
+ /* Dirty the bitmap, as it was destroyed when onDetachedFromWindow
+ was called. */
+ bitmapDirty = true;
+
+ /* Now expose the view contents again. */
+ EmacsNative.sendExpose (this.window.handle, 0, 0,
+ measuredWidth, measuredHeight);
+ }
+
public void
showOnScreenKeyboard ()
{
--
cgit v1.2.1