aboutsummaryrefslogtreecommitdiffstats
path: root/java
diff options
context:
space:
mode:
authorPo Lu2023-03-18 10:54:26 +0800
committerPo Lu2023-03-18 10:54:26 +0800
commit634e3fcc20ea9fa5b1af59286f4b846a351f52c8 (patch)
tree2a98eff1365c2776f53c163e58cd539d1a65ba87 /java
parent773bdb15abd5527dfc27d811a70263ac10cf451b (diff)
downloademacs-634e3fcc20ea9fa5b1af59286f4b846a351f52c8.tar.gz
emacs-634e3fcc20ea9fa5b1af59286f4b846a351f52c8.zip
Update Android port
* java/org/gnu/emacs/EmacsView.java (EmacsView) (prepareForLayout): New function. Call this prior to mapping the view. (onGlobalLayout): New function. Register as global layout listener. * java/org/gnu/emacs/EmacsWindow.java (EmacsWindow) (notifyContentRectPosition): New function. Use specified xPosition and yPosition when reporting the offsets of children of the root window. * java/org/gnu/emacs/EmacsWindowAttachmentManager.java (registerWindow): Specify activity launch bounds if necessary. * src/androidterm.c (handle_one_android_event): Send MOVE_FRAME_EVENT where necessary.
Diffstat (limited to 'java')
-rw-r--r--java/org/gnu/emacs/EmacsView.java30
-rw-r--r--java/org/gnu/emacs/EmacsWindow.java145
-rw-r--r--java/org/gnu/emacs/EmacsWindowAttachmentManager.java16
3 files changed, 128 insertions, 63 deletions
diff --git a/java/org/gnu/emacs/EmacsView.java b/java/org/gnu/emacs/EmacsView.java
index 681da98fa16..88d17a255a2 100644
--- a/java/org/gnu/emacs/EmacsView.java
+++ b/java/org/gnu/emacs/EmacsView.java
@@ -28,6 +28,7 @@ import android.view.View;
28import android.view.KeyEvent; 28import android.view.KeyEvent;
29import android.view.MotionEvent; 29import android.view.MotionEvent;
30import android.view.ViewGroup; 30import android.view.ViewGroup;
31import android.view.ViewTreeObserver;
31 32
32import android.view.inputmethod.EditorInfo; 33import android.view.inputmethod.EditorInfo;
33import android.view.inputmethod.InputConnection; 34import android.view.inputmethod.InputConnection;
@@ -51,6 +52,7 @@ import android.util.Log;
51 It is also a ViewGroup, as it also lays out children. */ 52 It is also a ViewGroup, as it also lays out children. */
52 53
53public final class EmacsView extends ViewGroup 54public final class EmacsView extends ViewGroup
55 implements ViewTreeObserver.OnGlobalLayoutListener
54{ 56{
55 public static final String TAG = "EmacsView"; 57 public static final String TAG = "EmacsView";
56 58
@@ -136,6 +138,9 @@ public final class EmacsView extends ViewGroup
136 context = getContext (); 138 context = getContext ();
137 tem = context.getSystemService (Context.INPUT_METHOD_SERVICE); 139 tem = context.getSystemService (Context.INPUT_METHOD_SERVICE);
138 imManager = (InputMethodManager) tem; 140 imManager = (InputMethodManager) tem;
141
142 /* Add this view as its own global layout listener. */
143 getViewTreeObserver ().addOnGlobalLayoutListener (this);
139 } 144 }
140 145
141 private void 146 private void
@@ -238,6 +243,13 @@ public final class EmacsView extends ViewGroup
238 return canvas; 243 return canvas;
239 } 244 }
240 245
246 public void
247 prepareForLayout (int wantedWidth, int wantedHeight)
248 {
249 measuredWidth = wantedWidth;
250 measuredHeight = wantedWidth;
251 }
252
241 @Override 253 @Override
242 protected void 254 protected void
243 onMeasure (int widthMeasureSpec, int heightMeasureSpec) 255 onMeasure (int widthMeasureSpec, int heightMeasureSpec)
@@ -562,8 +574,7 @@ public final class EmacsView extends ViewGroup
562 bitmapDirty = true; 574 bitmapDirty = true;
563 575
564 /* Now expose the view contents again. */ 576 /* Now expose the view contents again. */
565 EmacsNative.sendExpose (this.window.handle, 0, 0, 577 EmacsNative.sendExpose (this.window.handle, 0, 0, 0, 0);
566 measuredWidth, measuredHeight);
567 578
568 super.onAttachedToWindow (); 579 super.onAttachedToWindow ();
569 } 580 }
@@ -678,4 +689,19 @@ public final class EmacsView extends ViewGroup
678 { 689 {
679 return icMode; 690 return icMode;
680 } 691 }
692
693 @Override
694 public void
695 onGlobalLayout ()
696 {
697 int[] locations;
698
699 /* Get the absolute offset of this view and specify its left and
700 top position in subsequent ConfigureNotify events. */
701
702 locations = new int[2];
703 getLocationInWindow (locations);
704 window.notifyContentRectPosition (locations[0],
705 locations[1]);
706 }
681}; 707};
diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java
index a8d1beedef7..c14bf16b96e 100644
--- a/java/org/gnu/emacs/EmacsWindow.java
+++ b/java/org/gnu/emacs/EmacsWindow.java
@@ -133,6 +133,9 @@ public final class EmacsWindow extends EmacsHandleObject
133 creating new bitmaps. */ 133 creating new bitmaps. */
134 public volatile int background; 134 public volatile int background;
135 135
136 /* The position of this window relative to the root window. */
137 public int xPosition, yPosition;
138
136 public 139 public
137 EmacsWindow (short handle, final EmacsWindow parent, int x, int y, 140 EmacsWindow (short handle, final EmacsWindow parent, int x, int y,
138 int width, int height, boolean overrideRedirect) 141 int width, int height, boolean overrideRedirect)
@@ -192,18 +195,14 @@ public final class EmacsWindow extends EmacsHandleObject
192 background = pixel; 195 background = pixel;
193 } 196 }
194 197
195 public Rect 198 public synchronized Rect
196 getGeometry () 199 getGeometry ()
197 { 200 {
198 synchronized (this) 201 return new Rect (rect);
199 {
200 /* Huh, this is it. */
201 return rect;
202 }
203 } 202 }
204 203
205 @Override 204 @Override
206 public void 205 public synchronized void
207 destroyHandle () throws IllegalStateException 206 destroyHandle () throws IllegalStateException
208 { 207 {
209 if (parent != null) 208 if (parent != null)
@@ -258,22 +257,28 @@ public final class EmacsWindow extends EmacsHandleObject
258 return attached; 257 return attached;
259 } 258 }
260 259
261 public long 260 public synchronized long
262 viewLayout (int left, int top, int right, int bottom) 261 viewLayout (int left, int top, int right, int bottom)
263 { 262 {
264 int rectWidth, rectHeight; 263 int rectWidth, rectHeight;
265 264
266 synchronized (this) 265 rect.left = left;
267 { 266 rect.top = top;
268 rect.left = left; 267 rect.right = right;
269 rect.top = top; 268 rect.bottom = bottom;
270 rect.right = right;
271 rect.bottom = bottom;
272 }
273 269
274 rectWidth = right - left; 270 rectWidth = right - left;
275 rectHeight = bottom - top; 271 rectHeight = bottom - top;
276 272
273 /* If parent is null, use xPosition and yPosition instead of the
274 geometry rectangle positions. */
275
276 if (parent == null)
277 {
278 left = xPosition;
279 top = yPosition;
280 }
281
277 return EmacsNative.sendConfigureNotify (this.handle, 282 return EmacsNative.sendConfigureNotify (this.handle,
278 System.currentTimeMillis (), 283 System.currentTimeMillis (),
279 left, top, rectWidth, 284 left, top, rectWidth,
@@ -283,8 +288,6 @@ public final class EmacsWindow extends EmacsHandleObject
283 public void 288 public void
284 requestViewLayout () 289 requestViewLayout ()
285 { 290 {
286 /* This is necessary because otherwise subsequent drawing on the
287 Emacs thread may be lost. */
288 view.explicitlyDirtyBitmap (); 291 view.explicitlyDirtyBitmap ();
289 292
290 EmacsService.SERVICE.runOnUiThread (new Runnable () { 293 EmacsService.SERVICE.runOnUiThread (new Runnable () {
@@ -302,35 +305,29 @@ public final class EmacsWindow extends EmacsHandleObject
302 }); 305 });
303 } 306 }
304 307
305 public void 308 public synchronized void
306 resizeWindow (int width, int height) 309 resizeWindow (int width, int height)
307 { 310 {
308 synchronized (this) 311 rect.right = rect.left + width;
309 { 312 rect.bottom = rect.top + height;
310 rect.right = rect.left + width;
311 rect.bottom = rect.top + height;
312 313
313 requestViewLayout (); 314 requestViewLayout ();
314 }
315 } 315 }
316 316
317 public void 317 public synchronized void
318 moveWindow (int x, int y) 318 moveWindow (int x, int y)
319 { 319 {
320 int width, height; 320 int width, height;
321 321
322 synchronized (this) 322 width = rect.width ();
323 { 323 height = rect.height ();
324 width = rect.width ();
325 height = rect.height ();
326 324
327 rect.left = x; 325 rect.left = x;
328 rect.top = y; 326 rect.top = y;
329 rect.right = x + width; 327 rect.right = x + width;
330 rect.bottom = y + height; 328 rect.bottom = y + height;
331 329
332 requestViewLayout (); 330 requestViewLayout ();
333 }
334 } 331 }
335 332
336 private WindowManager.LayoutParams 333 private WindowManager.LayoutParams
@@ -366,13 +363,17 @@ public final class EmacsWindow extends EmacsHandleObject
366 return EmacsService.SERVICE; 363 return EmacsService.SERVICE;
367 } 364 }
368 365
369 public void 366 public synchronized void
370 mapWindow () 367 mapWindow ()
371 { 368 {
369 final int width, height;
370
372 if (isMapped) 371 if (isMapped)
373 return; 372 return;
374 373
375 isMapped = true; 374 isMapped = true;
375 width = rect.width ();
376 height = rect.height ();
376 377
377 if (parent == null) 378 if (parent == null)
378 { 379 {
@@ -424,6 +425,7 @@ public final class EmacsWindow extends EmacsHandleObject
424 /* Attach the view. */ 425 /* Attach the view. */
425 try 426 try
426 { 427 {
428 view.prepareForLayout (width, height);
427 windowManager.addView (view, params); 429 windowManager.addView (view, params);
428 430
429 /* Record the window manager being used in the 431 /* Record the window manager being used in the
@@ -448,10 +450,14 @@ public final class EmacsWindow extends EmacsHandleObject
448 public void 450 public void
449 run () 451 run ()
450 { 452 {
453 /* Prior to mapping the view, set its measuredWidth and
454 measuredHeight to some reasonable value, in order to
455 avoid excessive bitmap dirtying. */
456
457 view.prepareForLayout (width, height);
451 view.setVisibility (View.VISIBLE); 458 view.setVisibility (View.VISIBLE);
452 459
453 if (!getDontFocusOnMap ()) 460 if (!getDontFocusOnMap ())
454 /* Eventually this should check no-focus-on-map. */
455 view.requestFocus (); 461 view.requestFocus ();
456 } 462 }
457 }); 463 });
@@ -512,12 +518,9 @@ public final class EmacsWindow extends EmacsHandleObject
512 public void 518 public void
513 clearWindow () 519 clearWindow ()
514 { 520 {
515 synchronized (this) 521 EmacsService.SERVICE.fillRectangle (this, scratchGC,
516 { 522 0, 0, rect.width (),
517 EmacsService.SERVICE.fillRectangle (this, scratchGC, 523 rect.height ());
518 0, 0, rect.width (),
519 rect.height ());
520 }
521 } 524 }
522 525
523 public void 526 public void
@@ -1001,7 +1004,7 @@ public final class EmacsWindow extends EmacsHandleObject
1001 return false; 1004 return false;
1002 } 1005 }
1003 1006
1004 public void 1007 public synchronized void
1005 reparentTo (final EmacsWindow otherWindow, int x, int y) 1008 reparentTo (final EmacsWindow otherWindow, int x, int y)
1006 { 1009 {
1007 int width, height; 1010 int width, height;
@@ -1017,15 +1020,12 @@ public final class EmacsWindow extends EmacsHandleObject
1017 parent = otherWindow; 1020 parent = otherWindow;
1018 1021
1019 /* Move this window to the new location. */ 1022 /* Move this window to the new location. */
1020 synchronized (this) 1023 width = rect.width ();
1021 { 1024 height = rect.height ();
1022 width = rect.width (); 1025 rect.left = x;
1023 height = rect.height (); 1026 rect.top = y;
1024 rect.left = x; 1027 rect.right = x + width;
1025 rect.top = y; 1028 rect.bottom = y + height;
1026 rect.right = x + width;
1027 rect.bottom = y + height;
1028 }
1029 1029
1030 /* Now do the work necessary on the UI thread to reparent the 1030 /* Now do the work necessary on the UI thread to reparent the
1031 window. */ 1031 window. */
@@ -1081,7 +1081,7 @@ public final class EmacsWindow extends EmacsHandleObject
1081 }); 1081 });
1082 } 1082 }
1083 1083
1084 public void 1084 public synchronized void
1085 raise () 1085 raise ()
1086 { 1086 {
1087 /* This does nothing here. */ 1087 /* This does nothing here. */
@@ -1103,7 +1103,7 @@ public final class EmacsWindow extends EmacsHandleObject
1103 }); 1103 });
1104 } 1104 }
1105 1105
1106 public void 1106 public synchronized void
1107 lower () 1107 lower ()
1108 { 1108 {
1109 /* This does nothing here. */ 1109 /* This does nothing here. */
@@ -1125,17 +1125,15 @@ public final class EmacsWindow extends EmacsHandleObject
1125 }); 1125 });
1126 } 1126 }
1127 1127
1128 public int[] 1128 public synchronized int[]
1129 getWindowGeometry () 1129 getWindowGeometry ()
1130 { 1130 {
1131 int[] array; 1131 int[] array;
1132 Rect rect;
1133 1132
1134 array = new int[4]; 1133 array = new int[4];
1135 rect = getGeometry ();
1136 1134
1137 array[0] = rect.left; 1135 array[0] = parent != null ? rect.left : xPosition;
1138 array[1] = rect.top; 1136 array[1] = parent != null ? rect.top : yPosition;
1139 array[2] = rect.width (); 1137 array[2] = rect.width ();
1140 array[3] = rect.height (); 1138 array[3] = rect.height ();
1141 1139
@@ -1272,4 +1270,31 @@ public final class EmacsWindow extends EmacsHandleObject
1272 } 1270 }
1273 }); 1271 });
1274 } 1272 }
1273
1274 public synchronized void
1275 notifyContentRectPosition (int xPosition, int yPosition)
1276 {
1277 Rect geometry;
1278
1279 /* Ignore these notifications if not a child of the root
1280 window. */
1281 if (parent != null)
1282 return;
1283
1284 /* xPosition and yPosition are the position of this window
1285 relative to the screen. Set them and request a ConfigureNotify
1286 event. */
1287
1288 if (this.xPosition != xPosition
1289 || this.yPosition != yPosition)
1290 {
1291 this.xPosition = xPosition;
1292 this.yPosition = yPosition;
1293
1294 EmacsNative.sendConfigureNotify (this.handle,
1295 System.currentTimeMillis (),
1296 xPosition, yPosition,
1297 rect.width (), rect.height ());
1298 }
1299 }
1275}; 1300};
diff --git a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java
index c0197ab802c..4fda48616f0 100644
--- a/java/org/gnu/emacs/EmacsWindowAttachmentManager.java
+++ b/java/org/gnu/emacs/EmacsWindowAttachmentManager.java
@@ -22,7 +22,9 @@ package org.gnu.emacs;
22import java.util.ArrayList; 22import java.util.ArrayList;
23import java.util.List; 23import java.util.List;
24 24
25import android.app.ActivityOptions;
25import android.content.Intent; 26import android.content.Intent;
27import android.os.Build;
26import android.util.Log; 28import android.util.Log;
27 29
28/* Code to paper over the differences in lifecycles between 30/* Code to paper over the differences in lifecycles between
@@ -102,6 +104,7 @@ public final class EmacsWindowAttachmentManager
102 registerWindow (EmacsWindow window) 104 registerWindow (EmacsWindow window)
103 { 105 {
104 Intent intent; 106 Intent intent;
107 ActivityOptions options;
105 108
106 Log.d (TAG, "registerWindow (maybe): " + window); 109 Log.d (TAG, "registerWindow (maybe): " + window);
107 110
@@ -128,7 +131,18 @@ public final class EmacsWindowAttachmentManager
128 intent.addFlags (Intent.FLAG_ACTIVITY_NEW_DOCUMENT 131 intent.addFlags (Intent.FLAG_ACTIVITY_NEW_DOCUMENT
129 | Intent.FLAG_ACTIVITY_NEW_TASK 132 | Intent.FLAG_ACTIVITY_NEW_TASK
130 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK); 133 | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
131 EmacsService.SERVICE.startActivity (intent); 134
135 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
136 EmacsService.SERVICE.startActivity (intent);
137 else
138 {
139 /* Specify the desired window size. */
140 options = ActivityOptions.makeBasic ();
141 options.setLaunchBounds (window.getGeometry ());
142 EmacsService.SERVICE.startActivity (intent,
143 options.toBundle ());
144 }
145
132 Log.d (TAG, "registerWindow: startActivity"); 146 Log.d (TAG, "registerWindow: startActivity");
133 } 147 }
134 148