1
0
Fork 0
forked from wry/wry

config: allow configuring client capabilities

This commit is contained in:
Julian Orth 2025-09-18 21:06:28 +02:00
parent 76a1a86091
commit e680a3dc09
21 changed files with 624 additions and 39 deletions

View file

@ -12,7 +12,7 @@ use {
logging,
},
Axis, Direction, ModifiedKeySym, PciId, Workspace,
client::{Client, ClientCriterion, ClientMatcher, MatchedClient},
client::{Client, ClientCapabilities, ClientCriterion, ClientMatcher, MatchedClient},
exec::Command,
input::{
FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, SwitchEvent, Timeline,
@ -1343,6 +1343,22 @@ impl ConfigClient {
workspaces
}
pub fn set_client_matcher_capabilities(
&self,
matcher: ClientMatcher,
caps: ClientCapabilities,
) {
self.send(&ClientMessage::SetClientMatcherCapabilities { matcher, caps });
}
pub fn set_client_matcher_bounding_capabilities(
&self,
matcher: ClientMatcher,
caps: ClientCapabilities,
) {
self.send(&ClientMessage::SetClientMatcherBoundingCapabilities { matcher, caps });
}
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

@ -2,7 +2,7 @@ use {
crate::{
_private::{ClientCriterionIpc, PollableId, WindowCriterionIpc, WireMode},
Axis, Direction, PciId, Workspace,
client::{Client, ClientMatcher},
client::{Client, ClientCapabilities, ClientMatcher},
input::{
FocusFollowsMouseMode, InputDevice, LayerDirection, Seat, SwitchEvent, Timeline,
acceleration::AccelProfile, capability::Capability, clickmethod::ClickMethod,
@ -774,6 +774,14 @@ pub enum ClientMessage<'a> {
SetTitleFont {
font: &'a str,
},
SetClientMatcherCapabilities {
matcher: ClientMatcher,
caps: ClientCapabilities,
},
SetClientMatcherBoundingCapabilities {
matcher: ClientMatcher,
caps: ClientCapabilities,
},
}
#[derive(Serialize, Deserialize, Debug)]

View file

@ -105,6 +105,20 @@ impl ClientCriterion<'_> {
pub fn bind<F: FnMut(MatchedClient) + 'static>(self, cb: F) {
self.to_matcher().bind(cb);
}
/// Sets the capabilities granted to clients matching this matcher.
///
/// This leaks the matcher.
pub fn set_capabilities(self, caps: ClientCapabilities) {
self.to_matcher().set_capabilities(caps);
}
/// Sets the upper capability bounds for clients in sandboxes created by this client.
///
/// This leaks the matcher.
pub fn set_sandbox_bounding_capabilities(self, caps: ClientCapabilities) {
self.to_matcher().set_sandbox_bounding_capabilities(caps);
}
}
impl ClientMatcher {
@ -121,6 +135,36 @@ impl ClientMatcher {
pub fn bind<F: FnMut(MatchedClient) + 'static>(self, cb: F) {
get!().set_client_matcher_handler(self, cb);
}
/// Sets the capabilities granted to clients matching this matcher.
///
/// If multiple matchers match a client, the capabilities are added.
///
/// If no matcher matches a client, it is granted the default capabilities depending
/// on whether it's sandboxed or not. If it is not sandboxed, it is granted the
/// capabilities [`CC_LAYER_SHELL`] and [`CC_DRM_LEASE`]. Otherwise it is granted the
/// capability [`CC_DRM_LEASE`].
///
/// Regardless of any capabilities set through this function, the capabilities of the
/// client can never exceed its bounding capabilities.
pub fn set_capabilities(self, caps: ClientCapabilities) {
get!().set_client_matcher_capabilities(self, caps);
}
/// Sets the upper capability bounds for clients in sandboxes created by this client.
///
/// If multiple matchers match a client, the capabilities are added.
///
/// If no matcher matches a client, the bounding capabilities for sandboxes depend on
/// whether the client is itself sandboxed. If it is sandboxed, the bounding
/// capabilities are the effective capabilities of the client. Otherwise the bounding
/// capabilities are all capabilities.
///
/// Regardless of any capabilities set through this function, the capabilities set
/// through this function can never exceed the client's bounding capabilities.
pub fn set_sandbox_bounding_capabilities(self, caps: ClientCapabilities) {
get!().set_client_matcher_bounding_capabilities(self, caps);
}
}
impl MatchedClient {
@ -147,3 +191,39 @@ impl Deref for MatchedClient {
&self.client
}
}
bitflags! {
/// Capabilities granted to a client.
#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq)]
pub struct ClientCapabilities(pub u64) {
/// Grants access to the `ext_data_control_manager_v1` and
/// `zwlr_data_control_manager_v1` globals.
pub const CC_DATA_CONTROL = 1 << 0,
/// Grants access to the `zwp_virtual_keyboard_manager_v1` global.
pub const CC_VIRTUAL_KEYBOARD = 1 << 1,
/// Grants access to the `ext_foreign_toplevel_list_v1` global.
pub const CC_FOREIGN_TOPLEVEL_LIST = 1 << 2,
/// Grants access to the `ext_idle_notifier_v1` global.
pub const CC_IDLE_NOTIFIER = 1 << 3,
/// Grants access to the `ext_session_lock_manager_v1` global.
pub const CC_SESSION_LOCK = 1 << 4,
/// Grants access to the `zwlr_layer_shell_v1` global.
pub const CC_LAYER_SHELL = 1 << 6,
/// Grants access to the `ext_image_copy_capture_manager_v1` and
/// `zwlr_screencopy_manager_v1` globals.
pub const CC_SCREENCOPY = 1 << 7,
/// Grants access to the `ext_transient_seat_manager_v1` global.
pub const CC_SEAT_MANAGER = 1 << 8,
/// Grants access to the `wp_drm_lease_device_v1` global.
pub const CC_DRM_LEASE = 1 << 9,
/// Grants access to the `zwp_input_method_manager_v2` global.
pub const CC_INPUT_METHOD = 1 << 10,
/// Grants access to the `ext_workspace_manager_v1` global.
pub const CC_WORKSPACE_MANAGER = 1 << 11,
/// Grants access to the `zwlr_foreign_toplevel_manager_v1` global.
pub const CC_FOREIGN_TOPLEVEL_MANAGER = 1 << 12,
/// Grants access to the `jay_head_manager_v1` and `zwlr_output_manager_v1`
/// globals.
pub const CC_HEAD_MANAGER = 1 << 13,
}
}