mirror of
https://github.com/wez/wezterm.git
synced 2024-11-23 15:04:36 +03:00
allow dragging by tab bar on linux
This works with X11 on fedora, but the window movement is ignored by the xwayland machinery on chromeos.
This commit is contained in:
parent
01eaa7db08
commit
349a24ccd9
@ -37,6 +37,7 @@ pub struct TermWindow {
|
||||
show_tab_bar: bool,
|
||||
tab_bar: TabBarState,
|
||||
last_mouse_coords: (usize, i64),
|
||||
drag_start_coords: Option<Point>,
|
||||
}
|
||||
|
||||
struct Host<'a> {
|
||||
@ -117,6 +118,19 @@ impl WindowCallbacks for TermWindow {
|
||||
None => return,
|
||||
};
|
||||
|
||||
match event.kind {
|
||||
WMEK::Release(MousePress::Left) => self.drag_start_coords = None,
|
||||
WMEK::Move => {
|
||||
if let Some(drag) = self.drag_start_coords.as_ref() {
|
||||
context.set_window_position(ScreenPoint::new(
|
||||
event.screen_coords.x - drag.x,
|
||||
event.screen_coords.y - drag.y,
|
||||
));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
let x = (event.coords.x.max(0) / self.render_metrics.cell_size.width) as usize;
|
||||
let y = (event.coords.y.max(0) / self.render_metrics.cell_size.height) as i64;
|
||||
|
||||
@ -124,6 +138,11 @@ impl WindowCallbacks for TermWindow {
|
||||
self.last_mouse_coords = (x, y);
|
||||
|
||||
if self.show_tab_bar && y == 0 {
|
||||
match event.kind {
|
||||
WMEK::Press(MousePress::Left) => self.drag_start_coords = Some(event.coords),
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if let Some(tab_idx) = self.tab_bar.hit_test(x) {
|
||||
match event.kind {
|
||||
WMEK::Press(MousePress::Left) => {
|
||||
@ -387,6 +406,7 @@ impl TermWindow {
|
||||
show_tab_bar: config.enable_tab_bar,
|
||||
tab_bar: TabBarState::default(),
|
||||
last_mouse_coords: (0, -1),
|
||||
drag_start_coords: None,
|
||||
}),
|
||||
)?;
|
||||
|
||||
|
@ -127,7 +127,10 @@ pub enum MouseEventKind {
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct MouseEvent {
|
||||
pub kind: MouseEventKind,
|
||||
/// Coordinates of the mouse relative to the top left of the window
|
||||
pub coords: crate::Point,
|
||||
/// The mouse position in screen coordinates
|
||||
pub screen_coords: crate::ScreenPoint,
|
||||
pub mouse_buttons: MouseButtons,
|
||||
pub modifiers: Modifiers,
|
||||
}
|
||||
|
@ -59,6 +59,9 @@ pub type Point = euclid::Point2D<isize, PixelUnit>;
|
||||
pub type Rect = euclid::Rect<isize, PixelUnit>;
|
||||
pub type Size = euclid::Size2D<isize, PixelUnit>;
|
||||
|
||||
pub struct ScreenPixelUnit;
|
||||
pub type ScreenPoint = euclid::Point2D<isize, ScreenPixelUnit>;
|
||||
|
||||
pub trait PaintContext {
|
||||
fn get_dimensions(&self) -> Dimensions;
|
||||
|
||||
@ -173,6 +176,13 @@ pub trait WindowOps {
|
||||
/// Resize the inner or client area of the window
|
||||
fn set_inner_size(&self, width: usize, height: usize) -> Future<()>;
|
||||
|
||||
/// Changes the location of the window on the screen.
|
||||
/// The coordinates are of the top left pixel of the
|
||||
/// client area.
|
||||
fn set_window_position(&self, _coords: ScreenPoint) -> Future<()> {
|
||||
Future::ok(())
|
||||
}
|
||||
|
||||
/// inform the windowing system of the current textual
|
||||
/// cursor input location. This is used primarily for
|
||||
/// the platform specific input method editor
|
||||
@ -238,4 +248,9 @@ pub trait WindowOpsMut {
|
||||
/// cursor input location. This is used primarily for
|
||||
/// the platform specific input method editor
|
||||
fn set_text_cursor_position(&mut self, _cursor: Rect) {}
|
||||
|
||||
/// Changes the location of the window on the screen.
|
||||
/// The coordinates are of the top left pixel of the
|
||||
/// client area.
|
||||
fn set_window_position(&self, _coords: ScreenPoint) {}
|
||||
}
|
||||
|
@ -81,8 +81,8 @@ impl TimerList {
|
||||
|
||||
pub struct Connection {
|
||||
pub display: *mut x11::xlib::Display,
|
||||
conn: xcb::Connection,
|
||||
screen_num: i32,
|
||||
conn: xcb_util::ewmh::Connection,
|
||||
pub screen_num: i32,
|
||||
pub keyboard: Keyboard,
|
||||
pub kbd_ev: u8,
|
||||
pub atom_protocols: xcb::Atom,
|
||||
@ -370,6 +370,8 @@ impl Connection {
|
||||
}
|
||||
let screen_num = unsafe { x11::xlib::XDefaultScreen(display) };
|
||||
let conn = unsafe { xcb::Connection::from_raw_conn(XGetXCBConnection(display)) };
|
||||
let conn = xcb_util::ewmh::Connection::connect(conn)
|
||||
.map_err(|_| failure::err_msg("failed to init ewmh"))?;
|
||||
unsafe { XSetEventQueueOwner(display, 1) };
|
||||
|
||||
let atom_protocols = xcb::intern_atom(&conn, false, "WM_PROTOCOLS")
|
||||
@ -391,7 +393,7 @@ impl Connection {
|
||||
.get_reply()?
|
||||
.atom();
|
||||
|
||||
let keysyms = unsafe { xcb_key_symbols_alloc(conn.get_raw_conn()) };
|
||||
let keysyms = unsafe { xcb_key_symbols_alloc((*conn).get_raw_conn()) };
|
||||
|
||||
let shm_available = server_supports_shm();
|
||||
eprintln!("shm_available: {}", shm_available);
|
||||
@ -452,10 +454,14 @@ impl Connection {
|
||||
Ok(conn)
|
||||
}
|
||||
|
||||
pub fn conn(&self) -> &xcb::Connection {
|
||||
pub fn ewmh_conn(&self) -> &xcb_util::ewmh::Connection {
|
||||
&self.conn
|
||||
}
|
||||
|
||||
pub fn conn(&self) -> &xcb::Connection {
|
||||
&*self.conn
|
||||
}
|
||||
|
||||
pub fn screen_num(&self) -> i32 {
|
||||
self.screen_num
|
||||
}
|
||||
|
@ -3,7 +3,8 @@ use crate::bitmaps::*;
|
||||
use crate::connection::ConnectionOps;
|
||||
use crate::{
|
||||
Color, Dimensions, KeyEvent, MouseButtons, MouseCursor, MouseEvent, MouseEventKind, MousePress,
|
||||
Operator, PaintContext, Point, Rect, Size, WindowCallbacks, WindowOps, WindowOpsMut,
|
||||
Operator, PaintContext, Point, Rect, ScreenPoint, Size, WindowCallbacks, WindowOps,
|
||||
WindowOpsMut,
|
||||
};
|
||||
use failure::Fallible;
|
||||
use promise::Future;
|
||||
@ -281,6 +282,10 @@ impl WindowInner {
|
||||
motion.event_x().try_into().unwrap(),
|
||||
motion.event_y().try_into().unwrap(),
|
||||
),
|
||||
screen_coords: ScreenPoint::new(
|
||||
motion.root_x().try_into().unwrap(),
|
||||
motion.root_y().try_into().unwrap(),
|
||||
),
|
||||
modifiers: xkeysyms::modifiers_from_state(motion.state()),
|
||||
mouse_buttons: MouseButtons::default(),
|
||||
};
|
||||
@ -321,6 +326,10 @@ impl WindowInner {
|
||||
button_press.event_x().try_into().unwrap(),
|
||||
button_press.event_y().try_into().unwrap(),
|
||||
),
|
||||
screen_coords: ScreenPoint::new(
|
||||
button_press.root_x().try_into().unwrap(),
|
||||
button_press.root_y().try_into().unwrap(),
|
||||
),
|
||||
modifiers: xkeysyms::modifiers_from_state(button_press.state()),
|
||||
mouse_buttons: MouseButtons::default(),
|
||||
};
|
||||
@ -343,6 +352,54 @@ impl WindowInner {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn disable_decorations(&mut self) -> Fallible<()> {
|
||||
// Set the motif hints to disable decorations.
|
||||
// See https://stackoverflow.com/a/1909708
|
||||
#[repr(C)]
|
||||
struct MwmHints {
|
||||
flags: u32,
|
||||
functions: u32,
|
||||
decorations: u32,
|
||||
input_mode: i32,
|
||||
status: u32,
|
||||
}
|
||||
|
||||
const HINTS_FUNCTIONS: u32 = 1 << 0;
|
||||
const HINTS_DECORATIONS: u32 = 1 << 1;
|
||||
const FUNC_ALL: u32 = 1 << 0;
|
||||
const FUNC_RESIZE: u32 = 1 << 1;
|
||||
const FUNC_MOVE: u32 = 1 << 2;
|
||||
const FUNC_MINIMIZE: u32 = 1 << 3;
|
||||
const FUNC_MAXIMIZE: u32 = 1 << 4;
|
||||
const FUNC_CLOSE: u32 = 1 << 5;
|
||||
|
||||
let hints = MwmHints {
|
||||
flags: HINTS_DECORATIONS,
|
||||
functions: 0,
|
||||
decorations: 0, // off
|
||||
input_mode: 0,
|
||||
status: 0,
|
||||
};
|
||||
|
||||
let hints_slice =
|
||||
unsafe { std::slice::from_raw_parts(&hints as *const _ as *const u32, 5) };
|
||||
|
||||
let atom = xcb::intern_atom(self.conn.conn(), false, "_MOTIF_WM_HINTS")
|
||||
.get_reply()?
|
||||
.atom();
|
||||
xcb::change_property(
|
||||
self.conn.conn(),
|
||||
xcb::PROP_MODE_REPLACE as u8,
|
||||
self.window_id,
|
||||
atom,
|
||||
atom,
|
||||
32,
|
||||
hints_slice,
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A Window!
|
||||
@ -438,6 +495,8 @@ impl Window {
|
||||
&[conn.atom_delete],
|
||||
);
|
||||
|
||||
// window.lock().unwrap().disable_decorations()?;
|
||||
|
||||
let window_handle = Window::from_id(window_id);
|
||||
|
||||
window.lock().unwrap().callbacks.created(&window_handle);
|
||||
@ -483,6 +542,43 @@ impl WindowOpsMut for WindowInner {
|
||||
);
|
||||
}
|
||||
|
||||
fn set_window_position(&self, coords: ScreenPoint) {
|
||||
// We ask the window manager to move the window for us so that
|
||||
// we don't have to deal with adjusting for the frame size.
|
||||
// Note that neither this technique or the configure_window
|
||||
// approach below will successfully move a window running
|
||||
// under the crostini environment on a chromebook :-(
|
||||
xcb_util::ewmh::request_move_resize_window(
|
||||
self.conn.ewmh_conn(),
|
||||
self.conn.screen_num,
|
||||
self.window_id,
|
||||
xcb::xproto::GRAVITY_STATIC,
|
||||
1, // normal program
|
||||
xcb_util::ewmh::MOVE_RESIZE_MOVE
|
||||
| xcb_util::ewmh::MOVE_RESIZE_WINDOW_X
|
||||
| xcb_util::ewmh::MOVE_RESIZE_WINDOW_Y,
|
||||
coords.x as u32,
|
||||
coords.y as u32,
|
||||
// these dimensions are ignored because we're not
|
||||
// passing the relevant MOVE_RESIZE_XX flags above,
|
||||
// but are preserved here for clarity on what these
|
||||
// parameters do
|
||||
self.width as u32,
|
||||
self.height as u32,
|
||||
);
|
||||
|
||||
/*
|
||||
xcb::configure_window(
|
||||
self.conn.conn(),
|
||||
self.window_id,
|
||||
&[
|
||||
(xcb::CONFIG_WINDOW_X as u16, coords.x as u32),
|
||||
(xcb::CONFIG_WINDOW_Y as u16, coords.y as u32),
|
||||
],
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
/// Change the title for the window manager
|
||||
fn set_title(&mut self, title: &str) {
|
||||
xcb_util::icccm::set_wm_name(self.conn.conn(), self.window_id, title);
|
||||
@ -540,6 +636,13 @@ impl WindowOps for Window {
|
||||
})
|
||||
}
|
||||
|
||||
fn set_window_position(&self, coords: ScreenPoint) -> Future<()> {
|
||||
Connection::with_window_inner(self.0, move |inner| {
|
||||
inner.set_window_position(coords);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn apply<R, F: Send + 'static + Fn(&mut dyn Any, &dyn WindowOps) -> Fallible<R>>(
|
||||
&self,
|
||||
func: F,
|
||||
|
Loading…
Reference in New Issue
Block a user