aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPo Lu2022-05-12 04:11:12 +0000
committerPo Lu2022-05-12 04:11:32 +0000
commitec1a14ab331c0abc57bc34972a8a6f69c6ffa17a (patch)
tree32af759dd3116a83ab3e133ed2c63d5d9d2ebcc4 /src
parente2bb618ea7599548d8f6e0f9e23db5a15a90d8ac (diff)
downloademacs-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.c306
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
1631haiku_draw_image_glyph_string (struct glyph_string *s) 1631haiku_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
2002static void 2019static void
2003haiku_draw_window_cursor (struct window *w, 2020haiku_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
2071static void
2072haiku_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: 2168static void
2113 if (phys_cursor_glyph->type != IMAGE_GLYPH) 2169haiku_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
2131static void 2217static void