diff options
| author | Po Lu | 2023-01-24 10:34:40 +0800 |
|---|---|---|
| committer | Po Lu | 2023-01-24 10:34:40 +0800 |
| commit | 4de6b187933479ce93b6079f42a485e5868f01a5 (patch) | |
| tree | db3e4cbeb5487a8397e686e9a242fdeb90fad43a /java | |
| parent | 9d3aacedf0c217af207d39e390f376914160396b (diff) | |
| download | emacs-4de6b187933479ce93b6079f42a485e5868f01a5.tar.gz emacs-4de6b187933479ce93b6079f42a485e5868f01a5.zip | |
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.
Diffstat (limited to 'java')
| -rw-r--r-- | java/AndroidManifest.xml.in | 5 | ||||
| -rw-r--r-- | java/Makefile.in | 30 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsClipboard.java | 44 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsFontDriver.java | 3 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsNative.java | 4 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsSdk11Clipboard.java | 156 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsSdk8Clipboard.java | 116 | ||||
| -rw-r--r-- | java/org/gnu/emacs/EmacsView.java | 23 |
8 files changed, 368 insertions, 13 deletions
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 <https://www.gnu.org/licenses/>. --> | |||
| 60 | android:hardwareAccelerated="true" | 60 | android:hardwareAccelerated="true" |
| 61 | android:supportsRtl="true" | 61 | android:supportsRtl="true" |
| 62 | android:theme="@android:style/Theme" | 62 | android:theme="@android:style/Theme" |
| 63 | android:debuggable="true" | 63 | android:debuggable="@ANDROID_DEBUGGABLE@" |
| 64 | android:extractNativeLibs="true"> | 64 | android:extractNativeLibs="true"> |
| 65 | 65 | ||
| 66 | <activity android:name="org.gnu.emacs.EmacsActivity" | 66 | <activity android:name="org.gnu.emacs.EmacsActivity" |
| 67 | android:launchMode="singleTop" | 67 | android:launchMode="singleTop" |
| 68 | android:windowSoftInputMode="adjustResize" | 68 | android:windowSoftInputMode="adjustResize" |
| 69 | android:exported="true" | ||
| 69 | android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"> | 70 | android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"> |
| 70 | <intent-filter> | 71 | <intent-filter> |
| 71 | <action android:name="android.intent.action.MAIN" /> | 72 | <action android:name="android.intent.action.MAIN" /> |
| @@ -76,10 +77,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. --> | |||
| 76 | 77 | ||
| 77 | <activity android:name="org.gnu.emacs.EmacsMultitaskActivity" | 78 | <activity android:name="org.gnu.emacs.EmacsMultitaskActivity" |
| 78 | android:windowSoftInputMode="adjustResize" | 79 | android:windowSoftInputMode="adjustResize" |
| 80 | android:exported="true" | ||
| 79 | android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"/> | 81 | android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"/> |
| 80 | 82 | ||
| 81 | <activity android:autoRemoveFromRecents="true" | 83 | <activity android:autoRemoveFromRecents="true" |
| 82 | android:label="Emacs options" | 84 | android:label="Emacs options" |
| 85 | android:exported="true" | ||
| 83 | android:name=".EmacsPreferencesActivity"> | 86 | android:name=".EmacsPreferencesActivity"> |
| 84 | <intent-filter> | 87 | <intent-filter> |
| 85 | <action android:name="android.intent.action.APPLICATION_PREFERENCES" /> | 88 | <action android:name="android.intent.action.APPLICATION_PREFERENCES" /> |
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 | |||
| 81 | all: $(APK_NAME) | 81 | all: $(APK_NAME) |
| 82 | 82 | ||
| 83 | # Binaries to cross-compile. | 83 | # Binaries to cross-compile. |
| 84 | CROSS_BINS = ../xcompile/src/android-emacs ../xcompile/lib-src/ctags \ | 84 | CROSS_BINS = ../cross/src/android-emacs ../cross/lib-src/ctags \ |
| 85 | ../xcompile/lib-src/hexl ../xcompile/lib-src/movemail \ | 85 | ../cross/lib-src/hexl ../cross/lib-src/movemail \ |
| 86 | ../xcompile/lib-src/ebrowse ../xcompile/lib-src/emacsclient | 86 | ../cross/lib-src/ebrowse ../cross/lib-src/emacsclient |
| 87 | 87 | ||
| 88 | # Libraries to cross-compile. | 88 | # Libraries to cross-compile. |
| 89 | CROSS_LIBS = ../xcompile/src/libemacs.so | 89 | CROSS_LIBS = ../cross/src/libemacs.so |
| 90 | |||
| 91 | # Third party libraries to compile. | ||
| 92 | include $(top_builddir)/cross/ndk-build/ndk-build.mk | ||
| 90 | 93 | ||
| 91 | .PHONY: $(CROSS_BINS) $(CROSS_LIBS) | 94 | .PHONY: $(CROSS_BINS) $(CROSS_LIBS) |
| 92 | 95 | ||
| 93 | ../xcompile/src/android-emacs ../xcompile/src/libemacs.so: | 96 | ../cross/src/android-emacs ../cross/src/libemacs.so: |
| 94 | make -C ../xcompile src/$(notdir $@) | 97 | make -C ../cross src/$(notdir $@) |
| 95 | 98 | ||
| 96 | ../xcompile/lib-src/hexl ../xcompile/lib-src/movemail \ | 99 | ../cross/lib-src/hexl ../cross/lib-src/movemail \ |
| 97 | ../xcompile/lib-src/ctags ../xcompile/lib-src/ebrowse &: | 100 | ../cross/lib-src/ctags ../cross/lib-src/ebrowse &: |
| 98 | make -C ../xcompile lib-src/$(notdir $@) | 101 | make -C ../cross lib-src/$(notdir $@) |
| 99 | 102 | ||
| 100 | # This is needed to generate the ``.directory-tree'' file used by the | 103 | # This is needed to generate the ``.directory-tree'' file used by the |
| 101 | # Android emulations of readdir and faccessat. | 104 | # Android emulations of readdir and faccessat. |
| @@ -104,7 +107,7 @@ $(libsrc)/asset-directory-tool: | |||
| 104 | $(MAKE) -C $(libsrc) $(notdir $@) | 107 | $(MAKE) -C $(libsrc) $(notdir $@) |
| 105 | 108 | ||
| 106 | emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) $(libsrc)/asset-directory-tool \ | 109 | emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) $(libsrc)/asset-directory-tool \ |
| 107 | AndroidManifest.xml | 110 | AndroidManifest.xml $(NDK_BUILD_SHARED) |
| 108 | # Make the working directory for this stuff | 111 | # Make the working directory for this stuff |
| 109 | rm -rf install_temp | 112 | rm -rf install_temp |
| 110 | mkdir -p install_temp/lib/$(ANDROID_ABI) | 113 | mkdir -p install_temp/lib/$(ANDROID_ABI) |
| @@ -145,11 +148,13 @@ emacs.apk-in: $(CROSS_BINS) $(CROSS_LIBS) $(libsrc)/asset-directory-tool \ | |||
| 145 | cp -f $$file install_temp/lib/$(ANDROID_ABI); \ | 148 | cp -f $$file install_temp/lib/$(ANDROID_ABI); \ |
| 146 | fi \ | 149 | fi \ |
| 147 | done | 150 | done |
| 151 | $(foreach module,$(NDK_BUILD_SHARED), \ | ||
| 152 | cp -f $(module) install_temp/lib/$(ANDROID_ABI)) | ||
| 148 | # Package everything. Specifying the assets on this command line is | 153 | # Package everything. Specifying the assets on this command line is |
| 149 | # necessary for AAssetManager_getNextFileName to work on old versions | 154 | # necessary for AAssetManager_getNextFileName to work on old versions |
| 150 | # of Android. | 155 | # of Android. |
| 151 | $(AAPT) package -I "$(ANDROID_JAR)" -F $@ -f -M AndroidManifest.xml \ | 156 | $(AAPT) package -I "$(ANDROID_JAR)" -F $@ -f \ |
| 152 | -A install_temp/assets | 157 | -M AndroidManifest.xml -A install_temp/assets |
| 153 | pushd install_temp; $(AAPT) add ../$@ `find lib -type f`; popd | 158 | pushd install_temp; $(AAPT) add ../$@ `find lib -type f`; popd |
| 154 | rm -rf install_temp | 159 | rm -rf install_temp |
| 155 | 160 | ||
| @@ -196,3 +201,4 @@ clean: | |||
| 196 | find . -name '*.class' -delete | 201 | find . -name '*.class' -delete |
| 197 | 202 | ||
| 198 | maintainer-clean distclean bootstrap-clean: clean | 203 | maintainer-clean distclean bootstrap-clean: clean |
| 204 | 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 @@ | |||
| 1 | /* Communication module for Android terminals. -*- c-file-style: "GNU" -*- | ||
| 2 | |||
| 3 | Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 10 | your option) any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 19 | |||
| 20 | package org.gnu.emacs; | ||
| 21 | |||
| 22 | import android.os.Build; | ||
| 23 | |||
| 24 | /* This class provides helper code for accessing the clipboard, | ||
| 25 | abstracting between the different interfaces on API 8 and 11. */ | ||
| 26 | |||
| 27 | public abstract class EmacsClipboard | ||
| 28 | { | ||
| 29 | public abstract void setClipboard (byte[] bytes); | ||
| 30 | public abstract int ownsClipboard (); | ||
| 31 | public abstract boolean clipboardExists (); | ||
| 32 | public abstract byte[] getClipboard (); | ||
| 33 | |||
| 34 | /* Create the correct kind of clipboard for this system. */ | ||
| 35 | |||
| 36 | public static EmacsClipboard | ||
| 37 | makeClipboard () | ||
| 38 | { | ||
| 39 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) | ||
| 40 | return new EmacsSdk11Clipboard (); | ||
| 41 | else | ||
| 42 | return new EmacsSdk8Clipboard (); | ||
| 43 | } | ||
| 44 | }; | ||
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; | |||
| 23 | 23 | ||
| 24 | import android.os.Build; | 24 | import android.os.Build; |
| 25 | 25 | ||
| 26 | /* This code is mostly unused. See sfntfont-android.c for the code | ||
| 27 | that is actually used. */ | ||
| 28 | |||
| 26 | public abstract class EmacsFontDriver | 29 | public abstract class EmacsFontDriver |
| 27 | { | 30 | { |
| 28 | /* Font weights. */ | 31 | /* 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 | |||
| 132 | /* Send an ANDROID_CONTEXT_MENU event. */ | 132 | /* Send an ANDROID_CONTEXT_MENU event. */ |
| 133 | public static native long sendContextMenu (short window, int menuEventID); | 133 | public static native long sendContextMenu (short window, int menuEventID); |
| 134 | 134 | ||
| 135 | /* Send an ANDROID_EXPOSE event. */ | ||
| 136 | public static native long sendExpose (short window, int x, int y, | ||
| 137 | int width, int height); | ||
| 138 | |||
| 135 | static | 139 | static |
| 136 | { | 140 | { |
| 137 | System.loadLibrary ("emacs"); | 141 | 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 @@ | |||
| 1 | /* Communication module for Android terminals. -*- c-file-style: "GNU" -*- | ||
| 2 | |||
| 3 | Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 10 | your option) any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 19 | |||
| 20 | package org.gnu.emacs; | ||
| 21 | |||
| 22 | import android.content.ClipboardManager; | ||
| 23 | import android.content.Context; | ||
| 24 | import android.content.ClipData; | ||
| 25 | |||
| 26 | import android.util.Log; | ||
| 27 | |||
| 28 | import java.io.UnsupportedEncodingException; | ||
| 29 | |||
| 30 | /* This class implements EmacsClipboard for Android 3.0 and later | ||
| 31 | systems. */ | ||
| 32 | |||
| 33 | public class EmacsSdk11Clipboard extends EmacsClipboard | ||
| 34 | implements ClipboardManager.OnPrimaryClipChangedListener | ||
| 35 | { | ||
| 36 | private static final String TAG = "EmacsSdk11Clipboard"; | ||
| 37 | private ClipboardManager manager; | ||
| 38 | private boolean ownsClipboard; | ||
| 39 | private int clipboardChangedCount; | ||
| 40 | private int monitoredClipboardChangedCount; | ||
| 41 | |||
| 42 | public | ||
| 43 | EmacsSdk11Clipboard () | ||
| 44 | { | ||
| 45 | String what; | ||
| 46 | Context context; | ||
| 47 | |||
| 48 | what = Context.CLIPBOARD_SERVICE; | ||
| 49 | context = EmacsService.SERVICE; | ||
| 50 | manager | ||
| 51 | = (ClipboardManager) context.getSystemService (what); | ||
| 52 | manager.addPrimaryClipChangedListener (this); | ||
| 53 | } | ||
| 54 | |||
| 55 | @Override | ||
| 56 | public synchronized void | ||
| 57 | onPrimaryClipChanged () | ||
| 58 | { | ||
| 59 | Log.d (TAG, ("onPrimaryClipChanged: " | ||
| 60 | + monitoredClipboardChangedCount | ||
| 61 | + " " + clipboardChangedCount)); | ||
| 62 | |||
| 63 | /* Increment monitoredClipboardChangeCount. If it is now greater | ||
| 64 | than clipboardChangedCount, then Emacs no longer owns the | ||
| 65 | clipboard. */ | ||
| 66 | monitoredClipboardChangedCount++; | ||
| 67 | |||
| 68 | if (monitoredClipboardChangedCount > clipboardChangedCount) | ||
| 69 | { | ||
| 70 | ownsClipboard = false; | ||
| 71 | |||
| 72 | /* Reset both values back to 0. */ | ||
| 73 | monitoredClipboardChangedCount = 0; | ||
| 74 | clipboardChangedCount = 0; | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | /* Set the clipboard text to CLIPBOARD, a string in UTF-8 | ||
| 79 | encoding. */ | ||
| 80 | |||
| 81 | @Override | ||
| 82 | public synchronized void | ||
| 83 | setClipboard (byte[] bytes) | ||
| 84 | { | ||
| 85 | ClipData data; | ||
| 86 | String string; | ||
| 87 | |||
| 88 | try | ||
| 89 | { | ||
| 90 | string = new String (bytes, "UTF-8"); | ||
| 91 | data = ClipData.newPlainText ("Emacs", string); | ||
| 92 | manager.setPrimaryClip (data); | ||
| 93 | ownsClipboard = true; | ||
| 94 | |||
| 95 | /* onPrimaryClipChanged will be called again. Use this | ||
| 96 | variable to keep track of how many times the clipboard has | ||
| 97 | been changed. */ | ||
| 98 | ++clipboardChangedCount; | ||
| 99 | } | ||
| 100 | catch (UnsupportedEncodingException exception) | ||
| 101 | { | ||
| 102 | Log.w (TAG, "setClipboard: " + exception); | ||
| 103 | } | ||
| 104 | } | ||
| 105 | |||
| 106 | /* Return whether or not Emacs owns the clipboard. Value is 1 if | ||
| 107 | Emacs does, 0 if Emacs does not, and -1 if that information is | ||
| 108 | unavailable. */ | ||
| 109 | |||
| 110 | @Override | ||
| 111 | public synchronized int | ||
| 112 | ownsClipboard () | ||
| 113 | { | ||
| 114 | return ownsClipboard ? 1 : 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | /* Return whether or not clipboard content currently exists. */ | ||
| 118 | |||
| 119 | @Override | ||
| 120 | public boolean | ||
| 121 | clipboardExists () | ||
| 122 | { | ||
| 123 | return manager.hasPrimaryClip (); | ||
| 124 | } | ||
| 125 | |||
| 126 | /* Return the current content of the clipboard, as plain text, or | ||
| 127 | NULL if no content is available. */ | ||
| 128 | |||
| 129 | @Override | ||
| 130 | public byte[] | ||
| 131 | getClipboard () | ||
| 132 | { | ||
| 133 | ClipData clip; | ||
| 134 | CharSequence text; | ||
| 135 | Context context; | ||
| 136 | |||
| 137 | clip = manager.getPrimaryClip (); | ||
| 138 | |||
| 139 | if (clip == null || clip.getItemCount () < 1) | ||
| 140 | return null; | ||
| 141 | |||
| 142 | context = EmacsService.SERVICE; | ||
| 143 | |||
| 144 | try | ||
| 145 | { | ||
| 146 | text = clip.getItemAt (0).coerceToText (context); | ||
| 147 | return text.toString ().getBytes ("UTF-8"); | ||
| 148 | } | ||
| 149 | catch (UnsupportedEncodingException exception) | ||
| 150 | { | ||
| 151 | Log.w (TAG, "getClipboard: " + exception); | ||
| 152 | } | ||
| 153 | |||
| 154 | return null; | ||
| 155 | } | ||
| 156 | }; | ||
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 @@ | |||
| 1 | /* Communication module for Android terminals. -*- c-file-style: "GNU" -*- | ||
| 2 | |||
| 3 | Copyright (C) 2023 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 10 | your option) any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */ | ||
| 19 | |||
| 20 | package org.gnu.emacs; | ||
| 21 | |||
| 22 | /* Importing the entire package avoids the deprecation warning. */ | ||
| 23 | import android.text.*; | ||
| 24 | |||
| 25 | import android.content.Context; | ||
| 26 | import android.util.Log; | ||
| 27 | |||
| 28 | import java.io.UnsupportedEncodingException; | ||
| 29 | |||
| 30 | /* This class implements EmacsClipboard for Android 2.2 and other | ||
| 31 | similarly old systems. */ | ||
| 32 | |||
| 33 | @SuppressWarnings ("deprecation") | ||
| 34 | public class EmacsSdk8Clipboard extends EmacsClipboard | ||
| 35 | { | ||
| 36 | private static final String TAG = "EmacsSdk8Clipboard"; | ||
| 37 | private ClipboardManager manager; | ||
| 38 | |||
| 39 | public | ||
| 40 | EmacsSdk8Clipboard () | ||
| 41 | { | ||
| 42 | String what; | ||
| 43 | Context context; | ||
| 44 | |||
| 45 | what = Context.CLIPBOARD_SERVICE; | ||
| 46 | context = EmacsService.SERVICE; | ||
| 47 | manager | ||
| 48 | = (ClipboardManager) context.getSystemService (what); | ||
| 49 | } | ||
| 50 | |||
| 51 | /* Set the clipboard text to CLIPBOARD, a string in UTF-8 | ||
| 52 | encoding. */ | ||
| 53 | |||
| 54 | @Override | ||
| 55 | public void | ||
| 56 | setClipboard (byte[] bytes) | ||
| 57 | { | ||
| 58 | try | ||
| 59 | { | ||
| 60 | manager.setText (new String (bytes, "UTF-8")); | ||
| 61 | } | ||
| 62 | catch (UnsupportedEncodingException exception) | ||
| 63 | { | ||
| 64 | Log.w (TAG, "setClipboard: " + exception); | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | /* Return whether or not Emacs owns the clipboard. Value is 1 if | ||
| 69 | Emacs does, 0 if Emacs does not, and -1 if that information is | ||
| 70 | unavailable. */ | ||
| 71 | |||
| 72 | @Override | ||
| 73 | public int | ||
| 74 | ownsClipboard () | ||
| 75 | { | ||
| 76 | return -1; | ||
| 77 | } | ||
| 78 | |||
| 79 | /* Return whether or not clipboard content currently exists. */ | ||
| 80 | |||
| 81 | @Override | ||
| 82 | public boolean | ||
| 83 | clipboardExists () | ||
| 84 | { | ||
| 85 | return manager.hasText (); | ||
| 86 | } | ||
| 87 | |||
| 88 | /* Return the current content of the clipboard, as plain text, or | ||
| 89 | NULL if no content is available. */ | ||
| 90 | |||
| 91 | @Override | ||
| 92 | public byte[] | ||
| 93 | getClipboard () | ||
| 94 | { | ||
| 95 | String string; | ||
| 96 | CharSequence text; | ||
| 97 | |||
| 98 | text = manager.getText (); | ||
| 99 | |||
| 100 | if (text == null) | ||
| 101 | return null; | ||
| 102 | |||
| 103 | string = text.toString (); | ||
| 104 | |||
| 105 | try | ||
| 106 | { | ||
| 107 | return string.getBytes ("UTF-8"); | ||
| 108 | } | ||
| 109 | catch (UnsupportedEncodingException exception) | ||
| 110 | { | ||
| 111 | Log.w (TAG, "getClipboard: " + exception); | ||
| 112 | } | ||
| 113 | |||
| 114 | return null; | ||
| 115 | } | ||
| 116 | }; | ||
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 | |||
| 99 | yet responded to. 0 if there is no such outstanding event. */ | 99 | yet responded to. 0 if there is no such outstanding event. */ |
| 100 | public long pendingConfigure; | 100 | public long pendingConfigure; |
| 101 | 101 | ||
| 102 | /* Whether or not this view is attached to a window. */ | ||
| 103 | public boolean isAttachedToWindow; | ||
| 104 | |||
| 102 | public | 105 | public |
| 103 | EmacsView (EmacsWindow window) | 106 | EmacsView (EmacsWindow window) |
| 104 | { | 107 | { |
| @@ -140,6 +143,9 @@ public class EmacsView extends ViewGroup | |||
| 140 | if (measuredWidth == 0 || measuredHeight == 0) | 143 | if (measuredWidth == 0 || measuredHeight == 0) |
| 141 | return; | 144 | return; |
| 142 | 145 | ||
| 146 | if (!isAttachedToWindow) | ||
| 147 | return; | ||
| 148 | |||
| 143 | /* If bitmap is the same width and height as the measured width | 149 | /* If bitmap is the same width and height as the measured width |
| 144 | and height, there is no need to do anything. Avoid allocating | 150 | and height, there is no need to do anything. Avoid allocating |
| 145 | the extra bitmap. */ | 151 | the extra bitmap. */ |
| @@ -547,6 +553,8 @@ public class EmacsView extends ViewGroup | |||
| 547 | public synchronized void | 553 | public synchronized void |
| 548 | onDetachedFromWindow () | 554 | onDetachedFromWindow () |
| 549 | { | 555 | { |
| 556 | isAttachedToWindow = false; | ||
| 557 | |||
| 550 | synchronized (this) | 558 | synchronized (this) |
| 551 | { | 559 | { |
| 552 | /* Recycle the bitmap and call GC. */ | 560 | /* Recycle the bitmap and call GC. */ |
| @@ -559,6 +567,21 @@ public class EmacsView extends ViewGroup | |||
| 559 | } | 567 | } |
| 560 | } | 568 | } |
| 561 | 569 | ||
| 570 | @Override | ||
| 571 | public synchronized void | ||
| 572 | onAttachedToWindow () | ||
| 573 | { | ||
| 574 | isAttachedToWindow = true; | ||
| 575 | |||
| 576 | /* Dirty the bitmap, as it was destroyed when onDetachedFromWindow | ||
| 577 | was called. */ | ||
| 578 | bitmapDirty = true; | ||
| 579 | |||
| 580 | /* Now expose the view contents again. */ | ||
| 581 | EmacsNative.sendExpose (this.window.handle, 0, 0, | ||
| 582 | measuredWidth, measuredHeight); | ||
| 583 | } | ||
| 584 | |||
| 562 | public void | 585 | public void |
| 563 | showOnScreenKeyboard () | 586 | showOnScreenKeyboard () |
| 564 | { | 587 | { |