1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-20 11:17:15 +03:00

x11: mouse cursors

This commit is contained in:
Wez Furlong 2019-08-10 15:28:10 -07:00
parent cc4a089c41
commit e371e0385d
5 changed files with 96 additions and 12 deletions

View File

@ -40,8 +40,9 @@ impl WindowCallbacks for MyWindow {
false
}
fn mouse_event(&mut self, event: &MouseEvent) {
fn mouse_event(&mut self, event: &MouseEvent) -> Option<MouseCursor> {
eprintln!("{:?}", event);
Some(MouseCursor::Text)
}
}

View File

@ -82,6 +82,13 @@ pub trait PaintContext {
);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MouseCursor {
Arrow,
Hand,
Text,
}
#[allow(unused_variables)]
pub trait WindowCallbacks {
/// Called when the window close button is clicked.
@ -110,5 +117,7 @@ pub trait WindowCallbacks {
false
}
fn mouse_event(&mut self, event: &MouseEvent) {}
fn mouse_event(&mut self, event: &MouseEvent) -> Option<MouseCursor> {
Some(MouseCursor::Arrow)
}
}

View File

@ -3,8 +3,8 @@ use super::*;
use crate::bitmaps::*;
use crate::color::Color;
use crate::{
Dimensions, KeyCode, KeyEvent, Modifiers, MouseButtons, MouseEvent, MouseEventKind, MousePress,
Operator, PaintContext, WindowCallbacks,
Dimensions, KeyCode, KeyEvent, Modifiers, MouseButtons, MouseCursor, MouseEvent,
MouseEventKind, MousePress, Operator, PaintContext, WindowCallbacks,
};
use failure::Fallible;
use std::io::Error as IoError;
@ -386,6 +386,28 @@ fn mouse_coords(lparam: LPARAM) -> (u16, u16) {
(x.max(0) as u16, y.max(0) as u16)
}
fn apply_mouse_cursor(cursor: Option<MouseCursor>) {
match cursor {
None => unsafe {
SetCursor(null_mut());
},
Some(cursor) => unsafe {
SetCursor(LoadCursorW(
null_mut(),
match cursor {
MouseCursor::Arrow => IDC_ARROW,
MouseCursor::Hand => IDC_HAND,
MouseCursor::Text => IDC_IBEAM,
},
));
},
}
}
fn do_mouse_event(inner: &mut WindowInner, event: &MouseEvent) {
apply_mouse_cursor(inner.callbacks.mouse_event(event))
}
unsafe fn mouse_button(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) -> Option<LRESULT> {
if let Some(inner) = arc_from_hwnd(hwnd) {
let (modifiers, mouse_buttons) = mods_and_buttons(wparam);
@ -409,7 +431,7 @@ unsafe fn mouse_button(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) ->
modifiers,
};
let mut inner = inner.lock().unwrap();
inner.callbacks.mouse_event(&event);
do_mouse_event(&mut inner, &event);
Some(0)
} else {
None
@ -428,7 +450,7 @@ unsafe fn mouse_move(hwnd: HWND, _msg: UINT, wparam: WPARAM, lparam: LPARAM) ->
modifiers,
};
let mut inner = inner.lock().unwrap();
inner.callbacks.mouse_event(&event);
do_mouse_event(&mut inner, &event);
Some(0)
} else {
None
@ -452,7 +474,7 @@ unsafe fn mouse_wheel(hwnd: HWND, msg: UINT, wparam: WPARAM, lparam: LPARAM) ->
modifiers,
};
let mut inner = inner.lock().unwrap();
inner.callbacks.mouse_event(&event);
do_mouse_event(&mut inner, &event);
Some(0)
} else {
None

View File

@ -82,6 +82,7 @@ pub struct Connection {
pub keyboard: Keyboard,
pub kbd_ev: u8,
pub atom_protocols: xcb::Atom,
pub cursor_font_id: xcb::ffi::xcb_font_t,
pub atom_delete: xcb::Atom,
pub atom_utf8_string: xcb::Atom,
pub atom_xsel_data: xcb::Atom,
@ -371,9 +372,14 @@ impl Connection {
let (keyboard, kbd_ev) = Keyboard::new(&conn)?;
let cursor_font_id = conn.generate_id().into();
let cursor_font_name = "cursor";
xcb::open_font_checked(&conn, cursor_font_id, cursor_font_name);
let conn = Arc::new(Connection {
display,
conn,
cursor_font_id,
screen_num,
atom_protocols,
atom_clipboard,

View File

@ -1,8 +1,8 @@
use super::*;
use crate::bitmaps::*;
use crate::{
Color, Dimensions, KeyEvent, MouseButtons, MouseEvent, MouseEventKind, MousePress, Operator,
PaintContext, WindowCallbacks,
Color, Dimensions, KeyEvent, MouseButtons, MouseCursor, MouseEvent, MouseEventKind, MousePress,
Operator, PaintContext, WindowCallbacks,
};
use failure::Fallible;
use std::collections::VecDeque;
@ -67,6 +67,7 @@ struct WindowInner {
expose: VecDeque<Rect>,
paint_all: bool,
buffer_image: BufferImage,
cursor: Option<MouseCursor>,
}
impl Drop for WindowInner {
@ -229,6 +230,51 @@ impl WindowInner {
self.expose.push_back(expose);
}
fn do_mouse_event(&mut self, event: &MouseEvent) -> Fallible<()> {
let cursor = self.callbacks.mouse_event(&event);
self.set_cursor(cursor)?;
Ok(())
}
fn set_cursor(&mut self, cursor: Option<MouseCursor>) -> Fallible<()> {
if cursor == self.cursor {
return Ok(());
}
let id_no = match cursor.unwrap_or(MouseCursor::Arrow) {
// `/usr/include/X11/cursorfont.h`
MouseCursor::Arrow => 2,
MouseCursor::Hand => 58,
MouseCursor::Text => 152,
};
let cursor_id: xcb::ffi::xcb_cursor_t = self.conn.generate_id().into();
xcb::create_glyph_cursor(
&self.conn,
cursor_id,
self.conn.cursor_font_id,
self.conn.cursor_font_id,
id_no,
id_no + 1,
0xffff,
0xffff,
0xffff,
0,
0,
0,
);
xcb::change_window_attributes(
&self.conn,
self.window_id,
&[(xcb::ffi::XCB_CW_CURSOR, cursor_id)],
);
xcb::free_cursor(&self.conn, cursor_id);
Ok(())
}
fn dispatch_event(&mut self, event: &xcb::GenericEvent) -> Fallible<()> {
let r = event.response_type() & 0x7f;
match r {
@ -269,7 +315,7 @@ impl WindowInner {
modifiers: xkeysyms::modifiers_from_state(motion.state()),
mouse_buttons: MouseButtons::default(),
};
self.callbacks.mouse_event(&event);
self.do_mouse_event(&event)?;
}
xcb::BUTTON_PRESS | xcb::BUTTON_RELEASE => {
let button_press: &xcb::ButtonPressEvent = unsafe { xcb::cast_event(event) };
@ -307,8 +353,7 @@ impl WindowInner {
modifiers: xkeysyms::modifiers_from_state(button_press.state()),
mouse_buttons: MouseButtons::default(),
};
self.callbacks.mouse_event(&event);
self.do_mouse_event(&event)?;
}
xcb::CLIENT_MESSAGE => {
let msg: &xcb::ClientMessageEvent = unsafe { xcb::cast_event(event) };
@ -406,6 +451,7 @@ impl Window {
expose: VecDeque::new(),
paint_all: true,
buffer_image,
cursor: None,
}))
};