From 119f613cf5a39db1712c87ebcc21d7600ef79e5f Mon Sep 17 00:00:00 2001 From: Po Lu Date: Fri, 13 May 2022 03:14:26 +0000 Subject: [PATCH] Allow actually setting cursor colors on Haiku * src/haiku_support.cc (be_create_pixmap_cursor): New function. * src/haiku_support.h: Update prototypes. * src/haikufns.c (haiku_create_frame): Change default cursor color to "font-color". (haiku_create_tip_frame): Likewise. (struct user_cursor_bitmap_info): New struct. (cursor_bitmaps): New list of bitmaps corresponding to cursors. (haiku_create_colored_cursor): New function. (haiku_free_custom_cursors): Set current cursor to the default cursor before freeing the original value. (haiku_set_mouse_color): Actually recolor cursors based on built-in bitmaps. * src/haikuterm.c (haiku_defined_color): Clean up coding style. --- src/haiku_support.cc | 18 +++++ src/haiku_support.h | 1 + src/haikufns.c | 152 ++++++++++++++++++++++++++++++++++++------- src/haikuterm.c | 7 +- 4 files changed, 149 insertions(+), 29 deletions(-) diff --git a/src/haiku_support.cc b/src/haiku_support.cc index 39e8daa8269..c0bd3c1b0e2 100644 --- a/src/haiku_support.cc +++ b/src/haiku_support.cc @@ -5122,3 +5122,21 @@ be_roster_launch (const char *type, const char *file, char **cargs, ? INT_MAX : nargs), cargs, team_id); } + +void * +be_create_pixmap_cursor (void *bitmap, int x, int y) +{ + BBitmap *bm; + BCursor *cursor; + + bm = (BBitmap *) bitmap; + cursor = new BCursor (bm, BPoint (x, y)); + + if (cursor->InitCheck () != B_OK) + { + delete cursor; + return NULL; + } + + return cursor; +} diff --git a/src/haiku_support.h b/src/haiku_support.h index 3ea6e838d7f..b9cbd6ca4c9 100644 --- a/src/haiku_support.h +++ b/src/haiku_support.h @@ -563,6 +563,7 @@ extern void *BCursor_create_i_beam (void); extern void *BCursor_create_progress_cursor (void); extern void *BCursor_create_grab (void); extern void BCursor_delete (void *); +extern void *be_create_pixmap_cursor (void *, int, int); extern void *BScrollBar_make_for_view (void *, int, int, int, int, int, void *); extern void BScrollBar_delete (void *); diff --git a/src/haikufns.c b/src/haikufns.c index 13432785bd3..9bf672f1d83 100644 --- a/src/haikufns.c +++ b/src/haikufns.c @@ -34,6 +34,9 @@ along with GNU Emacs. If not, see . */ #include "haiku_support.h" #include "termhooks.h" +#include "bitmaps/leftptr.xbm" +#include "bitmaps/leftpmsk.xbm" + #include #include @@ -763,7 +766,7 @@ 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"), + gui_default_parameter (f, parms, Qmouse_color, build_string ("font-color"), "pointerColor", "Foreground", RES_TYPE_STRING); gui_default_parameter (f, parms, Qline_spacing, Qnil, "lineSpacing", "LineSpacing", RES_TYPE_NUMBER); @@ -1056,7 +1059,10 @@ haiku_create_tip_frame (Lisp_Object parms) 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"), + + /* FIXME: is there a better method to tell Emacs to not recolor the + cursors other than setting the color to a special value? */ + gui_default_parameter (f, parms, Qmouse_color, build_string ("font-color"), "pointerColor", "Foreground", RES_TYPE_STRING); gui_default_parameter (f, parms, Qcursor_color, build_string ("black"), "cursorColor", "Foreground", RES_TYPE_STRING); @@ -1787,6 +1793,23 @@ struct user_cursor_info ptrdiff_t default_offset; }; +struct user_cursor_bitmap_info +{ + /* The name of a bitmap to use instead of the font cursor if a + cursor color was set. */ + const void *bits; + + /* The mask for that bitmap. */ + const void *mask; + + /* The dimensions of the cursor bitmap. */ + int width, height; + + /* The position inside the cursor bitmap corresponding to the + position of the mouse pointer. */ + int x, y; +}; + #define INIT_USER_CURSOR(lisp, cursor) \ { (lisp), offsetof (struct haiku_output, cursor), \ offsetof (struct haiku_display_info, cursor) } @@ -1811,7 +1834,70 @@ struct user_cursor_info custom_cursors[] = INIT_USER_CURSOR (NULL, no_cursor), }; -/* Free all cursors not default in F. */ +struct user_cursor_bitmap_info cursor_bitmaps[] = + { + { NULL, NULL, 0, 0, 0, 0 }, /* text_cursor */ + { left_ptr_bits, left_ptrmsk_bits, 16, 16, 4, 1 }, /* nontext_cursor */ + { left_ptr_bits, left_ptrmsk_bits, 16, 16, 4, 1 }, /* modeline_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* hand_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* hourglass_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* horizontal_drag_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* vertical_drag_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* left_edge_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* top_left_corner_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* top_edge_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* top_right_corner_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* right_edge_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* bottom_right_corner_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* bottom_edge_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* bottom_left_corner_cursor */ + { NULL, NULL, 0, 0, 0, 0 }, /* no_cursor */ + }; + +static void * +haiku_create_colored_cursor (struct user_cursor_bitmap_info *info, + uint32_t foreground, uint32_t background) +{ + const char *bits, *mask; + void *bitmap, *cursor; + int width, height, bytes_per_line, x, y; + + bits = info->bits; + mask = info->mask; + width = info->width; + height = info->height; + bytes_per_line = (width + 7) / 8; + + bitmap = BBitmap_new (width, height, false); + + if (!bitmap) + memory_full (SIZE_MAX); + + for (y = 0; y < height; ++y) + { + for (x = 0; x < width; ++x) + { + if (mask[x / 8] >> (x % 8) & 1) + haiku_put_pixel (bitmap, x, y, + (bits[x / 8] >> (x % 8) & 1 + ? (foreground | 255u << 24) + : (background | 255u << 24))); + else + haiku_put_pixel (bitmap, x, y, 0); + } + + mask += bytes_per_line; + bits += bytes_per_line; + } + + cursor = be_create_pixmap_cursor (bitmap, info->x, info->y); + BBitmap_free (bitmap); + + return cursor; +} + +/* Free all cursors on F that were allocated specifically for the + frame. */ void haiku_free_custom_cursors (struct frame *f) { @@ -1833,13 +1919,12 @@ haiku_free_custom_cursors (struct frame *f) display_cursor = (Emacs_Cursor *) ((char *) dpyinfo + cursor->default_offset); - if (*frame_cursor != *display_cursor - && *frame_cursor) + if (*frame_cursor != *display_cursor && *frame_cursor) { - BCursor_delete (*frame_cursor); - if (output->current_cursor == *frame_cursor) output->current_cursor = *display_cursor; + + BCursor_delete (*frame_cursor); } *frame_cursor = *display_cursor; @@ -1850,8 +1935,21 @@ 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; + Emacs_Cursor *frame_cursor, old, *recolored; + int i, n, rc; + bool color_specified_p; + Emacs_Color color; + + CHECK_STRING (arg); + color_specified_p = true; + + if (!strcmp (SSDATA (arg), "font-color")) + color_specified_p = false; + else + rc = haiku_get_color (SSDATA (arg), &color); + + if (color_specified_p && rc) + signal_error ("Invalid color", arg); output = FRAME_OUTPUT_DATA (f); @@ -1876,24 +1974,30 @@ haiku_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) n = XFIXNUM (*custom_cursors[i].lisp_cursor); /* Create and set the custom cursor. */ - block_input (); *frame_cursor = BCursor_from_id (n); - unblock_input (); + } + else if (color_specified_p && cursor_bitmaps[i].bits) + { + recolored + = haiku_create_colored_cursor (&cursor_bitmaps[i], color.pixel, + FRAME_BACKGROUND_PIXEL (f)); - /* 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; + if (recolored) + *frame_cursor = recolored; + } + } - block_input (); - BView_set_view_cursor (FRAME_HAIKU_VIEW (f), - *frame_cursor); - unblock_input (); - } - } + /* This function can be called before the frame's window is + created. */ + if (FRAME_HAIKU_WINDOW (f)) + { + if (output->current_cursor == old + && old != *frame_cursor) + { + output->current_cursor = *frame_cursor; + + BView_set_view_cursor (FRAME_HAIKU_VIEW (f), + *frame_cursor); } } diff --git a/src/haikuterm.c b/src/haikuterm.c index 49121629b3b..3ef3f584957 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c @@ -577,11 +577,8 @@ haiku_query_frame_background_color (struct frame *f, Emacs_Color *bgcolor) } static bool -haiku_defined_color (struct frame *f, - const char *name, - Emacs_Color *color, - bool alloc, - bool make_index) +haiku_defined_color (struct frame *f, const char *name, + Emacs_Color *color, bool alloc, bool make_index) { return !haiku_get_color (name, color); } -- 2.39.2