Add resize/move via pointer
This commit is contained in:
parent
673af15cfd
commit
20e16ca508
5 changed files with 315 additions and 17 deletions
122
src/deco.rs
122
src/deco.rs
|
|
@ -1,8 +1,21 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use wl_proxy::{
|
||||
fixed::Fixed,
|
||||
object::ObjectCoreApi,
|
||||
protocols::wayland::{wl_buffer::WlBuffer, wl_subsurface::WlSubsurface, wl_surface::WlSurface},
|
||||
protocols::{
|
||||
cursor_shape_v1::wp_cursor_shape_device_v1::{
|
||||
WpCursorShapeDeviceV1, WpCursorShapeDeviceV1Shape,
|
||||
},
|
||||
wayland::{
|
||||
wl_buffer::WlBuffer,
|
||||
wl_pointer::WlPointerButtonState,
|
||||
wl_seat::WlSeat,
|
||||
wl_subsurface::WlSubsurface,
|
||||
wl_surface::{WlSurface, WlSurfaceHandler},
|
||||
},
|
||||
xdg_shell::xdg_toplevel::{XdgToplevel, XdgToplevelResizeEdge},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{buffer::SimpleBufferPool, globals::Globals, util::Bounds};
|
||||
|
|
@ -14,12 +27,104 @@ pub struct Deco {
|
|||
|
||||
wl_surface: Rc<WlSurface>,
|
||||
subsurface: Rc<WlSubsurface>,
|
||||
toplevel: Rc<XdgToplevel>,
|
||||
pool: RefCell<SimpleBufferPool>,
|
||||
globals: Rc<Globals>,
|
||||
}
|
||||
|
||||
impl Deco {
|
||||
pub fn new(host_surface: &Rc<WlSurface>, globals: &Rc<Globals>) -> Deco {
|
||||
fn resize_anchor(&self, x: i32, y: i32) -> XdgToplevelResizeEdge {
|
||||
let n = y < self.border_size;
|
||||
let e = x >= self.bounds.borrow().width + self.border_size;
|
||||
let w = x < self.border_size;
|
||||
let s = y >= self.bounds.borrow().height + self.border_size;
|
||||
if n && e {
|
||||
XdgToplevelResizeEdge::TOP_RIGHT
|
||||
} else if n && w {
|
||||
XdgToplevelResizeEdge::TOP_LEFT
|
||||
} else if s && e {
|
||||
XdgToplevelResizeEdge::BOTTOM_RIGHT
|
||||
} else if s && w {
|
||||
XdgToplevelResizeEdge::BOTTOM_LEFT
|
||||
} else if n {
|
||||
XdgToplevelResizeEdge::TOP
|
||||
} else if e {
|
||||
XdgToplevelResizeEdge::RIGHT
|
||||
} else if w {
|
||||
XdgToplevelResizeEdge::LEFT
|
||||
} else if s {
|
||||
XdgToplevelResizeEdge::BOTTOM
|
||||
} else {
|
||||
XdgToplevelResizeEdge::NONE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn resize_cursor(anchor: XdgToplevelResizeEdge) -> WpCursorShapeDeviceV1Shape {
|
||||
match anchor {
|
||||
XdgToplevelResizeEdge::TOP_LEFT => WpCursorShapeDeviceV1Shape::NW_RESIZE,
|
||||
XdgToplevelResizeEdge::TOP_RIGHT => WpCursorShapeDeviceV1Shape::NE_RESIZE,
|
||||
XdgToplevelResizeEdge::BOTTOM_LEFT => WpCursorShapeDeviceV1Shape::SW_RESIZE,
|
||||
XdgToplevelResizeEdge::BOTTOM_RIGHT => WpCursorShapeDeviceV1Shape::SE_RESIZE,
|
||||
XdgToplevelResizeEdge::TOP => WpCursorShapeDeviceV1Shape::N_RESIZE,
|
||||
XdgToplevelResizeEdge::LEFT => WpCursorShapeDeviceV1Shape::W_RESIZE,
|
||||
XdgToplevelResizeEdge::RIGHT => WpCursorShapeDeviceV1Shape::E_RESIZE,
|
||||
XdgToplevelResizeEdge::BOTTOM => WpCursorShapeDeviceV1Shape::S_RESIZE,
|
||||
_ => WpCursorShapeDeviceV1Shape::DEFAULT,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DecoSurface(Rc<Deco>);
|
||||
|
||||
impl WlSurfaceHandler for DecoSurface {}
|
||||
|
||||
impl DecoSurface {
|
||||
pub fn pointer_motion(
|
||||
&self,
|
||||
serial: u32,
|
||||
surface_x: Fixed,
|
||||
surface_y: Fixed,
|
||||
cursor_shape: Option<&Rc<WpCursorShapeDeviceV1>>,
|
||||
) {
|
||||
let x = surface_x.to_i32_round_towards_nearest();
|
||||
let y = surface_y.to_i32_round_towards_nearest();
|
||||
cursor_shape
|
||||
.unwrap()
|
||||
.send_set_shape(serial, resize_cursor(self.0.resize_anchor(x, y)));
|
||||
}
|
||||
|
||||
pub fn pointer_button(
|
||||
&self,
|
||||
seat: &Rc<WlSeat>,
|
||||
serial: u32,
|
||||
surface_x: Fixed,
|
||||
surface_y: Fixed,
|
||||
button: u32,
|
||||
state: WlPointerButtonState,
|
||||
) {
|
||||
let x = surface_x.to_i32_round_towards_nearest();
|
||||
let y = surface_y.to_i32_round_towards_nearest();
|
||||
let anchor = self.0.resize_anchor(x, y);
|
||||
const BTN_LEFT: u32 = 0x110;
|
||||
if button != BTN_LEFT {
|
||||
return;
|
||||
}
|
||||
if state == WlPointerButtonState::PRESSED {
|
||||
if anchor == XdgToplevelResizeEdge::NONE {
|
||||
self.0.toplevel.send_move(seat, serial);
|
||||
} else {
|
||||
self.0.toplevel.send_resize(seat, serial, anchor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Deco {
|
||||
pub fn new(
|
||||
host_surface: &Rc<WlSurface>,
|
||||
toplevel: &Rc<XdgToplevel>,
|
||||
globals: &Rc<Globals>,
|
||||
) -> Rc<Deco> {
|
||||
let wl_surface = globals.wl_compositor.new_send_create_surface();
|
||||
wl_surface.set_forward_to_client(false);
|
||||
let subsurface = globals
|
||||
|
|
@ -28,7 +133,7 @@ impl Deco {
|
|||
subsurface.set_forward_to_client(false);
|
||||
subsurface.send_place_below(&host_surface);
|
||||
let pool = SimpleBufferPool::new(globals, 1, 1).unwrap();
|
||||
Deco {
|
||||
let deco = Rc::new(Deco {
|
||||
bounds: RefCell::new(Bounds {
|
||||
x: 0,
|
||||
y: 0,
|
||||
|
|
@ -37,11 +142,14 @@ impl Deco {
|
|||
}),
|
||||
top_size: 24,
|
||||
border_size: 8,
|
||||
wl_surface,
|
||||
wl_surface: wl_surface.clone(),
|
||||
subsurface,
|
||||
toplevel: toplevel.clone(),
|
||||
pool: RefCell::new(pool),
|
||||
globals: globals.clone(),
|
||||
}
|
||||
});
|
||||
wl_surface.set_handler(DecoSurface(deco.clone()));
|
||||
deco
|
||||
}
|
||||
|
||||
pub fn handle_window_geometry(
|
||||
|
|
@ -88,6 +196,10 @@ impl Deco {
|
|||
self.wl_surface.send_damage_buffer(0, 0, width, height);
|
||||
let input_region = self.globals.wl_compositor.new_send_create_region();
|
||||
input_region.set_forward_to_client(false);
|
||||
input_region.send_add(0, 0, width, self.top_size);
|
||||
input_region.send_add(0, 0, self.border_size, height);
|
||||
input_region.send_add(width - self.border_size, 0, self.border_size, height);
|
||||
input_region.send_add(0, height - self.border_size, width, self.border_size);
|
||||
self.wl_surface.send_set_input_region(Some(&input_region));
|
||||
self.subsurface
|
||||
.send_set_position(bounds.x - self.border_size, bounds.y - self.top_size);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue