1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-04-27 08:43:40 -07:00

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.
This commit is contained in:
Po Lu 2023-03-18 10:54:26 +08:00
parent 773bdb15ab
commit 634e3fcc20
4 changed files with 160 additions and 63 deletions

View file

@ -28,6 +28,7 @@ import android.view.View;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
@ -51,6 +52,7 @@ import android.util.Log;
It is also a ViewGroup, as it also lays out children. */
public final class EmacsView extends ViewGroup
implements ViewTreeObserver.OnGlobalLayoutListener
{
public static final String TAG = "EmacsView";
@ -136,6 +138,9 @@ public final class EmacsView extends ViewGroup
context = getContext ();
tem = context.getSystemService (Context.INPUT_METHOD_SERVICE);
imManager = (InputMethodManager) tem;
/* Add this view as its own global layout listener. */
getViewTreeObserver ().addOnGlobalLayoutListener (this);
}
private void
@ -238,6 +243,13 @@ public final class EmacsView extends ViewGroup
return canvas;
}
public void
prepareForLayout (int wantedWidth, int wantedHeight)
{
measuredWidth = wantedWidth;
measuredHeight = wantedWidth;
}
@Override
protected void
onMeasure (int widthMeasureSpec, int heightMeasureSpec)
@ -562,8 +574,7 @@ public final class EmacsView extends ViewGroup
bitmapDirty = true;
/* Now expose the view contents again. */
EmacsNative.sendExpose (this.window.handle, 0, 0,
measuredWidth, measuredHeight);
EmacsNative.sendExpose (this.window.handle, 0, 0, 0, 0);
super.onAttachedToWindow ();
}
@ -678,4 +689,19 @@ public final class EmacsView extends ViewGroup
{
return icMode;
}
@Override
public void
onGlobalLayout ()
{
int[] locations;
/* Get the absolute offset of this view and specify its left and
top position in subsequent ConfigureNotify events. */
locations = new int[2];
getLocationInWindow (locations);
window.notifyContentRectPosition (locations[0],
locations[1]);
}
};

View file

@ -133,6 +133,9 @@ public final class EmacsWindow extends EmacsHandleObject
creating new bitmaps. */
public volatile int background;
/* The position of this window relative to the root window. */
public int xPosition, yPosition;
public
EmacsWindow (short handle, final EmacsWindow parent, int x, int y,
int width, int height, boolean overrideRedirect)
@ -192,18 +195,14 @@ public final class EmacsWindow extends EmacsHandleObject
background = pixel;
}
public Rect
public synchronized Rect
getGeometry ()
{
synchronized (this)
{
/* Huh, this is it. */
return rect;
}
return new Rect (rect);
}
@Override
public void
public synchronized void
destroyHandle () throws IllegalStateException
{
if (parent != null)
@ -258,22 +257,28 @@ public final class EmacsWindow extends EmacsHandleObject
return attached;
}
public long
public synchronized long
viewLayout (int left, int top, int right, int bottom)
{
int rectWidth, rectHeight;
synchronized (this)
{
rect.left = left;
rect.top = top;
rect.right = right;
rect.bottom = bottom;
}
rect.left = left;
rect.top = top;
rect.right = right;
rect.bottom = bottom;
rectWidth = right - left;
rectHeight = bottom - top;
/* If parent is null, use xPosition and yPosition instead of the
geometry rectangle positions. */
if (parent == null)
{
left = xPosition;
top = yPosition;
}
return EmacsNative.sendConfigureNotify (this.handle,
System.currentTimeMillis (),
left, top, rectWidth,
@ -283,8 +288,6 @@ public final class EmacsWindow extends EmacsHandleObject
public void
requestViewLayout ()
{
/* This is necessary because otherwise subsequent drawing on the
Emacs thread may be lost. */
view.explicitlyDirtyBitmap ();
EmacsService.SERVICE.runOnUiThread (new Runnable () {
@ -302,35 +305,29 @@ public final class EmacsWindow extends EmacsHandleObject
});
}
public void
public synchronized void
resizeWindow (int width, int height)
{
synchronized (this)
{
rect.right = rect.left + width;
rect.bottom = rect.top + height;
rect.right = rect.left + width;
rect.bottom = rect.top + height;
requestViewLayout ();
}
requestViewLayout ();
}
public void
public synchronized void
moveWindow (int x, int y)
{
int width, height;
synchronized (this)
{
width = rect.width ();
height = rect.height ();
width = rect.width ();
height = rect.height ();
rect.left = x;
rect.top = y;
rect.right = x + width;
rect.bottom = y + height;
rect.left = x;
rect.top = y;
rect.right = x + width;
rect.bottom = y + height;
requestViewLayout ();
}
requestViewLayout ();
}
private WindowManager.LayoutParams
@ -366,13 +363,17 @@ public final class EmacsWindow extends EmacsHandleObject
return EmacsService.SERVICE;
}
public void
public synchronized void
mapWindow ()
{
final int width, height;
if (isMapped)
return;
isMapped = true;
width = rect.width ();
height = rect.height ();
if (parent == null)
{
@ -424,6 +425,7 @@ public final class EmacsWindow extends EmacsHandleObject
/* Attach the view. */
try
{
view.prepareForLayout (width, height);
windowManager.addView (view, params);
/* Record the window manager being used in the
@ -448,10 +450,14 @@ public final class EmacsWindow extends EmacsHandleObject
public void
run ()
{
/* Prior to mapping the view, set its measuredWidth and
measuredHeight to some reasonable value, in order to
avoid excessive bitmap dirtying. */
view.prepareForLayout (width, height);
view.setVisibility (View.VISIBLE);
if (!getDontFocusOnMap ())
/* Eventually this should check no-focus-on-map. */
view.requestFocus ();
}
});
@ -512,12 +518,9 @@ public final class EmacsWindow extends EmacsHandleObject
public void
clearWindow ()
{
synchronized (this)
{
EmacsService.SERVICE.fillRectangle (this, scratchGC,
0, 0, rect.width (),
rect.height ());
}
EmacsService.SERVICE.fillRectangle (this, scratchGC,
0, 0, rect.width (),
rect.height ());
}
public void
@ -1001,7 +1004,7 @@ public final class EmacsWindow extends EmacsHandleObject
return false;
}
public void
public synchronized void
reparentTo (final EmacsWindow otherWindow, int x, int y)
{
int width, height;
@ -1017,15 +1020,12 @@ public final class EmacsWindow extends EmacsHandleObject
parent = otherWindow;
/* Move this window to the new location. */
synchronized (this)
{
width = rect.width ();
height = rect.height ();
rect.left = x;
rect.top = y;
rect.right = x + width;
rect.bottom = y + height;
}
width = rect.width ();
height = rect.height ();
rect.left = x;
rect.top = y;
rect.right = x + width;
rect.bottom = y + height;
/* Now do the work necessary on the UI thread to reparent the
window. */
@ -1081,7 +1081,7 @@ public final class EmacsWindow extends EmacsHandleObject
});
}
public void
public synchronized void
raise ()
{
/* This does nothing here. */
@ -1103,7 +1103,7 @@ public final class EmacsWindow extends EmacsHandleObject
});
}
public void
public synchronized void
lower ()
{
/* This does nothing here. */
@ -1125,17 +1125,15 @@ public final class EmacsWindow extends EmacsHandleObject
});
}
public int[]
public synchronized int[]
getWindowGeometry ()
{
int[] array;
Rect rect;
array = new int[4];
rect = getGeometry ();
array[0] = rect.left;
array[1] = rect.top;
array[0] = parent != null ? rect.left : xPosition;
array[1] = parent != null ? rect.top : yPosition;
array[2] = rect.width ();
array[3] = rect.height ();
@ -1272,4 +1270,31 @@ public final class EmacsWindow extends EmacsHandleObject
}
});
}
public synchronized void
notifyContentRectPosition (int xPosition, int yPosition)
{
Rect geometry;
/* Ignore these notifications if not a child of the root
window. */
if (parent != null)
return;
/* xPosition and yPosition are the position of this window
relative to the screen. Set them and request a ConfigureNotify
event. */
if (this.xPosition != xPosition
|| this.yPosition != yPosition)
{
this.xPosition = xPosition;
this.yPosition = yPosition;
EmacsNative.sendConfigureNotify (this.handle,
System.currentTimeMillis (),
xPosition, yPosition,
rect.width (), rect.height ());
}
}
};

View file

@ -22,7 +22,9 @@ package org.gnu.emacs;
import java.util.ArrayList;
import java.util.List;
import android.app.ActivityOptions;
import android.content.Intent;
import android.os.Build;
import android.util.Log;
/* Code to paper over the differences in lifecycles between
@ -102,6 +104,7 @@ public final class EmacsWindowAttachmentManager
registerWindow (EmacsWindow window)
{
Intent intent;
ActivityOptions options;
Log.d (TAG, "registerWindow (maybe): " + window);
@ -128,7 +131,18 @@ public final class EmacsWindowAttachmentManager
intent.addFlags (Intent.FLAG_ACTIVITY_NEW_DOCUMENT
| Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
EmacsService.SERVICE.startActivity (intent);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
EmacsService.SERVICE.startActivity (intent);
else
{
/* Specify the desired window size. */
options = ActivityOptions.makeBasic ();
options.setLaunchBounds (window.getGeometry ());
EmacsService.SERVICE.startActivity (intent,
options.toBundle ());
}
Log.d (TAG, "registerWindow: startActivity");
}