From: Po Lu Date: Fri, 10 Mar 2023 07:16:05 +0000 (+0800) Subject: Implement mouse cursors on Android 7.0 and later X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=ae5513ede52536df2cd823699d6168985915ce0f;p=emacs.git Implement mouse cursors on Android 7.0 and later * java/org/gnu/emacs/EmacsWindow.java (defineCursor): New function. * src/android.c (struct android_emacs_cursor): New struct. (android_init_emacs_cursor): New function. (JNICALL): Call it. (android_create_font_cursor, android_define_cursor) (android_free_cursor): New functions. * src/android.h (enum android_handle_type): Add cursor handle type. * src/androidfns.c (Fx_create_frame, android_create_tip_frame) (enum mouse_cursor, struct mouse_cursor_types, mouse_cursor_types) (struct mouse_cursor_data, android_set_mouse_color) (syms_of_androidfns): * src/androidgui.h (enum android_cursor_shape): * src/androidterm.c (make_invisible_cursor) (android_toggle_invisible_pointer, android_free_frame_resources) (android_define_frame_cursor): * src/androidterm.h (struct android_display_info) (struct android_output): Port mouse cursor code over from X. --- diff --git a/java/org/gnu/emacs/EmacsWindow.java b/java/org/gnu/emacs/EmacsWindow.java index 3569d93136b..6be609edcfe 100644 --- a/java/org/gnu/emacs/EmacsWindow.java +++ b/java/org/gnu/emacs/EmacsWindow.java @@ -1222,4 +1222,20 @@ public final class EmacsWindow extends EmacsHandleObject } }); } + + public void + defineCursor (final EmacsCursor cursor) + { + /* Don't post this message if pointer icons aren't supported. */ + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) + view.post (new Runnable () { + @Override + public void + run () + { + view.setPointerIcon (cursor.icon); + } + }); + } }; diff --git a/src/android.c b/src/android.c index 763e17e9430..e39c34136de 100644 --- a/src/android.c +++ b/src/android.c @@ -155,6 +155,13 @@ struct android_emacs_window jmethodID translate_coordinates; jmethodID set_dont_accept_focus; jmethodID set_dont_focus_on_map; + jmethodID define_cursor; +}; + +struct android_emacs_cursor +{ + jclass class; + jmethodID constructor; }; /* The API level of the current device. */ @@ -234,6 +241,9 @@ static struct android_emacs_drawable drawable_class; /* Various methods associated with the EmacsWindow class. */ static struct android_emacs_window window_class; +/* Various methods associated with the EmacsCursor class. */ +static struct android_emacs_cursor cursor_class; + /* The last event serial used. This is a 32 bit value, but it is stored in unsigned long to be consistent with X. */ unsigned int event_serial; @@ -2288,6 +2298,38 @@ android_init_emacs_window (void) "(II)[I"); FIND_METHOD (set_dont_focus_on_map, "setDontFocusOnMap", "(Z)V"); FIND_METHOD (set_dont_accept_focus, "setDontAcceptFocus", "(Z)V"); + FIND_METHOD (define_cursor, "defineCursor", + "(Lorg/gnu/emacs/EmacsCursor;)V"); +#undef FIND_METHOD +} + +static void +android_init_emacs_cursor (void) +{ + jclass old; + + cursor_class.class + = (*android_java_env)->FindClass (android_java_env, + "org/gnu/emacs/EmacsCursor"); + eassert (cursor_class.class); + + old = cursor_class.class; + cursor_class.class + = (jclass) (*android_java_env)->NewGlobalRef (android_java_env, + (jobject) old); + ANDROID_DELETE_LOCAL_REF (old); + + if (!cursor_class.class) + emacs_abort (); + +#define FIND_METHOD(c_name, name, signature) \ + cursor_class.c_name \ + = (*android_java_env)->GetMethodID (android_java_env, \ + cursor_class.class, \ + name, signature); \ + assert (cursor_class.c_name); + + FIND_METHOD (constructor, "", "(SI)V"); #undef FIND_METHOD } @@ -2339,6 +2381,7 @@ NATIVE_NAME (initEmacs) (JNIEnv *env, jobject object, jarray argv, android_init_graphics_point (); android_init_emacs_drawable (); android_init_emacs_window (); + android_init_emacs_cursor (); /* Set HOME to the app data directory. */ setenv ("HOME", android_files_dir, 1); @@ -6243,6 +6286,81 @@ android_asset_fstat (struct android_fd_or_asset asset, return 0; } + + +/* Window cursor support. */ + +android_cursor +android_create_font_cursor (enum android_cursor_shape shape) +{ + android_cursor id; + short prev_max_handle; + jobject object; + + /* First, allocate the cursor handle. */ + prev_max_handle = max_handle; + id = android_alloc_id (); + + if (!id) + error ("Out of cursor handles!"); + + /* Next, create the cursor. */ + object = (*android_java_env)->NewObject (android_java_env, + cursor_class.class, + cursor_class.constructor, + (jshort) id, + (jint) shape); + if (!object) + { + (*android_java_env)->ExceptionClear (android_java_env); + max_handle = prev_max_handle; + memory_full (0); + } + + android_handles[id].type = ANDROID_HANDLE_CURSOR; + android_handles[id].handle + = (*android_java_env)->NewGlobalRef (android_java_env, object); + (*android_java_env)->ExceptionClear (android_java_env); + ANDROID_DELETE_LOCAL_REF (object); + + if (!android_handles[id].handle) + memory_full (0); + + return id; +} + +void +android_define_cursor (android_window window, android_cursor cursor) +{ + jobject window1, cursor1; + jmethodID method; + + window1 = android_resolve_handle (window, ANDROID_HANDLE_WINDOW); + cursor1 = (cursor + ? android_resolve_handle (cursor, ANDROID_HANDLE_CURSOR) + : NULL); + method = window_class.define_cursor; + + (*android_java_env)->CallNonvirtualVoidMethod (android_java_env, + window1, + window_class.class, + method, cursor1); + android_exception_check (); +} + +void +android_free_cursor (android_cursor cursor) +{ + if (android_handles[cursor].type != ANDROID_HANDLE_CURSOR) + { + __android_log_print (ANDROID_LOG_ERROR, __func__, + "Trying to destroy something not a CURSOR!"); + emacs_abort (); + } + + android_destroy_handle (cursor); +} + #else /* ANDROID_STUBIFY */ /* X emulation functions for Android. */ diff --git a/src/android.h b/src/android.h index 450f3859df9..03592bd955d 100644 --- a/src/android.h +++ b/src/android.h @@ -63,6 +63,7 @@ enum android_handle_type ANDROID_HANDLE_WINDOW, ANDROID_HANDLE_GCONTEXT, ANDROID_HANDLE_PIXMAP, + ANDROID_HANDLE_CURSOR, }; extern jobject android_resolve_handle (android_handle, diff --git a/src/androidfns.c b/src/androidfns.c index 2724b9595c1..589ae4331cb 100644 --- a/src/androidfns.c +++ b/src/androidfns.c @@ -802,6 +802,7 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, FRAME_BACKGROUND_PIXEL (f) = -1; f->output_data.android->cursor_pixel = -1; f->output_data.android->cursor_foreground_pixel = -1; + f->output_data.android->mouse_pixel = -1; black = build_string ("black"); FRAME_FOREGROUND_PIXEL (f) @@ -812,6 +813,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); f->output_data.android->cursor_foreground_pixel = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); + f->output_data.android->mouse_pixel + = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); } /* Set the name; the functions to which we pass f expect the name to @@ -1798,6 +1801,7 @@ android_create_tip_frame (struct android_display_info *dpyinfo, FRAME_BACKGROUND_PIXEL (f) = -1; f->output_data.android->cursor_pixel = -1; f->output_data.android->cursor_foreground_pixel = -1; + f->output_data.android->mouse_pixel = -1; black = build_string ("black"); FRAME_FOREGROUND_PIXEL (f) @@ -1808,6 +1812,8 @@ android_create_tip_frame (struct android_display_info *dpyinfo, = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); f->output_data.android->cursor_foreground_pixel = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); + f->output_data.android->mouse_pixel + = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); } /* Set the name; the functions to which we pass f expect the name to @@ -2632,13 +2638,147 @@ android_set_menu_bar_lines (struct frame *f, Lisp_Object value, adjust_frame_glyphs (f); } + + +/* These enums must stay in sync with the mouse_cursor_types array + below! */ + +enum mouse_cursor + { + mouse_cursor_text, + mouse_cursor_nontext, + mouse_cursor_hourglass, + mouse_cursor_mode, + mouse_cursor_hand, + mouse_cursor_horizontal_drag, + mouse_cursor_vertical_drag, + mouse_cursor_left_edge, + mouse_cursor_top_left_corner, + mouse_cursor_top_edge, + mouse_cursor_top_right_corner, + mouse_cursor_right_edge, + mouse_cursor_bottom_right_corner, + mouse_cursor_bottom_edge, + mouse_cursor_bottom_left_corner, + mouse_cursor_max + }; + +struct mouse_cursor_types +{ + /* Printable name for error messages (optional). */ + const char *name; + + /* Lisp variable controlling the cursor shape. */ + /* FIXME: A couple of these variables are defined in the C code but + are not actually accessible from Lisp. They should probably be + made accessible or removed. */ + Lisp_Object *shape_var_ptr; + + /* The default shape. */ + int default_shape; +}; + +/* This array must stay in sync with enum mouse_cursor above! */ + +static const struct mouse_cursor_types mouse_cursor_types[] = + { + {"text", &Vx_pointer_shape, ANDROID_XC_XTERM, }, + {"nontext", &Vx_nontext_pointer_shape, ANDROID_XC_LEFT_PTR, }, + {"hourglass", &Vx_hourglass_pointer_shape, ANDROID_XC_WATCH, }, + {"modeline", &Vx_mode_pointer_shape, ANDROID_XC_XTERM, }, + {NULL, &Vx_sensitive_text_pointer_shape, ANDROID_XC_HAND2, }, + {NULL, &Vx_window_horizontal_drag_shape, ANDROID_XC_SB_H_DOUBLE_ARROW, }, + {NULL, &Vx_window_vertical_drag_shape, ANDROID_XC_SB_V_DOUBLE_ARROW, }, + {NULL, &Vx_window_left_edge_shape, ANDROID_XC_LEFT_SIDE, }, + {NULL, &Vx_window_top_left_corner_shape, ANDROID_XC_TOP_LEFT_CORNER, }, + {NULL, &Vx_window_top_edge_shape, ANDROID_XC_TOP_SIDE, }, + {NULL, &Vx_window_top_right_corner_shape, ANDROID_XC_TOP_RIGHT_CORNER, }, + {NULL, &Vx_window_right_edge_shape, ANDROID_XC_RIGHT_SIDE, }, + {NULL, &Vx_window_bottom_right_corner_shape, + ANDROID_XC_BOTTOM_RIGHT_CORNER, }, + {NULL, &Vx_window_bottom_edge_shape, ANDROID_XC_BOTTOM_SIDE, }, + {NULL, &Vx_window_bottom_left_corner_shape, + ANDROID_XC_BOTTOM_LEFT_CORNER, }, + }; + +struct mouse_cursor_data +{ + /* Cursor numbers chosen. */ + unsigned int cursor_num[mouse_cursor_max]; + + /* Allocated Cursor values, or zero for failed attempts. */ + android_cursor cursor[mouse_cursor_max]; +}; + + + static void android_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { - /* Changing the mouse color is unsupported under Android, so this is - left intact. */ - android_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); + struct android_output *x = f->output_data.android; + struct mouse_cursor_data cursor_data = { -1, -1 }; + unsigned long pixel = android_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); + unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f); + int i; + + /* Don't let pointers be invisible. */ + if (mask_color == pixel) + pixel = FRAME_FOREGROUND_PIXEL (f); + + x->mouse_pixel = pixel; + + for (i = 0; i < mouse_cursor_max; i++) + { + Lisp_Object shape_var = *mouse_cursor_types[i].shape_var_ptr; + cursor_data.cursor_num[i] + = (!NILP (shape_var) + ? check_uinteger_max (shape_var, UINT_MAX) + : mouse_cursor_types[i].default_shape); + } + + block_input (); + + for (i = 0; i < mouse_cursor_max; i++) + cursor_data.cursor[i] + = android_create_font_cursor (cursor_data.cursor_num[i]); + + if (FRAME_ANDROID_WINDOW (f)) + { + f->output_data.android->current_cursor + = cursor_data.cursor[mouse_cursor_text]; + android_define_cursor (FRAME_ANDROID_WINDOW (f), + f->output_data.android->current_cursor); + } + +#define INSTALL_CURSOR(FIELD, SHORT_INDEX) \ + eassert (x->FIELD \ + != cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX]); \ + if (x->FIELD != 0) \ + android_free_cursor (x->FIELD); \ + x->FIELD = cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX]; + + INSTALL_CURSOR (text_cursor, text); + INSTALL_CURSOR (nontext_cursor, nontext); + INSTALL_CURSOR (hourglass_cursor, hourglass); + INSTALL_CURSOR (modeline_cursor, mode); + INSTALL_CURSOR (hand_cursor, hand); + INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag); + INSTALL_CURSOR (vertical_drag_cursor, vertical_drag); + INSTALL_CURSOR (left_edge_cursor, left_edge); + INSTALL_CURSOR (top_left_corner_cursor, top_left_corner); + INSTALL_CURSOR (top_edge_cursor, top_edge); + INSTALL_CURSOR (top_right_corner_cursor, top_right_corner); + INSTALL_CURSOR (right_edge_cursor, right_edge); + INSTALL_CURSOR (bottom_right_corner_cursor, bottom_right_corner); + INSTALL_CURSOR (bottom_edge_cursor, bottom_edge); + INSTALL_CURSOR (bottom_left_corner_cursor, bottom_left_corner); + +#undef INSTALL_CURSOR + + unblock_input (); + + update_face_from_frame_parameter (f, Qmouse_color, arg); } static void @@ -2845,6 +2985,81 @@ syms_of_androidfns (void) DEFSYM (Qtrue_color, "true-color"); DEFSYM (Qalways, "always"); + DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_pointer_shape = Qnil; + +#if false /* This doesn't really do anything. */ + DEFVAR_LISP ("x-nontext-pointer-shape", Vx_nontext_pointer_shape, + doc: /* SKIP: real doc in xfns.c. */); +#endif + Vx_nontext_pointer_shape = Qnil; + + DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_hourglass_pointer_shape = Qnil; + + DEFVAR_LISP ("x-sensitive-text-pointer-shape", + Vx_sensitive_text_pointer_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_sensitive_text_pointer_shape = Qnil; + + DEFVAR_LISP ("x-window-horizontal-drag-cursor", + Vx_window_horizontal_drag_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_window_horizontal_drag_shape = Qnil; + + DEFVAR_LISP ("x-window-vertical-drag-cursor", + Vx_window_vertical_drag_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_window_vertical_drag_shape = Qnil; + + DEFVAR_LISP ("x-window-left-edge-cursor", + Vx_window_left_edge_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_window_left_edge_shape = Qnil; + + DEFVAR_LISP ("x-window-top-left-corner-cursor", + Vx_window_top_left_corner_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_window_top_left_corner_shape = Qnil; + + DEFVAR_LISP ("x-window-top-edge-cursor", + Vx_window_top_edge_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_window_top_edge_shape = Qnil; + + DEFVAR_LISP ("x-window-top-right-corner-cursor", + Vx_window_top_right_corner_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_window_top_right_corner_shape = Qnil; + + DEFVAR_LISP ("x-window-right-edge-cursor", + Vx_window_right_edge_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_window_right_edge_shape = Qnil; + + DEFVAR_LISP ("x-window-bottom-right-corner-cursor", + Vx_window_bottom_right_corner_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_window_bottom_right_corner_shape = Qnil; + + DEFVAR_LISP ("x-window-bottom-edge-cursor", + Vx_window_bottom_edge_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_window_bottom_edge_shape = Qnil; + +#if false /* This doesn't really do anything. */ + DEFVAR_LISP ("x-mode-pointer-shape", Vx_mode_pointer_shape, + doc: /* SKIP: real doc in xfns.c. */); +#endif + Vx_mode_pointer_shape = Qnil; + + DEFVAR_LISP ("x-window-bottom-left-corner-cursor", + Vx_window_bottom_left_corner_shape, + doc: /* SKIP: real text in xfns.c. */); + Vx_window_bottom_left_corner_shape = Qnil; + DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel, doc: /* SKIP: real doc in xfns.c. */); Vx_cursor_fore_pixel = Qnil; diff --git a/src/androidgui.h b/src/androidgui.h index 5858a168080..b918d03ceca 100644 --- a/src/androidgui.h +++ b/src/androidgui.h @@ -36,6 +36,7 @@ typedef android_handle android_pixmap, Emacs_Pixmap; typedef android_handle android_window, Emacs_Window; typedef android_handle android_gcontext, GContext; typedef android_handle android_drawable, Drawable; +typedef android_handle android_cursor, Emacs_Cursor; typedef unsigned int android_time; @@ -162,10 +163,6 @@ struct android_swap_info enum android_swap_action swap_action; }; -/* Android doesn't support cursors, so define this to something - unused. */ -typedef char Emacs_Cursor; - #define NativeRectangle Emacs_Rectangle #define CONVERT_TO_NATIVE_RECT(xr, nr) ((xr) = (nr)) #define CONVERT_FROM_EMACS_RECT(xr, nr) ((nr) = (xr)) @@ -620,6 +617,29 @@ extern void android_update_extracted_text (android_window, void *, int); extern int android_set_fullscreen (android_window, bool); +enum android_cursor_shape + { + ANDROID_XC_XTERM = 1008, + ANDROID_XC_LEFT_PTR = 1000, + ANDROID_XC_WATCH = 1004, + ANDROID_XC_HAND2 = 1002, + ANDROID_XC_SB_H_DOUBLE_ARROW = 1014, + ANDROID_XC_SB_V_DOUBLE_ARROW = 1015, + ANDROID_XC_LEFT_SIDE = 1020, + ANDROID_XC_TOP_LEFT_CORNER = 1020, + ANDROID_XC_TOP_SIDE = 1020, + ANDROID_XC_TOP_RIGHT_CORNER = 1020, + ANDROID_XC_RIGHT_SIDE = 1020, + ANDROID_XC_BOTTOM_RIGHT_CORNER = 1020, + ANDROID_XC_BOTTOM_SIDE = 1020, + ANDROID_XC_BOTTOM_LEFT_CORNER = 1020, + ANDROID_XC_NULL = 0, + }; + +extern android_cursor android_create_font_cursor (enum android_cursor_shape); +extern void android_define_cursor (android_window, android_cursor); +extern void android_free_cursor (android_cursor); + #endif diff --git a/src/androidterm.c b/src/androidterm.c index 2e2bf86706c..3a0f1ccc463 100644 --- a/src/androidterm.c +++ b/src/androidterm.c @@ -224,10 +224,38 @@ android_ring_bell (struct frame *f) } } +static android_cursor +make_invisible_cursor (struct android_display_info *dpyinfo) +{ + return android_create_font_cursor (ANDROID_XC_NULL); +} + static void -android_toggle_invisible_pointer (struct frame *f, bool invisible) +android_toggle_visible_pointer (struct frame *f, bool invisible) { + struct android_display_info *dpyinfo; + + dpyinfo = FRAME_DISPLAY_INFO (f); + + if (!dpyinfo->invisible_cursor) + dpyinfo->invisible_cursor = make_invisible_cursor (dpyinfo); + + if (invisible) + android_define_cursor (FRAME_ANDROID_WINDOW (f), + dpyinfo->invisible_cursor); + else + android_define_cursor (FRAME_ANDROID_WINDOW (f), + f->output_data.android->current_cursor); + f->pointer_invisible = invisible; +} + +static void +android_toggle_invisible_pointer (struct frame *f, bool invisible) +{ + block_input (); + android_toggle_visible_pointer (f, invisible); + unblock_input (); } /* Start an update of frame F. This function is installed as a hook @@ -2040,6 +2068,38 @@ android_free_frame_resources (struct frame *f) android_free_gcs (f); + /* Free cursors. */ + if (f->output_data.android->text_cursor) + android_free_cursor (f->output_data.android->text_cursor); + if (f->output_data.android->nontext_cursor) + android_free_cursor (f->output_data.android->nontext_cursor); + if (f->output_data.android->modeline_cursor) + android_free_cursor (f->output_data.android->modeline_cursor); + if (f->output_data.android->hand_cursor) + android_free_cursor (f->output_data.android->hand_cursor); + if (f->output_data.android->hourglass_cursor) + android_free_cursor (f->output_data.android->hourglass_cursor); + if (f->output_data.android->horizontal_drag_cursor) + android_free_cursor (f->output_data.android->horizontal_drag_cursor); + if (f->output_data.android->vertical_drag_cursor) + android_free_cursor (f->output_data.android->vertical_drag_cursor); + if (f->output_data.android->left_edge_cursor) + android_free_cursor (f->output_data.android->left_edge_cursor); + if (f->output_data.android->top_left_corner_cursor) + android_free_cursor (f->output_data.android->top_left_corner_cursor); + if (f->output_data.android->top_edge_cursor) + android_free_cursor (f->output_data.android->top_edge_cursor); + if (f->output_data.android->top_right_corner_cursor) + android_free_cursor (f->output_data.android->top_right_corner_cursor); + if (f->output_data.android->right_edge_cursor) + android_free_cursor (f->output_data.android->right_edge_cursor); + if (f->output_data.android->bottom_right_corner_cursor) + android_free_cursor (f->output_data.android->bottom_right_corner_cursor); + if (f->output_data.android->bottom_edge_cursor) + android_free_cursor (f->output_data.android->bottom_edge_cursor); + if (f->output_data.android->bottom_left_corner_cursor) + android_free_cursor (f->output_data.android->bottom_left_corner_cursor); + /* Free extra GCs allocated by android_setup_relief_colors. */ if (f->output_data.android->white_relief.gc) { @@ -3971,7 +4031,11 @@ android_draw_glyph_string (struct glyph_string *s) static void android_define_frame_cursor (struct frame *f, Emacs_Cursor cursor) { - /* Not supported, because cursors are not supported on Android. */ + if (!f->pointer_invisible + && f->output_data.android->current_cursor != cursor) + android_define_cursor (FRAME_ANDROID_WINDOW (f), cursor); + + f->output_data.android->current_cursor = cursor; } static void diff --git a/src/androidterm.h b/src/androidterm.h index 9964eb54880..2e59365b56d 100644 --- a/src/androidterm.h +++ b/src/androidterm.h @@ -136,6 +136,9 @@ struct android_display_info /* ID of the last menu event received. -1 means Emacs is waiting for a context menu event. */ int menu_event_id; + + /* The invisible cursor used for pointer blanking. */ + android_cursor invisible_cursor; }; /* Structure representing a single tool (finger or stylus) pressed @@ -176,6 +179,7 @@ struct android_output /* Various colors. */ unsigned long cursor_pixel; + unsigned long mouse_pixel; unsigned long cursor_foreground_pixel; /* Foreground color for scroll bars. A value of -1 means use the @@ -187,7 +191,7 @@ struct android_output bars). */ unsigned long scroll_bar_background_pixel; - /* Unused stuff (cursors). */ + /* Cursors associated with this frame. */ Emacs_Cursor text_cursor; Emacs_Cursor nontext_cursor; Emacs_Cursor modeline_cursor;