diff --git a/api/lua/example_config.lua b/api/lua/example_config.lua index cf858cf..33728d8 100644 --- a/api/lua/example_config.lua +++ b/api/lua/example_config.lua @@ -69,22 +69,46 @@ require("pinnacle").setup(function(pinnacle) "CornerBottomLeft", "CornerBottomRight", } - local index = 1 + local indices = {} + -- Layout cycling + -- Yes, this is very complicated and yes, I'll cook up a way to make it less complicated. input.keybind({ mod_key }, keys.space, function() - tag.set_layout("1", layouts[index]) - if index + 1 > #layouts then - index = 1 - else - index = index + 1 + local tags = output.get_focused():tags() + for _, tg in pairs(tags) do + if tg:active() then + local name = tg:name() + tg:set_layout(layouts[indices[name] or 1]) + if indices[name] == nil then + indices[name] = 2 + else + if indices[name] + 1 > #layouts then + indices[name] = 1 + else + indices[name] = indices[name] + 1 + end + end + break + end 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 + local tags = output.get_focused():tags() + for _, tg in pairs(tags) do + if tg:active() then + local name = tg:name() + tg:set_layout(layouts[indices[name] or #layouts]) + if indices[name] == nil then + indices[name] = #layouts - 1 + else + if indices[name] - 1 < 1 then + indices[name] = #layouts + else + indices[name] = indices[name] - 1 + end + end + break + end end end) diff --git a/api/lua/msg.lua b/api/lua/msg.lua index 1eb04fe..f541b4d 100644 --- a/api/lua/msg.lua +++ b/api/lua/msg.lua @@ -40,6 +40,8 @@ ---@field GetOutputsByModel { model: string } ---@field GetOutputsByRes { res: integer[] } ---@field GetTagsByOutput { output: string } +---@field GetTagActive { tag_id: integer } +---@field GetTagName { tag_id: integer } ---@alias Request _Request | "GetWindowByFocus" | "GetAllWindows" | "GetOutputByFocus" @@ -56,6 +58,8 @@ ---@field GetAllWindows { windows: WindowProperties[] } ---@field Outputs { names: string[] } ---@field Tags { tags: TagProperties[] } +---@field TagActive { active: boolean } +---@field TagName { name: string } ---@class WindowProperties ---@field id integer diff --git a/api/lua/output.lua b/api/lua/output.lua index b5dac89..496465c 100644 --- a/api/lua/output.lua +++ b/api/lua/output.lua @@ -56,11 +56,9 @@ local output = {} ---@param name string The name of the output. ---@return Output|nil function output.get_by_name(name) - SendMsg({ - Request = { - GetOutputByName = { - name = name, - }, + SendRequest({ + GetOutputByName = { + name = name, }, }) @@ -82,11 +80,9 @@ end ---@param model string The model of the output(s). ---@return Output[] outputs All outputs with this model. If there are none, the returned table will be empty. function output.get_by_model(model) - SendMsg({ - Request = { - GetOutputsByModel = { - model = model, - }, + SendRequest({ + GetOutputsByModel = { + model = model, }, }) @@ -109,11 +105,9 @@ end ---@param height integer The height of the outputs, in pixels. ---@return Output[] outputs All outputs with this resolution. If there are none, the returned table will be empty. function output.get_by_res(width, height) - SendMsg({ - Request = { - GetOutputsByRes = { - res = { width, height }, - }, + SendRequest({ + GetOutputsByRes = { + res = { width, height }, }, }) diff --git a/api/lua/pinnacle.lua b/api/lua/pinnacle.lua index 7cc0965..55aaf91 100644 --- a/api/lua/pinnacle.lua +++ b/api/lua/pinnacle.lua @@ -19,6 +19,7 @@ local function read_exact(socket_fd, count) local len_to_read = count local data = "" while len_to_read > 0 do + -- print("need to read " .. tostring(len_to_read) .. " bytes") local bytes, err_msg, errnum = socket.recv(socket_fd, len_to_read) if bytes == nil then @@ -105,9 +106,11 @@ function pinnacle.setup(config_func) ---@type integer local msg_len = string.unpack("=I4", msg_len_bytes) + -- print(msg_len) local msg_bytes, err_msg2, err_num2 = read_exact(socket_fd, msg_len) assert(msg_bytes) + -- print(msg_bytes) ---@type IncomingMsg local tb = msgpack.decode(msg_bytes) diff --git a/api/lua/tag.lua b/api/lua/tag.lua index 3880506..31b337a 100644 --- a/api/lua/tag.lua +++ b/api/lua/tag.lua @@ -4,6 +4,8 @@ -- -- SPDX-License-Identifier: MPL-2.0 +local tag = {} + ---@alias Layout ---| "MasterStack" # One master window on the left with all other windows stacked to the right. ---| "Dwindle" # Windows split in half towards the bottom right corner. @@ -28,7 +30,39 @@ local function new_tag(props) return props end -local tag = {} +---Get this tag's active status. +---@return boolean active True if the tag is active, otherwise false. +function tg:active() + SendRequest({ + GetTagActive = { + tag_id = self.id, + }, + }) + + local response = ReadMsg() + local active = response.RequestResponse.response.TagActive.active + return active +end + +function tg:name() + SendRequest({ + GetTagName = { + tag_id = self.id, + }, + }) + + local response = ReadMsg() + local name = response.RequestResponse.response.TagName.name + return name +end + +---Set this tag's layout. +---@param layout Layout +function tg:set_layout(layout) -- TODO: output param + tag.set_layout(self:name(), layout) +end + +----------------------------------------------------------- ---Add tags. --- @@ -183,11 +217,9 @@ end ---@param output Output ---@return Tag[] function tag.get_on_output(output) - SendMsg({ - Request = { - GetTagsByOutput = { - output = output.name, - }, + SendRequest({ + GetTagsByOutput = { + output = output.name, }, }) diff --git a/src/api.rs b/src/api.rs index effabef..e28b8ff 100644 --- a/src/api.rs +++ b/src/api.rs @@ -112,6 +112,7 @@ pub fn send_to_client( stream: &mut UnixStream, msg: &OutgoingMsg, ) -> Result<(), rmp_serde::encode::Error> { + // tracing::debug!("Sending {msg:?}"); let msg = rmp_serde::to_vec_named(msg)?; let msg_len = msg.len() as u32; let bytes = msg_len.to_ne_bytes(); diff --git a/src/api/msg.rs b/src/api/msg.rs index 482575d..4553742 100644 --- a/src/api/msg.rs +++ b/src/api/msg.rs @@ -9,7 +9,7 @@ use crate::{ layout::Layout, - tag::TagProperties, + tag::{TagId, TagProperties}, window::{window_state::WindowId, WindowProperties}, }; @@ -111,6 +111,8 @@ pub enum Request { GetOutputsByRes { res: (u32, u32) }, GetOutputByFocus, GetTagsByOutput { output: String }, + GetTagActive { tag_id: TagId }, + GetTagName { tag_id: TagId }, } #[derive(Debug, PartialEq, Eq, Copy, Clone, serde::Serialize, serde::Deserialize)] @@ -192,4 +194,6 @@ pub enum RequestResponse { GetAllWindows { windows: Vec }, Outputs { names: Vec }, Tags { tags: Vec }, + TagActive { active: bool }, + TagName { name: String }, } diff --git a/src/layout.rs b/src/layout.rs index 78c83a1..baeb6f4 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -167,8 +167,10 @@ impl Layout { Slice::Right => { let width_partition = win1_size.w / 2; win1.toplevel().with_pending_state(|state| { - state.size = - Some((win1_size.w - width_partition, win1_size.h).into()); + state.size = Some( + (win1_size.w - width_partition, i32::max(win1_size.h, 40)) + .into(), + ); }); win1.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -177,7 +179,8 @@ impl Layout { ); }); win2.toplevel().with_pending_state(|state| { - state.size = Some((width_partition, win1_size.h).into()); + state.size = + Some((width_partition, i32::max(win1_size.h, 40)).into()); }); win2.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -190,8 +193,10 @@ impl Layout { Slice::Below => { let height_partition = win1_size.h / 2; win1.toplevel().with_pending_state(|state| { - state.size = - Some((win1_size.w, win1_size.h - height_partition).into()); + state.size = Some( + (win1_size.w, i32::max(win1_size.h - height_partition, 40)) + .into(), + ); }); win1.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -200,7 +205,8 @@ impl Layout { ); }); win2.toplevel().with_pending_state(|state| { - state.size = Some((win1_size.w, height_partition).into()); + state.size = + Some((win1_size.w, i32::max(height_partition, 40)).into()); }); win2.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -273,8 +279,10 @@ impl Layout { Slice::Above => { let height_partition = win1_size.h / 2; win1.toplevel().with_pending_state(|state| { - state.size = - Some((win1_size.w, win1_size.h - height_partition).into()); + state.size = Some( + (win1_size.w, i32::max(win1_size.h - height_partition, 40)) + .into(), + ); }); win1.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -283,7 +291,8 @@ impl Layout { ); }); win2.toplevel().with_pending_state(|state| { - state.size = Some((win1_size.w, height_partition).into()); + state.size = + Some((win1_size.w, i32::max(height_partition, 40)).into()); }); win2.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -295,8 +304,10 @@ impl Layout { Slice::Below => { let height_partition = win1_size.h / 2; win1.toplevel().with_pending_state(|state| { - state.size = - Some((win1_size.w, win1_size.h - height_partition).into()); + state.size = Some( + (win1_size.w, win1_size.h - i32::max(height_partition, 40)) + .into(), + ); }); win1.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -305,7 +316,8 @@ impl Layout { ); }); win2.toplevel().with_pending_state(|state| { - state.size = Some((win1_size.w, height_partition).into()); + state.size = + Some((win1_size.w, i32::max(height_partition, 40)).into()); }); win2.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -318,8 +330,10 @@ impl Layout { Slice::Left => { let width_partition = win1_size.w / 2; win1.toplevel().with_pending_state(|state| { - state.size = - Some((win1_size.w - width_partition, win1_size.h).into()); + state.size = Some( + (win1_size.w - width_partition, i32::max(win1_size.h, 40)) + .into(), + ); }); win1.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -328,7 +342,8 @@ impl Layout { ); }); win2.toplevel().with_pending_state(|state| { - state.size = Some((width_partition, win1_size.h).into()); + state.size = + Some((width_partition, i32::max(win1_size.h, 40)).into()); }); win2.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -340,8 +355,10 @@ impl Layout { Slice::Right => { let width_partition = win1_size.w / 2; win1.toplevel().with_pending_state(|state| { - state.size = - Some((win1_size.w - width_partition, win1_size.h).into()); + state.size = Some( + (win1_size.w - width_partition, i32::max(win1_size.h, 40)) + .into(), + ); }); win1.with_state(|state| { state.resize_state = WindowResizeState::Requested( @@ -350,7 +367,8 @@ impl Layout { ); }); win2.toplevel().with_pending_state(|state| { - state.size = Some((width_partition, win1_size.h).into()); + state.size = + Some((width_partition, i32::max(win1_size.h, 40)).into()); }); win2.with_state(|state| { state.resize_state = WindowResizeState::Requested( diff --git a/src/state.rs b/src/state.rs index 056d3c0..9fb4a60 100644 --- a/src/state.rs +++ b/src/state.rs @@ -105,6 +105,7 @@ pub struct State { impl State { pub fn handle_msg(&mut self, msg: Msg) { + // tracing::debug!("Got {msg:?}"); match msg { Msg::SetKeybind { key, @@ -491,6 +492,44 @@ impl State { }).unwrap(); } } + Request::GetTagActive { tag_id } => { + let tag = self + .space + .outputs() + .flat_map(|op| { + op.with_state(|state| state.tags.clone()) + }) + .find(|tag| tag.id() == tag_id); + if let Some(tag) = tag { + crate::api::send_to_client( + &mut stream, + &OutgoingMsg::RequestResponse { + response: RequestResponse::TagActive { + active: tag.active() + } + }) + .unwrap(); + } + } + Request::GetTagName { tag_id } => { + let tag = self + .space + .outputs() + .flat_map(|op| { + op.with_state(|state| state.tags.clone()) + }) + .find(|tag| tag.id() == tag_id); + if let Some(tag) = tag { + crate::api::send_to_client( + &mut stream, + &OutgoingMsg::RequestResponse { + response: RequestResponse::TagName { + name: tag.name() + } + }) + .unwrap(); + } + } } }, }