pinnacle/api/lua/tag.lua

480 lines
13 KiB
Lua
Raw Normal View History

2023-08-01 18:06:35 +02:00
-- SPDX-License-Identifier: GPL-3.0-or-later
2023-07-01 04:34:07 +02:00
2023-07-22 04:02:02 +02:00
---@class TagModule
local tag_module = {}
2023-07-18 19:37:40 +02:00
2023-07-13 01:50:41 +02:00
---@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.
---| "Spiral" # Windows split in half in a spiral.
2023-07-18 03:40:56 +02:00
---| "CornerTopLeft" # One main corner window in the top left with a column of windows on the right and a row on the bottom.
---| "CornerTopRight" # One main corner window in the top right with a column of windows on the left and a row on the bottom.
---| "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.
2023-07-13 01:50:41 +02:00
---@alias TagTable { [1]: string, [2]: (string|Output)? }
---@alias TagTableNamed { name: string, output: (string|Output)? }
2023-07-18 17:31:08 +02:00
---@class Tag
2023-07-20 22:22:22 +02:00
---@field private _id integer The internal id of this tag.
local tag = {}
2023-07-18 17:31:08 +02:00
---Create a tag from `Tag|TagTable|TagTableNamed|string`.
---@param tb Tag|TagTable|TagTableNamed|string
---@return Tag|nil
local function create_tag_from_params(tb)
-- If creating from a tag object, just return the obj
if tb.id then
return tb --[[@as Tag]]
end
-- string passed in
if type(tb) == "string" then
local op = require("output").get_focused()
if op == nil then
return nil
end
local tags = tag_module.get_by_name(tb)
for _, t in pairs(tags) do
if t:output() and t:output():name() == op:name() then
return t
end
end
return nil
end
-- TagTable was passed in
local tag_name = tb[1]
if type(tag_name) == "string" then
local op = tb[2]
if op == nil then
local o = require("output").get_focused()
if o == nil then
return nil
end
op = o
elseif type(op) == "string" then
local o = require("output").get_by_name(op)
if o == nil then
return nil
end
op = o
end
local tags = tag_module.get_by_name(tag_name)
for _, t in pairs(tags) do
if t:output() and t:output():name() == op:name() then
return t
end
end
return nil
end
-- TagTableNamed was passed in
local tb = tb --[[@as TagTableNamed]]
local tag_name = tb.name
local op = tb.output
if op == nil then
local o = require("output").get_focused()
if o == nil then
return nil
end
op = o
elseif type(op) == "string" then
local o = require("output").get_by_name(op)
if o == nil then
return nil
end
op = o
end
local tags = tag_module.get_by_name(tag_name)
for _, t in pairs(tags) do
if t:output() and t:output():name() == op:name() then
return t
end
end
return nil
end
2023-07-22 04:02:02 +02:00
---Create a tag from an id.
---The id is the unique identifier for each tag.
---@param id TagId
2023-07-18 17:31:08 +02:00
---@return Tag
2023-07-22 04:02:02 +02:00
local function create_tag(id)
2023-07-20 22:22:22 +02:00
---@type Tag
2023-07-22 04:02:02 +02:00
local t = { _id = id }
2023-07-18 17:31:08 +02:00
-- Copy functions over
for k, v in pairs(tag) do
2023-07-20 22:22:22 +02:00
t[k] = v
2023-07-18 17:31:08 +02:00
end
2023-07-20 22:22:22 +02:00
return t
end
---Get this tag's internal id.
2023-07-22 04:02:02 +02:00
---***You probably won't need to use this.***
2023-07-20 22:22:22 +02:00
---@return integer
function tag:id()
2023-07-20 22:22:22 +02:00
return self._id
2023-07-18 17:31:08 +02:00
end
2023-07-18 19:37:40 +02:00
---Get this tag's active status.
2023-07-20 01:55:22 +02:00
---@return boolean|nil active `true` if the tag is active, `false` if not, and `nil` if the tag doesn't exist.
2023-07-22 04:44:56 +02:00
---@see TagModule.active — The corresponding module function
function tag:active()
2023-07-22 04:02:02 +02:00
return tag_module.active(self)
2023-07-18 19:37:40 +02:00
end
2023-07-20 01:55:22 +02:00
---Get this tag's name.
---@return string|nil name The name of this tag, or nil if it doesn't exist.
2023-07-22 04:44:56 +02:00
---@see TagModule.name — The corresponding module function
function tag:name()
2023-07-22 04:02:02 +02:00
return tag_module.name(self)
2023-07-18 19:37:40 +02:00
end
2023-07-20 01:55:22 +02:00
---Get this tag's output.
---@return Output|nil output The output this tag is on, or nil if the tag doesn't exist.
2023-07-22 04:44:56 +02:00
---@see TagModule.output — The corresponding module function
function tag:output()
2023-07-22 04:02:02 +02:00
return tag_module.output(self)
2023-07-20 01:55:22 +02:00
end
---Switch to this tag.
2023-07-22 04:44:56 +02:00
---@see TagModule.switch_to — The corresponding module function
function tag:switch_to()
2023-07-22 04:02:02 +02:00
tag_module.switch_to(self)
end
---Toggle this tag.
2023-07-22 04:44:56 +02:00
---@see TagModule.toggle — The corresponding module function
function tag:toggle()
2023-07-22 04:02:02 +02:00
tag_module.toggle(self)
end
2023-07-18 19:37:40 +02:00
---Set this tag's layout.
---@param layout Layout
2023-07-22 04:44:56 +02:00
---@see TagModule.set_layout — The corresponding module function
function tag:set_layout(layout)
2023-07-22 04:02:02 +02:00
tag_module.set_layout(self, layout)
2023-07-18 19:37:40 +02:00
end
-----------------------------------------------------------
2023-07-01 04:34:07 +02:00
2023-07-20 23:54:26 +02:00
---Add tags to the specified output.
2023-07-01 04:34:07 +02:00
---
2023-07-20 23:54:26 +02:00
---### Examples
2023-07-01 04:34:07 +02:00
---```lua
2023-07-20 01:55:22 +02:00
---local op = output.get_by_name("DP-1")
---if op ~= nil then
--- tag.add(op, "1", "2", "3", "4", "5") -- Add tags with names 1-5
2023-07-11 18:59:38 +02:00
---end
2023-07-01 04:34:07 +02:00
---```
2023-07-20 23:54:26 +02:00
---You can also pass in a table.
2023-07-11 18:59:38 +02:00
---```lua
2023-07-20 23:54:26 +02:00
---local tags = {"Terminal", "Browser", "Code", "Potato", "Email"}
---tag.add(op, tags) -- Add tags with those names
2023-07-11 18:59:38 +02:00
---```
---@param output Output The output you want these tags to be added to.
2023-07-20 23:54:26 +02:00
---@param ... string The names of the new tags you want to add.
---@overload fun(output: Output, tag_names: string[])
2023-07-22 04:02:02 +02:00
---@see Output.add_tags — The corresponding object method
function tag_module.add(output, ...)
2023-07-20 23:54:26 +02:00
local varargs = { ... }
if type(varargs[1]) == "string" then
local tag_names = varargs
tag_names["n"] = nil -- remove the length to make it a true array for serializing
SendMsg({
AddTags = {
output_name = output:name(),
tag_names = tag_names,
},
})
else
local tag_names = varargs[1] --[=[@as string[]]=]
SendMsg({
AddTags = {
output_name = output:name(),
tag_names = tag_names,
},
})
end
2023-07-01 04:34:07 +02:00
end
---Toggle a tag on the specified output. If the output isn't specified, toggle it on the currently focused output instead.
2023-07-11 18:59:38 +02:00
---
2023-07-18 22:12:23 +02:00
---### Example
2023-07-11 18:59:38 +02:00
---
---```lua
---local op = output.get_by_name("DP-1")
---
---tag.toggle("1") -- Toggle tag 1 on the focused output
---tag.toggle({ "1" }) -- Same as above
---
---tag.toggle({ "1", "DP-1" }) -- Toggle tag 1 on DP-1
---tag.toggle({ "1", op }) -- Same as above
---
----- Verbose versions of the two above
---tag.toggle({ name = "1", output = "DP-1" })
---tag.toggle({ name = "1", output = op })
---
----- Using a tag object
---local t = tag.get_by_name("1")[1] -- `t` is the first tag with the name "1"
---tag.toggle(t)
2023-07-11 18:59:38 +02:00
---```
---@param t Tag|TagTable|TagTableNamed|string
2023-07-22 04:02:02 +02:00
---@see Tag.toggle — The corresponding object method
function tag_module.toggle(t)
local t = create_tag_from_params(t)
if t then
SendMsg({
ToggleTag = {
tag_id = t:id(),
},
})
end
2023-07-01 04:34:07 +02:00
end
---Switch to a tag on the specified output, deactivating any other active tags on it.
---If the output is not specified, this uses the currently focused output instead.
2023-07-11 18:59:38 +02:00
---
---This is used to replicate what a traditional workspace is on some other Wayland compositors.
---
2023-07-22 04:02:02 +02:00
---### Examples
2023-07-11 18:59:38 +02:00
---```lua
---local op = output.get_by_name("DP-1")
---
---tag.switch_to("1") -- Switch to tag 1 on the focused output
---tag.switch_to({ "1" }) -- Same as above
---
---tag.switch_to({ "1", "DP-1" }) -- Switch to tag 1 on DP-1
---tag.switch_to({ "1", op }) -- Same as above
---
----- Verbose versions of the two above
---tag.switch_to({ name = "1", output = "DP-1" })
---tag.switch_to({ name = "1", output = op })
---
----- Using a tag object
---local t = tag.get_by_name("1")[1] -- `t` is the first tag with the name "1"
---tag.switch_to(t)
2023-07-11 18:59:38 +02:00
---```
---@param t Tag|TagTable|TagTableNamed|string
2023-07-22 04:02:02 +02:00
---@see Tag.switch_to — The corresponding object method
function tag_module.switch_to(t)
local t = create_tag_from_params(t)
if t then
SendMsg({
SwitchToTag = {
tag_id = t:id(),
},
})
end
2023-07-02 02:06:37 +02:00
end
---Set a layout for the tag on the specified output. If no output is provided, set it for the tag on the currently focused one.
2023-07-22 04:02:02 +02:00
---
---### Examples
---```lua
---local op = output.get_by_name("DP-1")
2023-07-22 04:02:02 +02:00
---
---tag.set_layout("1", "Dwindle") -- Set tag 1 on the focused output to "Dwindle"
---tag.set_layout({ "1" }, "Dwindle") -- Same as above
---
---tag.set_layout({ "1", "DP-1" }, "Dwindle") -- Set tag 1 on DP-1 to "Dwindle"
---tag.set_layout({ "1", op }, "Dwindle") -- Same as above
---
----- Verbose versions of the two above
---tag.set_layout({ name = "1", output = "DP-1" }, "Dwindle")
---tag.set_layout({ name = "1", output = op }, "Dwindle")
---
----- Using a tag object
---local t = tag.get_by_name("1")[1] -- `t` is the first tag with the name "1"
2023-07-22 04:02:02 +02:00
---tag.set_layout(t, "Dwindle")
---```
---
---@param t Tag|TagTable|TagTableNamed|string
---@param layout Layout The layout.
2023-07-22 04:02:02 +02:00
---@see Tag.set_layout — The corresponding object method
function tag_module.set_layout(t, layout)
local t = create_tag_from_params(t)
if t then
SendMsg({
SetLayout = {
tag_id = t:id(),
layout = layout,
},
})
end
end
---Get a tag with the specified name and optional output.
---
---If the output isn't specified, the focused one is used.
---
---If you have duplicate tags on an output, this returns the first one.
---If you need access to all duplicates, use `tag.get_on_output`, `tag.get_by_name`, or `tag.get_all`
---and filter for what you need.
---
---### Examples
---```lua
---local t = tag.get("1")
---local t = tag.get({ "1", "HDMI-A-0" })
---local t = tag.get({ name = "3" })
---
---local op = output.get_by_name("DP-2")
---if op ~= nil then
--- local t = tag.get({ name = "Code", output = op })
---end
---```
---@param params TagTable|TagTableNamed|string
---
---@see TagModule.get_on_output
---@see TagModule.get_by_name
---@see TagModule.get_all
function tag_module.get(params)
return create_tag_from_params(params)
2023-07-13 01:50:41 +02:00
end
2023-07-18 17:31:08 +02:00
---Get all tags on the specified output.
---
2023-07-22 04:02:02 +02:00
---### Example
2023-07-18 17:31:08 +02:00
---```lua
2023-07-22 04:02:02 +02:00
---local op = output.get_focused()
---if op ~= nil then
--- local tags = tag.get_on_output(op) -- All tags on the focused output
---end
2023-07-18 17:31:08 +02:00
---```
---@param output Output
---@return Tag[]
2023-07-22 04:02:02 +02:00
---
---@see Output.tags — The corresponding object method
function tag_module.get_on_output(output)
2023-07-21 22:04:39 +02:00
local response = Request({
2023-07-20 22:22:22 +02:00
GetOutputProps = {
output_name = output:name(),
2023-07-18 17:31:08 +02:00
},
2023-07-21 22:04:39 +02:00
})
2023-07-18 17:31:08 +02:00
2023-07-20 22:22:22 +02:00
local tag_ids = response.RequestResponse.response.OutputProps.tag_ids
2023-07-18 17:31:08 +02:00
---@type Tag[]
local tags = {}
2023-07-20 22:22:22 +02:00
if tag_ids == nil then
return tags
end
2023-07-18 22:12:23 +02:00
for _, tag_id in pairs(tag_ids) do
2023-07-22 04:02:02 +02:00
table.insert(tags, create_tag(tag_id))
2023-07-18 17:31:08 +02:00
end
return tags
end
2023-07-20 01:55:22 +02:00
---Get all tags with this name across all outputs.
2023-07-22 04:02:02 +02:00
---
---### Example
---```lua
----- Given one monitor with the tags "OBS", "OBS", "VSCode", and "Spotify"...
---local tags = tag.get_by_name("OBS")
----- ...will have 2 tags in `tags`, while...
---local no_tags = tag.get_by_name("Firefox")
----- ...will have `no_tags` be empty.
---```
---@param name string The name of the tag(s) you want.
2023-07-20 01:55:22 +02:00
---@return Tag[]
2023-07-22 04:02:02 +02:00
function tag_module.get_by_name(name)
local t_s = tag_module.get_all()
2023-07-20 23:05:26 +02:00
---@type Tag[]
local tags = {}
for _, t in pairs(t_s) do
2023-07-20 23:05:26 +02:00
if t:name() == name then
table.insert(tags, t)
end
end
return tags
end
2023-07-22 04:02:02 +02:00
---Get all tags across all outputs.
---
---### Example
---```lua
----- With two monitors with the same tags: "1", "2", "3", "4", and "5"...
---local tags = tag.get_all()
----- ...`tags` should have 10 tags, with 5 pairs of those names across both outputs.
---```
2023-07-20 23:05:26 +02:00
---@return Tag[]
2023-07-22 04:02:02 +02:00
function tag_module.get_all()
2023-07-21 22:04:39 +02:00
local response = Request("GetTags")
2023-07-20 01:55:22 +02:00
local tag_ids = response.RequestResponse.response.Tags.tag_ids
---@type Tag[]
local tags = {}
for _, tag_id in pairs(tag_ids) do
2023-07-22 04:02:02 +02:00
table.insert(tags, create_tag(tag_id))
2023-07-20 01:55:22 +02:00
end
return tags
end
2023-07-22 04:02:02 +02:00
---Get the specified tag's name.
---
---### Example
---```lua
----- Assuming the tag `Terminal` exists...
---print(tag.name(tag.get_by_name("Terminal")[1]))
----- ...should print `Terminal`.
---```
---@param t Tag
---@return string|nil
---@see Tag.name — The corresponding object method
function tag_module.name(t)
local response = Request({
GetTagProps = {
tag_id = t:id(),
},
})
local name = response.RequestResponse.response.TagProps.name
return name
end
---Get whether or not the specified tag is active.
---@param t Tag
---@return boolean|nil
---@see Tag.active — The corresponding object method
function tag_module.active(t)
local response = Request({
GetTagProps = {
tag_id = t:id(),
},
})
local active = response.RequestResponse.response.TagProps.active
return active
end
---Get the output the specified tag is on.
---@param t Tag
---@return Output|nil
2023-07-22 04:44:56 +02:00
---@see OutputModule.get_for_tag — The called function
2023-07-22 04:02:02 +02:00
---@see Tag.output — The corresponding object method
function tag_module.output(t)
return require("output").get_for_tag(t)
end
return tag_module