use super::*;
use derive_more::Display;
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
async fn call_hyprctl_data_cmd_async(cmd: DataCommands) -> String {
let socket_path = get_socket_path(SocketType::Command);
let command = CommandContent {
flag: CommandFlag::JSON,
data: cmd.to_string(),
};
match write_to_socket(socket_path, command).await {
Ok(data) => data,
Err(e) => panic!("A error occured while parsing the output from the hypr socket: {e:?}"),
}
}
fn call_hyprctl_data_cmd(cmd: DataCommands) -> String {
let socket_path = get_socket_path(SocketType::Command);
let command = CommandContent {
flag: CommandFlag::JSON,
data: cmd.to_string(),
};
match write_to_socket_sync(socket_path, command) {
Ok(data) => data,
Err(e) => panic!("A error occured while parsing the output from the hypr socket: {e:?}"),
}
}
#[derive(Debug, Display)]
pub(crate) enum DataCommands {
#[display(fmt = "monitors")]
Monitors,
#[display(fmt = "workspaces")]
Workspaces,
#[display(fmt = "activeworkspace")]
ActiveWorkspace,
#[display(fmt = "clients")]
Clients,
#[display(fmt = "activewindow")]
ActiveWindow,
#[display(fmt = "layers")]
Layers,
#[display(fmt = "devices")]
Devices,
#[display(fmt = "version")]
Version,
#[display(fmt = "cursorpos")]
CursorPosition,
#[display(fmt = "binds")]
Binds,
#[display(fmt = "animations")]
Animations,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct WorkspaceBasic {
pub id: WorkspaceId,
pub name: String,
}
#[derive(Serialize_repr, Deserialize_repr, Debug, Clone)]
#[repr(u8)]
pub enum Transforms {
Normal = 0,
Normal90 = 1,
Normal180 = 2,
Normal270 = 3,
Flipped = 4,
Flipped90 = 5,
Flipped180 = 6,
Flipped270 = 7,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Monitor {
pub id: u64,
pub name: String,
pub description: String,
pub width: u16,
pub height: u16,
#[serde(rename = "refreshRate")]
pub refresh_rate: f32,
pub x: i32,
pub y: i32,
#[serde(rename = "activeWorkspace")]
pub active_workspace: WorkspaceBasic,
pub reserved: (u16, u16, u16, u16),
pub scale: f32,
pub transform: Transforms,
pub focused: bool,
#[serde(rename = "dpmsStatus")]
pub dpms_status: bool,
pub vrr: bool,
}
#[async_trait]
impl HyprDataActive for Monitor {
fn get_active() -> crate::Result<Self> {
let mut all = Monitors::get()?;
if let Some(it) = all.find(|item| item.focused) {
Ok(it)
} else {
panic!("No active monitor?")
}
}
async fn get_active_async() -> crate::Result<Self> {
let mut all = Monitors::get_async().await?;
if let Some(it) = all.find(|item| item.focused) {
Ok(it)
} else {
panic!("No active monitor?")
}
}
}
create_data_struct!(
vec Monitors,
DataCommands::Monitors,
Monitor,
"This struct holds a vector of monitors"
);
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Workspace {
pub id: WorkspaceId,
pub name: String,
pub monitor: String,
pub windows: u16,
#[serde(rename = "hasfullscreen")]
pub fullscreen: bool,
#[serde(rename = "lastwindow")]
pub last_window: Address,
#[serde(rename = "lastwindowtitle")]
pub last_window_title: String,
}
#[async_trait]
impl HyprDataActive for Workspace {
fn get_active() -> crate::Result<Self> {
let data = call_hyprctl_data_cmd(DataCommands::ActiveWorkspace);
let deserialized: Workspace = serde_json::from_str(&data)?;
Ok(deserialized)
}
async fn get_active_async() -> crate::Result<Self> {
let data = call_hyprctl_data_cmd_async(DataCommands::ActiveWorkspace).await;
let deserialized: Workspace = serde_json::from_str(&data)?;
Ok(deserialized)
}
}
create_data_struct!(
vec Workspaces,
DataCommands::Workspaces,
Workspace,
"This type provides a vector of workspaces"
);
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Client {
pub address: Address,
pub at: (i16, i16),
pub size: (i16, i16),
pub workspace: WorkspaceBasic,
pub floating: bool,
pub fullscreen: bool,
#[serde(rename = "fullscreenMode")]
pub fullscreen_mode: i8,
pub monitor: u64,
#[serde(rename = "initialClass")]
pub initial_class: String,
pub class: String,
#[serde(rename = "initialTitle")]
pub initial_title: String,
pub title: String,
pub pid: i32,
pub xwayland: bool,
pub pinned: bool,
pub grouped: Vec<Box<Address>>,
pub mapped: bool,
pub swallowing: Option<Box<Address>>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub(crate) struct ActiveWindow(
#[serde(deserialize_with = "object_empty_as_none")]
pub Option<Client>,
);
#[async_trait]
impl HyprDataActiveOptional for Client {
fn get_active() -> crate::Result<Option<Self>> {
let data = call_hyprctl_data_cmd(DataCommands::ActiveWindow);
let deserialized: ActiveWindow = serde_json::from_str(&data)?;
Ok(deserialized.0)
}
async fn get_active_async() -> crate::Result<Option<Self>> {
let data = call_hyprctl_data_cmd_async(DataCommands::ActiveWindow).await;
let deserialized: ActiveWindow = serde_json::from_str(&data)?;
Ok(deserialized.0)
}
}
create_data_struct!(
vec Clients,
DataCommands::Clients,
Client,
"This struct holds a vector of clients"
);
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct LayerClient {
pub address: Address,
pub x: i32,
pub y: i32,
pub w: i16,
pub h: i16,
pub namespace: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct LayerDisplay {
pub levels: HashMap<String, Vec<LayerClient>>,
}
impl LayerDisplay {
pub fn iter(&self) -> impl Iterator<Item = (&String, &Vec<LayerClient>)> {
self.levels.iter()
}
}
create_data_struct!(
sing Layers,
DataCommands::Layers,
HashMap<String, LayerDisplay>,
"This struct holds a hashmap of all current displays, and their layer surfaces",
iter_item = (&String, &LayerDisplay)
);
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Mouse {
pub address: Address,
pub name: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Keyboard {
pub address: Address,
pub name: String,
pub rules: String,
pub model: String,
pub layout: String,
pub variant: String,
pub options: String,
pub active_keymap: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum TabletType {
#[serde(rename = "tabletPad")]
TabletPad,
#[serde(rename = "tabletTool")]
TabletTool,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum TabletBelongsTo {
TabletPad {
name: String,
address: Address,
},
Address(Address),
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Tablet {
pub address: Address,
#[serde(rename = "type")]
pub tablet_type: Option<TabletType>,
#[serde(rename = "belongsTo")]
pub belongs_to: Option<TabletBelongsTo>,
pub name: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Devices {
pub mice: Vec<Mouse>,
pub keyboards: Vec<Keyboard>,
pub tablets: Vec<Tablet>,
}
impl_on!(Devices);
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Version {
pub branch: String,
pub commit: String,
pub dirty: bool,
pub commit_message: String,
pub flags: Vec<String>,
}
impl_on!(Version);
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CursorPosition {
pub x: i64,
pub y: i64,
}
impl_on!(CursorPosition);
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Bind {
pub locked: bool,
pub mouse: bool,
pub release: bool,
pub repeat: bool,
pub modmask: u16,
pub submap: String,
pub key: String,
pub keycode: i16,
pub dispatcher: String,
pub arg: String,
}
create_data_struct!(
vec Binds,
DataCommands::Binds,
Bind,
"This struct holds a vector of binds"
);
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum AnimationStyle {
Slide,
SlideVert,
PopIn(u8),
Fade,
Once,
Loop,
None,
Unknown(String),
}
impl<Str: ToString + Clone> From<Str> for AnimationStyle {
fn from(value: Str) -> Self {
let string = value.to_string();
if string.starts_with("popin") {
let mut iter = string.split(' ');
iter.next();
AnimationStyle::PopIn({
let mut str = iter.next().unwrap_or("100%").to_string();
str.remove(str.len() - 1);
str.parse().unwrap_or(100_u8)
})
} else {
match value.to_string().as_str() {
"slide" => AnimationStyle::Slide,
"slidevert" => AnimationStyle::SlideVert,
"fade" => AnimationStyle::Fade,
"once" => AnimationStyle::Once,
"loop" => AnimationStyle::Loop,
"" => AnimationStyle::None,
_ => AnimationStyle::Unknown(string),
}
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum BezierIdent {
#[serde(rename = "")]
None,
#[serde(rename = "default")]
Default,
#[serde(rename = "name")]
Specified(String),
}
impl<Str: ToString + Clone> From<Str> for BezierIdent {
fn from(value: Str) -> Self {
let str = value.to_string();
match str.as_str() {
"" => BezierIdent::None,
"default" => BezierIdent::Default,
_ => BezierIdent::Specified(str),
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
struct RawBezierIdent {
pub name: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Bezier {
pub name: String,
pub x0: f32,
pub y0: f32,
pub x1: f32,
pub y1: f32,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
struct AnimationRaw {
pub name: String,
pub overridden: bool,
pub bezier: String,
pub enabled: bool,
pub speed: f32,
pub style: String,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Animation {
pub name: String,
pub overridden: bool,
pub bezier: BezierIdent,
pub enabled: bool,
pub speed: f32,
pub style: AnimationStyle,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
struct AnimationsRaw(Vec<AnimationRaw>, Vec<RawBezierIdent>);
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Animations(Vec<Animation>, Vec<BezierIdent>);
#[async_trait]
impl HyprData for Animations {
fn get() -> crate::Result<Self>
where
Self: Sized,
{
let out = call_hyprctl_data_cmd(DataCommands::Animations);
let des: AnimationsRaw = serde_json::from_str(&out)?;
let AnimationsRaw(anims, beziers) = des;
let new_anims: Vec<Animation> = anims
.iter()
.map(|item| Animation {
name: item.name.clone(),
overridden: item.overridden,
bezier: item.bezier.clone().into(),
enabled: item.enabled,
speed: item.speed,
style: item.style.clone().into(),
})
.collect();
let new_bezs: Vec<BezierIdent> = beziers
.iter()
.map(|item| item.name.clone().into())
.collect();
Ok(Animations(new_anims, new_bezs))
}
async fn get_async() -> crate::Result<Self>
where
Self: Sized,
{
let out = call_hyprctl_data_cmd_async(DataCommands::Animations).await;
let des: AnimationsRaw = serde_json::from_str(&out)?;
let AnimationsRaw(anims, beziers) = des;
let new_anims: Vec<Animation> = anims
.iter()
.map(|item| Animation {
name: item.name.clone(),
overridden: item.overridden,
bezier: item.bezier.clone().into(),
enabled: item.enabled,
speed: item.speed,
style: item.style.clone().into(),
})
.collect();
let new_bezs: Vec<BezierIdent> = beziers
.iter()
.map(|item| item.name.clone().into())
.collect();
Ok(Animations(new_anims, new_bezs))
}
}