mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-26 21:58:10 +01:00
Add more stuff to API
This commit is contained in:
parent
f6784da8a8
commit
b1ee8e03c1
7 changed files with 269 additions and 172 deletions
|
@ -51,17 +51,11 @@ require("pinnacle").setup(function(pinnacle)
|
|||
process.spawn("nautilus")
|
||||
end)
|
||||
|
||||
input.keybind({ mod_key }, keys.g, function()
|
||||
local op = output.get_by_res(2560, 1440)
|
||||
for _, v in pairs(op) do
|
||||
print(v.name)
|
||||
end
|
||||
end)
|
||||
|
||||
-- Tags ---------------------------------------------------------------------------
|
||||
|
||||
output.connect_for_all(function(op)
|
||||
tag.add(op, "1", "2", "3", "4", "5")
|
||||
op:add_tags("1", "2", "3", "4", "5")
|
||||
-- Same as tag.add(op, "1", "2", "3", "4", "5")
|
||||
tag.toggle("1", op)
|
||||
end)
|
||||
|
||||
|
@ -85,6 +79,14 @@ require("pinnacle").setup(function(pinnacle)
|
|||
index = index + 1
|
||||
end
|
||||
end)
|
||||
input.keybind({ mod_key, "Shift" }, keys.space, function()
|
||||
tag.set_layout("1", layouts[index])
|
||||
if index - 1 < 1 then
|
||||
index = #layouts
|
||||
else
|
||||
index = index - 1
|
||||
end
|
||||
end)
|
||||
|
||||
input.keybind({ mod_key }, keys.KEY_1, function()
|
||||
tag.switch_to("1")
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
---@field GetOutputByName { name: string }
|
||||
---@field GetOutputsByModel { model: string }
|
||||
---@field GetOutputsByRes { res: integer[] }
|
||||
---@field GetTagsByOutput { output: string }
|
||||
|
||||
---@alias Request _Request | "GetWindowByFocus" | "GetAllWindows" | "GetOutputByFocus"
|
||||
|
||||
|
@ -54,6 +55,7 @@
|
|||
---@field Window { window: WindowProperties }
|
||||
---@field GetAllWindows { windows: WindowProperties[] }
|
||||
---@field Outputs { names: string[] }
|
||||
---@field Tags { tags: TagProperties[] }
|
||||
|
||||
---@class WindowProperties
|
||||
---@field id integer
|
||||
|
@ -62,3 +64,6 @@
|
|||
---@field size integer[] A two element int array, \[1\] = w, \[2\] = h
|
||||
---@field location integer[] A two element int array, \[1\] = x, \[2\] = y
|
||||
---@field floating boolean
|
||||
|
||||
---@class TagProperties
|
||||
---@field id integer
|
||||
|
|
|
@ -8,6 +8,24 @@
|
|||
---@field name string The name of this output (or rather, of its connector).
|
||||
local op = {}
|
||||
|
||||
---Get all tags on this output. See `tag.get_on_output`.
|
||||
---@return Tag[]
|
||||
function op:tags()
|
||||
return require("tag").get_on_output(self)
|
||||
end
|
||||
|
||||
---Add tags to this output. See `tag.add`.
|
||||
---@param ... string The names of the tags you want to add.
|
||||
function op:add_tags(...)
|
||||
require("tag").add(self, ...)
|
||||
end
|
||||
|
||||
---Add tags to this output as a table. See `tag.add_table`.
|
||||
---@param names string[] The names of the tags you want to add, as a table.
|
||||
function op:add_tags_table(names)
|
||||
require("tag").add_table(self, names)
|
||||
end
|
||||
|
||||
---Add methods to this output.
|
||||
---@param props Output
|
||||
---@return Output
|
||||
|
@ -57,7 +75,7 @@ function output.get_by_name(name)
|
|||
end
|
||||
end
|
||||
|
||||
---NOTE: This may or may not be what is reported by other monitor listing utilities. Pinnacle currently fails to pick up one of my monitors' models when it is correctly picked up by tools like wlr-randr. I'll fix this in the future.
|
||||
---Note: This may or may not be what is reported by other monitor listing utilities. Pinnacle currently fails to pick up one of my monitors' models when it is correctly picked up by tools like wlr-randr. I'll fix this in the future.
|
||||
---
|
||||
---Get outputs by their model.
|
||||
---This is something like "DELL E2416H" or whatever gibberish monitor manufacturers call their displays.
|
||||
|
@ -113,6 +131,24 @@ function output.get_by_res(width, height)
|
|||
end
|
||||
|
||||
---Get the currently focused output. This is currently implemented as the one with the cursor on it.
|
||||
---
|
||||
---This function may return nil, which means you may get a warning if you try to use it without checking for nil.
|
||||
---Usually this function will not be nil unless you unplug all monitors, so instead of checking,
|
||||
---you can ignore the warning by either forcing the type to be non-nil with an inline comment:
|
||||
---```lua
|
||||
---local op = output.get_focused() --[[@as Output]]
|
||||
---```
|
||||
---or by disabling nil check warnings for the line:
|
||||
---```lua
|
||||
---local op = output.get_focused()
|
||||
------@diagnostic disable-next-line:need-check-nil
|
||||
---local tags_on_output = op:tags()
|
||||
---```
|
||||
---Type checking done by Lua LS isn't perfect.
|
||||
---Note that directly using the result of this function inline will *not* raise a warning, so be careful.
|
||||
---```lua
|
||||
---local tags = output.get_focused():tags() -- will NOT warn for nil
|
||||
---```
|
||||
---@return Output|nil output The output, or nil if none are focused.
|
||||
function output.get_focused()
|
||||
SendMsg({
|
||||
|
|
|
@ -13,6 +13,21 @@
|
|||
---| "CornerBottomLeft" # One main corner window in the bottom left with a column of windows on the right and a row on the top.
|
||||
---| "CornerBottomRight" # One main corner window in the bottom right with a column of windows on the left and a row on the top.
|
||||
|
||||
---@class Tag
|
||||
---@field private id integer The internal id of this tag.
|
||||
local tg = {}
|
||||
|
||||
---@param props Tag
|
||||
---@return Tag
|
||||
local function new_tag(props)
|
||||
-- Copy functions over
|
||||
for k, v in pairs(tg) do
|
||||
props[k] = v
|
||||
end
|
||||
|
||||
return props
|
||||
end
|
||||
|
||||
local tag = {}
|
||||
|
||||
---Add tags.
|
||||
|
@ -53,12 +68,12 @@ end
|
|||
---end
|
||||
---```
|
||||
---@param output Output The output you want these tags to be added to.
|
||||
---@param tags string[] The names of the new tags you want to add, as a table.
|
||||
function tag.add_table(output, tags)
|
||||
---@param names string[] The names of the new tags you want to add, as a table.
|
||||
function tag.add_table(output, names)
|
||||
SendMsg({
|
||||
AddTags = {
|
||||
output_name = output.name,
|
||||
tags = tags,
|
||||
tags = names,
|
||||
},
|
||||
})
|
||||
end
|
||||
|
@ -156,4 +171,38 @@ function tag.set_layout(name, layout, output)
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
---Get all tags on the specified output.
|
||||
---
|
||||
---You can also use `output_obj:tags()`, which delegates to this function:
|
||||
---```lua
|
||||
---local tags_on_output = output.get_focused():tags()
|
||||
----- This is the same as
|
||||
----- local tags_on_output = tag.get_on_output(output.get_focused())
|
||||
---```
|
||||
---@param output Output
|
||||
---@return Tag[]
|
||||
function tag.get_on_output(output)
|
||||
SendMsg({
|
||||
Request = {
|
||||
GetTagsByOutput = {
|
||||
output = output.name,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
local response = ReadMsg()
|
||||
|
||||
local tag_props = response.RequestResponse.response.Tags.tags
|
||||
|
||||
---@type Tag[]
|
||||
local tags = {}
|
||||
|
||||
for _, prop in pairs(tag_props) do
|
||||
table.insert(tags, new_tag({ id = prop.id }))
|
||||
end
|
||||
|
||||
return tags
|
||||
end
|
||||
|
||||
return tag
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
use crate::{
|
||||
layout::Layout,
|
||||
tag::TagProperties,
|
||||
window::{window_state::WindowId, WindowProperties},
|
||||
};
|
||||
|
||||
|
@ -109,6 +110,7 @@ pub enum Request {
|
|||
GetOutputsByModel { model: String },
|
||||
GetOutputsByRes { res: (u32, u32) },
|
||||
GetOutputByFocus,
|
||||
GetTagsByOutput { output: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Copy, Clone, serde::Serialize, serde::Deserialize)]
|
||||
|
@ -189,4 +191,5 @@ pub enum RequestResponse {
|
|||
Window { window: WindowProperties },
|
||||
GetAllWindows { windows: Vec<WindowProperties> },
|
||||
Outputs { names: Vec<String> },
|
||||
Tags { tags: Vec<TagProperties> },
|
||||
}
|
||||
|
|
81
src/state.rs
81
src/state.rs
|
@ -21,7 +21,7 @@ use crate::{
|
|||
},
|
||||
focus::FocusState,
|
||||
grab::resize_grab::ResizeSurfaceState,
|
||||
tag::Tag,
|
||||
tag::{Tag, TagProperties},
|
||||
window::{window_state::WindowResizeState, WindowProperties},
|
||||
};
|
||||
use calloop::futures::Scheduler;
|
||||
|
@ -310,7 +310,14 @@ impl<B: Backend> State<B> {
|
|||
self.loop_signal.stop();
|
||||
}
|
||||
|
||||
Msg::Request(request) => match request {
|
||||
Msg::Request(request) => {
|
||||
let stream = self
|
||||
.api_state
|
||||
.stream
|
||||
.as_ref()
|
||||
.expect("Stream doesn't exist");
|
||||
let mut stream = stream.lock().expect("Couldn't lock stream");
|
||||
match request {
|
||||
Request::GetWindowByAppId { app_id } => todo!(),
|
||||
Request::GetWindowByTitle { title } => todo!(),
|
||||
Request::GetWindowByFocus => {
|
||||
|
@ -337,12 +344,6 @@ impl<B: Backend> State<B> {
|
|||
location: location.into(),
|
||||
floating,
|
||||
};
|
||||
let stream = self
|
||||
.api_state
|
||||
.stream
|
||||
.as_ref()
|
||||
.expect("Stream doesn't exist");
|
||||
let mut stream = stream.lock().expect("Couldn't lock stream");
|
||||
crate::api::send_to_client(
|
||||
&mut stream,
|
||||
&OutgoingMsg::RequestResponse {
|
||||
|
@ -385,12 +386,6 @@ impl<B: Backend> State<B> {
|
|||
.collect::<Vec<_>>();
|
||||
|
||||
// FIXME: figure out what to do if error
|
||||
let stream = self
|
||||
.api_state
|
||||
.stream
|
||||
.as_ref()
|
||||
.expect("Stream doesn't exist");
|
||||
let mut stream = stream.lock().expect("Couldn't lock stream");
|
||||
crate::api::send_to_client(
|
||||
&mut stream,
|
||||
&OutgoingMsg::RequestResponse {
|
||||
|
@ -402,22 +397,22 @@ impl<B: Backend> State<B> {
|
|||
.expect("Couldn't send to client");
|
||||
}
|
||||
Request::GetOutputByName { name } => {
|
||||
// TODO: name better
|
||||
let names = self
|
||||
.space
|
||||
.outputs()
|
||||
.filter(|output| output.name() == name)
|
||||
.map(|output| output.name())
|
||||
.collect::<Vec<_>>();
|
||||
let stream = self
|
||||
.api_state
|
||||
.stream
|
||||
.as_ref()
|
||||
.expect("Stream doesn't exist");
|
||||
let mut stream = stream.lock().expect("Couldn't lock stream");
|
||||
.find(|output| output.name() == name)
|
||||
.map(|output| output.name());
|
||||
crate::api::send_to_client(
|
||||
&mut stream,
|
||||
&OutgoingMsg::RequestResponse {
|
||||
response: RequestResponse::Outputs { names },
|
||||
response: RequestResponse::Outputs {
|
||||
names: if let Some(name) = names {
|
||||
vec![name]
|
||||
} else {
|
||||
vec![]
|
||||
}
|
||||
},
|
||||
},
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -429,12 +424,6 @@ impl<B: Backend> State<B> {
|
|||
.filter(|output| output.physical_properties().model == model)
|
||||
.map(|output| output.name())
|
||||
.collect::<Vec<_>>();
|
||||
let stream = self
|
||||
.api_state
|
||||
.stream
|
||||
.as_ref()
|
||||
.expect("Stream doesn't exist");
|
||||
let mut stream = stream.lock().expect("Couldn't lock stream");
|
||||
crate::api::send_to_client(
|
||||
&mut stream,
|
||||
&OutgoingMsg::RequestResponse {
|
||||
|
@ -459,12 +448,6 @@ impl<B: Backend> State<B> {
|
|||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
let stream = self
|
||||
.api_state
|
||||
.stream
|
||||
.as_ref()
|
||||
.expect("Stream doesn't exist");
|
||||
let mut stream = stream.lock().expect("Couldn't lock stream");
|
||||
crate::api::send_to_client(
|
||||
&mut stream,
|
||||
&OutgoingMsg::RequestResponse {
|
||||
|
@ -481,12 +464,6 @@ impl<B: Backend> State<B> {
|
|||
.map(|output| output.name())
|
||||
.into_iter()
|
||||
.collect::<Vec<_>>();
|
||||
let stream = self
|
||||
.api_state
|
||||
.stream
|
||||
.as_ref()
|
||||
.expect("Stream doesn't exist");
|
||||
let mut stream = stream.lock().expect("Couldn't lock stream");
|
||||
crate::api::send_to_client(
|
||||
&mut stream,
|
||||
&OutgoingMsg::RequestResponse {
|
||||
|
@ -495,6 +472,26 @@ impl<B: Backend> State<B> {
|
|||
)
|
||||
.unwrap();
|
||||
}
|
||||
Request::GetTagsByOutput { output } => {
|
||||
let output = self
|
||||
.space
|
||||
.outputs()
|
||||
.find(|op| op.name() == output);
|
||||
if let Some(output) = output {
|
||||
let tag_props = output.with_state(|state| {
|
||||
state.tags
|
||||
.iter()
|
||||
.map(|tag| TagProperties { id: tag.id() })
|
||||
.collect::<Vec<_>>()
|
||||
});
|
||||
crate::api::send_to_client(
|
||||
&mut stream,
|
||||
&OutgoingMsg::RequestResponse {
|
||||
response: RequestResponse::Tags { tags: tag_props }
|
||||
}).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,6 +90,11 @@ impl Tag {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct TagProperties {
|
||||
pub id: TagId,
|
||||
}
|
||||
|
||||
impl<B: Backend> State<B> {
|
||||
pub fn output_for_tag(&self, tag: &Tag) -> Option<Output> {
|
||||
self.space
|
||||
|
|
Loading…
Reference in a new issue