mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-15 07:41:09 -08:00
Update Android port
* configure.ac (ANDROID_MIN_SDK): New variable. (DX): Remove and replace with D8. (XCONFIGURE): Check for the minimum version of Android the cross compiler compiles for. Generate java/AndroidManifest.xml from java/AndroidManifest.xml.in. Allow using Zlib on Android. * java/AndroidManifest.xml.in: New file. Use the minimum SDK detected by configure. * java/Makefile.in (top_srcdir, version): New variables. (DX, D8): Replace with D8. (ANDROID_MIN_SDK, APK_NAME): New variables. (.PHONY): (.PRECIOUS): (classes.dex): (emacs.apk): Generate $(APK_NAME) instead of `emacs.apk'. * java/debug.sh: New option --attach-existing. Attach to an existing Emacs instance when specified. * java/org/gnu/emacs/EmacsActivity.java (EmacsActivity): New field `isPaused'. (invalidateFocus1): Fix infinite recursion. (detachWindow): Deiconify window. (attachWindow): Iconify the window if the activity is paused. (onCreate): Use the ``no title bar'' theme. (onPause, onResume): New functions. * java/org/gnu/emacs/EmacsNative.java (sendTouchUp, sendTouchDown) (sendTouchMove, sendWheel, sendIconified, sendDeiconified): New functions. * java/org/gnu/emacs/EmacsSdk7FontDriver.java (Sdk7Typeface): (list): Remove logging for code that is mostly going to be unused. * java/org/gnu/emacs/EmacsService.java (ringBell, queryTree) (getScreenWidth, getScreenHeight, detectMouse): New functions. * java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView) (surfaceChanged, surfaceCreated, surfaceDestroyed): Add extra debug logging. Avoid deadlock in surfaceCreated. * java/org/gnu/emacs/EmacsView.java (EmacsView): Try very hard to make the SurfaceView respect Z order. It didn't work. (handleDirtyBitmap): Copy over the contents from the old bitmap. (explicitlyDirtyBitmap): New function. (onLayout): Don't dirty bitmap if unnecessary. (damageRect, swapBuffers): Don't synchronize so hard. (onTouchEvent): Call window.onTouchEvent instead. (moveChildToBack, raise, lower): New functions. * java/org/gnu/emacs/EmacsWindow.java (Coordinate): New subclass. (pointerMap, isMapped, isIconified, dontFocusOnMap) (dontAcceptFocus): New fields. (EmacsWindow): Don't immediately register unmapped window. (viewLayout): Send configure event outside the lock. (requestViewLayout): Explicitly dirty the bitmap. (mapWindow): Register the window now. Respect dontFocusOnMap. (unmapWindow): Unregister the window now. (figureChange, onTouchEvent): New functions. (onSomeKindOfMotionEvent): Handle scroll wheel events. (reparentTo, makeInputFocus, raise, lower, getWindowGeometry) (noticeIconified, noticeDeiconified, setDontAcceptFocus) (setDontFocusOnMap, getDontFocusOnMap): New functions. * java/org/gnu/emacs/EmacsWindowAttachmentManager.java (registerWindow, detachWindow): Synchronize. (noticeIconified, noticeDeiconified): New functions. (copyWindows): New function. * lisp/frame.el (frame-geometry, frame-edges) (mouse-absolute-pixel-position, set-mouse-absolute-pixel-position) (frame-list-z-order, frame-restack, display-mouse-p) (display-monitor-attributes-list): Implement on Android. * lisp/mwheel.el (mouse-wheel-down-event): (mouse-wheel-up-event): (mouse-wheel-left-event): (mouse-wheel-right-event): Define on Android. * src/android.c (struct android_emacs_service): New methods `ringBell', `queryTree', `getScreenWidth', `getScreenHeight', and `detectMouse'. (struct android_event_queue, android_init_events) (android_next_event, android_write_event): Remove write limit. (android_file_access_p): Handle directories correcty. (android_close): Fix coding style. (android_fclose): New function. (android_init_emacs_service): Initialize new methods. (android_reparent_window): Implement function. (android_bell, android_set_input_focus, android_raise_window) (android_lower_window, android_query_tree, android_get_geometry) (android_get_screen_width, android_get_screen_height) (android_get_mm_width, android_get_mm_height, android_detect_mouse) (android_set_dont_focus_on_map, android_set_dont_accept_focus): New functions. (struct android_dir): New structure. (android_opendir, android_readdir, android_closedir): New functions. (emacs_abort): Implement here on Android and poke debuggerd into generating a tombstone. * src/android.h: Update prototypes. * src/androidfns.c (android_set_parent_frame): New function. (android_default_font_parameter): Use sane font size by default. (Fx_display_pixel_width, Fx_display_pixel_height) (Fx_display_mm_width, Fx_display_mm_height) (Fx_display_monitor_attributes_list): Rename to start with `android-'. Implement. Fiddle with documentation to introduce Android specific nuances. (Fandroid_display_monitor_attributes_list): New function. (Fx_frame_geometry, frame_geometry): New function. (Fandroid_frame_geometry): Implement correctly. (Fx_frame_list_z_order): Rename to start with `android-'. (android_frame_list_z_order, Fandroid_frame_list_z_order): Implement. (Fx_frame_restack): Rename to start with `android-'. (Fandroid_frame_restack): ``Implement''. (Fx_mouse_absolute_pixel_position): Rename to start with `android-'. (Fandroid_mouse_absolute_pixel_position): ``Implement''. (Fx_set_mouse_absolute_pixel_position): Rename to start with `android-'. (Fandroid_set_mouse_absolute_pixel_position): ``Implement''. (Fandroid_detect_mouse): New function. (android_set_menu_bar_lines): Use FRAME_ANDROID_DRAWABLE when clearing area. (android_set_no_focus_on_map, android_set_no_accept_focus): New functions. (android_frame_parm_handlers): Register new frame parameter handlers. (syms_of_androidfns): Update appropriately. * src/androidfont.c (androidfont_draw): Use FRAME_ANDROID_DRAWABLE instead of FRAME_ANDROID_WINDOW. * src/androidgui.h (enum android_event_type): New events. (struct android_touch_event, struct android_wheel_event) (struct android_iconify_event): New structures. (union android_event): Add new events. * src/androidterm.c (android_clear_frame): Use FRAME_ANDROID_DRAWABLE instead of FRAME_ANDROID_WINDOW. (android_flash, android_ring_bell): Implement bell ringing. (android_toggle_invisible_pointer): Don't TODO function that can't be implemented. (show_back_buffer, android_flush_dirty_back_buffer_on): Check if a buffer flip is required before doing the flip. (android_lower_frame, android_raise_frame): Implement functions. (android_update_tools, android_find_tool): New functions. (handle_one_android_event): Handle new iconification, wheel and touch events. (android_read_socket): Implement pending-autoraise-frames. (android_frame_up_to_date): Implement bell ringing. (android_buffer_flipping_unblocked_hook): Check if a buffer flip is required before doing the flip. (android_focus_frame, android_frame_highlight) (android_frame_unhighlight): New function. (android_frame_rehighlight): Implement functions. (android_iconify_frame): Always display error. (android_set_alpha): Update commentary. (android_free_frame_resources): Free frame touch points. (android_scroll_run, android_flip_and_flush) (android_clear_rectangle, android_draw_fringe_bitmap) (android_draw_glyph_string_background, android_fill_triangle) (android_clear_point, android_draw_relief_rect) (android_draw_box_rect, android_draw_glyph_string_bg_rect) (android_draw_image_foreground, android_draw_stretch_glyph_string) (android_draw_underwave, android_draw_glyph_string_foreground) (android_draw_composite_glyph_string_foreground) (android_draw_glyphless_glyph_string_foreground) (android_draw_glyph_string, android_clear_frame_area) (android_clear_under_internal_border, android_draw_hollow_cursor) (android_draw_bar_cursor, android_draw_vertical_window_border) (android_draw_window_divider): Use FRAME_ANDROID_DRAWABLE instead of FRAME_ANDROID_WINDOW for drawing operations. * src/androidterm.h (struct android_touch_point): New structure. (struct android_output): New fields. (FRAME_ANDROID_NEED_BUFFER_FLIP): New macro. * src/dired.c (emacs_readdir, open_directory) (directory_files_internal_unwind, read_dirent) (directory_files_internal, file_name_completion): Add indirection over readdir and opendir. Use android variants on Android. * src/dispnew.c (Fopen_termscript): * src/fileio.c (fclose_unwind): Use emacs_fclose. (Faccess_file): Call android_file_access_p. (file_accessible_directory_p): Append right suffix to Android assets directory. (do_auto_save_unwind): Use emacs_fclose. * src/keyboard.c (lispy_function_keys): Use right function key for page up and page down. (Fopen_dribble_file): Use emacs_fclose. * src/lisp.h: New prototype emacs_fclose. * src/lread.c (close_infile_unwind): Use emacs_fclose. * src/sfnt.c (sfnt_curve_is_flat): Fix area-squared computation. (sfnt_prepare_raster): Compute raster width and height consistently with outline building. (sfnt_build_outline_edges): Use the same offsets used to set offy and offx. (main): Adjust debug code. * src/sfntfont-android.c (sfntfont_android_saturate32): Delete function. (sfntfont_android_blend, sfntfont_android_blendrgb): Remove unnecessary debug code. (sfntfont_android_composite_bitmap): Prevent out of bounds write. (sfntfont_android_put_glyphs): Use FRAME_ANDROID_DRAWABLE. (init_sfntfont_android): Initialize Monospace Serif font to something sensible. * src/sfntfont.c (sfntfont_text_extents): Clear glyph metrics before summing up pcm. (sfntfont_draw): Use s->font instead of s->face->font. * src/sysdep.c (emacs_fclose): Wrap around android_fclose on android. * src/term.c (Fsuspend_tty): (delete_tty): Use emacs_fclose. * src/verbose.mk.in (AM_V_DX): Replace with D8 version.
This commit is contained in:
parent
2fa5583d96
commit
f9732131cf
33 changed files with 2815 additions and 351 deletions
|
|
@ -22,6 +22,7 @@ package org.gnu.emacs;
|
|||
import java.lang.IllegalStateException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.Canvas;
|
||||
|
|
@ -50,9 +51,29 @@ import android.os.Build;
|
|||
Views are also drawables, meaning they can accept drawing
|
||||
requests. */
|
||||
|
||||
/* Help wanted. What does not work includes `EmacsView.raise',
|
||||
`EmacsView.lower', reparenting a window onto another window.
|
||||
|
||||
All three are likely undocumented restrictions within
|
||||
EmacsSurface. */
|
||||
|
||||
public class EmacsWindow extends EmacsHandleObject
|
||||
implements EmacsDrawable
|
||||
{
|
||||
private static final String TAG = "EmacsWindow";
|
||||
|
||||
private class Coordinate
|
||||
{
|
||||
/* Integral coordinate. */
|
||||
int x, y;
|
||||
|
||||
Coordinate (int x, int y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
};
|
||||
|
||||
/* The view associated with the window. */
|
||||
public EmacsView view;
|
||||
|
||||
|
|
@ -60,12 +81,16 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
private Rect rect;
|
||||
|
||||
/* The parent window, or null if it is the root window. */
|
||||
private EmacsWindow parent;
|
||||
public EmacsWindow parent;
|
||||
|
||||
/* List of all children in stacking order. This must be kept
|
||||
consistent! */
|
||||
public ArrayList<EmacsWindow> children;
|
||||
|
||||
/* Map between pointer identifiers and last known position. Used to
|
||||
compute which pointer changed upon a touch event. */
|
||||
private HashMap<Integer, Coordinate> pointerMap;
|
||||
|
||||
/* The window consumer currently attached, if it exists. */
|
||||
private EmacsWindowAttachmentManager.WindowConsumer attached;
|
||||
|
||||
|
|
@ -77,6 +102,14 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
last button press or release event. */
|
||||
private int lastButtonState, lastModifiers;
|
||||
|
||||
/* Whether or not the window is mapped, and whether or not it is
|
||||
deiconified. */
|
||||
private boolean isMapped, isIconified;
|
||||
|
||||
/* Whether or not to ask for focus upon being mapped, and whether or
|
||||
not the window should be focusable. */
|
||||
private boolean dontFocusOnMap, dontAcceptFocus;
|
||||
|
||||
public
|
||||
EmacsWindow (short handle, final EmacsWindow parent, int x, int y,
|
||||
int width, int height)
|
||||
|
|
@ -84,6 +117,7 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
super (handle);
|
||||
|
||||
rect = new Rect (x, y, x + width, y + height);
|
||||
pointerMap = new HashMap<Integer, Coordinate> ();
|
||||
|
||||
/* Create the view from the context's UI thread. The window is
|
||||
unmapped, so the view is GONE. */
|
||||
|
|
@ -97,7 +131,7 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
if (parent != null)
|
||||
{
|
||||
parent.children.add (this);
|
||||
parent.view.post (new Runnable () {
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
|
|
@ -106,23 +140,6 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
EmacsWindowAttachmentManager manager;
|
||||
|
||||
manager = EmacsWindowAttachmentManager.MANAGER;
|
||||
|
||||
/* If parent is the root window, notice that there are new
|
||||
children available for interested activites to pick
|
||||
up. */
|
||||
|
||||
manager.registerWindow (EmacsWindow.this);
|
||||
}
|
||||
});
|
||||
|
||||
scratchGC = new EmacsGC ((short) 0);
|
||||
}
|
||||
|
|
@ -159,7 +176,7 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
+ "children!");
|
||||
|
||||
/* Remove the view from its parent and make it invisible. */
|
||||
view.post (new Runnable () {
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
|
|
@ -174,7 +191,7 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
|
||||
parent = (View) view.getParent ();
|
||||
|
||||
if (parent != null && attached == null)
|
||||
if (parent != null)
|
||||
((ViewGroup) parent).removeView (view);
|
||||
|
||||
manager.detachWindow (EmacsWindow.this);
|
||||
|
|
@ -199,24 +216,33 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
public void
|
||||
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;
|
||||
|
||||
EmacsNative.sendConfigureNotify (this.handle,
|
||||
System.currentTimeMillis (),
|
||||
left, top, rect.width (),
|
||||
rect.height ());
|
||||
}
|
||||
|
||||
rectWidth = right - left;
|
||||
rectHeight = bottom - top;
|
||||
|
||||
EmacsNative.sendConfigureNotify (this.handle,
|
||||
System.currentTimeMillis (),
|
||||
left, top, rectWidth,
|
||||
rectHeight);
|
||||
}
|
||||
|
||||
public void
|
||||
requestViewLayout ()
|
||||
{
|
||||
view.post (new Runnable () {
|
||||
/* This is necessary because otherwise subsequent drawing on the
|
||||
Emacs thread may be lost. */
|
||||
view.explicitlyDirtyBitmap (rect);
|
||||
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
|
|
@ -261,28 +287,77 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
public void
|
||||
mapWindow ()
|
||||
{
|
||||
view.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
if (isMapped)
|
||||
return;
|
||||
|
||||
view.setVisibility (View.VISIBLE);
|
||||
/* Eventually this should check no-focus-on-map. */
|
||||
view.requestFocus ();
|
||||
}
|
||||
});
|
||||
isMapped = true;
|
||||
|
||||
if (parent == null)
|
||||
{
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
EmacsWindowAttachmentManager manager;
|
||||
|
||||
/* Make the view visible, first of all. */
|
||||
view.setVisibility (View.VISIBLE);
|
||||
|
||||
manager = EmacsWindowAttachmentManager.MANAGER;
|
||||
|
||||
/* If parent is the root window, notice that there are new
|
||||
children available for interested activites to pick
|
||||
up. */
|
||||
manager.registerWindow (EmacsWindow.this);
|
||||
|
||||
if (!getDontFocusOnMap ())
|
||||
/* Eventually this should check no-focus-on-map. */
|
||||
view.requestFocus ();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do the same thing as above, but don't register this
|
||||
window. */
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.setVisibility (View.VISIBLE);
|
||||
|
||||
if (!getDontFocusOnMap ())
|
||||
/* Eventually this should check no-focus-on-map. */
|
||||
view.requestFocus ();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void
|
||||
unmapWindow ()
|
||||
{
|
||||
if (!isMapped)
|
||||
return;
|
||||
|
||||
isMapped = false;
|
||||
|
||||
view.post (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
EmacsWindowAttachmentManager manager;
|
||||
|
||||
manager = EmacsWindowAttachmentManager.MANAGER;
|
||||
|
||||
view.setVisibility (View.GONE);
|
||||
|
||||
/* Now that the window is unmapped, unregister it as
|
||||
well. */
|
||||
manager.detachWindow (EmacsWindow.this);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -413,6 +488,161 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
return 4;
|
||||
}
|
||||
|
||||
/* Return the ID of the pointer which changed in EVENT. Value is -1
|
||||
if it could not be determined, else the pointer that changed, or
|
||||
-2 if -1 would have been returned, but there is also a pointer
|
||||
that is a mouse. */
|
||||
|
||||
private int
|
||||
figureChange (MotionEvent event)
|
||||
{
|
||||
int pointerID, i, truncatedX, truncatedY, pointerIndex;
|
||||
Coordinate coordinate;
|
||||
boolean mouseFlag;
|
||||
|
||||
/* pointerID is always initialized but the Java compiler is too
|
||||
dumb to know that. */
|
||||
pointerID = -1;
|
||||
mouseFlag = false;
|
||||
|
||||
switch (event.getActionMasked ())
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
/* Primary pointer pressed with index 0. */
|
||||
|
||||
/* Detect mice. If this is a mouse event, give it to
|
||||
onSomeKindOfMotionEvent. */
|
||||
if ((Build.VERSION.SDK_INT
|
||||
>= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
&& event.getToolType (0) == MotionEvent.TOOL_TYPE_MOUSE)
|
||||
return -2;
|
||||
|
||||
pointerID = event.getPointerId (0);
|
||||
pointerMap.put (pointerID,
|
||||
new Coordinate ((int) event.getX (0),
|
||||
(int) event.getY (0)));
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
/* Primary pointer released with index 0. */
|
||||
pointerID = event.getPointerId (0);
|
||||
pointerMap.remove (pointerID);
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
/* New pointer. Find the pointer ID from the index and place
|
||||
it in the map. */
|
||||
pointerIndex = event.getActionIndex ();
|
||||
pointerID = event.getPointerId (pointerIndex);
|
||||
pointerMap.put (pointerID,
|
||||
new Coordinate ((int) event.getX (pointerID),
|
||||
(int) event.getY (pointerID)));
|
||||
break;
|
||||
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
/* Pointer removed. Remove it from the map. */
|
||||
pointerIndex = event.getActionIndex ();
|
||||
pointerID = event.getPointerId (pointerIndex);
|
||||
pointerMap.remove (pointerID);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
/* Loop through each pointer in the event. */
|
||||
for (i = 0; i < event.getPointerCount (); ++i)
|
||||
{
|
||||
pointerID = event.getPointerId (i);
|
||||
|
||||
/* Look up that pointer in the map. */
|
||||
coordinate = pointerMap.get (pointerID);
|
||||
|
||||
if (coordinate != null)
|
||||
{
|
||||
/* See if coordinates have changed. */
|
||||
truncatedX = (int) event.getX (i);
|
||||
truncatedY = (int) event.getY (i);
|
||||
|
||||
if (truncatedX != coordinate.x
|
||||
|| truncatedY != coordinate.y)
|
||||
{
|
||||
/* The pointer changed. Update the coordinate and
|
||||
break out of the loop. */
|
||||
coordinate.x = truncatedX;
|
||||
coordinate.y = truncatedY;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* See if this is a mouse. If so, set the mouseFlag. */
|
||||
if ((Build.VERSION.SDK_INT
|
||||
>= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
&& event.getToolType (i) == MotionEvent.TOOL_TYPE_MOUSE)
|
||||
mouseFlag = true;
|
||||
}
|
||||
|
||||
/* Set the pointer ID to -1 if the loop failed to find any
|
||||
changed pointer. If a mouse pointer was found, set it to
|
||||
-2. */
|
||||
if (i == event.getPointerCount ())
|
||||
pointerID = (mouseFlag ? -2 : -1);
|
||||
}
|
||||
|
||||
/* Return the pointer ID. */
|
||||
return pointerID;
|
||||
}
|
||||
|
||||
public boolean
|
||||
onTouchEvent (MotionEvent event)
|
||||
{
|
||||
int pointerID, index;
|
||||
|
||||
/* Extract the ``touch ID'' (or in Android, the ``pointer
|
||||
ID''.) */
|
||||
pointerID = figureChange (event);
|
||||
|
||||
if (pointerID < 0)
|
||||
{
|
||||
/* If this is a mouse event, give it to
|
||||
onSomeKindOfMotionEvent. */
|
||||
if (pointerID == -2)
|
||||
return onSomeKindOfMotionEvent (event);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Find the pointer index corresponding to the event. */
|
||||
index = event.findPointerIndex (pointerID);
|
||||
|
||||
switch (event.getActionMasked ())
|
||||
{
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN:
|
||||
/* Touch down event. */
|
||||
EmacsNative.sendTouchDown (this.handle, (int) event.getX (index),
|
||||
(int) event.getY (index),
|
||||
event.getEventTime (), pointerID);
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
/* Touch up event. */
|
||||
EmacsNative.sendTouchUp (this.handle, (int) event.getX (index),
|
||||
(int) event.getY (index),
|
||||
event.getEventTime (), pointerID);
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
/* Pointer motion event. */
|
||||
EmacsNative.sendTouchMove (this.handle, (int) event.getX (index),
|
||||
(int) event.getY (index),
|
||||
event.getEventTime (), pointerID);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean
|
||||
onSomeKindOfMotionEvent (MotionEvent event)
|
||||
{
|
||||
|
|
@ -472,13 +702,201 @@ public class EmacsWindow extends EmacsHandleObject
|
|||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_UP:
|
||||
/* Emacs must return true even though touch events are not yet
|
||||
handled, because the value of this function is used by the
|
||||
system to decide whether or not Emacs gets ACTION_MOVE
|
||||
/* Emacs must return true even though touch events are not
|
||||
handled here, because the value of this function is used by
|
||||
the system to decide whether or not Emacs gets ACTION_MOVE
|
||||
events. */
|
||||
return true;
|
||||
|
||||
case MotionEvent.ACTION_SCROLL:
|
||||
/* Send a scroll event with the specified deltas. */
|
||||
EmacsNative.sendWheel (this.handle, (int) event.getX (),
|
||||
(int) event.getY (),
|
||||
event.getEventTime (),
|
||||
lastModifiers,
|
||||
event.getAxisValue (MotionEvent.AXIS_HSCROLL),
|
||||
event.getAxisValue (MotionEvent.AXIS_VSCROLL));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void
|
||||
reparentTo (final EmacsWindow otherWindow, int x, int y)
|
||||
{
|
||||
int width, height;
|
||||
|
||||
/* Reparent this window to the other window. */
|
||||
|
||||
if (parent != null)
|
||||
parent.children.remove (this);
|
||||
|
||||
if (otherWindow != null)
|
||||
otherWindow.children.add (this);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* Now do the work necessary on the UI thread to reparent the
|
||||
window. */
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
EmacsWindowAttachmentManager manager;
|
||||
View parent;
|
||||
|
||||
/* First, detach this window if necessary. */
|
||||
manager = EmacsWindowAttachmentManager.MANAGER;
|
||||
manager.detachWindow (EmacsWindow.this);
|
||||
|
||||
/* Also unparent this view. */
|
||||
parent = (View) view.getParent ();
|
||||
|
||||
if (parent != null)
|
||||
((ViewGroup) parent).removeView (view);
|
||||
|
||||
/* Next, either add this window as a child of the new
|
||||
parent's view, or make it available again. */
|
||||
if (otherWindow != null)
|
||||
otherWindow.view.addView (view);
|
||||
else if (EmacsWindow.this.isMapped)
|
||||
manager.registerWindow (EmacsWindow.this);
|
||||
|
||||
/* Request relayout. */
|
||||
view.requestLayout ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void
|
||||
makeInputFocus (long time)
|
||||
{
|
||||
/* TIME is currently ignored. Request the input focus now. */
|
||||
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.requestFocus ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void
|
||||
raise ()
|
||||
{
|
||||
/* This does nothing here. */
|
||||
if (parent == null)
|
||||
return;
|
||||
|
||||
/* Remove and add this view again. */
|
||||
parent.children.remove (this);
|
||||
parent.children.add (this);
|
||||
|
||||
/* Request a relayout. */
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.raise ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void
|
||||
lower ()
|
||||
{
|
||||
/* This does nothing here. */
|
||||
if (parent == null)
|
||||
return;
|
||||
|
||||
/* Remove and add this view again. */
|
||||
parent.children.remove (this);
|
||||
parent.children.add (this);
|
||||
|
||||
/* Request a relayout. */
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.lower ();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public int[]
|
||||
getWindowGeometry ()
|
||||
{
|
||||
int[] array;
|
||||
Rect rect;
|
||||
|
||||
array = new int[4];
|
||||
rect = getGeometry ();
|
||||
|
||||
array[0] = rect.left;
|
||||
array[1] = rect.top;
|
||||
array[2] = rect.width ();
|
||||
array[3] = rect.height ();
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public void
|
||||
noticeIconified ()
|
||||
{
|
||||
isIconified = true;
|
||||
EmacsNative.sendIconified (this.handle);
|
||||
}
|
||||
|
||||
public void
|
||||
noticeDeiconified ()
|
||||
{
|
||||
isIconified = false;
|
||||
EmacsNative.sendDeiconified (this.handle);
|
||||
}
|
||||
|
||||
public synchronized void
|
||||
setDontAcceptFocus (final boolean dontAcceptFocus)
|
||||
{
|
||||
this.dontAcceptFocus = dontAcceptFocus;
|
||||
|
||||
/* Update the view's focus state. */
|
||||
EmacsService.SERVICE.runOnUiThread (new Runnable () {
|
||||
@Override
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
view.setFocusable (!dontAcceptFocus);
|
||||
view.setFocusableInTouchMode (!dontAcceptFocus);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized void
|
||||
setDontFocusOnMap (final boolean dontFocusOnMap)
|
||||
{
|
||||
this.dontFocusOnMap = dontFocusOnMap;
|
||||
}
|
||||
|
||||
public synchronized boolean
|
||||
getDontFocusOnMap ()
|
||||
{
|
||||
return dontFocusOnMap;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue