diff options
| author | Po Lu | 2023-06-17 11:24:54 +0800 |
|---|---|---|
| committer | Po Lu | 2023-06-17 11:24:54 +0800 |
| commit | fa821ed18639aa1b0275c2938af9987c0c71b581 (patch) | |
| tree | 48348b6de19ca0989f598354e818d5df326088de /java | |
| parent | 6999067034b7e2e79326db7c2243150831f0fe99 (diff) | |
| download | emacs-fa821ed18639aa1b0275c2938af9987c0c71b581.tar.gz emacs-fa821ed18639aa1b0275c2938af9987c0c71b581.zip | |
; * java/README: More documentation.
Diffstat (limited to 'java')
| -rw-r--r-- | java/README | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/java/README b/java/README index 96271279c28..a6adb805b9e 100644 --- a/java/README +++ b/java/README | |||
| @@ -906,3 +906,144 @@ of memory. | |||
| 906 | Otherwise, it applies the specified window attributes and returns the | 906 | Otherwise, it applies the specified window attributes and returns the |
| 907 | handle of the new window. | 907 | handle of the new window. |
| 908 | } | 908 | } |
| 909 | |||
| 910 | |||
| 911 | |||
| 912 | DRAWABLES, CURSORS AND HANDLES | ||
| 913 | |||
| 914 | Each widget created by Emacs corresponds to a single ``window'', which | ||
| 915 | has its own backing store. This arrangement is quite similar to X. | ||
| 916 | |||
| 917 | C code does not directly refer to the EmacsView widgets that implement | ||
| 918 | the UI logic behind windows. Instead, its handles refer to | ||
| 919 | EmacsWindow structures, which contain the state necessary to interact | ||
| 920 | with the widgets in an orderly and synchronized manner. | ||
| 921 | |||
| 922 | Like X, both pixmaps and windows are drawable resources, and the same | ||
| 923 | graphics operations can be applied to both. Thus, a separate | ||
| 924 | EmacsPixmap structure is used to wrap around Android Bitmap resources, | ||
| 925 | and the Java-level graphics operation functions are capable of | ||
| 926 | operating on them both. | ||
| 927 | |||
| 928 | Finally, graphics contexts are maintained on both the C and Java | ||
| 929 | levels; the C state recorded in `struct android_gc' is kept in sync | ||
| 930 | with the Java state in the GContext handle's corresponding EmacsGC | ||
| 931 | structure, and cursors are used through handles that refer to | ||
| 932 | EmacsCursor structures that hold system PointerIcons. | ||
| 933 | |||
| 934 | In all cases, the interfaces provided are identical to X. | ||
| 935 | |||
| 936 | |||
| 937 | |||
| 938 | EVENT LOOP | ||
| 939 | |||
| 940 | In a typical Android application, the event loop is managed by the | ||
| 941 | operating system, and callbacks (implemented through overriding | ||
| 942 | separate functions in widgets) are run by the event loop wherever | ||
| 943 | necessary. The thread which runs the event loop is also the only | ||
| 944 | thread capable of creating and manipulating widgets and activities, | ||
| 945 | and is referred to as the ``UI thread''. | ||
| 946 | |||
| 947 | These callbacks are used by Emacs to write representations of X-like | ||
| 948 | events to a separate event queue, which are then read from Emacs's own | ||
| 949 | event loop running in a separate thread. This is accomplished through | ||
| 950 | replacing `select' by a function which waits for the event queue to be | ||
| 951 | occupied, in addition to any file descriptors that `select' would | ||
| 952 | normally wait for. | ||
| 953 | |||
| 954 | Conversely, Emacs's event loop sometimes needs to send events to the | ||
| 955 | UI thread. These events are implemented as tiny fragments of code, | ||
| 956 | which are run as they are received by the main thread. | ||
| 957 | |||
| 958 | A typical example is `displayToast', which is implemented in | ||
| 959 | EmacsService.java: | ||
| 960 | |||
| 961 | public void | ||
| 962 | displayToast (final String string) | ||
| 963 | { | ||
| 964 | runOnUiThread (new Runnable () { | ||
| 965 | @Override | ||
| 966 | public void | ||
| 967 | run () | ||
| 968 | { | ||
| 969 | Toast toast; | ||
| 970 | |||
| 971 | toast = Toast.makeText (getApplicationContext (), | ||
| 972 | string, Toast.LENGTH_SHORT); | ||
| 973 | toast.show (); | ||
| 974 | } | ||
| 975 | }); | ||
| 976 | } | ||
| 977 | |||
| 978 | Here, the variable `string' is used by a nested function. This nested | ||
| 979 | function contains a copy of that variable, and is run on the main | ||
| 980 | thread using the function `runOnUiThread', in order to display a short | ||
| 981 | status message on the display. | ||
| 982 | |||
| 983 | When Emacs needs to wait for the nested function to finish, it uses a | ||
| 984 | mechanism implemented in `syncRunnable'. This mechanism first calls a | ||
| 985 | deadlock avoidance mechanism, then runs a nested function on the UI | ||
| 986 | thread, which is expected to signal itself as a condition variable | ||
| 987 | upon completion. It is typically used to allocate resources that can | ||
| 988 | only be allocated from the UI thread, or to obtain non-thread-safe | ||
| 989 | information. The following function is an example; it returns a new | ||
| 990 | EmacsView widget corresponding to the provided window: | ||
| 991 | |||
| 992 | public EmacsView | ||
| 993 | getEmacsView (final EmacsWindow window, final int visibility, | ||
| 994 | final boolean isFocusedByDefault) | ||
| 995 | { | ||
| 996 | Runnable runnable; | ||
| 997 | final EmacsHolder<EmacsView> view; | ||
| 998 | |||
| 999 | view = new EmacsHolder<EmacsView> (); | ||
| 1000 | |||
| 1001 | runnable = new Runnable () { | ||
| 1002 | public void | ||
| 1003 | run () | ||
| 1004 | { | ||
| 1005 | synchronized (this) | ||
| 1006 | { | ||
| 1007 | view.thing = new EmacsView (window); | ||
| 1008 | view.thing.setVisibility (visibility); | ||
| 1009 | |||
| 1010 | /* The following function is only present on Android 26 | ||
| 1011 | or later. */ | ||
| 1012 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) | ||
| 1013 | view.thing.setFocusedByDefault (isFocusedByDefault); | ||
| 1014 | |||
| 1015 | notify (); | ||
| 1016 | } | ||
| 1017 | } | ||
| 1018 | }; | ||
| 1019 | |||
| 1020 | syncRunnable (runnable); | ||
| 1021 | return view.thing; | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | As no value can be directly returned from the nested function, a | ||
| 1025 | separate container object is used to hold the result after the | ||
| 1026 | function finishes execution. Note the type name inside the angle | ||
| 1027 | brackets: this type is substituted into the class definition as it is | ||
| 1028 | used; a definition such as: | ||
| 1029 | |||
| 1030 | public class Foo<T> | ||
| 1031 | { | ||
| 1032 | T bar; | ||
| 1033 | }; | ||
| 1034 | |||
| 1035 | can not be used alone: | ||
| 1036 | |||
| 1037 | Foo holder; /* Error! */ | ||
| 1038 | |||
| 1039 | but must have a type specified: | ||
| 1040 | |||
| 1041 | Foo<Object> holder; | ||
| 1042 | |||
| 1043 | in which case the effective definition is: | ||
| 1044 | |||
| 1045 | public class Foo | ||
| 1046 | { | ||
| 1047 | Object bar; | ||
| 1048 | }; | ||
| 1049 | |||