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:
parent
cc4a089c41
commit
e371e0385d
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
}))
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user