mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-07 13:23:22 +00:00
Handle font wheel input in native viewports
This commit is contained in:
@@ -677,18 +677,22 @@ mod input {
|
||||
"vectorcraft document windows input"
|
||||
}
|
||||
|
||||
fn input_hook(&mut self, _: &egui::Context, input: &mut egui::RawInput) {
|
||||
if let Some(hook) = self.hook.as_ref().filter(|_| self.windows.contains(&input.viewport_id)) {
|
||||
hook(input);
|
||||
fn input_hook(&mut self, ctx: &egui::Context, input: &mut egui::RawInput) {
|
||||
if self.windows.contains(&input.viewport_id) {
|
||||
if let Some(hook) = &self.hook {
|
||||
hook(input);
|
||||
}
|
||||
crate::font_menu::take_raw_wheel(ctx, input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Run `hook` on the input of `windows` from their next frame on.
|
||||
pub(super) fn register(ctx: &egui::Context, hook: Option<NativeInputHook>, windows: HashSet<egui::ViewportId>) {
|
||||
if hook.is_none() && ctx.with_plugin(|_: &mut DocumentWindowInput| ()).is_none() {
|
||||
if windows.is_empty() && ctx.with_plugin(|_: &mut DocumentWindowInput| ()).is_none() {
|
||||
return;
|
||||
}
|
||||
crate::font_menu::ensure_native_wheel_layers(ctx);
|
||||
ctx.add_plugin(DocumentWindowInput::default());
|
||||
ctx.with_plugin(|p: &mut DocumentWindowInput| {
|
||||
p.hook = hook;
|
||||
|
||||
@@ -447,6 +447,57 @@ struct WheelFields {
|
||||
pending: HashMap<egui::Id, Vec<WheelInput>>,
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[derive(Clone)]
|
||||
struct WheelLayers(Arc<dyn Fn(egui::Pos2) -> Option<egui::LayerId> + Send + Sync>);
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[derive(Default)]
|
||||
struct WheelLayerSnapshot;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl egui::Plugin for WheelLayerSnapshot {
|
||||
fn debug_name(&self) -> &'static str {
|
||||
"font wheel viewport layers"
|
||||
}
|
||||
|
||||
fn on_end_pass(&mut self, ui: &mut Ui) {
|
||||
let ctx = ui.ctx();
|
||||
let viewport = ctx.viewport_id();
|
||||
if viewport == egui::ViewportId::ROOT || ctx.data(|d| d.get_temp::<WheelFields>(wheel_fields_id(viewport))).is_none() {
|
||||
return;
|
||||
}
|
||||
let current_layers = ctx.viewport(|viewport| {
|
||||
viewport.this_pass.widgets.layers().filter_map(|(layer, widgets)| (!widgets.is_empty()).then_some(*layer)).collect::<Vec<_>>()
|
||||
});
|
||||
let layers = ctx.memory(|m| {
|
||||
m.layer_ids()
|
||||
.filter(|layer| current_layers.contains(layer))
|
||||
.filter(|layer| m.areas().is_visible(layer))
|
||||
.filter_map(|layer| m.area_rect(layer.id).map(|rect| (layer, rect)))
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
let layers = layers
|
||||
.into_iter()
|
||||
.filter(|(layer, _)| egui::AreaState::load(ctx, layer.id).is_some_and(|state| state.interactable))
|
||||
.map(|(layer, rect)| (layer, ctx.layer_transform_to_global(layer).map_or(rect, |transform| transform * rect)))
|
||||
.collect::<Vec<_>>();
|
||||
ctx.data_mut(|d| {
|
||||
d.insert_temp(
|
||||
wheel_fields_id(viewport).with("layers"),
|
||||
WheelLayers(Arc::new(move |p| layers.iter().rev().find(|(_, rect)| rect.contains(p)).map(|(layer, _)| *layer))),
|
||||
)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(crate) fn ensure_native_wheel_layers(ctx: &egui::Context) {
|
||||
if ctx.with_plugin(|_: &mut WheelLayerSnapshot| ()).is_none() {
|
||||
ctx.add_plugin(WheelLayerSnapshot);
|
||||
}
|
||||
}
|
||||
|
||||
fn wheel_fields_id(viewport: egui::ViewportId) -> egui::Id {
|
||||
egui::Id::unique("font-wheel-fields").with(viewport)
|
||||
}
|
||||
@@ -535,6 +586,10 @@ pub(crate) fn take_raw_wheel(ctx: &egui::Context, raw: &mut egui::RawInput) {
|
||||
let Some(mut fields) = ctx.data(|d| d.get_temp::<WheelFields>(key)) else { return };
|
||||
if !ctx.input(|i| i.raw.viewports.contains_key(&raw.viewport_id)) {
|
||||
ctx.data_mut(|d| d.remove::<WheelFields>(key));
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
ctx.data_mut(|d| {
|
||||
d.remove::<WheelLayers>(key.with("layers"));
|
||||
});
|
||||
return;
|
||||
}
|
||||
let frame = ctx.cumulative_frame_nr_for(raw.viewport_id);
|
||||
@@ -548,9 +603,28 @@ pub(crate) fn take_raw_wheel(ctx: &egui::Context, raw: &mut egui::RawInput) {
|
||||
fields.pending.clear();
|
||||
}
|
||||
let line = ctx.options(|o| o.input_options.line_scroll_speed).max(1.0);
|
||||
let mut pointer = fields.pointer.or_else(|| ctx.input(|i| i.pointer.latest_pos()));
|
||||
let over =
|
||||
|field: &WheelField, point: Option<egui::Pos2>| point.is_some_and(|p| field.rect.contains(p) && ctx.layer_id_at(p) == Some(field.layer));
|
||||
let mut pointer = fields.pointer.or_else(|| ctx.input_for(raw.viewport_id, |i| i.pointer.latest_pos()));
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let native_layers = ctx.data(|d| d.get_temp::<WheelLayers>(key.with("layers")));
|
||||
let over = |field: &WheelField, point: Option<egui::Pos2>| {
|
||||
point.is_some_and(|p| {
|
||||
if !field.rect.contains(p) {
|
||||
return false;
|
||||
}
|
||||
if ctx.viewport_id() == raw.viewport_id {
|
||||
ctx.layer_id_at(p) == Some(field.layer)
|
||||
} else {
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
native_layers.as_ref().is_some_and(|layers| (layers.0)(p) == Some(field.layer))
|
||||
}
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
{
|
||||
false
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
// An activation batch belongs to the popup, including a release after a prior press.
|
||||
if fields.activation_pass != pass {
|
||||
fields.activation_pass = pass;
|
||||
|
||||
@@ -1123,8 +1123,15 @@ pub(crate) fn show(app: &mut VectorcraftApp, ui: &mut egui::Ui) {
|
||||
.input_blocked(modal)
|
||||
.auto_collapse_iconic(app.session.prefs.auto_collapse_icon_panels);
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
if let Some(hook) = app.services.native_input_hook.clone() {
|
||||
dock = dock.native_input_hook(move |_, raw| hook(raw));
|
||||
{
|
||||
crate::font_menu::ensure_native_wheel_layers(ui.ctx());
|
||||
let hook = app.services.native_input_hook.clone();
|
||||
dock = dock.native_input_hook(move |ctx, raw| {
|
||||
if let Some(hook) = &hook {
|
||||
hook(raw);
|
||||
}
|
||||
crate::font_menu::take_raw_wheel(ctx, raw);
|
||||
});
|
||||
}
|
||||
// Tab and Shift+Tab (`window.dock`, `window.panels`) and the full screen modes hide the panels;
|
||||
// the canvas stays.
|
||||
|
||||
@@ -29,6 +29,11 @@ struct Window {
|
||||
|
||||
struct Host {
|
||||
windows: HashMap<ViewportId, Window>,
|
||||
child_overlay: Option<(ViewportId, Rect)>,
|
||||
child_transparent_overlay: Option<(ViewportId, Rect)>,
|
||||
child_transition_overlay: Option<(ViewportId, Rect, bool)>,
|
||||
child_empty_overlay: Option<(ViewportId, Rect)>,
|
||||
child_pass_through_overlay: Option<(ViewportId, Rect)>,
|
||||
/// The window with the keyboard.
|
||||
focus: ViewportId,
|
||||
time: f64,
|
||||
@@ -87,7 +92,54 @@ impl Host {
|
||||
..Default::default()
|
||||
}
|
||||
};
|
||||
let mut full = ctx.run_ui(input, |ui| (viewport.viewport_ui_cb)(ui));
|
||||
let child_overlay = host.borrow().child_overlay.filter(|(viewport, _)| *viewport == id).map(|(_, rect)| rect);
|
||||
let child_transparent_overlay = host.borrow().child_transparent_overlay.filter(|(viewport, _)| *viewport == id).map(|(_, rect)| rect);
|
||||
let child_transition_overlay =
|
||||
host.borrow().child_transition_overlay.filter(|(viewport, _, _)| *viewport == id).map(|(_, rect, painted)| (rect, painted));
|
||||
let child_empty_overlay = host.borrow().child_empty_overlay.filter(|(viewport, _)| *viewport == id).map(|(_, rect)| rect);
|
||||
let child_pass_through_overlay = host.borrow().child_pass_through_overlay.filter(|(viewport, _)| *viewport == id).map(|(_, rect)| rect);
|
||||
let mut full = ctx.run_ui(input, |ui| {
|
||||
(viewport.viewport_ui_cb)(ui);
|
||||
if let Some(rect) = child_overlay {
|
||||
egui::Window::new("Child overlay").fixed_pos(rect.min).fixed_size(rect.size()).show(ui.ctx(), |ui| {
|
||||
ui.label("Child overlay");
|
||||
});
|
||||
}
|
||||
if let Some(rect) = child_transparent_overlay {
|
||||
egui::Area::new(egui::Id::unique("Child transparent overlay")).order(egui::Order::Foreground).fixed_pos(rect.min).show(
|
||||
ui.ctx(),
|
||||
|ui| {
|
||||
ui.allocate_space(rect.size());
|
||||
},
|
||||
);
|
||||
}
|
||||
if let Some((rect, painted)) = child_transition_overlay {
|
||||
egui::Area::new(egui::Id::unique("Child transition overlay")).order(egui::Order::Foreground).fixed_pos(rect.min).show(
|
||||
ui.ctx(),
|
||||
|ui| {
|
||||
ui.allocate_space(rect.size());
|
||||
if painted {
|
||||
ui.label("Child transition overlay");
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
if let Some(rect) = child_empty_overlay {
|
||||
egui::Area::new(egui::Id::unique("Child empty overlay")).order(egui::Order::Foreground).fixed_pos(rect.min).show(ui.ctx(), |ui| {
|
||||
ui.set_min_size(rect.size());
|
||||
});
|
||||
}
|
||||
if let Some(rect) = child_pass_through_overlay {
|
||||
egui::Area::new(egui::Id::unique("Child pass-through overlay"))
|
||||
.order(egui::Order::Foreground)
|
||||
.fixed_pos(rect.min)
|
||||
.interactable(false)
|
||||
.show(ui.ctx(), |ui| {
|
||||
let (paint, _) = ui.allocate_exact_size(rect.size(), egui::Sense::hover());
|
||||
ui.painter().rect_filled(paint, 0.0, egui::Color32::TRANSPARENT);
|
||||
});
|
||||
}
|
||||
});
|
||||
full.textures_delta.clear();
|
||||
fn texts(s: &egui::Shape, out: &mut Vec<(String, Rect)>) {
|
||||
match s {
|
||||
@@ -110,18 +162,29 @@ struct Harness {
|
||||
app: VectorcraftApp,
|
||||
ctx: egui::Context,
|
||||
host: Rc<RefCell<Host>>,
|
||||
root_overlay: Option<Rect>,
|
||||
}
|
||||
|
||||
impl Harness {
|
||||
fn new() -> Self {
|
||||
let host = Rc::new(RefCell::new(Host { windows: HashMap::new(), focus: ViewportId::ROOT, time: 0.0, commands: Vec::new() }));
|
||||
let host = Rc::new(RefCell::new(Host {
|
||||
windows: HashMap::new(),
|
||||
child_overlay: None,
|
||||
child_transparent_overlay: None,
|
||||
child_transition_overlay: None,
|
||||
child_empty_overlay: None,
|
||||
child_pass_through_overlay: None,
|
||||
focus: ViewportId::ROOT,
|
||||
time: 0.0,
|
||||
commands: Vec::new(),
|
||||
}));
|
||||
let shared = host.clone();
|
||||
egui::Context::set_immediate_viewport_renderer(move |ctx, viewport| Host::render(&shared, ctx, viewport));
|
||||
let ctx = egui::Context::default();
|
||||
ctx.set_embed_viewports(false);
|
||||
let mut app = VectorcraftApp::new(Session::new(), Default::default());
|
||||
app.run("file.new", json!({"width": 400, "height": 300})).unwrap();
|
||||
let mut h = Self { app, ctx, host };
|
||||
let mut h = Self { app, ctx, host, root_overlay: None };
|
||||
h.frames(3);
|
||||
h
|
||||
}
|
||||
@@ -135,9 +198,15 @@ impl Harness {
|
||||
let mut input = egui::RawInput { time: Some(time), events, screen_rect: Some(SCREEN), viewports, focused, ..Default::default() };
|
||||
self.app.raw_input_hook(&self.ctx, &mut input);
|
||||
let app = &mut self.app;
|
||||
let root_overlay = self.root_overlay;
|
||||
let mut full = self.ctx.run_ui(input, |ui| {
|
||||
app.logic(ui.ctx());
|
||||
app.ui(ui);
|
||||
if let Some(rect) = root_overlay {
|
||||
egui::Window::new("Root overlay").fixed_pos(rect.min).fixed_size(rect.size()).show(ui.ctx(), |ui| {
|
||||
ui.label("Root overlay");
|
||||
});
|
||||
}
|
||||
});
|
||||
full.textures_delta.clear();
|
||||
self.host.borrow_mut().apply(&full);
|
||||
@@ -399,3 +468,221 @@ fn ui_docking_leaves_out_the_controls_of_os_windows() {
|
||||
assert!(!hits.iter().any(swatches), "none of the OS window's: {hits:?}");
|
||||
assert!(report["layout"]["floating"][0]["native"].is_array(), "its place is the window's native rect");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wheel_over_a_floating_character_font_field_changes_the_font() {
|
||||
let mut h = Harness::new();
|
||||
h.app.run("text.create", json!({"x": 30, "y": 50, "text": "Hi", "font": "Source Sans 3"})).unwrap();
|
||||
let viewport = h.float("character");
|
||||
let field = h
|
||||
.host
|
||||
.borrow()
|
||||
.windows
|
||||
.get(&viewport)
|
||||
.and_then(|w| w.texts.iter().find(|(text, _)| text == "Source Sans 3").map(|(_, rect)| *rect))
|
||||
.expect("the Character panel's font family field");
|
||||
let pointer = pos2(field.min.x + 4.0, field.center().y);
|
||||
h.root_overlay = Some(field.expand(10.0));
|
||||
h.frames(2);
|
||||
h.host.borrow_mut().windows.get_mut(&viewport).unwrap().events.extend([
|
||||
Event::PointerMoved(pointer),
|
||||
Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Line,
|
||||
delta: vec2(0.0, -1.0),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: Default::default(),
|
||||
source: egui::MouseWheelSource::Unknown,
|
||||
},
|
||||
]);
|
||||
h.frame(vec![]);
|
||||
h.frames(2);
|
||||
let fonts = h.app.run("text.fonts", json!({})).unwrap();
|
||||
assert_ne!(fonts[0]["family"], "Source Sans 3", "{fonts}");
|
||||
|
||||
h.host.borrow_mut().child_overlay = Some((viewport, field.expand(10.0)));
|
||||
h.frames(2);
|
||||
let covered = h.app.run("text.fonts", json!({})).unwrap();
|
||||
h.host.borrow_mut().windows.get_mut(&viewport).unwrap().events.extend([
|
||||
Event::PointerMoved(pointer),
|
||||
Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Line,
|
||||
delta: vec2(0.0, -1.0),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: Default::default(),
|
||||
source: egui::MouseWheelSource::Unknown,
|
||||
},
|
||||
]);
|
||||
h.frame(vec![]);
|
||||
assert_eq!(h.app.run("text.fonts", json!({})).unwrap(), covered);
|
||||
|
||||
h.host.borrow_mut().child_overlay = None;
|
||||
h.frame(vec![]);
|
||||
h.host.borrow_mut().windows.get_mut(&viewport).unwrap().events.extend([
|
||||
Event::PointerMoved(pointer),
|
||||
Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Line,
|
||||
delta: vec2(0.0, -1.0),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: Default::default(),
|
||||
source: egui::MouseWheelSource::Unknown,
|
||||
},
|
||||
]);
|
||||
h.frame(vec![]);
|
||||
assert_ne!(h.app.run("text.fonts", json!({})).unwrap(), covered);
|
||||
|
||||
h.host.borrow_mut().child_transparent_overlay = Some((viewport, field.expand(10.0)));
|
||||
h.frames(2);
|
||||
let covered = h.app.run("text.fonts", json!({})).unwrap();
|
||||
h.host.borrow_mut().windows.get_mut(&viewport).unwrap().events.extend([
|
||||
Event::PointerMoved(pointer),
|
||||
Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Line,
|
||||
delta: vec2(0.0, -1.0),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: Default::default(),
|
||||
source: egui::MouseWheelSource::Unknown,
|
||||
},
|
||||
]);
|
||||
h.frame(vec![]);
|
||||
assert_eq!(h.app.run("text.fonts", json!({})).unwrap(), covered);
|
||||
|
||||
h.host.borrow_mut().child_transparent_overlay = None;
|
||||
h.host.borrow_mut().child_pass_through_overlay = Some((viewport, field.expand(10.0)));
|
||||
h.frames(2);
|
||||
h.host.borrow_mut().windows.get_mut(&viewport).unwrap().events.extend([
|
||||
Event::PointerMoved(pointer),
|
||||
Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Line,
|
||||
delta: vec2(0.0, -1.0),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: Default::default(),
|
||||
source: egui::MouseWheelSource::Unknown,
|
||||
},
|
||||
]);
|
||||
h.frame(vec![]);
|
||||
assert_ne!(h.app.run("text.fonts", json!({})).unwrap(), covered);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_modal_blocks_font_wheel_input_in_a_floating_panel() {
|
||||
let mut h = Harness::new();
|
||||
h.app.run("text.create", json!({"x": 30, "y": 50, "text": "Hi", "font": "Source Sans 3"})).unwrap();
|
||||
let viewport = h.float("character");
|
||||
let field = h
|
||||
.host
|
||||
.borrow()
|
||||
.windows
|
||||
.get(&viewport)
|
||||
.and_then(|w| w.texts.iter().find(|(text, _)| text == "Source Sans 3").map(|(_, rect)| *rect))
|
||||
.expect("the Character panel's font family field");
|
||||
let pointer = pos2(field.min.x + 4.0, field.center().y);
|
||||
let before = h.app.run("text.fonts", json!({})).unwrap();
|
||||
h.app.ui.about = true;
|
||||
h.host.borrow_mut().windows.get_mut(&viewport).unwrap().events.extend([
|
||||
Event::PointerMoved(pointer),
|
||||
Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Line,
|
||||
delta: vec2(0.0, -1.0),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: Default::default(),
|
||||
source: egui::MouseWheelSource::Unknown,
|
||||
},
|
||||
]);
|
||||
h.frame(vec![]);
|
||||
h.frames(2);
|
||||
assert_eq!(h.app.run("text.fonts", json!({})).unwrap(), before);
|
||||
h.app.ui.about = false;
|
||||
h.frames(2);
|
||||
assert_eq!(h.app.run("text.fonts", json!({})).unwrap(), before);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wheel_stays_under_an_overlay_that_stops_painting() {
|
||||
let mut h = Harness::new();
|
||||
h.app.run("text.create", json!({"x": 30, "y": 50, "text": "Hi", "font": "Source Sans 3"})).unwrap();
|
||||
let viewport = h.float("character");
|
||||
let field = h
|
||||
.host
|
||||
.borrow()
|
||||
.windows
|
||||
.get(&viewport)
|
||||
.and_then(|w| w.texts.iter().find(|(text, _)| text == "Source Sans 3").map(|(_, rect)| *rect))
|
||||
.expect("the Character panel's font family field");
|
||||
let pointer = pos2(field.min.x + 4.0, field.center().y);
|
||||
h.host.borrow_mut().child_transition_overlay = Some((viewport, field.expand(10.0), true));
|
||||
h.frames(2);
|
||||
let covered = h.app.run("text.fonts", json!({})).unwrap();
|
||||
h.host.borrow_mut().child_transition_overlay = Some((viewport, field.expand(10.0), false));
|
||||
h.frame(vec![]);
|
||||
h.host.borrow_mut().windows.get_mut(&viewport).unwrap().events.extend([
|
||||
Event::PointerMoved(pointer),
|
||||
Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Line,
|
||||
delta: vec2(0.0, -1.0),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: Default::default(),
|
||||
source: egui::MouseWheelSource::Unknown,
|
||||
},
|
||||
]);
|
||||
h.frame(vec![]);
|
||||
assert_eq!(h.app.run("text.fonts", json!({})).unwrap(), covered);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wheel_stays_under_an_empty_interactive_overlay() {
|
||||
let mut h = Harness::new();
|
||||
h.app.run("text.create", json!({"x": 30, "y": 50, "text": "Hi", "font": "Source Sans 3"})).unwrap();
|
||||
let viewport = h.float("character");
|
||||
let field = h
|
||||
.host
|
||||
.borrow()
|
||||
.windows
|
||||
.get(&viewport)
|
||||
.and_then(|w| w.texts.iter().find(|(text, _)| text == "Source Sans 3").map(|(_, rect)| *rect))
|
||||
.expect("the Character panel's font family field");
|
||||
let pointer = pos2(field.min.x + 4.0, field.center().y);
|
||||
h.host.borrow_mut().child_empty_overlay = Some((viewport, field.expand(10.0)));
|
||||
h.frames(2);
|
||||
let covered = h.app.run("text.fonts", json!({})).unwrap();
|
||||
h.host.borrow_mut().windows.get_mut(&viewport).unwrap().events.extend([
|
||||
Event::PointerMoved(pointer),
|
||||
Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Line,
|
||||
delta: vec2(0.0, -1.0),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: Default::default(),
|
||||
source: egui::MouseWheelSource::Unknown,
|
||||
},
|
||||
]);
|
||||
h.frame(vec![]);
|
||||
assert_eq!(h.app.run("text.fonts", json!({})).unwrap(), covered);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wheel_without_a_move_uses_the_floating_viewports_pointer() {
|
||||
let mut h = Harness::new();
|
||||
h.app.run("text.create", json!({"x": 30, "y": 50, "text": "Hi", "font": "Source Sans 3"})).unwrap();
|
||||
let viewport = h.float("character");
|
||||
let field = h
|
||||
.host
|
||||
.borrow()
|
||||
.windows
|
||||
.get(&viewport)
|
||||
.and_then(|w| w.texts.iter().find(|(text, _)| text == "Source Sans 3").map(|(_, rect)| *rect))
|
||||
.expect("the Character panel's font family field");
|
||||
let pointer = pos2(field.min.x + 4.0, field.center().y);
|
||||
h.host.borrow_mut().windows.get_mut(&viewport).unwrap().events.push(Event::PointerMoved(pointer));
|
||||
h.frame(vec![Event::PointerMoved(pos2(1200.0, 800.0))]);
|
||||
h.app.run("text.create", json!({"x": 30, "y": 90, "text": "New", "font": "Source Sans 3"})).unwrap();
|
||||
h.frames(2);
|
||||
let before = h.app.run("text.fonts", json!({})).unwrap();
|
||||
h.host.borrow_mut().windows.get_mut(&viewport).unwrap().events.push(Event::MouseWheel {
|
||||
unit: egui::MouseWheelUnit::Line,
|
||||
delta: vec2(0.0, -1.0),
|
||||
phase: egui::TouchPhase::Move,
|
||||
modifiers: Default::default(),
|
||||
source: egui::MouseWheelSource::Unknown,
|
||||
});
|
||||
h.frame(vec![]);
|
||||
assert_ne!(h.app.run("text.fonts", json!({})).unwrap(), before);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user