I'm implementing a Rust alternative to .NET's DragMove method however the result causes the application to flicker between two relative positions.
See screencast and sample project.
Code I'm using to perform the drag move:
let mut mouse_down = false;
let mut last_pos: Option<PhysicalPosition<f64>> = None;
event_loop.run(move |event, _, control_flow| match event {
Event::WindowEvent {
event: WindowEvent::CursorMoved {
position,
..
},
..
} => {
let gl_window = display.gl_window();
let window = gl_window.window();
if mouse_down {
if last_pos.is_some() {
let previous_pos = last_pos.unwrap();
let delta_x = previous_pos.x - position.x;
let delta_y = previous_pos.y - position.y;
window.set_outer_position(PhysicalPosition::new(position.x + delta_x, position.y + delta_y));
}
last_pos = Some(position);
}
}
Event::WindowEvent {
event: WindowEvent::MouseInput{
state,
button,
..
},
..
} => {
mouse_down = button == MouseButton::Left && state == ElementState::Pressed;
if !mouse_down {
last_pos = None;
}
}
_ => {}
});
CursorMoved reports
When you're later using that position to
set_outer_position
, you are essentially reinterpreting window-relative coordinates as screen-relative.You should instead apply the offset to the position returned from outer_position.
While that fixes the immediate problem, I'm not sure it is enough to account for the window movement. When you're handling the next
CursorMoved
event, the coordinates are still window-relative, but the window has since moved. That may produce artifacts all over.A more robust solution would store the window's position when the drag-move operation starts, and offset that position by the accumulated deltas.