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:
parent
dfa1e35138
commit
6807d7c18f
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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, ©_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;
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user