mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-14 08:01:14 +01:00
Add quit function to api, update README and example_config
This commit is contained in:
parent
c46159c77a
commit
8c054e17ba
8 changed files with 121 additions and 131 deletions
18
README.md
18
README.md
|
@ -77,7 +77,7 @@ It is *highly* recommended to use the [Lua language server](https://github.com/L
|
||||||
Install the [Lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) plugin, then go into its settings and add the absolute(?) path to the [`api/lua`](api/lua) directory to Workspace: Library.
|
Install the [Lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) plugin, then go into its settings and add the absolute(?) path to the [`api/lua`](api/lua) directory to Workspace: Library.
|
||||||
|
|
||||||
#### For Neovim:
|
#### For Neovim:
|
||||||
Pass
|
Pass this table into your Lua language server settings:
|
||||||
```lua
|
```lua
|
||||||
Lua = {
|
Lua = {
|
||||||
workspace = {
|
workspace = {
|
||||||
|
@ -87,28 +87,18 @@ Lua = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
into your Lua language server settings.
|
|
||||||
|
|
||||||
Doc website soon:tm:
|
Doc website soon:tm:
|
||||||
|
|
||||||
## Controls
|
## Controls
|
||||||
The following controls are currently hardcoded:
|
The following controls are currently hardcoded:
|
||||||
|
|
||||||
- `Esc`: Stop Pinnacle
|
|
||||||
- `Ctrl + Left Mouse`: Move a window
|
- `Ctrl + Left Mouse`: Move a window
|
||||||
- `Ctrl + Right Mouse`: Resize a window
|
- `Ctrl + Right Mouse`: Resize a window
|
||||||
|
|
||||||
The following controls are set in the [`example_config`](api/lua/example_config.lua):
|
You can find the rest of the controls in the [`example_config`](api/lua/example_config.lua).
|
||||||
- `Ctrl + Alt + C`: Close the currently focused window
|
|
||||||
- `Ctrl + Alt + Space`: Toggle "floating" for the currently focused window
|
|
||||||
- `Ctrl + Return`: Open Alacritty
|
|
||||||
- `Ctrl + 1`: Open Kitty
|
|
||||||
- `Ctrl + 2`: Open Foot
|
|
||||||
- `Ctrl + 3`: Open Nautilus
|
|
||||||
|
|
||||||
"Floating" is in quotes because while windows do currently tile themselves, tiled ones can still be moved just like a floating window. Toggling to and from floating will retile all tiled windows.
|
|
||||||
|
|
||||||
The only layout currently is a master stack with the master on the left side.
|
|
||||||
|
|
||||||
## A Small Note
|
## A Small Note
|
||||||
This is currently just a summer project I'm working on, but I hope that I can work on it enough that it becomes somewhat usable! If development slows down during the rest of the year, it's because :star:university:star:.
|
This is currently just a summer project I'm working on, but I hope that I can work on it enough that it becomes somewhat usable! If development slows down during the rest of the year, it's because :star:university:star:.
|
||||||
|
|
||||||
|
Also the only layout is kinda wonk right now if you close all but one window
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
require("pinnacle").setup(function(pinnacle)
|
require("pinnacle").setup(function(pinnacle)
|
||||||
local input = pinnacle.input
|
local input = pinnacle.input --Key and mouse binds
|
||||||
local client = pinnacle.client
|
local client = pinnacle.client --Window management
|
||||||
local keys = pinnacle.keys
|
local process = pinnacle.process -- Process spawning
|
||||||
local process = pinnacle.process
|
|
||||||
|
|
||||||
input.keybind({ "Alt", "Ctrl" }, keys.c, client.close_window)
|
-- Every key supported by xkbcommon.
|
||||||
|
-- Support for just putting in a string of a key is intended.
|
||||||
|
local keys = input.keys
|
||||||
|
|
||||||
|
-- Keybinds ----------------------------------------------------------------------
|
||||||
|
input.keybind({ "Ctrl", "Alt" }, keys.c, client.close_window)
|
||||||
|
|
||||||
|
-- NOTE: In tiled mode you can still move stuff around as if it's floating. Actual tiling is TODO
|
||||||
input.keybind({ "Ctrl", "Alt" }, keys.space, client.toggle_floating)
|
input.keybind({ "Ctrl", "Alt" }, keys.space, client.toggle_floating)
|
||||||
|
|
||||||
input.keybind({ "Ctrl" }, keys.Return, function()
|
input.keybind({ "Ctrl" }, keys.Return, function()
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
local M = {}
|
local M = {
|
||||||
|
keys = require("keys"),
|
||||||
|
}
|
||||||
|
|
||||||
---Set a keybind. If called on an already existing keybind, it gets replaced.
|
---Set a keybind. If called on an already existing keybind, it gets replaced.
|
||||||
---@param key Keys The key for the keybind. NOTE: uppercase and lowercase characters are considered different.
|
---@param key Keys The key for the keybind. NOTE: uppercase and lowercase characters are considered different.
|
||||||
|
|
|
@ -43,10 +43,14 @@ end
|
||||||
local pinnacle = {
|
local pinnacle = {
|
||||||
input = require("input"),
|
input = require("input"),
|
||||||
client = require("client"),
|
client = require("client"),
|
||||||
keys = require("keys"),
|
|
||||||
process = require("process"),
|
process = require("process"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---Quit Pinnacle.
|
||||||
|
function pinnacle.quit()
|
||||||
|
SendMsg("Quit")
|
||||||
|
end
|
||||||
|
|
||||||
---Configure Pinnacle. You should put mostly eveything into the config_func to avoid invalid state.
|
---Configure Pinnacle. You should put mostly eveything into the config_func to avoid invalid state.
|
||||||
---The function takes one argument: the Pinnacle table, which is how you'll access all of the available config options.
|
---The function takes one argument: the Pinnacle table, which is how you'll access all of the available config options.
|
||||||
---@param config_func fun(pinnacle: Pinnacle)
|
---@param config_func fun(pinnacle: Pinnacle)
|
||||||
|
|
|
@ -66,7 +66,6 @@ impl PinnacleSocketSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
|
||||||
pub fn send_to_client(
|
pub fn send_to_client(
|
||||||
stream: &mut UnixStream,
|
stream: &mut UnixStream,
|
||||||
msg: &OutgoingMsg,
|
msg: &OutgoingMsg,
|
||||||
|
|
|
@ -41,6 +41,10 @@ pub enum Msg {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
callback_id: Option<CallbackId>,
|
callback_id: Option<CallbackId>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Pinnacle management
|
||||||
|
/// Quit the compositor.
|
||||||
|
Quit,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, PartialEq, Eq, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
|
|
48
src/input.rs
48
src/input.rs
|
@ -228,17 +228,6 @@ impl<B: Backend> State<B> {
|
||||||
{
|
{
|
||||||
return FilterResult::Intercept(*callback_id);
|
return FilterResult::Intercept(*callback_id);
|
||||||
}
|
}
|
||||||
match keysym.modified_sym() {
|
|
||||||
keysyms::KEY_L => return FilterResult::Intercept(100),
|
|
||||||
keysyms::KEY_K => return FilterResult::Intercept(200),
|
|
||||||
keysyms::KEY_J => return FilterResult::Intercept(300),
|
|
||||||
keysyms::KEY_H => return FilterResult::Intercept(400),
|
|
||||||
keysyms::KEY_Escape => {
|
|
||||||
state.loop_signal.stop();
|
|
||||||
return FilterResult::Intercept(0);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if keysym.modified_sym() == keysyms::KEY_Control_L {
|
if keysym.modified_sym() == keysyms::KEY_Control_L {
|
||||||
|
@ -259,34 +248,19 @@ impl<B: Backend> State<B> {
|
||||||
|
|
||||||
self.move_mode = move_mode;
|
self.move_mode = move_mode;
|
||||||
|
|
||||||
let program = match action {
|
if let Some(callback_id) = action {
|
||||||
Some(100) => "alacritty",
|
if let Some(stream) = self.api_state.stream.as_ref() {
|
||||||
Some(200) => "nautilus",
|
if let Err(err) = crate::api::send_to_client(
|
||||||
Some(300) => "kitty",
|
&mut stream.lock().unwrap(),
|
||||||
Some(400) => "foot",
|
&OutgoingMsg::CallCallback {
|
||||||
Some(callback_id) => {
|
callback_id: CallbackId(callback_id),
|
||||||
if let Some(stream) = self.api_state.stream.as_mut() {
|
args: None,
|
||||||
if let Err(err) = crate::api::send_to_client(
|
},
|
||||||
&mut self.api_state.stream.as_ref().unwrap().lock().unwrap(),
|
) {
|
||||||
&OutgoingMsg::CallCallback {
|
// TODO: print error
|
||||||
callback_id: CallbackId(callback_id),
|
|
||||||
args: None,
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
// TODO: print error
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
None => return,
|
}
|
||||||
};
|
|
||||||
|
|
||||||
tracing::info!("Spawning {}", program);
|
|
||||||
std::process::Command::new(program)
|
|
||||||
.env("WAYLAND_DISPLAY", self.socket_name.clone())
|
|
||||||
.spawn()
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
155
src/state.rs
155
src/state.rs
|
@ -118,6 +118,7 @@ impl<B: Backend> State<B> {
|
||||||
let (tx_channel, rx_channel) = calloop::channel::channel::<Msg>();
|
let (tx_channel, rx_channel) = calloop::channel::channel::<Msg>();
|
||||||
loop_handle.insert_source(rx_channel, |msg, _, data| match msg {
|
loop_handle.insert_source(rx_channel, |msg, _, data| match msg {
|
||||||
Event::Msg(msg) => {
|
Event::Msg(msg) => {
|
||||||
|
// TODO: move this into its own function
|
||||||
match msg {
|
match msg {
|
||||||
Msg::SetKeybind {
|
Msg::SetKeybind {
|
||||||
key,
|
key,
|
||||||
|
@ -162,6 +163,8 @@ impl<B: Backend> State<B> {
|
||||||
.stdin(if callback_id.is_some() {
|
.stdin(if callback_id.is_some() {
|
||||||
Stdio::piped()
|
Stdio::piped()
|
||||||
} else {
|
} else {
|
||||||
|
// piping to null because foot won't open without a callback_id
|
||||||
|
// otherwise
|
||||||
Stdio::null()
|
Stdio::null()
|
||||||
})
|
})
|
||||||
.stdout(if callback_id.is_some() {
|
.stdout(if callback_id.is_some() {
|
||||||
|
@ -180,81 +183,84 @@ impl<B: Backend> State<B> {
|
||||||
|
|
||||||
// TODO: find a way to make this hellish code look better, deal with unwraps
|
// TODO: find a way to make this hellish code look better, deal with unwraps
|
||||||
if let Some(callback_id) = callback_id {
|
if let Some(callback_id) = callback_id {
|
||||||
let stdout = child.stdout.take().unwrap();
|
let stdout = child.stdout.take();
|
||||||
let stderr = child.stderr.take().unwrap();
|
let stderr = child.stderr.take();
|
||||||
let stream = data.state.api_state.stream.as_ref().unwrap().clone();
|
let stream_out = data.state.api_state.stream.as_ref().unwrap().clone();
|
||||||
// data.state
|
let stream_err = stream_out.clone();
|
||||||
// .api_state
|
let stream_exit = stream_out.clone();
|
||||||
// .stream
|
|
||||||
// .replace(stream.try_clone().unwrap());
|
if let Some(stdout) = stdout {
|
||||||
let stream2 = stream.clone();
|
std::thread::spawn(move || {
|
||||||
let stream3 = stream.clone();
|
// TODO: maybe find a way to make this async?
|
||||||
std::thread::spawn(move || {
|
let mut reader = BufReader::new(stdout);
|
||||||
// TODO: maybe make this not a thread?
|
loop {
|
||||||
let mut reader = BufReader::new(stdout);
|
let mut buf = String::new();
|
||||||
loop {
|
match reader.read_line(&mut buf) {
|
||||||
let mut buf = String::new();
|
Ok(0) => break, // stream closed
|
||||||
match reader.read_line(&mut buf) {
|
Ok(_) => {
|
||||||
Ok(0) => break, // EOF
|
let mut stream = stream_out.lock().unwrap();
|
||||||
Ok(_) => {
|
crate::api::send_to_client(
|
||||||
let mut stream = stream.lock().unwrap();
|
&mut stream,
|
||||||
crate::api::send_to_client(
|
&OutgoingMsg::CallCallback {
|
||||||
&mut stream,
|
callback_id,
|
||||||
&OutgoingMsg::CallCallback {
|
args: Some(Args::Spawn {
|
||||||
callback_id,
|
stdout: Some(
|
||||||
args: Some(Args::Spawn {
|
buf.trim_end_matches('\n')
|
||||||
stdout: Some(
|
.to_string(),
|
||||||
buf.trim_end_matches('\n').to_string(),
|
),
|
||||||
),
|
stderr: None,
|
||||||
stderr: None,
|
exit_code: None,
|
||||||
exit_code: None,
|
exit_msg: None,
|
||||||
exit_msg: None,
|
}),
|
||||||
}),
|
},
|
||||||
},
|
)
|
||||||
)
|
.unwrap();
|
||||||
.unwrap();
|
}
|
||||||
}
|
Err(err) => {
|
||||||
Err(err) => {
|
tracing::error!("child read err: {err}");
|
||||||
tracing::error!("child read err: {err}");
|
break;
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
std::thread::spawn(move || {
|
if let Some(stderr) = stderr {
|
||||||
let mut reader = BufReader::new(stderr);
|
std::thread::spawn(move || {
|
||||||
loop {
|
let mut reader = BufReader::new(stderr);
|
||||||
let mut buf = String::new();
|
loop {
|
||||||
match reader.read_line(&mut buf) {
|
let mut buf = String::new();
|
||||||
Ok(0) => break, // EOF
|
match reader.read_line(&mut buf) {
|
||||||
Ok(_) => {
|
Ok(0) => break, // stream closed
|
||||||
let mut stream = stream2.lock().unwrap();
|
Ok(_) => {
|
||||||
crate::api::send_to_client(
|
let mut stream = stream_err.lock().unwrap();
|
||||||
&mut stream,
|
crate::api::send_to_client(
|
||||||
&OutgoingMsg::CallCallback {
|
&mut stream,
|
||||||
callback_id,
|
&OutgoingMsg::CallCallback {
|
||||||
args: Some(Args::Spawn {
|
callback_id,
|
||||||
stdout: None,
|
args: Some(Args::Spawn {
|
||||||
stderr: Some(
|
stdout: None,
|
||||||
buf.trim_end_matches('\n').to_string(),
|
stderr: Some(
|
||||||
),
|
buf.trim_end_matches('\n')
|
||||||
exit_code: None,
|
.to_string(),
|
||||||
exit_msg: None,
|
),
|
||||||
}),
|
exit_code: None,
|
||||||
},
|
exit_msg: None,
|
||||||
)
|
}),
|
||||||
.unwrap();
|
},
|
||||||
}
|
)
|
||||||
Err(err) => {
|
.unwrap();
|
||||||
tracing::error!("child read err: {err}");
|
}
|
||||||
break;
|
Err(err) => {
|
||||||
|
tracing::error!("child read err: {err}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
std::thread::spawn(move || match child.wait() {
|
std::thread::spawn(move || match child.wait() {
|
||||||
Ok(exit_status) => {
|
Ok(exit_status) => {
|
||||||
let mut stream = stream3.lock().unwrap();
|
let mut stream = stream_exit.lock().unwrap();
|
||||||
crate::api::send_to_client(
|
crate::api::send_to_client(
|
||||||
&mut stream,
|
&mut stream,
|
||||||
&OutgoingMsg::CallCallback {
|
&OutgoingMsg::CallCallback {
|
||||||
|
@ -275,9 +281,14 @@ impl<B: Backend> State<B> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Msg::SpawnShell {
|
||||||
// TODO: add the rest
|
shell,
|
||||||
_ => (),
|
command,
|
||||||
|
callback_id,
|
||||||
|
} => todo!(),
|
||||||
|
Msg::Quit => {
|
||||||
|
data.state.loop_signal.stop();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Event::Closed => todo!(),
|
Event::Closed => todo!(),
|
||||||
|
|
Loading…
Reference in a new issue