aboutsummaryrefslogtreecommitdiffstats
path: root/java/README
diff options
context:
space:
mode:
Diffstat (limited to 'java/README')
-rw-r--r--java/README1027
1 files changed, 3 insertions, 1024 deletions
diff --git a/java/README b/java/README
index e518e9fbb2f..a909cdd22ef 100644
--- a/java/README
+++ b/java/README
@@ -22,1027 +22,6 @@ Please keep the Java code indented with tabs and formatted according
22to the rules for C code in the GNU coding standards. Always use 22to the rules for C code in the GNU coding standards. Always use
23C-style comments. 23C-style comments.
24 24
25====================================================================== 25Refer to the file `admin/notes/java' in the toplevel directory of the
26 26Emacs distribution or repository for specifics regarding writing Java
27OVERVIEW OF JAVA 27code for Emacs and the organization of the Android port.
28
29Emacs developers do not know Java, and there is no reason they should
30have to. Thus, the code in this directory is confined to what is
31strictly necessary to support Emacs, and only uses a subset of Java
32written in a way that is easily understandable to C programmers.
33
34Java is required because the entire Android runtime is based around
35Java, and there is no way to write an Android program which runs
36without Java.
37
38This text exists to prime other Emacs developers, already familar with
39C, on the basic architecture of the Android port, and to teach them
40how to read and write the Java code found in this directory.
41
42Java is an object oriented language with automatic memory management
43compiled down to bytecode, which is then subject to interpretation by
44a Java virtual machine.
45
46What that means, is that:
47
48struct emacs_window
49{
50 int some_fields;
51 int of_emacs_window;
52};
53
54static void
55do_something_with_emacs_window (struct emacs_window *a, int n)
56{
57 a->some_fields = a->of_emacs_window + n;
58}
59
60would be written:
61
62public class EmacsWindow
63{
64 public int someFields;
65 public int ofEmacsWindow;
66
67 public void
68 doSomething (int n)
69 {
70 someFields = ofEmacsWindow + n;
71 }
72}
73
74and instead of doing:
75
76do_something_with_emacs_window (my_window, 1);
77
78you say:
79
80myWindow.doSomething (1);
81
82In addition to functions associated with an object of a given class
83(such as EmacsWindow), Java also has two other kinds of functions.
84
85The first are so-called ``static'' functions (the static means
86something entirely different from what it does in C.)
87
88A static function, while still having to be defined within a class,
89can be called without any object. Instead of the object, you write
90the name of the Java class within which it is defined. For example,
91the following C code:
92
93int
94multiply_a_with_b_and_then_add_c (int a, int b, int c)
95{
96 return a * b + c;
97}
98
99would be:
100
101public class EmacsSomething
102{
103 public static int
104 multiplyAWithBAndThenAddC (int a, int b, int c)
105 {
106 return a * b + c;
107 }
108};
109
110Then, instead of calling:
111
112int foo;
113
114foo = multiply_a_with_b_then_add_c (1, 2, 3);
115
116you say:
117
118int foo;
119
120foo = EmacsSomething.multiplyAWithBAndThenAddC (1, 2, 3);
121
122In Java, ``static'' does not mean that the function is only used
123within its compilation unit! Instead, the ``private'' qualifier is
124used to mean more or less the same thing:
125
126static void
127this_procedure_is_only_used_within_this_file (void)
128{
129 do_something ();
130}
131
132becomes
133
134public class EmacsSomething
135{
136 private static void
137 thisProcedureIsOnlyUsedWithinThisClass ()
138 {
139
140 }
141}
142
143the other kind are called ``constructors''. They are functions that
144must be called to allocate memory to hold a class:
145
146public class EmacsFoo
147{
148 int bar;
149
150 public
151 EmacsFoo (int tokenA, int tokenB)
152 {
153 bar = tokenA + tokenB;
154 }
155}
156
157now, the following statement:
158
159EmacsFoo foo;
160
161foo = new EmacsFoo (1, 2);
162
163becomes more or less equivalent to the following C code:
164
165struct emacs_foo
166{
167 int bar;
168};
169
170struct emacs_foo *
171make_emacs_foo (int token_a, int token_b)
172{
173 struct emacs_foo *foo;
174
175 foo = xmalloc (sizeof *foo);
176 foo->bar = token_a + token_b;
177
178 return foo;
179}
180
181/* ... */
182
183struct emacs_foo *foo;
184
185foo = make_emacs_foo (1, 2);
186
187A class may have any number of constructors, or no constructors at
188all, in which case the compiler inserts an empty constructor.
189
190
191
192Sometimes, you will see Java code that looks like this:
193
194 allFiles = filesDirectory.listFiles (new FileFilter () {
195 @Override
196 public boolean
197 accept (File file)
198 {
199 return (!file.isDirectory ()
200 && file.getName ().endsWith (".pdmp"));
201 }
202 });
203
204This is Java's version of GCC's nested function extension. The major
205difference is that the nested function may still be called even after
206it goes out of scope, and always retains a reference to the class and
207local variables around where it was called.
208
209Being an object-oriented language, Java also allows defining that a
210class ``extends'' another class. The following C code:
211
212struct a
213{
214 long thirty_two;
215};
216
217struct b
218{
219 struct a a;
220 long long sixty_four;
221};
222
223extern void do_something (struct a *);
224
225void
226my_function (struct b *b)
227{
228 do_something (&b->a);
229}
230
231is roughly equivalent to the following Java code, split into two
232files:
233
234 A.java
235
236public class A
237{
238 int thirtyTwo;
239
240 public void
241 doSomething ()
242 {
243 etcEtcEtc ();
244 }
245};
246
247 B.java
248
249public class B extends A
250{
251 long sixty_four;
252
253 public static void
254 myFunction (B b)
255 {
256 b.doSomething ();
257 }
258}
259
260the Java runtime has transformed the call to ``b.doSomething'' to
261``((A) b).doSomething''.
262
263However, Java also allows overriding this behavior, by specifying the
264@Override keyword:
265
266public class B extends A
267{
268 long sixty_four;
269
270 @Override
271 public void
272 doSomething ()
273 {
274 Something.doSomethingTwo ();
275 super.doSomething ();
276 }
277}
278
279now, any call to ``doSomething'' on a ``B'' created using ``new B ()''
280will end up calling ``Something.doSomethingTwo'', before calling back
281to ``A.doSomething''. This override also applies in reverse; that is
282to say, even if you write:
283
284 ((A) b).doSomething ();
285
286B's version of doSomething will still be called, if ``b'' was created
287using ``new B ()''.
288
289This mechanism is used extensively throughout the Java language and
290Android windowing APIs.
291
292Elsewhere, you will encounter Java code that defines arrays:
293
294public class EmacsFrobinicator
295{
296 public static void
297 emacsFrobinicate (int something)
298 {
299 int[] primesFromSomething;
300
301 primesFromSomething = new int[numberOfPrimes];
302 /* ... */
303 }
304}
305
306Java arrays are similar to C arrays in that they can not grow. But
307they are very much unlike C arrays in that they are always references
308(as opposed to decaying into pointers in only some situations), and
309contain information about their length.
310
311If another function named ``frobinicate1'' takes an array as an
312argument, then it need not take the length of the array.
313
314Instead, it may simply iterate over the array like so:
315
316int i, k;
317
318for (i = 0; i < array.length; ++i)
319 {
320 k = array[i];
321
322 Whatever.doSomethingWithK (k);
323 }
324
325The syntax used to define arrays is also slightly different. As
326arrays are always references, there is no way for you to tell the
327runtime to allocate an array of size N in a structure (class.)
328
329Instead, if you need an array of that size, you must declare a field
330with the type of the array, and allocate the array inside the class's
331constructor, like so:
332
333public class EmacsArrayContainer
334{
335 public int[] myArray;
336
337 public
338 EmacsArrayContainer ()
339 {
340 myArray = new array[10];
341 }
342}
343
344while in C, you could just have written:
345
346struct emacs_array_container
347{
348 int my_array[10];
349};
350
351or, possibly even better,
352
353typedef int emacs_array_container[10];
354
355Alas, Java has no equivalent of `typedef'.
356
357Like in C, Java string literals are delimited by double quotes.
358Unlike C, however, strings are not NULL-terminated arrays of
359characters, but a distinct type named ``String''. They store their
360own length, characters in Java's 16-bit ``char'' type, and are capable
361of holding NULL bytes.
362
363Instead of writing:
364
365wchar_t character;
366extern char *s;
367size_t s;
368
369 for (/* determine n, s in a loop. */)
370 s += mbstowc (&character, s, n);
371
372or:
373
374const char *byte;
375
376for (byte = my_string; *byte; ++byte)
377 /* do something with *byte. */;
378
379or perhaps even:
380
381size_t length, i;
382char foo;
383
384length = strlen (my_string);
385
386for (i = 0; i < length; ++i)
387 foo = my_string[i];
388
389you write:
390
391char foo;
392int i;
393
394for (i = 0; i < myString.length (); ++i)
395 foo = myString.charAt (0);
396
397Java also has stricter rules on what can be used as a truth value in a
398conditional. While in C, any non-zero value is true, Java requires
399that every truth value be of the boolean type ``boolean''.
400
401What this means is that instead of simply writing:
402
403 if (foo || bar)
404
405where foo can either be 1 or 0, and bar can either be NULL or a
406pointer to something, you must explicitly write:
407
408 if (foo != 0 || bar != null)
409
410in Java.
411
412JAVA NATIVE INTERFACE
413
414Java also provides an interface for C code to interface with Java.
415
416C functions exported from a shared library become static Java
417functions within a class, like so:
418
419public class EmacsNative
420{
421 /* Obtain the fingerprint of this build of Emacs. The fingerprint
422 can be used to determine the dump file name. */
423 public static native String getFingerprint ();
424
425 /* Set certain parameters before initializing Emacs.
426
427 assetManager must be the asset manager associated with the
428 context that is loading Emacs. It is saved and remains for the
429 remainder the lifetime of the Emacs process.
430
431 filesDir must be the package's data storage location for the
432 current Android user.
433
434 libDir must be the package's data storage location for native
435 libraries. It is used as PATH.
436
437 cacheDir must be the package's cache directory. It is used as
438 the `temporary-file-directory'.
439
440 pixelDensityX and pixelDensityY are the DPI values that will be
441 used by Emacs.
442
443 classPath must be the classpath of this app_process process, or
444 NULL.
445
446 emacsService must be the EmacsService singleton, or NULL. */
447 public static native void setEmacsParams (AssetManager assetManager,
448 String filesDir,
449 String libDir,
450 String cacheDir,
451 float pixelDensityX,
452 float pixelDensityY,
453 String classPath,
454 EmacsService emacsService);
455}
456
457Where the corresponding C functions are located in android.c, and
458loaded by the special invocation:
459
460 static
461 {
462 System.loadLibrary ("emacs");
463 };
464
465where ``static'' defines a section of code which will be run upon the
466object (containing class) being loaded. This is like:
467
468 __attribute__((constructor))
469
470on systems where shared object constructors are supported.
471
472See http://docs.oracle.com/en/java/javase/19/docs/specs/jni/intro.html
473for more details.
474
475
476
477OVERVIEW OF ANDROID
478
479When the Android system starts an application, it does not actually
480call the application's ``main'' function. It may not even start the
481application's process if one is already running.
482
483Instead, Android is organized around components. When the user opens
484the ``Emacs'' icon, the Android system looks up and starts the
485component associated with the ``Emacs'' icon. In this case, the
486component is called an activity, and is declared in
487the AndroidManifest.xml in this directory:
488
489 <activity android:name="org.gnu.emacs.EmacsActivity"
490 android:launchMode="singleTop"
491 android:windowSoftInputMode="adjustResize"
492 android:exported="true"
493 android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
494 <intent-filter>
495 <action android:name="android.intent.action.MAIN" />
496 <category android:name="android.intent.category.DEFAULT" />
497 <category android:name="android.intent.category.LAUNCHER" />
498 </intent-filter>
499 </activity>
500
501This tells Android to start the activity defined in ``EmacsActivity''
502(defined in org/gnu/emacs/EmacsActivity.java), a class extending the
503Android class ``Activity''.
504
505To do so, the Android system creates an instance of ``EmacsActivity''
506and the window system window associated with it, and eventually calls:
507
508 Activity activity;
509
510 activity.onCreate (...);
511
512But which ``onCreate'' is really called?
513It is actually the ``onCreate'' defined in EmacsActivity.java, as
514it overrides the ``onCreate'' defined in Android's own Activity class:
515
516 @Override
517 public void
518 onCreate (Bundle savedInstanceState)
519 {
520 FrameLayout.LayoutParams params;
521 Intent intent;
522
523Then, this is what happens step-by-step within the ``onCreate''
524function:
525
526 /* See if Emacs should be started with -Q. */
527 intent = getIntent ();
528 EmacsService.needDashQ
529 = intent.getBooleanExtra ("org.gnu.emacs.START_DASH_Q",
530 false);
531
532Here, Emacs obtains the intent (a request to start a component) which
533was used to start Emacs, and sets a special flag if it contains a
534request for Emacs to start with the ``-Q'' command-line argument.
535
536 /* Set the theme to one without a title bar. */
537
538 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
539 setTheme (android.R.style.Theme_DeviceDefault_NoActionBar);
540 else
541 setTheme (android.R.style.Theme_NoTitleBar);
542
543Next, Emacs sets an appropriate theme for the activity's associated
544window decorations.
545
546 params = new FrameLayout.LayoutParams (LayoutParams.MATCH_PARENT,
547 LayoutParams.MATCH_PARENT);
548
549 /* Make the frame layout. */
550 layout = new FrameLayout (this);
551 layout.setLayoutParams (params);
552
553 /* Set it as the content view. */
554 setContentView (layout);
555
556Then, Emacs creates a ``FrameLayout'', a widget that holds a single
557other widget, and makes it the activity's ``content view''.
558
559The activity itself is a ``FrameLayout'', so the ``layout parameters''
560here apply to the FrameLayout itself, and not its children.
561
562 /* Maybe start the Emacs service if necessary. */
563 EmacsService.startEmacsService (this);
564
565And after that, Emacs calls the static function ``startEmacsService'',
566defined in the class ``EmacsService''. This starts the Emacs service
567component if necessary.
568
569 /* Add this activity to the list of available activities. */
570 EmacsWindowAttachmentManager.MANAGER.registerWindowConsumer (this);
571
572 super.onCreate (savedInstanceState);
573
574Finally, Emacs registers that this activity is now ready to receive
575top-level frames (windows) created from Lisp.
576
577Activities come and go, but Emacs has to stay running in the mean
578time. Thus, Emacs also defines a ``service'', which is a long-running
579component that the Android system allows to run in the background.
580
581Let us go back and review the definition of ``startEmacsService'':
582
583 public static void
584 startEmacsService (Context context)
585 {
586 if (EmacsService.SERVICE == null)
587 {
588 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
589 /* Start the Emacs service now. */
590 context.startService (new Intent (context,
591 EmacsService.class));
592 else
593 /* Display the permanant notification and start Emacs as a
594 foreground service. */
595 context.startForegroundService (new Intent (context,
596 EmacsService.class));
597 }
598 }
599
600If ``EmacsService.SERVICE'' does not yet exist, what this does is to
601tell the ``context'' (the equivalent of an Xlib Display *) to start a
602service defined by the class ``EmacsService''. Eventually, this
603results in ``EmacsService.onCreate'' being called:
604
605 @Override
606 public void
607 onCreate ()
608 {
609 AssetManager manager;
610 Context app_context;
611 String filesDir, libDir, cacheDir, classPath;
612 double pixelDensityX;
613 double pixelDensityY;
614
615Here is what this function does, step-by-step:
616
617 SERVICE = this;
618
619First, it sets the special static variable ``SERVICE'' to ``this'',
620which is a pointer to the ``EmacsService' object that was created.
621
622 handler = new Handler (Looper.getMainLooper ());
623
624Next, it creates a ``Handler'' object for the ``main looper''.
625This is a helper structure which allows executing code on the Android
626user interface thread.
627
628 manager = getAssets ();
629 app_context = getApplicationContext ();
630 metrics = getResources ().getDisplayMetrics ();
631 pixelDensityX = metrics.xdpi;
632 pixelDensityY = metrics.ydpi;
633
634Finally, it obtains:
635
636 - the asset manager, which is used to retrieve assets packaged
637 into the Emacs application package.
638
639 - the application context, used to obtain application specific
640 information.
641
642 - the display metrics, and from them, the X and Y densities in dots
643 per inch.
644
645Then, inside a ``try'' block:
646
647 try
648 {
649 /* Configure Emacs with the asset manager and other necessary
650 parameters. */
651 filesDir = app_context.getFilesDir ().getCanonicalPath ();
652 libDir = getLibraryDirectory ();
653 cacheDir = app_context.getCacheDir ().getCanonicalPath ();
654
655It obtains the names of the Emacs home, shared library, and temporary
656file directories.
657
658 /* Now provide this application's apk file, so a recursive
659 invocation of app_process (through android-emacs) can
660 find EmacsNoninteractive. */
661 classPath = getApkFile ();
662
663The name of the Emacs application package.
664
665 Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir
666 + ", libDir = " + libDir + ", and classPath = " + classPath);
667
668Prints a debug message to the Android system log with this
669information.
670
671 EmacsNative.setEmacsParams (manager, filesDir, libDir,
672 cacheDir, (float) pixelDensityX,
673 (float) pixelDensityY,
674 classPath, this);
675
676And calls the native function ``setEmacsParams'' (defined in
677android.c) to configure Emacs with this information.
678
679 /* Start the thread that runs Emacs. */
680 thread = new EmacsThread (this, needDashQ);
681 thread.start ();
682
683Then, it allocates an ``EmacsThread'' object, and starts that thread.
684Inside that thread is where Emacs's C code runs.
685
686 }
687 catch (IOException exception)
688 {
689 EmacsNative.emacsAbort ();
690 return;
691
692And here is the purpose of the ``try'' block. Functions related to
693file names in Java will signal errors of various types upon failure.
694
695This ``catch'' block means that the Java virtual machine will abort
696execution of the contents of the ``try'' block as soon as an error of
697type ``IOException'' is encountered, and begin executing the contents
698of the ``catch'' block.
699
700Any failure of that type here is a crash, and
701``EmacsNative.emacsAbort'' is called to quickly abort the process to
702get a useful backtrace.
703 }
704 }
705
706Now, let us look at the definition of the class ``EmacsThread'', found
707in org/gnu/emacs/EmacsThread.java:
708
709public class EmacsThread extends Thread
710{
711 /* Whether or not Emacs should be started -Q. */
712 private boolean startDashQ;
713
714 public
715 EmacsThread (EmacsService service, boolean startDashQ)
716 {
717 super ("Emacs main thread");
718 this.startDashQ = startDashQ;
719 }
720
721 @Override
722 public void
723 run ()
724 {
725 String args[];
726
727 if (!startDashQ)
728 args = new String[] { "libandroid-emacs.so", };
729 else
730 args = new String[] { "libandroid-emacs.so", "-Q", };
731
732 /* Run the native code now. */
733 EmacsNative.initEmacs (args, EmacsApplication.dumpFileName);
734 }
735};
736
737The class itself defines a single field, ``startDashQ'', a constructor
738with an unused argument of the type ``EmacsService'' (which is useful
739while debugging) and a flag ``startDashQ'', and a single function
740``run'', overriding the same function in the class ``Thread''.
741
742When ``thread.start'' is called, the Java virtual machine creates a
743new thread, and then calls the function ``run'' within that thread.
744
745This function then computes a suitable argument vector, and calls
746``EmacsNative.initEmacs'' (defined in android.c), which then calls a
747modified version of the regular Emacs ``main'' function.
748
749At that point, Emacs initialization proceeds as usual:
750Vinitial_window_system is set, loadup.el calls `normal-top-level',
751which calls `command-line', and finally
752`window-system-initialization', which initializes the `android'
753terminal interface as usual.
754
755What happens here is the same as on other platforms. Now, here is
756what happens when the initial frame is created: Fx_create_frame calls
757`android_create_frame_window' to create a top level window:
758
759static void
760android_create_frame_window (struct frame *f)
761{
762 struct android_set_window_attributes attributes;
763 enum android_window_value_mask attribute_mask;
764
765 attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
766 attribute_mask = ANDROID_CW_BACK_PIXEL;
767
768 block_input ();
769 FRAME_ANDROID_WINDOW (f)
770 = android_create_window (FRAME_DISPLAY_INFO (f)->root_window,
771 f->left_pos,
772 f->top_pos,
773 FRAME_PIXEL_WIDTH (f),
774 FRAME_PIXEL_HEIGHT (f),
775 attribute_mask, &attributes);
776 unblock_input ();
777}
778
779This calls the function `android_create_window' with some arguments
780whose meanings are identical to the arguments to `XCreateWindow'.
781
782Here is the definition of `android_create_window', in android.c:
783
784android_window
785android_create_window (android_window parent, int x, int y,
786 int width, int height,
787 enum android_window_value_mask value_mask,
788 struct android_set_window_attributes *attrs)
789{
790 static jclass class;
791 static jmethodID constructor;
792 jobject object, parent_object, old;
793 android_window window;
794 android_handle prev_max_handle;
795 bool override_redirect;
796
797What does it do? First, some context:
798
799At any time, there can be at most 65535 Java objects referred to by
800the rest of Emacs through the Java native interface. Each such object
801is assigned a ``handle'' (similar to an XID on X) and given a unique
802type. The function `android_resolve_handle' returns the JNI `jobject'
803associated with a given handle.
804
805 parent_object = android_resolve_handle (parent, ANDROID_HANDLE_WINDOW);
806
807Here, it is being used to look up the `jobject' associated with the
808`parent' handle.
809
810 prev_max_handle = max_handle;
811 window = android_alloc_id ();
812
813Next, `max_handle' is saved, and a new handle is allocated for
814`window'.
815
816 if (!window)
817 error ("Out of window handles!");
818
819An error is signalled if Emacs runs out of available handles.
820
821 if (!class)
822 {
823 class = (*android_java_env)->FindClass (android_java_env,
824 "org/gnu/emacs/EmacsWindow");
825 assert (class != NULL);
826
827Then, if this initialization has not yet been completed, Emacs
828proceeds to find the Java class named ``EmacsWindow''.
829
830 constructor
831 = (*android_java_env)->GetMethodID (android_java_env, class, "<init>",
832 "(SLorg/gnu/emacs/EmacsWindow;"
833 "IIIIZ)V");
834 assert (constructor != NULL);
835
836And it tries to look up the constructor, which should take seven
837arguments:
838
839 S - a short. (the handle ID)
840 Lorg/gnu/Emacs/EmacsWindow; - an instance of the EmacsWindow
841 class. (the parent)
842 IIII - four ints. (the window geometry.)
843 Z - a boolean. (whether or not the
844 window is override-redirect; see
845 XChangeWindowAttributes.)
846
847 old = class;
848 class = (*android_java_env)->NewGlobalRef (android_java_env, class);
849 (*android_java_env)->ExceptionClear (android_java_env);
850 ANDROID_DELETE_LOCAL_REF (old);
851
852Next, it saves a global reference to the class and deletes the local
853reference. Global references will never be deallocated by the Java
854virtual machine as long as they still exist.
855
856 if (!class)
857 memory_full (0);
858 }
859
860 /* N.B. that ANDROID_CW_OVERRIDE_REDIRECT can only be set at window
861 creation time. */
862 override_redirect = ((value_mask
863 & ANDROID_CW_OVERRIDE_REDIRECT)
864 && attrs->override_redirect);
865
866 object = (*android_java_env)->NewObject (android_java_env, class,
867 constructor, (jshort) window,
868 parent_object, (jint) x, (jint) y,
869 (jint) width, (jint) height,
870 (jboolean) override_redirect);
871
872Then, it creates an instance of the ``EmacsWindow'' class with the
873appropriate arguments and previously determined constructor.
874
875 if (!object)
876 {
877 (*android_java_env)->ExceptionClear (android_java_env);
878
879 max_handle = prev_max_handle;
880 memory_full (0);
881
882If creating the object fails, Emacs clears the ``pending exception''
883and signals that it is out of memory.
884 }
885
886 android_handles[window].type = ANDROID_HANDLE_WINDOW;
887 android_handles[window].handle
888 = (*android_java_env)->NewGlobalRef (android_java_env,
889 object);
890 (*android_java_env)->ExceptionClear (android_java_env);
891 ANDROID_DELETE_LOCAL_REF (object);
892
893Otherwise, it associates a new global reference to the object with the
894handle, and deletes the local reference returned from the JNI
895NewObject function.
896
897 if (!android_handles[window].handle)
898 memory_full (0);
899
900If allocating the global reference fails, Emacs signals that it is out
901of memory.
902
903 android_change_window_attributes (window, value_mask, attrs);
904 return window;
905
906Otherwise, it applies the specified window attributes and returns the
907handle of the new window.
908}
909
910
911
912DRAWABLES, CURSORS AND HANDLES
913
914Each widget created by Emacs corresponds to a single ``window'', which
915has its own backing store. This arrangement is quite similar to X.
916
917C code does not directly refer to the EmacsView widgets that implement
918the UI logic behind windows. Instead, its handles refer to
919EmacsWindow structures, which contain the state necessary to interact
920with the widgets in an orderly and synchronized manner.
921
922Like X, both pixmaps and windows are drawable resources, and the same
923graphics operations can be applied to both. Thus, a separate
924EmacsPixmap structure is used to wrap around Android Bitmap resources,
925and the Java-level graphics operation functions are capable of
926operating on them both.
927
928Finally, graphics contexts are maintained on both the C and Java
929levels; the C state recorded in `struct android_gc' is kept in sync
930with the Java state in the GContext handle's corresponding EmacsGC
931structure, and cursors are used through handles that refer to
932EmacsCursor structures that hold system PointerIcons.
933
934In all cases, the interfaces provided are identical to X.
935
936
937
938EVENT LOOP
939
940In a typical Android application, the event loop is managed by the
941operating system, and callbacks (implemented through overriding
942separate functions in widgets) are run by the event loop wherever
943necessary. The thread which runs the event loop is also the only
944thread capable of creating and manipulating widgets and activities,
945and is referred to as the ``UI thread''.
946
947These callbacks are used by Emacs to write representations of X-like
948events to a separate event queue, which are then read from Emacs's own
949event loop running in a separate thread. This is accomplished through
950replacing `select' by a function which waits for the event queue to be
951occupied, in addition to any file descriptors that `select' would
952normally wait for.
953
954Conversely, Emacs's event loop sometimes needs to send events to the
955UI thread. These events are implemented as tiny fragments of code,
956which are run as they are received by the main thread.
957
958A typical example is `displayToast', which is implemented in
959EmacsService.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
978Here, the variable `string' is used by a nested function. This nested
979function contains a copy of that variable, and is run on the main
980thread using the function `runOnUiThread', in order to display a short
981status message on the display.
982
983When Emacs needs to wait for the nested function to finish, it uses a
984mechanism implemented in `syncRunnable'. This mechanism first calls a
985deadlock avoidance mechanism, then runs a nested function on the UI
986thread, which is expected to signal itself as a condition variable
987upon completion. It is typically used to allocate resources that can
988only be allocated from the UI thread, or to obtain non-thread-safe
989information. The following function is an example; it returns a new
990EmacsView 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
1024As no value can be directly returned from the nested function, a
1025separate container object is used to hold the result after the
1026function finishes execution. Note the type name inside the angle
1027brackets: this type is substituted into the class definition as it is
1028used; a definition such as:
1029
1030public class Foo<T>
1031{
1032 T bar;
1033};
1034
1035can not be used alone:
1036
1037 Foo holder; /* Error! */
1038
1039but must have a type specified:
1040
1041 Foo<Object> holder;
1042
1043in which case the effective definition is:
1044
1045public class Foo
1046{
1047 Object bar;
1048};