mirror of
https://github.com/emilk/egui.git
synced 2026-08-29 04:40:03 -04:00
Merge branch 'main' into lucas/allow-constructing-kittest-node
# Conflicts: # crates/egui_kittest/src/lib.rs # crates/egui_kittest/src/node.rs
This commit is contained in:
@@ -20,6 +20,12 @@ pub(crate) struct WebInput {
|
|||||||
/// Helps to track the delta rotation from gesture events
|
/// Helps to track the delta rotation from gesture events
|
||||||
pub accumulated_rotation: f32,
|
pub accumulated_rotation: f32,
|
||||||
|
|
||||||
|
/// The last modifier state we sent to egui.
|
||||||
|
///
|
||||||
|
/// The web has no dedicated modifier event, so we derive the state from each DOM event and
|
||||||
|
/// emit [`egui::Event::ModifiersChanged`] when it changes (see [`Self::set_modifiers`]).
|
||||||
|
pub modifiers: egui::Modifiers,
|
||||||
|
|
||||||
/// The raw input to `egui`.
|
/// The raw input to `egui`.
|
||||||
pub raw: egui::RawInput,
|
pub raw: egui::RawInput,
|
||||||
}
|
}
|
||||||
@@ -53,11 +59,23 @@ impl WebInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// log::debug!("on_web_page_focus_change: {focused}");
|
// log::debug!("on_web_page_focus_change: {focused}");
|
||||||
self.raw.modifiers = egui::Modifiers::default(); // Avoid sticky modifier keys on alt-tab:
|
self.modifiers = egui::Modifiers::default(); // Avoid sticky modifier keys on alt-tab:
|
||||||
self.raw.focused = focused;
|
self.raw.focused = focused;
|
||||||
self.raw.events.push(egui::Event::WindowFocused(focused));
|
self.raw.events.push(egui::Event::WindowFocused(focused));
|
||||||
self.primary_touch = None;
|
self.primary_touch = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the modifier state, emitting [`egui::Event::ModifiersChanged`] if it changed.
|
||||||
|
///
|
||||||
|
/// Call before pushing the DOM event itself so egui sees the new modifier state first.
|
||||||
|
pub fn set_modifiers(&mut self, modifiers: egui::Modifiers) {
|
||||||
|
if self.modifiers != modifiers {
|
||||||
|
self.modifiers = modifiers;
|
||||||
|
self.raw
|
||||||
|
.events
|
||||||
|
.push(egui::Event::ModifiersChanged(modifiers));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ pub(crate) fn on_keydown(event: web_sys::KeyboardEvent, runner: &mut AppRunner)
|
|||||||
}
|
}
|
||||||
|
|
||||||
let modifiers = modifiers_from_kb_event(&event);
|
let modifiers = modifiers_from_kb_event(&event);
|
||||||
runner.input.raw.modifiers = modifiers;
|
runner.input.set_modifiers(modifiers);
|
||||||
|
|
||||||
let key = event.key();
|
let key = event.key();
|
||||||
let egui_key = translate_key(&key);
|
let egui_key = translate_key(&key);
|
||||||
@@ -287,7 +287,7 @@ fn install_keyup(runner_ref: &WebRunner, target: &EventTarget) -> Result<(), JsV
|
|||||||
#[expect(clippy::needless_pass_by_value)] // So that we can pass it directly to `add_event_listener`
|
#[expect(clippy::needless_pass_by_value)] // So that we can pass it directly to `add_event_listener`
|
||||||
pub(crate) fn on_keyup(event: web_sys::KeyboardEvent, runner: &mut AppRunner) {
|
pub(crate) fn on_keyup(event: web_sys::KeyboardEvent, runner: &mut AppRunner) {
|
||||||
let modifiers = modifiers_from_kb_event(&event);
|
let modifiers = modifiers_from_kb_event(&event);
|
||||||
runner.input.raw.modifiers = modifiers;
|
runner.input.set_modifiers(modifiers);
|
||||||
|
|
||||||
let mut should_stop_propagation = true;
|
let mut should_stop_propagation = true;
|
||||||
|
|
||||||
@@ -535,11 +535,11 @@ fn install_pointerdown(runner_ref: &WebRunner, target: &EventTarget) -> Result<(
|
|||||||
"pointerdown",
|
"pointerdown",
|
||||||
|event: web_sys::PointerEvent, runner: &mut AppRunner| {
|
|event: web_sys::PointerEvent, runner: &mut AppRunner| {
|
||||||
let modifiers = modifiers_from_mouse_event(&event);
|
let modifiers = modifiers_from_mouse_event(&event);
|
||||||
runner.input.raw.modifiers = modifiers;
|
runner.input.set_modifiers(modifiers);
|
||||||
let mut should_stop_propagation = true;
|
let mut should_stop_propagation = true;
|
||||||
if let Some(button) = button_from_mouse_event(&event) {
|
if let Some(button) = button_from_mouse_event(&event) {
|
||||||
let pos = pos_from_mouse_event(runner.canvas(), &event, runner.egui_ctx());
|
let pos = pos_from_mouse_event(runner.canvas(), &event, runner.egui_ctx());
|
||||||
let modifiers = runner.input.raw.modifiers;
|
let modifiers = runner.input.modifiers;
|
||||||
let egui_event = egui::Event::PointerButton {
|
let egui_event = egui::Event::PointerButton {
|
||||||
pos,
|
pos,
|
||||||
button,
|
button,
|
||||||
@@ -572,7 +572,7 @@ fn install_pointerup(runner_ref: &WebRunner, target: &EventTarget) -> Result<(),
|
|||||||
"pointerup",
|
"pointerup",
|
||||||
|event: web_sys::PointerEvent, runner| {
|
|event: web_sys::PointerEvent, runner| {
|
||||||
let modifiers = modifiers_from_mouse_event(&event);
|
let modifiers = modifiers_from_mouse_event(&event);
|
||||||
runner.input.raw.modifiers = modifiers;
|
runner.input.set_modifiers(modifiers);
|
||||||
|
|
||||||
let pos = pos_from_mouse_event(runner.canvas(), &event, runner.egui_ctx());
|
let pos = pos_from_mouse_event(runner.canvas(), &event, runner.egui_ctx());
|
||||||
|
|
||||||
@@ -581,7 +581,7 @@ fn install_pointerup(runner_ref: &WebRunner, target: &EventTarget) -> Result<(),
|
|||||||
egui::pos2(event.client_x() as f32, event.client_y() as f32),
|
egui::pos2(event.client_x() as f32, event.client_y() as f32),
|
||||||
) && let Some(button) = button_from_mouse_event(&event)
|
) && let Some(button) = button_from_mouse_event(&event)
|
||||||
{
|
{
|
||||||
let modifiers = runner.input.raw.modifiers;
|
let modifiers = runner.input.modifiers;
|
||||||
let egui_event = egui::Event::PointerButton {
|
let egui_event = egui::Event::PointerButton {
|
||||||
pos,
|
pos,
|
||||||
button,
|
button,
|
||||||
@@ -647,7 +647,7 @@ fn is_interested_in_pointer_event(runner: &AppRunner, pos: egui::Pos2) -> bool {
|
|||||||
fn install_mousemove(runner_ref: &WebRunner, target: &EventTarget) -> Result<(), JsValue> {
|
fn install_mousemove(runner_ref: &WebRunner, target: &EventTarget) -> Result<(), JsValue> {
|
||||||
runner_ref.add_event_listener(target, "mousemove", |event: web_sys::MouseEvent, runner| {
|
runner_ref.add_event_listener(target, "mousemove", |event: web_sys::MouseEvent, runner| {
|
||||||
let modifiers = modifiers_from_mouse_event(&event);
|
let modifiers = modifiers_from_mouse_event(&event);
|
||||||
runner.input.raw.modifiers = modifiers;
|
runner.input.set_modifiers(modifiers);
|
||||||
|
|
||||||
let pos = pos_from_mouse_event(runner.canvas(), &event, runner.egui_ctx());
|
let pos = pos_from_mouse_event(runner.canvas(), &event, runner.egui_ctx());
|
||||||
|
|
||||||
@@ -705,7 +705,7 @@ fn install_touchstart(runner_ref: &WebRunner, target: &EventTarget) -> Result<()
|
|||||||
pos,
|
pos,
|
||||||
button: egui::PointerButton::Primary,
|
button: egui::PointerButton::Primary,
|
||||||
pressed: true,
|
pressed: true,
|
||||||
modifiers: runner.input.raw.modifiers,
|
modifiers: runner.input.modifiers,
|
||||||
};
|
};
|
||||||
should_stop_propagation = (runner.web_options.should_stop_propagation)(&egui_event);
|
should_stop_propagation = (runner.web_options.should_stop_propagation)(&egui_event);
|
||||||
should_prevent_default = (runner.web_options.should_prevent_default)(&egui_event);
|
should_prevent_default = (runner.web_options.should_prevent_default)(&egui_event);
|
||||||
@@ -770,7 +770,7 @@ fn install_touchend(runner_ref: &WebRunner, target: &EventTarget) -> Result<(),
|
|||||||
pos,
|
pos,
|
||||||
button: egui::PointerButton::Primary,
|
button: egui::PointerButton::Primary,
|
||||||
pressed: false,
|
pressed: false,
|
||||||
modifiers: runner.input.raw.modifiers,
|
modifiers: runner.input.modifiers,
|
||||||
};
|
};
|
||||||
should_stop_propagation &= (runner.web_options.should_stop_propagation)(&egui_event);
|
should_stop_propagation &= (runner.web_options.should_stop_propagation)(&egui_event);
|
||||||
should_prevent_default &= (runner.web_options.should_prevent_default)(&egui_event);
|
should_prevent_default &= (runner.web_options.should_prevent_default)(&egui_event);
|
||||||
@@ -832,7 +832,7 @@ fn install_wheel(runner_ref: &WebRunner, target: &EventTarget) -> Result<(), JsV
|
|||||||
|
|
||||||
let modifiers = modifiers_from_wheel_event(&event);
|
let modifiers = modifiers_from_wheel_event(&event);
|
||||||
|
|
||||||
let egui_event = if modifiers.ctrl && !runner.input.raw.modifiers.ctrl {
|
let egui_event = if modifiers.ctrl && !runner.input.modifiers.ctrl {
|
||||||
// The browser is saying the ctrl key is down, but it isn't _really_.
|
// The browser is saying the ctrl key is down, but it isn't _really_.
|
||||||
// This happens on pinch-to-zoom on multitouch trackpads
|
// This happens on pinch-to-zoom on multitouch trackpads
|
||||||
// egui will treat ctrl+scroll as zoom, so it all works.
|
// egui will treat ctrl+scroll as zoom, so it all works.
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ impl WebPainterWgpu {
|
|||||||
&& create_new.display_handle.is_none()
|
&& create_new.display_handle.is_none()
|
||||||
{
|
{
|
||||||
// Force WebGL, useful for quick & dirty testing:
|
// Force WebGL, useful for quick & dirty testing:
|
||||||
//create_new.instance_descriptor.backends = wgpu::Backends::GL;
|
// create_new.instance_descriptor.backends = wgpu::Backends::GL;
|
||||||
create_new.display_handle = Some(Box::new(WebDisplay));
|
create_new.display_handle = Some(Box::new(WebDisplay));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,13 @@ pub struct State {
|
|||||||
viewport_id: ViewportId,
|
viewport_id: ViewportId,
|
||||||
start_time: web_time::Instant,
|
start_time: web_time::Instant,
|
||||||
egui_input: egui::RawInput,
|
egui_input: egui::RawInput,
|
||||||
|
|
||||||
|
/// The current modifier state.
|
||||||
|
///
|
||||||
|
/// We keep a copy so we can stamp
|
||||||
|
/// it onto per-event `modifiers` fields and emit [`egui::Event::ModifiersChanged`].
|
||||||
|
modifiers: egui::Modifiers,
|
||||||
|
|
||||||
pointer_pos_in_points: Option<egui::Pos2>,
|
pointer_pos_in_points: Option<egui::Pos2>,
|
||||||
any_pointer_button_down: bool,
|
any_pointer_button_down: bool,
|
||||||
current_cursor_icon: Option<egui::CursorIcon>,
|
current_cursor_icon: Option<egui::CursorIcon>,
|
||||||
@@ -146,6 +153,7 @@ impl State {
|
|||||||
.unwrap_or_else(web_time::Instant::now),
|
.unwrap_or_else(web_time::Instant::now),
|
||||||
egui_ctx,
|
egui_ctx,
|
||||||
egui_input,
|
egui_input,
|
||||||
|
modifiers: egui::Modifiers::default(),
|
||||||
pointer_pos_in_points: None,
|
pointer_pos_in_points: None,
|
||||||
any_pointer_button_down: false,
|
any_pointer_button_down: false,
|
||||||
current_cursor_icon: None,
|
current_cursor_icon: None,
|
||||||
@@ -422,6 +430,10 @@ impl State {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.egui_input.focused = focused;
|
self.egui_input.focused = focused;
|
||||||
|
if !focused {
|
||||||
|
// Avoid sticky modifiers when focus is lost (egui clears its own copy too).
|
||||||
|
self.modifiers = egui::Modifiers::default();
|
||||||
|
}
|
||||||
self.egui_input
|
self.egui_input
|
||||||
.events
|
.events
|
||||||
.push(egui::Event::WindowFocused(focused));
|
.push(egui::Event::WindowFocused(focused));
|
||||||
@@ -473,16 +485,20 @@ impl State {
|
|||||||
let shift = state.shift_key();
|
let shift = state.shift_key();
|
||||||
let super_ = state.super_key();
|
let super_ = state.super_key();
|
||||||
|
|
||||||
self.egui_input.modifiers.alt = alt;
|
self.modifiers.alt = alt;
|
||||||
self.egui_input.modifiers.ctrl = ctrl;
|
self.modifiers.ctrl = ctrl;
|
||||||
self.egui_input.modifiers.shift = shift;
|
self.modifiers.shift = shift;
|
||||||
self.egui_input.modifiers.mac_cmd = cfg!(target_os = "macos") && super_;
|
self.modifiers.mac_cmd = cfg!(target_os = "macos") && super_;
|
||||||
self.egui_input.modifiers.command = if cfg!(target_os = "macos") {
|
self.modifiers.command = if cfg!(target_os = "macos") {
|
||||||
super_
|
super_
|
||||||
} else {
|
} else {
|
||||||
ctrl
|
ctrl
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.egui_input
|
||||||
|
.events
|
||||||
|
.push(egui::Event::ModifiersChanged(self.modifiers));
|
||||||
|
|
||||||
EventResponse {
|
EventResponse {
|
||||||
repaint: true,
|
repaint: true,
|
||||||
consumed: false,
|
consumed: false,
|
||||||
@@ -541,7 +557,7 @@ impl State {
|
|||||||
unit: egui::MouseWheelUnit::Point,
|
unit: egui::MouseWheelUnit::Point,
|
||||||
delta: Vec2::new(delta.x, delta.y) / pixels_per_point,
|
delta: Vec2::new(delta.x, delta.y) / pixels_per_point,
|
||||||
phase: to_egui_touch_phase(*phase),
|
phase: to_egui_touch_phase(*phase),
|
||||||
modifiers: self.egui_input.modifiers,
|
modifiers: self.modifiers,
|
||||||
});
|
});
|
||||||
EventResponse {
|
EventResponse {
|
||||||
repaint: true,
|
repaint: true,
|
||||||
@@ -790,7 +806,7 @@ impl State {
|
|||||||
pos,
|
pos,
|
||||||
button,
|
button,
|
||||||
pressed,
|
pressed,
|
||||||
modifiers: self.egui_input.modifiers,
|
modifiers: self.modifiers,
|
||||||
});
|
});
|
||||||
|
|
||||||
if self.simulate_touch_screen {
|
if self.simulate_touch_screen {
|
||||||
@@ -937,7 +953,7 @@ impl State {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
let phase = to_egui_touch_phase(phase);
|
let phase = to_egui_touch_phase(phase);
|
||||||
let modifiers = self.egui_input.modifiers;
|
let modifiers = self.modifiers;
|
||||||
self.egui_input.events.push(egui::Event::MouseWheel {
|
self.egui_input.events.push(egui::Event::MouseWheel {
|
||||||
unit,
|
unit,
|
||||||
delta,
|
delta,
|
||||||
@@ -998,13 +1014,13 @@ impl State {
|
|||||||
// See also: https://github.com/emilk/egui/issues/3653
|
// See also: https://github.com/emilk/egui/issues/3653
|
||||||
if let Some(active_key) = logical_key.or(physical_key) {
|
if let Some(active_key) = logical_key.or(physical_key) {
|
||||||
if pressed {
|
if pressed {
|
||||||
if is_cut_command(self.egui_input.modifiers, active_key) {
|
if is_cut_command(self.modifiers, active_key) {
|
||||||
self.egui_input.events.push(egui::Event::Cut);
|
self.egui_input.events.push(egui::Event::Cut);
|
||||||
return;
|
return;
|
||||||
} else if is_copy_command(self.egui_input.modifiers, active_key) {
|
} else if is_copy_command(self.modifiers, active_key) {
|
||||||
self.egui_input.events.push(egui::Event::Copy);
|
self.egui_input.events.push(egui::Event::Copy);
|
||||||
return;
|
return;
|
||||||
} else if is_paste_command(self.egui_input.modifiers, active_key) {
|
} else if is_paste_command(self.modifiers, active_key) {
|
||||||
if let Some(contents) = self.clipboard.get() {
|
if let Some(contents) = self.clipboard.get() {
|
||||||
let contents = contents.replace("\r\n", "\n");
|
let contents = contents.replace("\r\n", "\n");
|
||||||
if !contents.is_empty() {
|
if !contents.is_empty() {
|
||||||
@@ -1020,7 +1036,7 @@ impl State {
|
|||||||
physical_key,
|
physical_key,
|
||||||
pressed,
|
pressed,
|
||||||
repeat: false, // egui will fill this in for us!
|
repeat: false, // egui will fill this in for us!
|
||||||
modifiers: self.egui_input.modifiers,
|
modifiers: self.modifiers,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1036,9 +1052,8 @@ impl State {
|
|||||||
// We need to ignore these characters that are side-effects of commands.
|
// We need to ignore these characters that are side-effects of commands.
|
||||||
// Also make sure the key is pressed (not released). On Linux, text might
|
// Also make sure the key is pressed (not released). On Linux, text might
|
||||||
// contain some data even when the key is released.
|
// contain some data even when the key is released.
|
||||||
let is_cmd = self.egui_input.modifiers.ctrl
|
let is_cmd =
|
||||||
|| self.egui_input.modifiers.command
|
self.modifiers.ctrl || self.modifiers.command || self.modifiers.mac_cmd;
|
||||||
|| self.egui_input.modifiers.mac_cmd;
|
|
||||||
if pressed && !is_cmd {
|
if pressed && !is_cmd {
|
||||||
self.egui_input
|
self.egui_input
|
||||||
.events
|
.events
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ impl AnimationManager {
|
|||||||
anim.from_value..=anim.to_value,
|
anim.from_value..=anim.to_value,
|
||||||
);
|
);
|
||||||
if anim.to_value != value {
|
if anim.to_value != value {
|
||||||
anim.from_value = current_value; //start new animation from current position of playing animation
|
anim.from_value = current_value; // start new animation from current position of playing animation
|
||||||
anim.to_value = value;
|
anim.to_value = value;
|
||||||
anim.toggle_time = input.time;
|
anim.toggle_time = input.time;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -571,6 +571,7 @@ impl<'a> Popup<'a> {
|
|||||||
.fixed_pos(anchor)
|
.fixed_pos(anchor)
|
||||||
.sense(sense)
|
.sense(sense)
|
||||||
.layout(layout)
|
.layout(layout)
|
||||||
|
.sizing_pass(!was_open_last_frame)
|
||||||
.info(info.unwrap_or_else(|| {
|
.info(info.unwrap_or_else(|| {
|
||||||
UiStackInfo::new(kind.into()).with_tag_value(
|
UiStackInfo::new(kind.into()).with_tag_value(
|
||||||
MenuConfig::MENU_CONFIG_TAG,
|
MenuConfig::MENU_CONFIG_TAG,
|
||||||
|
|||||||
@@ -69,6 +69,9 @@ pub enum Event {
|
|||||||
modifiers: Modifiers,
|
modifiers: Modifiers,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/// The set of held modifier keys changed.
|
||||||
|
ModifiersChanged(Modifiers),
|
||||||
|
|
||||||
/// The mouse or touch moved to a new place.
|
/// The mouse or touch moved to a new place.
|
||||||
PointerMoved(Pos2),
|
PointerMoved(Pos2),
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use crate::{OrderedViewportIdMap, Theme, ViewportId, ViewportIdMap, emath::Rect};
|
use crate::{OrderedViewportIdMap, Theme, ViewportId, ViewportIdMap, emath::Rect};
|
||||||
|
|
||||||
use super::{DroppedFile, Event, HoveredFile, Modifiers, SafeAreaInsets, ViewportInfo};
|
use super::{DroppedFile, Event, HoveredFile, SafeAreaInsets, ViewportInfo};
|
||||||
|
|
||||||
/// What the integrations provides to egui at the start of each frame.
|
/// What the integrations provides to egui at the start of each frame.
|
||||||
///
|
///
|
||||||
@@ -53,9 +53,6 @@ pub struct RawInput {
|
|||||||
/// Can safely be left at its default value.
|
/// Can safely be left at its default value.
|
||||||
pub predicted_dt: f32,
|
pub predicted_dt: f32,
|
||||||
|
|
||||||
/// Which modifier keys are down at the start of the frame?
|
|
||||||
pub modifiers: Modifiers,
|
|
||||||
|
|
||||||
/// In-order events received this frame.
|
/// In-order events received this frame.
|
||||||
///
|
///
|
||||||
/// There is currently no way to know if egui handles a particular event,
|
/// There is currently no way to know if egui handles a particular event,
|
||||||
@@ -92,7 +89,6 @@ impl Default for RawInput {
|
|||||||
max_texture_side: None,
|
max_texture_side: None,
|
||||||
time: None,
|
time: None,
|
||||||
predicted_dt: 1.0 / 60.0,
|
predicted_dt: 1.0 / 60.0,
|
||||||
modifiers: Modifiers::default(),
|
|
||||||
events: vec![],
|
events: vec![],
|
||||||
hovered_files: Default::default(),
|
hovered_files: Default::default(),
|
||||||
dropped_files: Default::default(),
|
dropped_files: Default::default(),
|
||||||
@@ -127,7 +123,6 @@ impl RawInput {
|
|||||||
max_texture_side: self.max_texture_side.take(),
|
max_texture_side: self.max_texture_side.take(),
|
||||||
time: self.time,
|
time: self.time,
|
||||||
predicted_dt: self.predicted_dt,
|
predicted_dt: self.predicted_dt,
|
||||||
modifiers: self.modifiers,
|
|
||||||
events: std::mem::take(&mut self.events),
|
events: std::mem::take(&mut self.events),
|
||||||
hovered_files: self.hovered_files.clone(),
|
hovered_files: self.hovered_files.clone(),
|
||||||
dropped_files: std::mem::take(&mut self.dropped_files),
|
dropped_files: std::mem::take(&mut self.dropped_files),
|
||||||
@@ -145,7 +140,6 @@ impl RawInput {
|
|||||||
max_texture_side,
|
max_texture_side,
|
||||||
time,
|
time,
|
||||||
predicted_dt,
|
predicted_dt,
|
||||||
modifiers,
|
|
||||||
mut events,
|
mut events,
|
||||||
mut hovered_files,
|
mut hovered_files,
|
||||||
mut dropped_files,
|
mut dropped_files,
|
||||||
@@ -160,7 +154,6 @@ impl RawInput {
|
|||||||
self.max_texture_side = max_texture_side.or(self.max_texture_side);
|
self.max_texture_side = max_texture_side.or(self.max_texture_side);
|
||||||
self.time = time; // use latest time
|
self.time = time; // use latest time
|
||||||
self.predicted_dt = predicted_dt; // use latest dt
|
self.predicted_dt = predicted_dt; // use latest dt
|
||||||
self.modifiers = modifiers; // use latest
|
|
||||||
self.events.append(&mut events);
|
self.events.append(&mut events);
|
||||||
self.hovered_files.append(&mut hovered_files);
|
self.hovered_files.append(&mut hovered_files);
|
||||||
self.dropped_files.append(&mut dropped_files);
|
self.dropped_files.append(&mut dropped_files);
|
||||||
@@ -179,7 +172,6 @@ impl RawInput {
|
|||||||
max_texture_side,
|
max_texture_side,
|
||||||
time,
|
time,
|
||||||
predicted_dt,
|
predicted_dt,
|
||||||
modifiers,
|
|
||||||
events,
|
events,
|
||||||
hovered_files,
|
hovered_files,
|
||||||
dropped_files,
|
dropped_files,
|
||||||
@@ -210,7 +202,6 @@ impl RawInput {
|
|||||||
ui.label("time: None");
|
ui.label("time: None");
|
||||||
}
|
}
|
||||||
ui.label(format!("predicted_dt: {:.1} ms", 1e3 * predicted_dt));
|
ui.label(format!("predicted_dt: {:.1} ms", 1e3 * predicted_dt));
|
||||||
ui.label(format!("modifiers: {modifiers:#?}"));
|
|
||||||
ui.label(format!("hovered_files: {}", hovered_files.len()));
|
ui.label(format!("hovered_files: {}", hovered_files.len()));
|
||||||
ui.label(format!("dropped_files: {}", dropped_files.len()));
|
ui.label(format!("dropped_files: {}", dropped_files.len()));
|
||||||
ui.label(format!("focused: {focused}"));
|
ui.label(format!("focused: {focused}"));
|
||||||
|
|||||||
@@ -393,6 +393,7 @@ impl InputState {
|
|||||||
let pointer = self.pointer.begin_pass(time, &new, options);
|
let pointer = self.pointer.begin_pass(time, &new, options);
|
||||||
|
|
||||||
let mut keys_down = self.keys_down;
|
let mut keys_down = self.keys_down;
|
||||||
|
let mut modifiers = self.modifiers;
|
||||||
let mut zoom_factor_delta = 1.0; // TODO(emilk): smoothing for zoom factor
|
let mut zoom_factor_delta = 1.0; // TODO(emilk): smoothing for zoom factor
|
||||||
let mut rotation_radians = 0.0;
|
let mut rotation_radians = 0.0;
|
||||||
|
|
||||||
@@ -429,6 +430,9 @@ impl InputState {
|
|||||||
*modifiers,
|
*modifiers,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Event::ModifiersChanged(new_modifiers) => {
|
||||||
|
modifiers = *new_modifiers;
|
||||||
|
}
|
||||||
Event::Zoom(factor) => {
|
Event::Zoom(factor) => {
|
||||||
zoom_factor_delta *= *factor;
|
zoom_factor_delta *= *factor;
|
||||||
}
|
}
|
||||||
@@ -442,6 +446,7 @@ impl InputState {
|
|||||||
// So we take the safe route and just clear all the keys and modifiers when
|
// So we take the safe route and just clear all the keys and modifiers when
|
||||||
// the app loses focus.
|
// the app loses focus.
|
||||||
keys_down.clear();
|
keys_down.clear();
|
||||||
|
modifiers = Modifiers::default();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@@ -482,7 +487,7 @@ impl InputState {
|
|||||||
predicted_dt: new.predicted_dt,
|
predicted_dt: new.predicted_dt,
|
||||||
stable_dt,
|
stable_dt,
|
||||||
focused: new.focused,
|
focused: new.focused,
|
||||||
modifiers: new.modifiers,
|
modifiers,
|
||||||
keys_down,
|
keys_down,
|
||||||
events: new.events.clone(), // TODO(emilk): remove clone() and use raw.events
|
events: new.events.clone(), // TODO(emilk): remove clone() and use raw.events
|
||||||
raw: new,
|
raw: new,
|
||||||
|
|||||||
@@ -251,14 +251,7 @@ impl<'a, State> Harness<'a, State> {
|
|||||||
self._step(false);
|
self._step(false);
|
||||||
}
|
}
|
||||||
for event in events {
|
for event in events {
|
||||||
match event {
|
self.input.events.push(event);
|
||||||
EventType::Event(event) => {
|
|
||||||
self.input.events.push(event);
|
|
||||||
}
|
|
||||||
EventType::Modifiers(modifiers) => {
|
|
||||||
self.input.modifiers = modifiers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self._step(false);
|
self._step(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -471,7 +464,7 @@ impl<'a, State> Harness<'a, State> {
|
|||||||
|
|
||||||
/// Queue an event to be processed in the next frame.
|
/// Queue an event to be processed in the next frame.
|
||||||
pub fn event(&self, event: egui::Event) {
|
pub fn event(&self, event: egui::Event) {
|
||||||
self.queued_events.lock().push(EventType::Event(event));
|
self.queued_events.lock().push(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Queue an event with modifiers.
|
/// Queue an event with modifiers.
|
||||||
@@ -479,15 +472,15 @@ impl<'a, State> Harness<'a, State> {
|
|||||||
/// Queues the modifiers to be pressed, then the event, then the modifiers to be released.
|
/// Queues the modifiers to be pressed, then the event, then the modifiers to be released.
|
||||||
pub fn event_modifiers(&self, event: egui::Event, modifiers: Modifiers) {
|
pub fn event_modifiers(&self, event: egui::Event, modifiers: Modifiers) {
|
||||||
let mut queue = self.queued_events.lock();
|
let mut queue = self.queued_events.lock();
|
||||||
queue.push(EventType::Modifiers(modifiers));
|
queue.push(egui::Event::ModifiersChanged(modifiers));
|
||||||
queue.push(EventType::Event(event));
|
queue.push(event);
|
||||||
queue.push(EventType::Modifiers(Modifiers::default()));
|
queue.push(egui::Event::ModifiersChanged(Modifiers::default()));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modifiers(&self, modifiers: Modifiers) {
|
fn modifiers(&self, modifiers: Modifiers) {
|
||||||
self.queued_events
|
self.queued_events
|
||||||
.lock()
|
.lock()
|
||||||
.push(EventType::Modifiers(modifiers));
|
.push(egui::Event::ModifiersChanged(modifiers));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn key_down(&self, key: egui::Key) {
|
pub fn key_down(&self, key: egui::Key) {
|
||||||
@@ -735,7 +728,11 @@ impl<'a, State> Harness<'a, State> {
|
|||||||
|
|
||||||
/// The root node of the test harness.
|
/// The root node of the test harness.
|
||||||
pub fn root(&self) -> Node<'_> {
|
pub fn root(&self) -> Node<'_> {
|
||||||
Node::new(self.kittest.root(), &self.queued_events, self.ctx.pixels_per_point())
|
Node::new(
|
||||||
|
self.kittest.root(),
|
||||||
|
&self.queued_events,
|
||||||
|
self.ctx.pixels_per_point(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Spawn a real native eframe window running this harness's app, reusing its [`egui::Context`].
|
/// Spawn a real native eframe window running this harness's app, reusing its [`egui::Context`].
|
||||||
|
|||||||
@@ -4,16 +4,7 @@ use egui::{Modifiers, PointerButton, Pos2, accesskit};
|
|||||||
use kittest::{AccessKitNode, NodeT, debug_fmt_node};
|
use kittest::{AccessKitNode, NodeT, debug_fmt_node};
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
|
|
||||||
/// Modifiers aren't part of [`egui::Event`] and must be handled by the integration, so we need
|
pub type EventQueue = Mutex<Vec<egui::Event>>;
|
||||||
/// an enum to handle these.
|
|
||||||
///
|
|
||||||
/// The most recent [`Self::Modifiers`] should always be passed to [`egui::RawInput`].
|
|
||||||
pub enum EventType {
|
|
||||||
Event(egui::Event),
|
|
||||||
Modifiers(Modifiers),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type EventQueue = Mutex<Vec<EventType>>;
|
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub struct Node<'tree> {
|
pub struct Node<'tree> {
|
||||||
@@ -40,20 +31,26 @@ impl<'tree> NodeT<'tree> for Node<'tree> {
|
|||||||
|
|
||||||
impl<'tree> Node<'tree> {
|
impl<'tree> Node<'tree> {
|
||||||
/// Construct a new accesskit node
|
/// Construct a new accesskit node
|
||||||
pub fn new(accesskit_node: AccessKitNode<'tree>, queue: &'tree EventQueue, pixels_per_point: f32) -> Self {
|
pub fn new(
|
||||||
|
accesskit_node: AccessKitNode<'tree>,
|
||||||
|
queue: &'tree EventQueue,
|
||||||
|
pixels_per_point: f32,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
queue,
|
|
||||||
accesskit_node,
|
accesskit_node,
|
||||||
|
queue,
|
||||||
pixels_per_point,
|
pixels_per_point,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn event(&self, event: egui::Event) {
|
fn event(&self, event: egui::Event) {
|
||||||
self.queue.lock().push(EventType::Event(event));
|
self.queue.lock().push(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modifiers(&self, modifiers: Modifiers) {
|
fn modifiers(&self, modifiers: Modifiers) {
|
||||||
self.queue.lock().push(EventType::Modifiers(modifiers));
|
self.queue
|
||||||
|
.lock()
|
||||||
|
.push(egui::Event::ModifiersChanged(modifiers));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn hover(&self) {
|
pub fn hover(&self) {
|
||||||
|
|||||||
@@ -1,5 +1,72 @@
|
|||||||
|
use egui::{Align, Layout, Popup};
|
||||||
|
use egui_kittest::Harness;
|
||||||
use kittest::Queryable as _;
|
use kittest::Queryable as _;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reopened_popup_resizes_for_wider_items() {
|
||||||
|
const POPUP_BUTTON: &str = "Dynamic popup";
|
||||||
|
const SHORT_ITEM: &str = "Short item";
|
||||||
|
const WIDE_ITEM: &str = "Newly added item with a much wider label";
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct State {
|
||||||
|
open: bool,
|
||||||
|
show_wide_item: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut harness = Harness::builder()
|
||||||
|
.with_size(egui::Vec2::new(500.0, 300.0))
|
||||||
|
.build_ui_state(
|
||||||
|
|ui, state| {
|
||||||
|
let response = ui.button(POPUP_BUTTON);
|
||||||
|
if response.clicked() {
|
||||||
|
state.open = !state.open;
|
||||||
|
}
|
||||||
|
|
||||||
|
Popup::from_response(&response)
|
||||||
|
.open(state.open)
|
||||||
|
.layout(Layout::top_down_justified(Align::Min))
|
||||||
|
.show(|ui| {
|
||||||
|
_ = ui.selectable_label(false, SHORT_ITEM);
|
||||||
|
_ = ui.selectable_label(false, "Another short item");
|
||||||
|
if state.show_wide_item {
|
||||||
|
_ = ui.selectable_label(false, WIDE_ITEM);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
State::default(),
|
||||||
|
);
|
||||||
|
|
||||||
|
harness.get_by_label(POPUP_BUTTON).click();
|
||||||
|
harness.run();
|
||||||
|
let initial_row_size = harness.get_by_label(SHORT_ITEM).rect().size();
|
||||||
|
|
||||||
|
harness.get_by_label(POPUP_BUTTON).click();
|
||||||
|
harness.run();
|
||||||
|
assert!(harness.query_by_label(SHORT_ITEM).is_none());
|
||||||
|
|
||||||
|
harness.state_mut().show_wide_item = true;
|
||||||
|
harness.run();
|
||||||
|
harness.get_by_label(POPUP_BUTTON).click();
|
||||||
|
harness.run();
|
||||||
|
|
||||||
|
let reopened_row_size = harness.get_by_label(SHORT_ITEM).rect().size();
|
||||||
|
let wide_row_size = harness.get_by_label(WIDE_ITEM).rect().size();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
reopened_row_size.x > initial_row_size.x,
|
||||||
|
"reopened row width ({}) did not grow beyond its initial width ({})",
|
||||||
|
reopened_row_size.x,
|
||||||
|
initial_row_size.x
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
wide_row_size.y <= initial_row_size.y + 0.5,
|
||||||
|
"new row height ({}) exceeds the single-line row height ({})",
|
||||||
|
wide_row_size.y,
|
||||||
|
initial_row_size.y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_interactive_tooltip() {
|
fn test_interactive_tooltip() {
|
||||||
struct State {
|
struct State {
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ impl CubicBezierShape {
|
|||||||
|
|
||||||
/// Logical bounding rectangle (ignoring stroke width)
|
/// Logical bounding rectangle (ignoring stroke width)
|
||||||
pub fn logical_bounding_rect(&self) -> Rect {
|
pub fn logical_bounding_rect(&self) -> Rect {
|
||||||
//temporary solution
|
// temporary solution
|
||||||
let (mut min_x, mut max_x) = if self.points[0].x < self.points[3].x {
|
let (mut min_x, mut max_x) = if self.points[0].x < self.points[3].x {
|
||||||
(self.points[0].x, self.points[3].x)
|
(self.points[0].x, self.points[3].x)
|
||||||
} else {
|
} else {
|
||||||
@@ -793,7 +793,7 @@ mod tests {
|
|||||||
assert!((bbox.max.x - 180.0).abs() < 0.01);
|
assert!((bbox.max.x - 180.0).abs() < 0.01);
|
||||||
assert!((bbox.max.y - 170.0).abs() < 0.01);
|
assert!((bbox.max.y - 170.0).abs() < 0.01);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.1, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.1, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
@@ -817,7 +817,7 @@ mod tests {
|
|||||||
assert!((bbox.max.x - 130.42).abs() < 0.01);
|
assert!((bbox.max.x - 130.42).abs() < 0.01);
|
||||||
assert!((bbox.max.y - 170.0).abs() < 0.01);
|
assert!((bbox.max.y - 170.0).abs() < 0.01);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.1, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.1, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
@@ -837,28 +837,28 @@ mod tests {
|
|||||||
fill: Default::default(),
|
fill: Default::default(),
|
||||||
stroke: Default::default(),
|
stroke: Default::default(),
|
||||||
};
|
};
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(1.0, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(1.0, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 9);
|
assert_eq!(result.len(), 9);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.1, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.1, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 25);
|
assert_eq!(result.len(), 25);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 77);
|
assert_eq!(result.len(), 77);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.001, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.001, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
@@ -938,35 +938,35 @@ mod tests {
|
|||||||
stroke: Default::default(),
|
stroke: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(1.0, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(1.0, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 10);
|
assert_eq!(result.len(), 10);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.5, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.5, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 13);
|
assert_eq!(result.len(), 13);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.1, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.1, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 28);
|
assert_eq!(result.len(), 28);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 83);
|
assert_eq!(result.len(), 83);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.001, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.001, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
@@ -988,7 +988,7 @@ mod tests {
|
|||||||
stroke: Default::default(),
|
stroke: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
@@ -1007,7 +1007,7 @@ mod tests {
|
|||||||
stroke: Default::default(),
|
stroke: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
@@ -1026,7 +1026,7 @@ mod tests {
|
|||||||
stroke: Default::default(),
|
stroke: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
@@ -1045,7 +1045,7 @@ mod tests {
|
|||||||
stroke: Default::default(),
|
stroke: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
@@ -1064,7 +1064,7 @@ mod tests {
|
|||||||
stroke: Default::default(),
|
stroke: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
@@ -1083,7 +1083,7 @@ mod tests {
|
|||||||
stroke: Default::default(),
|
stroke: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
@@ -1100,34 +1100,34 @@ mod tests {
|
|||||||
stroke: Default::default(),
|
stroke: Default::default(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(1.0, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(1.0, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 9);
|
assert_eq!(result.len(), 9);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.5, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.5, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 11);
|
assert_eq!(result.len(), 11);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.1, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.1, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 24);
|
assert_eq!(result.len(), 24);
|
||||||
|
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.01, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_eq!(result.len(), 72);
|
assert_eq!(result.len(), 72);
|
||||||
let mut result = vec![curve.points[0]]; //add the start point
|
let mut result = vec![curve.points[0]]; // add the start point
|
||||||
curve.for_each_flattened_with_t(0.001, &mut |pos, _t| {
|
curve.for_each_flattened_with_t(0.001, &mut |pos, _t| {
|
||||||
result.push(pos);
|
result.push(pos);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ ignore = [
|
|||||||
"RUSTSEC-2026-0192", # ttf-parser is unmaintained. Only brought in via winit/sctk-adwaita (wayland window frame rendering)
|
"RUSTSEC-2026-0192", # ttf-parser is unmaintained. Only brought in via winit/sctk-adwaita (wayland window frame rendering)
|
||||||
"RUSTSEC-2026-0194", # quick-xml DoS - fix is in >=0.41, but held back transitively by zbus_xml (accesskit) and wayland-scanner (winit)
|
"RUSTSEC-2026-0194", # quick-xml DoS - fix is in >=0.41, but held back transitively by zbus_xml (accesskit) and wayland-scanner (winit)
|
||||||
"RUSTSEC-2026-0195", # quick-xml DoS - same as above
|
"RUSTSEC-2026-0195", # quick-xml DoS - same as above
|
||||||
|
"RUSTSEC-2026-0206", # rustybuzz is unmaintained. Brought in via resvg. TODO(linebender/resvg#922): Remove once the PR lands and is released
|
||||||
]
|
]
|
||||||
|
|
||||||
[bans]
|
[bans]
|
||||||
|
|||||||
Reference in New Issue
Block a user