mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-13 08:01:05 +01:00
Change static callback vec to local
This commit is contained in:
parent
4e36637e19
commit
1680acc5e9
5 changed files with 184 additions and 90 deletions
|
@ -2,9 +2,6 @@ use pinnacle_api::prelude::*;
|
|||
use pinnacle_api::*;
|
||||
|
||||
fn main() {
|
||||
// let mut num = 5;
|
||||
// let test = &mut num;
|
||||
|
||||
pinnacle_api::connect().unwrap();
|
||||
|
||||
let mod_key = Modifier::Ctrl;
|
||||
|
@ -13,65 +10,97 @@ fn main() {
|
|||
|
||||
process::set_env("MOZ_ENABLE_WAYLAND", "1");
|
||||
|
||||
input::mousebind(&[mod_key], MouseButton::Left, MouseEdge::Press, move || {
|
||||
window::begin_move(MouseButton::Left);
|
||||
});
|
||||
let mut callback_vec = CallbackVec::new();
|
||||
|
||||
input::mousebind(
|
||||
&[mod_key],
|
||||
MouseButton::Left,
|
||||
MouseEdge::Press,
|
||||
move |_| {
|
||||
window::begin_move(MouseButton::Left);
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
|
||||
input::mousebind(
|
||||
&[mod_key],
|
||||
MouseButton::Right,
|
||||
MouseEdge::Press,
|
||||
move || {
|
||||
move |_| {
|
||||
window::begin_resize(MouseButton::Right);
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
|
||||
input::keybind(&[mod_key, Modifier::Alt], 'q', pinnacle::quit);
|
||||
input::keybind(
|
||||
&[mod_key, Modifier::Alt],
|
||||
'q',
|
||||
|_| pinnacle::quit(),
|
||||
&mut callback_vec,
|
||||
);
|
||||
|
||||
input::keybind(&[mod_key, Modifier::Alt], 'c', move || {
|
||||
if let Some(window) = window::get_focused() {
|
||||
window.close();
|
||||
}
|
||||
});
|
||||
input::keybind(
|
||||
&[mod_key, Modifier::Alt],
|
||||
'c',
|
||||
move |_| {
|
||||
if let Some(window) = window::get_focused() {
|
||||
window.close();
|
||||
}
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
|
||||
input::keybind(&[mod_key], xkbcommon::xkb::keysyms::KEY_Return, move || {
|
||||
process::spawn(vec![terminal]).unwrap();
|
||||
});
|
||||
input::keybind(
|
||||
&[mod_key],
|
||||
xkbcommon::xkb::keysyms::KEY_Return,
|
||||
move |_| {
|
||||
process::spawn(vec![terminal]).unwrap();
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
|
||||
input::keybind(
|
||||
&[mod_key, Modifier::Alt],
|
||||
xkbcommon::xkb::keysyms::KEY_space,
|
||||
move || {
|
||||
move |_| {
|
||||
if let Some(window) = window::get_focused() {
|
||||
window.toggle_floating();
|
||||
}
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
|
||||
input::keybind(&[mod_key], 'f', move || {
|
||||
if let Some(window) = window::get_focused() {
|
||||
window.toggle_fullscreen();
|
||||
}
|
||||
});
|
||||
input::keybind(
|
||||
&[mod_key],
|
||||
'f',
|
||||
move |_| {
|
||||
if let Some(window) = window::get_focused() {
|
||||
window.toggle_fullscreen();
|
||||
}
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
|
||||
input::keybind(&[mod_key], 'm', move || {
|
||||
if let Some(window) = window::get_focused() {
|
||||
window.toggle_maximized();
|
||||
}
|
||||
});
|
||||
input::keybind(
|
||||
&[mod_key],
|
||||
'm',
|
||||
move |_| {
|
||||
if let Some(window) = window::get_focused() {
|
||||
window.toggle_maximized();
|
||||
}
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
|
||||
let tags = ["1", "2", "3", "4", "5"];
|
||||
|
||||
output::connect_for_all(move |output| {
|
||||
tag::add(&output, tags.as_slice());
|
||||
tag::get("1", Some(&output)).unwrap().toggle();
|
||||
});
|
||||
|
||||
// let mut num = 5;
|
||||
//
|
||||
// input::keybind(&[mod_key], 'm', || {
|
||||
// num += 1;
|
||||
// });
|
||||
output::connect_for_all(
|
||||
move |output, _| {
|
||||
tag::add(&output, tags.as_slice());
|
||||
tag::get("1", Some(&output)).unwrap().toggle();
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
|
||||
// let layout_cycler = tag.layout_cycler(&[
|
||||
// Layout::MasterStack,
|
||||
|
@ -89,38 +118,46 @@ fn main() {
|
|||
|
||||
for tag_name in tags.iter().map(|t| t.to_string()) {
|
||||
let t = tag_name.clone();
|
||||
input::keybind(&[mod_key], tag_name.chars().next().unwrap(), move || {
|
||||
tag::get(&t, None).unwrap().switch_to();
|
||||
});
|
||||
input::keybind(
|
||||
&[mod_key],
|
||||
tag_name.chars().next().unwrap(),
|
||||
move |_| {
|
||||
tag::get(&t, None).unwrap().switch_to();
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
let t = tag_name.clone();
|
||||
input::keybind(
|
||||
&[mod_key, Modifier::Shift],
|
||||
tag_name.chars().next().unwrap(),
|
||||
move || {
|
||||
move |_| {
|
||||
tag::get(&t, None).unwrap().toggle();
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
let t = tag_name.clone();
|
||||
input::keybind(
|
||||
&[mod_key, Modifier::Alt],
|
||||
tag_name.chars().next().unwrap(),
|
||||
move || {
|
||||
move |_| {
|
||||
if let Some(window) = window::get_focused() {
|
||||
window.move_to_tag(&tag::get(&t, None).unwrap());
|
||||
}
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
let t = tag_name.clone();
|
||||
input::keybind(
|
||||
&[mod_key, Modifier::Shift, Modifier::Alt],
|
||||
tag_name.chars().next().unwrap(),
|
||||
move || {
|
||||
move |_| {
|
||||
if let Some(window) = window::get_focused() {
|
||||
window.toggle_tag(&tag::get(&t, None).unwrap());
|
||||
}
|
||||
},
|
||||
&mut callback_vec,
|
||||
);
|
||||
}
|
||||
|
||||
pinnacle_api::listen();
|
||||
pinnacle_api::listen(callback_vec);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use xkbcommon::xkb::Keysym;
|
|||
|
||||
use crate::{
|
||||
msg::{Args, CallbackId, KeyIntOrString, Msg},
|
||||
send_msg, CALLBACK_VEC,
|
||||
send_msg, CallbackVec,
|
||||
};
|
||||
|
||||
/// Set a keybind.
|
||||
|
@ -18,17 +18,22 @@ use crate::{
|
|||
/// - [`char`]: A character of the key you want. This can be `a`, `~`, `@`, and so on.
|
||||
/// - [`u32`]: The key in numeric form. You can use the keys defined in [`xkbcommon::xkb::keysyms`] for this.
|
||||
/// - [`Keysym`]: The key in `Keysym` form, from [xkbcommon::xkb::Keysym].
|
||||
pub fn keybind<F>(modifiers: &[Modifier], key: impl Into<KeyIntOrString>, mut action: F)
|
||||
where
|
||||
F: FnMut() + Send + 'static,
|
||||
///
|
||||
/// `action` takes in a `&mut `[`CallbackVec`] for use in the closure.
|
||||
pub fn keybind<'a, F>(
|
||||
modifiers: &[Modifier],
|
||||
key: impl Into<KeyIntOrString>,
|
||||
mut action: F,
|
||||
callback_vec: &mut CallbackVec<'a>,
|
||||
) where
|
||||
F: FnMut(&mut CallbackVec) + 'a,
|
||||
{
|
||||
let args_callback = move |_: Option<Args>| {
|
||||
action();
|
||||
let args_callback = move |_: Option<Args>, callback_vec: &mut CallbackVec<'_>| {
|
||||
action(callback_vec);
|
||||
};
|
||||
|
||||
let mut callback_vec = CALLBACK_VEC.lock().unwrap();
|
||||
let len = callback_vec.len();
|
||||
callback_vec.push(Box::new(args_callback));
|
||||
let len = callback_vec.callbacks.len();
|
||||
callback_vec.callbacks.push(Box::new(args_callback));
|
||||
|
||||
let key = key.into();
|
||||
|
||||
|
@ -45,17 +50,23 @@ where
|
|||
///
|
||||
/// The mousebind can happen either on button press or release, so you must
|
||||
/// specify which edge you desire.
|
||||
pub fn mousebind<F>(modifiers: &[Modifier], button: MouseButton, edge: MouseEdge, mut action: F)
|
||||
where
|
||||
F: FnMut() + Send + 'static,
|
||||
///
|
||||
/// `action` takes in a `&mut `[`CallbackVec`] for use in the closure.
|
||||
pub fn mousebind<'a, F>(
|
||||
modifiers: &[Modifier],
|
||||
button: MouseButton,
|
||||
edge: MouseEdge,
|
||||
mut action: F,
|
||||
callback_vec: &mut CallbackVec<'a>,
|
||||
) where
|
||||
F: FnMut(&mut CallbackVec) + 'a,
|
||||
{
|
||||
let args_callback = move |_: Option<Args>| {
|
||||
action();
|
||||
let args_callback = move |_: Option<Args>, callback_vec: &mut CallbackVec<'_>| {
|
||||
action(callback_vec);
|
||||
};
|
||||
|
||||
let mut callback_vec = CALLBACK_VEC.lock().unwrap();
|
||||
let len = callback_vec.len();
|
||||
callback_vec.push(Box::new(args_callback));
|
||||
let len = callback_vec.callbacks.len();
|
||||
callback_vec.callbacks.push(Box::new(args_callback));
|
||||
|
||||
let msg = Msg::SetMousebind {
|
||||
modifiers: modifiers.to_vec(),
|
||||
|
|
|
@ -46,8 +46,6 @@ use msg::{Args, CallbackId, IncomingMsg, Msg, Request, RequestResponse};
|
|||
use crate::msg::RequestId;
|
||||
|
||||
static STREAM: OnceLock<Mutex<UnixStream>> = OnceLock::new();
|
||||
#[allow(clippy::type_complexity)]
|
||||
static CALLBACK_VEC: Mutex<Vec<Box<dyn FnMut(Option<Args>) + Send>>> = Mutex::new(Vec::new());
|
||||
lazy_static::lazy_static! {
|
||||
static ref UNREAD_CALLBACK_MSGS: Mutex<HashMap<CallbackId, IncomingMsg>> = Mutex::new(HashMap::new());
|
||||
static ref UNREAD_REQUEST_MSGS: Mutex<HashMap<RequestId, IncomingMsg>> = Mutex::new(HashMap::new());
|
||||
|
@ -157,7 +155,7 @@ pub fn connect() -> anyhow::Result<()> {
|
|||
/// Begin listening for messages coming from Pinnacle.
|
||||
///
|
||||
/// This needs to be called at the very end of your `setup` function.
|
||||
pub fn listen() -> Infallible {
|
||||
pub fn listen(mut callback_vec: CallbackVec) -> Infallible {
|
||||
loop {
|
||||
let mut unread_callback_msgs = UNREAD_CALLBACK_MSGS.lock().unwrap();
|
||||
|
||||
|
@ -168,11 +166,18 @@ pub fn listen() -> Infallible {
|
|||
let IncomingMsg::CallCallback { callback_id, args } = entry.remove() else {
|
||||
unreachable!();
|
||||
};
|
||||
let mut callback_vec = CALLBACK_VEC.lock().unwrap();
|
||||
let Some(callback) = callback_vec.get_mut(callback_id.0 as usize) else {
|
||||
unreachable!();
|
||||
};
|
||||
callback(args);
|
||||
|
||||
// Take the callback out and replace it with a dummy callback
|
||||
// to allow callback_vec to be used mutably below.
|
||||
let mut callback = std::mem::replace(
|
||||
&mut callback_vec.callbacks[callback_id.0 as usize],
|
||||
Box::new(|_, _| {}),
|
||||
);
|
||||
|
||||
callback(args, &mut callback_vec);
|
||||
|
||||
// Put it back.
|
||||
callback_vec.callbacks[callback_id.0 as usize] = callback;
|
||||
}
|
||||
|
||||
let incoming_msg = read_msg(None);
|
||||
|
@ -181,11 +186,43 @@ pub fn listen() -> Infallible {
|
|||
unreachable!();
|
||||
};
|
||||
|
||||
let mut callback_vec = CALLBACK_VEC.lock().unwrap();
|
||||
let Some(callback) = callback_vec.get_mut(callback_id.0 as usize) else {
|
||||
unreachable!();
|
||||
};
|
||||
let mut callback = std::mem::replace(
|
||||
&mut callback_vec.callbacks[callback_id.0 as usize],
|
||||
Box::new(|_, _| {}),
|
||||
);
|
||||
|
||||
callback(args);
|
||||
callback(args, &mut callback_vec);
|
||||
|
||||
callback_vec.callbacks[callback_id.0 as usize] = callback;
|
||||
}
|
||||
}
|
||||
|
||||
/// A wrapper around a vector that holds all of your callbacks.
|
||||
///
|
||||
/// You will need to create this before you can start calling config functions
|
||||
/// that require callbacks.
|
||||
///
|
||||
/// Because your callbacks can capture things, we need a non-static way to hold them.
|
||||
/// That's where this struct comes in.
|
||||
///
|
||||
/// Every function that needs you to provide a callback will also need you to
|
||||
/// provide a `&mut CallbackVec`. This will insert the callback for use in [`listen`].
|
||||
///
|
||||
/// Additionally, all callbacks will also take in `&mut CallbackVec`. This is so you can
|
||||
/// call functions that need it inside of other callbacks.
|
||||
///
|
||||
/// At the end of your config, you will need to call [`listen`] to begin listening for
|
||||
/// messages from Pinnacle that will call your callbacks. Here, you must in pass your
|
||||
/// `CallbackVec`.
|
||||
#[derive(Default)]
|
||||
pub struct CallbackVec<'a> {
|
||||
#[allow(clippy::type_complexity)]
|
||||
pub(crate) callbacks: Vec<Box<dyn FnMut(Option<Args>, &mut CallbackVec) + 'a>>,
|
||||
}
|
||||
|
||||
impl<'a> CallbackVec<'a> {
|
||||
/// Create a new, empty `CallbackVec`.
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
msg::{Args, CallbackId, Msg, Request, RequestResponse},
|
||||
request, send_msg,
|
||||
tag::TagHandle,
|
||||
CALLBACK_VEC,
|
||||
CallbackVec,
|
||||
};
|
||||
|
||||
/// A unique identifier for an output.
|
||||
|
@ -58,6 +58,10 @@ pub fn get_focused() -> Option<OutputHandle> {
|
|||
/// When called, `connect_for_all` will run `func` with all currently connected outputs.
|
||||
/// If a new output is connected, `func` will also be called with it.
|
||||
///
|
||||
/// `func` takes in two parameters:
|
||||
/// - `0`: An [`OutputHandle`] you can act on.
|
||||
/// - `1`: A `&mut `[`CallbackVec`] for use in the closure.
|
||||
///
|
||||
/// This will *not* be called if it has already been called for a given connector.
|
||||
/// This means turning your monitor off and on or unplugging and replugging it *to the same port*
|
||||
/// won't trigger `func`. Plugging it in to a new port *will* trigger `func`.
|
||||
|
@ -66,19 +70,18 @@ pub fn get_focused() -> Option<OutputHandle> {
|
|||
/// Please note: this function will be run *after* Pinnacle processes your entire config.
|
||||
/// For example, if you define tags in `func` but toggle them directly after `connect_for_all`,
|
||||
/// nothing will happen as the tags haven't been added yet.
|
||||
pub fn connect_for_all<F>(mut func: F)
|
||||
pub fn connect_for_all<'a, F>(mut func: F, callback_vec: &mut CallbackVec<'a>)
|
||||
where
|
||||
F: FnMut(OutputHandle) + Send + 'static,
|
||||
F: FnMut(OutputHandle, &mut CallbackVec) + 'a,
|
||||
{
|
||||
let args_callback = move |args: Option<Args>| {
|
||||
let args_callback = move |args: Option<Args>, callback_vec: &mut CallbackVec<'_>| {
|
||||
if let Some(Args::ConnectForAllOutputs { output_name }) = args {
|
||||
func(OutputHandle(OutputName(output_name)));
|
||||
func(OutputHandle(OutputName(output_name)), callback_vec);
|
||||
}
|
||||
};
|
||||
|
||||
let mut callback_vec = CALLBACK_VEC.lock().unwrap();
|
||||
let len = callback_vec.len();
|
||||
callback_vec.push(Box::new(args_callback));
|
||||
let len = callback_vec.callbacks.len();
|
||||
callback_vec.callbacks.push(Box::new(args_callback));
|
||||
|
||||
let msg = Msg::ConnectForAllOutputs {
|
||||
callback_id: CallbackId(len as u32),
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use crate::{
|
||||
msg::{Args, CallbackId, Msg},
|
||||
send_msg, CALLBACK_VEC,
|
||||
send_msg, CallbackVec,
|
||||
};
|
||||
|
||||
/// Spawn a process.
|
||||
|
@ -26,11 +26,18 @@ pub fn spawn(command: Vec<&str>) -> anyhow::Result<()> {
|
|||
/// - `1`: The process's stderr printed this line.
|
||||
/// - `2`: The process exited with this code.
|
||||
/// - `3`: The process exited with this message.
|
||||
pub fn spawn_with_callback<F>(command: Vec<&str>, mut callback: F) -> anyhow::Result<()>
|
||||
/// - `4`: A `&mut `[`CallbackVec`] for use inside the closure.
|
||||
///
|
||||
/// You must also pass in a mutable reference to a [`CallbackVec`] in order to store your callback.
|
||||
pub fn spawn_with_callback<'a, F>(
|
||||
command: Vec<&str>,
|
||||
mut callback: F,
|
||||
callback_vec: &mut CallbackVec<'a>,
|
||||
) -> anyhow::Result<()>
|
||||
where
|
||||
F: FnMut(Option<String>, Option<String>, Option<i32>, Option<String>) + Send + 'static,
|
||||
F: FnMut(Option<String>, Option<String>, Option<i32>, Option<String>, &mut CallbackVec) + 'a,
|
||||
{
|
||||
let args_callback = move |args: Option<Args>| {
|
||||
let args_callback = move |args: Option<Args>, callback_vec: &mut CallbackVec<'_>| {
|
||||
if let Some(Args::Spawn {
|
||||
stdout,
|
||||
stderr,
|
||||
|
@ -38,13 +45,12 @@ where
|
|||
exit_msg,
|
||||
}) = args
|
||||
{
|
||||
callback(stdout, stderr, exit_code, exit_msg);
|
||||
callback(stdout, stderr, exit_code, exit_msg, callback_vec);
|
||||
}
|
||||
};
|
||||
|
||||
let mut callback_vec = CALLBACK_VEC.lock().unwrap();
|
||||
let len = callback_vec.len();
|
||||
callback_vec.push(Box::new(args_callback));
|
||||
let len = callback_vec.callbacks.len();
|
||||
callback_vec.callbacks.push(Box::new(args_callback));
|
||||
|
||||
let msg = Msg::Spawn {
|
||||
command: command.into_iter().map(|s| s.to_string()).collect(),
|
||||
|
|
Loading…
Reference in a new issue