diff options
| author | Po Lu | 2022-05-12 04:11:12 +0000 |
|---|---|---|
| committer | Po Lu | 2022-05-12 04:11:32 +0000 |
| commit | ec1a14ab331c0abc57bc34972a8a6f69c6ffa17a (patch) | |
| tree | 32af759dd3116a83ab3e133ed2c63d5d9d2ebcc4 /src | |
| parent | e2bb618ea7599548d8f6e0f9e23db5a15a90d8ac (diff) | |
| download | emacs-ec1a14ab331c0abc57bc34972a8a6f69c6ffa17a.tar.gz emacs-ec1a14ab331c0abc57bc34972a8a6f69c6ffa17a.zip | |
Make cursor display on Haiku consistent with X
* src/haikuterm.c (haiku_draw_image_glyph_string): Merge cursor
foregrounds correctly.
(haiku_draw_hollow_cursor, haiku_draw_bar_cursor): New
functions. Port code from X.
(haiku_draw_window_cursor): Port code from X so bar cursors on
top of images are treated right.
Diffstat (limited to 'src')
| -rw-r--r-- | src/haikuterm.c | 306 |
1 files changed, 196 insertions, 110 deletions
diff --git a/src/haikuterm.c b/src/haikuterm.c index 58855d07fb8..b74584e2dca 100644 --- a/src/haikuterm.c +++ b/src/haikuterm.c | |||
| @@ -1631,12 +1631,13 @@ static void | |||
| 1631 | haiku_draw_image_glyph_string (struct glyph_string *s) | 1631 | haiku_draw_image_glyph_string (struct glyph_string *s) |
| 1632 | { | 1632 | { |
| 1633 | struct face *face = s->face; | 1633 | struct face *face = s->face; |
| 1634 | 1634 | void *view, *bitmap, *mask; | |
| 1635 | int box_line_hwidth = max (face->box_vertical_line_width, 0); | 1635 | int box_line_hwidth = max (face->box_vertical_line_width, 0); |
| 1636 | int box_line_vwidth = max (face->box_horizontal_line_width, 0); | 1636 | int box_line_vwidth = max (face->box_horizontal_line_width, 0); |
| 1637 | 1637 | int x, y, height, width, relief; | |
| 1638 | int x, y; | 1638 | struct haiku_rect nr; |
| 1639 | int height, width; | 1639 | Emacs_Rectangle cr, ir, r; |
| 1640 | unsigned long background; | ||
| 1640 | 1641 | ||
| 1641 | height = s->height; | 1642 | height = s->height; |
| 1642 | if (s->slice.y == 0) | 1643 | if (s->slice.y == 0) |
| @@ -1657,20 +1658,22 @@ haiku_draw_image_glyph_string (struct glyph_string *s) | |||
| 1657 | if (s->slice.y == 0) | 1658 | if (s->slice.y == 0) |
| 1658 | y += box_line_vwidth; | 1659 | y += box_line_vwidth; |
| 1659 | 1660 | ||
| 1660 | void *view = FRAME_HAIKU_VIEW (s->f); | 1661 | view = FRAME_HAIKU_VIEW (s->f); |
| 1661 | void *bitmap = s->img->pixmap; | 1662 | bitmap = s->img->pixmap; |
| 1662 | 1663 | ||
| 1663 | /* TODO: implement stipples for images with masks. */ | 1664 | /* TODO: implement stipples for images with masks. */ |
| 1664 | s->stippled_p = face->stipple != 0; | 1665 | s->stippled_p = face->stipple != 0; |
| 1665 | 1666 | ||
| 1666 | BView_SetHighColor (view, face->background); | 1667 | if (s->hl == DRAW_CURSOR) |
| 1668 | haiku_merge_cursor_foreground (s, NULL, &background); | ||
| 1669 | else | ||
| 1670 | background = face->background; | ||
| 1671 | |||
| 1672 | BView_SetHighColor (view, background); | ||
| 1667 | BView_FillRectangle (view, x, y, width, height); | 1673 | BView_FillRectangle (view, x, y, width, height); |
| 1668 | 1674 | ||
| 1669 | if (bitmap) | 1675 | if (bitmap) |
| 1670 | { | 1676 | { |
| 1671 | struct haiku_rect nr; | ||
| 1672 | Emacs_Rectangle cr, ir, r; | ||
| 1673 | |||
| 1674 | get_glyph_string_clip_rect (s, &nr); | 1677 | get_glyph_string_clip_rect (s, &nr); |
| 1675 | CONVERT_TO_EMACS_RECT (cr, nr); | 1678 | CONVERT_TO_EMACS_RECT (cr, nr); |
| 1676 | x = s->x; | 1679 | x = s->x; |
| @@ -1692,7 +1695,7 @@ haiku_draw_image_glyph_string (struct glyph_string *s) | |||
| 1692 | ir.height = s->slice.height; | 1695 | ir.height = s->slice.height; |
| 1693 | r = ir; | 1696 | r = ir; |
| 1694 | 1697 | ||
| 1695 | void *mask = s->img->mask; | 1698 | mask = s->img->mask; |
| 1696 | 1699 | ||
| 1697 | if (gui_intersect_rectangles (&cr, &ir, &r)) | 1700 | if (gui_intersect_rectangles (&cr, &ir, &r)) |
| 1698 | { | 1701 | { |
| @@ -1726,11 +1729,25 @@ haiku_draw_image_glyph_string (struct glyph_string *s) | |||
| 1726 | BBitmap_free (bitmap); | 1729 | BBitmap_free (bitmap); |
| 1727 | } | 1730 | } |
| 1728 | 1731 | ||
| 1729 | if (s->hl == DRAW_CURSOR) | 1732 | if (!s->img->mask) |
| 1730 | { | 1733 | { |
| 1731 | BView_SetPenSize (view, 1); | 1734 | /* When the image has a mask, we can expect that at |
| 1732 | BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel); | 1735 | least part of a mouse highlight or a block cursor will |
| 1733 | BView_StrokeRectangle (view, r.x, r.y, r.width, r.height); | 1736 | be visible. If the image doesn't have a mask, make |
| 1737 | a block cursor visible by drawing a rectangle around | ||
| 1738 | the image. I believe it's looking better if we do | ||
| 1739 | nothing here for mouse-face. */ | ||
| 1740 | |||
| 1741 | if (s->hl == DRAW_CURSOR) | ||
| 1742 | { | ||
| 1743 | relief = eabs (s->img->relief); | ||
| 1744 | |||
| 1745 | BView_SetPenSize (view, 1); | ||
| 1746 | BView_SetHighColor (view, FRAME_CURSOR_COLOR (s->f).pixel); | ||
| 1747 | BView_StrokeRectangle (view, x - relief, y - relief, | ||
| 1748 | s->slice.width + relief * 2, | ||
| 1749 | s->slice.height + relief * 2); | ||
| 1750 | } | ||
| 1734 | } | 1751 | } |
| 1735 | } | 1752 | } |
| 1736 | 1753 | ||
| @@ -2000,132 +2017,201 @@ haiku_set_window_size (struct frame *f, bool change_gravity, | |||
| 2000 | } | 2017 | } |
| 2001 | 2018 | ||
| 2002 | static void | 2019 | static void |
| 2003 | haiku_draw_window_cursor (struct window *w, | 2020 | haiku_draw_hollow_cursor (struct window *w, struct glyph_row *row) |
| 2004 | struct glyph_row *glyph_row, | ||
| 2005 | int x, int y, | ||
| 2006 | enum text_cursor_kinds cursor_type, | ||
| 2007 | int cursor_width, bool on_p, bool active_p) | ||
| 2008 | { | 2021 | { |
| 2009 | struct frame *f = XFRAME (WINDOW_FRAME (w)); | 2022 | struct frame *f; |
| 2010 | struct face *face; | 2023 | int x, y, wd, h; |
| 2011 | struct glyph *phys_cursor_glyph; | ||
| 2012 | struct glyph *cursor_glyph; | 2024 | struct glyph *cursor_glyph; |
| 2025 | uint32_t foreground; | ||
| 2026 | void *view; | ||
| 2013 | 2027 | ||
| 2014 | void *view = FRAME_HAIKU_VIEW (f); | 2028 | f = XFRAME (WINDOW_FRAME (w)); |
| 2015 | 2029 | view = FRAME_HAIKU_VIEW (f); | |
| 2016 | int fx, fy, h, cursor_height; | ||
| 2017 | 2030 | ||
| 2018 | if (!on_p) | 2031 | /* Get the glyph the cursor is on. If we can't tell because |
| 2032 | the current matrix is invalid or such, give up. */ | ||
| 2033 | cursor_glyph = get_phys_cursor_glyph (w); | ||
| 2034 | if (cursor_glyph == NULL) | ||
| 2019 | return; | 2035 | return; |
| 2020 | 2036 | ||
| 2021 | if (cursor_type == NO_CURSOR) | 2037 | /* Compute frame-relative coordinates for phys cursor. */ |
| 2022 | { | 2038 | get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h); |
| 2023 | w->phys_cursor_width = 0; | 2039 | wd = w->phys_cursor_width; |
| 2024 | return; | ||
| 2025 | } | ||
| 2026 | 2040 | ||
| 2027 | w->phys_cursor_on_p = true; | 2041 | /* The foreground of cursor_gc is typically the same as the normal |
| 2028 | w->phys_cursor_type = cursor_type; | 2042 | background color, which can cause the cursor box to be invisible. */ |
| 2043 | foreground = FRAME_CURSOR_COLOR (f).pixel; | ||
| 2029 | 2044 | ||
| 2030 | phys_cursor_glyph = get_phys_cursor_glyph (w); | 2045 | /* When on R2L character, show cursor at the right edge of the |
| 2046 | glyph, unless the cursor box is as wide as the glyph or wider | ||
| 2047 | (the latter happens when x-stretch-cursor is non-nil). */ | ||
| 2048 | if ((cursor_glyph->resolved_level & 1) != 0 | ||
| 2049 | && cursor_glyph->pixel_width > wd) | ||
| 2050 | x += cursor_glyph->pixel_width - wd; | ||
| 2031 | 2051 | ||
| 2032 | if (!phys_cursor_glyph) | 2052 | /* Set clipping, draw the rectangle, and reset clipping again. |
| 2033 | { | 2053 | This also marks the region as invalidated. */ |
| 2034 | if (glyph_row->exact_window_width_line_p | ||
| 2035 | && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]) | ||
| 2036 | { | ||
| 2037 | glyph_row->cursor_in_fringe_p = 1; | ||
| 2038 | draw_fringe_bitmap (w, glyph_row, 0); | ||
| 2039 | } | ||
| 2040 | return; | ||
| 2041 | } | ||
| 2042 | 2054 | ||
| 2043 | get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h); | 2055 | BView_draw_lock (view, true, x, y, wd, h); |
| 2056 | BView_StartClip (view); | ||
| 2057 | haiku_clip_to_row (w, row, TEXT_AREA); | ||
| 2044 | 2058 | ||
| 2045 | if (cursor_type == BAR_CURSOR) | 2059 | /* Now set the foreground color and pen size. */ |
| 2060 | BView_SetHighColor (view, foreground); | ||
| 2061 | BView_SetPenSize (view, 1); | ||
| 2062 | |||
| 2063 | /* Actually draw the rectangle. */ | ||
| 2064 | BView_StrokeRectangle (view, x, y, wd, h); | ||
| 2065 | |||
| 2066 | /* Reset clipping. */ | ||
| 2067 | BView_EndClip (view); | ||
| 2068 | BView_draw_unlock (view); | ||
| 2069 | } | ||
| 2070 | |||
| 2071 | static void | ||
| 2072 | haiku_draw_bar_cursor (struct window *w, struct glyph_row *row, | ||
| 2073 | int width, enum text_cursor_kinds kind) | ||
| 2074 | { | ||
| 2075 | struct frame *f; | ||
| 2076 | struct glyph *cursor_glyph; | ||
| 2077 | struct glyph_row *r; | ||
| 2078 | struct face *face; | ||
| 2079 | uint32_t foreground; | ||
| 2080 | void *view; | ||
| 2081 | int x, y, dummy_x, dummy_y, dummy_h; | ||
| 2082 | |||
| 2083 | f = XFRAME (w->frame); | ||
| 2084 | |||
| 2085 | /* If cursor is out of bounds, don't draw garbage. This can happen | ||
| 2086 | in mini-buffer windows when switching between echo area glyphs | ||
| 2087 | and mini-buffer. */ | ||
| 2088 | cursor_glyph = get_phys_cursor_glyph (w); | ||
| 2089 | if (cursor_glyph == NULL) | ||
| 2090 | return; | ||
| 2091 | |||
| 2092 | /* If on an image, draw like a normal cursor. That's usually better | ||
| 2093 | visible than drawing a bar, esp. if the image is large so that | ||
| 2094 | the bar might not be in the window. */ | ||
| 2095 | if (cursor_glyph->type == IMAGE_GLYPH) | ||
| 2046 | { | 2096 | { |
| 2047 | if (cursor_width < 1) | 2097 | r = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos); |
| 2048 | cursor_width = max (FRAME_CURSOR_WIDTH (f), 1); | 2098 | draw_phys_cursor_glyph (w, r, DRAW_CURSOR); |
| 2049 | if (cursor_width < w->phys_cursor_width) | ||
| 2050 | w->phys_cursor_width = cursor_width; | ||
| 2051 | } | 2099 | } |
| 2052 | else if (cursor_type == HBAR_CURSOR) | 2100 | else |
| 2053 | { | 2101 | { |
| 2054 | cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width; | 2102 | view = FRAME_HAIKU_VIEW (f); |
| 2055 | if (cursor_height > glyph_row->height) | 2103 | face = FACE_FROM_ID (f, cursor_glyph->face_id); |
| 2056 | cursor_height = glyph_row->height; | ||
| 2057 | if (h > cursor_height) | ||
| 2058 | fy += h - cursor_height; | ||
| 2059 | h = cursor_height; | ||
| 2060 | } | ||
| 2061 | 2104 | ||
| 2062 | BView_draw_lock (view, false, 0, 0, 0, 0); | 2105 | /* If the glyph's background equals the color we normally draw |
| 2063 | BView_StartClip (view); | 2106 | the bars cursor in, the bar cursor in its normal color is |
| 2107 | invisible. Use the glyph's foreground color instead in this | ||
| 2108 | case, on the assumption that the glyph's colors are chosen so | ||
| 2109 | that the glyph is legible. */ | ||
| 2110 | if (face->background == FRAME_CURSOR_COLOR (f).pixel) | ||
| 2111 | foreground = face->foreground; | ||
| 2112 | else | ||
| 2113 | foreground = FRAME_CURSOR_COLOR (f).pixel; | ||
| 2064 | 2114 | ||
| 2065 | if (cursor_type == BAR_CURSOR) | 2115 | BView_draw_lock (view, false, 0, 0, 0, 0); |
| 2066 | { | 2116 | BView_StartClip (view); |
| 2067 | cursor_glyph = get_phys_cursor_glyph (w); | 2117 | BView_SetHighColor (view, foreground); |
| 2068 | face = FACE_FROM_ID (f, cursor_glyph->face_id); | 2118 | haiku_clip_to_row (w, row, TEXT_AREA); |
| 2069 | } | ||
| 2070 | 2119 | ||
| 2071 | /* If the glyph's background equals the color we normally draw the | 2120 | if (kind == BAR_CURSOR) |
| 2072 | bar cursor in, our cursor in its normal color is invisible. Use | 2121 | { |
| 2073 | the glyph's foreground color instead in this case, on the | 2122 | x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); |
| 2074 | assumption that the glyph's colors are chosen so that the glyph | 2123 | y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y); |
| 2075 | is legible. */ | ||
| 2076 | 2124 | ||
| 2077 | /* xterm.c only does this for bar cursors, and nobody has | 2125 | if (width < 0) |
| 2078 | complained, so it would be best to do that here as well. */ | 2126 | width = FRAME_CURSOR_WIDTH (f); |
| 2079 | if (cursor_type == BAR_CURSOR | 2127 | width = min (cursor_glyph->pixel_width, width); |
| 2080 | && face->background == FRAME_CURSOR_COLOR (f).pixel) | ||
| 2081 | BView_SetHighColor (view, face->foreground); | ||
| 2082 | else | ||
| 2083 | BView_SetHighColor (view, FRAME_CURSOR_COLOR (f).pixel); | ||
| 2084 | haiku_clip_to_row (w, glyph_row, TEXT_AREA); | ||
| 2085 | 2128 | ||
| 2086 | switch (cursor_type) | 2129 | w->phys_cursor_width = width; |
| 2087 | { | ||
| 2088 | default: | ||
| 2089 | case DEFAULT_CURSOR: | ||
| 2090 | case NO_CURSOR: | ||
| 2091 | break; | ||
| 2092 | 2130 | ||
| 2093 | case HBAR_CURSOR: | 2131 | /* If the character under cursor is R2L, draw the bar cursor |
| 2094 | BView_FillRectangle (view, fx, fy, w->phys_cursor_width, h); | 2132 | on the right of its glyph, rather than on the left. */ |
| 2095 | BView_invalidate_region (view, fx, fy, w->phys_cursor_width, h); | 2133 | if ((cursor_glyph->resolved_level & 1) != 0) |
| 2096 | break; | 2134 | x += cursor_glyph->pixel_width - width; |
| 2097 | 2135 | ||
| 2098 | case BAR_CURSOR: | 2136 | BView_FillRectangle (view, x, y, width, row->height); |
| 2099 | if (cursor_glyph->resolved_level & 1) | 2137 | BView_invalidate_region (view, x, y, width, row->height); |
| 2138 | } | ||
| 2139 | else /* HBAR_CURSOR */ | ||
| 2100 | { | 2140 | { |
| 2101 | BView_FillRectangle (view, fx + cursor_glyph->pixel_width - w->phys_cursor_width, | 2141 | x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); |
| 2102 | fy, w->phys_cursor_width, h); | 2142 | y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + |
| 2103 | BView_invalidate_region (view, fx + cursor_glyph->pixel_width - w->phys_cursor_width, | 2143 | row->height - width); |
| 2104 | fy, w->phys_cursor_width, h); | 2144 | |
| 2145 | if (width < 0) | ||
| 2146 | width = row->height; | ||
| 2147 | |||
| 2148 | width = min (row->height, width); | ||
| 2149 | |||
| 2150 | get_phys_cursor_geometry (w, row, cursor_glyph, &dummy_x, | ||
| 2151 | &dummy_y, &dummy_h); | ||
| 2152 | |||
| 2153 | if ((cursor_glyph->resolved_level & 1) != 0 | ||
| 2154 | && cursor_glyph->pixel_width > w->phys_cursor_width - 1) | ||
| 2155 | x += cursor_glyph->pixel_width - w->phys_cursor_width + 1; | ||
| 2156 | |||
| 2157 | BView_FillRectangle (view, x, y, w->phys_cursor_width - 1, | ||
| 2158 | width); | ||
| 2159 | BView_invalidate_region (view, x, y, w->phys_cursor_width - 1, | ||
| 2160 | width); | ||
| 2105 | } | 2161 | } |
| 2106 | else | ||
| 2107 | BView_FillRectangle (view, fx, fy, w->phys_cursor_width, h); | ||
| 2108 | 2162 | ||
| 2109 | BView_invalidate_region (view, fx, fy, w->phys_cursor_width, h); | 2163 | BView_EndClip (view); |
| 2110 | break; | 2164 | BView_draw_unlock (view); |
| 2165 | } | ||
| 2166 | } | ||
| 2111 | 2167 | ||
| 2112 | case HOLLOW_BOX_CURSOR: | 2168 | static void |
| 2113 | if (phys_cursor_glyph->type != IMAGE_GLYPH) | 2169 | haiku_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, |
| 2170 | int x, int y, enum text_cursor_kinds cursor_type, | ||
| 2171 | int cursor_width, bool on_p, bool active_p) | ||
| 2172 | { | ||
| 2173 | if (on_p) | ||
| 2174 | { | ||
| 2175 | w->phys_cursor_type = cursor_type; | ||
| 2176 | w->phys_cursor_on_p = true; | ||
| 2177 | |||
| 2178 | if (glyph_row->exact_window_width_line_p | ||
| 2179 | && (glyph_row->reversed_p | ||
| 2180 | ? (w->phys_cursor.hpos < 0) | ||
| 2181 | : (w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]))) | ||
| 2114 | { | 2182 | { |
| 2115 | BView_SetPenSize (view, 1); | 2183 | glyph_row->cursor_in_fringe_p = true; |
| 2116 | BView_StrokeRectangle (view, fx, fy, w->phys_cursor_width, h); | 2184 | draw_fringe_bitmap (w, glyph_row, glyph_row->reversed_p); |
| 2117 | } | 2185 | } |
| 2118 | else | 2186 | else |
| 2119 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); | 2187 | { |
| 2188 | switch (cursor_type) | ||
| 2189 | { | ||
| 2190 | case HOLLOW_BOX_CURSOR: | ||
| 2191 | haiku_draw_hollow_cursor (w, glyph_row); | ||
| 2192 | break; | ||
| 2120 | 2193 | ||
| 2121 | BView_invalidate_region (view, fx, fy, w->phys_cursor_width, h); | 2194 | case FILLED_BOX_CURSOR: |
| 2122 | break; | 2195 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); |
| 2196 | break; | ||
| 2197 | |||
| 2198 | case BAR_CURSOR: | ||
| 2199 | haiku_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR); | ||
| 2200 | break; | ||
| 2201 | |||
| 2202 | case HBAR_CURSOR: | ||
| 2203 | haiku_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR); | ||
| 2204 | break; | ||
| 2123 | 2205 | ||
| 2124 | case FILLED_BOX_CURSOR: | 2206 | case NO_CURSOR: |
| 2125 | draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); | 2207 | w->phys_cursor_width = 0; |
| 2208 | break; | ||
| 2209 | |||
| 2210 | default: | ||
| 2211 | emacs_abort (); | ||
| 2212 | } | ||
| 2213 | } | ||
| 2126 | } | 2214 | } |
| 2127 | BView_EndClip (view); | ||
| 2128 | BView_draw_unlock (view); | ||
| 2129 | } | 2215 | } |
| 2130 | 2216 | ||
| 2131 | static void | 2217 | static void |