1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-24 13:52:55 +03:00

Mouse seems to do something, but it is incorrect

This commit is contained in:
Timmy Xiao 2024-01-19 17:27:32 -08:00 committed by Wez Furlong
parent dfa1e35138
commit 6807d7c18f
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387
4 changed files with 299 additions and 37 deletions

View File

@ -1,48 +1,182 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use smithay_client_toolkit::seat::pointer::{PointerEvent, PointerEventKind, PointerHandler};
use smithay_client_toolkit::seat::pointer::{
PointerData, PointerDataExt, PointerEvent, PointerEventKind, PointerHandler,
};
use wayland_client::backend::ObjectId;
use wayland_client::protocol::wl_pointer::{ButtonState, WlPointer};
use wayland_client::protocol::wl_seat::WlSeat;
use wayland_client::{Connection, Proxy, QueueHandle};
use wezterm_input_types::MousePress;
use crate::ConnectionOps;
use super::state::WaylandState;
use super::WaylandConnection;
impl PointerHandler for WaylandState {
fn pointer_frame(
&mut self,
conn: &Connection,
qh: &QueueHandle<Self>,
_conn: &Connection,
_qh: &QueueHandle<Self>,
pointer: &WlPointer,
events: &[PointerEvent],
) {
let mut pstate = pointer
.data::<PointerUserData>()
.unwrap()
.state
.lock()
.unwrap();
for evt in events {
if let PointerEventKind::Enter { .. } = &evt.kind {
let surface_id = evt.surface.id();
self.active_surface_id = RefCell::new(Some(surface_id));
self.active_surface_id = RefCell::new(Some(surface_id.clone()));
pstate.active_surface_id = Some(surface_id);
}
if let Some(serial) = event_serial(&evt) {
*self.last_serial.borrow_mut() = serial;
pstate.serial = serial;
}
if let Some(pending) = self
.surface_to_pending
.get(&self.active_surface_id.borrow().as_ref().unwrap())
{
let mut pending = pending.lock().unwrap();
if pending.queue(evt) {
WaylandConnection::with_window_inner(pending.window_id, move |inner| {
inner.dispatch_pending_mouse();
Ok(())
});
}
}
if let Some(serial) = event_serial(&evt) {}
}
}
}
// pub(super) struct PointerData {
// active_surface_id: u32,
// surface_to_pending: HashMap<u32, Arc<Mutex<PendingMouse>>>,
// // TODO: drag_and_drop: DragAndDrop,
// serial: u32,
// }
//
// #[derive(Clone, Debug)]
// pub struct PendingMouse {
// window_id: usize,
// // TODO: copy_and_paste: Arc<Mutex<CopyAndPaste>>,
// surface_coords: Option<(f64, f64)>,
// button: Vec<(MousePress, ButtonState)>,
// scroll: Option<(f64, f64)>,
// in_window: bool,
// }
#[derive(Debug)]
pub(super) struct PointerUserData {
pdata: PointerData,
state: Mutex<PointerState>,
}
impl PointerUserData {
pub(super) fn new(seat: WlSeat) -> Self {
Self {
pdata: PointerData::new(seat),
state: Default::default(),
}
}
}
#[derive(Debug, Default)]
struct PointerState {
active_surface_id: Option<ObjectId>,
// TODO: drag_and_drop: DragAndDrop,
serial: u32,
}
impl PointerDataExt for PointerUserData {
fn pointer_data(&self) -> &PointerData {
&self.pdata
}
}
#[derive(Clone, Debug)]
pub struct PendingMouse {
window_id: usize,
// TODO: copy_and_paste: Arc<Mutex<CopyAndPaste>>,
surface_coords: Option<(f64, f64)>,
button: Vec<(MousePress, ButtonState)>,
scroll: Option<(f64, f64)>,
in_window: bool,
}
impl PendingMouse {
// TODO: copy and paste
pub(super) fn create(window_id: usize) -> Arc<Mutex<Self>> {
Arc::new(Mutex::new(Self {
window_id,
button: vec![],
scroll: None,
surface_coords: None,
in_window: false,
}))
}
pub(super) fn queue(&mut self, evt: &PointerEvent) -> bool {
match evt.kind {
PointerEventKind::Enter { .. } => {
self.in_window = true;
false
}
PointerEventKind::Leave { .. } => {
let changed = self.in_window;
self.surface_coords = None;
self.in_window = false;
changed
}
PointerEventKind::Motion { .. } => {
let changed = self.surface_coords.is_none();
self.surface_coords.replace(evt.position);
changed
}
PointerEventKind::Press { button, .. } => {
fn linux_button(b: u32) -> Option<MousePress> {
// See BTN_LEFT and friends in <linux/input-event-codes.h>
match b {
0x110 => Some(MousePress::Left),
0x111 => Some(MousePress::Right),
0x112 => Some(MousePress::Middle),
_ => None,
}
}
let button = match linux_button(button) {
Some(button) => button,
None => return false,
};
let changed = self.button.is_empty();
self.button.push((button, ButtonState::Pressed));
changed
}
PointerEventKind::Axis {
horizontal,
vertical,
..
} => {
let changed = self.scroll.is_none();
let (x, y) = self.scroll.take().unwrap_or((0., 0.));
self.scroll
.replace((x + horizontal.absolute, y + vertical.absolute));
changed
}
_ => false,
}
}
pub(super) fn next_button(pending: &Arc<Mutex<Self>>) -> Option<(MousePress, ButtonState)> {
let mut pending = pending.lock().unwrap();
if pending.button.is_empty() {
None
} else {
Some(pending.button.remove(0))
}
}
pub(super) fn coords(pending: &Arc<Mutex<Self>>) -> Option<(f64, f64)> {
pending.lock().unwrap().surface_coords.take()
}
pub(super) fn scroll(pending: &Arc<Mutex<Self>>) -> Option<(f64, f64)> {
pending.lock().unwrap().scroll.take()
}
pub(super) fn in_window(pending: &Arc<Mutex<Self>>) -> bool {
pending.lock().unwrap().in_window
}
}
fn event_serial(event: &PointerEvent) -> Option<u32> {
Some(match event.kind {

View File

@ -3,6 +3,7 @@ use wayland_client::protocol::wl_seat::WlSeat;
use wayland_client::{Connection, QueueHandle};
use crate::wayland::keyboard::KeyboardData;
use crate::wayland::pointer::PointerUserData;
use super::state::WaylandState;
@ -32,7 +33,7 @@ impl SeatHandler for WaylandState {
log::trace!("Setting pointer capability");
let pointer = self
.seat_state()
.get_pointer(qh, &seat)
.get_pointer_with_data(qh, &seat, PointerUserData::new(seat.clone()))
.expect("Failed to create pointer");
self.pointer = Some(pointer);
}

View File

@ -1,6 +1,7 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use std::sync::{Arc, Mutex};
use smithay_client_toolkit::compositor::CompositorState;
use smithay_client_toolkit::output::{OutputHandler, OutputState};
@ -10,8 +11,8 @@ use smithay_client_toolkit::shell::xdg::XdgShell;
use smithay_client_toolkit::shm::slot::SlotPool;
use smithay_client_toolkit::shm::{Shm, ShmHandler};
use smithay_client_toolkit::{
delegate_compositor, delegate_output, delegate_pointer, delegate_registry, delegate_seat,
delegate_shm, delegate_xdg_shell, delegate_xdg_window, registry_handlers,
delegate_compositor, delegate_output, delegate_registry, delegate_seat, delegate_shm,
delegate_xdg_shell, delegate_xdg_window, registry_handlers,
};
use wayland_client::backend::ObjectId;
use wayland_client::globals::GlobalList;
@ -23,6 +24,7 @@ use wayland_client::{delegate_dispatch, Connection, QueueHandle};
use crate::x11::KeyboardWithFallback;
use super::pointer::{PendingMouse, PointerUserData};
use super::{SurfaceUserData, WaylandWindowInner};
// We can't combine WaylandState and WaylandConnection together because
@ -44,6 +46,7 @@ pub(super) struct WaylandState {
pub(super) keyboard_window_id: Option<usize>,
pub(super) pointer: Option<WlPointer>,
pub(super) surface_to_pending: HashMap<ObjectId, Arc<Mutex<PendingMouse>>>,
shm: Shm,
pub(super) mem_pool: RefCell<SlotPool>,
@ -68,6 +71,7 @@ impl WaylandState {
key_repeat_delay: 400,
keyboard_window_id: None,
pointer: None,
surface_to_pending: HashMap::new(),
shm,
mem_pool: RefCell::new(mem_pool),
};
@ -120,7 +124,10 @@ delegate_output!(WaylandState);
delegate_compositor!(WaylandState);
delegate_seat!(WaylandState);
delegate_pointer!(WaylandState);
// Updating to 0.18 should have this be able to work
// delegate_pointer!(WaylandState, pointer: [PointerUserData]);
delegate_dispatch!(WaylandState: [WlPointer: PointerUserData] => SeatState);
delegate_xdg_shell!(WaylandState);
delegate_xdg_window!(WaylandState);

View File

@ -22,20 +22,25 @@ use smithay_client_toolkit::shell::xdg::window::{
use smithay_client_toolkit::shell::WaylandSurface;
use wayland_client::protocol::wl_callback::WlCallback;
use wayland_client::protocol::wl_keyboard::{Event as WlKeyboardEvent, KeyState};
use wayland_client::protocol::wl_pointer::ButtonState;
use wayland_client::protocol::wl_surface::WlSurface;
use wayland_client::{Connection as WConnection, Proxy};
use wayland_egl::{is_available as egl_is_available, WlEglSurface};
use wezterm_font::FontConfiguration;
use wezterm_input_types::{KeyboardLedStatus, Modifiers, WindowDecorations};
use wezterm_input_types::{
KeyboardLedStatus, Modifiers, MouseButtons, MouseEvent, MouseEventKind, MousePress,
ScreenPoint, WindowDecorations,
};
use crate::wayland::WaylandConnection;
use crate::x11::KeyboardWithFallback;
use crate::{
Clipboard, Connection, ConnectionOps, Dimensions, MouseCursor, Rect, RequestedWindowGeometry,
ResolvedGeometry, Window, WindowEvent, WindowEventSender, WindowKeyEvent, WindowOps,
WindowState,
Clipboard, Connection, ConnectionOps, Dimensions, MouseCursor, Point, Rect,
RequestedWindowGeometry, ResolvedGeometry, Window, WindowEvent, WindowEventSender,
WindowKeyEvent, WindowOps, WindowState,
};
use super::pointer::PendingMouse;
use super::state::WaylandState;
#[derive(Debug)]
@ -219,9 +224,15 @@ impl WaylandWindow {
window.commit();
//
// TODO:
// TODO: copy and paste
// let copy_and_paste = CopyAndPaste::create();
// let pending_mouse = PendingMouse::create(window_id, &copy_and_paste);
let pending_mouse = PendingMouse::create(window_id);
{
let surface_to_pending = &mut conn.wayland_state.borrow_mut().surface_to_pending;
surface_to_pending.insert(surface.id(), Arc::clone(&pending_mouse));
}
// conn.pointer.borrow().add_window(&surface, &pending_mouse);
@ -234,12 +245,17 @@ impl WaylandWindow {
dimensions,
resize_increments: None,
window_state: WindowState::default(),
last_mouse_coords: Point::new(0, 0),
mouse_buttons: MouseButtons::NONE,
hscroll_remainder: 0.0,
vscroll_remainder: 0.0,
modifiers: Modifiers::NONE,
leds: KeyboardLedStatus::empty(),
key_repeat: None,
pending_event,
pending_mouse,
pending_first_configure: Some(pending_first_configure),
frame_callback: None,
@ -371,15 +387,15 @@ pub struct WaylandWindowInner {
dimensions: Dimensions,
resize_increments: Option<(u16, u16)>,
window_state: WindowState,
// last_mouse_coords: Point,
// mouse_buttons: MouseButtons,
// hscroll_remainder: f64,
// vscroll_remainder: f64,
last_mouse_coords: Point,
mouse_buttons: MouseButtons,
hscroll_remainder: f64,
vscroll_remainder: f64,
modifiers: Modifiers,
leds: KeyboardLedStatus,
pub(super) key_repeat: Option<(u32, Arc<Mutex<KeyRepeatState>>)>,
pub(crate) pending_event: Arc<Mutex<PendingEvent>>,
// pending_mouse: Arc<Mutex<PendingMouse>>,
pub(super) pending_event: Arc<Mutex<PendingEvent>>,
pub(super) pending_mouse: Arc<Mutex<PendingMouse>>,
pending_first_configure: Option<async_channel::Sender<()>>,
frame_callback: Option<WlCallback>,
invalidated: bool,
@ -490,6 +506,110 @@ impl WaylandWindowInner {
((pixels as f64) / self.get_dpi_factor()).ceil() as i32
}
pub(crate) fn dispatch_pending_mouse(&mut self) {
let pending_mouse = Arc::clone(&self.pending_mouse);
if let Some((x, y)) = PendingMouse::coords(&pending_mouse) {
let coords = Point::new(
self.surface_to_pixels(x as i32) as isize,
self.surface_to_pixels(y as i32) as isize,
);
self.last_mouse_coords = coords;
let event = MouseEvent {
kind: MouseEventKind::Move,
coords,
screen_coords: ScreenPoint::new(
coords.x + self.dimensions.pixel_width as isize,
coords.y + self.dimensions.pixel_height as isize,
),
mouse_buttons: self.mouse_buttons,
modifiers: self.modifiers,
};
self.events.dispatch(WindowEvent::MouseEvent(event));
self.refresh_frame();
}
while let Some((button, state)) = PendingMouse::next_button(&pending_mouse) {
let button_mask = match button {
MousePress::Left => MouseButtons::LEFT,
MousePress::Right => MouseButtons::RIGHT,
MousePress::Middle => MouseButtons::MIDDLE,
};
if state == ButtonState::Pressed {
self.mouse_buttons |= button_mask;
} else {
self.mouse_buttons -= button_mask;
}
let event = MouseEvent {
kind: match state {
ButtonState::Pressed => MouseEventKind::Press(button),
ButtonState::Released => MouseEventKind::Release(button),
_ => continue,
},
coords: self.last_mouse_coords,
screen_coords: ScreenPoint::new(
self.last_mouse_coords.x + self.dimensions.pixel_width as isize,
self.last_mouse_coords.y + self.dimensions.pixel_height as isize,
),
mouse_buttons: self.mouse_buttons,
modifiers: self.modifiers,
};
self.events.dispatch(WindowEvent::MouseEvent(event));
}
if let Some((value_x, value_y)) = PendingMouse::scroll(&pending_mouse) {
let factor = self.get_dpi_factor() as f64;
if value_x.signum() != self.hscroll_remainder.signum() {
// reset accumulator when changing scroll direction
self.hscroll_remainder = 0.0;
}
let scaled_x = (value_x * factor) + self.hscroll_remainder;
let discrete_x = scaled_x.trunc();
self.hscroll_remainder = scaled_x - discrete_x;
if discrete_x != 0. {
let event = MouseEvent {
kind: MouseEventKind::HorzWheel(-discrete_x as i16),
coords: self.last_mouse_coords,
screen_coords: ScreenPoint::new(
self.last_mouse_coords.x + self.dimensions.pixel_width as isize,
self.last_mouse_coords.y + self.dimensions.pixel_height as isize,
),
mouse_buttons: self.mouse_buttons,
modifiers: self.modifiers,
};
self.events.dispatch(WindowEvent::MouseEvent(event));
}
if value_y.signum() != self.vscroll_remainder.signum() {
self.vscroll_remainder = 0.0;
}
let scaled_y = (value_y * factor) + self.vscroll_remainder;
let discrete_y = scaled_y.trunc();
self.vscroll_remainder = scaled_y - discrete_y;
if discrete_y != 0. {
let event = MouseEvent {
kind: MouseEventKind::VertWheel(-discrete_y as i16),
coords: self.last_mouse_coords,
screen_coords: ScreenPoint::new(
self.last_mouse_coords.x + self.dimensions.pixel_width as isize,
self.last_mouse_coords.y + self.dimensions.pixel_height as isize,
),
mouse_buttons: self.mouse_buttons,
modifiers: self.modifiers,
};
self.events.dispatch(WindowEvent::MouseEvent(event));
}
}
if !PendingMouse::in_window(&pending_mouse) {
self.events.dispatch(WindowEvent::MouseLeave);
self.refresh_frame();
}
}
pub(crate) fn dispatch_pending_event(&mut self) {
let mut pending;
{