2023-07-01 04:34:07 +02:00
|
|
|
-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
-- License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
-- file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
|
|
--
|
|
|
|
-- SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2023-07-21 21:36:32 +02:00
|
|
|
---@class TagGlobal
|
|
|
|
local tag_global = {}
|
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
|
|
|
|
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.
|
2023-07-21 21:36:32 +02:00
|
|
|
local tag = {}
|
2023-07-18 17:31:08 +02:00
|
|
|
|
2023-07-20 22:22:22 +02:00
|
|
|
---@param tag_id integer
|
2023-07-18 17:31:08 +02:00
|
|
|
---@return Tag
|
2023-07-20 22:22:22 +02:00
|
|
|
local function new_tag(tag_id)
|
|
|
|
---@type Tag
|
|
|
|
local t = { _id = tag_id }
|
2023-07-18 17:31:08 +02:00
|
|
|
-- Copy functions over
|
2023-07-21 21:36:32 +02:00
|
|
|
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.
|
|
|
|
---@return integer
|
2023-07-21 21:36:32 +02:00
|
|
|
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-21 21:36:32 +02:00
|
|
|
function tag:active()
|
|
|
|
local response = ReadMsg(SendRequest({
|
2023-07-20 23:05:26 +02:00
|
|
|
GetTagProps = {
|
2023-07-20 22:22:22 +02:00
|
|
|
tag_id = self._id,
|
2023-07-18 19:37:40 +02:00
|
|
|
},
|
2023-07-21 21:36:32 +02:00
|
|
|
}))
|
2023-07-20 23:05:26 +02:00
|
|
|
local active = response.RequestResponse.response.TagProps.active
|
2023-07-18 19:37:40 +02:00
|
|
|
return active
|
|
|
|
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-21 21:36:32 +02:00
|
|
|
function tag:name()
|
|
|
|
local response = ReadMsg(SendRequest({
|
2023-07-20 23:05:26 +02:00
|
|
|
GetTagProps = {
|
2023-07-20 22:22:22 +02:00
|
|
|
tag_id = self._id,
|
2023-07-18 19:37:40 +02:00
|
|
|
},
|
2023-07-21 21:36:32 +02:00
|
|
|
}))
|
2023-07-20 23:05:26 +02:00
|
|
|
local name = response.RequestResponse.response.TagProps.name
|
2023-07-18 19:37:40 +02:00
|
|
|
return name
|
|
|
|
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-21 21:36:32 +02:00
|
|
|
function tag:output()
|
2023-07-20 22:22:22 +02:00
|
|
|
return require("output").get_for_tag(self)
|
2023-07-20 01:55:22 +02:00
|
|
|
end
|
|
|
|
|
2023-07-21 21:36:32 +02:00
|
|
|
---Switch to this tag.
|
|
|
|
function tag:switch_to()
|
|
|
|
tag_global.switch_to(self)
|
|
|
|
end
|
|
|
|
|
|
|
|
---Toggle this tag.
|
|
|
|
function tag:toggle()
|
|
|
|
tag_global.toggle(self)
|
|
|
|
end
|
|
|
|
|
2023-07-18 19:37:40 +02:00
|
|
|
---Set this tag's layout.
|
|
|
|
---@param layout Layout
|
2023-07-21 21:36:32 +02:00
|
|
|
function tag:set_layout(layout)
|
|
|
|
local name = self:name()
|
|
|
|
if name ~= nil then
|
|
|
|
tag_global.set_layout(name, layout)
|
|
|
|
end
|
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
|
|
|
---You can also do `output_object:add_tags(...)`.
|
2023-07-02 17:26: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-21 21:36:32 +02:00
|
|
|
function tag_global.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
|
|
|
|
|
2023-07-11 23:10:31 +02:00
|
|
|
---Toggle a tag on the specified output. If `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
|
|
|
|
----- Assuming all tags are toggled off...
|
2023-07-11 23:10:31 +02:00
|
|
|
---local op = output.get_by_name("DP-1")
|
|
|
|
---tag.toggle("1", op)
|
|
|
|
---tag.toggle("2", op)
|
2023-07-11 18:59:38 +02:00
|
|
|
----- will cause windows on both tags 1 and 2 to be displayed at the same time.
|
|
|
|
---```
|
2023-07-21 21:36:32 +02:00
|
|
|
---@param name string The name of the tag.
|
|
|
|
---@param output Output? The output.
|
|
|
|
---@overload fun(t: Tag)
|
|
|
|
function tag_global.toggle(name, output)
|
|
|
|
if type(name) == "table" then
|
|
|
|
SendMsg({
|
|
|
|
ToggleTag = {
|
|
|
|
tag_id = name--[[@as Tag]]:id(),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local output = output or require("output").get_focused()
|
|
|
|
|
|
|
|
if output == nil then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
print("before tag_global.get_by_name")
|
|
|
|
local tags = tag_global.get_by_name(name)
|
|
|
|
print("after tag_global.get_by_name")
|
|
|
|
for _, t in pairs(tags) do
|
|
|
|
if t:output() and t:output():name() == output:name() then
|
|
|
|
SendMsg({
|
|
|
|
ToggleTag = {
|
|
|
|
tag_id = t:id(),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
2023-07-01 04:34:07 +02:00
|
|
|
end
|
|
|
|
|
2023-07-11 23:10:31 +02:00
|
|
|
---Switch to a tag on the specified output, deactivating any other active tags on it.
|
|
|
|
---If `output` is not specified, this uses the currently focused output instead.
|
2023-07-21 21:36:32 +02:00
|
|
|
---Alternatively, provide a tag object instead of a name and output.
|
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-18 22:12:23 +02:00
|
|
|
---### Example
|
2023-07-11 18:59:38 +02:00
|
|
|
---
|
|
|
|
---```lua
|
|
|
|
---tag.switch_to("3") -- Switches to and displays *only* windows on tag 3
|
|
|
|
---```
|
2023-07-21 21:36:32 +02:00
|
|
|
---@param name string The name of the tag.
|
|
|
|
---@param output Output? The output.
|
|
|
|
---@overload fun(t: Tag)
|
|
|
|
function tag_global.switch_to(name, output)
|
|
|
|
if type(name) == "table" then
|
|
|
|
SendMsg({
|
|
|
|
SwitchToTag = {
|
|
|
|
tag_id = name--[[@as Tag]]:id(),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local output = output or require("output").get_focused()
|
|
|
|
|
|
|
|
if output == nil then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local tags = tag_global.get_by_name(name)
|
|
|
|
for _, t in pairs(tags) do
|
|
|
|
if t:output() and t:output():name() == output:name() then
|
|
|
|
SendMsg({
|
|
|
|
SwitchToTag = {
|
|
|
|
tag_id = t:id(),
|
|
|
|
},
|
|
|
|
})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
2023-07-02 02:06:37 +02:00
|
|
|
end
|
|
|
|
|
2023-07-21 21:36:32 +02:00
|
|
|
---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.
|
|
|
|
---Alternatively, provide a tag object instead of a name and output.
|
|
|
|
---@param name string The name of the tag.
|
|
|
|
---@param layout Layout The layout.
|
|
|
|
---@param output Output? The output.
|
|
|
|
---@overload fun(t: Tag, layout: Layout)
|
|
|
|
function tag_global.set_layout(name, layout, output)
|
|
|
|
if type(name) == "table" then
|
|
|
|
SendMsg({
|
|
|
|
SetLayout = {
|
|
|
|
tag_id = name--[[@as Tag]]:id(),
|
|
|
|
layout = layout,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local output = output or require("output").get_focused()
|
|
|
|
|
|
|
|
if output == nil then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local tags = tag_global.get_by_name(name)
|
|
|
|
for _, t in pairs(tags) do
|
|
|
|
if t:output() and t:output():name() == output:name() then
|
|
|
|
SendMsg({
|
|
|
|
SetLayout = {
|
|
|
|
tag_id = t:id(),
|
|
|
|
layout = layout,
|
|
|
|
},
|
|
|
|
})
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
2023-07-13 01:50:41 +02:00
|
|
|
end
|
2023-07-18 17:31:08 +02:00
|
|
|
|
|
|
|
---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[]
|
2023-07-21 21:36:32 +02:00
|
|
|
function tag_global.get_on_output(output)
|
|
|
|
local response = ReadMsg(SendRequest({
|
2023-07-20 22:22:22 +02:00
|
|
|
GetOutputProps = {
|
|
|
|
output_name = output:name(),
|
2023-07-18 17:31:08 +02:00
|
|
|
},
|
2023-07-21 21:36:32 +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-20 22:22:22 +02:00
|
|
|
table.insert(tags, new_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.
|
|
|
|
---@param name string The name of the tags you want.
|
|
|
|
---@return Tag[]
|
2023-07-21 21:36:32 +02:00
|
|
|
function tag_global.get_by_name(name)
|
|
|
|
local t_s = tag_global.get_all()
|
2023-07-20 23:05:26 +02:00
|
|
|
|
|
|
|
---@type Tag[]
|
|
|
|
local tags = {}
|
|
|
|
|
2023-07-21 21:36:32 +02:00
|
|
|
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
|
|
|
|
|
|
|
|
---Get all tags across all ouptuts.
|
|
|
|
---@return Tag[]
|
2023-07-21 21:36:32 +02:00
|
|
|
function tag_global.get_all()
|
|
|
|
local response = ReadMsg(SendRequest("GetTags"))
|
|
|
|
RPrint(response)
|
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-20 22:22:22 +02:00
|
|
|
table.insert(tags, new_tag(tag_id))
|
2023-07-20 01:55:22 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
return tags
|
|
|
|
end
|
|
|
|
|
2023-07-21 21:36:32 +02:00
|
|
|
return tag_global
|