1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//! macOS (Core Graphics) rasteriser for [`crate::DropOverlay`].
//!
//! Painting moved to the shared
//! [`crate::primitives::drop_zone::native_surface_paint::paint`] (#865,
//! `PaintSurface` Phase 2d slice 8/9) — see that fn's doc for the one
//! named divergence (Windows's pre-migration CPU-premixed highlight,
//! unlike GTK/macOS's real alpha blend) found and reported while
//! unifying `gtk::draw_drop_overlay`, `macos::drop_overlay::
//! draw_drop_overlay` and `win::drop_overlay::draw_drop_overlay` into
//! one implementation. This module no longer carries any public
//! rasteriser of its own — the deprecated `draw_drop_overlay`
//! compatibility shim over the shared [`super::surface::CgSurface`]
//! adapter was removed in issue #1109 (zero uses in coord-tui's `main`
//! and vimcode's `develop`); the driver-tier tests below paint through
//! [`crate::Backend::draw_drop_overlay`] instead.
//!
//! `DropOverlay::ghost_position` is not rendered — neither GTK nor TUI
//! paints a ghost label either, so this is parity, not a macOS gap.
#[cfg(test)]
use crate::primitives::drop_zone::DropOverlay;
#[cfg(test)]
use crate::theme::Theme;
#[cfg(test)]
mod tests {
use super::super::headless::BitmapSurface;
use super::super::text::make_font;
use super::super::MacBackend;
use super::*;
use crate::event::{Rect as QRect, Viewport};
use crate::Backend;
const W: u32 = 200;
const H: u32 = 120;
fn paint_via_backend(overlay: &DropOverlay) -> BitmapSurface {
let surface = BitmapSurface::new(W, H);
// Opaque black base so the 15% tint composites to a predictable,
// non-white value.
surface.fill(0.0, 0.0, 0.0, 1.0);
let mut backend = MacBackend::new();
backend.set_current_font(make_font("Menlo", 14.0).expect("Menlo installed"));
backend.begin_frame(Viewport::new(W as f32, H as f32, 1.0));
backend.enter_frame_scope(surface.context_ptr(), |b| {
b.draw_drop_overlay(overlay);
});
backend.end_frame();
surface
}
/// The impl this replaced had an empty body — the whole frame stayed
/// exactly as the caller left it (quadraui#484 §4).
#[test]
fn highlight_tints_the_target_rect() {
let overlay = DropOverlay {
highlight: Some(QRect::new(20.0, 20.0, 60.0, 40.0)),
insertion_bar: None,
ghost_position: None,
};
let surface = paint_via_backend(&overlay);
let theme = Theme::default();
let (r, g, b, _) = surface.pixel(50, 40);
assert_ne!(
(r, g, b),
(0, 0, 0),
"the highlight must actually tint the surface, not no-op",
);
// 15% of accent over black — each channel lands near 0.15 * accent.
let expect = |c: u8| (c as f64 * DropOverlay::HIGHLIGHT_ALPHA as f64).round() as i32;
for (got, want, name) in [
(r as i32, expect(theme.accent_fg.r), "r"),
(g as i32, expect(theme.accent_fg.g), "g"),
(b as i32, expect(theme.accent_fg.b), "b"),
] {
assert!(
(got - want).abs() <= 2,
"{name} channel {got} should be within 2 of the composited {want}",
);
}
// Outside the highlight rect: untouched.
assert_eq!(
{
let (r, g, b, _) = surface.pixel(5, 5);
(r, g, b)
},
(0, 0, 0),
"nothing should paint outside the highlight rect",
);
}
#[test]
fn insertion_bar_paints_solid_accent() {
let overlay = DropOverlay {
highlight: None,
insertion_bar: Some(QRect::new(100.0, 10.0, 2.0, 80.0)),
ghost_position: None,
};
let surface = paint_via_backend(&overlay);
let theme = Theme::default();
let (r, g, b, _) = surface.pixel(100, 50);
assert_eq!(
(r, g, b),
(theme.accent_fg.r, theme.accent_fg.g, theme.accent_fg.b),
"the insertion bar is opaque accent",
);
}
/// Non-zero-origin guard: the overlay carries absolute rects, so a
/// bar at x=140 must paint at x=140 and nowhere else.
#[test]
fn insertion_bar_honours_a_nonzero_origin() {
let overlay = DropOverlay {
highlight: None,
insertion_bar: Some(QRect::new(140.0, 33.0, 0.0, 40.0)),
ghost_position: None,
};
let surface = paint_via_backend(&overlay);
let theme = Theme::default();
let accent = (theme.accent_fg.r, theme.accent_fg.g, theme.accent_fg.b);
// Zero-width bars are widened to DropOverlay::MIN_BAR_THICKNESS, matching GTK.
let (r, g, b, _) = surface.pixel(140, 50);
assert_eq!((r, g, b), accent, "bar should paint at its own x");
let (r, g, b, _) = surface.pixel(141, 50);
assert_eq!((r, g, b), accent, "zero-width bar widens to 2 points");
// Above the bar's y and left of its x: untouched.
assert_eq!(
{
let (r, g, b, _) = surface.pixel(140, 20);
(r, g, b)
},
(0, 0, 0),
"nothing should paint above the bar",
);
assert_eq!(
{
let (r, g, b, _) = surface.pixel(130, 50);
(r, g, b)
},
(0, 0, 0),
"nothing should paint left of the bar",
);
}
#[test]
fn empty_overlay_paints_nothing() {
let overlay = DropOverlay {
highlight: None,
insertion_bar: None,
ghost_position: None,
};
let surface = paint_via_backend(&overlay);
assert!(
surface
.bytes()
.chunks_exact(4)
.all(|p| (p[0], p[1], p[2]) == (0, 0, 0)),
"an overlay with no geometry must leave the frame untouched",
);
}
}