Merge branch 'rework-moveresize'
amend: fixes / dead_code and functions that are now useless addressed amend 2: didnt actually stage, oops
This commit is contained in:
commit
019ce4e350
327
src/state.rs
327
src/state.rs
|
@ -3,8 +3,8 @@ use std::rc::Rc;
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
|
|
||||||
use x11::xlib::{
|
use x11::xlib::{
|
||||||
self, Mod4Mask, ShiftMask, Window, XButtonEvent, XEvent, XKeyEvent,
|
self, Mod4Mask, ShiftMask, Window, XButtonPressedEvent,
|
||||||
XMotionEvent,
|
XButtonReleasedEvent, XEvent, XKeyEvent, XMotionEvent,
|
||||||
};
|
};
|
||||||
use xlib::{
|
use xlib::{
|
||||||
ButtonPressMask, ButtonReleaseMask, PointerMotionMask,
|
ButtonPressMask, ButtonReleaseMask, PointerMotionMask,
|
||||||
|
@ -30,8 +30,7 @@ pub struct WMConfig {
|
||||||
|
|
||||||
pub struct WindowManager {
|
pub struct WindowManager {
|
||||||
clients: ClientState,
|
clients: ClientState,
|
||||||
move_window: Option<MoveWindow>,
|
move_resize_window: MoveResizeInfo,
|
||||||
resize_window: Option<MoveWindow>,
|
|
||||||
keybinds: Vec<KeyBinding>,
|
keybinds: Vec<KeyBinding>,
|
||||||
xlib: XLib,
|
xlib: XLib,
|
||||||
|
|
||||||
|
@ -45,9 +44,22 @@ pub enum Direction {
|
||||||
Right,
|
Right,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MoveWindow {
|
enum MoveResizeInfo {
|
||||||
key: Window,
|
Move(MoveInfoInner),
|
||||||
cached_cursor_position: (i32, i32),
|
Resize(ResizeInfoInner),
|
||||||
|
None,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MoveInfoInner {
|
||||||
|
window: Window,
|
||||||
|
starting_cursor_pos: (i32, i32),
|
||||||
|
starting_window_pos: (i32, i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ResizeInfoInner {
|
||||||
|
window: Window,
|
||||||
|
starting_cursor_pos: (i32, i32),
|
||||||
|
starting_window_size: (i32, i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -64,8 +76,7 @@ impl WindowManager {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
clients,
|
clients,
|
||||||
move_window: None,
|
move_resize_window: MoveResizeInfo::None,
|
||||||
resize_window: None,
|
|
||||||
keybinds: Vec::new(),
|
keybinds: Vec::new(),
|
||||||
xlib,
|
xlib,
|
||||||
last_rotation: None,
|
last_rotation: None,
|
||||||
|
@ -188,17 +199,15 @@ impl WindowManager {
|
||||||
loop {
|
loop {
|
||||||
let event = self.xlib.next_event();
|
let event = self.xlib.next_event();
|
||||||
|
|
||||||
self.handle_toggle_floating(&event);
|
|
||||||
self.handle_move_window(&event);
|
|
||||||
self.handle_resize_client(&event);
|
|
||||||
|
|
||||||
match event.get_type() {
|
match event.get_type() {
|
||||||
xlib::MapRequest => self.map_request(&event),
|
xlib::MapRequest => self.map_request(&event),
|
||||||
xlib::UnmapNotify => self.unmap_notify(&event),
|
xlib::UnmapNotify => self.unmap_notify(&event),
|
||||||
xlib::ConfigureRequest => self.configure_request(&event),
|
xlib::ConfigureRequest => self.configure_request(&event),
|
||||||
xlib::EnterNotify => self.enter_notify(&event),
|
xlib::EnterNotify => self.enter_notify(&event),
|
||||||
xlib::DestroyNotify => self.destroy_notify(&event),
|
xlib::DestroyNotify => self.destroy_notify(&event),
|
||||||
xlib::ButtonPress => self.button_notify(&event),
|
xlib::ButtonPress => self.button_press(event.as_ref()),
|
||||||
|
xlib::ButtonRelease => self.button_release(event.as_ref()),
|
||||||
|
xlib::MotionNotify => self.motion_notify(event.as_ref()),
|
||||||
xlib::KeyPress => self.handle_keybinds(event.as_ref()),
|
xlib::KeyPress => self.handle_keybinds(event.as_ref()),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -233,25 +242,6 @@ impl WindowManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_toggle_floating(&mut self, event: &XEvent) {
|
|
||||||
if event.get_type() == xlib::ButtonPress {
|
|
||||||
let event: &XButtonEvent = event.as_ref();
|
|
||||||
let clean_mask = self.xlib.get_clean_mask();
|
|
||||||
|
|
||||||
if event.button == 2
|
|
||||||
&& event.state & clean_mask == self.config.mod_key & clean_mask
|
|
||||||
{
|
|
||||||
if self.clients.contains(&event.subwindow) {
|
|
||||||
info!("toggleing floating for {:?}", event.subwindow);
|
|
||||||
|
|
||||||
self.clients.toggle_floating(&event.subwindow);
|
|
||||||
|
|
||||||
self.arrange_clients();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_switch_stack(&mut self, event: &XKeyEvent) {
|
fn handle_switch_stack(&mut self, event: &XKeyEvent) {
|
||||||
info!("Switching stack for window{:?}", event.subwindow);
|
info!("Switching stack for window{:?}", event.subwindow);
|
||||||
|
|
||||||
|
@ -260,143 +250,6 @@ impl WindowManager {
|
||||||
self.arrange_clients();
|
self.arrange_clients();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_move_window(&mut self, event: &XEvent) {
|
|
||||||
let clean_mask = self.xlib.get_clean_mask();
|
|
||||||
|
|
||||||
match event.get_type() {
|
|
||||||
xlib::ButtonPress => {
|
|
||||||
let event: &XButtonEvent = event.as_ref();
|
|
||||||
|
|
||||||
if self.move_window.is_none()
|
|
||||||
&& event.button == 1
|
|
||||||
&& event.state & clean_mask
|
|
||||||
== self.config.mod_key & clean_mask
|
|
||||||
&& self.clients.contains(&event.subwindow)
|
|
||||||
{
|
|
||||||
// if client is tiled, set to floating
|
|
||||||
if self.clients.set_floating(&event.subwindow) {
|
|
||||||
self.arrange_clients();
|
|
||||||
}
|
|
||||||
|
|
||||||
self.move_window = Some(MoveWindow {
|
|
||||||
key: event.subwindow,
|
|
||||||
cached_cursor_position: (event.x, event.y),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset on release
|
|
||||||
xlib::ButtonRelease => {
|
|
||||||
let event: &XButtonEvent = event.as_ref();
|
|
||||||
|
|
||||||
if event.button == 1 && self.move_window.is_some() {
|
|
||||||
self.move_window = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xlib::MotionNotify => {
|
|
||||||
//let event = self.xlib.squash_event(xlib::MotionNotify);
|
|
||||||
let event: &XMotionEvent = event.as_ref();
|
|
||||||
|
|
||||||
if let Some(move_window) = &mut self.move_window {
|
|
||||||
let (x, y) = (
|
|
||||||
event.x - move_window.cached_cursor_position.0,
|
|
||||||
event.y - move_window.cached_cursor_position.1,
|
|
||||||
);
|
|
||||||
|
|
||||||
move_window.cached_cursor_position = (event.x, event.y);
|
|
||||||
|
|
||||||
if let Some(client) =
|
|
||||||
self.clients.get_mut(&move_window.key).into_option()
|
|
||||||
{
|
|
||||||
let position = &mut client.position;
|
|
||||||
position.0 += x;
|
|
||||||
position.1 += y;
|
|
||||||
|
|
||||||
self.xlib.move_client(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_resize_client(&mut self, event: &XEvent) {
|
|
||||||
let clean_mask = self.xlib.get_clean_mask();
|
|
||||||
|
|
||||||
match event.get_type() {
|
|
||||||
xlib::ButtonPress => {
|
|
||||||
let event: &XButtonEvent = event.as_ref();
|
|
||||||
|
|
||||||
if self.resize_window.is_none()
|
|
||||||
&& event.button == 3
|
|
||||||
&& event.state & clean_mask
|
|
||||||
== self.config.mod_key & clean_mask
|
|
||||||
&& self.clients.contains(&event.subwindow)
|
|
||||||
{
|
|
||||||
// if client is tiled, set to floating
|
|
||||||
if self.clients.set_floating(&event.subwindow) {
|
|
||||||
self.arrange_clients();
|
|
||||||
}
|
|
||||||
|
|
||||||
let client = self.clients.get(&event.subwindow).unwrap();
|
|
||||||
|
|
||||||
let position = {
|
|
||||||
(
|
|
||||||
client.position.0 + client.size.0,
|
|
||||||
client.position.1 + client.size.1,
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
self.xlib.move_cursor(client.window, position);
|
|
||||||
self.xlib.grab_cursor();
|
|
||||||
|
|
||||||
self.resize_window = Some(MoveWindow {
|
|
||||||
key: event.subwindow,
|
|
||||||
cached_cursor_position: position,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// reset on release
|
|
||||||
xlib::ButtonRelease => {
|
|
||||||
let event: &XButtonEvent = event.as_ref();
|
|
||||||
|
|
||||||
if event.button == 3 && self.resize_window.is_some() {
|
|
||||||
self.resize_window = None;
|
|
||||||
self.xlib.release_cursor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xlib::MotionNotify => {
|
|
||||||
let event = self.xlib.squash_event(xlib::MotionNotify);
|
|
||||||
let event: &XMotionEvent = event.as_ref();
|
|
||||||
|
|
||||||
if let Some(resize_window) = &mut self.resize_window {
|
|
||||||
info!("MotionNotify-resize");
|
|
||||||
let (x, y) = (
|
|
||||||
event.x - resize_window.cached_cursor_position.0,
|
|
||||||
event.y - resize_window.cached_cursor_position.1,
|
|
||||||
);
|
|
||||||
|
|
||||||
resize_window.cached_cursor_position = (event.x, event.y);
|
|
||||||
|
|
||||||
if let Some(client) =
|
|
||||||
self.clients.get_mut(&resize_window.key).into_option()
|
|
||||||
{
|
|
||||||
let size = &mut client.size;
|
|
||||||
|
|
||||||
size.0 = std::cmp::max(1, size.0 + x);
|
|
||||||
size.1 = std::cmp::max(1, size.1 + y);
|
|
||||||
|
|
||||||
self.xlib.resize_client(client);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn rotate_virtual_screen_back(&mut self) {
|
fn rotate_virtual_screen_back(&mut self) {
|
||||||
if let Some(dir) = self.last_rotation {
|
if let Some(dir) = self.last_rotation {
|
||||||
self.rotate_virtual_screen(!dir);
|
self.rotate_virtual_screen(!dir);
|
||||||
|
@ -563,13 +416,137 @@ impl WindowManager {
|
||||||
self.focus_client(&event.window);
|
self.focus_client(&event.window);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn button_notify(&mut self, event: &XEvent) {
|
/// ensure event.subwindow refers to a valid client.
|
||||||
let event: &XButtonEvent = event.as_ref();
|
fn start_move_resize_window(&mut self, event: &XButtonPressedEvent) {
|
||||||
|
let window = event.subwindow;
|
||||||
|
|
||||||
self.focus_client(&event.subwindow);
|
match event.button {
|
||||||
if let Some(client) = self.clients.get(&event.subwindow).into_option() {
|
1 => {
|
||||||
self.xlib.raise_client(client);
|
if self.clients.set_floating(&window) {
|
||||||
|
self.arrange_clients();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.move_resize_window = MoveResizeInfo::Move(MoveInfoInner {
|
||||||
|
window,
|
||||||
|
starting_cursor_pos: (event.x, event.y),
|
||||||
|
starting_window_pos: self
|
||||||
|
.clients
|
||||||
|
.get(&window)
|
||||||
|
.unwrap()
|
||||||
|
.position,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
3 => {
|
||||||
|
if self.clients.set_floating(&window) {
|
||||||
|
self.arrange_clients();
|
||||||
|
}
|
||||||
|
|
||||||
|
let client = self.clients.get(&window).unwrap();
|
||||||
|
|
||||||
|
let corner_pos = {
|
||||||
|
(
|
||||||
|
client.position.0 + client.size.0,
|
||||||
|
client.position.1 + client.size.1,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.xlib.move_cursor(None, corner_pos);
|
||||||
|
self.xlib.grab_cursor();
|
||||||
|
|
||||||
|
self.move_resize_window =
|
||||||
|
MoveResizeInfo::Resize(ResizeInfoInner {
|
||||||
|
window,
|
||||||
|
starting_cursor_pos: corner_pos,
|
||||||
|
starting_window_size: client.size,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn end_move_resize_window(&mut self, event: &XButtonReleasedEvent) {
|
||||||
|
if event.button == 1 || event.button == 3 {
|
||||||
|
self.move_resize_window = MoveResizeInfo::None;
|
||||||
|
}
|
||||||
|
if event.button == 3 {
|
||||||
|
self.xlib.release_cursor();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_move_resize_window(&mut self, event: &XMotionEvent) {
|
||||||
|
match &self.move_resize_window {
|
||||||
|
MoveResizeInfo::Move(info) => {
|
||||||
|
let (x, y) = (
|
||||||
|
event.x - info.starting_cursor_pos.0,
|
||||||
|
event.y - info.starting_cursor_pos.1,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(client) =
|
||||||
|
self.clients.get_mut(&info.window).into_option()
|
||||||
|
{
|
||||||
|
let position = &mut client.position;
|
||||||
|
|
||||||
|
position.0 = info.starting_window_pos.0 + x;
|
||||||
|
position.1 = info.starting_window_pos.1 + y;
|
||||||
|
|
||||||
|
self.xlib.move_client(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MoveResizeInfo::Resize(info) => {
|
||||||
|
let (x, y) = (
|
||||||
|
event.x - info.starting_cursor_pos.0,
|
||||||
|
event.y - info.starting_cursor_pos.1,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some(client) =
|
||||||
|
self.clients.get_mut(&info.window).into_option()
|
||||||
|
{
|
||||||
|
let size = &mut client.size;
|
||||||
|
|
||||||
|
size.0 = std::cmp::max(1, info.starting_window_size.0 + x);
|
||||||
|
size.1 = std::cmp::max(1, info.starting_window_size.1 + y);
|
||||||
|
|
||||||
|
self.xlib.resize_client(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn button_press(&mut self, event: &XButtonPressedEvent) {
|
||||||
|
self.focus_client(&event.subwindow);
|
||||||
|
|
||||||
|
match event.button {
|
||||||
|
1 | 3 => match self.move_resize_window {
|
||||||
|
MoveResizeInfo::None
|
||||||
|
if self
|
||||||
|
.xlib
|
||||||
|
.are_masks_equal(event.state, self.config.mod_key)
|
||||||
|
&& self.clients.contains(&event.subwindow) =>
|
||||||
|
{
|
||||||
|
self.start_move_resize_window(event)
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
self.clients.toggle_floating(&event.subwindow);
|
||||||
|
self.arrange_clients();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn button_release(&mut self, event: &XButtonReleasedEvent) {
|
||||||
|
match self.move_resize_window {
|
||||||
|
MoveResizeInfo::None => {}
|
||||||
|
_ => {
|
||||||
|
self.end_move_resize_window(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn motion_notify(&mut self, event: &XMotionEvent) {
|
||||||
|
self.do_move_resize_window(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spawn(&self, command: &str, args: &[&str]) {
|
pub fn spawn(&self, command: &str, args: &[&str]) {
|
||||||
|
|
27
src/xlib.rs
27
src/xlib.rs
|
@ -102,6 +102,8 @@ impl XLib {
|
||||||
);
|
);
|
||||||
|
|
||||||
XSetErrorHandler(Some(xlib_error_handler));
|
XSetErrorHandler(Some(xlib_error_handler));
|
||||||
|
|
||||||
|
XSync(self.dpy(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.grab_global_keybinds(self.root);
|
self.grab_global_keybinds(self.root);
|
||||||
|
@ -128,6 +130,7 @@ impl XLib {
|
||||||
self.display.get()
|
self.display.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn squash_event(&self, event_type: i32) -> XEvent {
|
pub fn squash_event(&self, event_type: i32) -> XEvent {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut event =
|
let mut event =
|
||||||
|
@ -260,8 +263,6 @@ impl XLib {
|
||||||
|
|
||||||
// I don't think I have to call this ~
|
// I don't think I have to call this ~
|
||||||
//self.configure_client(client);
|
//self.configure_client(client);
|
||||||
|
|
||||||
xlib::XSync(self.dpy(), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,8 +288,6 @@ impl XLib {
|
||||||
(xlib::CWX | xlib::CWY) as u32,
|
(xlib::CWX | xlib::CWY) as u32,
|
||||||
&mut wc,
|
&mut wc,
|
||||||
);
|
);
|
||||||
|
|
||||||
xlib::XSync(self.dpy(), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,8 +313,6 @@ impl XLib {
|
||||||
(xlib::CWWidth | xlib::CWHeight) as u32,
|
(xlib::CWWidth | xlib::CWHeight) as u32,
|
||||||
&mut wc,
|
&mut wc,
|
||||||
);
|
);
|
||||||
|
|
||||||
xlib::XSync(self.dpy(), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -341,8 +338,6 @@ impl XLib {
|
||||||
(xlib::CWX | xlib::CWY) as u32,
|
(xlib::CWX | xlib::CWY) as u32,
|
||||||
&mut wc,
|
&mut wc,
|
||||||
);
|
);
|
||||||
|
|
||||||
xlib::XSync(self.dpy(), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,7 +345,6 @@ impl XLib {
|
||||||
pub fn raise_client(&self, client: &Client) {
|
pub fn raise_client(&self, client: &Client) {
|
||||||
unsafe {
|
unsafe {
|
||||||
XRaiseWindow(self.dpy(), client.window);
|
XRaiseWindow(self.dpy(), client.window);
|
||||||
XSync(self.dpy(), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,12 +487,12 @@ impl XLib {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn move_cursor(&self, window: Window, position: (i32, i32)) {
|
pub fn move_cursor(&self, window: Option<Window>, position: (i32, i32)) {
|
||||||
unsafe {
|
unsafe {
|
||||||
XWarpPointer(
|
XWarpPointer(
|
||||||
self.dpy(),
|
self.dpy(),
|
||||||
0,
|
0,
|
||||||
window,
|
window.unwrap_or(self.root),
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -621,6 +615,17 @@ impl XLib {
|
||||||
| Mod4Mask
|
| Mod4Mask
|
||||||
| Mod5Mask)
|
| Mod5Mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub fn clean_mask(&self, mask: u32) -> u32 {
|
||||||
|
mask & self.get_clean_mask()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn are_masks_equal(&self, rhs: u32, lhs: u32) -> bool {
|
||||||
|
let clean = self.get_clean_mask();
|
||||||
|
|
||||||
|
rhs & clean == lhs & clean
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display {
|
impl Display {
|
||||||
|
|
Loading…
Reference in a new issue