1
0
Fork 0
forked from wry/wry

config: add Seat.get_keyboard_output and Connector.workspaces

This commit is contained in:
khyperia 2025-04-26 15:48:02 +02:00 committed by Julian Orth
parent b83bf0657b
commit 00735e4621
7 changed files with 127 additions and 30 deletions

View file

@ -417,6 +417,12 @@ impl Client {
workspace
}
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 });
workspace
}
pub fn set_default_workspace_capture(&self, capture: bool) {
self.send(&ClientMessage::SetDefaultWorkspaceCapture { capture });
}
@ -1076,6 +1082,19 @@ impl Client {
self.send(&ClientMessage::SetEiSocketEnabled { enabled })
}
pub fn get_connector_active_workspace(&self, connector: Connector) -> Workspace {
let res =
self.send_with_response(&ClientMessage::GetConnectorActiveWorkspace { connector });
get_response!(res, Workspace(0), GetConnectorActiveWorkspace { workspace });
workspace
}
pub fn get_connector_workspaces(&self, connector: Connector) -> Vec<Workspace> {
let res = self.send_with_response(&ClientMessage::GetConnectorWorkspaces { connector });
get_response!(res, vec![], GetConnectorWorkspaces { workspaces });
workspaces
}
pub fn latch<F: FnOnce() + 'static>(&self, seat: Seat, f: F) {
if !self.feat_mod_mask.get() {
log::error!("compositor does not support latching");

View file

@ -556,6 +556,15 @@ pub enum ClientMessage<'a> {
SetShowFloatPinIcon {
show: bool,
},
GetSeatKeyboardWorkspace {
seat: Seat,
},
GetConnectorActiveWorkspace {
connector: Connector,
},
GetConnectorWorkspaces {
connector: Connector,
},
}
#[derive(Serialize, Deserialize, Debug)]
@ -710,6 +719,15 @@ pub enum Response {
GetFloatPinned {
pinned: bool,
},
GetSeatKeyboardWorkspace {
workspace: Workspace,
},
GetConnectorActiveWorkspace {
workspace: Workspace,
},
GetConnectorWorkspaces {
workspaces: Vec<Workspace>,
},
}
#[derive(Serialize, Deserialize, Debug)]

View file

@ -359,6 +359,14 @@ impl Seat {
get!(Workspace(0)).get_seat_workspace(self)
}
/// Returns the workspace that is currently active on the output that contains the seat's
/// keyboard focus.
///
/// If no such workspace exists, `exists` returns `false` for the returned workspace.
pub fn get_keyboard_workspace(self) -> Workspace {
get!(Workspace(0)).get_seat_keyboard_workspace(self)
}
/// Shows the workspace and sets the keyboard focus of the seat to that workspace.
///
/// If the workspace doesn't currently exist, it is created on the output that contains the

View file

@ -3,7 +3,7 @@
use {
crate::{
_private::WireMode,
PciId,
PciId, Workspace,
video::connector_type::{
CON_9PIN_DIN, CON_COMPONENT, CON_COMPOSITE, CON_DISPLAY_PORT, CON_DPI, CON_DSI,
CON_DVIA, CON_DVID, CON_DVII, CON_EDP, CON_EMBEDDED_WINDOW, CON_HDMIA, CON_HDMIB,
@ -301,6 +301,21 @@ impl Connector {
pub fn set_brightness(self, brightness: Option<f64>) {
get!().connector_set_brightness(self, brightness);
}
/// Get the currently visible/active workspace.
///
/// If this connector is not connected, or is there no active workspace, returns a
/// workspace whose `exists()` returns false.
pub fn active_workspace(self) -> Workspace {
get!(Workspace(0)).get_connector_active_workspace(self)
}
/// Get all workspaces on this connector.
///
/// If this connector is not connected, returns an empty list.
pub fn workspaces(self) -> Vec<Workspace> {
get!().get_connector_workspaces(self)
}
}
/// Returns all available DRM devices.

View file

@ -137,6 +137,20 @@ impl ConfigProxyHandler {
self.next_id.fetch_add(1)
}
fn get_workspace_by_name(&self, name: &String) -> Workspace {
let id = match self.workspaces_by_name.get(name) {
None => {
let id = self.workspace_ids.fetch_add(1);
let name = Rc::new(name.clone());
self.workspaces_by_name.set(name.clone(), id);
self.workspaces_by_id.set(id, name);
id
}
Some(id) => id,
};
Workspace(id)
}
fn handle_log_request(
&self,
level: LogLevel,
@ -410,17 +424,7 @@ impl ConfigProxyHandler {
fn handle_get_workspaces(&self) {
let mut workspaces = vec![];
for ws in self.state.workspaces.lock().values() {
let id = match self.workspaces_by_name.get(&ws.name) {
None => {
let id = self.workspace_ids.fetch_add(1);
let name = Rc::new(ws.name.clone());
self.workspaces_by_name.set(name.clone(), id);
self.workspaces_by_id.set(id, name);
id
}
Some(id) => id,
};
workspaces.push(Workspace(id));
workspaces.push(self.get_workspace_by_name(&ws.name));
}
self.respond(Response::GetWorkspaces { workspaces });
}
@ -708,18 +712,8 @@ impl ConfigProxyHandler {
}
fn handle_get_workspace(&self, name: &str) {
let name = Rc::new(name.to_owned());
let ws = match self.workspaces_by_name.get(&name) {
Some(w) => w,
_ => {
let ws = self.workspace_ids.fetch_add(1);
self.workspaces_by_name.set(name.clone(), ws);
self.workspaces_by_id.set(ws, name);
ws
}
};
self.respond(Response::GetWorkspace {
workspace: Workspace(ws),
workspace: self.get_workspace_by_name(&name.to_owned()),
});
}
@ -818,17 +812,27 @@ impl ConfigProxyHandler {
fn handle_get_seat_workspace(&self, seat: Seat) -> Result<(), CphError> {
let seat = self.get_seat(seat)?;
let output = seat.get_output();
let mut workspace = 0;
let mut workspace = Workspace(0);
if !output.is_dummy {
if let Some(ws) = output.workspace.get() {
if let Some(ws) = self.workspaces_by_name.get(&ws.name) {
workspace = ws;
workspace = self.get_workspace_by_name(&ws.name);
}
}
self.respond(Response::GetSeatWorkspace { workspace });
Ok(())
}
fn handle_get_seat_keyboard_workspace(&self, seat: Seat) -> Result<(), CphError> {
let seat = self.get_seat(seat)?;
let mut workspace = Workspace(0);
if let Some(output) = seat.get_keyboard_output() {
if !output.is_dummy {
if let Some(ws) = output.workspace.get() {
workspace = self.get_workspace_by_name(&ws.name);
}
}
}
self.respond(Response::GetSeatWorkspace {
workspace: Workspace(workspace),
});
self.respond(Response::GetSeatKeyboardWorkspace { workspace });
Ok(())
}
@ -1292,6 +1296,27 @@ impl ConfigProxyHandler {
Ok(())
}
fn handle_get_connector_active_workspace(&self, connector: Connector) -> Result<(), CphError> {
let output = self.get_output_node(connector)?;
let workspace = output
.workspace
.get()
.map_or(Workspace(0), |ws| self.get_workspace_by_name(&ws.name));
self.respond(Response::GetConnectorActiveWorkspace { workspace });
Ok(())
}
fn handle_get_connector_workspaces(&self, connector: Connector) -> Result<(), CphError> {
let output = self.get_output_node(connector)?;
let workspaces = output
.workspaces
.iter()
.map(|ws| self.get_workspace_by_name(&ws.name))
.collect::<Vec<_>>();
self.respond(Response::GetConnectorWorkspaces { workspaces });
Ok(())
}
fn handle_has_capability(&self, device: InputDevice, cap: Capability) -> Result<(), CphError> {
let dev = self.get_device_handler_data(device)?;
let mut is_unknown = false;
@ -1904,6 +1929,9 @@ impl ConfigProxyHandler {
ClientMessage::GetSeatWorkspace { seat } => self
.handle_get_seat_workspace(seat)
.wrn("get_seat_workspace")?,
ClientMessage::GetSeatKeyboardWorkspace { seat } => self
.handle_get_seat_keyboard_workspace(seat)
.wrn("get_seat_keyboard_workspace")?,
ClientMessage::SetDefaultWorkspaceCapture { capture } => {
self.handle_set_default_workspace_capture(capture)
}
@ -2092,6 +2120,12 @@ impl ConfigProxyHandler {
ClientMessage::SetShowFloatPinIcon { show } => {
self.handle_set_show_float_pin_icon(show)
}
ClientMessage::GetConnectorActiveWorkspace { connector } => self
.handle_get_connector_active_workspace(connector)
.wrn("get_connector_active_workspace")?,
ClientMessage::GetConnectorWorkspaces { connector } => self
.handle_get_connector_workspaces(connector)
.wrn("get_connector_workspaces")?,
}
Ok(())
}

View file

@ -401,6 +401,10 @@ impl WlSeatGlobal {
self.cursor_user_group.latest_output()
}
pub fn get_keyboard_output(&self) -> Option<Rc<OutputNode>> {
self.keyboard_node.get().node_output()
}
pub fn set_workspace(&self, ws: &Rc<WorkspaceNode>) {
let tl = match self.keyboard_node.get().node_toplevel() {
Some(tl) => tl,

View file

@ -122,7 +122,6 @@ pub trait Node: 'static {
fn node_visit_children(&self, visitor: &mut dyn NodeVisitor);
fn node_visible(&self) -> bool;
fn node_absolute_position(&self) -> Rect;
#[expect(dead_code)]
fn node_output(&self) -> Option<Rc<OutputNode>>;
fn node_child_title_changed(self: Rc<Self>, child: &dyn Node, title: &str) {