aboutsummaryrefslogtreecommitdiffstats
path: root/java/org/gnu
diff options
context:
space:
mode:
Diffstat (limited to 'java/org/gnu')
-rw-r--r--java/org/gnu/emacs/EmacsActivity.java36
-rw-r--r--java/org/gnu/emacs/EmacsContextMenu.java17
-rw-r--r--java/org/gnu/emacs/EmacsService.java90
-rw-r--r--java/org/gnu/emacs/EmacsWindow.java101
4 files changed, 140 insertions, 104 deletions
diff --git a/java/org/gnu/emacs/EmacsActivity.java b/java/org/gnu/emacs/EmacsActivity.java
index 3237f650240..66a1e41d84c 100644
--- a/java/org/gnu/emacs/EmacsActivity.java
+++ b/java/org/gnu/emacs/EmacsActivity.java
@@ -97,7 +97,7 @@ public class EmacsActivity extends Activity
97 } 97 }
98 98
99 public static void 99 public static void
100 invalidateFocus () 100 invalidateFocus (int whence)
101 { 101 {
102 EmacsWindow oldFocus; 102 EmacsWindow oldFocus;
103 103
@@ -144,7 +144,7 @@ public class EmacsActivity extends Activity
144 layout.removeView (window.view); 144 layout.removeView (window.view);
145 window = null; 145 window = null;
146 146
147 invalidateFocus (); 147 invalidateFocus (0);
148 } 148 }
149 } 149 }
150 150
@@ -172,8 +172,17 @@ public class EmacsActivity extends Activity
172 if (isPaused) 172 if (isPaused)
173 window.noticeIconified (); 173 window.noticeIconified ();
174 174
175 /* Invalidate the focus. */ 175 /* Invalidate the focus. Since attachWindow may be called from
176 invalidateFocus (); 176 either the main or the UI thread, post this to the UI thread. */
177
178 runOnUiThread (new Runnable () {
179 @Override
180 public void
181 run ()
182 {
183 invalidateFocus (1);
184 }
185 });
177 } 186 }
178 187
179 @Override 188 @Override
@@ -238,6 +247,10 @@ public class EmacsActivity extends Activity
238 } 247 }
239 248
240 super.onCreate (savedInstanceState); 249 super.onCreate (savedInstanceState);
250
251 /* Call `onWindowFocusChanged' to read the focus state, which fails
252 to be called after an activity is recreated. */
253 onWindowFocusChanged (false);
241 } 254 }
242 255
243 @Override 256 @Override
@@ -261,7 +274,7 @@ public class EmacsActivity extends Activity
261 isMultitask = this instanceof EmacsMultitaskActivity; 274 isMultitask = this instanceof EmacsMultitaskActivity;
262 manager.removeWindowConsumer (this, isMultitask || isFinishing ()); 275 manager.removeWindowConsumer (this, isMultitask || isFinishing ());
263 focusedActivities.remove (this); 276 focusedActivities.remove (this);
264 invalidateFocus (); 277 invalidateFocus (2);
265 278
266 /* Remove this activity from the static field, lest it leak. */ 279 /* Remove this activity from the static field, lest it leak. */
267 if (lastFocusedActivity == this) 280 if (lastFocusedActivity == this)
@@ -274,9 +287,16 @@ public class EmacsActivity extends Activity
274 public final void 287 public final void
275 onWindowFocusChanged (boolean isFocused) 288 onWindowFocusChanged (boolean isFocused)
276 { 289 {
277 if (isFocused && !focusedActivities.contains (this)) 290 /* At times and on certain versions of Android ISFOCUSED does not
291 reflect whether the window actually holds focus, so replace it
292 with the value of `hasWindowFocus'. */
293 isFocused = hasWindowFocus ();
294
295 if (isFocused)
278 { 296 {
279 focusedActivities.add (this); 297 if (!focusedActivities.contains (this))
298 focusedActivities.add (this);
299
280 lastFocusedActivity = this; 300 lastFocusedActivity = this;
281 301
282 /* Update the window insets as the focus change may have 302 /* Update the window insets as the focus change may have
@@ -291,7 +311,7 @@ public class EmacsActivity extends Activity
291 else 311 else
292 focusedActivities.remove (this); 312 focusedActivities.remove (this);
293 313
294 invalidateFocus (); 314 invalidateFocus (3);
295 } 315 }
296 316
297 @Override 317 @Override
diff --git a/java/org/gnu/emacs/EmacsContextMenu.java b/java/org/gnu/emacs/EmacsContextMenu.java
index 17e6033377d..2bbf2a313d6 100644
--- a/java/org/gnu/emacs/EmacsContextMenu.java
+++ b/java/org/gnu/emacs/EmacsContextMenu.java
@@ -361,8 +361,23 @@ public final class EmacsContextMenu
361 public Boolean 361 public Boolean
362 call () 362 call ()
363 { 363 {
364 boolean rc;
365
364 lastMenuEventSerial = serial; 366 lastMenuEventSerial = serial;
365 return display1 (window, xPosition, yPosition); 367 rc = display1 (window, xPosition, yPosition);
368
369 /* Android 3.0 to Android 7.0 perform duplicate calls to
370 onContextMenuClosed the second time a context menu is
371 dismissed. Since the second call after such a dismissal is
372 otherwise liable to prematurely cancel any context menu
373 displayed immediately afterwards, ignore calls received
374 within 150 milliseconds of this menu's being displayed. */
375
376 if (rc && Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB
377 && Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
378 wasSubmenuSelected = System.currentTimeMillis () - 150;
379
380 return rc;
366 } 381 }
367 }); 382 });
368 383
diff --git a/java/org/gnu/emacs/EmacsService.java b/java/org/gnu/emacs/EmacsService.java
index 5cb1ceca0aa..d17ba597d8e 100644
--- a/java/org/gnu/emacs/EmacsService.java
+++ b/java/org/gnu/emacs/EmacsService.java
@@ -60,6 +60,7 @@ import android.content.UriPermission;
60import android.content.pm.PackageManager; 60import android.content.pm.PackageManager;
61 61
62import android.content.res.AssetManager; 62import android.content.res.AssetManager;
63import android.content.res.Configuration;
63 64
64import android.hardware.input.InputManager; 65import android.hardware.input.InputManager;
65 66
@@ -135,6 +136,10 @@ public final class EmacsService extends Service
135 been created yet. */ 136 been created yet. */
136 private EmacsSafThread storageThread; 137 private EmacsSafThread storageThread;
137 138
139 /* The Thread object representing the Android user interface
140 thread. */
141 private Thread mainThread;
142
138 static 143 static
139 { 144 {
140 servicingQuery = new AtomicInteger (); 145 servicingQuery = new AtomicInteger ();
@@ -235,6 +240,7 @@ public final class EmacsService extends Service
235 / metrics.density) 240 / metrics.density)
236 * pixelDensityX); 241 * pixelDensityX);
237 resolver = getContentResolver (); 242 resolver = getContentResolver ();
243 mainThread = Thread.currentThread ();
238 244
239 /* If the density used to compute the text size is lesser than 245 /* If the density used to compute the text size is lesser than
240 160, there's likely a bug with display density computation. 246 160, there's likely a bug with display density computation.
@@ -383,7 +389,13 @@ public final class EmacsService extends Service
383 { 389 {
384 if (DEBUG_THREADS) 390 if (DEBUG_THREADS)
385 { 391 {
386 if (Thread.currentThread () instanceof EmacsThread) 392 /* When SERVICE is NULL, Emacs is being executed non-interactively. */
393 if (SERVICE == null
394 /* It was previously assumed that only instances of
395 `EmacsThread' were valid for graphics calls, but this is
396 no longer true now that Lisp threads can be attached to
397 the JVM. */
398 || (Thread.currentThread () != SERVICE.mainThread))
387 return; 399 return;
388 400
389 throw new RuntimeException ("Emacs thread function" 401 throw new RuntimeException ("Emacs thread function"
@@ -437,21 +449,6 @@ public final class EmacsService extends Service
437 EmacsDrawPoint.perform (drawable, gc, x, y); 449 EmacsDrawPoint.perform (drawable, gc, x, y);
438 } 450 }
439 451
440 public void
441 clearWindow (EmacsWindow window)
442 {
443 checkEmacsThread ();
444 window.clearWindow ();
445 }
446
447 public void
448 clearArea (EmacsWindow window, int x, int y, int width,
449 int height)
450 {
451 checkEmacsThread ();
452 window.clearArea (x, y, width, height);
453 }
454
455 @SuppressWarnings ("deprecation") 452 @SuppressWarnings ("deprecation")
456 public void 453 public void
457 ringBell (int duration) 454 ringBell (int duration)
@@ -581,6 +578,15 @@ public final class EmacsService extends Service
581 return false; 578 return false;
582 } 579 }
583 580
581 public boolean
582 detectKeyboard ()
583 {
584 Configuration configuration;
585
586 configuration = getResources ().getConfiguration ();
587 return configuration.keyboard != Configuration.KEYBOARD_NOKEYS;
588 }
589
584 public String 590 public String
585 nameKeysym (int keysym) 591 nameKeysym (int keysym)
586 { 592 {
@@ -905,48 +911,6 @@ public final class EmacsService extends Service
905 911
906 /* Content provider functions. */ 912 /* Content provider functions. */
907 913
908 /* Return a ContentResolver capable of accessing as many files as
909 possible, namely the content resolver of the last selected
910 activity if available: only they posses the rights to access drag
911 and drop files. */
912
913 public ContentResolver
914 getUsefulContentResolver ()
915 {
916 EmacsActivity activity;
917
918 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
919 /* Since the system predates drag and drop, return this resolver
920 to avoid any unforeseen difficulties. */
921 return resolver;
922
923 activity = EmacsActivity.lastFocusedActivity;
924 if (activity == null)
925 return resolver;
926
927 return activity.getContentResolver ();
928 }
929
930 /* Return a context whose ContentResolver is granted access to most
931 files, as in `getUsefulContentResolver'. */
932
933 public Context
934 getContentResolverContext ()
935 {
936 EmacsActivity activity;
937
938 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
939 /* Since the system predates drag and drop, return this resolver
940 to avoid any unforeseen difficulties. */
941 return this;
942
943 activity = EmacsActivity.lastFocusedActivity;
944 if (activity == null)
945 return this;
946
947 return activity;
948 }
949
950 /* Open a content URI described by the bytes BYTES, a non-terminated 914 /* Open a content URI described by the bytes BYTES, a non-terminated
951 string; make it writable if WRITABLE, and readable if READABLE. 915 string; make it writable if WRITABLE, and readable if READABLE.
952 Truncate the file if TRUNCATE. 916 Truncate the file if TRUNCATE.
@@ -960,9 +924,6 @@ public final class EmacsService extends Service
960 String name, mode; 924 String name, mode;
961 ParcelFileDescriptor fd; 925 ParcelFileDescriptor fd;
962 int i; 926 int i;
963 ContentResolver resolver;
964
965 resolver = getUsefulContentResolver ();
966 927
967 /* Figure out the file access mode. */ 928 /* Figure out the file access mode. */
968 929
@@ -1024,12 +985,8 @@ public final class EmacsService extends Service
1024 ParcelFileDescriptor fd; 985 ParcelFileDescriptor fd;
1025 Uri uri; 986 Uri uri;
1026 int rc, flags; 987 int rc, flags;
1027 Context context;
1028 ContentResolver resolver;
1029 ParcelFileDescriptor descriptor; 988 ParcelFileDescriptor descriptor;
1030 989
1031 context = getContentResolverContext ();
1032
1033 uri = Uri.parse (name); 990 uri = Uri.parse (name);
1034 flags = 0; 991 flags = 0;
1035 992
@@ -1039,7 +996,7 @@ public final class EmacsService extends Service
1039 if (writable) 996 if (writable)
1040 flags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION; 997 flags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
1041 998
1042 rc = context.checkCallingUriPermission (uri, flags); 999 rc = checkCallingUriPermission (uri, flags);
1043 1000
1044 if (rc == PackageManager.PERMISSION_GRANTED) 1001 if (rc == PackageManager.PERMISSION_GRANTED)
1045 return true; 1002 return true;
@@ -1053,7 +1010,6 @@ public final class EmacsService extends Service
1053 1010
1054 try 1011 try
1055 { 1012 {
1056 resolver = context.getContentResolver ();
1057 descriptor = resolver.openFileDescriptor (uri, "r"); 1013 descriptor = resolver.openFileDescriptor (uri, "r");
1058 return true; 1014 return true;
1059 } 1015 }
diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java
index 304304a328b..6e8bdaf7401 100644
--- a/java/org/gnu/emacs/EmacsWindow.java
+++ b/java/org/gnu/emacs/EmacsWindow.java
@@ -27,6 +27,8 @@ import java.util.HashMap;
27import java.util.LinkedHashMap; 27import java.util.LinkedHashMap;
28import java.util.Map; 28import java.util.Map;
29 29
30import android.app.Activity;
31
30import android.content.ClipData; 32import android.content.ClipData;
31import android.content.ClipDescription; 33import android.content.ClipDescription;
32import android.content.Context; 34import android.content.Context;
@@ -240,7 +242,7 @@ public final class EmacsWindow extends EmacsHandleObject
240 } 242 }
241 } 243 }
242 244
243 EmacsActivity.invalidateFocus (); 245 EmacsActivity.invalidateFocus (4);
244 246
245 if (!children.isEmpty ()) 247 if (!children.isEmpty ())
246 throw new IllegalStateException ("Trying to destroy window with " 248 throw new IllegalStateException ("Trying to destroy window with "
@@ -362,6 +364,9 @@ public final class EmacsWindow extends EmacsHandleObject
362 requestViewLayout (); 364 requestViewLayout ();
363 } 365 }
364 366
367 /* Return WM layout parameters for an override redirect window with
368 the geometry provided here. */
369
365 private WindowManager.LayoutParams 370 private WindowManager.LayoutParams
366 getWindowLayoutParams () 371 getWindowLayoutParams ()
367 { 372 {
@@ -384,15 +389,15 @@ public final class EmacsWindow extends EmacsHandleObject
384 return params; 389 return params;
385 } 390 }
386 391
387 private Context 392 private Activity
388 findSuitableActivityContext () 393 findSuitableActivityContext ()
389 { 394 {
390 /* Find a recently focused activity. */ 395 /* Find a recently focused activity. */
391 if (!EmacsActivity.focusedActivities.isEmpty ()) 396 if (!EmacsActivity.focusedActivities.isEmpty ())
392 return EmacsActivity.focusedActivities.get (0); 397 return EmacsActivity.focusedActivities.get (0);
393 398
394 /* Return the service context, which probably won't work. */ 399 /* Resort to the last activity to be focused. */
395 return EmacsService.SERVICE; 400 return EmacsActivity.lastFocusedActivity;
396 } 401 }
397 402
398 public synchronized void 403 public synchronized void
@@ -416,7 +421,7 @@ public final class EmacsWindow extends EmacsHandleObject
416 { 421 {
417 EmacsWindowAttachmentManager manager; 422 EmacsWindowAttachmentManager manager;
418 WindowManager windowManager; 423 WindowManager windowManager;
419 Context ctx; 424 Activity ctx;
420 Object tem; 425 Object tem;
421 WindowManager.LayoutParams params; 426 WindowManager.LayoutParams params;
422 427
@@ -447,11 +452,23 @@ public final class EmacsWindow extends EmacsHandleObject
447 activity using the system window manager. */ 452 activity using the system window manager. */
448 453
449 ctx = findSuitableActivityContext (); 454 ctx = findSuitableActivityContext ();
455
456 if (ctx == null)
457 {
458 Log.w (TAG, "failed to attach override-redirect window"
459 + " for want of activity");
460 return;
461 }
462
450 tem = ctx.getSystemService (Context.WINDOW_SERVICE); 463 tem = ctx.getSystemService (Context.WINDOW_SERVICE);
451 windowManager = (WindowManager) tem; 464 windowManager = (WindowManager) tem;
452 465
453 /* Calculate layout parameters. */ 466 /* Calculate layout parameters and propagate the
467 activity's token into it. */
468
454 params = getWindowLayoutParams (); 469 params = getWindowLayoutParams ();
470 params.token = (ctx.findViewById (android.R.id.content)
471 .getWindowToken ());
455 view.setLayoutParams (params); 472 view.setLayoutParams (params);
456 473
457 /* Attach the view. */ 474 /* Attach the view. */
@@ -644,7 +661,7 @@ public final class EmacsWindow extends EmacsHandleObject
644 public void 661 public void
645 onKeyDown (int keyCode, KeyEvent event) 662 onKeyDown (int keyCode, KeyEvent event)
646 { 663 {
647 int state, state_1, num_lock_flag; 664 int state, state_1, extra_ignored;
648 long serial; 665 long serial;
649 String characters; 666 String characters;
650 667
@@ -665,23 +682,37 @@ public final class EmacsWindow extends EmacsHandleObject
665 682
666 state = eventModifiers (event); 683 state = eventModifiers (event);
667 684
668 /* Num Lock and Scroll Lock aren't supported by systems older than 685 /* Num Lock, Scroll Lock and Meta aren't supported by systems older
669 Android 3.0. */ 686 than Android 3.0. */
670 687
671 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 688 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
672 num_lock_flag = (KeyEvent.META_NUM_LOCK_ON 689 extra_ignored = (KeyEvent.META_NUM_LOCK_ON
673 | KeyEvent.META_SCROLL_LOCK_ON); 690 | KeyEvent.META_SCROLL_LOCK_ON
691 | KeyEvent.META_META_MASK);
674 else 692 else
675 num_lock_flag = 0; 693 extra_ignored = 0;
676 694
677 /* Ignore meta-state understood by Emacs for now, or key presses 695 /* Ignore meta-state understood by Emacs for now, or key presses
678 such as Ctrl+C and Meta+C will not be recognized as an ASCII 696 such as Ctrl+C and Meta+C will not be recognized as ASCII key
679 key press event. */ 697 press events. */
680 698
681 state_1 699 state_1
682 = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK 700 = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK
683 | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK 701 | KeyEvent.META_SYM_ON | extra_ignored);
684 | num_lock_flag); 702
703 /* There's no distinction between Right Alt and Alt Gr on Android,
704 so restore META_ALT_RIGHT_ON if set in state to enable composing
705 characters. (bug#69321) */
706
707 if ((state & KeyEvent.META_ALT_RIGHT_ON) != 0)
708 {
709 state_1 |= KeyEvent.META_ALT_ON | KeyEvent.META_ALT_RIGHT_ON;
710
711 /* If Alt is also not depressed, remove its bit from the mask
712 reported to Emacs. */
713 if ((state & KeyEvent.META_ALT_LEFT_ON) == 0)
714 state &= ~KeyEvent.META_ALT_MASK;
715 }
685 716
686 synchronized (eventStrings) 717 synchronized (eventStrings)
687 { 718 {
@@ -702,29 +733,43 @@ public final class EmacsWindow extends EmacsHandleObject
702 public void 733 public void
703 onKeyUp (int keyCode, KeyEvent event) 734 onKeyUp (int keyCode, KeyEvent event)
704 { 735 {
705 int state, state_1, unicode_char, num_lock_flag; 736 int state, state_1, unicode_char, extra_ignored;
706 long time; 737 long time;
707 738
708 /* Compute the event's modifier mask. */ 739 /* Compute the event's modifier mask. */
709 state = eventModifiers (event); 740 state = eventModifiers (event);
710 741
711 /* Num Lock and Scroll Lock aren't supported by systems older than 742 /* Num Lock, Scroll Lock and Meta aren't supported by systems older
712 Android 3.0. */ 743 than Android 3.0. */
713 744
714 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) 745 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
715 num_lock_flag = (KeyEvent.META_NUM_LOCK_ON 746 extra_ignored = (KeyEvent.META_NUM_LOCK_ON
716 | KeyEvent.META_SCROLL_LOCK_ON); 747 | KeyEvent.META_SCROLL_LOCK_ON
748 | KeyEvent.META_META_MASK);
717 else 749 else
718 num_lock_flag = 0; 750 extra_ignored = 0;
719 751
720 /* Ignore meta-state understood by Emacs for now, or key presses 752 /* Ignore meta-state understood by Emacs for now, or key presses
721 such as Ctrl+C and Meta+C will not be recognized as an ASCII 753 such as Ctrl+C and Meta+C will not be recognized as ASCII key
722 key press event. */ 754 press events. */
723 755
724 state_1 756 state_1
725 = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK 757 = state & ~(KeyEvent.META_ALT_MASK | KeyEvent.META_CTRL_MASK
726 | KeyEvent.META_SYM_ON | KeyEvent.META_META_MASK 758 | KeyEvent.META_SYM_ON | extra_ignored);
727 | num_lock_flag); 759
760 /* There's no distinction between Right Alt and Alt Gr on Android,
761 so restore META_ALT_RIGHT_ON if set in state to enable composing
762 characters. */
763
764 if ((state & KeyEvent.META_ALT_RIGHT_ON) != 0)
765 {
766 state_1 |= KeyEvent.META_ALT_ON | KeyEvent.META_ALT_RIGHT_ON;
767
768 /* If Alt is also not depressed, remove its bit from the mask
769 reported to Emacs. */
770 if ((state & KeyEvent.META_ALT_LEFT_ON) == 0)
771 state &= ~KeyEvent.META_ALT_MASK;
772 }
728 773
729 unicode_char = getEventUnicodeChar (event, state_1); 774 unicode_char = getEventUnicodeChar (event, state_1);
730 775
@@ -760,7 +805,7 @@ public final class EmacsWindow extends EmacsHandleObject
760 public void 805 public void
761 onFocusChanged (boolean gainFocus) 806 onFocusChanged (boolean gainFocus)
762 { 807 {
763 EmacsActivity.invalidateFocus (); 808 EmacsActivity.invalidateFocus (gainFocus ? 6 : 5);
764 } 809 }
765 810
766 /* Notice that the activity has been detached or destroyed. 811 /* Notice that the activity has been detached or destroyed.
@@ -1746,7 +1791,7 @@ public final class EmacsWindow extends EmacsHandleObject
1746 1791
1747 /* Attempt to acquire permissions for this URI; 1792 /* Attempt to acquire permissions for this URI;
1748 failing which, insert it as text instead. */ 1793 failing which, insert it as text instead. */
1749 1794
1750 if (uri != null 1795 if (uri != null
1751 && uri.getScheme () != null 1796 && uri.getScheme () != null
1752 && uri.getScheme ().equals ("content") 1797 && uri.getScheme ().equals ("content")