mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-07 12:20:39 -08:00
Implement submenus on Android
* java/org/gnu/emacs/EmacsActivity.java (onCreate): Set the default theme to Theme.DeviceDefault.NoActionBar if possible. (onContextMenuClosed): Add hack for Android bug. * java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu) (onMenuItemClick): Set flag upon submenu selection. (inflateMenuItems): Set onClickListener for submenus as well. (display1): Clear new flag. * java/org/gnu/emacs/EmacsDrawRectangle.java (perform): Fix rectangle bounds. * java/org/gnu/emacs/EmacsNative.java (EmacsNative): * java/org/gnu/emacs/EmacsService.java (onCreate): Pass cache directory. (sync): New function. * src/android.c (struct android_emacs_service): New method `sync'. (setEmacsParams, initEmacs): Handle cache directory. (android_init_emacs_service): Initialize new method `sync'. (android_sync): New function. * src/androidfns.c (Fx_show_tip): Call both functions. * src/androidgui.h: Update prototypes. * src/androidmenu.c (struct android_menu_subprefix) (android_free_subprefixes, android_menu_show): Handle submenu prefixes correctly. * src/androidterm.c (handle_one_android_event): Clear help echo on MotionNotify like on X. * src/menu.c (single_menu_item): Enable submenus on Android.
This commit is contained in:
parent
a336fd98a1
commit
da9ae10636
11 changed files with 255 additions and 24 deletions
|
|
@ -27,6 +27,7 @@ import android.app.Activity;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.FrameLayout.LayoutParams;
|
||||
|
|
@ -162,7 +163,11 @@ public class EmacsActivity extends Activity
|
|||
FrameLayout.LayoutParams params;
|
||||
|
||||
/* Set the theme to one without a title bar. */
|
||||
setTheme (android.R.style.Theme_NoTitleBar);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
||||
setTheme (android.R.style.Theme_DeviceDefault_NoActionBar);
|
||||
else
|
||||
setTheme (android.R.style.Theme_NoTitleBar);
|
||||
|
||||
params = new FrameLayout.LayoutParams (LayoutParams.MATCH_PARENT,
|
||||
LayoutParams.MATCH_PARENT);
|
||||
|
|
@ -235,6 +240,11 @@ public class EmacsActivity extends Activity
|
|||
{
|
||||
Log.d (TAG, "onContextMenuClosed: " + menu);
|
||||
|
||||
/* See the comment inside onMenuItemClick. */
|
||||
if (EmacsContextMenu.wasSubmenuSelected
|
||||
&& menu.toString ().contains ("ContextMenuBuilder"))
|
||||
return;
|
||||
|
||||
/* Send a context menu event given that no menu item has already
|
||||
been selected. */
|
||||
if (!EmacsContextMenu.itemAlreadySelected)
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import android.os.Bundle;
|
|||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.SubMenu;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
|
|
@ -47,6 +48,9 @@ public class EmacsContextMenu
|
|||
/* Whether or not an item was selected. */
|
||||
public static boolean itemAlreadySelected;
|
||||
|
||||
/* Whether or not a submenu was selected. */
|
||||
public static boolean wasSubmenuSelected;
|
||||
|
||||
private class Item implements MenuItem.OnMenuItemClickListener
|
||||
{
|
||||
public int itemID;
|
||||
|
|
@ -60,6 +64,20 @@ public class EmacsContextMenu
|
|||
{
|
||||
Log.d (TAG, "onMenuItemClick: " + itemName + " (" + itemID + ")");
|
||||
|
||||
if (subMenu != null)
|
||||
{
|
||||
/* After opening a submenu within a submenu, Android will
|
||||
send onContextMenuClosed for a ContextMenuBuilder. This
|
||||
will normally confuse Emacs into thinking that the
|
||||
context menu has been dismissed. Wrong!
|
||||
|
||||
Setting this flag makes EmacsActivity to only handle
|
||||
SubMenuBuilder being closed, which always means the menu
|
||||
has actually been dismissed. */
|
||||
wasSubmenuSelected = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Send a context menu event. */
|
||||
EmacsNative.sendContextMenu ((short) 0, itemID);
|
||||
|
||||
|
|
@ -144,7 +162,7 @@ public class EmacsContextMenu
|
|||
{
|
||||
Intent intent;
|
||||
MenuItem menuItem;
|
||||
Menu submenu;
|
||||
SubMenu submenu;
|
||||
|
||||
for (Item item : menuItems)
|
||||
{
|
||||
|
|
@ -153,7 +171,11 @@ public class EmacsContextMenu
|
|||
/* This is a submenu. Create the submenu and add the
|
||||
contents of the menu to it. */
|
||||
submenu = menu.addSubMenu (item.itemName);
|
||||
inflateMenuItems (submenu);
|
||||
item.subMenu.inflateMenuItems (submenu);
|
||||
|
||||
/* This is still needed to set wasSubmenuSelected. */
|
||||
menuItem = submenu.getItem ();
|
||||
menuItem.setOnMenuItemClickListener (item);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -184,7 +206,7 @@ public class EmacsContextMenu
|
|||
public EmacsContextMenu
|
||||
parent ()
|
||||
{
|
||||
return parent;
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
/* Like display, but does the actual work and runs in the main
|
||||
|
|
@ -197,6 +219,9 @@ public class EmacsContextMenu
|
|||
send 0 in response to the context menu being closed. */
|
||||
itemAlreadySelected = false;
|
||||
|
||||
/* No submenu has been selected yet. */
|
||||
wasSubmenuSelected = false;
|
||||
|
||||
return window.view.popupMenu (this, xPosition, yPosition);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ public class EmacsDrawRectangle
|
|||
}
|
||||
|
||||
paint = gc.gcPaint;
|
||||
rect = new Rect (x + 1, y + 1, x + width, y + height);
|
||||
rect = new Rect (x, y, x + width, y + height);
|
||||
|
||||
paint.setStyle (Paint.Style.STROKE);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ public class EmacsNative
|
|||
libDir must be the package's data storage location for native
|
||||
libraries. It is used as PATH.
|
||||
|
||||
cacheDir must be the package's cache directory. It is used as
|
||||
the `temporary-file-directory'.
|
||||
|
||||
pixelDensityX and pixelDensityY are the DPI values that will be
|
||||
used by Emacs.
|
||||
|
||||
|
|
@ -45,6 +48,7 @@ public class EmacsNative
|
|||
public static native void setEmacsParams (AssetManager assetManager,
|
||||
String filesDir,
|
||||
String libDir,
|
||||
String cacheDir,
|
||||
float pixelDensityX,
|
||||
float pixelDensityY,
|
||||
EmacsService emacsService);
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ public class EmacsService extends Service
|
|||
{
|
||||
AssetManager manager;
|
||||
Context app_context;
|
||||
String filesDir, libDir;
|
||||
String filesDir, libDir, cacheDir;
|
||||
double pixelDensityX;
|
||||
double pixelDensityY;
|
||||
|
||||
|
|
@ -126,12 +126,13 @@ public class EmacsService extends Service
|
|||
parameters. */
|
||||
filesDir = app_context.getFilesDir ().getCanonicalPath ();
|
||||
libDir = getLibraryDirectory ();
|
||||
cacheDir = app_context.getCacheDir ().getCanonicalPath ();
|
||||
|
||||
Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir
|
||||
+ " and libDir = " + libDir);
|
||||
|
||||
EmacsNative.setEmacsParams (manager, filesDir, libDir,
|
||||
(float) pixelDensityX,
|
||||
cacheDir, (float) pixelDensityX,
|
||||
(float) pixelDensityY,
|
||||
this);
|
||||
|
||||
|
|
@ -407,4 +408,35 @@ public class EmacsService extends Service
|
|||
{
|
||||
return KeyEvent.keyCodeToString (keysym);
|
||||
}
|
||||
|
||||
public void
|
||||
sync ()
|
||||
{
|
||||
Runnable runnable;
|
||||
|
||||
runnable = new Runnable () {
|
||||
public void
|
||||
run ()
|
||||
{
|
||||
synchronized (this)
|
||||
{
|
||||
notify ();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
synchronized (runnable)
|
||||
{
|
||||
runOnUiThread (runnable);
|
||||
|
||||
try
|
||||
{
|
||||
runnable.wait ();
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
EmacsNative.emacsAbort ();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue