config: add documentation
This commit is contained in:
parent
6916f03e94
commit
fe80440f38
36 changed files with 620 additions and 199 deletions
|
|
@ -7,14 +7,17 @@ use {
|
|||
ipc::{ClientMessage, InitMessage, Response, ServerMessage},
|
||||
logging, Config, ConfigEntry, ConfigEntryGen, VERSION,
|
||||
},
|
||||
drm::{
|
||||
exec::Command,
|
||||
input::{acceleration::AccelProfile, capability::Capability, InputDevice, Seat},
|
||||
keyboard::Keymap,
|
||||
logging::LogLevel,
|
||||
theme::{colors::Colorable, sized::Resizable, Color},
|
||||
timer::Timer,
|
||||
video::{
|
||||
connector_type::{ConnectorType, CON_UNKNOWN},
|
||||
Connector, DrmDevice, Mode,
|
||||
},
|
||||
input::{acceleration::AccelProfile, capability::Capability, InputDevice, Seat},
|
||||
keyboard::keymap::Keymap,
|
||||
theme::{colors::Colorable, sized::Resizable, Color},
|
||||
Axis, Command, Direction, LogLevel, ModifiedKeySym, PciId, Timer, Workspace,
|
||||
Axis, Direction, ModifiedKeySym, PciId, Workspace,
|
||||
},
|
||||
std::{
|
||||
cell::{Cell, RefCell},
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
use {
|
||||
crate::{
|
||||
drm::{connector_type::ConnectorType, Connector, DrmDevice},
|
||||
input::{acceleration::AccelProfile, capability::Capability, InputDevice, Seat},
|
||||
keyboard::{keymap::Keymap, mods::Modifiers, syms::KeySym},
|
||||
keyboard::{mods::Modifiers, syms::KeySym, Keymap},
|
||||
logging::LogLevel,
|
||||
theme::{colors::Colorable, sized::Resizable, Color},
|
||||
Axis, Direction, LogLevel, PciId, Timer, Workspace,
|
||||
timer::Timer,
|
||||
video::{connector_type::ConnectorType, Connector, DrmDevice},
|
||||
Axis, Direction, PciId, Workspace,
|
||||
},
|
||||
bincode::{BorrowDecode, Decode, Encode},
|
||||
std::time::Duration,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use {
|
||||
crate::LogLevel,
|
||||
crate::logging::LogLevel,
|
||||
log::{Level, LevelFilter, Log, Metadata, Record},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,11 @@
|
|||
//! Tools to configure the compositor in embedded environments.
|
||||
|
||||
use crate::input::InputDevice;
|
||||
|
||||
/// Grab the input device.
|
||||
///
|
||||
/// This usually only works if the compositor is running as an application under X. It will
|
||||
/// probably not work under XWayland.
|
||||
pub fn grab_input_device(kb: InputDevice, grab: bool) {
|
||||
get!().grab(kb, grab);
|
||||
}
|
||||
|
|
|
|||
50
jay-config/src/exec.rs
Normal file
50
jay-config/src/exec.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
//! Tools for spawning programs.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// Sets an environment variable.
|
||||
///
|
||||
/// This does not affect the compositor itself but only programs spawned by the compositor.
|
||||
pub fn set_env(key: &str, val: &str) {
|
||||
get!().set_env(key, val);
|
||||
}
|
||||
|
||||
/// A command to be spawned.
|
||||
pub struct Command {
|
||||
pub(crate) prog: String,
|
||||
pub(crate) args: Vec<String>,
|
||||
pub(crate) env: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
/// Creates a new command to be spawned.
|
||||
///
|
||||
/// `prog` should be the path to the program being spawned. If `prog` does not contain
|
||||
/// a `/`, then it will be searched in `PATH` similar to how a shell would do it.
|
||||
///
|
||||
/// The first argument passed to `prog`, `argv[0]`, is `prog` itself.
|
||||
pub fn new(prog: &str) -> Self {
|
||||
Self {
|
||||
prog: prog.to_string(),
|
||||
args: vec![],
|
||||
env: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Adds an argument to be passed to the command.
|
||||
pub fn arg(&mut self, arg: &str) -> &mut Self {
|
||||
self.args.push(arg.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets an environment variable for this command only.
|
||||
pub fn env(&mut self, key: &str, val: &str) -> &mut Self {
|
||||
self.env.insert(key.to_string(), val.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
/// Executes the command.
|
||||
pub fn spawn(&self) {
|
||||
get!().spawn(self);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +1,90 @@
|
|||
//! Tools for configuring input devices.
|
||||
|
||||
pub mod acceleration;
|
||||
pub mod capability;
|
||||
|
||||
use {
|
||||
crate::{
|
||||
input::{acceleration::AccelProfile, capability::Capability},
|
||||
Axis, Direction, Keymap, ModifiedKeySym, Workspace,
|
||||
keyboard::Keymap,
|
||||
Axis, Direction, ModifiedKeySym, Workspace,
|
||||
},
|
||||
bincode::{Decode, Encode},
|
||||
};
|
||||
|
||||
/// An input device.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct InputDevice(pub u64);
|
||||
|
||||
impl InputDevice {
|
||||
/// Assigns the input device to a seat.
|
||||
pub fn set_seat(self, seat: Seat) {
|
||||
get!().set_seat(self, seat)
|
||||
}
|
||||
|
||||
/// Returns whether the device has the specified capability.
|
||||
pub fn has_capability(self, cap: Capability) -> bool {
|
||||
get!(false).has_capability(self, cap)
|
||||
}
|
||||
|
||||
/// Sets the device to be left handed.
|
||||
///
|
||||
/// This has the effect of swapping the left and right mouse button. See the libinput
|
||||
/// documentation for more details.
|
||||
pub fn set_left_handed(self, left_handed: bool) {
|
||||
get!().set_left_handed(self, left_handed);
|
||||
}
|
||||
|
||||
/// Sets the acceleration profile of the device.
|
||||
///
|
||||
/// This corresponds to the libinput setting of the same name.
|
||||
pub fn set_accel_profile(self, profile: AccelProfile) {
|
||||
get!().set_accel_profile(self, profile);
|
||||
}
|
||||
|
||||
/// Sets the acceleration speed of the device.
|
||||
///
|
||||
/// This corresponds to the libinput setting of the same name.
|
||||
pub fn set_accel_speed(self, speed: f64) {
|
||||
get!().set_accel_speed(self, speed);
|
||||
}
|
||||
|
||||
/// Sets the transformation matrix of the device.
|
||||
///
|
||||
/// This is not a libinput setting but a setting of the compositor. It currently affects
|
||||
/// relative mouse motions in that the matrix is applied to the motion. To reduce the mouse
|
||||
/// speed to 35%, use the following matrix:
|
||||
///
|
||||
/// ```text
|
||||
/// [
|
||||
/// [0.35, 1.0],
|
||||
/// [1.0, 0.35],
|
||||
/// ]
|
||||
/// ```
|
||||
///
|
||||
/// This might give you better results than using `set_accel_profile` and `set_accel_speed`.
|
||||
pub fn set_transform_matrix(self, matrix: [[f64; 2]; 2]) {
|
||||
get!().set_transform_matrix(self, matrix);
|
||||
}
|
||||
|
||||
/// Returns the name of the device.
|
||||
pub fn name(self) -> String {
|
||||
get!(String::new()).device_name(self)
|
||||
}
|
||||
}
|
||||
|
||||
/// A seat.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Seat(pub u64);
|
||||
|
||||
impl Seat {
|
||||
pub const INVALID: Self = Self(0);
|
||||
|
||||
/// Returns whether the seat is invalid.
|
||||
pub fn is_invalid(self) -> bool {
|
||||
self == Self::INVALID
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn raw(self) -> u64 {
|
||||
self.0
|
||||
|
|
@ -53,143 +95,164 @@ impl Seat {
|
|||
Self(raw)
|
||||
}
|
||||
|
||||
/// Creates a compositor-wide hotkey.
|
||||
///
|
||||
/// The closure is invoked when the user presses the last key of the modified keysym.
|
||||
/// Note that the keysym is calculated without modifiers applied. To perform an action
|
||||
/// when `SHIFT+k` is pressed, use `SHIFT | SYM_k` not `SHIFT | SYM_K`.
|
||||
pub fn bind<T: Into<ModifiedKeySym>, F: Fn() + 'static>(self, mod_sym: T, f: F) {
|
||||
get!().bind(self, mod_sym, f)
|
||||
}
|
||||
|
||||
/// Unbinds a hotkey.
|
||||
pub fn unbind<T: Into<ModifiedKeySym>>(self, mod_sym: T) {
|
||||
get!().unbind(self, mod_sym)
|
||||
}
|
||||
|
||||
/// Moves the keyboard focus of the seat in the specified direction.
|
||||
pub fn focus(self, direction: Direction) {
|
||||
get!().focus(self, direction)
|
||||
}
|
||||
|
||||
/// Moves the focused window in the specified direction.
|
||||
pub fn move_(self, direction: Direction) {
|
||||
get!().move_(self, direction)
|
||||
}
|
||||
|
||||
/// Sets the keymap of the seat.
|
||||
pub fn set_keymap(self, keymap: Keymap) {
|
||||
get!().seat_set_keymap(self, keymap)
|
||||
}
|
||||
|
||||
/// Returns the repeat rate of the seat.
|
||||
///
|
||||
/// The returned tuple is `(rate, delay)` where `rate` is the number of times keys repeat per second
|
||||
/// and `delay` is the time after the button press after which keys start repeating.
|
||||
pub fn repeat_rate(self) -> (i32, i32) {
|
||||
let mut res = (25, 250);
|
||||
(|| res = get!().seat_get_repeat_rate(self))();
|
||||
res
|
||||
get!((25, 250)).seat_get_repeat_rate(self)
|
||||
}
|
||||
|
||||
/// Sets the repeat rate of the seat.
|
||||
pub fn set_repeat_rate(self, rate: i32, delay: i32) {
|
||||
get!().seat_set_repeat_rate(self, rate, delay)
|
||||
}
|
||||
|
||||
/// Returns whether the parent-container of the currently focused window is in mono-mode.
|
||||
pub fn mono(self) -> bool {
|
||||
get!(false).mono(self)
|
||||
}
|
||||
|
||||
/// Sets whether the parent-container of the currently focused window is in mono-mode.
|
||||
pub fn set_mono(self, mono: bool) {
|
||||
get!().set_mono(self, mono)
|
||||
}
|
||||
|
||||
/// Toggles whether the parent-container of the currently focused window is in mono-mode.
|
||||
pub fn toggle_mono(self) {
|
||||
self.set_mono(!self.mono());
|
||||
}
|
||||
|
||||
/// Returns the split axis of the parent-container of the currently focused window.
|
||||
pub fn split(self) -> Axis {
|
||||
get!(Axis::Horizontal).split(self)
|
||||
}
|
||||
|
||||
/// Sets the split axis of the parent-container of the currently focused window.
|
||||
pub fn set_split(self, axis: Axis) {
|
||||
get!().set_split(self, axis)
|
||||
}
|
||||
|
||||
/// Toggles the split axis of the parent-container of the currently focused window.
|
||||
pub fn toggle_split(self) {
|
||||
self.set_split(self.split().other());
|
||||
}
|
||||
|
||||
/// Returns the input devices assigned to this seat.
|
||||
pub fn input_devices(self) -> Vec<InputDevice> {
|
||||
get!().get_input_devices(Some(self))
|
||||
}
|
||||
|
||||
/// Creates a new container with the specified split in place of the currently focused window.
|
||||
pub fn create_split(self, axis: Axis) {
|
||||
get!().create_split(self, axis);
|
||||
}
|
||||
|
||||
/// Focuses the parent node of the currently focused window.
|
||||
pub fn focus_parent(self) {
|
||||
get!().focus_parent(self);
|
||||
}
|
||||
|
||||
/// Requests the currently focused window to be closed.
|
||||
pub fn close(self) {
|
||||
get!().close(self);
|
||||
}
|
||||
|
||||
/// Returns whether the currently focused window is floating.
|
||||
pub fn get_floating(self) -> bool {
|
||||
get!().get_floating(self)
|
||||
}
|
||||
|
||||
/// Sets whether the currently focused window is floating.
|
||||
pub fn set_floating(self, floating: bool) {
|
||||
get!().set_floating(self, floating);
|
||||
}
|
||||
|
||||
/// Toggles whether the currently focused window is floating.
|
||||
pub fn toggle_floating(self) {
|
||||
get!().toggle_floating(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
|
||||
/// seat's cursor.
|
||||
pub fn show_workspace(self, workspace: Workspace) {
|
||||
get!().show_workspace(self, workspace)
|
||||
}
|
||||
|
||||
/// Moves the currently focused window to the workspace.
|
||||
pub fn set_workspace(self, workspace: Workspace) {
|
||||
get!().set_workspace(self, workspace)
|
||||
}
|
||||
|
||||
/// Toggles whether the currently focused window is fullscreen.
|
||||
pub fn toggle_fullscreen(self) {
|
||||
let c = get!();
|
||||
c.set_fullscreen(self, !c.get_fullscreen(self));
|
||||
}
|
||||
|
||||
/// Returns whether the currently focused window is fullscreen.
|
||||
pub fn fullscreen(self) -> bool {
|
||||
get!(false).get_fullscreen(self)
|
||||
}
|
||||
|
||||
/// Sets whether the currently focused window is fullscreen.
|
||||
pub fn set_fullscreen(self, fullscreen: bool) {
|
||||
get!().set_fullscreen(self, fullscreen)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns all seats.
|
||||
pub fn get_seats() -> Vec<Seat> {
|
||||
let mut res = vec![];
|
||||
(|| res = get!().seats())();
|
||||
res
|
||||
get!().seats()
|
||||
}
|
||||
|
||||
/// Returns all input devices.
|
||||
pub fn input_devices() -> Vec<InputDevice> {
|
||||
get!().get_input_devices(None)
|
||||
}
|
||||
|
||||
pub fn remove_all_seats() {}
|
||||
|
||||
/// Returns or creates a seat.
|
||||
///
|
||||
/// Seats are identified by their name. If no seat with the name exists, a new seat will be created.
|
||||
pub fn get_seat(name: &str) -> Seat {
|
||||
let mut res = Seat(0);
|
||||
(|| res = get!().get_seat(name))();
|
||||
res
|
||||
get!(Seat(0)).get_seat(name)
|
||||
}
|
||||
|
||||
/// Sets a closure to run when a new seat has been created.
|
||||
pub fn on_new_seat<F: Fn(Seat) + 'static>(f: F) {
|
||||
get!().on_new_seat(f)
|
||||
}
|
||||
|
||||
/// Sets a closure to run when a new input device has been added.
|
||||
pub fn on_new_input_device<F: Fn(InputDevice) + 'static>(f: F) {
|
||||
get!().on_new_input_device(f)
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Seat(pub u64);
|
||||
|
||||
impl Seat {
|
||||
pub const INVALID: Self = Self(0);
|
||||
|
||||
pub fn is_invalid(self) -> bool {
|
||||
self == Self::INVALID
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,14 @@
|
|||
//! Constants determining the acceleration profile of a device.
|
||||
//!
|
||||
//! See the libinput documentation for details.
|
||||
|
||||
use bincode::{Decode, Encode};
|
||||
|
||||
/// The acceleration profile of a device.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct AccelProfile(pub u32);
|
||||
|
||||
/// A flat acceleration profile.
|
||||
pub const ACCEL_PROFILE_FLAT: AccelProfile = AccelProfile(1 << 0);
|
||||
/// An adaptive acceleration profile.
|
||||
pub const ACCEL_PROFILE_ADAPTIVE: AccelProfile = AccelProfile(1 << 1);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,10 @@
|
|||
//! Constants specifying the capabilities of an input device.
|
||||
//!
|
||||
//! See the libinput documentation for the meanings of these constants.
|
||||
|
||||
use bincode::{Decode, Encode};
|
||||
|
||||
/// A capability of an input device.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Capability(pub u32);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +0,0 @@
|
|||
use bincode::{Decode, Encode};
|
||||
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct Keymap(pub u64);
|
||||
|
||||
impl Keymap {
|
||||
pub const INVALID: Self = Self(0);
|
||||
|
||||
pub fn is_invalid(self) -> bool {
|
||||
self == Self::INVALID
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_keymap(keymap: &str) -> Keymap {
|
||||
get!(Keymap::INVALID).parse_keymap(keymap)
|
||||
}
|
||||
|
|
@ -1,13 +1,15 @@
|
|||
//! Tools affecting the keyboard behavior.
|
||||
|
||||
use {
|
||||
crate::keyboard::{mods::Modifiers, syms::KeySym},
|
||||
bincode::{Decode, Encode},
|
||||
std::ops::{BitOr, BitOrAssign},
|
||||
};
|
||||
|
||||
pub mod keymap;
|
||||
pub mod mods;
|
||||
pub mod syms;
|
||||
|
||||
/// A keysym with zero or more modifiers
|
||||
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct ModifiedKeySym {
|
||||
pub mods: Modifiers,
|
||||
|
|
@ -39,3 +41,62 @@ impl BitOrAssign<Modifiers> for ModifiedKeySym {
|
|||
self.mods |= rhs;
|
||||
}
|
||||
}
|
||||
|
||||
/// A keymap.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||
pub struct Keymap(pub u64);
|
||||
|
||||
impl Keymap {
|
||||
/// The invalid keymap.
|
||||
pub const INVALID: Self = Self(0);
|
||||
|
||||
/// Returns whether this keymap is valid.
|
||||
pub fn is_valid(self) -> bool {
|
||||
self != Self::INVALID
|
||||
}
|
||||
|
||||
/// Returns whether this keymap is invalid.
|
||||
pub fn is_invalid(self) -> bool {
|
||||
self == Self::INVALID
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a keymap.
|
||||
///
|
||||
/// The returned keymap can later be used to set the keymap of a seat. If the keymap cannot
|
||||
/// be parsed, returns an invalid keymap. Trying to set a seat's keymap to an invalid keymap
|
||||
/// has no effect.
|
||||
///
|
||||
/// A simple keymap looks as follows:
|
||||
///
|
||||
/// ```text
|
||||
/// xkb_keymap {
|
||||
/// xkb_keycodes { include "evdev+aliases(qwerty)" };
|
||||
/// xkb_types { include "complete" };
|
||||
/// xkb_compat { include "complete" };
|
||||
/// xkb_symbols { include "pc+inet(evdev)+us(basic)" };
|
||||
/// };
|
||||
/// ```
|
||||
///
|
||||
/// To use a programmer Dvorak, replace the corresponding line by
|
||||
///
|
||||
/// ```text
|
||||
/// xkb_symbols { include "pc+inet(evdev)+us(dvp)" };
|
||||
/// ```
|
||||
///
|
||||
/// To use a German keymap, replace the corresponding line by
|
||||
///
|
||||
/// ```text
|
||||
/// xkb_symbols { include "pc+inet(evdev)+de(basic)" };
|
||||
/// ```
|
||||
///
|
||||
/// You can also use a completely custom keymap that doesn't use any includes. See the
|
||||
/// [default][default] Jay keymap for an example.
|
||||
///
|
||||
/// General information about the keymap format can be found in the [arch wiki][wiki].
|
||||
///
|
||||
/// [default]: https://github.com/mahkoh/jay/tree/master/src/keymap.xkb
|
||||
/// [wiki]: https://wiki.archlinux.org/title/X_keyboard_extension
|
||||
pub fn parse_keymap(keymap: &str) -> Keymap {
|
||||
get!(Keymap::INVALID).parse_keymap(keymap)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,24 +1,39 @@
|
|||
//! Keyboard modifiers
|
||||
|
||||
use {
|
||||
crate::{keyboard::syms::KeySym, ModifiedKeySym},
|
||||
bincode::{Decode, Encode},
|
||||
std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign},
|
||||
};
|
||||
|
||||
/// Zero or more keyboard modifiers
|
||||
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Default, Hash, Debug)]
|
||||
pub struct Modifiers(pub u32);
|
||||
|
||||
/// The Shift modifier
|
||||
pub const SHIFT: Modifiers = Modifiers(1 << 0);
|
||||
/// The CapsLock modifier.
|
||||
pub const LOCK: Modifiers = Modifiers(1 << 1);
|
||||
/// The Ctrl modifier.
|
||||
pub const CTRL: Modifiers = Modifiers(1 << 2);
|
||||
/// The Mod1 modifier, i.e., Alt.
|
||||
pub const MOD1: Modifiers = Modifiers(1 << 3);
|
||||
/// The Mod2 modifier, i.e., NumLock.
|
||||
pub const MOD2: Modifiers = Modifiers(1 << 4);
|
||||
/// The Mod3 modifier.
|
||||
pub const MOD3: Modifiers = Modifiers(1 << 5);
|
||||
/// The Mod4 modifier, i.e., Logo.
|
||||
pub const MOD4: Modifiers = Modifiers(1 << 6);
|
||||
/// The Mod5 modifier.
|
||||
pub const MOD5: Modifiers = Modifiers(1 << 7);
|
||||
|
||||
/// Alias for `LOCK`.
|
||||
pub const CAPS: Modifiers = LOCK;
|
||||
/// Alias for `MOD1`.
|
||||
pub const ALT: Modifiers = MOD1;
|
||||
/// Alias for `MOD2`.
|
||||
pub const NUM: Modifiers = MOD2;
|
||||
/// Alias for `MOD4`.
|
||||
pub const LOGO: Modifiers = MOD4;
|
||||
|
||||
impl BitOr for Modifiers {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
//! Keysyms
|
||||
|
||||
#![allow(non_upper_case_globals)]
|
||||
|
||||
use bincode::{Decode, Encode};
|
||||
|
||||
/// A keysym.
|
||||
#[derive(Encode, Decode, Copy, Clone, Eq, PartialEq, Hash, Debug)]
|
||||
pub struct KeySym(pub u32);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,42 +1,69 @@
|
|||
//! This crate allows you to configure the Jay compositor.
|
||||
//!
|
||||
//! A minimal example configuration looks as follows:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use jay_config::config;
|
||||
//!
|
||||
//! fn configure() {
|
||||
//!
|
||||
//! }
|
||||
//!
|
||||
//! config!(configure);
|
||||
//! ```
|
||||
//!
|
||||
//! This configuration will not allow you to interact with the compositor at all nor exit it.
|
||||
//! To add at least that much functionality, add the following code to `configure`:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use jay_config::{config, quit};
|
||||
//! use jay_config::input::{get_seat, input_devices, on_new_input_device};
|
||||
//! use jay_config::keyboard::mods::ALT;
|
||||
//! use jay_config::keyboard::syms::SYM_q;
|
||||
//!
|
||||
//! fn configure() {
|
||||
//! // Create a seat.
|
||||
//! let seat = get_seat("default");
|
||||
//! // Create a key binding to exit the compositor.
|
||||
//! seat.bind(ALT | SYM_q, || quit());
|
||||
//! // Assign all current and future input devices to this seat.
|
||||
//! input_devices().into_iter().for_each(move |d| d.set_seat(seat));
|
||||
//! on_new_input_device(move |d| d.set_seat(seat));
|
||||
//! }
|
||||
//!
|
||||
//! config!(configure);
|
||||
//! ```
|
||||
|
||||
use {
|
||||
crate::keyboard::{keymap::Keymap, ModifiedKeySym},
|
||||
crate::keyboard::ModifiedKeySym,
|
||||
bincode::{Decode, Encode},
|
||||
std::{
|
||||
collections::HashMap,
|
||||
fmt::{Debug, Display, Formatter},
|
||||
time::Duration,
|
||||
},
|
||||
std::fmt::{Debug, Display, Formatter},
|
||||
};
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
#[doc(hidden)]
|
||||
pub mod _private;
|
||||
pub mod drm;
|
||||
pub mod embedded;
|
||||
pub mod exec;
|
||||
pub mod input;
|
||||
pub mod keyboard;
|
||||
pub mod logging;
|
||||
pub mod status;
|
||||
pub mod theme;
|
||||
pub mod timer;
|
||||
pub mod video;
|
||||
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug)]
|
||||
pub enum LogLevel {
|
||||
Error,
|
||||
Warn,
|
||||
Info,
|
||||
Debug,
|
||||
Trace,
|
||||
}
|
||||
|
||||
/// A planar direction.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum Direction {
|
||||
Unspecified,
|
||||
Left,
|
||||
Down,
|
||||
Up,
|
||||
Right,
|
||||
}
|
||||
|
||||
/// A planar axis.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub enum Axis {
|
||||
Horizontal,
|
||||
|
|
@ -44,6 +71,7 @@ pub enum Axis {
|
|||
}
|
||||
|
||||
impl Axis {
|
||||
/// Returns the axis orthogonal to `self`.
|
||||
pub fn other(self) -> Self {
|
||||
match self {
|
||||
Self::Horizontal => Self::Vertical,
|
||||
|
|
@ -52,88 +80,47 @@ impl Axis {
|
|||
}
|
||||
}
|
||||
|
||||
/// Exits the compositor.
|
||||
pub fn quit() {
|
||||
get!().quit()
|
||||
}
|
||||
|
||||
/// Switches to a different VT.
|
||||
pub fn switch_to_vt(n: u32) {
|
||||
get!().switch_to_vt(n)
|
||||
}
|
||||
|
||||
pub fn set_env(key: &str, val: &str) {
|
||||
get!().set_env(key, val);
|
||||
}
|
||||
|
||||
pub struct Command {
|
||||
prog: String,
|
||||
args: Vec<String>,
|
||||
env: HashMap<String, String>,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn new(prog: &str) -> Self {
|
||||
Self {
|
||||
prog: prog.to_string(),
|
||||
args: vec![],
|
||||
env: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, arg: &str) -> &mut Self {
|
||||
self.args.push(arg.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn env(&mut self, key: &str, val: &str) -> &mut Self {
|
||||
self.env.insert(key.to_string(), val.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn spawn(&self) {
|
||||
get!().spawn(self);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Workspace(pub u64);
|
||||
|
||||
pub fn get_workspace(name: &str) -> Workspace {
|
||||
get!(Workspace(0)).get_workspace(name)
|
||||
}
|
||||
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Timer(pub u64);
|
||||
|
||||
pub fn get_timer(name: &str) -> Timer {
|
||||
get!(Timer(0)).get_timer(name)
|
||||
}
|
||||
|
||||
impl Timer {
|
||||
pub fn program(self, initial: Duration, periodic: Option<Duration>) {
|
||||
get!().program_timer(self, Some(initial), periodic);
|
||||
}
|
||||
|
||||
pub fn cancel(self) {
|
||||
get!().program_timer(self, None, None);
|
||||
}
|
||||
|
||||
pub fn remove(self) {
|
||||
get!().remove_timer(self);
|
||||
}
|
||||
|
||||
pub fn on_tick<F: Fn() + 'static>(self, f: F) {
|
||||
get!().on_timer_tick(self, f);
|
||||
}
|
||||
}
|
||||
|
||||
/// Reloads the configuration.
|
||||
///
|
||||
/// If the configuration cannot be reloaded, this function has no effect.
|
||||
pub fn reload() {
|
||||
get!().reload()
|
||||
}
|
||||
|
||||
/// Returns whether this execution of the configuration function is due to a reload.
|
||||
///
|
||||
/// This can be used to decide whether the configuration should auto-start programs.
|
||||
pub fn is_reload() -> bool {
|
||||
get!(false).is_reload()
|
||||
}
|
||||
|
||||
/// A workspace.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Workspace(pub u64);
|
||||
|
||||
/// Returns the workspace with the given name.
|
||||
///
|
||||
/// Workspaces are identified by their name. Calling this function alone does not create the
|
||||
/// workspace if it doesn't already exist.
|
||||
pub fn get_workspace(name: &str) -> Workspace {
|
||||
get!(Workspace(0)).get_workspace(name)
|
||||
}
|
||||
|
||||
/// A PCI ID.
|
||||
///
|
||||
/// PCI IDs can be used to identify a hardware component. See the Debian [documentation][pci].
|
||||
///
|
||||
/// [pci]: https://wiki.debian.org/HowToIdentifyADevice/PCI
|
||||
#[derive(Encode, Decode, Debug, Copy, Clone, Hash, Eq, PartialEq, Default)]
|
||||
pub struct PciId {
|
||||
pub vendor: u32,
|
||||
|
|
|
|||
16
jay-config/src/logging.rs
Normal file
16
jay-config/src/logging.rs
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//! Tools for modifying the logging behavior of the compositor.
|
||||
//!
|
||||
//! Note that you can use the `log` crate for logging. All invocations of `log::info` etc.
|
||||
//! automatically log into the compositors log.
|
||||
|
||||
use bincode::{Decode, Encode};
|
||||
|
||||
/// The log level of the compositor or a log message.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug)]
|
||||
pub enum LogLevel {
|
||||
Error,
|
||||
Warn,
|
||||
Info,
|
||||
Debug,
|
||||
Trace,
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
/// Declares the entry point of the configuration.
|
||||
#[macro_export]
|
||||
macro_rules! config {
|
||||
($f:path) => {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,12 @@
|
|||
//! Knobs for changing the status text.
|
||||
|
||||
/// Sets the status text.
|
||||
///
|
||||
/// The status text is displayed at the right end of the bar.
|
||||
///
|
||||
/// The status text should be specified in [pango][pango] markup language.
|
||||
///
|
||||
/// [pango]: https://docs.gtk.org/Pango/pango_markup.html
|
||||
pub fn set_status(status: &str) {
|
||||
get!().set_status(status);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! Knobs for changing the look of the compositor.
|
||||
//! Tools for configuring the look of the compositor.
|
||||
|
||||
use bincode::{Decode, Encode};
|
||||
|
||||
|
|
@ -156,7 +156,7 @@ pub fn reset_font() {
|
|||
get!().reset_font()
|
||||
}
|
||||
|
||||
/// Tools for customizing the colors of the desktop.
|
||||
/// Elements of the compositor whose color can be changed.
|
||||
pub mod colors {
|
||||
use {
|
||||
crate::theme::Color,
|
||||
|
|
@ -248,7 +248,7 @@ pub mod colors {
|
|||
}
|
||||
}
|
||||
|
||||
/// Tools for customizing the sizes of GUI elements.
|
||||
/// Elements of the compositor whose size can be changed.
|
||||
pub mod sized {
|
||||
use bincode::{Decode, Encode};
|
||||
|
||||
|
|
|
|||
92
jay-config/src/timer.rs
Normal file
92
jay-config/src/timer.rs
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
//! Timers for one-time or repeated actions.
|
||||
|
||||
use {
|
||||
bincode::{Decode, Encode},
|
||||
std::time::{Duration, SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
/// A timer.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Timer(pub u64);
|
||||
|
||||
/// Creates a new timer or returns an existing one.
|
||||
///
|
||||
/// Timers are identified by their name and their lifetime is bound by the lifetime of
|
||||
/// the configuration. Reloading the configuration destroys all existing timers.
|
||||
///
|
||||
/// Within the same configuration, calling this function multiple times with the same name
|
||||
/// will return the same timer.
|
||||
///
|
||||
/// Timers can be deleted by calling `remove`. At that point all existing references to
|
||||
/// the timer become invalid and `get_timer` will return a new timer.
|
||||
pub fn get_timer(name: &str) -> Timer {
|
||||
get!(Timer(0)).get_timer(name)
|
||||
}
|
||||
|
||||
impl Timer {
|
||||
/// Programs the timer to fire once.
|
||||
pub fn once(self, initial: Duration) {
|
||||
get!().program_timer(self, Some(initial), None);
|
||||
}
|
||||
|
||||
/// Programs the timer to fire repeatedly.
|
||||
///
|
||||
/// `initial` is the period after which the timer expires for the first time.
|
||||
pub fn repeated(self, initial: Duration, period: Duration) {
|
||||
get!().program_timer(self, Some(initial), Some(period));
|
||||
}
|
||||
|
||||
/// Cancels the timer.
|
||||
///
|
||||
/// The timer remains valid but will never expire. It can be reprogrammed by calling
|
||||
/// `once` or `repeated`.
|
||||
pub fn cancel(self) {
|
||||
get!().program_timer(self, None, None);
|
||||
}
|
||||
|
||||
/// Removes the time.
|
||||
///
|
||||
/// This reference to the timer becomes invalid as do all other existing references.
|
||||
/// A new timer with the same name can be created by calling `get_timer`.
|
||||
pub fn remove(self) {
|
||||
get!().remove_timer(self);
|
||||
}
|
||||
|
||||
/// Sets the function to be executed when the timer expires.
|
||||
pub fn on_tick<F: Fn() + 'static>(self, f: F) {
|
||||
get!().on_timer_tick(self, f);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the duration until the wall clock is a multiple of `duration`.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Execute a timer every time the wall clock becomes a multiple of 5 seconds:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// let period = Duration::from_secs(5);
|
||||
/// let timer = get_timer("status_timer");
|
||||
/// timer.repeated(
|
||||
/// duration_until_wall_clock_is_multiple_of(period),
|
||||
/// period,
|
||||
/// );
|
||||
/// timer.on_tick(|| todo!());
|
||||
/// ```
|
||||
pub fn duration_until_wall_clock_is_multiple_of(duration: Duration) -> Duration {
|
||||
let now = match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
Ok(n) => n,
|
||||
_ => return Duration::from_secs(0),
|
||||
};
|
||||
let now = now.as_nanos();
|
||||
let duration = duration.as_nanos();
|
||||
if duration == 0 {
|
||||
return Duration::from_secs(0);
|
||||
}
|
||||
let nanos = duration - now % duration;
|
||||
if nanos == duration {
|
||||
Duration::from_secs(0)
|
||||
} else {
|
||||
Duration::from_nanos(nanos as _)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
//! Tools for configuring graphics cards and monitors.
|
||||
|
||||
use {
|
||||
crate::{
|
||||
drm::connector_type::{
|
||||
video::connector_type::{
|
||||
ConnectorType, 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, CON_LVDS, CON_SPI, CON_SVIDEO, CON_TV, CON_UNKNOWN, CON_USB, CON_VGA,
|
||||
|
|
@ -12,7 +14,14 @@ use {
|
|||
std::str::FromStr,
|
||||
};
|
||||
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
/// The mode of a connector.
|
||||
///
|
||||
/// Currently a mode consists of three properties:
|
||||
///
|
||||
/// - width in pixels
|
||||
/// - height in pixels
|
||||
/// - refresh rate in mhz.
|
||||
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Mode {
|
||||
pub(crate) width: i32,
|
||||
pub(crate) height: i32,
|
||||
|
|
@ -20,14 +29,19 @@ pub struct Mode {
|
|||
}
|
||||
|
||||
impl Mode {
|
||||
/// Returns the width of the mode.
|
||||
pub fn width(&self) -> i32 {
|
||||
self.width
|
||||
}
|
||||
|
||||
/// Returns the height of the mode.
|
||||
pub fn height(&self) -> i32 {
|
||||
self.height
|
||||
}
|
||||
|
||||
/// Returns the refresh rate of the mode in mhz.
|
||||
///
|
||||
/// For a 60hz monitor, this function would return 60_000.
|
||||
pub fn refresh_rate(&self) -> u32 {
|
||||
self.refresh_millihz
|
||||
}
|
||||
|
|
@ -41,14 +55,23 @@ impl Mode {
|
|||
}
|
||||
}
|
||||
|
||||
/// A connector that is potentially connected to an output device.
|
||||
///
|
||||
/// A connector is the part that sticks out of your graphics card. A graphics card usually
|
||||
/// has many connectors but one few of them are actually connected to a monitor.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct Connector(pub u64);
|
||||
|
||||
impl Connector {
|
||||
/// Returns whether this connector existed at the time `get_connector` was called.
|
||||
///
|
||||
/// This only implies existence at the time `get_connector` was called. Even if this
|
||||
/// function returns true, the connector might since have disappeared.
|
||||
pub fn exists(self) -> bool {
|
||||
self.0 != 0
|
||||
}
|
||||
|
||||
/// Returns whether the connector is connected to an output device.
|
||||
pub fn connected(self) -> bool {
|
||||
if !self.exists() {
|
||||
return false;
|
||||
|
|
@ -56,6 +79,7 @@ impl Connector {
|
|||
get!(false).connector_connected(self)
|
||||
}
|
||||
|
||||
/// Returns the connector type.
|
||||
pub fn ty(self) -> ConnectorType {
|
||||
if !self.exists() {
|
||||
return CON_UNKNOWN;
|
||||
|
|
@ -63,6 +87,7 @@ impl Connector {
|
|||
get!(CON_UNKNOWN).connector_type(self)
|
||||
}
|
||||
|
||||
/// Returns the current mode of the connector.
|
||||
pub fn mode(self) -> Mode {
|
||||
if !self.exists() {
|
||||
return Mode::zeroed();
|
||||
|
|
@ -70,18 +95,34 @@ impl Connector {
|
|||
get!(Mode::zeroed()).connector_mode(self)
|
||||
}
|
||||
|
||||
/// Returns the width of the current mode of the connector.
|
||||
///
|
||||
/// This is a shortcut for `mode().width()`.
|
||||
pub fn width(self) -> i32 {
|
||||
self.mode().width
|
||||
}
|
||||
|
||||
/// Returns the height of the current mode of the connector.
|
||||
///
|
||||
/// This is a shortcut for `mode().height()`.
|
||||
pub fn height(self) -> i32 {
|
||||
self.mode().height
|
||||
}
|
||||
|
||||
/// Returns the refresh rate in mhz of the current mode of the connector.
|
||||
///
|
||||
/// This is a shortcut for `mode().refresh_rate()`.
|
||||
pub fn refresh_rate(self) -> u32 {
|
||||
self.mode().refresh_millihz
|
||||
}
|
||||
|
||||
/// Sets the position of the connector in the global compositor space.
|
||||
///
|
||||
/// `x` and `y` must be non-negative and must not exceed a currently unspecified limit.
|
||||
/// Any reasonable values for `x` and `y` should work.
|
||||
///
|
||||
/// This function allows the connector to overlap with other connectors, however, such
|
||||
/// configurations are not supported and might result in unexpected behavior.
|
||||
pub fn set_position(self, x: i32, y: i32) {
|
||||
if !self.exists() {
|
||||
log::warn!("set_position called on a connector that does not exist");
|
||||
|
|
@ -91,30 +132,72 @@ impl Connector {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns all available DRM devices.
|
||||
pub fn drm_devices() -> Vec<DrmDevice> {
|
||||
get!().drm_devices()
|
||||
}
|
||||
|
||||
/// Sets the callback to be called when a new DRM device appears.
|
||||
pub fn on_new_drm_device<F: Fn(DrmDevice) + 'static>(f: F) {
|
||||
get!().on_new_drm_device(f)
|
||||
}
|
||||
|
||||
/// Sets the callback to be called when a DRM device is removed.
|
||||
pub fn on_drm_device_removed<F: Fn(DrmDevice) + 'static>(f: F) {
|
||||
get!().on_del_drm_device(f)
|
||||
}
|
||||
|
||||
/// Sets the callback to be called when a new connector appears.
|
||||
pub fn on_new_connector<F: Fn(Connector) + 'static>(f: F) {
|
||||
get!().on_new_connector(f)
|
||||
}
|
||||
|
||||
/// Sets the callback to be called when a connector becomes connected to an output device.
|
||||
pub fn on_connector_connected<F: Fn(Connector) + 'static>(f: F) {
|
||||
get!().on_connector_connected(f)
|
||||
}
|
||||
|
||||
/// Sets the callback to be called when the graphics of the compositor have been initialized.
|
||||
///
|
||||
/// This callback is only invoked once during the lifetime of the compositor. This is a good place
|
||||
/// to auto start graphical applications.
|
||||
pub fn on_graphics_initialized<F: FnOnce() + 'static>(f: F) {
|
||||
get!().on_graphics_initialized(f)
|
||||
}
|
||||
|
||||
/// Returns the connector with the given id.
|
||||
///
|
||||
/// The linux kernel identifies connectors by a (type, idx) tuple, e.g., `DP-0`.
|
||||
/// If the connector does not exist at the time this function is called, a sentinel value is
|
||||
/// returned. This can be checked by calling `exists()` on the returned connector.
|
||||
///
|
||||
/// The `id` argument can either be an explicit tuple, e.g. `(CON_DISPLAY_PORT, 0)`, or a string
|
||||
/// that can be parsed to such a tuple, e.g. `"DP-0"`.
|
||||
///
|
||||
/// The following string prefixes exist:
|
||||
///
|
||||
/// - `DP`
|
||||
/// - `eDP`
|
||||
/// - `HDMI-A`
|
||||
/// - `HDMI-B`
|
||||
/// - `EmbeddedWindow` - this is an implementation detail of the compositor and used if it
|
||||
/// runs as an embedded application.
|
||||
/// - `VGA`
|
||||
/// - `DVI-I`
|
||||
/// - `DVI-D`
|
||||
/// - `DVI-A`
|
||||
/// - `Composite`
|
||||
/// - `SVIDEO`
|
||||
/// - `LVDS`
|
||||
/// - `Component`
|
||||
/// - `DIN`
|
||||
/// - `TV`
|
||||
/// - `Virtual`
|
||||
/// - `DSI`
|
||||
/// - `DPI`
|
||||
/// - `Writeback`
|
||||
/// - `SPI`
|
||||
/// - `USB`
|
||||
pub fn get_connector(id: impl ToConnectorId) -> Connector {
|
||||
let (ty, idx) = match id.to_connector_id() {
|
||||
Ok(id) => id,
|
||||
|
|
@ -126,6 +209,7 @@ pub fn get_connector(id: impl ToConnectorId) -> Connector {
|
|||
get!(Connector(0)).get_connector(ty, idx)
|
||||
}
|
||||
|
||||
/// A type that can be converted to a `(ConnectorType, idx)` tuple.
|
||||
pub trait ToConnectorId {
|
||||
fn to_connector_id(&self) -> Result<(ConnectorType, u32), String>;
|
||||
}
|
||||
|
|
@ -172,9 +256,11 @@ impl ToConnectorId for &'_ str {
|
|||
}
|
||||
}
|
||||
|
||||
/// Module containing all known connector types.
|
||||
pub mod connector_type {
|
||||
use bincode::{Decode, Encode};
|
||||
|
||||
/// The type of a connector.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct ConnectorType(pub u32);
|
||||
|
||||
|
|
@ -202,26 +288,44 @@ pub mod connector_type {
|
|||
pub const CON_EMBEDDED_WINDOW: ConnectorType = ConnectorType(u32::MAX);
|
||||
}
|
||||
|
||||
/// A *Direct Rendering Manager* (DRM) device.
|
||||
///
|
||||
/// It's easiest to think of a DRM device as a graphics card.
|
||||
/// There are also DRM devices that are emulated in software but you are unlikely to encounter
|
||||
/// those accidentally.
|
||||
#[derive(Encode, Decode, Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
||||
pub struct DrmDevice(pub u64);
|
||||
|
||||
impl DrmDevice {
|
||||
/// Returns the connectors of this device.
|
||||
pub fn connectors(self) -> Vec<Connector> {
|
||||
get!().device_connectors(self)
|
||||
}
|
||||
|
||||
/// Returns the syspath of this device.
|
||||
///
|
||||
/// E.g. `/sys/devices/pci0000:00/0000:00:03.1/0000:07:00.0`.
|
||||
pub fn syspath(self) -> String {
|
||||
get!().drm_device_syspath(self)
|
||||
}
|
||||
|
||||
/// Returns the vendor of this device.
|
||||
///
|
||||
/// E.g. `Advanced Micro Devices, Inc. [AMD/ATI]`.
|
||||
pub fn vendor(self) -> String {
|
||||
get!().drm_device_vendor(self)
|
||||
}
|
||||
|
||||
/// Returns the model of this device.
|
||||
///
|
||||
/// E.g. `Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (Radeon RX 570 Armor 8G OC)`.
|
||||
pub fn model(self) -> String {
|
||||
get!().drm_device_model(self)
|
||||
}
|
||||
|
||||
/// Returns the PIC ID of this device.
|
||||
///
|
||||
/// E.g. `1002:67DF`.
|
||||
pub fn pci_id(self) -> PciId {
|
||||
get!().drm_device_pci_id(self)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue