Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 68 additions & 0 deletions jay-config/src/_private/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,52 @@ impl ConfigClient {
workspace
}

pub fn get_window_position(&self, window: Window) -> (i32, i32) {
let res = self.send_with_response(&ClientMessage::GetWindowPosition { window });
get_response!(res, (0, 0), GetWindowPosition { x, y });
(x, y)
}

pub fn get_window_size(&self, window: Window) -> (i32, i32) {
let res = self.send_with_response(&ClientMessage::GetWindowSize { window });
get_response!(res, (0, 0), GetWindowSize { width, height });
(width, height)
}

#[expect(clippy::too_many_arguments)]
pub fn set_window_position(
&self,
window: Window,
x1: Option<i32>,
y1: Option<i32>,
x2: Option<i32>,
y2: Option<i32>,
width: Option<i32>,
height: Option<i32>,
) {
self.send(&ClientMessage::SetWindowPosition {
window,
x1,
y1,
x2,
y2,
width,
height,
});
}

pub fn get_workspace_position(&self, workspace: Workspace) -> (i32, i32) {
let res = self.send_with_response(&ClientMessage::GetWorkspacePosition { workspace });
get_response!(res, (0, 0), GetWorkspacePosition { x, y });
(x, y)
}

pub fn get_workspace_size(&self, workspace: Workspace) -> (i32, i32) {
let res = self.send_with_response(&ClientMessage::GetWorkspaceSize { workspace });
get_response!(res, (0, 0), GetWorkspaceSize { width, height });
(width, height)
}

pub fn get_seat_keyboard_workspace(&self, seat: Seat) -> Workspace {
let res = self.send_with_response(&ClientMessage::GetSeatKeyboardWorkspace { seat });
get_response!(res, Workspace(0), GetSeatKeyboardWorkspace { workspace });
Expand Down Expand Up @@ -2108,6 +2154,28 @@ impl ConfigClient {
});
}

pub fn set_window_matcher_initial_floating_size(
&self,
matcher: WindowMatcher,
width: i32,
height: i32,
) {
self.send(&ClientMessage::SetWindowMatcherInitialFloatingSize {
matcher,
width,
height,
});
}

pub fn set_window_matcher_initial_floating_position(
&self,
matcher: WindowMatcher,
x: i32,
y: i32,
) {
self.send(&ClientMessage::SetWindowMatcherInitialFloatingPosition { matcher, x, y });
}

pub fn set_window_matcher_latch_handler(
&self,
matcher: WindowMatcher,
Expand Down
47 changes: 47 additions & 0 deletions jay-config/src/_private/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,37 @@ pub enum ClientMessage<'a> {
connector: Connector,
scaling_filter: ScalingFilter,
},
SetWindowMatcherInitialFloatingSize {
matcher: WindowMatcher,
width: i32,
height: i32,
},
SetWindowMatcherInitialFloatingPosition {
matcher: WindowMatcher,
x: i32,
y: i32,
},
GetWindowPosition {
window: Window,
},
GetWindowSize {
window: Window,
},
SetWindowPosition {
window: Window,
x1: Option<i32>,
y1: Option<i32>,
x2: Option<i32>,
y2: Option<i32>,
width: Option<i32>,
height: Option<i32>,
},
GetWorkspacePosition {
workspace: Workspace,
},
GetWorkspaceSize {
workspace: Workspace,
},
}

#[derive(Serialize, Deserialize, Debug)]
Expand Down Expand Up @@ -1239,6 +1270,22 @@ pub enum Response {
GetContainerBorders {
borders: ContainerBorders,
},
GetWindowPosition {
x: i32,
y: i32,
},
GetWindowSize {
width: i32,
height: i32,
},
GetWorkspacePosition {
x: i32,
y: i32,
},
GetWorkspaceSize {
width: i32,
height: i32,
},
}

#[derive(Serialize, Deserialize, Debug)]
Expand Down
15 changes: 15 additions & 0 deletions jay-config/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,21 @@ impl Seat {
self.window().resize(dx1, dy1, dx2, dy2);
}

/// Sets the position and/or size of the focused window.
///
/// See [`Window::set_position`](crate::window::Window::set_position) for details.
pub fn set_position(
self,
x1: Option<i32>,
y1: Option<i32>,
x2: Option<i32>,
y2: Option<i32>,
width: Option<i32>,
height: Option<i32>,
) {
self.window().set_position(x1, y1, x2, y2, width, height);
}

/// Sets whether the cursor should automatically move to the center of a window
/// when focus changes via keyboard commands (move-left, focus-right, show-workspace, etc.).
///
Expand Down
10 changes: 10 additions & 0 deletions jay-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,16 @@ impl Workspace {
pub fn set_initial_connector(self, connector: Option<Connector>) {
get!().set_workspace_initial_connector(self, connector);
}

/// Returns the position of the workspace in the global compositor space.
pub fn position(self) -> (i32, i32) {
get!((0, 0)).get_workspace_position(self)
}

/// Returns the size of the workspace.
pub fn size(self) -> (i32, i32) {
get!((0, 0)).get_workspace_size(self)
}
}

/// Returns the workspace with the given name.
Expand Down
10 changes: 10 additions & 0 deletions jay-config/src/video.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,16 @@ impl Connector {
get!().connector_size(self).1
}

/// Returns the logical size of the connector.
///
/// This is a shortcut for `(width(), height())` that only performs a single round-trip.
pub fn size(self) -> (i32, i32) {
if !self.exists() {
return (0, 0);
}
get!((0, 0)).connector_size(self)
}

/// Returns the refresh rate in mhz of the current mode of the connector.
///
/// This is a shortcut for `mode().refresh_rate()`.
Expand Down
69 changes: 69 additions & 0 deletions jay-config/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,43 @@ impl Window {
pub fn resize(self, dx1: i32, dy1: i32, dx2: i32, dy2: i32) {
get!().resize_window(self, dx1, dy1, dx2, dy2);
}

/// Returns the position of the window in the global compositor space.
pub fn position(self) -> (i32, i32) {
get!((0, 0)).get_window_position(self)
}

/// Returns the size of the window.
pub fn size(self) -> (i32, i32) {
get!((0, 0)).get_window_size(self)
}

/// Sets the position and/or size of the window.
///
/// This only has an effect if the window is floating.
///
/// Every argument that is `None` is left unconstrained by this call. Every argument that
/// is `Some(_)` is constrained to that value.
///
/// Since `x2 = x1 + width` (and analogously for the y axis), not every combination of
/// constraints is satisfiable. If `x1`, `x2`, and `width` are all constrained but not
/// self-consistent (and analogously for `y1`, `y2`, `height`), this call has no effect.
///
/// If fewer than two of `x1`, `x2`, `width` are constrained (and analogously for `y1`,
/// `y2`, `height`), the missing values default to preserving the window's current size,
/// e.g. setting only `width` keeps `x1` fixed and moves `x2`, while setting only `x1` keeps
/// the width fixed and moves `x2` along with it.
pub fn set_position(
self,
x1: Option<i32>,
y1: Option<i32>,
x2: Option<i32>,
y2: Option<i32>,
width: Option<i32>,
height: Option<i32>,
) {
get!().set_window_position(self, x1, y1, x2, y2, width, height);
}
}

/// A window matcher.
Expand Down Expand Up @@ -354,6 +391,24 @@ impl WindowCriterion<'_> {
pub fn set_initial_tile_state(self, tile_state: TileState) {
self.to_matcher().set_initial_tile_state(tile_state);
}

/// Sets the initial size of matched windows while they are floating.
///
/// If multiple such window matchers match a window, the used size is unspecified.
///
/// This leaks the matcher.
pub fn set_initial_floating_size(self, width: i32, height: i32) {
self.to_matcher().set_initial_floating_size(width, height);
}

/// Sets the initial position of matched windows while they are floating.
///
/// If multiple such window matchers match a window, the used position is unspecified.
///
/// This leaks the matcher.
pub fn set_initial_floating_position(self, x: i32, y: i32) {
self.to_matcher().set_initial_floating_position(x, y);
}
}

impl WindowMatcher {
Expand Down Expand Up @@ -387,6 +442,20 @@ impl WindowMatcher {
pub fn set_initial_tile_state(self, tile_state: TileState) {
get!().set_window_matcher_initial_tile_state(self, tile_state);
}

/// Sets the initial size of matched windows while they are floating.
///
/// If multiple such window matchers match a window, the used size is unspecified.
pub fn set_initial_floating_size(self, width: i32, height: i32) {
get!().set_window_matcher_initial_floating_size(self, width, height);
}

/// Sets the initial position of matched windows while they are floating.
///
/// If multiple such window matchers match a window, the used position is unspecified.
pub fn set_initial_floating_position(self, x: i32, y: i32) {
get!().set_window_matcher_initial_floating_position(self, x, y);
}
}

impl MatchedWindow {
Expand Down
10 changes: 10 additions & 0 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,14 @@ impl ConfigProxy {
self.handler.get()?.initial_tile_state(data)
}

pub fn initial_floating_size(&self, data: &ToplevelData) -> Option<(i32, i32)> {
self.handler.get()?.initial_floating_size(data)
}

pub fn initial_floating_position(&self, data: &ToplevelData) -> Option<(i32, i32)> {
self.handler.get()?.initial_floating_position(data)
}

pub fn initial_output_for_workspace(&self, name: &str) -> Option<Option<Rc<OutputNode>>> {
self.handler.get()?.initial_output_for_workspace(name)
}
Expand Down Expand Up @@ -281,6 +289,8 @@ impl ConfigProxy {
window_matcher_std_kinds: state.tl_matcher_manager.kind(window::CLIENT_WINDOW),
window_matcher_no_auto_focus: Default::default(),
window_matcher_initial_tile_state: Default::default(),
window_matcher_initial_floating_size: Default::default(),
window_matcher_initial_floating_position: Default::default(),
});
let init_msg = bincode_ops()
.serialize(&InitMessage::V1(V1InitMessage {}))
Expand Down
Loading
Loading