Skip to content

Commit

Permalink
Merge branch 'master' into patch22
Browse files Browse the repository at this point in the history
  • Loading branch information
rustbasic authored May 23, 2024
2 parents d7c754e + a98c42e commit 19bf8c8
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 82 deletions.
30 changes: 0 additions & 30 deletions crates/eframe/src/web/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,36 +503,6 @@ pub(crate) fn install_canvas_events(runner_ref: &WebRunner) -> Result<(), JsValu
modifiers,
});

let scroll_multiplier = match unit {
egui::MouseWheelUnit::Page => {
canvas_size_in_points(runner.canvas(), runner.egui_ctx()).y
}
egui::MouseWheelUnit::Line => {
#[allow(clippy::let_and_return)]
let points_per_scroll_line = 8.0; // Note that this is intentionally different from what we use in winit.
points_per_scroll_line
}
egui::MouseWheelUnit::Point => 1.0,
};

let mut delta = scroll_multiplier * delta;

// Report a zoom event in case CTRL (on Windows or Linux) or CMD (on Mac) is pressed.
// This if-statement is equivalent to how `Modifiers.command` is determined in
// `modifiers_from_kb_event()`, but we cannot directly use that fn for a [`WheelEvent`].
if event.ctrl_key() || event.meta_key() {
let factor = (delta.y / 200.0).exp();
runner.input.raw.events.push(egui::Event::Zoom(factor));
} else {
if event.shift_key() {
// Treat as horizontal scrolling.
// Note: one Mac we already get horizontal scroll events when shift is down.
delta = egui::vec2(delta.x + delta.y, 0.0);
}

runner.input.raw.events.push(egui::Event::Scroll(delta));
}

runner.needs_repaint.repaint_asap();
event.stop_propagation();
event.prevent_default();
Expand Down
23 changes: 0 additions & 23 deletions crates/egui-winit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,29 +694,6 @@ impl State {
modifiers,
});
}
let delta = match delta {
winit::event::MouseScrollDelta::LineDelta(x, y) => {
let points_per_scroll_line = 50.0; // Scroll speed decided by consensus: https://github.com/emilk/egui/issues/461
egui::vec2(x, y) * points_per_scroll_line
}
winit::event::MouseScrollDelta::PixelDelta(delta) => {
egui::vec2(delta.x as f32, delta.y as f32) / pixels_per_point
}
};

if self.egui_input.modifiers.ctrl || self.egui_input.modifiers.command {
// Treat as zoom instead:
let factor = (delta.y / 200.0).exp();
self.egui_input.events.push(egui::Event::Zoom(factor));
} else if self.egui_input.modifiers.shift {
// Treat as horizontal scrolling.
// Note: one Mac we already get horizontal scroll events when shift is down.
self.egui_input
.events
.push(egui::Event::Scroll(egui::vec2(delta.x + delta.y, 0.0)));
} else {
self.egui_input.events.push(egui::Event::Scroll(delta));
}
}

fn on_keyboard_input(&mut self, event: &winit::event::KeyEvent) {
Expand Down
1 change: 1 addition & 0 deletions crates/egui/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,7 @@ impl ContextImpl {
new_raw_input,
viewport.repaint.requested_immediate_repaint_prev_frame(),
pixels_per_point,
&self.memory.options,
);

let screen_rect = viewport.input.screen_rect;
Expand Down
35 changes: 13 additions & 22 deletions crates/egui/src/data/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,21 +530,6 @@ pub enum Event {
/// On touch-up first send `PointerButton{pressed: false, …}` followed by `PointerLeft`.
PointerGone,

/// How many points (logical pixels) the user scrolled.
///
/// The direction of the vector indicates how to move the _content_ that is being viewed.
/// So if you get positive values, the content being viewed should move to the right and down,
/// revealing new things to the left and up.
///
/// A positive X-value indicates the content is being moved right,
/// as when swiping right on a touch-screen or track-pad with natural scrolling.
///
/// A positive Y-value indicates the content is being moved down,
/// as when swiping down on a touch-screen or track-pad with natural scrolling.
///
/// Shift-scroll should result in horizontal scrolling (it is up to the integrations to do this).
Scroll(Vec2),

/// Zoom scale factor this frame (e.g. from ctrl-scroll or pinch gesture).
/// * `zoom = 1`: no change.
/// * `zoom < 1`: pinch together
Expand Down Expand Up @@ -577,16 +562,22 @@ pub enum Event {
force: Option<f32>,
},

/// A raw mouse wheel event as sent by the backend (minus the z coordinate),
/// for implementing alternative custom controls.
/// Note that the same event can also trigger [`Self::Zoom`] and [`Self::Scroll`],
/// so you probably want to handle only one of them.
/// A raw mouse wheel event as sent by the backend.
///
/// Used for scrolling.
MouseWheel {
/// The unit of scrolling: points, lines, or pages.
/// The unit of `delta`: points, lines, or pages.
unit: MouseWheelUnit,

/// The amount scrolled horizontally and vertically. The amount and direction corresponding
/// to one step of the wheel depends on the platform.
/// The direction of the vector indicates how to move the _content_ that is being viewed.
/// So if you get positive values, the content being viewed should move to the right and down,
/// revealing new things to the left and up.
///
/// A positive X-value indicates the content is being moved right,
/// as when swiping right on a touch-screen or track-pad with natural scrolling.
///
/// A positive Y-value indicates the content is being moved down,
/// as when swiping down on a touch-screen or track-pad with natural scrolling.
delta: Vec2,

/// The state of the modifier keys at the time of the event.
Expand Down
106 changes: 99 additions & 7 deletions crates/egui/src/input_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ pub struct InputState {
/// Used for smoothing the scroll delta.
unprocessed_scroll_delta: Vec2,

/// Used for smoothing the scroll delta when zooming.
unprocessed_scroll_delta_for_zoom: f32,

/// You probably want to use [`Self::smooth_scroll_delta`] instead.
///
/// The raw input of how many points the user scrolled.
///
/// The delta dictates how the _content_ should move.
Expand Down Expand Up @@ -152,6 +157,7 @@ impl Default for InputState {
pointer: Default::default(),
touch_states: Default::default(),
unprocessed_scroll_delta: Vec2::ZERO,
unprocessed_scroll_delta_for_zoom: 0.0,
raw_scroll_delta: Vec2::ZERO,
smooth_scroll_delta: Vec2::ZERO,
zoom_factor_delta: 1.0,
Expand All @@ -177,6 +183,7 @@ impl InputState {
mut new: RawInput,
requested_immediate_repaint_prev_frame: bool,
pixels_per_point: f32,
options: &crate::Options,
) -> Self {
crate::profile_function!();

Expand All @@ -198,9 +205,15 @@ impl InputState {
}
let pointer = self.pointer.clone().begin_frame(time, &new);

let mut keys_down = self.keys_down.clone();
let mut keys_down = self.keys_down;
let mut zoom_factor_delta = 1.0; // TODO(emilk): smoothing for zoom factor
let mut raw_scroll_delta = Vec2::ZERO;
let mut zoom_factor_delta = 1.0;

let mut unprocessed_scroll_delta = self.unprocessed_scroll_delta;
let mut unprocessed_scroll_delta_for_zoom = self.unprocessed_scroll_delta_for_zoom;
let mut smooth_scroll_delta = Vec2::ZERO;
let mut smooth_scroll_delta_for_zoom = 0.0;

for event in &mut new.events {
match event {
Event::Key {
Expand All @@ -216,8 +229,51 @@ impl InputState {
keys_down.remove(key);
}
}
Event::Scroll(delta) => {
raw_scroll_delta += *delta;
Event::MouseWheel {
unit,
delta,
modifiers,
} => {
let mut delta = match unit {
MouseWheelUnit::Point => *delta,
MouseWheelUnit::Line => options.line_scroll_speed * *delta,
MouseWheelUnit::Page => screen_rect.height() * *delta,
};

if modifiers.shift {
// Treat as horizontal scrolling.
// Note: one Mac we already get horizontal scroll events when shift is down.
delta = vec2(delta.x + delta.y, 0.0);
}

raw_scroll_delta += delta;

// Mouse wheels often go very large steps.
// A single notch on a logitech mouse wheel connected to a Macbook returns 14.0 raw_scroll_delta.
// So we smooth it out over several frames for a nicer user experience when scrolling in egui.
// BUT: if the user is using a nice smooth mac trackpad, we don't add smoothing,
// because it adds latency.
let is_smooth = match unit {
MouseWheelUnit::Point => delta.length() < 8.0, // a bit arbitrary here
MouseWheelUnit::Line | MouseWheelUnit::Page => false,
};

let is_zoom = modifiers.ctrl || modifiers.mac_cmd || modifiers.command;

#[allow(clippy::collapsible_else_if)]
if is_zoom {
if is_smooth {
smooth_scroll_delta_for_zoom += delta.y;
} else {
unprocessed_scroll_delta_for_zoom += delta.y;
}
} else {
if is_smooth {
smooth_scroll_delta += delta;
} else {
unprocessed_scroll_delta += delta;
}
}
}
Event::Zoom(factor) => {
zoom_factor_delta *= *factor;
Expand All @@ -226,13 +282,44 @@ impl InputState {
}
}

self.smooth_scroll_delta = Vec2::ZERO;
self.create_scroll_delta(true, false);
{
let dt = stable_dt.at_most(0.1);
let t = crate::emath::exponential_smooth_factor(0.90, 0.1, dt); // reach _% in _ seconds. TODO(emilk): parameterize

if unprocessed_scroll_delta != Vec2::ZERO {
for d in 0..2 {
if unprocessed_scroll_delta[d].abs() < 1.0 {
smooth_scroll_delta[d] += unprocessed_scroll_delta[d];
unprocessed_scroll_delta[d] = 0.0;
} else {
let applied = t * unprocessed_scroll_delta[d];
smooth_scroll_delta[d] += applied;
unprocessed_scroll_delta[d] -= applied;
}
}
}

{
// Smooth scroll-to-zoom:
if unprocessed_scroll_delta_for_zoom.abs() < 1.0 {
smooth_scroll_delta_for_zoom += unprocessed_scroll_delta_for_zoom;
unprocessed_scroll_delta_for_zoom = 0.0;
} else {
let applied = t * unprocessed_scroll_delta_for_zoom;
smooth_scroll_delta_for_zoom += applied;
unprocessed_scroll_delta_for_zoom -= applied;
}

zoom_factor_delta *=
(options.scroll_zoom_speed * smooth_scroll_delta_for_zoom).exp();
}
}

Self {
pointer,
touch_states: self.touch_states,
unprocessed_scroll_delta: self.unprocessed_scroll_delta,
unprocessed_scroll_delta,
unprocessed_scroll_delta_for_zoom,
raw_scroll_delta,
smooth_scroll_delta: self.smooth_scroll_delta,
zoom_factor_delta,
Expand Down Expand Up @@ -345,6 +432,7 @@ impl InputState {
pub fn wants_repaint(&self) -> bool {
self.pointer.wants_repaint()
|| self.unprocessed_scroll_delta.abs().max_elem() > 0.2
|| self.unprocessed_scroll_delta_for_zoom.abs() > 0.2
|| !self.events.is_empty()

// We need to wake up and check for press-and-hold for the context menu.
Expand Down Expand Up @@ -1155,6 +1243,7 @@ impl InputState {
touch_states,

unprocessed_scroll_delta,
unprocessed_scroll_delta_for_zoom,
raw_scroll_delta,
smooth_scroll_delta,

Expand Down Expand Up @@ -1196,6 +1285,9 @@ impl InputState {
ui.label(format!(
"unprocessed_scroll_delta: {unprocessed_scroll_delta:?} points"
));
ui.label(format!(
"unprocessed_scroll_delta_for_zoom: {unprocessed_scroll_delta_for_zoom:?} points"
));
}
ui.label(format!("raw_scroll_delta: {raw_scroll_delta:?} points"));
ui.label(format!(
Expand Down
44 changes: 44 additions & 0 deletions crates/egui/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,10 +231,26 @@ pub struct Options {
///
/// By default this is `true` in debug builds.
pub warn_on_id_clash: bool,

// ------------------------------
// Input:
/// Multiplier for the scroll speed when reported in [`crate::MouseWheelUnit::Line`]s.
pub line_scroll_speed: f32,

/// Controls the speed at which we zoom in when doing ctrl/cmd + scroll.
pub scroll_zoom_speed: f32,
}

impl Default for Options {
fn default() -> Self {
// TODO(emilk): figure out why these constants need to be different on web and on native (winit).
let is_web = cfg!(target_arch = "wasm32");
let line_scroll_speed = if is_web {
8.0
} else {
40.0 // Scroll speed decided by consensus: https://github.com/emilk/egui/issues/461
};

Self {
style: Default::default(),
zoom_factor: 1.0,
Expand All @@ -245,6 +261,10 @@ impl Default for Options {
screen_reader: false,
preload_font_glyphs: true,
warn_on_id_clash: cfg!(debug_assertions),

// Input:
line_scroll_speed,
scroll_zoom_speed: 1.0 / 200.0,
}
}
}
Expand All @@ -262,6 +282,9 @@ impl Options {
screen_reader: _, // needs to come from the integration
preload_font_glyphs: _,
warn_on_id_clash,

line_scroll_speed,
scroll_zoom_speed,
} = self;

use crate::Widget as _;
Expand Down Expand Up @@ -300,6 +323,27 @@ impl Options {
});
});

CollapsingHeader::new("🖱 Input")
.default_open(false)
.show(ui, |ui| {
ui.horizontal(|ui| {
ui.label("Line scroll speed");
ui.add(
crate::DragValue::new(line_scroll_speed).clamp_range(0.0..=f32::INFINITY),
)
.on_hover_text("How many lines to scroll with each tick of the mouse wheel");
});
ui.horizontal(|ui| {
ui.label("Scroll zoom speed");
ui.add(
crate::DragValue::new(scroll_zoom_speed)
.clamp_range(0.0..=f32::INFINITY)
.speed(0.001),
)
.on_hover_text("How fast to zoom with ctrl/cmd + scroll");
});
});

ui.vertical_centered(|ui| crate::reset_button(ui, self, "Reset all"));
}
}
Expand Down

0 comments on commit 19bf8c8

Please sign in to comment.