diff --git a/api/lua/msg.lua b/api/lua/msg.lua index 9f1aac9..579279d 100644 --- a/api/lua/msg.lua +++ b/api/lua/msg.lua @@ -10,20 +10,20 @@ ---@field SetKeybind { key: Keys, modifiers: Modifier[], callback_id: integer } ---@field SetMousebind { button: integer } --Windows ----@field CloseWindow { window_id: integer } ----@field ToggleFloating { window_id: integer } ----@field SetWindowSize { window_id: integer, width: integer?, height: integer? } ----@field MoveWindowToTag { window_id: integer, tag_id: string } ----@field ToggleTagOnWindow { window_id: integer, tag_id: string } +---@field CloseWindow { window_id: WindowId } +---@field ToggleFloating { window_id: WindowId } +---@field SetWindowSize { window_id: WindowId, width: integer?, height: integer? } +---@field MoveWindowToTag { window_id: WindowId, tag_id: TagId } +---@field ToggleTagOnWindow { window_id: WindowId, tag_id: TagId } -- ---@field Spawn { command: string[], callback_id: integer? } ---@field Request Request --Tags ----@field ToggleTag { output_name: string, tag_name: string } ----@field SwitchToTag { output_name: string, tag_name: string } +---@field ToggleTag { tag_id: TagId } +---@field SwitchToTag { tag_id: TagId } ---@field AddTags { output_name: string, tag_names: string[] } ----@field RemoveTags { output_name: string, tag_names: string[] } ----@field SetLayout { output_name: string, tag_name: string, layout: Layout } +---@field RemoveTags { tag_ids: TagId[] } +---@field SetLayout { tag_id: TagId, layout: Layout } --Outputs ---@field ConnectForAllOutputs { callback_id: integer } diff --git a/api/lua/tag.lua b/api/lua/tag.lua index d66b43e..680260a 100644 --- a/api/lua/tag.lua +++ b/api/lua/tag.lua @@ -32,6 +32,16 @@ local function new_tag(tag_id) return t end +---Switch to this tag. +function tg:switch_to() + tag.switch_to(self) +end + +---Toggle this tag. +function tg:toggle() + tag.toggle(self) +end + ---Get this tag's internal id. ---@return integer function tg:id() @@ -75,10 +85,7 @@ end ---Set this tag's layout. ---@param layout Layout function tg:set_layout(layout) - local name = self:name() - if name ~= nil then - tag.set_layout(name, layout) - end + tag.set_layout(self, layout) end ----------------------------------------------------------- @@ -138,27 +145,13 @@ end ---tag.toggle("2", op) ----- will cause windows on both tags 1 and 2 to be displayed at the same time. ---``` ----@param name string The name of the tag. ----@param output Output? The output. -function tag.toggle(name, output) - if output ~= nil then - SendMsg({ - ToggleTag = { - output_name = output:name(), - tag_name = name, - }, - }) - else - local op = require("output").get_focused() - if op ~= nil then - SendMsg({ - ToggleTag = { - output_name = op:name(), - tag_name = name, - }, - }) - end - end +---@param t Tag +function tag.toggle(t) + SendMsg({ + ToggleTag = { + tag_id = t:id(), + }, + }) end ---Switch to a tag on the specified output, deactivating any other active tags on it. @@ -171,54 +164,25 @@ end ---```lua ---tag.switch_to("3") -- Switches to and displays *only* windows on tag 3 ---``` ----@param name string The name of the tag. ----@param output Output? The output. -function tag.switch_to(name, output) - if output ~= nil then - SendMsg({ - SwitchToTag = { - output_name = output:name(), - tag_name = name, - }, - }) - else - local op = require("output").get_focused() - if op ~= nil then - SendMsg({ - SwitchToTag = { - output_name = op:name(), - tag_name = name, - }, - }) - end - end +---@param t Tag +function tag.switch_to(t) + SendMsg({ + SwitchToTag = { + tag_id = t:id(), + }, + }) end ----Set a layout for the tag on the specified output. If there is none, set it for the tag on the currently focused one. ----@param name string The name of the tag. ----@param layout Layout The layout. ----@param output Output? The output. -function tag.set_layout(name, layout, output) - if output ~= nil then - SendMsg({ - SetLayout = { - output_name = output:name(), - tag_name = name, - layout = layout, - }, - }) - else - local op = require("output").get_focused() - if op ~= nil then - SendMsg({ - SetLayout = { - output_name = op:name(), - tag_name = name, - layout = layout, - }, - }) - end - end +---Set a layout for the specified tag. +---@param t Tag +---@param layout Layout +function tag.set_layout(t, layout) + SendMsg({ + SetLayout = { + tag_id = t:id(), + layout = layout, + }, + }) end ---Get all tags on the specified output. diff --git a/api/lua/test_config.lua b/api/lua/test_config.lua index c2756aa..bb359e9 100644 --- a/api/lua/test_config.lua +++ b/api/lua/test_config.lua @@ -138,11 +138,17 @@ require("pinnacle").setup(function(pinnacle) -- Tags --------------------------------------------------------------------------- output.connect_for_all(function(op) - -- op:add_tags("1", "2", "3", "4", "5") + op:add_tags("1", "2", "3", "4", "5") -- Same as tag.add(op, "1", "2", "3", "4", "5") - local tags_table = { "Terminal", "Browser", "Code", "Email", "Potato" } - op:add_tags(tags_table) + -- local tags_table = { "Terminal", "Browser", "Code", "Email", "Potato" } + -- op:add_tags(tags_table) + + for _, t in pairs(tag.get_by_name("1")) do + if t:output() and t:output():focused() then + t:toggle() + end + end end) ---@type Layout[] @@ -205,66 +211,146 @@ require("pinnacle").setup(function(pinnacle) end) input.keybind({ mod_key }, keys.KEY_1, function() - tag.switch_to("1") + for _, t in pairs(tag.get_by_name("1")) do + if t:output() and t:output():focused() then + t:switch_to() + end + end end) input.keybind({ mod_key }, keys.KEY_2, function() - tag.switch_to("2") + for _, t in pairs(tag.get_by_name("2")) do + if t:output() and t:output():focused() then + t:switch_to() + end + end end) input.keybind({ mod_key }, keys.KEY_3, function() - tag.switch_to("3") + for _, t in pairs(tag.get_by_name("3")) do + if t:output() and t:output():focused() then + t:switch_to() + end + end end) input.keybind({ mod_key }, keys.KEY_4, function() - tag.switch_to("4") + for _, t in pairs(tag.get_by_name("4")) do + if t:output() and t:output():focused() then + t:switch_to() + end + end end) input.keybind({ mod_key }, keys.KEY_5, function() - tag.switch_to("5") + for _, t in pairs(tag.get_by_name("5")) do + if t:output() and t:output():focused() then + t:switch_to() + end + end end) input.keybind({ mod_key, "Shift" }, keys.KEY_1, function() - tag.toggle("1") + for _, t in pairs(tag.get_by_name("1")) do + if t:output() and t:output():focused() then + t:toggle() + end + end end) input.keybind({ mod_key, "Shift" }, keys.KEY_2, function() - tag.toggle("2") + for _, t in pairs(tag.get_by_name("2")) do + if t:output() and t:output():focused() then + t:toggle() + end + end end) input.keybind({ mod_key, "Shift" }, keys.KEY_3, function() - tag.toggle("3") + for _, t in pairs(tag.get_by_name("3")) do + if t:output() and t:output():focused() then + t:toggle() + end + end end) input.keybind({ mod_key, "Shift" }, keys.KEY_4, function() - tag.toggle("4") + for _, t in pairs(tag.get_by_name("4")) do + if t:output() and t:output():focused() then + t:toggle() + end + end end) input.keybind({ mod_key, "Shift" }, keys.KEY_5, function() - tag.toggle("5") + for _, t in pairs(tag.get_by_name("5")) do + if t:output() and t:output():focused() then + t:toggle() + end + end end) input.keybind({ mod_key, "Alt" }, keys.KEY_1, function() - window.get_focused():move_to_tag("1") + for _, t in pairs(tag.get_by_name("1")) do + if t:output() and t:output():focused() then + window.get_focused():move_to_tag(t) + end + end end) input.keybind({ mod_key, "Alt" }, keys.KEY_2, function() - window.get_focused():move_to_tag("2") + for _, t in pairs(tag.get_by_name("2")) do + if t:output() and t:output():focused() then + window.get_focused():move_to_tag(t) + end + end end) input.keybind({ mod_key, "Alt" }, keys.KEY_3, function() - window.get_focused():move_to_tag("3") + for _, t in pairs(tag.get_by_name("3")) do + if t:output() and t:output():focused() then + window.get_focused():move_to_tag(t) + end + end end) input.keybind({ mod_key, "Alt" }, keys.KEY_4, function() - window.get_focused():move_to_tag("4") + for _, t in pairs(tag.get_by_name("4")) do + if t:output() and t:output():focused() then + window.get_focused():move_to_tag(t) + end + end end) input.keybind({ mod_key, "Alt" }, keys.KEY_5, function() - window.get_focused():move_to_tag("5") + for _, t in pairs(tag.get_by_name("5")) do + if t:output() and t:output():focused() then + window.get_focused():move_to_tag(t) + end + end end) input.keybind({ mod_key, "Shift", "Alt" }, keys.KEY_1, function() - window.get_focused():toggle_tag("1") + for _, t in pairs(tag.get_by_name("1")) do + if t:output() and t:output():focused() then + window.get_focused():toggle_tag(t) + end + end end) input.keybind({ mod_key, "Shift", "Alt" }, keys.KEY_2, function() - window.get_focused():toggle_tag("2") + for _, t in pairs(tag.get_by_name("2")) do + if t:output() and t:output():focused() then + window.get_focused():toggle_tag(t) + end + end end) input.keybind({ mod_key, "Shift", "Alt" }, keys.KEY_3, function() - window.get_focused():toggle_tag("3") + for _, t in pairs(tag.get_by_name("3")) do + if t:output() and t:output():focused() then + window.get_focused():toggle_tag(t) + end + end end) input.keybind({ mod_key, "Shift", "Alt" }, keys.KEY_4, function() - window.get_focused():toggle_tag("4") + for _, t in pairs(tag.get_by_name("4")) do + if t:output() and t:output():focused() then + window.get_focused():toggle_tag(t) + end + end end) input.keybind({ mod_key, "Shift", "Alt" }, keys.KEY_5, function() - window.get_focused():toggle_tag("5") + for _, t in pairs(tag.get_by_name("5")) do + if t:output() and t:output():focused() then + window.get_focused():toggle_tag(t) + end + end end) end) diff --git a/api/lua/window.lua b/api/lua/window.lua index 092a74f..cb793d9 100644 --- a/api/lua/window.lua +++ b/api/lua/window.lua @@ -46,12 +46,12 @@ end ---window.get_focused():move_to_tag("5") ----- ...will make the window only appear on tag 5. ---``` ----@param name string The name of the tag. -function win:move_to_tag(name) +---@param t Tag +function win:move_to_tag(t) SendMsg({ MoveWindowToTag = { window_id = self.id, - tag_id = name, + tag_id = t:id(), }, }) end @@ -66,12 +66,12 @@ end ---window.get_focused():toggle_tag("2") ----- ...will also make the window appear on tag 2. ---``` ----@param name string The name of the tag. -function win:toggle_tag(name) +---@param t Tag +function win:toggle_tag(t) SendMsg({ ToggleTagOnWindow = { window_id = self.id, - tag_id = name, + tag_id = t:id(), }, }) end diff --git a/src/api/msg.rs b/src/api/msg.rs index b612257..94068f5 100644 --- a/src/api/msg.rs +++ b/src/api/msg.rs @@ -40,21 +40,19 @@ pub enum Msg { }, MoveWindowToTag { window_id: WindowId, - tag_id: String, + tag_id: TagId, }, ToggleTagOnWindow { window_id: WindowId, - tag_id: String, + tag_id: TagId, }, // Tag management ToggleTag { - output_name: String, - tag_name: String, + tag_id: TagId, }, SwitchToTag { - output_name: String, - tag_name: String, + tag_id: TagId, }, AddTags { /// The name of the output you want these tags on. @@ -63,12 +61,10 @@ pub enum Msg { }, RemoveTags { /// The name of the output you want these tags removed from. - output_name: String, - tag_names: Vec, + tag_ids: Vec, }, SetLayout { - output_name: String, - tag_name: String, + tag_id: TagId, layout: Layout, }, diff --git a/src/state.rs b/src/state.rs index 00f5e03..ee87cc4 100644 --- a/src/state.rs +++ b/src/state.rs @@ -159,110 +159,49 @@ impl State { window.toplevel().send_pending_configure(); } Msg::MoveWindowToTag { window_id, tag_id } => { - if let Some(window) = window_id.window(self) { - window.with_state(|state| { - self.focus_state - .focused_output - .as_ref() - .unwrap() - .with_state(|op_state| { - let tag = op_state.tags.iter().find(|tag| tag.name() == tag_id); - if let Some(tag) = tag { - state.tags = vec![tag.clone()]; - } - }); - }); - let output = self.focus_state.focused_output.clone().unwrap(); - self.re_layout(&output); - } + let Some(window) = window_id.window(self) else { return }; + let Some(tag) = tag_id.tag(self) else { return }; + window.with_state(|state| { + state.tags = vec![tag.clone()]; + }); + let Some(output) = tag.output(self) else { return }; + self.re_layout(&output); } Msg::ToggleTagOnWindow { window_id, tag_id } => { - if let Some(window) = window_id.window(self) { - window.with_state(|state| { - self.focus_state - .focused_output - .as_ref() - .unwrap() - .with_state(|op_state| { - let tag = op_state.tags.iter().find(|tag| tag.name() == tag_id); - if let Some(tag) = tag { - if state.tags.contains(tag) { - state.tags.retain(|tg| tg != tag); - } else { - state.tags.push(tag.clone()); - } - } - }); - }); + let Some(window) = window_id.window(self) else { return }; + let Some(tag) = tag_id.tag(self) else { return }; - let output = self.focus_state.focused_output.clone().unwrap(); - self.re_layout(&output); - } + window.with_state(|state| { + if state.tags.contains(&tag) { + state.tags.retain(|tg| tg != &tag); + } else { + state.tags.push(tag.clone()); + } + }); + + let Some(output) = tag.output(self) else { return }; + self.re_layout(&output); } - Msg::ToggleTag { - output_name, - tag_name, - } => { + Msg::ToggleTag { tag_id } => { tracing::debug!("ToggleTag"); - - let output = self - .space - .outputs() - .find(|op| op.name() == output_name) - .cloned(); - if let Some(output) = output { - output.with_state(|state| { - if let Some(tag) = state.tags.iter_mut().find(|tag| tag.name() == tag_name) - { - tracing::debug!("Setting tag {tag:?} to {}", !tag.active()); - tag.set_active(!tag.active()); - } - }); - self.re_layout(&output); + if let Some(tag) = tag_id.tag(self) { + tag.set_active(!tag.active()); + if let Some(output) = tag.output(self) { + self.re_layout(&output); + } } } - Msg::SwitchToTag { - output_name, - tag_name, - } => { - let output = self - .space - .outputs() - .find(|op| op.name() == output_name) - .cloned(); - if let Some(output) = output { - output.with_state(|state| { - if !state.tags.iter().any(|tag| tag.name() == tag_name) { - // TODO: notify error - return; - } - for tag in state.tags.iter_mut() { - tag.set_active(false); - } - - let Some(tag) = state - .tags - .iter_mut() - .find(|tag| tag.name() == tag_name) - else { - unreachable!() - }; - tag.set_active(true); - - tracing::debug!( - "focused tags: {:?}", - state - .tags - .iter() - .filter(|tag| tag.active()) - .map(|tag| tag.name()) - .collect::>() - ); - }); - self.re_layout(&output); - } + Msg::SwitchToTag { tag_id } => { + let Some(tag) = tag_id.tag(self) else { return }; + let Some(output) = tag.output(self) else { return }; + output.with_state(|state| { + for op_tag in state.tags.iter_mut() { + op_tag.set_active(false); + } + tag.set_active(true); + }); + self.re_layout(&output); } - // TODO: add output Msg::AddTags { output_name, tag_names, @@ -278,39 +217,20 @@ impl State { }); } } - Msg::RemoveTags { - output_name, - tag_names, - } => { - if let Some(output) = self - .space - .outputs() - .find(|output| output.name() == output_name) - { + Msg::RemoveTags { tag_ids } => { + let tags = tag_ids.into_iter().filter_map(|tag_id| tag_id.tag(self)); + for tag in tags { + let Some(output) = tag.output(self) else { continue }; output.with_state(|state| { - state.tags.retain(|tag| !tag_names.contains(&tag.name())); + state.tags.retain(|tg| tg != &tag); }); } } - Msg::SetLayout { - output_name, - tag_name, - layout, - } => { - let output = self - .space - .outputs() - .find(|op| op.name() == output_name) - .cloned(); - if let Some(output) = output { - output.with_state(|state| { - if let Some(tag) = state.tags.iter_mut().find(|tag| tag.name() == tag_name) - { - tag.set_layout(layout); - } - }); - self.re_layout(&output); - } + Msg::SetLayout { tag_id, layout } => { + let Some(tag) = tag_id.tag(self) else { return }; + tag.set_layout(layout); + let Some(output) = tag.output(self) else { return }; + self.re_layout(&output); } Msg::ConnectForAllOutputs { callback_id } => {