rewrite the mouse handling to handle upstream bugs somewhat better. Still haven't found the crash yet

macos-click-through
Keith Simmons 3 years ago
parent 76237c6d47
commit 59fa3ed2a9

@ -100,6 +100,10 @@ impl Corner {
} }
} }
if self.length_multiplier < 0.25 {
println!("{}", self.length_multiplier);
}
// Check first if animation's over // Check first if animation's over
if (self.t - 1.0).abs() < std::f32::EPSILON { if (self.t - 1.0).abs() < std::f32::EPSILON {
return false; return false;
@ -109,8 +113,7 @@ impl Corner {
let relative_scaled_position: Point = ( let relative_scaled_position: Point = (
self.relative_position.x * font_dimensions.x, self.relative_position.x * font_dimensions.x,
self.relative_position.y * font_dimensions.y, self.relative_position.y * font_dimensions.y,
) ).into();
.into();
let corner_destination = destination + relative_scaled_position; let corner_destination = destination + relative_scaled_position;

@ -119,6 +119,7 @@ pub struct RenderedWindow {
scroll_t: f32, scroll_t: f32,
} }
#[derive(Clone)]
pub struct WindowDrawDetails { pub struct WindowDrawDetails {
pub id: u64, pub id: u64,
pub region: Rect, pub region: Rect,

@ -3,8 +3,7 @@ use glutin::{
WindowedContext, WindowedContext,
dpi::{ dpi::{
LogicalPosition, LogicalPosition,
LogicalSize, PhysicalPosition,
PhysicalSize
}, },
event::{ event::{
ElementState, ElementState,
@ -18,13 +17,13 @@ use glutin::{
use crate::channel_utils::LoggingTx; use crate::channel_utils::LoggingTx;
use crate::bridge::UiCommand; use crate::bridge::UiCommand;
use crate::renderer::Renderer; use crate::renderer::{Renderer, WindowDrawDetails};
pub struct MouseManager { pub struct MouseManager {
command_sender: LoggingTx<UiCommand>, command_sender: LoggingTx<UiCommand>,
button_down: bool, dragging: bool,
position: LogicalPosition<u32>, position: LogicalPosition<u32>,
grid_id_under_mouse: u64, window_details_under_mouse: Option<WindowDrawDetails>,
pub enabled: bool, pub enabled: bool,
} }
@ -32,9 +31,9 @@ impl MouseManager {
pub fn new(command_sender: LoggingTx<UiCommand>) -> MouseManager { pub fn new(command_sender: LoggingTx<UiCommand>) -> MouseManager {
MouseManager { MouseManager {
command_sender, command_sender,
button_down: false, dragging: false,
position: LogicalPosition::new(0, 0), position: LogicalPosition::new(0, 0),
grid_id_under_mouse: 0, window_details_under_mouse: None,
enabled: true, enabled: true,
} }
} }
@ -45,76 +44,90 @@ impl MouseManager {
return; return;
} }
let previous_position = self.position; let logical_position: LogicalPosition<u32> = PhysicalPosition::new(x as u32, y as u32)
let logical_position: LogicalSize<u32> = PhysicalSize::new(x as u32, y as u32)
.to_logical(windowed_context.window().scale_factor()); .to_logical(windowed_context.window().scale_factor());
let mut top_window_position = (0.0, 0.0); // If dragging, the relevant window (the one which we send all commands to) is the one
let mut top_grid_position = None; // which the mouse drag started on. Otherwise its the top rendered window
let relevant_window_details = if self.dragging {
for details in renderer.window_regions.iter() { renderer.window_regions.iter()
if logical_position.width >= details.region.left as u32 .find(|details| details.id == self.window_details_under_mouse.as_ref().expect("If dragging, there should be a window details recorded").id)
&& logical_position.width < details.region.right as u32 } else {
&& logical_position.height >= details.region.top as u32 // the rendered window regions are sorted by draw order, so the earlier windows in the
&& logical_position.height < details.region.bottom as u32 // list are drawn under the later ones
{ renderer.window_regions.iter().filter(|details| {
top_window_position = (details.region.left, details.region.top); logical_position.x >= details.region.left as u32 &&
top_grid_position = Some(( logical_position.x < details.region.right as u32 &&
details.id, logical_position.y >= details.region.top as u32 &&
LogicalSize::<u32>::new( logical_position.y < details.region.bottom as u32
logical_position.width - details.region.left as u32, }).last()
logical_position.height - details.region.top as u32, };
),
details.floating_order.is_some(),
));
}
}
if let Some((grid_id, grid_position, grid_floating)) = top_grid_position {
self.grid_id_under_mouse = grid_id;
self.position = LogicalPosition::new(
(grid_position.width as u64 / renderer.font_width) as u32,
(grid_position.height as u64 / renderer.font_height) as u32,
);
if self.enabled && self.button_down && previous_position != self.position {
let (window_left, window_top) = top_window_position;
// Until https://github.com/neovim/neovim/pull/12667 is merged, we have to special
// case non floating windows. Floating windows correctly transform mouse positions
// into grid coordinates, but non floating windows do not.
let position = if grid_floating {
(self.position.x, self.position.y)
} else {
let adjusted_drag_left = self.position.x
+ (window_left / renderer.font_width as f32) as u32;
let adjusted_drag_top = self.position.y
+ (window_top / renderer.font_height as f32) as u32;
(adjusted_drag_left, adjusted_drag_top)
};
if let Some(relevant_window_details) = relevant_window_details {
let previous_position = self.position;
// Until https://github.com/neovim/neovim/pull/12667 is merged, we have to special
// case non floating windows. Floating windows correctly transform mouse positions
// into grid coordinates, but non floating windows do not.
self.position = if relevant_window_details.floating_order.is_some() {
// Floating windows handle relative grid coordinates just fine
LogicalPosition::new(
(logical_position.x - relevant_window_details.region.left as u32) / renderer.font_width as u32,
(logical_position.y - relevant_window_details.region.top as u32) / renderer.font_height as u32,
)
} else {
// Non floating windows need global coordinates
LogicalPosition::new(
logical_position.x / renderer.font_width as u32,
logical_position.y / renderer.font_height as u32
)
};
// If dragging and we haven't already sent a position, send a drag command
if self.dragging && self.position != previous_position {
let window_id_to_send_to = self.window_details_under_mouse.as_ref().map(|details| details.id).unwrap_or(0);
self.command_sender self.command_sender
.send(UiCommand::Drag { .send(UiCommand::Drag {
grid_id: self.grid_id_under_mouse, grid_id: window_id_to_send_to,
position, position: self.position.into(),
}) })
.ok(); .ok();
} else {
// otherwise, update the window_id_under_mouse to match the one selected
self.window_details_under_mouse = Some(relevant_window_details.clone());
} }
} }
} }
fn handle_pointer_down(&mut self) { fn handle_pointer_down(&mut self, renderer: &Renderer) {
if self.enabled { // For some reason pointer down is handled differently from pointer up and drag.
self.command_sender // Floating windows: relative coordinates are great.
.send(UiCommand::MouseButton { // Non floating windows: rather than global coordinates, relative are needed
action: String::from("press"), if self.enabled {
grid_id: self.grid_id_under_mouse, if let Some(details) = &self.window_details_under_mouse {
position: (self.position.x, self.position.y), if details.floating_order.is_some() {
}) self.command_sender
.ok(); .send(UiCommand::MouseButton {
action: String::from("press"),
grid_id: details.id,
position: (self.position.x, self.position.y),
})
.ok();
} else {
let relative_position = (
self.position.x - (details.region.left as u64 / renderer.font_width) as u32,
self.position.y - (details.region.top as u64 / renderer.font_height) as u32,
);
self.command_sender
.send(UiCommand::MouseButton {
action: String::from("press"),
grid_id: details.id,
position: relative_position,
})
.ok();
}
}
} }
self.button_down = true; self.dragging = true;
} }
fn handle_pointer_up(&mut self) { fn handle_pointer_up(&mut self) {
@ -122,12 +135,12 @@ impl MouseManager {
self.command_sender self.command_sender
.send(UiCommand::MouseButton { .send(UiCommand::MouseButton {
action: String::from("release"), action: String::from("release"),
grid_id: self.grid_id_under_mouse, grid_id: self.window_details_under_mouse.as_ref().map(|details| details.id).unwrap_or(0),
position: (self.position.x, self.position.y), position: (self.position.x, self.position.y),
}) })
.ok(); .ok();
} }
self.button_down = false; self.dragging = false;
} }
fn handle_mouse_wheel(&mut self, x: f32, y: f32) { fn handle_mouse_wheel(&mut self, x: f32, y: f32) {
@ -145,7 +158,7 @@ impl MouseManager {
self.command_sender self.command_sender
.send(UiCommand::Scroll { .send(UiCommand::Scroll {
direction: input_type.to_string(), direction: input_type.to_string(),
grid_id: self.grid_id_under_mouse, grid_id: self.window_details_under_mouse.as_ref().map(|details| details.id).unwrap_or(0),
position: (self.position.x, self.position.y), position: (self.position.x, self.position.y),
}) })
.ok(); .ok();
@ -161,7 +174,7 @@ impl MouseManager {
self.command_sender self.command_sender
.send(UiCommand::Scroll { .send(UiCommand::Scroll {
direction: input_type.to_string(), direction: input_type.to_string(),
grid_id: self.grid_id_under_mouse, grid_id: self.window_details_under_mouse.as_ref().map(|details| details.id).unwrap_or(0),
position: (self.position.x, self.position.y), position: (self.position.x, self.position.y),
}) })
.ok(); .ok();
@ -202,7 +215,7 @@ impl MouseManager {
.. ..
} => { } => {
if state == &ElementState::Pressed { if state == &ElementState::Pressed {
self.handle_pointer_down(); self.handle_pointer_down(renderer);
} else { } else {
self.handle_pointer_up(); self.handle_pointer_up();
} }

Loading…
Cancel
Save