diff options
| author | Po Lu | 2023-03-10 15:16:05 +0800 |
|---|---|---|
| committer | Po Lu | 2023-03-10 15:16:05 +0800 |
| commit | ae5513ede52536df2cd823699d6168985915ce0f (patch) | |
| tree | 61e38d5c1f5544b03778055af964e4e0289928ac /src/androidfns.c | |
| parent | a7c8ae7d675c402923e2ff8359b9cc286792bbb0 (diff) | |
| download | emacs-ae5513ede52536df2cd823699d6168985915ce0f.tar.gz emacs-ae5513ede52536df2cd823699d6168985915ce0f.zip | |
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.
Diffstat (limited to 'src/androidfns.c')
| -rw-r--r-- | src/androidfns.c | 221 |
1 files changed, 218 insertions, 3 deletions
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, | |||
| 802 | FRAME_BACKGROUND_PIXEL (f) = -1; | 802 | FRAME_BACKGROUND_PIXEL (f) = -1; |
| 803 | f->output_data.android->cursor_pixel = -1; | 803 | f->output_data.android->cursor_pixel = -1; |
| 804 | f->output_data.android->cursor_foreground_pixel = -1; | 804 | f->output_data.android->cursor_foreground_pixel = -1; |
| 805 | f->output_data.android->mouse_pixel = -1; | ||
| 805 | 806 | ||
| 806 | black = build_string ("black"); | 807 | black = build_string ("black"); |
| 807 | FRAME_FOREGROUND_PIXEL (f) | 808 | FRAME_FOREGROUND_PIXEL (f) |
| @@ -812,6 +813,8 @@ DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame, | |||
| 812 | = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); | 813 | = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); |
| 813 | f->output_data.android->cursor_foreground_pixel | 814 | f->output_data.android->cursor_foreground_pixel |
| 814 | = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); | 815 | = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); |
| 816 | f->output_data.android->mouse_pixel | ||
| 817 | = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); | ||
| 815 | } | 818 | } |
| 816 | 819 | ||
| 817 | /* Set the name; the functions to which we pass f expect the name to | 820 | /* 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, | |||
| 1798 | FRAME_BACKGROUND_PIXEL (f) = -1; | 1801 | FRAME_BACKGROUND_PIXEL (f) = -1; |
| 1799 | f->output_data.android->cursor_pixel = -1; | 1802 | f->output_data.android->cursor_pixel = -1; |
| 1800 | f->output_data.android->cursor_foreground_pixel = -1; | 1803 | f->output_data.android->cursor_foreground_pixel = -1; |
| 1804 | f->output_data.android->mouse_pixel = -1; | ||
| 1801 | 1805 | ||
| 1802 | black = build_string ("black"); | 1806 | black = build_string ("black"); |
| 1803 | FRAME_FOREGROUND_PIXEL (f) | 1807 | FRAME_FOREGROUND_PIXEL (f) |
| @@ -1808,6 +1812,8 @@ android_create_tip_frame (struct android_display_info *dpyinfo, | |||
| 1808 | = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); | 1812 | = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); |
| 1809 | f->output_data.android->cursor_foreground_pixel | 1813 | f->output_data.android->cursor_foreground_pixel |
| 1810 | = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); | 1814 | = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); |
| 1815 | f->output_data.android->mouse_pixel | ||
| 1816 | = android_decode_color (f, black, BLACK_PIX_DEFAULT (f)); | ||
| 1811 | } | 1817 | } |
| 1812 | 1818 | ||
| 1813 | /* Set the name; the functions to which we pass f expect the name to | 1819 | /* 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, | |||
| 2632 | adjust_frame_glyphs (f); | 2638 | adjust_frame_glyphs (f); |
| 2633 | } | 2639 | } |
| 2634 | 2640 | ||
| 2641 | |||
| 2642 | |||
| 2643 | /* These enums must stay in sync with the mouse_cursor_types array | ||
| 2644 | below! */ | ||
| 2645 | |||
| 2646 | enum mouse_cursor | ||
| 2647 | { | ||
| 2648 | mouse_cursor_text, | ||
| 2649 | mouse_cursor_nontext, | ||
| 2650 | mouse_cursor_hourglass, | ||
| 2651 | mouse_cursor_mode, | ||
| 2652 | mouse_cursor_hand, | ||
| 2653 | mouse_cursor_horizontal_drag, | ||
| 2654 | mouse_cursor_vertical_drag, | ||
| 2655 | mouse_cursor_left_edge, | ||
| 2656 | mouse_cursor_top_left_corner, | ||
| 2657 | mouse_cursor_top_edge, | ||
| 2658 | mouse_cursor_top_right_corner, | ||
| 2659 | mouse_cursor_right_edge, | ||
| 2660 | mouse_cursor_bottom_right_corner, | ||
| 2661 | mouse_cursor_bottom_edge, | ||
| 2662 | mouse_cursor_bottom_left_corner, | ||
| 2663 | mouse_cursor_max | ||
| 2664 | }; | ||
| 2665 | |||
| 2666 | struct mouse_cursor_types | ||
| 2667 | { | ||
| 2668 | /* Printable name for error messages (optional). */ | ||
| 2669 | const char *name; | ||
| 2670 | |||
| 2671 | /* Lisp variable controlling the cursor shape. */ | ||
| 2672 | /* FIXME: A couple of these variables are defined in the C code but | ||
| 2673 | are not actually accessible from Lisp. They should probably be | ||
| 2674 | made accessible or removed. */ | ||
| 2675 | Lisp_Object *shape_var_ptr; | ||
| 2676 | |||
| 2677 | /* The default shape. */ | ||
| 2678 | int default_shape; | ||
| 2679 | }; | ||
| 2680 | |||
| 2681 | /* This array must stay in sync with enum mouse_cursor above! */ | ||
| 2682 | |||
| 2683 | static const struct mouse_cursor_types mouse_cursor_types[] = | ||
| 2684 | { | ||
| 2685 | {"text", &Vx_pointer_shape, ANDROID_XC_XTERM, }, | ||
| 2686 | {"nontext", &Vx_nontext_pointer_shape, ANDROID_XC_LEFT_PTR, }, | ||
| 2687 | {"hourglass", &Vx_hourglass_pointer_shape, ANDROID_XC_WATCH, }, | ||
| 2688 | {"modeline", &Vx_mode_pointer_shape, ANDROID_XC_XTERM, }, | ||
| 2689 | {NULL, &Vx_sensitive_text_pointer_shape, ANDROID_XC_HAND2, }, | ||
| 2690 | {NULL, &Vx_window_horizontal_drag_shape, ANDROID_XC_SB_H_DOUBLE_ARROW, }, | ||
| 2691 | {NULL, &Vx_window_vertical_drag_shape, ANDROID_XC_SB_V_DOUBLE_ARROW, }, | ||
| 2692 | {NULL, &Vx_window_left_edge_shape, ANDROID_XC_LEFT_SIDE, }, | ||
| 2693 | {NULL, &Vx_window_top_left_corner_shape, ANDROID_XC_TOP_LEFT_CORNER, }, | ||
| 2694 | {NULL, &Vx_window_top_edge_shape, ANDROID_XC_TOP_SIDE, }, | ||
| 2695 | {NULL, &Vx_window_top_right_corner_shape, ANDROID_XC_TOP_RIGHT_CORNER, }, | ||
| 2696 | {NULL, &Vx_window_right_edge_shape, ANDROID_XC_RIGHT_SIDE, }, | ||
| 2697 | {NULL, &Vx_window_bottom_right_corner_shape, | ||
| 2698 | ANDROID_XC_BOTTOM_RIGHT_CORNER, }, | ||
| 2699 | {NULL, &Vx_window_bottom_edge_shape, ANDROID_XC_BOTTOM_SIDE, }, | ||
| 2700 | {NULL, &Vx_window_bottom_left_corner_shape, | ||
| 2701 | ANDROID_XC_BOTTOM_LEFT_CORNER, }, | ||
| 2702 | }; | ||
| 2703 | |||
| 2704 | struct mouse_cursor_data | ||
| 2705 | { | ||
| 2706 | /* Cursor numbers chosen. */ | ||
| 2707 | unsigned int cursor_num[mouse_cursor_max]; | ||
| 2708 | |||
| 2709 | /* Allocated Cursor values, or zero for failed attempts. */ | ||
| 2710 | android_cursor cursor[mouse_cursor_max]; | ||
| 2711 | }; | ||
| 2712 | |||
| 2713 | |||
| 2714 | |||
| 2635 | static void | 2715 | static void |
| 2636 | android_set_mouse_color (struct frame *f, Lisp_Object arg, | 2716 | android_set_mouse_color (struct frame *f, Lisp_Object arg, |
| 2637 | Lisp_Object oldval) | 2717 | Lisp_Object oldval) |
| 2638 | { | 2718 | { |
| 2639 | /* Changing the mouse color is unsupported under Android, so this is | 2719 | struct android_output *x = f->output_data.android; |
| 2640 | left intact. */ | 2720 | struct mouse_cursor_data cursor_data = { -1, -1 }; |
| 2641 | android_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); | 2721 | unsigned long pixel = android_decode_color (f, arg, BLACK_PIX_DEFAULT (f)); |
| 2722 | unsigned long mask_color = FRAME_BACKGROUND_PIXEL (f); | ||
| 2723 | int i; | ||
| 2724 | |||
| 2725 | /* Don't let pointers be invisible. */ | ||
| 2726 | if (mask_color == pixel) | ||
| 2727 | pixel = FRAME_FOREGROUND_PIXEL (f); | ||
| 2728 | |||
| 2729 | x->mouse_pixel = pixel; | ||
| 2730 | |||
| 2731 | for (i = 0; i < mouse_cursor_max; i++) | ||
| 2732 | { | ||
| 2733 | Lisp_Object shape_var = *mouse_cursor_types[i].shape_var_ptr; | ||
| 2734 | cursor_data.cursor_num[i] | ||
| 2735 | = (!NILP (shape_var) | ||
| 2736 | ? check_uinteger_max (shape_var, UINT_MAX) | ||
| 2737 | : mouse_cursor_types[i].default_shape); | ||
| 2738 | } | ||
| 2739 | |||
| 2740 | block_input (); | ||
| 2741 | |||
| 2742 | for (i = 0; i < mouse_cursor_max; i++) | ||
| 2743 | cursor_data.cursor[i] | ||
| 2744 | = android_create_font_cursor (cursor_data.cursor_num[i]); | ||
| 2745 | |||
| 2746 | if (FRAME_ANDROID_WINDOW (f)) | ||
| 2747 | { | ||
| 2748 | f->output_data.android->current_cursor | ||
| 2749 | = cursor_data.cursor[mouse_cursor_text]; | ||
| 2750 | android_define_cursor (FRAME_ANDROID_WINDOW (f), | ||
| 2751 | f->output_data.android->current_cursor); | ||
| 2752 | } | ||
| 2753 | |||
| 2754 | #define INSTALL_CURSOR(FIELD, SHORT_INDEX) \ | ||
| 2755 | eassert (x->FIELD \ | ||
| 2756 | != cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX]); \ | ||
| 2757 | if (x->FIELD != 0) \ | ||
| 2758 | android_free_cursor (x->FIELD); \ | ||
| 2759 | x->FIELD = cursor_data.cursor[mouse_cursor_ ## SHORT_INDEX]; | ||
| 2760 | |||
| 2761 | INSTALL_CURSOR (text_cursor, text); | ||
| 2762 | INSTALL_CURSOR (nontext_cursor, nontext); | ||
| 2763 | INSTALL_CURSOR (hourglass_cursor, hourglass); | ||
| 2764 | INSTALL_CURSOR (modeline_cursor, mode); | ||
| 2765 | INSTALL_CURSOR (hand_cursor, hand); | ||
| 2766 | INSTALL_CURSOR (horizontal_drag_cursor, horizontal_drag); | ||
| 2767 | INSTALL_CURSOR (vertical_drag_cursor, vertical_drag); | ||
| 2768 | INSTALL_CURSOR (left_edge_cursor, left_edge); | ||
| 2769 | INSTALL_CURSOR (top_left_corner_cursor, top_left_corner); | ||
| 2770 | INSTALL_CURSOR (top_edge_cursor, top_edge); | ||
| 2771 | INSTALL_CURSOR (top_right_corner_cursor, top_right_corner); | ||
| 2772 | INSTALL_CURSOR (right_edge_cursor, right_edge); | ||
| 2773 | INSTALL_CURSOR (bottom_right_corner_cursor, bottom_right_corner); | ||
| 2774 | INSTALL_CURSOR (bottom_edge_cursor, bottom_edge); | ||
| 2775 | INSTALL_CURSOR (bottom_left_corner_cursor, bottom_left_corner); | ||
| 2776 | |||
| 2777 | #undef INSTALL_CURSOR | ||
| 2778 | |||
| 2779 | unblock_input (); | ||
| 2780 | |||
| 2781 | update_face_from_frame_parameter (f, Qmouse_color, arg); | ||
| 2642 | } | 2782 | } |
| 2643 | 2783 | ||
| 2644 | static void | 2784 | static void |
| @@ -2845,6 +2985,81 @@ syms_of_androidfns (void) | |||
| 2845 | DEFSYM (Qtrue_color, "true-color"); | 2985 | DEFSYM (Qtrue_color, "true-color"); |
| 2846 | DEFSYM (Qalways, "always"); | 2986 | DEFSYM (Qalways, "always"); |
| 2847 | 2987 | ||
| 2988 | DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape, | ||
| 2989 | doc: /* SKIP: real text in xfns.c. */); | ||
| 2990 | Vx_pointer_shape = Qnil; | ||
| 2991 | |||
| 2992 | #if false /* This doesn't really do anything. */ | ||
| 2993 | DEFVAR_LISP ("x-nontext-pointer-shape", Vx_nontext_pointer_shape, | ||
| 2994 | doc: /* SKIP: real doc in xfns.c. */); | ||
| 2995 | #endif | ||
| 2996 | Vx_nontext_pointer_shape = Qnil; | ||
| 2997 | |||
| 2998 | DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape, | ||
| 2999 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3000 | Vx_hourglass_pointer_shape = Qnil; | ||
| 3001 | |||
| 3002 | DEFVAR_LISP ("x-sensitive-text-pointer-shape", | ||
| 3003 | Vx_sensitive_text_pointer_shape, | ||
| 3004 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3005 | Vx_sensitive_text_pointer_shape = Qnil; | ||
| 3006 | |||
| 3007 | DEFVAR_LISP ("x-window-horizontal-drag-cursor", | ||
| 3008 | Vx_window_horizontal_drag_shape, | ||
| 3009 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3010 | Vx_window_horizontal_drag_shape = Qnil; | ||
| 3011 | |||
| 3012 | DEFVAR_LISP ("x-window-vertical-drag-cursor", | ||
| 3013 | Vx_window_vertical_drag_shape, | ||
| 3014 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3015 | Vx_window_vertical_drag_shape = Qnil; | ||
| 3016 | |||
| 3017 | DEFVAR_LISP ("x-window-left-edge-cursor", | ||
| 3018 | Vx_window_left_edge_shape, | ||
| 3019 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3020 | Vx_window_left_edge_shape = Qnil; | ||
| 3021 | |||
| 3022 | DEFVAR_LISP ("x-window-top-left-corner-cursor", | ||
| 3023 | Vx_window_top_left_corner_shape, | ||
| 3024 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3025 | Vx_window_top_left_corner_shape = Qnil; | ||
| 3026 | |||
| 3027 | DEFVAR_LISP ("x-window-top-edge-cursor", | ||
| 3028 | Vx_window_top_edge_shape, | ||
| 3029 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3030 | Vx_window_top_edge_shape = Qnil; | ||
| 3031 | |||
| 3032 | DEFVAR_LISP ("x-window-top-right-corner-cursor", | ||
| 3033 | Vx_window_top_right_corner_shape, | ||
| 3034 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3035 | Vx_window_top_right_corner_shape = Qnil; | ||
| 3036 | |||
| 3037 | DEFVAR_LISP ("x-window-right-edge-cursor", | ||
| 3038 | Vx_window_right_edge_shape, | ||
| 3039 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3040 | Vx_window_right_edge_shape = Qnil; | ||
| 3041 | |||
| 3042 | DEFVAR_LISP ("x-window-bottom-right-corner-cursor", | ||
| 3043 | Vx_window_bottom_right_corner_shape, | ||
| 3044 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3045 | Vx_window_bottom_right_corner_shape = Qnil; | ||
| 3046 | |||
| 3047 | DEFVAR_LISP ("x-window-bottom-edge-cursor", | ||
| 3048 | Vx_window_bottom_edge_shape, | ||
| 3049 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3050 | Vx_window_bottom_edge_shape = Qnil; | ||
| 3051 | |||
| 3052 | #if false /* This doesn't really do anything. */ | ||
| 3053 | DEFVAR_LISP ("x-mode-pointer-shape", Vx_mode_pointer_shape, | ||
| 3054 | doc: /* SKIP: real doc in xfns.c. */); | ||
| 3055 | #endif | ||
| 3056 | Vx_mode_pointer_shape = Qnil; | ||
| 3057 | |||
| 3058 | DEFVAR_LISP ("x-window-bottom-left-corner-cursor", | ||
| 3059 | Vx_window_bottom_left_corner_shape, | ||
| 3060 | doc: /* SKIP: real text in xfns.c. */); | ||
| 3061 | Vx_window_bottom_left_corner_shape = Qnil; | ||
| 3062 | |||
| 2848 | DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel, | 3063 | DEFVAR_LISP ("x-cursor-fore-pixel", Vx_cursor_fore_pixel, |
| 2849 | doc: /* SKIP: real doc in xfns.c. */); | 3064 | doc: /* SKIP: real doc in xfns.c. */); |
| 2850 | Vx_cursor_fore_pixel = Qnil; | 3065 | Vx_cursor_fore_pixel = Qnil; |