all: split reusable components into workspace crates
This commit is contained in:
parent
2a079ed800
commit
657e7ce2f7
225 changed files with 7422 additions and 17602 deletions
|
|
@ -12,7 +12,6 @@ use {
|
|||
},
|
||||
bincode::Options,
|
||||
serde::{Deserialize, Serialize},
|
||||
std::marker::PhantomData,
|
||||
};
|
||||
|
||||
pub const VERSION: u32 = 1;
|
||||
|
|
@ -31,12 +30,6 @@ pub struct ConfigEntry {
|
|||
pub handle_msg: unsafe extern "C" fn(data: *const u8, msg: *const u8, size: usize),
|
||||
}
|
||||
|
||||
pub struct ConfigEntryGen<T> {
|
||||
_phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T: Config> ConfigEntryGen<T> {}
|
||||
|
||||
pub fn bincode_ops() -> impl Options {
|
||||
bincode::DefaultOptions::new()
|
||||
.with_fixint_encoding()
|
||||
|
|
@ -44,10 +37,6 @@ pub fn bincode_ops() -> impl Options {
|
|||
.with_no_limit()
|
||||
}
|
||||
|
||||
pub trait Config {
|
||||
extern "C" fn configure();
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WireMode {
|
||||
pub width: i32,
|
||||
|
|
@ -99,7 +88,6 @@ pub enum ClientCriterionStringField {
|
|||
SandboxInstanceId,
|
||||
Comm,
|
||||
Exe,
|
||||
Tag,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
|
|
|
|||
|
|
@ -3,16 +3,14 @@
|
|||
use {
|
||||
crate::{
|
||||
_private::{
|
||||
ClientCriterionIpc, ClientCriterionStringField, Config, ConfigEntry, ConfigEntryGen,
|
||||
GenericCriterionIpc, PollableId, VERSION, WindowCriterionIpc,
|
||||
WindowCriterionStringField, WireMode, bincode_ops,
|
||||
ClientCriterionIpc, ClientCriterionStringField, GenericCriterionIpc, PollableId,
|
||||
WindowCriterionIpc, WindowCriterionStringField, WireMode, bincode_ops,
|
||||
ipc::{
|
||||
ClientMessage, InitMessage, Response, ServerFeature, ServerMessage, WorkspaceSource,
|
||||
},
|
||||
logging,
|
||||
},
|
||||
Axis, Direction, ModifiedKeySym, PciId, Workspace,
|
||||
client::{Client, ClientCapabilities, ClientCriterion, ClientMatcher, MatchedClient},
|
||||
client::{Client, ClientCriterion, ClientMatcher, MatchedClient},
|
||||
exec::Command,
|
||||
input::{
|
||||
FallbackOutputMode, FocusFollowsMouseMode, InputDevice, LayerDirection, Seat,
|
||||
|
|
@ -199,35 +197,6 @@ unsafe fn with_client<T, F: FnOnce(&ConfigClient) -> T>(data: *const u8, f: F) -
|
|||
})
|
||||
}
|
||||
|
||||
impl<T: Config> ConfigEntryGen<T> {
|
||||
pub const ENTRY: ConfigEntry = ConfigEntry {
|
||||
version: VERSION,
|
||||
init: Self::init,
|
||||
unref,
|
||||
handle_msg,
|
||||
};
|
||||
|
||||
pub unsafe extern "C" fn init(
|
||||
srv_data: *const u8,
|
||||
srv_unref: unsafe extern "C" fn(data: *const u8),
|
||||
srv_handler: unsafe extern "C" fn(data: *const u8, msg: *const u8, size: usize),
|
||||
init_data: *const u8,
|
||||
size: usize,
|
||||
) -> *const u8 {
|
||||
logging::init();
|
||||
unsafe {
|
||||
init(
|
||||
srv_data,
|
||||
srv_unref,
|
||||
srv_handler,
|
||||
init_data,
|
||||
size,
|
||||
T::configure,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe extern "C" fn init(
|
||||
srv_data: *const u8,
|
||||
srv_unref: unsafe extern "C" fn(data: *const u8),
|
||||
|
|
@ -348,15 +317,7 @@ impl ConfigClient {
|
|||
.drain()
|
||||
.map(|(a, b)| (a, b.into_raw_fd()))
|
||||
.collect();
|
||||
if command.tag.is_some() {
|
||||
self.send(&ClientMessage::Run3 {
|
||||
prog: &command.prog,
|
||||
args: command.args.clone(),
|
||||
env,
|
||||
fds,
|
||||
tag: command.tag.as_deref(),
|
||||
});
|
||||
} else if fds.is_empty() {
|
||||
if fds.is_empty() {
|
||||
self.send(&ClientMessage::Run {
|
||||
prog: &command.prog,
|
||||
args: command.args.clone(),
|
||||
|
|
@ -1556,22 +1517,6 @@ impl ConfigClient {
|
|||
connector
|
||||
}
|
||||
|
||||
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");
|
||||
|
|
@ -1673,12 +1618,6 @@ impl ConfigClient {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn get_socket_path(&self) -> Option<String> {
|
||||
let res = self.send_with_response(&ClientMessage::GetSocketPath);
|
||||
get_response!(res, None, GetSocketPath { path });
|
||||
Some(path)
|
||||
}
|
||||
|
||||
pub fn create_pollable(&self, fd: i32) -> Result<PollableId, String> {
|
||||
let res = self.send_with_response(&ClientMessage::AddPollable { fd });
|
||||
get_response!(
|
||||
|
|
@ -1867,8 +1806,6 @@ impl ConfigClient {
|
|||
ClientCriterion::CommRegex(t) => string!(t, Comm, true),
|
||||
ClientCriterion::Exe(t) => string!(t, Exe, false),
|
||||
ClientCriterion::ExeRegex(t) => string!(t, Exe, true),
|
||||
ClientCriterion::Tag(t) => string!(t, Tag, false),
|
||||
ClientCriterion::TagRegex(t) => string!(t, Tag, true),
|
||||
};
|
||||
let res = self.send_with_response(&ClientMessage::CreateClientMatcher { criterion });
|
||||
get_response!(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ use {
|
|||
crate::{
|
||||
_private::{ClientCriterionIpc, PollableId, WindowCriterionIpc, WireMode},
|
||||
Axis, Direction, PciId, Workspace,
|
||||
client::{Client, ClientCapabilities, ClientMatcher},
|
||||
client::{Client, ClientMatcher},
|
||||
input::{
|
||||
FallbackOutputMode, FocusFollowsMouseMode, InputDevice, LayerDirection, Seat,
|
||||
SwitchEvent, Timeline, acceleration::AccelProfile, capability::Capability,
|
||||
|
|
@ -488,7 +488,6 @@ pub enum ClientMessage<'a> {
|
|||
SetExplicitSyncEnabled {
|
||||
enabled: bool,
|
||||
},
|
||||
GetSocketPath,
|
||||
DeviceSetKeymap {
|
||||
device: InputDevice,
|
||||
keymap: Keymap,
|
||||
|
|
@ -806,14 +805,6 @@ pub enum ClientMessage<'a> {
|
|||
SetTitleFont {
|
||||
font: &'a str,
|
||||
},
|
||||
SetClientMatcherCapabilities {
|
||||
matcher: ClientMatcher,
|
||||
caps: ClientCapabilities,
|
||||
},
|
||||
SetClientMatcherBoundingCapabilities {
|
||||
matcher: ClientMatcher,
|
||||
caps: ClientCapabilities,
|
||||
},
|
||||
ShowWorkspaceOn {
|
||||
seat: Seat,
|
||||
workspace: Workspace,
|
||||
|
|
@ -868,13 +859,6 @@ pub enum ClientMessage<'a> {
|
|||
SetXWaylandEnabled {
|
||||
enabled: bool,
|
||||
},
|
||||
Run3 {
|
||||
prog: &'a str,
|
||||
args: Vec<String>,
|
||||
env: Vec<(String, String)>,
|
||||
fds: Vec<(i32, i32)>,
|
||||
tag: Option<&'a str>,
|
||||
},
|
||||
ConnectorSupportsArbitraryModes {
|
||||
connector: Connector,
|
||||
},
|
||||
|
|
@ -1081,9 +1065,6 @@ pub enum Response {
|
|||
GetInputDeviceDevnode {
|
||||
devnode: String,
|
||||
},
|
||||
GetSocketPath {
|
||||
path: String,
|
||||
},
|
||||
GetFloatAboveFullscreen {
|
||||
above: bool,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -91,10 +91,6 @@ pub enum ClientCriterion<'a> {
|
|||
Exe(&'a str),
|
||||
/// Matches the `/proc/pid/exe` of the client with a regular expression.
|
||||
ExeRegex(&'a str),
|
||||
/// Matches the tag of the client verbatim.
|
||||
Tag(&'a str),
|
||||
/// Matches the tag of the client with a regular expression.
|
||||
TagRegex(&'a str),
|
||||
}
|
||||
|
||||
impl ClientCriterion<'_> {
|
||||
|
|
@ -110,19 +106,6 @@ impl ClientCriterion<'_> {
|
|||
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 {
|
||||
|
|
@ -140,35 +123,6 @@ impl ClientMatcher {
|
|||
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 {
|
||||
|
|
@ -195,45 +149,3 @@ 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,
|
||||
/// Grants access to the `zwlr_gamma_control_manager_v1` global.
|
||||
pub const CC_GAMMA_CONTROL_MANAGER = 1 << 14,
|
||||
/// Grants access to the `zwlr_virtual_pointer_manager_v1` global.
|
||||
pub const CC_VIRTUAL_POINTER = 1 << 15,
|
||||
/// Grants access to the `ext_foreign_toplevel_geometry_tracking_manager_v1` global.
|
||||
pub const CC_FOREIGN_TOPLEVEL_GEOMETRY_TRACKING = 1 << 16,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,6 @@ pub struct Command {
|
|||
pub(crate) args: Vec<String>,
|
||||
pub(crate) env: HashMap<String, String>,
|
||||
pub(crate) fds: RefCell<HashMap<i32, OwnedFd>>,
|
||||
pub(crate) tag: Option<String>,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
|
|
@ -38,7 +37,6 @@ impl Command {
|
|||
args: vec![],
|
||||
env: Default::default(),
|
||||
fds: Default::default(),
|
||||
tag: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -84,27 +82,6 @@ impl Command {
|
|||
self.fd(2, fd)
|
||||
}
|
||||
|
||||
/// Runs the application with access to privileged wayland protocols.
|
||||
///
|
||||
/// The default is `false`.
|
||||
pub fn privileged(&mut self) -> &mut Self {
|
||||
match get!(self).get_socket_path() {
|
||||
Some(path) => {
|
||||
self.env("WAYLAND_DISPLAY", &format!("{path}.jay"));
|
||||
}
|
||||
_ => {
|
||||
log::error!("Compositor did not send the socket path");
|
||||
}
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a tag to Wayland connections created by the spawned command.
|
||||
pub fn tag(&mut self, tag: &str) -> &mut Self {
|
||||
self.tag = Some(tag.to_owned());
|
||||
self
|
||||
}
|
||||
|
||||
/// Executes the command.
|
||||
///
|
||||
/// This consumes all attached file descriptors.
|
||||
|
|
|
|||
|
|
@ -832,8 +832,6 @@ pub enum SwitchEvent {
|
|||
|
||||
/// Enables or disables the unauthenticated libei socket.
|
||||
///
|
||||
/// Even if the socket is disabled, application can still request access via the portal.
|
||||
///
|
||||
/// The default is `false`.
|
||||
pub fn set_libei_socket_enabled(enabled: bool) {
|
||||
get!().set_ei_socket_enabled(enabled);
|
||||
|
|
|
|||
|
|
@ -1,36 +1,5 @@
|
|||
//! This crate allows you to configure the Jay compositor.
|
||||
//!
|
||||
//! A minimal example configuration looks as follows:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use jay_config::{config, quit, reload};
|
||||
//! use jay_config::input::get_default_seat;
|
||||
//! use jay_config::keyboard::mods::ALT;
|
||||
//! use jay_config::keyboard::syms::{SYM_q, SYM_r};
|
||||
//!
|
||||
//! fn configure() {
|
||||
//! let seat = get_default_seat();
|
||||
//! // Create a key binding to exit the compositor.
|
||||
//! seat.bind(ALT | SYM_q, || quit());
|
||||
//! // Reload the configuration.
|
||||
//! seat.bind(ALT | SYM_r, || reload());
|
||||
//! }
|
||||
//!
|
||||
//! config!(configure);
|
||||
//! ```
|
||||
//!
|
||||
//! You should configure your crate to be compiled as a shared library:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [lib]
|
||||
//! crate-type = ["cdylib"]
|
||||
//! ```
|
||||
//!
|
||||
//! After compiling it, copy the shared library to `$HOME/.config/jay/config.so` and restart
|
||||
//! the compositor. It should then use your configuration file.
|
||||
//!
|
||||
//! Note that you do not have to restart the compositor every time you want to reload your
|
||||
//! configuration afterwards. Instead, simply invoke the [`reload`] function via a shortcut.
|
||||
//! Internal Rust configuration API used by Jay's built-in TOML configuration
|
||||
//! implementation.
|
||||
|
||||
#![allow(
|
||||
clippy::zero_prefixed_literal,
|
||||
|
|
|
|||
|
|
@ -1,21 +1,3 @@
|
|||
/// Declares the entry point of the configuration.
|
||||
#[macro_export]
|
||||
macro_rules! config {
|
||||
($f:path) => {
|
||||
#[unsafe(no_mangle)]
|
||||
#[used]
|
||||
pub static mut JAY_CONFIG_ENTRY_V1: $crate::_private::ConfigEntry = {
|
||||
struct X;
|
||||
impl $crate::_private::Config for X {
|
||||
extern "C" fn configure() {
|
||||
$f();
|
||||
}
|
||||
}
|
||||
$crate::_private::ConfigEntryGen::<X>::ENTRY
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! try_get {
|
||||
() => {{
|
||||
unsafe {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue