Skip to content

Commit

Permalink
Hyprland-rs 0.3.2
Browse files Browse the repository at this point in the history
  • Loading branch information
yavko committed Apr 19, 2023
1 parent 96f1a3f commit bdff886
Show file tree
Hide file tree
Showing 11 changed files with 269 additions and 66 deletions.
181 changes: 124 additions & 57 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ lto = true
members = ["hyprland-macros"]

[workspace.package]
version = "0.3.1"
version = "0.3.2"
license = "GPL-3.0-or-later"
repository = "https://github.com/hyprland-community/hyprland-rs"
keywords = ["hyprland", "ipc", "hypr", "wayland", "linux"]
Expand Down Expand Up @@ -63,4 +63,4 @@ ctl = []
keyword = []
config = ["dispatch", "keyword"]
listener = ["data", "dispatch"]

silent = []
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Let's get started with Hyprland-rs!
Add the code below to the dependencies section of your Cargo.toml file!

```toml
hyprland = "0.3.1"
hyprland = "0.3.2"
```

#### Master version
Expand Down
38 changes: 38 additions & 0 deletions src/ctl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,44 @@ pub mod set_error {
}
}

/// Creates a notification with Hyprland
pub mod notify {
use super::*;
use std::time::Duration;
#[repr(u8)]
#[allow(missing_docs)]
pub enum Icon {
Warning = 0,
Info = 1,
Hint = 2,
Error = 3,
Confused = 4,
Ok = 5,
}
/// Creates a notification with Hyprland
pub fn call(icon: Icon, time: Duration, color: Color, msg: String) -> crate::Result<()> {
write_to_socket_sync(
get_socket_path(SocketType::Command),
&format!("notify {} {} {color} {msg}", icon as u8, time.as_millis()).into_bytes(),
)?;
Ok(())
}
/// Creates a error that Hyprland will display (async)
pub async fn call_async(
icon: Icon,
time: Duration,
color: Color,
msg: String,
) -> crate::Result<()> {
write_to_socket(
get_socket_path(SocketType::Command),
&format!("notify {} {} {color} {msg}", icon as u8, time.as_millis()).into_bytes(),
)
.await?;
Ok(())
}
}

/// A 8-bit color with a alpha channel
#[derive(MDisplay, Constructor)]
#[display(fmt = "rgba({},{},{},{})", "_0", "_1", "_2", "_3")]
Expand Down
48 changes: 48 additions & 0 deletions src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,16 @@ pub enum CycleDirection {
Previous,
}

/// This enum holds a direction for switch windows in a group
#[allow(missing_docs)]
#[derive(Debug, Clone, Display)]
pub enum WindowSwitchDirection {
#[display(fmt = "b")]
Back,
#[display(fmt = "f")]
Forward,
}

/// This enum is used for identifying monitors
#[derive(Debug, Clone)]
pub enum MonitorIdentifier<'a> {
Expand Down Expand Up @@ -260,6 +270,8 @@ pub enum DispatchType<'a> {
/// This dispatcher passes a keybind to a window when called in a
/// keybind, its used for global keybinds. And should **ONLY** be used with keybinds
Pass(WindowIdentifier<'a>),
/// Executes a Global Shortcut using the GlobalShortcuts portal.
Global(&'a str),
/// This dispatcher kills the active window/client
KillActiveWindow,
/// This dispatcher closes the specified window
Expand Down Expand Up @@ -338,6 +350,8 @@ pub enum DispatchType<'a> {
ToggleSpecialWorkspace(Option<String>),
/// This dispatcher jump to urgent or the last window
FocusUrgentOrLast,
/// Switch focus from current to previously focused window
FocusCurrentOrLast,

// LAYOUT DISPATCHERS
// DWINDLE
Expand Down Expand Up @@ -376,7 +390,34 @@ pub enum DispatchType<'a> {
OrientationNext,
/// Cycle to the previous orientation for the current workspace (counter-clockwise)
OrientationPrev,

// Group Dispatchers
/// Toggles the current active window into a group
ToggleGroup,
/// Switches to the next window in a group.
ChangeGroupActive(WindowSwitchDirection),
/// Locks the groups
LockGroups(LockType),
/// Moves the active window into a group in a specified direction
MoveIntoGroup(Direction),
/// Moves the active window out of a group.
MoveOutOfGroup,
}

/// Enum used with [DispatchType::LockGroups], to determine how to lock/unlock
#[derive(Debug, Clone, Copy, Display, PartialEq, Eq, PartialOrd, Ord)]
pub enum LockType {
/// Lock Group
#[display(fmt = "lock")]
Lock,
/// Unlock Group
#[display(fmt = "unlock")]
Unlock,
/// Toggle lock state of Group
#[display(fmt = "toggle")]
ToggleLock,
}

/// Param for [SwapWithMaster] dispatcher
#[derive(Debug, Clone, Display)]
pub enum SwapWithMasterParam {
Expand Down Expand Up @@ -422,6 +463,7 @@ pub(crate) fn gen_dispatch_str(cmd: DispatchType, dispatch: bool) -> crate::Resu
Custom(name, args) => format!("{name}{sep}{args}"),
Exec(sh) => format!("exec{sep}{sh}"),
Pass(win) => format!("pass{sep}{win}"),
Global(name) => format!("global{sep}{name}"),
KillActiveWindow => "killactive".to_string(),
CloseWindow(win) => format!("closewindow{sep}{win}"),
Workspace(work) => format!("workspace{sep}{work}"),
Expand Down Expand Up @@ -481,6 +523,7 @@ pub(crate) fn gen_dispatch_str(cmd: DispatchType, dispatch: bool) -> crate::Resu
BringActiveToTop => "bringactivetotop".to_string(),
SetCursor(theme, size) => format!("{theme} {}", *size),
FocusUrgentOrLast => "focusurgentorlast".to_string(),
FocusCurrentOrLast => "focuscurrentorlast".to_string(),
ToggleSplit => "togglesplit".to_string(),
SwapWithMaster(param) => format!("swapwithmaster{sep}{param}"),
FocusMaster(param) => format!("focusmaster{sep}{param}"),
Expand All @@ -493,6 +536,11 @@ pub(crate) fn gen_dispatch_str(cmd: DispatchType, dispatch: bool) -> crate::Resu
OrientationCenter => "orientationcenter".to_string(),
OrientationNext => "orientationnext".to_string(),
OrientationPrev => "orientationprev".to_string(),
ToggleGroup => "togglegroup".to_string(),
ChangeGroupActive(dir) => format!("changegroupactive{sep}{dir}"),
LockGroups(how) => format!("lockgroups{sep}{how}"),
MoveIntoGroup(dir) => format!("moveintogroup{sep}{dir}"),
MoveOutOfGroup => "moveoutofgroup".to_string(),
};
if let SetCursor(_, _) = cmd {
Ok(format!("setcursor {string_to_pass}"))
Expand Down
1 change: 1 addition & 0 deletions src/event_listener/async_im.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl AsyncEventListener {
Event::FloatStateChanged(even) => arm_async!(even.clone(), float_state_events, self),
Event::UrgentStateChanged(even) => arm_async!(even.clone(), urgent_state_events, self),
Event::Minimize(data) => arm_async!(data.clone(), minimize_events, self),
Event::Screencopy(data) => arm_async!(*data, screencopy_events, self),
}
}

Expand Down
1 change: 1 addition & 0 deletions src/event_listener/immutable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ impl EventListener {
FloatStateChanged(even) => arm!(even, float_state_events, self),
UrgentStateChanged(even) => arm!(even, urgent_state_events, self),
Minimize(data) => arm!(data, minimize_events, self),
Event::Screencopy(data) => arm!(data, screencopy_events, self),
}
}

Expand Down
1 change: 1 addition & 0 deletions src/event_listener/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ macro_rules! init_events {
float_state_events: vec![],
urgent_state_events: vec![],
minimize_events: vec![],
screencopy_events: vec![],
}
};
}
2 changes: 2 additions & 0 deletions src/event_listener/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,5 @@ add_listener!(layer_open, String, "a new layer is opened", "Layer opened" => dat
add_listener!(layer_closed, String, "a layer is closed", "Layer closed" => data);
add_listener!(float_state, WindowFloatEventData, "the float state of a window is changed", "Float state changed" => data);
add_listener!(urgent_state, Address, "the urgent state of a window is changed", "urgent state changed" => data);
add_listener!(minimize, MinimizeEventData, "the minimize state of a window is changed", "minimize state changed" => data);
add_listener!(screencopy, ScreencopyEventData, "the screencopy state of a window is changed", "screencopy state changed" => data);
2 changes: 2 additions & 0 deletions src/event_listener/mutable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ impl EventListener {
Event::FloatStateChanged(even) => mut_arm!(even.clone(), float_state_events, self),
Event::UrgentStateChanged(even) => mut_arm!(even.clone(), urgent_state_events, self),
Event::Minimize(data) => mut_arm!(data.clone(), minimize_events, self),
Event::Screencopy(data) => mut_arm!(*data, screencopy_events, self),
}
Ok(())
}
Expand Down Expand Up @@ -179,6 +180,7 @@ impl EventListener {
mut_arm_sync!(even.clone(), urgent_state_events, self)
}
Event::Minimize(data) => mut_arm_sync!(data.clone(), minimize_events, self),
Event::Screencopy(data) => mut_arm_sync!(*data, screencopy_events, self),
}
Ok(())
}
Expand Down
55 changes: 49 additions & 6 deletions src/event_listener/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ pub(crate) struct Events {
pub(crate) float_state_events: Closures<WindowFloatEventData>,
pub(crate) urgent_state_events: Closures<Address>,
pub(crate) minimize_events: Closures<MinimizeEventData>,
pub(crate) screencopy_events: Closures<ScreencopyEventData>,
}

#[allow(clippy::type_complexity)]
Expand All @@ -81,6 +82,7 @@ pub(crate) struct AsyncEvents {
pub(crate) float_state_events: AsyncClosures<WindowFloatEventData>,
pub(crate) urgent_state_events: AsyncClosures<Address>,
pub(crate) minimize_events: AsyncClosures<MinimizeEventData>,
pub(crate) screencopy_events: AsyncClosures<ScreencopyEventData>,
}

/// Event data for a minimize event
Expand All @@ -92,6 +94,15 @@ pub struct MinimizeEventData(
pub bool,
);

/// Event data for screencopy event
#[derive(Debug, Clone, Copy)]
pub struct ScreencopyEventData(
/// State/Is it turning on?
pub bool,
/// Owner type, is it a monitor?
pub bool,
);

/// The data for the event executed when moving a window to a new workspace
#[derive(Clone, Debug)]
pub struct WindowMoveEvent(
Expand Down Expand Up @@ -143,6 +154,7 @@ pub struct State {
use std::ops::{Deref, DerefMut};
/// Wrapper type that adds handler for events
#[derive(Clone)]
#[doc(hidden)]
pub struct MutWrapper<'a, 'b, T>(T, &'a (dyn Fn(T) + 'a), &'b (dyn Fn(T) -> VoidFuture + 'b));
impl<T> MutWrapper<'_, '_, T> {
#[allow(dead_code)]
Expand Down Expand Up @@ -177,6 +189,7 @@ impl<T: Clone> DerefMut for MutWrapper<'_, '_, T> {

/// The mutable state available to Closures
#[derive(PartialEq, Eq, Clone, Debug)]
#[doc(hidden)]
pub struct StateV2 {
/// The active workspace
pub workspace: MutWrapper<'static, 'static, String>,
Expand Down Expand Up @@ -396,6 +409,7 @@ pub(crate) enum Event {
FloatStateChanged(WindowFloatEventData),
UrgentStateChanged(Address),
Minimize(MinimizeEventData),
Screencopy(ScreencopyEventData),
}

fn check_for_regex_error(val: Result<Regex, RegexError>) -> Regex {
Expand Down Expand Up @@ -439,6 +453,7 @@ fn parse_string_as_work(str: String) -> WorkspaceType {

macro_rules! report_unknown {
($event:tt) => {
#[cfg(not(feature = "silent"))]
eprintln!(
"A unknown event was passed into Hyprland-rs
PLEASE MAKE AN ISSUE!!
Expand All @@ -448,6 +463,10 @@ macro_rules! report_unknown {
};
}

use std::collections::BTreeSet;
use std::sync::Mutex;
static CHECK_TABLE: Mutex<BTreeSet<String>> = Mutex::new(BTreeSet::new());

/// This internal function parses event strings
pub(crate) fn event_parser(event: String) -> crate::Result<Vec<Event>> {
lazy_static! {
Expand All @@ -471,6 +490,7 @@ pub(crate) fn event_parser(event: String) -> crate::Result<Vec<Event>> {
r"closelayer>>(?P<namespace>.*)",
r"changefloatingmode>>(?P<address>.*),(?P<floatstate>[0-1])",
r"minimize>>(?P<address>.*),(?P<state>[0-1])",
r"screencopy>>(?P<state>[0-1]),(?P<owner>[0-1])",
r"(?P<Event>.*)>>.*?"
]));
static ref EVENT_REGEXES: Vec<Regex> = EVENT_SET
Expand Down Expand Up @@ -649,23 +669,46 @@ pub(crate) fn event_parser(event: String) -> crate::Result<Vec<Event>> {
state,
)));
}
20 => {
// ScreenCopyStateChanged
let state = &captures["state"] == "1";
let owner = &captures["owner"] == "1";
events.push(Event::Screencopy(ScreencopyEventData(state, owner)));
}
_ => unreachable!(), //panic!("There are only 16 items in the array? prob a regex issue 🤷"),
}
} else if matches_event.len() == 1 {
if matches_event[0] != *EVENT_LEN {
panic!("One event matched, that isn't the unrecognised event type, sus")
} else {
// Unknown Event
#[cfg(not(feature = "silent"))]
match &captures.name("event") {
Some(s) => eprintln!(
"A unknown event was passed into Hyprland-rs
Some(s) => {
let table = CHECK_TABLE.lock();
if let Ok(mut tbl) = table {
let should_run = tbl.insert(s.as_str().to_string());
if should_run == true {
eprintln!(
"A unknown event was passed into Hyprland-rs
PLEASE MAKE AN ISSUE!!
The event was: {}",
s.as_str()
),
None => eprintln!(
s.as_str()
);
}
}
}
None => {
let table = CHECK_TABLE.lock();
if let Ok(mut tbl) = table {
let should_run = tbl.insert("unknown".to_string());
if should_run == true {
eprintln!(
"A unknown event was passed into Hyprland-rs\nPLEASE MAKE AN ISSUE!!\nThe event was: {item}"
),
);
}
}
}
};
}
} else {
Expand Down

0 comments on commit bdff886

Please sign in to comment.