commit 01b626ccbcc23798b430121cd300aa337bc9b36e (HEAD, refs/remotes/origin/master) Author: Eli Zaretskii Date: Sat May 4 09:57:05 2024 +0300 ; * etc/NEWS: Fix last change. diff --git a/etc/NEWS b/etc/NEWS index be65a6c0c58..718498cd836 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2427,8 +2427,8 @@ Its warning name is 'docstrings-wide'. Emacs now emits a run-time warning if an Elisp source file being loaded lacks the '-*- lexical-binding: ... -*-' cookie on the first line. See the lexical-binding compiler warning described above for how to make -the warning go away. User init file (whose name is the value of -'user-init-file') is exempt from this warning. +the warning go away. The user's init file (whose name is the value of +'user-init-file') and early-init file are exempt from this warning. --- ** New user option 'native-comp-async-warnings-errors-kind'. commit c74c65f5e1b2b2372910b3ebc41632b730ea46e9 Author: Eli Zaretskii Date: Sat May 4 09:34:18 2024 +0300 ; * etc/NEWS: Fix a recently-added entry. diff --git a/etc/NEWS b/etc/NEWS index d4177d759f3..be65a6c0c58 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2427,7 +2427,8 @@ Its warning name is 'docstrings-wide'. Emacs now emits a run-time warning if an Elisp source file being loaded lacks the '-*- lexical-binding: ... -*-' cookie on the first line. See the lexical-binding compiler warning described above for how to make -the warning go away. +the warning go away. User init file (whose name is the value of +'user-init-file') is exempt from this warning. --- ** New user option 'native-comp-async-warnings-errors-kind'. commit 139931fefb4cde3132ca68c3caa6ee9c4889c1b6 Author: Po Lu Date: Sat May 4 11:36:09 2024 +0800 Simplify management of Android handle IDs * java/org/gnu/emacs/EmacsCursor.java (EmacsCursor): * java/org/gnu/emacs/EmacsGC.java (EmacsGC): * java/org/gnu/emacs/EmacsHandleObject.java (EmacsHandleObject): Remove HANDLE argument to constructor. * java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap): * java/org/gnu/emacs/EmacsWindow.java (EmacsWindow): * java/org/gnu/emacs/EmacsInputConnection.java (EmacsInputConnection) : Change type to long. * java/org/gnu/emacs/EmacsNative.java (EmacsNative) (sendConfigureNotify, sendKeyPress, sendKeyRelease, sendFocusIn) (sendFocusOut, sendWindowAction, sendEnterNotify) (sendLeaveNotify, sendMotionNotify, sendButtonPress) (sendButtonRelease, sendTouchDown, sendTouchUp, sendTouchMove) (sendWheel, sendIconified, sendDeiconified, sendContextMenu) (sendExpose, sendDndDrag, sendDndUri, sendDndText) (beginBatchEdit, commitCompletion, endBatchEdit, commitText) (deleteSurroundingText, finishComposingText, replaceText) (getSelectedText, getTextAfterCursor, getTextBeforeCursor) (setComposingText, setComposingRegion, setSelection) (performEditorAction, performContextMenuAction, getExtractedText) (requestSelectionUpdate, requestCursorUpdates, clearInputFlags) (getSurroundingText, takeSnapshot, getSelection): Accept handles as longs, rather than shorts. All callers changed. * java/org/gnu/emacs/EmacsService.java (queryTree): Return handles as longs rather than shorts. (viewGetSelection): Take long WINDOW, not short. * src/android.c (struct android_emacs_handle): New structure. (handle_class): New variable. (android_init_emacs_service, android_init_emacs_pixmap) (android_init_emacs_gc_class, android_init_emacs_cursor): Adjust to match signature changes in constructors. (android_init_emacs_handle): New function. (initEmacs): Initialize the handle class, its fields and metods. (sendConfigureNotify, sendKeyPress, sendKeyRelease, sendFocusIn) (sendFocusOut, sendWindowAction, sendEnterNotify) (sendLeaveNotify, sendMotionNotify, sendButtonPress) (sendButtonRelease, sendTouchDown, sendTouchUp, sendTouchMove) (sendWheel, sendIconified, sendDeiconified, sendContextMenu) (sendExpose, sendDndDrag, sendDndUri, sendDndText): Update for changes to handle type. (android_alloc_id, android_resolve_handle) (android_resolve_handle2): Remove functions; replace the second with a macro that accepts one fewer argument. All callers changed. (android_destroy_handle): Cease indexing the handle list for the handle object. (android_globalize_reference): New function. (android_create_window, android_create_gc, android_create_pixmap) (android_create_font_cursor): Call android_globalize_reference to convert global references into handles. (android_free_cursor, android_destroy_window): Cease verifying the handle type. (android_copy_area): Check destination object type rather than handle entry. (android_query_tree): Adjust for changes to return types. (likely): Define __builtin_expect variant unconditionally. * src/android.h (android_resolve_handle): New macro. * src/androidgui.h (android_handle): Define to intptr_t. * src/androidterm.c (deleteSurroundingText, finishComposingText) (performEditorAction, performContextMenuAction, getExtractedText) (getSelectedText, requestSelectionUpdate, requestCursorUpdates) (clearInputFlags, getSurroundingText) (android_get_surrounding_text_internal): Accept handles as longs, not jshorts. diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java index 28bb6e4c065..90be9a385cf 100644 --- a/java/org/gnu/emacs/EmacsActivity.java +++ b/java/org/gnu/emacs/EmacsActivity.java @@ -440,8 +440,7 @@ children and RESETWHENCHILDLESS is set (implying it is a if (!EmacsContextMenu.itemAlreadySelected) { serial = EmacsContextMenu.lastMenuEventSerial; - EmacsNative.sendContextMenu ((short) 0, 0, - serial); + EmacsNative.sendContextMenu (0, 0, serial); } super.onContextMenuClosed (menu); diff --git a/java/org/gnu/emacs/EmacsContextMenu.java b/java/org/gnu/emacs/EmacsContextMenu.java index 0f52d45455f..365a7ec40af 100644 --- a/java/org/gnu/emacs/EmacsContextMenu.java +++ b/java/org/gnu/emacs/EmacsContextMenu.java @@ -121,8 +121,7 @@ private static final class Item implements MenuItem.OnMenuItemClickListener } /* Send a context menu event. */ - EmacsNative.sendContextMenu ((short) 0, itemID, - lastMenuEventSerial); + EmacsNative.sendContextMenu (0, itemID, lastMenuEventSerial); /* Say that an item has already been selected. */ itemAlreadySelected = true; diff --git a/java/org/gnu/emacs/EmacsCursor.java b/java/org/gnu/emacs/EmacsCursor.java index 1049c03d7da..e5f22c23cfc 100644 --- a/java/org/gnu/emacs/EmacsCursor.java +++ b/java/org/gnu/emacs/EmacsCursor.java @@ -31,9 +31,9 @@ public final class EmacsCursor extends EmacsHandleObject public final PointerIcon icon; public - EmacsCursor (short handle, int glyph) + EmacsCursor (int glyph) { - super (handle); + super (); if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) { diff --git a/java/org/gnu/emacs/EmacsDialog.java b/java/org/gnu/emacs/EmacsDialog.java index 0d5b650f7d0..31b2969197e 100644 --- a/java/org/gnu/emacs/EmacsDialog.java +++ b/java/org/gnu/emacs/EmacsDialog.java @@ -93,7 +93,7 @@ private final class EmacsButton implements View.OnClickListener, onClick (View view) { wasButtonClicked = true; - EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial); + EmacsNative.sendContextMenu (0, id, menuEventSerial); dismissDialog.dismiss (); } @@ -102,7 +102,7 @@ private final class EmacsButton implements View.OnClickListener, onClick (DialogInterface dialog, int which) { wasButtonClicked = true; - EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial); + EmacsNative.sendContextMenu (0, id, menuEventSerial); } }; @@ -414,6 +414,6 @@ else if (EmacsOpenActivity.currentActivity != null) if (wasButtonClicked) return; - EmacsNative.sendContextMenu ((short) 0, 0, menuEventSerial); + EmacsNative.sendContextMenu (0, 0, menuEventSerial); } }; diff --git a/java/org/gnu/emacs/EmacsGC.java b/java/org/gnu/emacs/EmacsGC.java index bb11f76c800..f956b230f8c 100644 --- a/java/org/gnu/emacs/EmacsGC.java +++ b/java/org/gnu/emacs/EmacsGC.java @@ -71,13 +71,13 @@ public final class EmacsGC extends EmacsHandleObject /* The following fields are only set on immutable GCs. */ public - EmacsGC (short handle) + EmacsGC () { /* For historical reasons the C code has an extra layer of indirection above this GC handle. struct android_gc is the GC used by Emacs code, while android_gcontext is the type of the handle. */ - super (handle); + super (); fill_style = GC_FILL_SOLID; function = GC_COPY; diff --git a/java/org/gnu/emacs/EmacsHandleObject.java b/java/org/gnu/emacs/EmacsHandleObject.java index 8534f08519c..cbd579bac5b 100644 --- a/java/org/gnu/emacs/EmacsHandleObject.java +++ b/java/org/gnu/emacs/EmacsHandleObject.java @@ -33,14 +33,9 @@ public abstract class EmacsHandleObject /* Whether or not this handle has been destroyed. */ volatile boolean destroyed; - /* The handle associated with this object. */ - public short handle; - - public - EmacsHandleObject (short handle) - { - this.handle = handle; - } + /* The handle associated with this object, set in + android_globalize_reference. */ + public long handle; public void destroyHandle () throws IllegalStateException diff --git a/java/org/gnu/emacs/EmacsInputConnection.java b/java/org/gnu/emacs/EmacsInputConnection.java index 054eca66cf3..5b409fa1f57 100644 --- a/java/org/gnu/emacs/EmacsInputConnection.java +++ b/java/org/gnu/emacs/EmacsInputConnection.java @@ -48,7 +48,7 @@ public final class EmacsInputConnection implements InputConnection private EmacsView view; /* The handle ID associated with that view's window. */ - private short windowHandle; + private long windowHandle; /* Number of batch edits currently underway. Used to avoid synchronizing with the Emacs thread after each diff --git a/java/org/gnu/emacs/EmacsNative.java b/java/org/gnu/emacs/EmacsNative.java index acf9e4b204b..b2764edad10 100644 --- a/java/org/gnu/emacs/EmacsNative.java +++ b/java/org/gnu/emacs/EmacsNative.java @@ -108,92 +108,92 @@ public static native void setEmacsParams (AssetManager assetManager, /* Send an ANDROID_CONFIGURE_NOTIFY event. The values of all the functions below are the serials of the events sent. */ - public static native long sendConfigureNotify (short window, long time, + public static native long sendConfigureNotify (long window, long time, int x, int y, int width, int height); /* Send an ANDROID_KEY_PRESS event. */ - public static native long sendKeyPress (short window, long time, int state, + public static native long sendKeyPress (long window, long time, int state, int keyCode, int unicodeChar); /* Send an ANDROID_KEY_RELEASE event. */ - public static native long sendKeyRelease (short window, long time, int state, + public static native long sendKeyRelease (long window, long time, int state, int keyCode, int unicodeChar); /* Send an ANDROID_FOCUS_IN event. */ - public static native long sendFocusIn (short window, long time); + public static native long sendFocusIn (long window, long time); /* Send an ANDROID_FOCUS_OUT event. */ - public static native long sendFocusOut (short window, long time); + public static native long sendFocusOut (long window, long time); /* Send an ANDROID_WINDOW_ACTION event. */ - public static native long sendWindowAction (short window, int action); + public static native long sendWindowAction (long window, int action); /* Send an ANDROID_ENTER_NOTIFY event. */ - public static native long sendEnterNotify (short window, int x, int y, + public static native long sendEnterNotify (long window, int x, int y, long time); /* Send an ANDROID_LEAVE_NOTIFY event. */ - public static native long sendLeaveNotify (short window, int x, int y, + public static native long sendLeaveNotify (long window, int x, int y, long time); /* Send an ANDROID_MOTION_NOTIFY event. */ - public static native long sendMotionNotify (short window, int x, int y, + public static native long sendMotionNotify (long window, int x, int y, long time); /* Send an ANDROID_BUTTON_PRESS event. */ - public static native long sendButtonPress (short window, int x, int y, + public static native long sendButtonPress (long window, int x, int y, long time, int state, int button); /* Send an ANDROID_BUTTON_RELEASE event. */ - public static native long sendButtonRelease (short window, int x, int y, + public static native long sendButtonRelease (long window, int x, int y, long time, int state, int button); /* Send an ANDROID_TOUCH_DOWN event. */ - public static native long sendTouchDown (short window, int x, int y, + public static native long sendTouchDown (long window, int x, int y, long time, int pointerID, int flags); /* Send an ANDROID_TOUCH_UP event. */ - public static native long sendTouchUp (short window, int x, int y, + public static native long sendTouchUp (long window, int x, int y, long time, int pointerID, int flags); /* Send an ANDROID_TOUCH_MOVE event. */ - public static native long sendTouchMove (short window, int x, int y, + public static native long sendTouchMove (long window, int x, int y, long time, int pointerID, int flags); /* Send an ANDROID_WHEEL event. */ - public static native long sendWheel (short window, int x, int y, + public static native long sendWheel (long window, int x, int y, long time, int state, float xDelta, float yDelta); /* Send an ANDROID_ICONIFIED event. */ - public static native long sendIconified (short window); + public static native long sendIconified (long window); /* Send an ANDROID_DEICONIFIED event. */ - public static native long sendDeiconified (short window); + public static native long sendDeiconified (long window); /* Send an ANDROID_CONTEXT_MENU event. */ - public static native long sendContextMenu (short window, int menuEventID, + public static native long sendContextMenu (long window, int menuEventID, int menuEventSerial); /* Send an ANDROID_EXPOSE event. */ - public static native long sendExpose (short window, int x, int y, + public static native long sendExpose (long window, int x, int y, int width, int height); /* Send an ANDROID_DND_DRAG event. */ - public static native long sendDndDrag (short window, int x, int y); + public static native long sendDndDrag (long window, int x, int y); /* Send an ANDROID_DND_URI event. */ - public static native long sendDndUri (short window, int x, int y, + public static native long sendDndUri (long window, int x, int y, String text); /* Send an ANDROID_DND_TEXT event. */ - public static native long sendDndText (short window, int x, int y, + public static native long sendDndText (long window, int x, int y, String text); /* Send an ANDROID_NOTIFICATION_CANCELED event. */ @@ -241,48 +241,48 @@ public static native long sendDndText (short window, int x, int y, /* Input connection functions. These mostly correspond to their counterparts in Android's InputConnection. */ - public static native void beginBatchEdit (short window); - public static native void endBatchEdit (short window); - public static native void commitCompletion (short window, String text, + public static native void beginBatchEdit (long window); + public static native void endBatchEdit (long window); + public static native void commitCompletion (long window, String text, int position); - public static native void commitText (short window, String text, + public static native void commitText (long window, String text, int position); - public static native void deleteSurroundingText (short window, + public static native void deleteSurroundingText (long window, int leftLength, int rightLength); - public static native void finishComposingText (short window); - public static native void replaceText (short window, int start, int end, + public static native void finishComposingText (long window); + public static native void replaceText (long window, int start, int end, String text, int newCursorPosition, TextAttribute attributes); - public static native String getSelectedText (short window, int flags); - public static native String getTextAfterCursor (short window, int length, + public static native String getSelectedText (long window, int flags); + public static native String getTextAfterCursor (long window, int length, int flags); - public static native String getTextBeforeCursor (short window, int length, + public static native String getTextBeforeCursor (long window, int length, int flags); - public static native void setComposingText (short window, String text, + public static native void setComposingText (long window, String text, int newCursorPosition); - public static native void setComposingRegion (short window, int start, + public static native void setComposingRegion (long window, int start, int end); - public static native void setSelection (short window, int start, int end); - public static native void performEditorAction (short window, + public static native void setSelection (long window, int start, int end); + public static native void performEditorAction (long window, int editorAction); - public static native void performContextMenuAction (short window, + public static native void performContextMenuAction (long window, int contextMenuAction); - public static native ExtractedText getExtractedText (short window, + public static native ExtractedText getExtractedText (long window, ExtractedTextRequest req, int flags); - public static native void requestSelectionUpdate (short window); - public static native void requestCursorUpdates (short window, int mode); - public static native void clearInputFlags (short window); - public static native SurroundingText getSurroundingText (short window, + public static native void requestSelectionUpdate (long window); + public static native void requestCursorUpdates (long window, int mode); + public static native void clearInputFlags (long window); + public static native SurroundingText getSurroundingText (long window, int left, int right, int flags); - public static native TextSnapshot takeSnapshot (short window); + public static native TextSnapshot takeSnapshot (long window); /* Return the current value of the selection, or -1 upon failure. */ - public static native int[] getSelection (short window); + public static native int[] getSelection (long window); /* Graphics functions used as replacements for potentially buggy diff --git a/java/org/gnu/emacs/EmacsPixmap.java b/java/org/gnu/emacs/EmacsPixmap.java index c621e2de3c5..bd4e085994e 100644 --- a/java/org/gnu/emacs/EmacsPixmap.java +++ b/java/org/gnu/emacs/EmacsPixmap.java @@ -51,9 +51,9 @@ public final class EmacsPixmap extends EmacsHandleObject private long gcClipRectID; public - EmacsPixmap (short handle, int width, int height, int depth) + EmacsPixmap (int width, int height, int depth) { - super (handle); + super (); if (depth != 1 && depth != 24) throw new IllegalArgumentException ("Invalid depth specified" diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java index 8e459ce4cdc..ced9f599960 100644 --- a/java/org/gnu/emacs/EmacsService.java +++ b/java/org/gnu/emacs/EmacsService.java @@ -514,10 +514,10 @@ invocation of app_process (through android-emacs) can vibrator.vibrate (duration); } - public short[] + public long[] queryTree (EmacsWindow window) { - short[] array; + long[] array; List windowList; int i; @@ -529,7 +529,7 @@ invocation of app_process (through android-emacs) can synchronized (windowList) { - array = new short[windowList.size () + 1]; + array = new long[windowList.size () + 1]; i = 1; array[0] = (window == null @@ -846,7 +846,7 @@ invocation of app_process (through android-emacs) can } public static int[] - viewGetSelection (short window) + viewGetSelection (long window) { int[] selection; diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 961292af527..16ff00070c4 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -170,11 +170,9 @@ private static class Coordinate public boolean preserve, previouslyAttached; public - EmacsWindow (short handle, final EmacsWindow parent, int x, int y, + EmacsWindow (final EmacsWindow parent, int x, int y, int width, int height, boolean overrideRedirect) { - super (handle); - rect = new Rect (x, y, x + width, y + height); pointerMap = new SparseArray (); @@ -205,7 +203,7 @@ private static class Coordinate }); } - scratchGC = new EmacsGC ((short) 0); + scratchGC = new EmacsGC (); /* Create the map of input method-committed strings. Keep at most ten strings in the map. */ diff --git a/java/org/gnu/emacs/EmacsWindowManager.java b/java/org/gnu/emacs/EmacsWindowManager.java index 49f0ebd5841..23dc71dbd29 100644 --- a/java/org/gnu/emacs/EmacsWindowManager.java +++ b/java/org/gnu/emacs/EmacsWindowManager.java @@ -145,7 +145,7 @@ && isWindowEligible (consumer, window)) } } - EmacsNative.sendWindowAction ((short) 0, 0); + EmacsNative.sendWindowAction (0, 0); } public synchronized void diff --git a/src/android.c b/src/android.c index c76afdb9bf2..0dd7702b301 100644 --- a/src/android.c +++ b/src/android.c @@ -129,6 +129,13 @@ struct android_key_character_map jmethodID get_dead_char; }; +struct android_emacs_handle +{ + jclass class; + jmethodID destroy_handle; + jfieldID handle; +}; + /* The API level of the current device. */ static int android_api_level; @@ -214,6 +221,10 @@ static struct android_emacs_cursor cursor_class; /* Various methods associated with the KeyCharacterMap class. */ static struct android_key_character_map key_character_map_class; +/* Various methods and fields associated with the EmacsHandleObject + class. */ +static struct android_emacs_handle handle_class; + /* The time at which Emacs was installed, which also supplies the mtime of asset files. */ struct timespec emacs_installation_time; @@ -1620,7 +1631,7 @@ android_init_emacs_service (void) "Lorg/gnu/emacs/EmacsGC;II)V"); FIND_METHOD (ring_bell, "ringBell", "(I)V"); FIND_METHOD (query_tree, "queryTree", - "(Lorg/gnu/emacs/EmacsWindow;)[S"); + "(Lorg/gnu/emacs/EmacsWindow;)[J"); FIND_METHOD (get_screen_width, "getScreenWidth", "(Z)I"); FIND_METHOD (get_screen_height, "getScreenHeight", "(Z)I"); FIND_METHOD (detect_mouse, "detectMouse", "()Z"); @@ -1723,7 +1734,7 @@ android_init_emacs_pixmap (void) name, signature); \ eassert (pixmap_class.c_name); - FIND_METHOD (constructor_mutable, "", "(SIII)V"); + FIND_METHOD (constructor_mutable, "", "(III)V"); #undef FIND_METHOD } @@ -1876,7 +1887,7 @@ android_init_emacs_cursor (void) name, signature); \ eassert (cursor_class.c_name); - FIND_METHOD (constructor, "", "(SI)V"); + FIND_METHOD (constructor, "", "(I)V"); #undef FIND_METHOD } @@ -1906,6 +1917,42 @@ android_init_key_character_map (void) eassert (key_character_map_class.get_dead_char); } +static void +android_init_emacs_handle (void) +{ + jclass old; + + handle_class.class + = (*android_java_env)->FindClass (android_java_env, + "org/gnu/emacs/EmacsHandleObject"); + eassert (handle_class.class); + + old = handle_class.class; + handle_class.class + = (jclass) (*android_java_env)->NewGlobalRef (android_java_env, + (jobject) old); + ANDROID_DELETE_LOCAL_REF (old); + + if (!handle_class.class) + emacs_abort (); + +#define FIND_METHOD(c_name, name, signature) \ + handle_class.c_name \ + = (*android_java_env)->GetMethodID (android_java_env, \ + handle_class.class, \ + name, signature); \ + eassert (handle_class.c_name); + + FIND_METHOD (destroy_handle, "destroyHandle", "()V"); +#undef FIND_METHOD + + handle_class.handle + = (*android_java_env)->GetFieldID (android_java_env, + handle_class.class, + "handle", "J"); + eassert (handle_class.handle); +} + JNIEXPORT void JNICALL NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv, jobject dump_file_object) @@ -1955,6 +2002,7 @@ NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv, android_init_emacs_window (); android_init_emacs_cursor (); android_init_key_character_map (); + android_init_emacs_handle (); /* Set HOME to the app data directory. */ setenv ("HOME", android_files_dir, 1); @@ -2074,7 +2122,7 @@ NATIVE_NAME (onLowMemory) (JNIEnv *env, jobject object) JNIEXPORT jlong JNICALL NATIVE_NAME (sendConfigureNotify) (JNIEnv *env, jobject object, - jshort window, jlong time, + jlong window, jlong time, jint x, jint y, jint width, jint height) { @@ -2097,7 +2145,7 @@ NATIVE_NAME (sendConfigureNotify) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendKeyPress) (JNIEnv *env, jobject object, - jshort window, jlong time, + jlong window, jlong time, jint state, jint keycode, jint unicode_char) { @@ -2120,7 +2168,7 @@ NATIVE_NAME (sendKeyPress) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendKeyRelease) (JNIEnv *env, jobject object, - jshort window, jlong time, + jlong window, jlong time, jint state, jint keycode, jint unicode_char) { @@ -2143,7 +2191,7 @@ NATIVE_NAME (sendKeyRelease) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendFocusIn) (JNIEnv *env, jobject object, - jshort window, jlong time) + jlong window, jlong time) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2160,7 +2208,7 @@ NATIVE_NAME (sendFocusIn) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendFocusOut) (JNIEnv *env, jobject object, - jshort window, jlong time) + jlong window, jlong time) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2177,7 +2225,7 @@ NATIVE_NAME (sendFocusOut) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendWindowAction) (JNIEnv *env, jobject object, - jshort window, jint action) + jlong window, jint action) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2194,7 +2242,7 @@ NATIVE_NAME (sendWindowAction) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendEnterNotify) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jlong time) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2214,7 +2262,7 @@ NATIVE_NAME (sendEnterNotify) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendLeaveNotify) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jlong time) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2234,7 +2282,7 @@ NATIVE_NAME (sendLeaveNotify) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendMotionNotify) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jlong time) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2254,7 +2302,7 @@ NATIVE_NAME (sendMotionNotify) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendButtonPress) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jlong time, jint state, jint button) { @@ -2277,7 +2325,7 @@ NATIVE_NAME (sendButtonPress) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendButtonRelease) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jlong time, jint state, jint button) { @@ -2300,7 +2348,7 @@ NATIVE_NAME (sendButtonRelease) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendTouchDown) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jlong time, jint pointer_id, jint flags) { @@ -2323,7 +2371,7 @@ NATIVE_NAME (sendTouchDown) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendTouchUp) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jlong time, jint pointer_id, jint flags) { @@ -2346,7 +2394,7 @@ NATIVE_NAME (sendTouchUp) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendTouchMove) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jlong time, jint pointer_id, jint flags) { @@ -2369,7 +2417,7 @@ NATIVE_NAME (sendTouchMove) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendWheel) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jlong time, jint state, jfloat x_delta, jfloat y_delta) { @@ -2393,7 +2441,7 @@ NATIVE_NAME (sendWheel) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendIconified) (JNIEnv *env, jobject object, - jshort window) + jlong window) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2409,7 +2457,7 @@ NATIVE_NAME (sendIconified) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendDeiconified) (JNIEnv *env, jobject object, - jshort window) + jlong window) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2425,7 +2473,7 @@ NATIVE_NAME (sendDeiconified) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendContextMenu) (JNIEnv *env, jobject object, - jshort window, jint menu_event_id, + jlong window, jint menu_event_id, jint menu_event_serial) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2444,7 +2492,7 @@ NATIVE_NAME (sendContextMenu) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendExpose) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jint width, jint height) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2465,7 +2513,7 @@ NATIVE_NAME (sendExpose) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendDndDrag) (JNIEnv *env, jobject object, - jshort window, jint x, jint y) + jlong window, jint x, jint y) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2485,7 +2533,7 @@ NATIVE_NAME (sendDndDrag) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendDndUri) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jstring string) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2522,7 +2570,7 @@ NATIVE_NAME (sendDndUri) (JNIEnv *env, jobject object, JNIEXPORT jlong JNICALL NATIVE_NAME (sendDndText) (JNIEnv *env, jobject object, - jshort window, jint x, jint y, + jlong window, jint x, jint y, jstring string) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -2711,7 +2759,6 @@ NATIVE_NAME (blitRect) (JNIEnv *env, jobject object, x2 = MAX (x2, 0); y2 = MAX (y2, 0); - if (x1 >= src_info.width || x1 >= dest_info.width) x1 = MIN (dest_info.width - 1, src_info.width - 1); @@ -2854,62 +2901,6 @@ NATIVE_NAME (setupSystemThread) (void) This means that every local reference must be explicitly destroyed with DeleteLocalRef. A helper macro is provided to do this. */ -struct android_handle_entry -{ - /* The type. */ - enum android_handle_type type; - - /* The handle. */ - jobject handle; -}; - -/* Table of handles MAX_HANDLE long. */ -struct android_handle_entry android_handles[USHRT_MAX]; - -/* The largest handle ID currently known, but subject to - wraparound. */ -static android_handle max_handle; - -/* Allocate a new, unused, handle identifier. If Emacs is out of - identifiers, return 0. */ - -static android_handle -android_alloc_id (void) -{ - android_handle handle; - - /* 0 is never a valid handle ID. */ - - if (!max_handle) - max_handle++; - - /* See if the handle is already occupied. */ - - if (android_handles[max_handle].handle) - { - /* Look for a fresh unoccupied handle. */ - - handle = max_handle; - max_handle++; - - while (handle != max_handle) - { - ++max_handle; - - /* Make sure the handle is valid. */ - if (!max_handle) - ++max_handle; - - if (!android_handles[max_handle].handle) - return max_handle++; - } - - return ANDROID_NONE; - } - - return max_handle++; -} - /* Destroy the specified handle and mark it as free on the Java side as well. */ @@ -2919,13 +2910,6 @@ android_destroy_handle (android_handle handle) static jclass old, class; static jmethodID method; - if (!android_handles[handle].handle) - { - __android_log_print (ANDROID_LOG_ERROR, __func__, - "Trying to destroy free handle!"); - emacs_abort (); - } - if (!class) { class @@ -2946,8 +2930,7 @@ android_destroy_handle (android_handle handle) ANDROID_DELETE_LOCAL_REF (old); } - (*android_java_env)->CallVoidMethod (android_java_env, - android_handles[handle].handle, + (*android_java_env)->CallVoidMethod (android_java_env, (jobject) handle, method); /* Just clear any exception thrown. If destroying the handle @@ -2956,76 +2939,7 @@ android_destroy_handle (android_handle handle) (*android_java_env)->ExceptionClear (android_java_env); /* Delete the global reference regardless of any error. */ - (*android_java_env)->DeleteGlobalRef (android_java_env, - android_handles[handle].handle); - android_handles[handle].handle = NULL; -} - -jobject -android_resolve_handle (android_handle handle, - enum android_handle_type type) -{ - if (!handle) - /* ANDROID_NONE. */ - return NULL; - - /* CheckJNI will normally ensure that the handle exists and is - the right type, but with a less informative error message. - Don't waste cycles doing our own checking here. */ - -#ifdef ENABLE_CHECKING - - if (!android_handles[handle].handle) - { - __android_log_print (ANDROID_LOG_ERROR, __func__, - "Trying to resolve free handle!"); - emacs_abort (); - } - - if (android_handles[handle].type != type) - { - __android_log_print (ANDROID_LOG_ERROR, __func__, - "Handle has wrong type!"); - emacs_abort (); - } - -#endif /* ENABLE_CHECKING */ - - return android_handles[handle].handle; -} - -static jobject -android_resolve_handle2 (android_handle handle, - enum android_handle_type type, - enum android_handle_type type2) -{ - if (!handle) - return NULL; - - /* CheckJNI will normally ensure that the handle exists and is - the right type, but with a less informative error message. - Don't waste cycles doing our own checking here. */ - -#ifdef ENABLE_CHECKING - - if (!android_handles[handle].handle) - { - __android_log_print (ANDROID_LOG_ERROR, __func__, - "Trying to resolve free handle!"); - emacs_abort (); - } - - if (android_handles[handle].type != type - && android_handles[handle].type != type2) - { - __android_log_print (ANDROID_LOG_ERROR, __func__, - "Handle has wrong type!"); - emacs_abort (); - } - -#endif /* ENABLE_CHECKING */ - - return android_handles[handle].handle; + (*android_java_env)->DeleteGlobalRef (android_java_env, (jobject) handle); } void @@ -3037,7 +2951,7 @@ android_change_window_attributes (android_window handle, jobject window; jint pixel; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); if (value_mask & ANDROID_CW_BACK_PIXEL) { @@ -3051,6 +2965,35 @@ android_change_window_attributes (android_window handle, } } +/* Return a reference to the local reference HANDLE suitable for + indefinite retention and save its value into HANDLE, deleting HANDLE, + or signal an error if such a reference cannot be allocated. */ + +static android_handle +android_globalize_reference (jobject handle) +{ + jobject global; + + /* Though Android 8.0 and later can support an unlimited number of + active local references, they remain inappropriate in threading + configurations for being local to the current thread. */ + + global = (*android_java_env)->NewGlobalRef (android_java_env, + handle); + (*android_java_env)->ExceptionClear (android_java_env); + ANDROID_DELETE_LOCAL_REF (handle); + + if (__builtin_expect (global == NULL, 0)) + error ("JNI global reference reserves exhausted"); + + /* Save the value of this handle into HANDLE. */ + (*android_java_env)->SetLongField (android_java_env, global, + handle_class.handle, + (jlong) global); + verify (sizeof (jlong) >= sizeof (intptr_t)); + return (intptr_t) global; +} + /* Create a new window with the given width, height and attributes. */ @@ -3064,16 +3007,10 @@ android_create_window (android_window parent, int x, int y, static jmethodID constructor; jobject object, parent_object, old; android_window window; - android_handle prev_max_handle; bool override_redirect; - parent_object = android_resolve_handle (parent, ANDROID_HANDLE_WINDOW); - - prev_max_handle = max_handle; - window = android_alloc_id (); + parent_object = android_resolve_handle (parent); - if (!window) - error ("Out of window handles!"); if (!class) { @@ -3083,7 +3020,7 @@ android_create_window (android_window parent, int x, int y, constructor = (*android_java_env)->GetMethodID (android_java_env, class, "", - "(SLorg/gnu/emacs/EmacsWindow;" + "(Lorg/gnu/emacs/EmacsWindow;" "IIIIZ)V"); eassert (constructor != NULL); @@ -3100,28 +3037,12 @@ android_create_window (android_window parent, int x, int y, && attrs->override_redirect); object = (*android_java_env)->NewObject (android_java_env, class, - constructor, (jshort) window, - parent_object, (jint) x, (jint) y, + constructor, parent_object, + (jint) x, (jint) y, (jint) width, (jint) height, (jboolean) override_redirect); - if (!object) - { - (*android_java_env)->ExceptionClear (android_java_env); - - max_handle = prev_max_handle; - memory_full (0); - } - - android_handles[window].type = ANDROID_HANDLE_WINDOW; - android_handles[window].handle - = (*android_java_env)->NewGlobalRef (android_java_env, - object); - (*android_java_env)->ExceptionClear (android_java_env); - ANDROID_DELETE_LOCAL_REF (object); - - if (!android_handles[window].handle) - memory_full (0); - + android_exception_check (); + window = android_globalize_reference (object); android_change_window_attributes (window, value_mask, attrs); return window; } @@ -3139,13 +3060,6 @@ android_set_window_background (android_window window, unsigned long pixel) void android_destroy_window (android_window window) { - if (android_handles[window].type != ANDROID_HANDLE_WINDOW) - { - __android_log_print (ANDROID_LOG_ERROR, __func__, - "Trying to destroy something not a window!"); - emacs_abort (); - } - android_destroy_handle (window); } @@ -3193,7 +3107,7 @@ android_init_emacs_gc_class (void) emacs_gc_constructor = (*android_java_env)->GetMethodID (android_java_env, emacs_gc_class, - "", "(S)V"); + "", "()V"); eassert (emacs_gc_constructor); emacs_gc_mark_dirty @@ -3279,14 +3193,12 @@ android_create_gc (enum android_gc_value_mask mask, struct android_gc_values *values) { struct android_gc *gc; - android_handle prev_max_handle; jobject object; android_init_emacs_gc_class (); gc = xmalloc (sizeof *gc); - prev_max_handle = max_handle; - gc->gcontext = android_alloc_id (); + gc->gcontext = 0; gc->foreground = 0; gc->background = 0xffffff; gc->clip_rects = NULL; @@ -3309,34 +3221,12 @@ android_create_gc (enum android_gc_value_mask mask, gc->dashes = NULL; gc->n_segments = 0; - if (!gc->gcontext) - { - xfree (gc); - error ("Out of GContext handles!"); - } - object = (*android_java_env)->NewObject (android_java_env, emacs_gc_class, - emacs_gc_constructor, - (jshort) gc->gcontext); - - if (!object) - { - (*android_java_env)->ExceptionClear (android_java_env); - - max_handle = prev_max_handle; - memory_full (0); - } - - android_handles[gc->gcontext].type = ANDROID_HANDLE_GCONTEXT; - android_handles[gc->gcontext].handle - = (*android_java_env)->NewGlobalRef (android_java_env, object); - (*android_java_env)->ExceptionClear (android_java_env); - ANDROID_DELETE_LOCAL_REF (object); - - if (!android_handles[gc->gcontext].handle) - memory_full (0); + emacs_gc_constructor); + android_exception_check (); + gc->gcontext = android_globalize_reference (object); android_change_gc (gc, mask, values); return gc; } @@ -3362,8 +3252,7 @@ android_change_gc (struct android_gc *gc, clip_changed = false; android_init_emacs_gc_class (); - gcontext = android_resolve_handle (gc->gcontext, - ANDROID_HANDLE_GCONTEXT); + gcontext = android_resolve_handle (gc->gcontext); if (mask & ANDROID_GC_FOREGROUND) { @@ -3414,8 +3303,7 @@ android_change_gc (struct android_gc *gc, if (mask & ANDROID_GC_CLIP_MASK) { - what = android_resolve_handle (values->clip_mask, - ANDROID_HANDLE_PIXMAP); + what = android_resolve_handle (values->clip_mask); (*android_java_env)->SetObjectField (android_java_env, gcontext, emacs_gc_clip_mask, @@ -3436,8 +3324,7 @@ android_change_gc (struct android_gc *gc, if (mask & ANDROID_GC_STIPPLE) { - what = android_resolve_handle (values->stipple, - ANDROID_HANDLE_PIXMAP); + what = android_resolve_handle (values->stipple); (*android_java_env)->SetObjectField (android_java_env, gcontext, emacs_gc_stipple, @@ -3549,8 +3436,7 @@ android_set_clip_rectangles (struct android_gc *gc, int clip_x_origin, android_init_android_rect_class (); android_init_emacs_gc_class (); - gcontext = android_resolve_handle (gc->gcontext, - ANDROID_HANDLE_GCONTEXT); + gcontext = android_resolve_handle (gc->gcontext); array = (*android_java_env)->NewObjectArray (android_java_env, n_clip_rects, @@ -3623,8 +3509,7 @@ android_set_dashes (struct android_gc *gc, int dash_offset, int i; jobject array, gcontext; - gcontext = android_resolve_handle (gc->gcontext, - ANDROID_HANDLE_GCONTEXT); + gcontext = android_resolve_handle (gc->gcontext); if (n == gc->n_segments && (!gc->dashes || !memcmp (gc->dashes, dash_list, @@ -3692,9 +3577,8 @@ android_reparent_window (android_window w, android_window parent_handle, jobject window, parent; jmethodID method; - window = android_resolve_handle (w, ANDROID_HANDLE_WINDOW); - parent = android_resolve_handle (parent_handle, - ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (w); + parent = android_resolve_handle (parent_handle); method = window_class.reparent_to; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, window, @@ -3708,7 +3592,7 @@ android_clear_window (android_window handle) { jobject window; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, window, @@ -3723,7 +3607,7 @@ android_map_window (android_window handle) jobject window; jmethodID map_window; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); map_window = window_class.map_window; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -3739,7 +3623,7 @@ android_unmap_window (android_window handle) jobject window; jmethodID unmap_window; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); unmap_window = window_class.unmap_window; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -3756,7 +3640,7 @@ android_resize_window (android_window handle, unsigned int width, jobject window; jmethodID resize_window; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); resize_window = window_class.resize_window; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -3774,7 +3658,7 @@ android_move_window (android_window handle, int x, int y) jobject window; jmethodID move_window; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); move_window = window_class.move_window; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -3794,8 +3678,7 @@ android_swap_buffers (struct android_swap_info *swap_info, for (i = 0; i < num_windows; ++i) { - window = android_resolve_handle (swap_info[i].swap_window, - ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (swap_info[i].swap_window); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, window, window_class.class, @@ -3856,11 +3739,8 @@ android_fill_rectangle (android_drawable handle, struct android_gc *gc, { jobject drawable, gcontext; - drawable = android_resolve_handle2 (handle, - ANDROID_HANDLE_WINDOW, - ANDROID_HANDLE_PIXMAP); - gcontext = android_resolve_handle (gc->gcontext, - ANDROID_HANDLE_GCONTEXT); + drawable = android_resolve_handle (handle); + gcontext = android_resolve_handle (gc->gcontext); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, emacs_service, @@ -4527,7 +4407,9 @@ android_copy_area (android_drawable src, android_drawable dest, /* Now damage the destination drawable accordingly, should it be a window. */ - if (android_handles[dest].type == ANDROID_HANDLE_WINDOW) + if ((*android_java_env)->IsInstanceOf (android_java_env, + (jobject) dest, + window_class.class)) android_damage_window (dest, &bounds); fail2: @@ -4573,11 +4455,8 @@ android_fill_polygon (android_drawable drawable, struct android_gc *gc, jobject point, drawable_object, gcontext; int i; - drawable_object = android_resolve_handle2 (drawable, - ANDROID_HANDLE_WINDOW, - ANDROID_HANDLE_PIXMAP); - gcontext = android_resolve_handle (gc->gcontext, - ANDROID_HANDLE_GCONTEXT); + drawable_object = android_resolve_handle (drawable); + gcontext = android_resolve_handle (gc->gcontext); array = (*android_java_env)->NewObjectArray (android_java_env, npoints, @@ -4615,11 +4494,8 @@ android_draw_rectangle (android_drawable handle, struct android_gc *gc, { jobject drawable, gcontext; - drawable = android_resolve_handle2 (handle, - ANDROID_HANDLE_WINDOW, - ANDROID_HANDLE_PIXMAP); - gcontext = android_resolve_handle (gc->gcontext, - ANDROID_HANDLE_GCONTEXT); + drawable = android_resolve_handle (handle); + gcontext = android_resolve_handle (gc->gcontext); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, emacs_service, @@ -4640,11 +4516,8 @@ android_draw_point (android_drawable handle, struct android_gc *gc, { jobject drawable, gcontext; - drawable = android_resolve_handle2 (handle, - ANDROID_HANDLE_WINDOW, - ANDROID_HANDLE_PIXMAP); - gcontext = android_resolve_handle (gc->gcontext, - ANDROID_HANDLE_GCONTEXT); + drawable = android_resolve_handle (handle); + gcontext = android_resolve_handle (gc->gcontext); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, emacs_service, @@ -4664,11 +4537,8 @@ android_draw_line (android_drawable handle, struct android_gc *gc, { jobject drawable, gcontext; - drawable = android_resolve_handle2 (handle, - ANDROID_HANDLE_WINDOW, - ANDROID_HANDLE_PIXMAP); - gcontext = android_resolve_handle (gc->gcontext, - ANDROID_HANDLE_GCONTEXT); + drawable = android_resolve_handle (handle); + gcontext = android_resolve_handle (gc->gcontext); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, emacs_service, @@ -4687,41 +4557,15 @@ android_pixmap android_create_pixmap (unsigned int width, unsigned int height, int depth) { - android_handle prev_max_handle; jobject object; - android_pixmap pixmap; - - /* First, allocate the pixmap handle. */ - prev_max_handle = max_handle; - pixmap = android_alloc_id (); - - if (!pixmap) - error ("Out of pixmap handles!"); object = (*android_java_env)->NewObject (android_java_env, pixmap_class.class, pixmap_class.constructor_mutable, - (jshort) pixmap, (jint) width, (jint) height, (jint) depth); - - if (!object) - { - (*android_java_env)->ExceptionClear (android_java_env); - max_handle = prev_max_handle; - memory_full (0); - } - - android_handles[pixmap].type = ANDROID_HANDLE_PIXMAP; - android_handles[pixmap].handle - = (*android_java_env)->NewGlobalRef (android_java_env, object); - (*android_java_env)->ExceptionClear (android_java_env); - ANDROID_DELETE_LOCAL_REF (object); - - if (!android_handles[pixmap].handle) - memory_full (0); - - return pixmap; + android_exception_check (); + return android_globalize_reference (object); } void @@ -4742,7 +4586,7 @@ android_clear_area (android_window handle, int x, int y, { jobject window; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, window, @@ -4894,8 +4738,7 @@ android_get_image (android_drawable handle, unsigned char *data1, *data2; int i, x; - drawable = android_resolve_handle2 (handle, ANDROID_HANDLE_WINDOW, - ANDROID_HANDLE_PIXMAP); + drawable = android_resolve_handle (handle); /* Look up the drawable and get the bitmap corresponding to it. Then, lock the bitmap's bits. */ @@ -5029,7 +4872,7 @@ android_put_image (android_pixmap handle, struct android_image *image) unsigned char *data_1, *data_2; int i, x; - drawable = android_resolve_handle (handle, ANDROID_HANDLE_PIXMAP); + drawable = android_resolve_handle (handle); /* Look up the drawable and get the bitmap corresponding to it. Then, lock the bitmap's bits. */ @@ -5131,7 +4974,7 @@ android_set_input_focus (android_window handle, unsigned long time) jobject window; jmethodID make_input_focus; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); make_input_focus = window_class.make_input_focus; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -5148,7 +4991,7 @@ android_raise_window (android_window handle) jobject window; jmethodID raise; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); raise = window_class.raise; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -5164,7 +5007,7 @@ android_lower_window (android_window handle) jobject window; jmethodID lower; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); lower = window_class.lower; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -5181,7 +5024,7 @@ android_reconfigure_wm_window (android_window handle, { jobject sibling, window; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); if (!(value_mask & ANDROID_CW_STACK_MODE)) return; @@ -5193,8 +5036,7 @@ android_reconfigure_wm_window (android_window handle, sibling = NULL; if (value_mask & ANDROID_CW_SIBLING) - sibling = android_resolve_handle (values->sibling, - ANDROID_HANDLE_WINDOW); + sibling = android_resolve_handle (values->sibling); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, window, @@ -5214,10 +5056,10 @@ android_query_tree (android_window handle, android_window *root_return, jobject window, array; jsize nelements, i; android_window *children; - jshort *shorts; + jlong *longs; jmethodID method; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); /* window can be NULL, so this is a service method. */ method = service_class.query_tree; @@ -5237,25 +5079,25 @@ android_query_tree (android_window handle, android_window *root_return, /* Now fill in the children. */ children = xnmalloc (nelements - 1, sizeof *children); - shorts - = (*android_java_env)->GetShortArrayElements (android_java_env, array, - NULL); - android_exception_check_nonnull (shorts, array); + longs + = (*android_java_env)->GetLongArrayElements (android_java_env, array, + NULL); + android_exception_check_nonnull (longs, array); for (i = 1; i < nelements; ++i) /* Subtract one from the index into children, since the parent is not included. */ - children[i - 1] = shorts[i]; + children[i - 1] = longs[i]; /* Finally, return the parent and other values. */ *root_return = 0; - *parent_return = shorts[0]; + *parent_return = longs[0]; *children_return = children; *nchildren_return = nelements - 1; /* Release the array contents. */ - (*android_java_env)->ReleaseShortArrayElements (android_java_env, array, - shorts, JNI_ABORT); + (*android_java_env)->ReleaseLongArrayElements (android_java_env, array, + longs, JNI_ABORT); ANDROID_DELETE_LOCAL_REF (array); return 1; @@ -5274,7 +5116,7 @@ android_get_geometry (android_window handle, jmethodID get_geometry; jint *ints; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); get_geometry = window_class.get_window_geometry; window_geometry @@ -5336,7 +5178,7 @@ android_translate_coordinates (android_window src, int x, jmethodID method; jint *ints; - window = android_resolve_handle (src, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (src); method = window_class.translate_coordinates; coordinates = (*android_java_env)->CallNonvirtualObjectMethod (android_java_env, @@ -5504,51 +5346,44 @@ android_wc_lookup_string (android_key_pressed_event *event, /* Now look up the window. */ rc = 0; - if (!android_handles[event->window].handle - || (android_handles[event->window].type - != ANDROID_HANDLE_WINDOW)) + window = android_resolve_handle (event->window); + string + = (*env)->CallNonvirtualObjectMethod (env, window, + window_class.class, + window_class.lookup_string, + (jint) event->serial); + android_exception_check (); + + if (!string) status = ANDROID_LOOKUP_NONE; else { - window = android_handles[event->window].handle; - string - = (*env)->CallNonvirtualObjectMethod (env, window, - window_class.class, - window_class.lookup_string, - (jint) event->serial); - android_exception_check (); - - if (!string) - status = ANDROID_LOOKUP_NONE; - else - { - /* Now return this input method string. */ - characters = (*env)->GetStringChars (env, string, NULL); - android_exception_check_nonnull ((void *) characters, string); + /* Now return this input method string. */ + characters = (*env)->GetStringChars (env, string, NULL); + android_exception_check_nonnull ((void *) characters, string); - /* Establish the size of the the string. */ - size = (*env)->GetStringLength (env, string); + /* Establish the size of the the string. */ + size = (*env)->GetStringLength (env, string); - /* Copy over the string data. */ - for (i = 0; i < MIN ((unsigned int) wchars_buffer, size); ++i) - buffer_return[i] = characters[i]; + /* Copy over the string data. */ + for (i = 0; i < MIN ((unsigned int) wchars_buffer, size); ++i) + buffer_return[i] = characters[i]; - if (i < size) - status = ANDROID_BUFFER_OVERFLOW; - else - status = ANDROID_LOOKUP_CHARS; + if (i < size) + status = ANDROID_BUFFER_OVERFLOW; + else + status = ANDROID_LOOKUP_CHARS; - /* Return the number of characters that should have been - written. */ + /* Return the number of characters that should have been + written. */ - if (size > INT_MAX) - rc = INT_MAX; - else - rc = size; + if (size > INT_MAX) + rc = INT_MAX; + else + rc = size; - (*env)->ReleaseStringChars (env, string, characters); - ANDROID_DELETE_LOCAL_REF (string); - } + (*env)->ReleaseStringChars (env, string, characters); + ANDROID_DELETE_LOCAL_REF (string); } *status_return = status; @@ -5582,8 +5417,7 @@ android_lock_bitmap (android_drawable drawable, jobject object, bitmap; void *data; - object = android_resolve_handle2 (drawable, ANDROID_HANDLE_WINDOW, - ANDROID_HANDLE_PIXMAP); + object = android_resolve_handle (drawable); /* Look up the drawable and get the bitmap corresponding to it. Then, lock the bitmap's bits. */ @@ -5637,7 +5471,7 @@ android_damage_window (android_drawable handle, { jobject drawable; - drawable = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + drawable = android_resolve_handle (handle); /* Post the damage to the drawable. */ (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -5758,7 +5592,7 @@ android_set_dont_focus_on_map (android_window handle, jmethodID method; jobject window; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); method = window_class.set_dont_focus_on_map; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, window, @@ -5775,7 +5609,7 @@ android_set_dont_accept_focus (android_window handle, jmethodID method; jobject window; - window = android_resolve_handle (handle, ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (handle); method = window_class.set_dont_accept_focus; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, window, @@ -5854,7 +5688,7 @@ android_toggle_on_screen_keyboard (android_window window, bool show) jobject object; jmethodID method; - object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW); + object = android_resolve_handle (window); method = window_class.toggle_on_screen_keyboard; /* Now display the on screen keyboard. */ @@ -6115,11 +5949,7 @@ android_build_jstring (const char *text) if global_foo cannot be allocated, and after the global reference is created. */ -#if __GNUC__ >= 3 #define likely(cond) __builtin_expect (cond, 1) -#else /* __GNUC__ < 3 */ -#define likely(cond) (cond) -#endif /* __GNUC__ >= 3 */ /* Check for JNI exceptions and call memory_full in that situation. */ @@ -6831,7 +6661,7 @@ android_recreate_activity (android_window window) jobject object; jmethodID method; - object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW); + object = android_resolve_handle (window); method = window_class.recreate_activity; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, object, @@ -7196,7 +7026,7 @@ android_update_ic (android_window window, ptrdiff_t selection_start, { jobject object; - object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW); + object = android_resolve_handle (window); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, emacs_service, @@ -7233,7 +7063,7 @@ android_reset_ic (android_window window, enum android_ic_mode mode) { jobject object; - object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW); + object = android_resolve_handle (window); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, emacs_service, @@ -7255,7 +7085,7 @@ android_update_extracted_text (android_window window, void *text, jobject object; jmethodID method; - object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW); + object = android_resolve_handle (window); method = service_class.update_extracted_text; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -7289,7 +7119,7 @@ android_update_cursor_anchor_info (android_window window, float x, jobject object; jmethodID method; - object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW); + object = android_resolve_handle (window); method = service_class.update_cursor_anchor_info; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -7324,7 +7154,7 @@ android_set_fullscreen (android_window window, bool fullscreen) if (android_api_level < 16) return 1; - object = android_resolve_handle (window, ANDROID_HANDLE_WINDOW); + object = android_resolve_handle (window); (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, object, @@ -7342,40 +7172,15 @@ android_set_fullscreen (android_window window, bool fullscreen) android_cursor android_create_font_cursor (enum android_cursor_shape shape) { - android_cursor id; - short prev_max_handle; jobject object; - /* First, allocate the cursor handle. */ - prev_max_handle = max_handle; - id = android_alloc_id (); - - if (!id) - error ("Out of cursor handles!"); - /* Next, create the cursor. */ object = (*android_java_env)->NewObject (android_java_env, cursor_class.class, cursor_class.constructor, - (jshort) id, (jint) shape); - if (!object) - { - (*android_java_env)->ExceptionClear (android_java_env); - max_handle = prev_max_handle; - memory_full (0); - } - - android_handles[id].type = ANDROID_HANDLE_CURSOR; - android_handles[id].handle - = (*android_java_env)->NewGlobalRef (android_java_env, object); - (*android_java_env)->ExceptionClear (android_java_env); - ANDROID_DELETE_LOCAL_REF (object); - - if (!android_handles[id].handle) - memory_full (0); - - return id; + android_exception_check (); + return android_globalize_reference (object); } void @@ -7384,8 +7189,8 @@ android_define_cursor (android_window window, android_cursor cursor) jobject window1, cursor1; jmethodID method; - window1 = android_resolve_handle (window, ANDROID_HANDLE_WINDOW); - cursor1 = android_resolve_handle (cursor, ANDROID_HANDLE_CURSOR); + window1 = android_resolve_handle (window); + cursor1 = android_resolve_handle (cursor); method = window_class.define_cursor; (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, @@ -7398,13 +7203,6 @@ android_define_cursor (android_window window, android_cursor cursor) void android_free_cursor (android_cursor cursor) { - if (android_handles[cursor].type != ANDROID_HANDLE_CURSOR) - { - __android_log_print (ANDROID_LOG_ERROR, __func__, - "Trying to destroy something not a CURSOR!"); - emacs_abort (); - } - android_destroy_handle (cursor); } diff --git a/src/android.h b/src/android.h index 7074ca2630c..a582a9b7dff 100644 --- a/src/android.h +++ b/src/android.h @@ -101,16 +101,9 @@ extern ssize_t android_readlinkat (int, const char *restrict, char *restrict, extern double android_pixel_density_x, android_pixel_density_y; extern double android_scaled_pixel_density; -enum android_handle_type - { - ANDROID_HANDLE_WINDOW, - ANDROID_HANDLE_GCONTEXT, - ANDROID_HANDLE_PIXMAP, - ANDROID_HANDLE_CURSOR, - }; - -extern jobject android_resolve_handle (android_handle, - enum android_handle_type); +verify (sizeof (android_handle) == sizeof (jobject)); +#define android_resolve_handle(handle) ((jobject) (handle)) + extern unsigned char *android_lock_bitmap (android_drawable, AndroidBitmapInfo *, jobject *); diff --git a/src/androidfont.c b/src/androidfont.c index 5fd3018b6d4..20a18327ff8 100644 --- a/src/androidfont.c +++ b/src/androidfont.c @@ -657,10 +657,8 @@ androidfont_draw (struct glyph_string *s, int from, int to, verify (sizeof (unsigned int) == sizeof (jint)); info = (struct androidfont_info *) s->font; - gcontext = android_resolve_handle (s->gc->gcontext, - ANDROID_HANDLE_GCONTEXT); - drawable = android_resolve_handle (FRAME_ANDROID_DRAWABLE (s->f), - ANDROID_HANDLE_WINDOW); + gcontext = android_resolve_handle (s->gc->gcontext); + drawable = android_resolve_handle (FRAME_ANDROID_DRAWABLE (s->f)); chars = (*android_java_env)->NewIntArray (android_java_env, to - from); android_exception_check (); diff --git a/src/androidgui.h b/src/androidgui.h index 3b3e08ca024..79e42c7947c 100644 --- a/src/androidgui.h +++ b/src/androidgui.h @@ -19,6 +19,8 @@ along with GNU Emacs. If not, see . */ #ifndef _ANDROID_GUI_H_ #define _ANDROID_GUI_H_ +#include + struct android_char_struct { int rbearing; @@ -30,7 +32,8 @@ struct android_char_struct typedef struct android_char_struct XCharStruct; -typedef unsigned short android_handle; +/* Handles are but JNI handles cast to intptr_t. */ +typedef intptr_t android_handle; typedef android_handle android_pixmap, Emacs_Pixmap; typedef android_handle android_window, Emacs_Window; diff --git a/src/androidmenu.c b/src/androidmenu.c index 362d500ac1a..7d24087fa87 100644 --- a/src/androidmenu.c +++ b/src/androidmenu.c @@ -488,8 +488,7 @@ android_menu_show (struct frame *f, int x, int y, int menuflags, unbind_to (count1, Qnil); /* Now, display the context menu. */ - window = android_resolve_handle (FRAME_ANDROID_WINDOW (f), - ANDROID_HANDLE_WINDOW); + window = android_resolve_handle (FRAME_ANDROID_WINDOW (f)); rc = (*env)->CallNonvirtualBooleanMethod (env, context_menu, menu_class.class, menu_class.display, diff --git a/src/androidterm.c b/src/androidterm.c index 2979e5c1401..f4c071f4519 100644 --- a/src/androidterm.c +++ b/src/androidterm.c @@ -4925,7 +4925,7 @@ android_copy_java_string (JNIEnv *env, jstring string, size_t *length) } JNIEXPORT void JNICALL -NATIVE_NAME (beginBatchEdit) (JNIEnv *env, jobject object, jshort window) +NATIVE_NAME (beginBatchEdit) (JNIEnv *env, jobject object, jlong window) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -4946,7 +4946,7 @@ NATIVE_NAME (beginBatchEdit) (JNIEnv *env, jobject object, jshort window) } JNIEXPORT void JNICALL -NATIVE_NAME (endBatchEdit) (JNIEnv *env, jobject object, jshort window) +NATIVE_NAME (endBatchEdit) (JNIEnv *env, jobject object, jlong window) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -4967,7 +4967,7 @@ NATIVE_NAME (endBatchEdit) (JNIEnv *env, jobject object, jshort window) } JNIEXPORT void JNICALL -NATIVE_NAME (commitCompletion) (JNIEnv *env, jobject object, jshort window, +NATIVE_NAME (commitCompletion) (JNIEnv *env, jobject object, jlong window, jstring completion_text, jint position) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5001,7 +5001,7 @@ NATIVE_NAME (commitCompletion) (JNIEnv *env, jobject object, jshort window, } JNIEXPORT void JNICALL -NATIVE_NAME (commitText) (JNIEnv *env, jobject object, jshort window, +NATIVE_NAME (commitText) (JNIEnv *env, jobject object, jlong window, jstring commit_text, jint position) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5036,7 +5036,7 @@ NATIVE_NAME (commitText) (JNIEnv *env, jobject object, jshort window, JNIEXPORT void JNICALL NATIVE_NAME (deleteSurroundingText) (JNIEnv *env, jobject object, - jshort window, jint left_length, + jlong window, jint left_length, jint right_length) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5059,7 +5059,7 @@ NATIVE_NAME (deleteSurroundingText) (JNIEnv *env, jobject object, JNIEXPORT void JNICALL NATIVE_NAME (finishComposingText) (JNIEnv *env, jobject object, - jshort window) + jlong window) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5080,7 +5080,7 @@ NATIVE_NAME (finishComposingText) (JNIEnv *env, jobject object, } JNIEXPORT void JNICALL -NATIVE_NAME (replaceText) (JNIEnv *env, jobject object, jshort window, +NATIVE_NAME (replaceText) (JNIEnv *env, jobject object, jlong window, jint start, jint end, jobject text, int new_cursor_position, jobject attribute) { @@ -5246,7 +5246,7 @@ android_text_to_string (JNIEnv *env, char *buffer, ptrdiff_t n, } JNIEXPORT jstring JNICALL -NATIVE_NAME (getTextAfterCursor) (JNIEnv *env, jobject object, jshort window, +NATIVE_NAME (getTextAfterCursor) (JNIEnv *env, jobject object, jlong window, jint length, jint flags) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5290,7 +5290,7 @@ NATIVE_NAME (getTextAfterCursor) (JNIEnv *env, jobject object, jshort window, } JNIEXPORT jstring JNICALL -NATIVE_NAME (getTextBeforeCursor) (JNIEnv *env, jobject object, jshort window, +NATIVE_NAME (getTextBeforeCursor) (JNIEnv *env, jobject object, jlong window, jint length, jint flags) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5334,7 +5334,7 @@ NATIVE_NAME (getTextBeforeCursor) (JNIEnv *env, jobject object, jshort window, } JNIEXPORT void JNICALL -NATIVE_NAME (setComposingText) (JNIEnv *env, jobject object, jshort window, +NATIVE_NAME (setComposingText) (JNIEnv *env, jobject object, jlong window, jstring composing_text, jint new_cursor_position) { @@ -5369,7 +5369,7 @@ NATIVE_NAME (setComposingText) (JNIEnv *env, jobject object, jshort window, } JNIEXPORT void JNICALL -NATIVE_NAME (setComposingRegion) (JNIEnv *env, jobject object, jshort window, +NATIVE_NAME (setComposingRegion) (JNIEnv *env, jobject object, jlong window, jint start, jint end) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5391,7 +5391,7 @@ NATIVE_NAME (setComposingRegion) (JNIEnv *env, jobject object, jshort window, } JNIEXPORT void JNICALL -NATIVE_NAME (setSelection) (JNIEnv *env, jobject object, jshort window, +NATIVE_NAME (setSelection) (JNIEnv *env, jobject object, jlong window, jint start, jint end) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5469,7 +5469,7 @@ android_get_selection (void *data) } JNIEXPORT jintArray JNICALL -NATIVE_NAME (getSelection) (JNIEnv *env, jobject object, jshort window) +NATIVE_NAME (getSelection) (JNIEnv *env, jobject object, jlong window) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5508,7 +5508,7 @@ NATIVE_NAME (getSelection) (JNIEnv *env, jobject object, jshort window) JNIEXPORT void JNICALL NATIVE_NAME (performEditorAction) (JNIEnv *env, jobject object, - jshort window, int action) + jlong window, int action) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5560,7 +5560,7 @@ NATIVE_NAME (performEditorAction) (JNIEnv *env, jobject object, JNIEXPORT void JNICALL NATIVE_NAME (performContextMenuAction) (JNIEnv *env, jobject object, - jshort window, int action) + jlong window, int action) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5765,7 +5765,7 @@ android_build_extracted_text (jstring text, ptrdiff_t start, JNIEXPORT jobject JNICALL NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object, - jshort window, jobject request, + jlong window, jobject request, jint flags) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5877,7 +5877,7 @@ NATIVE_NAME (getExtractedText) (JNIEnv *env, jobject ignored_object, JNIEXPORT jstring JNICALL NATIVE_NAME (getSelectedText) (JNIEnv *env, jobject object, - jshort window) + jlong window) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5907,7 +5907,7 @@ NATIVE_NAME (getSelectedText) (JNIEnv *env, jobject object, JNIEXPORT void JNICALL NATIVE_NAME (requestSelectionUpdate) (JNIEnv *env, jobject object, - jshort window) + jlong window) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5929,7 +5929,7 @@ NATIVE_NAME (requestSelectionUpdate) (JNIEnv *env, jobject object, JNIEXPORT void JNICALL NATIVE_NAME (requestCursorUpdates) (JNIEnv *env, jobject object, - jshort window, jint mode) + jlong window, jint mode) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -5958,7 +5958,7 @@ NATIVE_NAME (requestCursorUpdates) (JNIEnv *env, jobject object, JNIEXPORT void JNICALL NATIVE_NAME (clearInputFlags) (JNIEnv *env, jobject object, - jshort window) + jlong window) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -6073,7 +6073,7 @@ android_get_surrounding_text (void *data) Value is the object upon success, else NULL. */ static jobject -android_get_surrounding_text_internal (JNIEnv *env, jshort window, +android_get_surrounding_text_internal (JNIEnv *env, jlong window, jint before_length, jint after_length, ptrdiff_t *conversion_start, @@ -6166,7 +6166,7 @@ android_get_surrounding_text_internal (JNIEnv *env, jshort window, JNIEXPORT jobject JNICALL NATIVE_NAME (getSurroundingText) (JNIEnv *env, jobject object, - jshort window, jint before_length, + jlong window, jint before_length, jint after_length, jint flags) { JNI_STACK_ALIGNMENT_PROLOGUE; @@ -6176,7 +6176,7 @@ NATIVE_NAME (getSurroundingText) (JNIEnv *env, jobject object, } JNIEXPORT jobject JNICALL -NATIVE_NAME (takeSnapshot) (JNIEnv *env, jobject object, jshort window) +NATIVE_NAME (takeSnapshot) (JNIEnv *env, jobject object, jlong window) { JNI_STACK_ALIGNMENT_PROLOGUE; commit 7a7dd87842fde85666208b1ce26882aa83d99107 Author: Po Lu Date: Sat May 4 11:12:16 2024 +0800 ; * src/lread.c (warn_missing_cookie): Fix typo. diff --git a/src/lread.c b/src/lread.c index 2c856f5d42e..a8ea52a888d 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1352,10 +1352,10 @@ warn_missing_cookie (Lisp_Object file) if (!NILP (Fequal (file, Vuser_init_file))) return; - file = CALLN (Fformat, - build_string ("File %s lacks `lexical-binding'" - " directive on its first line"), - file); + msg = CALLN (Fformat, + build_string ("File %s lacks `lexical-binding'" + " directive on its first line"), + file); Vdelayed_warnings_list = Fcons (list2 (Qlexical_binding, msg), Vdelayed_warnings_list); } commit a5acc89712151645525bd2c0e2c90bf46a8e61ec Author: Po Lu Date: Sat May 4 11:11:36 2024 +0800 * src/lread.c (warn_missing_cookie): Exempt the user init file. diff --git a/src/lread.c b/src/lread.c index f9a1a8562cb..2c856f5d42e 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1345,10 +1345,17 @@ close_file_unwind_android_fd (void *ptr) static void warn_missing_cookie (Lisp_Object file) { - Lisp_Object msg = CALLN (Fformat, - build_string ("File %s lacks `lexical-binding'" - " directive on its first line"), - file); + Lisp_Object msg; + + /* The user init file should not be subject to these warnings, as + Emacs doesn't insert cookies into generated init files. */ + if (!NILP (Fequal (file, Vuser_init_file))) + return; + + file = CALLN (Fformat, + build_string ("File %s lacks `lexical-binding'" + " directive on its first line"), + file); Vdelayed_warnings_list = Fcons (list2 (Qlexical_binding, msg), Vdelayed_warnings_list); } commit d0e391957b01f101b214f055cd27bb89c8d6fec9 Author: Stefan Monnier Date: Fri May 3 16:51:57 2024 -0400 * lisp/progmodes/eglot.el (eglot--track-changes-signal): More typo diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index adbcac3c9af..8ba47fe268d 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2707,8 +2707,8 @@ Records BEG, END and PRE-CHANGE-LENGTH locally." ;; reschedule us. nil (run-hooks 'eglot--document-changed-hook) - (setq eglot--change-idle-timer nil)))) - (current-buffer))))) + (setq eglot--change-idle-timer nil))))) + (current-buffer)))) (defvar-local eglot-workspace-configuration () "Configure LSP servers specifically for a given project. commit c9b0e2bd8eb1941da0ec937fc6e65772a8f85304 Author: Stefan Monnier Date: Fri May 3 16:39:10 2024 -0400 * lisp/emacs-lisp/track-changes.el (track-changes-inconsistent-state-p): Typo diff --git a/lisp/emacs-lisp/track-changes.el b/lisp/emacs-lisp/track-changes.el index 368e637387c..6562cc7eb86 100644 --- a/lisp/emacs-lisp/track-changes.el +++ b/lisp/emacs-lisp/track-changes.el @@ -375,7 +375,7 @@ running those hooks. This function tries to detect those situations so clients can decide to postpone their work to a later time when the buffer is hopefully returned to a consistent state." - (or (equal track-changes--buffer-size (buffer-size)) + (or (not (equal track-changes--buffer-size (buffer-size))) inhibit-modification-hooks)) ;;;; Auxiliary functions. commit 3d4918c2f1d10df4051ca7dc1d17decf157adb3f Author: Philip Kaludercic Date: Thu Mar 7 10:21:45 2024 +0100 Query Eglot version via package.el * lisp/progmodes/eglot.el (eglot--version): Remove constant. (eglot--connect): Use 'package-get-version'. diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index c210de39c65..adbcac3c9af 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -565,13 +565,6 @@ This can be useful when using docker to run a language server.") ;;; Constants ;;; -(defconst eglot--version - (eval-when-compile - (when byte-compile-current-file - (require 'lisp-mnt) - (lm-version byte-compile-current-file))) - "The version as a string of this version of Eglot. -It is nil if Eglot is not byte-complied.") (defconst eglot--symbol-kind-names `((1 . "File") (2 . "Module") @@ -1606,8 +1599,10 @@ This docstring appeases checkdoc, that's all." 'network)) (emacs-pid)) :clientInfo - `(:name "Eglot" ,@(when eglot--version - `(:version ,eglot--version))) + (append + '(:name "Eglot") + (let ((v (package-get-version))) + (and v (list :version v)))) ;; Maybe turn trampy `/ssh:foo@bar:/path/to/baz.py' ;; into `/path/to/baz.py', so LSP groks it. :rootPath (file-local-name commit 81bad84a617be38459da313a75719b5627bb15fe Author: Mattias EngdegÄrd Date: Fri May 3 17:58:44 2024 +0200 Warn when loading .el files without lexical-binding declaration This corresponds to the byte-compiler warning for the same issue, here emitted for files that aren't compiled but loaded from source. It should make the planned change to enable lexical binding by default in Emacs 31 go smoother. * src/lread.c (lexical_cookie_t): New type. (lisp_file_lexically_bound_p): Renamed to... (lisp_file_lexical_cookie): ...this, with the return value retyped. * src/lread.c (warn_missing_cookie): New. (Fload): Warn when loading source file and cookie missing. (Feval_buffer): Add LOADING arg; warn when set and cookie missing. * lisp/international/mule.el (load-with-code-conversion): * lisp/startup.el (command-line--load-script): Call eval-buffer with LOADING arg set. * etc/NEWS: Announce. diff --git a/etc/NEWS b/etc/NEWS index e2588afeb40..d4177d759f3 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -2422,6 +2422,13 @@ The warning name is 'docstrings-control-chars'. *** The warning about wide docstrings can now be disabled separately. Its warning name is 'docstrings-wide'. +--- +** Warn about missing 'lexical-binding' directive when loading .el files. +Emacs now emits a run-time warning if an Elisp source file being loaded +lacks the '-*- lexical-binding: ... -*-' cookie on the first line. +See the lexical-binding compiler warning described above for how to make +the warning go away. + --- ** New user option 'native-comp-async-warnings-errors-kind'. It allows control of what kinds of warnings and errors from asynchronous diff --git a/lisp/international/mule.el b/lisp/international/mule.el index a17221e6d21..8875c4f06af 100644 --- a/lisp/international/mule.el +++ b/lisp/international/mule.el @@ -367,7 +367,7 @@ Return t if file exists." (eval-buffer buffer nil ;; This is compatible with what `load' does. (if dump-mode file fullname) - nil t)))) + nil t t)))) (let (kill-buffer-hook kill-buffer-query-functions) (kill-buffer buffer))) (do-after-load-evaluation fullname) diff --git a/lisp/startup.el b/lisp/startup.el index 357a4154e4c..f2532f5254e 100644 --- a/lisp/startup.el +++ b/lisp/startup.el @@ -2935,7 +2935,7 @@ nil default-directory" name) ;; buffer is empty. (when (looking-at "#!") (delete-line)) - (eval-buffer buffer nil file nil t))))) + (eval-buffer buffer nil file nil t t))))) (defun command-line--eval-script (file) (load-with-code-conversion diff --git a/src/lread.c b/src/lread.c index 983fdb883ff..f9a1a8562cb 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1053,13 +1053,19 @@ DEFUN ("get-file-char", Fget_file_char, Sget_file_char, 0, 0, 0, -/* Return true if the lisp code read using READCHARFUN defines a non-nil - `lexical-binding' file variable. After returning, the stream is - positioned following the first line, if it is a comment or #! line, - otherwise nothing is read. */ - -static bool -lisp_file_lexically_bound_p (Lisp_Object readcharfun) +typedef enum { + Cookie_None, /* no cookie */ + Cookie_Dyn, /* explicit dynamic binding */ + Cookie_Lex /* explicit lexical binding */ +} lexical_cookie_t; + +/* Determine if the lisp code read using READCHARFUN defines a + `lexical-binding' file variable return its value. + After returning, the stream is positioned following the first line, + if it is a comment or #! line, otherwise nothing is read. */ + +static lexical_cookie_t +lisp_file_lexical_cookie (Lisp_Object readcharfun) { int ch = READCHAR; @@ -1070,7 +1076,7 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun) { UNREAD (ch); UNREAD ('#'); - return 0; + return Cookie_None; } while (ch != '\n' && ch != EOF) ch = READCHAR; @@ -1083,12 +1089,12 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun) /* The first line isn't a comment, just give up. */ { UNREAD (ch); - return 0; + return Cookie_None; } else /* Look for an appropriate file-variable in the first line. */ { - bool rv = 0; + lexical_cookie_t rv = Cookie_None; enum { NOMINAL, AFTER_FIRST_DASH, AFTER_ASTERIX } beg_end_state = NOMINAL; @@ -1170,7 +1176,7 @@ lisp_file_lexically_bound_p (Lisp_Object readcharfun) if (strcmp (var, "lexical-binding") == 0) /* This is it... */ { - rv = (strcmp (val, "nil") != 0); + rv = strcmp (val, "nil") != 0 ? Cookie_Lex : Cookie_Dyn; break; } } @@ -1336,6 +1342,17 @@ close_file_unwind_android_fd (void *ptr) #endif +static void +warn_missing_cookie (Lisp_Object file) +{ + Lisp_Object msg = CALLN (Fformat, + build_string ("File %s lacks `lexical-binding'" + " directive on its first line"), + file); + Vdelayed_warnings_list = Fcons (list2 (Qlexical_binding, msg), + Vdelayed_warnings_list); +} + DEFUN ("load", Fload, Sload, 1, 5, 0, doc: /* Execute a file of Lisp code named FILE. First try FILE with `.elc' appended, then try with `.el', then try @@ -1785,7 +1802,10 @@ Return t if the file exists and loads successfully. */) } else { - if (lisp_file_lexically_bound_p (Qget_file_char)) + lexical_cookie_t lc = lisp_file_lexical_cookie (Qget_file_char); + if (lc == Cookie_None && !compiled) + warn_missing_cookie (file); + if (lc == Cookie_Lex) Fset (Qlexical_binding, Qt); if (! version || version >= 22) @@ -2618,7 +2638,7 @@ readevalloop (Lisp_Object readcharfun, unbind_to (count, Qnil); } -DEFUN ("eval-buffer", Feval_buffer, Seval_buffer, 0, 5, "", +DEFUN ("eval-buffer", Feval_buffer, Seval_buffer, 0,6, "", doc: /* Execute the accessible portion of current buffer as Lisp code. You can use \\[narrow-to-region] to limit the part of buffer to be evaluated. When called from a Lisp program (i.e., not interactively), this @@ -2635,6 +2655,8 @@ UNIBYTE, if non-nil, specifies `load-convert-to-unibyte' for this DO-ALLOW-PRINT, if non-nil, specifies that output functions in the evaluated code should work normally even if PRINTFLAG is nil, in which case the output is displayed in the echo area. +LOADING, if non-nil, indicates that this call is part of loading a +Lisp source file. This function ignores the current value of the `lexical-binding' variable. Instead it will heed any @@ -2643,7 +2665,8 @@ settings in the buffer, and if there is no such setting, the buffer will be evaluated without lexical binding. This function preserves the position of point. */) - (Lisp_Object buffer, Lisp_Object printflag, Lisp_Object filename, Lisp_Object unibyte, Lisp_Object do_allow_print) + (Lisp_Object buffer, Lisp_Object printflag, Lisp_Object filename, + Lisp_Object unibyte, Lisp_Object do_allow_print, Lisp_Object loading) { specpdl_ref count = SPECPDL_INDEX (); Lisp_Object tem, buf; @@ -2667,7 +2690,10 @@ This function preserves the position of point. */) specbind (Qstandard_output, tem); record_unwind_protect_excursion (); BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); - specbind (Qlexical_binding, lisp_file_lexically_bound_p (buf) ? Qt : Qnil); + lexical_cookie_t lc = lisp_file_lexical_cookie (buf); + if (!NILP (loading) && lc == Cookie_None) + warn_missing_cookie (filename); + specbind (Qlexical_binding, lc == Cookie_Lex ? Qt : Qnil); BUF_TEMP_SET_PT (XBUFFER (buf), BUF_BEGV (XBUFFER (buf))); readevalloop (buf, 0, filename, !NILP (printflag), unibyte, Qnil, Qnil, Qnil); commit b6d4e81a487ce40f5ea6520c53a88a1c2e7359a9 Author: Stefan Monnier Date: Fri May 3 13:23:00 2024 -0400 track-changes.el: Add a workaround for bug#70541 * lisp/emacs-lisp/track-changes.el (track-changes-inconsistent-state-p): New function. * lisp/progmodes/eglot.el (eglot--track-changes-signal): Use it. diff --git a/lisp/emacs-lisp/track-changes.el b/lisp/emacs-lisp/track-changes.el index ac7a99f3c3c..368e637387c 100644 --- a/lisp/emacs-lisp/track-changes.el +++ b/lisp/emacs-lisp/track-changes.el @@ -367,6 +367,17 @@ and re-enable the TRACKER corresponding to ID." ;; as to avoid nested invocations. (cl-pushnew id track-changes--clean-trackers)))) +(defun track-changes-inconsistent-state-p () + "Return whether the current buffer is in an inconsistent state. +Ideally `before/after-change-functions' should be called for each and every +buffer change, but some packages make transient changes without +running those hooks. +This function tries to detect those situations so clients can decide +to postpone their work to a later time when the buffer is hopefully +returned to a consistent state." + (or (equal track-changes--buffer-size (buffer-size)) + inhibit-modification-hooks)) + ;;;; Auxiliary functions. (defun track-changes--clean-state () diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 407707d4122..c210de39c65 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -2694,14 +2694,26 @@ Records BEG, END and PRE-CHANGE-LENGTH locally." ;; who check it as a boolean. (t (setq eglot--recent-changes :pending))) (when eglot--change-idle-timer (cancel-timer eglot--change-idle-timer)) - (let ((buf (current-buffer))) - (setq eglot--change-idle-timer - (run-with-idle-timer - eglot-send-changes-idle-time - nil (lambda () (eglot--when-live-buffer buf - (when eglot--managed-mode - (run-hooks 'eglot--document-changed-hook) - (setq eglot--change-idle-timer nil)))))))) + (setq eglot--change-idle-timer + (run-with-idle-timer + eglot-send-changes-idle-time nil + (lambda (buf) + (eglot--when-live-buffer buf + (when eglot--managed-mode + (if (and (fboundp 'track-changes-inconsistent-state-p) + (track-changes-inconsistent-state-p)) + ;; Not a good time (e.g. in the middle of Quail + ;; thingy, bug#70541), let's reschedule. + ;; Ideally, we'd `run-with-idle-timer' to call + ;; ourselves again but it's kind of a pain to do that + ;; right (because we first have to wait for the + ;; current idle period to end), so we just do + ;; nothing and wait for the next buffer change to + ;; reschedule us. + nil + (run-hooks 'eglot--document-changed-hook) + (setq eglot--change-idle-timer nil)))) + (current-buffer))))) (defvar-local eglot-workspace-configuration () "Configure LSP servers specifically for a given project. commit 15c77f2fce418983147346589158e2f0da97fa43 Author: Ihor Radchenko Date: Fri May 3 10:46:22 2024 +0300 mhtml-mode: Use `run-mode-hook' to run `prog-mode-hook' (bug#70671) * lisp/textmodes/mhtml-mode.el (mhtml-mode): When running hooks simulating inheritance from `prog-mode', use `run-mode-hooks' that honors `delay-mode-hooks' macro. Note that `delay-mode-hooks' is bound to non-nil when major mode body is evaluated, so there is no chance that any major mode-related hooks are executed twice. diff --git a/lisp/textmodes/mhtml-mode.el b/lisp/textmodes/mhtml-mode.el index 0b5c6756ab9..e2de6959dc6 100644 --- a/lisp/textmodes/mhtml-mode.el +++ b/lisp/textmodes/mhtml-mode.el @@ -359,7 +359,7 @@ the rules from `css-mode'." (add-hook 'before-change-functions #'c-foreign-truncate-lit-pos-cache nil t) ;; This is sort of a prog-mode as well as a text mode. - (run-hooks 'prog-mode-hook)) + (run-mode-hooks 'prog-mode-hook)) (put 'mhtml-mode 'flyspell-mode-predicate #'mhtml--flyspell-check-word)