1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 06:20:55 -08:00

Merge from savannah/emacs-30

b00fc31dd1 Do not set LD_LIBRARY_PATH during Android initialization
04bf3172f0 ; Set Transient's version
e6f78485aa ; Fix typos in 'which-key-mode' (bug#72093)
This commit is contained in:
Po Lu 2024-07-14 12:47:51 +08:00
commit f9dae55ccc
7 changed files with 153 additions and 153 deletions

View file

@ -378,20 +378,18 @@ definition documents, so your mileage may vary.
@cindex EMACS_CLASS_PATH environment variable, Android @cindex EMACS_CLASS_PATH environment variable, Android
Even when the location of the @command{libandroid-emacs.so} command is Even when the location of the @command{libandroid-emacs.so} command is
known in advance, special configuration is required to run Emacs from known in advance, special preparation is required to run Emacs from
elsewhere than a subprocess of an existing Emacs session, as it must be elsewhere than a subprocess of an existing Emacs session, as it must be
made to understand the location of resources and shared libraries in or made to understand the location of resources and shared libraries in or
extracted from the installed application package. The OS command extracted from the installed application package. The OS command
@command{pm path org.gnu.emacs} will print the location of the @command{pm path org.gnu.emacs} will print the location of the
application package, and the adjacent @file{lib} directory will hold application package, though the said command must be invoked in a
shared libraries extracted from the same, though the said command must peculiar manner to satisfy system restrictions on communication between
be invoked in a peculiar manner to satisfy system restrictions on pseudoterminal devices created by user applications and system services
communication between pseudoterminal devices created by user such as the package manager, which is to say, with the standard IO
applications and system services such as the package manager, which is streams redirected to a real file or a pipe. This value, once
to say, with the standard IO streams redirected to a real file or a established, must be specified in the environment variables
pipe. Such values, once established, must be specified in the @code{EMACS_CLASS_PATH}, so that this sample shell script may be
environment variables @code{EMACS_CLASS_PATH} and
@code{EMACS_LD_LIBRARY_PATH}, so that this sample shell script may be
installed as @code{emacs} in any location that is accessible: installed as @code{emacs} in any location that is accessible:
@example @example
@ -400,7 +398,6 @@ installed as @code{emacs} in any location that is accessible:
package_name=`pm path org.gnu.emacs 2>/dev/null </dev/null \ package_name=`pm path org.gnu.emacs 2>/dev/null </dev/null \
| sed 's/^package://'` | sed 's/^package://'`
emacs= emacs=
ld_path=
EMACS_CLASS_PATH=$package_name EMACS_CLASS_PATH=$package_name
for libdir in `dirname $package_name`/lib/*; do for libdir in `dirname $package_name`/lib/*; do
@ -409,10 +406,7 @@ for libdir in `dirname $package_name`/lib/*; do
&& emacs="$libdir"/libandroid-emacs.so && emacs="$libdir"/libandroid-emacs.so
done done
EMACS_LD_LIBRARY_PATH=$ld_path
export EMACS_CLASS_PATH export EMACS_CLASS_PATH
export EMACS_LD_LIBRARY_PATH
test -x "$emacs" || exit 1 test -x "$emacs" || exit 1
exec $emacs "$@@" exec $emacs "$@@"
@end example @end example

View file

@ -31,7 +31,7 @@ General Public License for more details.
@finalout @finalout
@titlepage @titlepage
@title Transient User and Developer Manual @title Transient User and Developer Manual
@subtitle for version 0.7.2 @subtitle for version 0.7.2.1
@author Jonas Bernoulli @author Jonas Bernoulli
@page @page
@vskip 0pt plus 1filll @vskip 0pt plus 1filll
@ -53,7 +53,7 @@ resource to get over that hurdle is Psionic K's interactive tutorial,
available at @uref{https://github.com/positron-solutions/transient-showcase}. available at @uref{https://github.com/positron-solutions/transient-showcase}.
@noindent @noindent
This manual is for Transient version 0.7.2. This manual is for Transient version 0.7.2.1.
@insertcopying @insertcopying
@end ifnottex @end ifnottex

View file

@ -30,37 +30,69 @@ import java.lang.reflect.Method;
/* Noninteractive Emacs. /* Noninteractive Emacs.
This is the class that libandroid-emacs.so starts. When started, libandroid-emacs.so invokes `app_process(64)' with a
libandroid-emacs.so figures out the system classpath, then starts command line placing Emacs's classes.dex file in the JVM class path,
dalvikvm with the framework jars. which in turn transfers control to `main'. `main' creates a context,
which may be likened to a connection to the system server, and a
At that point, dalvikvm calls main, which sets up the main looper, class loader derived from Emacs's application package, which it loads
creates an ActivityThread and attaches it to the main thread. beforehand. From this class loader, it loads another instance of
itself, and invokes `main1', to ensure the execution of
Then, it obtains an application context for the LoadedApk in the `EmacsNative''s static initializer within the application class
application thread. loader, where a proper library search path is in effect. */
Finally, it obtains the necessary context specific objects and
initializes Emacs. */
@SuppressWarnings ("unchecked") @SuppressWarnings ("unchecked")
public final class EmacsNoninteractive public final class EmacsNoninteractive
{ {
/* Prepare Emacs for startup and call `initEmacs'. This function is
called in an instance of `EmacsNoninteractive' loaded by the APK
ClassLoader acquired in `main', which guarantees that shared
libraries in the APK will be considered in resolving shared
libraries for `EmacsNative'. */
public static void
main1 (String[] args, Context context)
throws Exception
{
AssetManager assets;
String filesDir, libDir, cacheDir;
/* Don't actually start the looper or anything. Instead, obtain
an AssetManager. */
assets = context.getAssets ();
/* Now configure Emacs. The class path should already be set. */
filesDir = context.getFilesDir ().getCanonicalPath ();
libDir = EmacsService.getLibraryDirectory (context);
cacheDir = context.getCacheDir ().getCanonicalPath ();
EmacsNative.setEmacsParams (assets, filesDir,
libDir, cacheDir, 0.0f,
0.0f, 0.0f, null, null,
Build.VERSION.SDK_INT);
/* Now find the dump file that Emacs should use, if it has already
been dumped. */
EmacsApplication.findDumpFile (context);
/* Start Emacs. */
EmacsNative.initEmacs (args, EmacsApplication.dumpFileName);
}
public static void public static void
main (String[] args) main (String[] args)
{ {
Object activityThread, loadedApk; Object activityThread, loadedApk;
Class activityThreadClass, loadedApkClass, contextImplClass; Class activityThreadClass, loadedApkClass, contextImplClass;
Class compatibilityInfoClass; Class compatibilityInfoClass, emacsNoninteractiveClass;
Method method; Method method;
Context context; Context context;
AssetManager assets; ClassLoader classLoader;
String filesDir, libDir, cacheDir;
Looper.prepare (); Looper.prepare ();
context = null; context = null;
assets = null; loadedApkClass = null;
filesDir = libDir = cacheDir = null; classLoader = null;
try try
{ {
@ -72,7 +104,6 @@ public final class EmacsNoninteractive
/* Create and attach the activity thread. */ /* Create and attach the activity thread. */
activityThread = method.invoke (null); activityThread = method.invoke (null);
context = null;
/* Now get an LoadedApk. */ /* Now get an LoadedApk. */
@ -82,99 +113,88 @@ public final class EmacsNoninteractive
} }
catch (ClassNotFoundException exception) catch (ClassNotFoundException exception)
{ {
/* Android 2.2 has no LoadedApk class, but fortunately it /* Android 2.2 has no LoadedApk class; the several following
does not need to be used, since contexts can be statements will load a context and an
directly created. */ ActivityThread.PackageInfo, as is appropriate on this
system. */
}
loadedApkClass = null; /* Get a LoadedApk or ActivityThread.PackageInfo. How to do
contextImplClass = Class.forName ("android.app.ContextImpl"); this varies by Android version. On Android 2.3.3 and
earlier, there is no ``compatibilityInfo'' argument to
getPackageInfo. */
method = activityThreadClass.getDeclaredMethod ("getSystemContext"); if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1)
{
method
= activityThreadClass.getMethod ("getPackageInfo",
String.class,
int.class);
loadedApk = method.invoke (activityThread, "org.gnu.emacs",
(Context.CONTEXT_INCLUDE_CODE
| Context.CONTEXT_IGNORE_SECURITY));
}
else
{
compatibilityInfoClass
= Class.forName ("android.content.res.CompatibilityInfo");
method
= activityThreadClass.getMethod ("getPackageInfo",
String.class,
compatibilityInfoClass,
int.class);
loadedApk = method.invoke (activityThread, "org.gnu.emacs",
null, (Context.CONTEXT_INCLUDE_CODE
| Context.CONTEXT_IGNORE_SECURITY));
}
if (loadedApk == null)
throw new RuntimeException ("getPackageInfo returned NULL");
/* If loadedApkClass remains NULL, substitute the class of
the object returned by getPackageInfo. */
if (loadedApkClass == null)
loadedApkClass = loadedApk.getClass ();
/* Now, get a context. */
contextImplClass = Class.forName ("android.app.ContextImpl");
try
{
method
= contextImplClass.getDeclaredMethod ("createAppContext",
activityThreadClass,
loadedApkClass);
method.setAccessible (true);
context = (Context) method.invoke (null, activityThread,
loadedApk);
}
catch (NoSuchMethodException exception)
{
/* Older Android versions don't have createAppContext, but
instead require creating a ContextImpl, and then
calling createPackageContext. */
method
= activityThreadClass.getDeclaredMethod ("getSystemContext");
context = (Context) method.invoke (activityThread); context = (Context) method.invoke (activityThread);
method = contextImplClass.getDeclaredMethod ("createPackageContext", method
String.class, = contextImplClass.getDeclaredMethod ("createPackageContext",
int.class); String.class,
int.class);
method.setAccessible (true); method.setAccessible (true);
context = (Context) method.invoke (context, "org.gnu.emacs", context = (Context) method.invoke (context, "org.gnu.emacs",
0); 0);
} }
/* If the context has not already been created, then do what /* Retrieve the LoadedApk's class loader and execute the
is appropriate for newer versions of Android. */ remaining portion of the start-up process within its version
of EmacsNoninteractive, which will indicate to the system
that it must load shared libraries from the APK's library
search path. */
if (context == null) method = loadedApkClass.getDeclaredMethod ("getClassLoader");
{ classLoader = (ClassLoader) method.invoke (loadedApk);
/* Get a LoadedApk. How to do this varies by Android version.
On Android 2.3.3 and earlier, there is no
``compatibilityInfo'' argument to getPackageInfo. */
if (Build.VERSION.SDK_INT
<= Build.VERSION_CODES.GINGERBREAD_MR1)
{
method
= activityThreadClass.getMethod ("getPackageInfo",
String.class,
int.class);
loadedApk = method.invoke (activityThread, "org.gnu.emacs",
0);
}
else
{
compatibilityInfoClass
= Class.forName ("android.content.res.CompatibilityInfo");
method
= activityThreadClass.getMethod ("getPackageInfo",
String.class,
compatibilityInfoClass,
int.class);
loadedApk = method.invoke (activityThread, "org.gnu.emacs",
null, 0);
}
if (loadedApk == null)
throw new RuntimeException ("getPackageInfo returned NULL");
/* Now, get a context. */
contextImplClass = Class.forName ("android.app.ContextImpl");
try
{
method
= contextImplClass.getDeclaredMethod ("createAppContext",
activityThreadClass,
loadedApkClass);
method.setAccessible (true);
context = (Context) method.invoke (null, activityThread,
loadedApk);
}
catch (NoSuchMethodException exception)
{
/* Older Android versions don't have createAppContext, but
instead require creating a ContextImpl, and then
calling createPackageContext. */
method
= activityThreadClass.getDeclaredMethod ("getSystemContext");
context = (Context) method.invoke (activityThread);
method
= contextImplClass.getDeclaredMethod ("createPackageContext",
String.class,
int.class);
method.setAccessible (true);
context = (Context) method.invoke (context, "org.gnu.emacs",
0);
}
}
/* Don't actually start the looper or anything. Instead, obtain
an AssetManager. */
assets = context.getAssets ();
/* Now configure Emacs. The class path should already be set. */
filesDir = context.getFilesDir ().getCanonicalPath ();
libDir = EmacsService.getLibraryDirectory (context);
cacheDir = context.getCacheDir ().getCanonicalPath ();
} }
catch (Exception e) catch (Exception e)
{ {
@ -188,16 +208,20 @@ public final class EmacsNoninteractive
System.exit (1); System.exit (1);
} }
EmacsNative.setEmacsParams (assets, filesDir, try
libDir, cacheDir, 0.0f, {
0.0f, 0.0f, null, null, emacsNoninteractiveClass
Build.VERSION.SDK_INT); = classLoader.loadClass ("org.gnu.emacs.EmacsNoninteractive");
method = emacsNoninteractiveClass.getMethod ("main1", String[].class,
/* Now find the dump file that Emacs should use, if it has already Context.class);
been dumped. */ method.setAccessible (true);
EmacsApplication.findDumpFile (context); method.invoke (null, args, context);
}
/* Start Emacs. */ catch (Exception e)
EmacsNative.initEmacs (args, EmacsApplication.dumpFileName); {
System.err.println ("Internal error during startup: " + e);
e.printStackTrace ();
System.exit (1);
}
} }
}; };

View file

@ -5,7 +5,7 @@
;; Author: Jonas Bernoulli <jonas@bernoul.li> ;; Author: Jonas Bernoulli <jonas@bernoul.li>
;; URL: https://github.com/magit/transient ;; URL: https://github.com/magit/transient
;; Keywords: extensions ;; Keywords: extensions
;; Version: 0.7.2 ;; Version: 0.7.2.1
;; SPDX-License-Identifier: GPL-3.0-or-later ;; SPDX-License-Identifier: GPL-3.0-or-later

View file

@ -444,7 +444,7 @@ Note that `which-key-idle-delay' should be set before turning on
If non-nil, save window configuration before which-key buffer is If non-nil, save window configuration before which-key buffer is
shown and restore it after which-key buffer is hidden. It shown and restore it after which-key buffer is hidden. It
prevents which-key from changing window position of visible prevents which-key from changing window position of visible
buffers. Only takken into account when popup type is buffers. Only taken into account when popup type is
side-window." side-window."
:type 'boolean :type 'boolean
:package-version "1.0" :version "30.1") :package-version "1.0" :version "30.1")
@ -2113,7 +2113,7 @@ should be minimized."
(defun which-key--create-pages (keys &optional prefix-keys prefix-title) (defun which-key--create-pages (keys &optional prefix-keys prefix-title)
"Create page strings using `which-key--list-to-pages'. "Create page strings using `which-key--list-to-pages'.
Will try to find the best number of rows and columns using the Will try to find the best number of rows and columns using the
given dimensions and the length and wdiths of KEYS. SEL-WIN-WIDTH given dimensions and the length and widths of KEYS. SEL-WIN-WIDTH
is the width of the live window." is the width of the live window."
(let* ((max-dims (which-key--popup-max-dimensions)) (let* ((max-dims (which-key--popup-max-dimensions))
(max-lines (car max-dims)) (max-lines (car max-dims))
@ -2825,7 +2825,7 @@ Finally, show the buffer."
(funcall which-key-this-command-keys-function))))) (funcall which-key-this-command-keys-function)))))
(cancel-timer which-key--paging-timer) (cancel-timer which-key--paging-timer)
(if which-key-idle-secondary-delay (if which-key-idle-secondary-delay
;; we haven't executed a command yet so the secandary ;; we haven't executed a command yet so the secondary
;; timer is more relevant here ;; timer is more relevant here
(which-key--start-timer which-key-idle-secondary-delay t) (which-key--start-timer which-key-idle-secondary-delay t)
(which-key--start-timer))))))) (which-key--start-timer)))))))

View file

@ -37,7 +37,7 @@ main (int argc, char **argv)
{ {
char **args; char **args;
int i; int i;
char *bootclasspath, *emacs_class_path, *ld_library_path; char *bootclasspath, *emacs_class_path;
/* Allocate enough to hold the arguments to app_process. */ /* Allocate enough to hold the arguments to app_process. */
args = alloca ((10 + argc) * sizeof *args); args = alloca ((10 + argc) * sizeof *args);
@ -63,15 +63,6 @@ main (int argc, char **argv)
return 1; return 1;
} }
/* Restore LD_LIBRARY_PATH to its original value, the app library
directory, to guarantee that it is possible for Java to find the
Emacs C code later. */
ld_library_path = getenv ("EMACS_LD_LIBRARY_PATH");
if (ld_library_path)
setenv ("LD_LIBRARY_PATH", ld_library_path, 1);
if (asprintf (&bootclasspath, "-Djava.class.path=%s", if (asprintf (&bootclasspath, "-Djava.class.path=%s",
emacs_class_path) < 0) emacs_class_path) < 0)
{ {

View file

@ -1338,7 +1338,7 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object,
int pipefd[2]; int pipefd[2];
pthread_t thread; pthread_t thread;
const char *java_string; const char *java_string, *tem;
struct stat statb; struct stat statb;
#ifdef THREADS_ENABLED #ifdef THREADS_ENABLED
@ -1491,15 +1491,6 @@ NATIVE_NAME (setEmacsParams) (JNIEnv *env, jobject object,
EmacsNoninteractive can be found. */ EmacsNoninteractive can be found. */
setenv ("EMACS_CLASS_PATH", android_class_path, 1); setenv ("EMACS_CLASS_PATH", android_class_path, 1);
/* Set LD_LIBRARY_PATH to an appropriate value. */
setenv ("LD_LIBRARY_PATH", android_lib_dir, 1);
/* EMACS_LD_LIBRARY_PATH records the location of the app library
directory. android-emacs refers to this, since users have valid
reasons for changing LD_LIBRARY_PATH to a value that precludes
the possibility of Java locating libemacs later. */
setenv ("EMACS_LD_LIBRARY_PATH", android_lib_dir, 1);
/* If the system is Android 5.0 or later, set LANG to en_US.utf8, /* If the system is Android 5.0 or later, set LANG to en_US.utf8,
which is understood by the C library. In other instances set it which is understood by the C library. In other instances set it
to C, a meaningless value, for good measure. */ to C, a meaningless value, for good measure. */