Skip to content

Commit

Permalink
add lua methods to access position and pane in the direction
Browse files Browse the repository at this point in the history
  • Loading branch information
Maxim Sokolov committed Jan 25, 2023
1 parent 9d7e613 commit 2c0099a
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 11 deletions.
19 changes: 19 additions & 0 deletions lua-api-crates/mux/src/tab.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use config::keyassignment::PaneDirection;

use super::*;
use luahelper::to_lua;
use std::sync::Arc;
Expand Down Expand Up @@ -53,6 +55,23 @@ impl UserData for MuxTab {
.collect::<Vec<MuxPane>>())
});

methods.add_method("get_pane_direction", |_, this, direction: String| {
let mux = get_mux()?;
let tab = this.resolve(&mux)?;
let panes = tab.iter_panes_ignoring_zoom();

let dir = PaneDirection::direction_from_str(&direction).map_err(|err| {
mlua::Error::external(format!(
"Unable to convert direction '{}'. Error: {}",
direction, err
))
})?;
let pane = tab
.get_pane_direction(dir, true)
.map(|pane_index| MuxPane(panes[pane_index].pane.pane_id()));
Ok(pane)
});

methods.add_method("set_zoomed", |_, this, zoomed: bool| {
let mux = get_mux()?;
let tab = this.resolve(&mux)?;
Expand Down
39 changes: 28 additions & 11 deletions mux/src/tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,14 @@ impl Tab {
self.inner.lock().activate_pane_direction(direction)
}

/// Returns an adjacent pane in the specified direction.
/// In cases where there are multiple adjacent panes in the
/// intended direction, we take the pane that has the largest
/// edge intersection.
pub fn get_pane_direction(&self, direction: PaneDirection, ignore_zoom: bool) -> Option<usize> {
self.inner.lock().get_pane_direction(direction, ignore_zoom)
}

pub fn prune_dead_panes(&self) -> bool {
self.inner.lock().prune_dead_panes()
}
Expand Down Expand Up @@ -1410,34 +1418,42 @@ impl TabInner {
}
self.toggle_zoom();
}
let panes = self.iter_panes();
if let Some(panel_idx) = self.get_pane_direction(direction, false) {
self.set_active_idx(panel_idx);
}
}

fn get_pane_direction(&mut self, direction: PaneDirection, ignore_zoom: bool) -> Option<usize> {
let panes = if ignore_zoom {
self.iter_panes_ignoring_zoom()
} else {
self.iter_panes()
};

let active = match panes.iter().find(|pane| pane.is_active) {
Some(p) => p,
None => {
// No active pane somehow...
self.set_active_idx(0);
return;
return Some(0);
}
};

if matches!(direction, PaneDirection::Next | PaneDirection::Prev) {
let max_pane_id = panes.iter().map(|p| p.index).max().unwrap_or(active.index);

if direction == PaneDirection::Next {
self.set_active_idx(if active.index == max_pane_id {
return Some(if direction == PaneDirection::Next {
if active.index == max_pane_id {
0
} else {
active.index + 1
});
}
} else {
self.set_active_idx(if active.index == 0 {
if active.index == 0 {
max_pane_id
} else {
active.index - 1
});
}
return;
}
});
}

let mut best = None;
Expand Down Expand Up @@ -1508,8 +1524,9 @@ impl TabInner {
drop(recency);

if let Some((_, target)) = best.take() {
self.set_active_idx(target.index);
return Some(target.index);
}
None
}

fn prune_dead_panes(&mut self) -> bool {
Expand Down
16 changes: 16 additions & 0 deletions wezterm-gui/src/scripting/guiwin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ impl UserData for GuiWin {
Ok(())
},
);
methods.add_async_method("get_position", |_, this, _: ()| async move {
let p = this
.window
.get_window_position()
.await
.map_err(|e| anyhow::anyhow!("{:#}", e))
.map_err(luaerr)?;
#[derive(FromDynamic, ToDynamic)]
struct Point {
x: isize,
y: isize,
}
impl_lua_conversion_dynamic!(Point);
let p = Point { x: p.x, y: p.y };
Ok(p)
});
methods.add_method("set_position", |_, this, (x, y): (isize, isize)| {
this.window.set_window_position(euclid::point2(x, y));
Ok(())
Expand Down
8 changes: 8 additions & 0 deletions window/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,14 @@ pub trait WindowOps {
/// click before forwarding the event (Windows).
fn set_window_drag_position(&self, _coords: ScreenPoint) {}

/// Returns the location of the window on the screen.
/// The coordinates are of the top left pixel of the
/// client area.
///
/// This is only implemented on backends that allow
/// windows to move themselves (not Wayland).
fn get_window_position(&self) -> Future<ScreenPoint>;

/// Changes the location of the window on the screen.
/// The coordinates are of the top left pixel of the
/// client area.
Expand Down
18 changes: 18 additions & 0 deletions window/src/os/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,10 @@ impl WindowOps for Window {
);
}

fn get_window_position(&self) -> Future<ScreenPoint> {
Connection::with_window_inner(self.id, move |inner| Ok(inner.get_window_position()))
}

fn set_window_position(&self, coords: ScreenPoint) {
Connection::with_window_inner(self.id, move |inner| {
inner.set_window_position(coords);
Expand Down Expand Up @@ -1084,6 +1088,20 @@ impl WindowInner {
}
}

fn get_window_position(&self) -> ScreenPoint {
unsafe {
let frame = NSWindow::frame(*self.window);
let content_frame = NSWindow::contentRectForFrameRect_(*self.window, frame);
let delta_x = content_frame.origin.x - frame.origin.x;
let delta_y = content_frame.origin.y - frame.origin.y;
let cartesian = NSPoint::new(
frame.origin.x as f64 + delta_x,
frame.origin.y as f64 + delta_y + content_frame.size.height,
);
cartesian_to_screen_point(cartesian)
}
}

fn set_text_cursor_position(&mut self, cursor: Rect) {
if let Some(window_view) = WindowView::get_this(unsafe { &**self.view }) {
window_view.inner.borrow_mut().text_cursor_position = cursor;
Expand Down

0 comments on commit 2c0099a

Please sign in to comment.