From 5079f42446aab520e20aad30f825ccbc448ba4e3 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Wed, 11 May 2022 12:40:32 +0000 Subject: [PATCH] Add support for changing pointer types on Haiku * doc/lispref/frames.texi (Pointer Shape): Document that the pointer shape can now be changed on some window systems other than X. * lisp/term/haiku-win.el (x-pointer-X-cursor, x-pointer-arrow) (x-pointer-bottom-left-corner, x-pointer-bottom-right-corner) (x-pointer-bottom-side, x-pointer-clock, x-pointer-cross) (x-pointer-cross-reverse, x-pointer-crosshair) (x-pointer-diamond-cross, x-pointer-hand1, x-pointer-hand2) (x-pointer-left-side, x-pointer-right-side) (x-pointer-sb-down-arrow, x-pointer-sb-left-arrow) (x-pointer-sb-right-arrow, x-pointer-sb-up-arrow, x-pointer-target) (x-pointer-top-left-corner, x-pointer-top-right-corner) (x-pointer-top-side, x-pointer-watch, x-pointer-invisible): New pointer constants. * src/haiku_support.cc (BCursor_from_id): Accept int instead of enum. * src/haiku_support.h: Update prototypes. * src/haikufns.c (haiku_create_frame): Stop manually assigning cursors and set default value of the mouse color property. (haiku_free_frame_resources): Free custom cursors too. (struct user_cursor_info, INIT_USER_CURSOR): New struct. (haiku_free_custom_cursors): New function. (haiku_set_mouse_color): New param handler. (haiku_frame_parm_handlers): Add param handler. (syms_of_haikufns): New cursor shape variables from X. * src/haikuterm.h: Update prototypes. --- doc/lispref/frames.texi | 5 +- lisp/term/haiku-win.el | 31 +++++++ src/haiku_support.cc | 2 +- src/haiku_support.h | 2 +- src/haikufns.c | 173 ++++++++++++++++++++++++++++++++++------ src/haikuterm.h | 1 + 6 files changed, 184 insertions(+), 30 deletions(-) diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi index 05c6e4b719b..3bbeef005bd 100644 --- a/doc/lispref/frames.texi +++ b/doc/lispref/frames.texi @@ -3877,8 +3877,9 @@ in the buffer. The default is to use the @code{arrow} (non-text) pointer style. @end defopt - When using X, you can specify what the @code{text} pointer style -really looks like by setting the variable @code{x-pointer-shape}. + When using some window systems, you can specify what the @code{text} +pointer style really looks like by setting the variable +@code{x-pointer-shape}. @defvar x-pointer-shape This variable specifies the pointer shape to use ordinarily in the diff --git a/lisp/term/haiku-win.el b/lisp/term/haiku-win.el index 6396779d60d..7f3bba52e59 100644 --- a/lisp/term/haiku-win.el +++ b/lisp/term/haiku-win.el @@ -392,6 +392,37 @@ take effect on menu items until the menu bar is updated again." ;; the Deskbar will not, so kill ourself here. (unless cancel-shutdown (kill-emacs)))) + +;;;; Cursors. + +;; We use the same interface as X, but the cursor numbers are +;; different, and there are also less cursors. + +(defconst x-pointer-X-cursor 5) ; B_CURSOR_ID_CROSS_HAIR +(defconst x-pointer-arrow 1) ; B_CURSOR_ID_SYSTEM_DEFAULT +(defconst x-pointer-bottom-left-corner 22) ; B_CURSOR_ID_RESIZE_SOUTH_WEST +(defconst x-pointer-bottom-right-corner 21) ; B_CURSOR_ID_RESIZE_SOUTH_EAST +(defconst x-pointer-bottom-side 17) ; B_CURSOR_ID_RESIZE_SOUTH +(defconst x-pointer-clock 14) ; B_CURSOR_ID_PROGRESS +(defconst x-pointer-cross 5) ; B_CURSOR_ID_CROSS_HAIR +(defconst x-pointer-cross-reverse 5) ; B_CURSOR_ID_CROSS_HAIR +(defconst x-pointer-crosshair 5) ; B_CURSOR_ID_CROSS_HAIR +(defconst x-pointer-diamond-cross 5) ; B_CURSOR_ID_CROSS_HAIR +(defconst x-pointer-hand1 7) ; B_CURSOR_ID_GRAB +(defconst x-pointer-hand2 8) ; B_CURSOR_ID_GRABBING +(defconst x-pointer-left-side 18) ; B_CURSOR_ID_RESIZE_WEST +(defconst x-pointer-right-side 16) ; B_CURSOR_ID_RESIZE_EAST +(defconst x-pointer-sb-down-arrow 17) ; B_CURSOR_ID_RESIZE_SOUTH +(defconst x-pointer-sb-left-arrow 18) ; B_CURSOR_ID_RESIZE_WEST +(defconst x-pointer-sb-right-arrow 16) ; B_CURSOR_ID_RESIZE_EAST +(defconst x-pointer-sb-up-arrow 16) ; B_CURSOR_ID_RESIZE_NORTH +(defconst x-pointer-target 5) ; B_CURSOR_ID_CROSS_HAIR +(defconst x-pointer-top-left-corner 20) ; B_CURSOR_ID_RESIZE_NORTH_WEST +(defconst x-pointer-top-right-corner 19) ; B_CURSOR_ID_RESIZE_NORTH_EAST +(defconst x-pointer-top-side 16) ; B_CURSOR_ID_RESIZE_NORTH +(defconst x-pointer-watch 14) ; B_CURSOR_ID_PROGRESS +(defconst x-pointer-invisible 12) ; B_CURSOR_ID_NO_CURSOR + (provide 'haiku-win) (provide 'term/haiku-win) diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 6caf8049d1f..39e8daa8269 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -3392,7 +3392,7 @@ BCursor_create_modeline (void) } void * -BCursor_from_id (enum haiku_cursor cursor) +BCursor_from_id (int cursor) { return new BCursor ((enum BCursorID) cursor); } diff --git a/src/haiku_support.h b/src/haiku_support.h index 416c717546f..3ea6e838d7f 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -557,7 +557,7 @@ extern void be_get_screen_dimensions (int *, int *); /* Functions for creating and freeing cursors. */ extern void *BCursor_create_default (void); -extern void *BCursor_from_id (enum haiku_cursor); +extern void *BCursor_from_id (int); extern void *BCursor_create_modeline (void); extern void *BCursor_create_i_beam (void); extern void *BCursor_create_progress_cursor (void); diff --git a/src/haikufns.c b/src/haikufns.c index 8596317de25..0abb4188955 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -763,6 +763,8 @@ haiku_create_frame (Lisp_Object parms) "foreground", "Foreground", RES_TYPE_STRING); gui_default_parameter (f, parms, Qbackground_color, build_string ("white"), "background", "Background", RES_TYPE_STRING); + gui_default_parameter (f, parms, Qmouse_color, build_string ("black"), + "pointerColor", "Foreground", RES_TYPE_STRING); gui_default_parameter (f, parms, Qline_spacing, Qnil, "lineSpacing", "LineSpacing", RES_TYPE_NUMBER); gui_default_parameter (f, parms, Qleft_fringe, Qnil, @@ -820,33 +822,11 @@ haiku_create_frame (Lisp_Object parms) RES_TYPE_BOOLEAN); f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !NILP (tem)); - block_input (); -#define ASSIGN_CURSOR(cursor) \ - (FRAME_OUTPUT_DATA (f)->cursor = dpyinfo->cursor) - - ASSIGN_CURSOR (text_cursor); - ASSIGN_CURSOR (nontext_cursor); - ASSIGN_CURSOR (modeline_cursor); - ASSIGN_CURSOR (hand_cursor); - ASSIGN_CURSOR (hourglass_cursor); - ASSIGN_CURSOR (horizontal_drag_cursor); - ASSIGN_CURSOR (vertical_drag_cursor); - ASSIGN_CURSOR (left_edge_cursor); - ASSIGN_CURSOR (top_left_corner_cursor); - ASSIGN_CURSOR (top_edge_cursor); - ASSIGN_CURSOR (top_right_corner_cursor); - ASSIGN_CURSOR (right_edge_cursor); - ASSIGN_CURSOR (bottom_right_corner_cursor); - ASSIGN_CURSOR (bottom_edge_cursor); - ASSIGN_CURSOR (bottom_left_corner_cursor); - ASSIGN_CURSOR (no_cursor); - - FRAME_OUTPUT_DATA (f)->current_cursor = dpyinfo->text_cursor; -#undef ASSIGN_CURSOR - f->terminal->reference_count++; - FRAME_OUTPUT_DATA (f)->window = BWindow_new (&FRAME_OUTPUT_DATA (f)->view); + block_input (); + FRAME_OUTPUT_DATA (f)->window + = BWindow_new (&FRAME_OUTPUT_DATA (f)->view); unblock_input (); if (!FRAME_OUTPUT_DATA (f)->window) @@ -1567,6 +1547,7 @@ haiku_free_frame_resources (struct frame *f) dpyinfo = FRAME_DISPLAY_INFO (f); free_frame_faces (f); + haiku_free_custom_cursors (f); /* Free scroll bars */ for (bar = FRAME_SCROLL_BARS (f); !NILP (bar); bar = b->next) @@ -1792,6 +1773,133 @@ haiku_set_sticky (struct frame *f, Lisp_Object new_value, unblock_input (); } +struct user_cursor_info +{ + /* A pointer to the Lisp_Object describing the cursor. */ + Lisp_Object *lisp_cursor; + + /* The offset of the cursor in the `struct haiku_output' of each + frame. */ + ptrdiff_t output_offset; + + /* The offset of the default value of the cursor in the display + info structure. */ + ptrdiff_t default_offset; +}; + +#define INIT_USER_CURSOR(lisp, cursor) \ + { (lisp), offsetof (struct haiku_output, cursor), \ + offsetof (struct haiku_display_info, cursor) } + +struct user_cursor_info custom_cursors[] = + { + INIT_USER_CURSOR (&Vx_pointer_shape, text_cursor), + INIT_USER_CURSOR (NULL, nontext_cursor), + INIT_USER_CURSOR (NULL, modeline_cursor), + INIT_USER_CURSOR (&Vx_sensitive_text_pointer_shape, hand_cursor), + INIT_USER_CURSOR (&Vx_hourglass_pointer_shape, hourglass_cursor), + INIT_USER_CURSOR (NULL, horizontal_drag_cursor), + INIT_USER_CURSOR (NULL, vertical_drag_cursor), + INIT_USER_CURSOR (NULL, left_edge_cursor), + INIT_USER_CURSOR (NULL, top_left_corner_cursor), + INIT_USER_CURSOR (NULL, top_edge_cursor), + INIT_USER_CURSOR (NULL, top_right_corner_cursor), + INIT_USER_CURSOR (NULL, right_edge_cursor), + INIT_USER_CURSOR (NULL, bottom_right_corner_cursor), + INIT_USER_CURSOR (NULL, bottom_edge_cursor), + INIT_USER_CURSOR (NULL, bottom_left_corner_cursor), + INIT_USER_CURSOR (NULL, no_cursor), + }; + +/* Free all cursors not default in F. */ +void +haiku_free_custom_cursors (struct frame *f) +{ + struct user_cursor_info *cursor; + struct haiku_output *output; + struct haiku_display_info *dpyinfo; + Emacs_Cursor *frame_cursor; + Emacs_Cursor *display_cursor; + int i; + + output = FRAME_OUTPUT_DATA (f); + dpyinfo = FRAME_DISPLAY_INFO (f); + + for (i = 0; i < ARRAYELTS (custom_cursors); ++i) + { + cursor = &custom_cursors[i]; + frame_cursor = (Emacs_Cursor *) ((char *) output + + cursor->output_offset); + display_cursor = (Emacs_Cursor *) ((char *) dpyinfo + + cursor->default_offset); + + if (*frame_cursor != *display_cursor + && *frame_cursor) + { + BCursor_delete (*frame_cursor); + + if (output->current_cursor == *frame_cursor) + output->current_cursor = *display_cursor; + } + + *frame_cursor = *display_cursor; + } +} + +static void +haiku_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) +{ + struct haiku_output *output; + Emacs_Cursor *frame_cursor, old; + int i, n; + + output = FRAME_OUTPUT_DATA (f); + + /* This will also reset all the cursors back to their default + values. */ + haiku_free_custom_cursors (f); + + for (i = 0; i < ARRAYELTS (custom_cursors); ++i) + { + frame_cursor = (Emacs_Cursor *) ((char *) output + + custom_cursors[i].output_offset); + old = *frame_cursor; + + if (custom_cursors[i].lisp_cursor + && FIXNUMP (*custom_cursors[i].lisp_cursor)) + { + if (!RANGED_FIXNUMP (0, *custom_cursors[i].lisp_cursor, + 28)) /* 28 is the largest Haiku cursor ID. */ + signal_error ("Invalid cursor", + *custom_cursors[i].lisp_cursor); + + n = XFIXNUM (*custom_cursors[i].lisp_cursor); + + /* Create and set the custom cursor. */ + block_input (); + *frame_cursor = BCursor_from_id (n); + unblock_input (); + + /* This function can be called before the frame's window is + created. */ + if (FRAME_HAIKU_WINDOW (f)) + { + if (output->current_cursor == old) + { + output->current_cursor = *frame_cursor; + + block_input (); + BView_set_view_cursor (FRAME_HAIKU_VIEW (f), + *frame_cursor); + unblock_input (); + } + } + } + } + + update_face_from_frame_parameter (f, Qmouse_color, arg); +} + DEFUN ("haiku-set-mouse-absolute-pixel-position", @@ -2701,7 +2809,7 @@ frame_parm_handler haiku_frame_parm_handlers[] = gui_set_right_divider_width, gui_set_bottom_divider_width, haiku_set_menu_bar_lines, - NULL, /* set mouse color */ + haiku_set_mouse_color, haiku_explicitly_set_name, gui_set_scroll_bar_width, gui_set_scroll_bar_height, @@ -2805,6 +2913,19 @@ syms_of_haikufns (void) doc: /* SKIP: real doc in xfns.c. */); Vx_cursor_fore_pixel = Qnil; + DEFVAR_LISP ("x-pointer-shape", Vx_pointer_shape, + doc: /* SKIP: real doc in xfns.c. */); + Vx_pointer_shape = Qnil; + + DEFVAR_LISP ("x-hourglass-pointer-shape", Vx_hourglass_pointer_shape, + doc: /* SKIP: real doc in xfns.c. */); + Vx_hourglass_pointer_shape = Qnil; + + DEFVAR_LISP ("x-sensitive-text-pointer-shape", + Vx_sensitive_text_pointer_shape, + doc: /* SKIP: real doc in xfns.c. */); + Vx_sensitive_text_pointer_shape = Qnil; + DEFVAR_LISP ("haiku-allowed-ui-colors", Vhaiku_allowed_ui_colors, doc: /* Vector of UI colors that Emacs can look up from the system. If this is set up incorrectly, Emacs can crash when encoutering an diff --git a/src/haikuterm.h b/src/haikuterm.h index cc032d03892..4b124a6ba30 100644 --- a/src/haikuterm.h +++ b/src/haikuterm.h @@ -304,6 +304,7 @@ extern void haiku_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object); extern void haiku_set_internal_border_width (struct frame *, Lisp_Object, Lisp_Object); extern void haiku_change_tab_bar_height (struct frame *, int); extern void haiku_change_tool_bar_height (struct frame *, int); +extern void haiku_free_custom_cursors (struct frame *); extern void haiku_query_color (uint32_t, Emacs_Color *); -- 2.39.2