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:
parent
773bdb15ab
commit
634e3fcc20
4 changed files with 160 additions and 63 deletions
|
|
@ -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]);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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 ());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue