1
Fork 0
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:
Po Lu 2023-01-13 15:53:08 +08:00
parent 2fa5583d96
commit f9732131cf
33 changed files with 2815 additions and 351 deletions

View file

@ -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;
}
};