Change config objects to modules

This commit is contained in:
Ottatop 2024-02-07 21:39:56 -06:00
parent 8f73819aed
commit fa2eed1adc
8 changed files with 284 additions and 376 deletions

View file

@ -16,12 +16,12 @@ require("pinnacle").setup(function(Pinnacle)
-- Mousebinds --
--------------------
Input:mousebind({ mod_key }, "btn_left", "press", function()
Window:begin_move("btn_left")
Input.mousebind({ mod_key }, "btn_left", "press", function()
Window.begin_move("btn_left")
end)
Input:mousebind({ mod_key }, "btn_right", "press", function()
Window:begin_resize("btn_right")
Input.mousebind({ mod_key }, "btn_right", "press", function()
Window.begin_resize("btn_right")
end)
--------------------
@ -29,42 +29,42 @@ require("pinnacle").setup(function(Pinnacle)
--------------------
-- mod_key + alt + q = Quit Pinnacle
Input:keybind({ mod_key, "alt" }, "q", function()
Pinnacle:quit()
Input.keybind({ mod_key, "alt" }, "q", function()
Pinnacle.quit()
end)
-- mod_key + alt + c = Close window
Input:keybind({ mod_key, "alt" }, "c", function()
local focused = Window:get_focused()
Input.keybind({ mod_key, "alt" }, "c", function()
local focused = Window.get_focused()
if focused then
focused:close()
end
end)
-- mod_key + alt + Return = Spawn `terminal`
Input:keybind({ mod_key }, key.Return, function()
Process:spawn(terminal)
Input.keybind({ mod_key }, key.Return, function()
Process.spawn(terminal)
end)
-- mod_key + alt + space = Toggle floating
Input:keybind({ mod_key, "alt" }, key.space, function()
local focused = Window:get_focused()
Input.keybind({ mod_key, "alt" }, key.space, function()
local focused = Window.get_focused()
if focused then
focused:toggle_floating()
end
end)
-- mod_key + f = Toggle fullscreen
Input:keybind({ mod_key }, "f", function()
local focused = Window:get_focused()
Input.keybind({ mod_key }, "f", function()
local focused = Window.get_focused()
if focused then
focused:toggle_fullscreen()
end
end)
-- mod_key + m = Toggle maximized
Input:keybind({ mod_key }, "m", function()
local focused = Window:get_focused()
Input.keybind({ mod_key }, "m", function()
local focused = Window.get_focused()
if focused then
focused:toggle_maximized()
end
@ -78,16 +78,16 @@ require("pinnacle").setup(function(Pinnacle)
-- `connect_for_all` is useful for performing setup on every monitor you have.
-- Here, we add tags with names 1-5 and set tag 1 as active.
Output:connect_for_all(function(op)
local tags = Tag:add(op, tag_names)
Output.connect_for_all(function(op)
local tags = Tag.add(op, tag_names)
tags[1]:set_active(true)
end)
-- Spawning must happen after you add tags, as Pinnacle currently doesn't render windows without tags.
Process:spawn_once(terminal)
Process.spawn_once(terminal)
-- Create a layout cycler to cycle layouts on an output.
local layout_cycler = Tag:new_layout_cycler({
local layout_cycler = Tag.new_layout_cycler({
"master_stack",
"dwindle",
"spiral",
@ -98,16 +98,16 @@ require("pinnacle").setup(function(Pinnacle)
})
-- mod_key + space = Cycle forward one layout on the focused output
Input:keybind({ mod_key }, key.space, function()
local focused_op = Output:get_focused()
Input.keybind({ mod_key }, key.space, function()
local focused_op = Output.get_focused()
if focused_op then
layout_cycler.next(focused_op)
end
end)
-- mod_key + shift + space = Cycle backward one layout on the focused output
Input:keybind({ mod_key, "shift" }, key.space, function()
local focused_op = Output:get_focused()
Input.keybind({ mod_key, "shift" }, key.space, function()
local focused_op = Output.get_focused()
if focused_op then
layout_cycler.prev(focused_op)
end
@ -117,28 +117,28 @@ require("pinnacle").setup(function(Pinnacle)
-- nil-safety: tags are guaranteed to be on the outputs due to connect_for_all above
-- mod_key + 1-5 = Switch to tags 1-5
Input:keybind({ mod_key }, tag_name, function()
Tag:get(tag_name):switch_to()
Input.keybind({ mod_key }, tag_name, function()
Tag.get(tag_name):switch_to()
end)
-- mod_key + shift + 1-5 = Toggle tags 1-5
Input:keybind({ mod_key, "shift" }, tag_name, function()
Tag:get(tag_name):toggle_active()
Input.keybind({ mod_key, "shift" }, tag_name, function()
Tag.get(tag_name):toggle_active()
end)
-- mod_key + alt + 1-5 = Move window to tags 1-5
Input:keybind({ mod_key, "alt" }, tag_name, function()
local focused = Window:get_focused()
Input.keybind({ mod_key, "alt" }, tag_name, function()
local focused = Window.get_focused()
if focused then
focused:move_to_tag(Tag:get(tag_name) --[[@as TagHandle]])
focused:move_to_tag(Tag.get(tag_name) --[[@as TagHandle]])
end
end)
-- mod_key + shift + alt + 1-5 = Toggle tags 1-5 on window
Input:keybind({ mod_key, "shift", "alt" }, tag_name, function()
local focused = Window:get_focused()
Input.keybind({ mod_key, "shift", "alt" }, tag_name, function()
local focused = Window.get_focused()
if focused then
focused:toggle_tag(Tag:get(tag_name) --[[@as TagHandle]])
focused:toggle_tag(Tag.get(tag_name) --[[@as TagHandle]])
end
end)
end

View file

@ -2,34 +2,28 @@
-- 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/.
local cqueues = require("cqueues")
local client = require("pinnacle.grpc.client")
---The entry point to configuration.
---
---This module contains one function: `setup`, which is how you'll access all the ways to configure Pinnacle.
---@class PinnacleModule
---@class Pinnacle
local pinnacle = {
version = "v0alpha1",
---@type Input
input = require("pinnacle.input"),
---@type Tag
tag = require("pinnacle.tag"),
---@type Output
output = require("pinnacle.output"),
---@type Window
window = require("pinnacle.window"),
---@type Process
process = require("pinnacle.process"),
}
---The Pinnacle module.
---
---This module holds all the other configuration modules (Window, Input, etc.), and allows you to
---quit the compositor using the `quit` method.
---@class Pinnacle
---@field private config_client Client
---@field input Input
---@field output Output
---@field process Process
---@field tag Tag
---@field window Window
local Pinnacle = {}
---Quit Pinnacle.
function Pinnacle:quit()
self.config_client:unary_request({
function pinnacle.quit()
client.unary_request({
service = "pinnacle.v0alpha1.PinnacleService",
method = "Quit",
request_type = "pinnacle.v0alpha1.QuitRequest",
@ -39,36 +33,18 @@ end
---Setup Pinnacle.
---
---You must pass in a function that takes in the `Pinnacle` module object. The module is how you'll access the other config modules.
---You must pass in a function that takes in the `Pinnacle` table. This table is how you'll access the other config modules.
---
---Note: All the config modules are object instantiations, and their methods require you to use the colon operator
---instead of the dot operator to call them.
---
---If you want to do a multi-file config, you should have other files return a function taking in necessary modules.
---Or you could cheat and stick the modules into globals :TrollFace:
---You can also `require` the other modules. Just be sure not to call any of their functions outside this
---setup function.
---
---@param config_fn fun(pinnacle: Pinnacle)
function pinnacle.setup(config_fn)
require("pinnacle.grpc.protobuf").build_protos()
local loop = cqueues.new()
config_fn(pinnacle)
local config_client = client.new(loop)
---@type Pinnacle
local self = {
config_client = config_client,
input = require("pinnacle.input").new(config_client),
process = require("pinnacle.process").new(config_client),
window = require("pinnacle.window").new(config_client),
output = require("pinnacle.output").new(config_client),
tag = require("pinnacle.tag").new(config_client),
}
setmetatable(self, { __index = Pinnacle })
config_fn(self)
loop:loop()
client.loop:loop()
end
return pinnacle

View file

@ -22,15 +22,27 @@ local function create_request_headers(service, method)
return req_headers
end
---@nodoc
---@class ClientModule
local client = {}
local function new_conn()
local sock = socket.connect({
path = os.getenv("PINNACLE_GRPC_SOCKET"),
})
sock:connect()
local conn = h2_connection.new(sock, "client")
conn:connect()
return conn
end
---@nodoc
---@class Client
---@field conn H2Connection
---@field loop CqueuesLoop
local Client = {}
local client = {
conn = new_conn(),
loop = require("cqueues").new(),
version = "v0alpha1",
}
---@class GrpcRequestParams
---@field service string
@ -49,8 +61,8 @@ local Client = {}
---`google.protobuf.Empty`.
---@param grpc_request_params GrpcRequestParams
---@return table
function Client:unary_request(grpc_request_params)
local stream = self.conn:new_stream()
function client.unary_request(grpc_request_params)
local stream = client.conn:new_stream()
local service = grpc_request_params.service
local method = grpc_request_params.method
@ -98,8 +110,8 @@ end
---`google.protobuf.Empty`.
---@param grpc_request_params GrpcRequestParams
---@param callback fun(response: table)
function Client:server_streaming_request(grpc_request_params, callback)
local stream = self.conn:new_stream()
function client.server_streaming_request(grpc_request_params, callback)
local stream = client.conn:new_stream()
local service = grpc_request_params.service
local method = grpc_request_params.method
@ -126,7 +138,7 @@ function Client:server_streaming_request(grpc_request_params, callback)
local response_headers = stream:get_headers()
-- TODO: check headers for errors
self.loop:wrap(function()
client.loop:wrap(function()
for response_body in stream:each_chunk() do
-- Skip the 1-byte compressed flag and the 4-byte message length
local response_body = response_body:sub(6)
@ -150,25 +162,4 @@ function Client:server_streaming_request(grpc_request_params, callback)
end)
end
---@nodoc
---@return Client
function client.new(loop)
local sock = socket.connect({
path = os.getenv("PINNACLE_GRPC_SOCKET"),
})
sock:connect()
local conn = h2_connection.new(sock, "client")
conn:connect()
---@type Client
local self = {
conn = conn,
loop = loop,
}
setmetatable(self, { __index = Client })
return self
end
return client

View file

@ -2,8 +2,10 @@
-- 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/.
local client = require("pinnacle.grpc.client")
---The protobuf absolute path prefix
local prefix = "pinnacle.input." .. require("pinnacle").version .. "."
local prefix = "pinnacle.input." .. client.version .. "."
local service = prefix .. "InputService"
---@type table<string, { request_type: string?, response_type: string? }>
@ -97,20 +99,15 @@ local mouse_edge_values = {
---| "press" Trigger on mouse button press
---| "release" Trigger on mouse button release
---@nodoc
---@class InputModule
---@field private btn table
local input = {}
input.btn = mouse_button_values
---Input management.
---
---This module provides utilities to set key- and mousebinds as well as change keyboard settings.
---@class Input
---@field private config_client Client
local Input = {
---@field private btn table
local input = {
key = require("pinnacle.input.keys"),
}
input.btn = mouse_button_values
---Set a keybind. If called with an already existing keybind, it gets replaced.
---
@ -127,29 +124,29 @@ local Input = {
---Usually, it's best to use the non-modified key to prevent confusion and unintended behavior.
---
---```lua
---Input:keybind({ "shift" }, "a", function() end) -- This is preferred
---Input:keybind({ "shift" }, "A", function() end) -- over this
---Input.keybind({ "shift" }, "a", function() end) -- This is preferred
---Input.keybind({ "shift" }, "A", function() end) -- over this
---
--- -- This keybind will only work with capslock on.
---Input:keybind({}, "A", function() end)
---Input.keybind({}, "A", function() end)
---
--- -- This keybind won't work at all because to get `@` you need to hold shift,
--- -- which this keybind doesn't accept.
---Input:keybind({ "ctrl" }, "@", function() end)
---Input.keybind({ "ctrl" }, "@", function() end)
---```
---
---### Example
---```lua
--- -- Set `super + Return` to open Alacritty
---Input:keybind({ "super" }, Input.key.Return, function()
--- Process:spawn("alacritty")
---Input.keybind({ "super" }, Input.key.Return, function()
--- Process.spawn("alacritty")
---end)
---```
---
---@param mods Modifier[] The modifiers that need to be held down for the bind to trigger
---@param key Key | string The key used to trigger the bind
---@param action fun() The function to run when the bind is triggered
function Input:keybind(mods, key, action)
function input.keybind(mods, key, action)
local raw_code = nil
local xkb_name = nil
@ -164,7 +161,7 @@ function Input:keybind(mods, key, action)
table.insert(mod_values, modifier_values[mod])
end
self.config_client:server_streaming_request(
client.server_streaming_request(
build_grpc_request_params("SetKeybind", {
modifiers = mod_values,
raw_code = raw_code,
@ -181,8 +178,8 @@ end
---### Example
---```lua
--- -- Set `super + left mouse button` to move a window on press
---Input:mousebind({ "super" }, "btn_left", "press", function()
--- Window:begin_move("btn_left")
---Input.mousebind({ "super" }, "btn_left", "press", function()
--- Window.begin_move("btn_left")
---end)
---```
---
@ -190,7 +187,7 @@ end
---@param button MouseButton The mouse button used to trigger the bind
---@param edge MouseEdge "press" or "release" to trigger on button press or release
---@param action fun() The function to run when the bind is triggered
function Input:mousebind(mods, button, edge, action)
function input.mousebind(mods, button, edge, action)
local edge = mouse_edge_values[edge]
local mod_values = {}
@ -198,7 +195,7 @@ function Input:mousebind(mods, button, edge, action)
table.insert(mod_values, modifier_values[mod])
end
self.config_client:server_streaming_request(
client.server_streaming_request(
build_grpc_request_params("SetMousebind", {
modifiers = mod_values,
button = mouse_button_values[button],
@ -223,28 +220,28 @@ end
---
---### Example
---```lua
---Input:set_xkb_config({
---Input.set_xkb_config({
--- layout = "us,fr,ge",
--- options = "ctrl:swapcaps,caps:shift"
---})
---```
---
---@param xkb_config XkbConfig The new xkbconfig
function Input:set_xkb_config(xkb_config)
self.config_client:unary_request(build_grpc_request_params("SetXkbConfig", xkb_config))
function input.set_xkb_config(xkb_config)
client.unary_request(build_grpc_request_params("SetXkbConfig", xkb_config))
end
---Set the keyboard's repeat rate and delay.
---
---### Example
---```lua
---Input:set_repeat_rate(100, 1000) -- Key must be held down for 1 second, then repeats 10 times per second.
---Input.set_repeat_rate(100, 1000) -- Key must be held down for 1 second, then repeats 10 times per second.
---```
---
---@param rate integer The time between repeats in milliseconds
---@param delay integer The duration a key needs to be held down before repeating starts in milliseconds
function Input:set_repeat_rate(rate, delay)
self.config_client:unary_request(build_grpc_request_params("SetRepeatRate", {
function input.set_repeat_rate(rate, delay)
client.unary_request(build_grpc_request_params("SetRepeatRate", {
rate = rate,
delay = delay,
}))
@ -308,42 +305,39 @@ local tap_button_map_values = {
---
---This includes settings for pointer devices, like acceleration profiles, natural scroll, and more.
---
---### Example
---```lua
---Input.set_libinput_settings({
--- accel_profile = "flat",
--- natural_scroll = true,
---})
---```
---
---@param settings LibinputSettings
function Input:set_libinput_settings(settings)
function input.set_libinput_settings(settings)
for setting, value in pairs(settings) do
if setting == "accel_profile" then
self.config_client:unary_request(
client.unary_request(
build_grpc_request_params("SetLibinputSetting", { [setting] = accel_profile_values[value] })
)
elseif setting == "calibration_matrix" then
self.config_client:unary_request(
build_grpc_request_params("SetLibinputSetting", { [setting] = { matrix = value } })
)
client.unary_request(build_grpc_request_params("SetLibinputSetting", { [setting] = { matrix = value } }))
elseif setting == "click_method" then
self.config_client:unary_request(
client.unary_request(
build_grpc_request_params("SetLibinputSetting", { [setting] = click_method_values[value] })
)
elseif setting == "scroll_method" then
self.config_client:unary_request(
client.unary_request(
build_grpc_request_params("SetLibinputSetting", { [setting] = scroll_method_values[value] })
)
elseif setting == "tap_button_map" then
self.config_client:unary_request(
client.unary_request(
build_grpc_request_params("SetLibinputSetting", { [setting] = tap_button_map_values[value] })
)
else
self.config_client:unary_request(build_grpc_request_params("SetLibinputSetting", { [setting] = value }))
client.unary_request(build_grpc_request_params("SetLibinputSetting", { [setting] = value }))
end
end
end
function input.new(config_client)
---@type Input
local self = {
config_client = config_client,
}
setmetatable(self, { __index = Input })
return self
end
return input

View file

@ -2,8 +2,10 @@
-- 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/.
local client = require("pinnacle.grpc.client")
---The protobuf absolute path prefix
local prefix = "pinnacle.output." .. require("pinnacle").version .. "."
local prefix = "pinnacle.output." .. client.version .. "."
local service = prefix .. "OutputService"
---@type table<string, { request_type: string?, response_type: string? }>
@ -52,41 +54,35 @@ local output_handle = {}
---This can be retrieved through the various `get` functions in the `Output` module.
---@classmod
---@class OutputHandle
---@field private config_client Client
---@field name string The unique name of this output
local OutputHandle = {}
---@nodoc
---@class OutputModule
---@field private handle OutputHandleModule
local output = {}
output.handle = output_handle
---Output management.
---
---An output is what you would call a monitor. It presents windows, your cursor, and other UI elements.
---
---Outputs are uniquely identified by their name, a.k.a. the name of the connector they're plugged in to.
---@class Output
---@field private config_client Client
local Output = {}
---@field private handle OutputHandleModule
local output = {}
output.handle = output_handle
---Get all outputs.
---
---### Example
---```lua
---local outputs = Output:get_all()
---local outputs = Output.get_all()
---```
---
---@return OutputHandle[]
function Output:get_all()
local response = self.config_client:unary_request(build_grpc_request_params("Get", {}))
function output.get_all()
local response = client.unary_request(build_grpc_request_params("Get", {}))
---@type OutputHandle[]
local handles = {}
for _, output_name in ipairs(response.output_names or {}) do
table.insert(handles, output_handle.new(self.config_client, output_name))
table.insert(handles, output_handle.new(output_name))
end
return handles
@ -96,13 +92,13 @@ end
---
---### Example
---```lua
---local output = Output:get_by_name("eDP-1")
---local output = Output.get_by_name("eDP-1")
---```
---
---@param name string The name of the connector the output is connected to
---@return OutputHandle | nil
function Output:get_by_name(name)
local handles = self:get_all()
function output.get_by_name(name)
local handles = output.get_all()
for _, handle in ipairs(handles) do
if handle.name == name then
@ -119,12 +115,12 @@ end
---
---### Example
---```lua
---local output = Output:get_focused()
---local output = Output.get_focused()
---```
---
---@return OutputHandle | nil
function Output:get_focused()
local handles = self:get_all()
function output.get_focused()
local handles = output.get_all()
for _, handle in ipairs(handles) do
if handle:props().focused then
@ -148,22 +144,22 @@ end
---### Example
---```lua
--- -- Add tags "1" through "5" to all outputs
---Output:connect_for_all(function(output)
--- local tags = Tag:add(output, "1", "2", "3", "4", "5")
---Output.connect_for_all(function(output)
--- local tags = Tag.add(output, "1", "2", "3", "4", "5")
--- tags[1]:toggle_active()
---end)
---```
---
---@param callback fun(output: OutputHandle)
function Output:connect_for_all(callback)
local handles = self:get_all()
function output.connect_for_all(callback)
local handles = output.get_all()
for _, handle in ipairs(handles) do
callback(handle)
end
self.config_client:server_streaming_request(build_grpc_request_params("ConnectForAll", {}), function(response)
client.server_streaming_request(build_grpc_request_params("ConnectForAll", {}), function(response)
local output_name = response.output_name
local handle = output_handle.new(self.config_client, output_name)
local handle = output_handle.new(output_name)
callback(handle)
end)
end
@ -188,8 +184,8 @@ end
--- -- │ 2560x │
--- -- │ 1440 │
--- -- └───────┘
---Output:get_by_name("DP-1"):set_location({ x = 0, y = 0 })
---Output:get_by_name("HDMI-1"):set_location({ x = 1920, y = -360 })
---Output.get_by_name("DP-1"):set_location({ x = 0, y = 0 })
---Output.get_by_name("HDMI-1"):set_location({ x = 1920, y = -360 })
--- -- Results in:
--- -- ┌───────┐
--- -- ┌─────┤ │
@ -202,7 +198,7 @@ end
---
---@see OutputHandle.set_loc_adj_to
function OutputHandle:set_location(loc)
self.config_client:unary_request(build_grpc_request_params("SetLocation", {
client.unary_request(build_grpc_request_params("SetLocation", {
output_name = self.name,
x = loc.x,
y = loc.y,
@ -239,7 +235,7 @@ end
--- -- │ 2560x │
--- -- │ 1440 │
--- -- └───────┘
---Output:get_by_name("DP-1"):set_loc_adj_to(Output:get_by_name("HDMI-1"), "bottom_align_right")
---Output.get_by_name("DP-1"):set_loc_adj_to(Output:get_by_name("HDMI-1"), "bottom_align_right")
--- -- Results in:
--- -- ┌───────┐
--- -- │ │
@ -328,10 +324,9 @@ end
---
---@return OutputProperties
function OutputHandle:props()
local response =
self.config_client:unary_request(build_grpc_request_params("GetProperties", { output_name = self.name }))
local response = client.unary_request(build_grpc_request_params("GetProperties", { output_name = self.name }))
local handles = require("pinnacle.tag").handle.new_from_table(self.config_client, response.tag_ids or {})
local handles = require("pinnacle.tag").handle.new_from_table(response.tag_ids or {})
response.tags = handles
response.tag_ids = nil
@ -446,24 +441,12 @@ function OutputHandle:tags()
return self:props().tags
end
---@nodoc
---@return Output
function output.new(config_client)
---@type Output
local self = {
config_client = config_client,
}
setmetatable(self, { __index = Output })
return self
end
---@nodoc
---Create a new `OutputHandle` from its raw name.
---@param output_name string
function output_handle.new(config_client, output_name)
function output_handle.new(output_name)
---@type OutputHandle
local self = {
config_client = config_client,
name = output_name,
}
setmetatable(self, { __index = OutputHandle })

View file

@ -2,8 +2,10 @@
-- 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/.
local client = require("pinnacle.grpc.client")
---The protobuf absolute path prefix
local prefix = "pinnacle.process." .. require("pinnacle").version .. "."
local prefix = "pinnacle.process." .. client.version .. "."
local service = prefix .. "ProcessService"
---@type table<string, { request_type: string?, response_type: string? }>
@ -33,22 +35,16 @@ local function build_grpc_request_params(method, data)
}
end
---@nodoc
---@class ProcessModule
local process = {}
---Process management.
---
---This module provides utilities to spawn processes and capture their output.
---@class Process
---@field private config_client Client
local Process = {}
local process = {}
---@param config_client Client
---@param args string[]
---@param callbacks { stdout: fun(line: string)?, stderr: fun(line: string)?, exit: fun(code: integer, msg: string)? }?
---@param once boolean
local function spawn_inner(config_client, args, callbacks, once)
local function spawn_inner(args, callbacks, once)
local callback = function() end
if callbacks then
@ -65,7 +61,7 @@ local function spawn_inner(config_client, args, callbacks, once)
end
end
config_client:server_streaming_request(
client.server_streaming_request(
build_grpc_request_params("Spawn", {
args = args,
once = once,
@ -88,47 +84,65 @@ end
---Note 2: If you spawn a window before tags are added it will spawn without any tags and
---won't be displayed in the compositor. TODO: Do what awesome does and display on all tags instead
---
---### Example
---```lua
---Process.spawn("alacritty")
---
--- -- With a table of arguments
---Process.spawn({ "bash", "-c", "echo hello" })
---
--- -- With callbacks
---Process.spawn("alacritty", {
--- stdout = function(line)
--- print(line)
--- end,
--- -- You can ignore callbacks you don't need
--- exit = function(code, msg)
--- print("exited with code", code)
--- print("exited with msg", msg)
--- end,
---})
---```
---
---@param args string | string[] The program arguments; a string instead of an array should be for only 1 argument
---@param callbacks { stdout: fun(line: string)?, stderr: fun(line: string)?, exit: fun(code: integer, msg: string)? }? Callbacks that will be run whenever the program outputs to stdout, stderr, or exits.
function Process:spawn(args, callbacks)
function process.spawn(args, callbacks)
if type(args) == "string" then
args = { args }
end
spawn_inner(self.config_client, args, callbacks, false)
spawn_inner(args, callbacks, false)
end
---Like `Process:spawn` but will only spawn the program if it isn't already running.
---Like `Process.spawn` but will only spawn the program if it isn't already running.
---
---@param args string | string[]
---@param callbacks { stdout: fun(line: string)?, stderr: fun(line: string)?, exit: fun(code: integer, msg: string)? }?
---
---@see Process.spawn
function Process:spawn_once(args, callbacks)
function process.spawn_once(args, callbacks)
if type(args) == "string" then
args = { args }
end
spawn_inner(self.config_client, args, callbacks, true)
spawn_inner(args, callbacks, true)
end
---Set an environment variable for the compositor.
---This will cause any future spawned processes to have this environment variable.
---
---### Example
---```lua
---Process.set_env("ENV_NAME", "the value")
---```
---
---@param key string The environment variable key
---@param value string The environment variable value
function Process:set_env(key, value)
self.config_client:unary_request(build_grpc_request_params("SetEnv", {
function process.set_env(key, value)
client.unary_request(build_grpc_request_params("SetEnv", {
key = key,
value = value,
}))
end
function process.new(config_client)
---@type Process
local self = { config_client = config_client }
setmetatable(self, { __index = Process })
return self
end
return process

View file

@ -2,8 +2,10 @@
-- 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/.
local client = require("pinnacle.grpc.client")
---The protobuf absolute path prefix
local prefix = "pinnacle.tag." .. require("pinnacle").version .. "."
local prefix = "pinnacle.tag." .. client.version .. "."
local service = prefix .. "TagService"
---@type table<string, { request_type: string?, response_type: string? }>
@ -53,16 +55,9 @@ local tag_handle = {}
---This can be retrieved through the various `get` functions in the `Tag` module.
---@classmod
---@class TagHandle
---@field private config_client Client
---@field id integer
local TagHandle = {}
---@nodoc
---@class TagModule
---@field private handle TagHandleModule
local tag = {}
tag.handle = tag_handle
---Tag management.
---
---This module provides utilities for creating and manipulating tags.
@ -79,20 +74,21 @@ tag.handle = tag_handle
---
---If you need to get tags beyond the first with the same name, use the `get` method and find what you need.
---@class Tag
---@field private config_client Client
local Tag = {}
---@field private handle TagHandleModule
local tag = {}
tag.handle = tag_handle
---Get all tags across all outputs.
---
---@return TagHandle[]
function Tag:get_all()
local response = self.config_client:unary_request(build_grpc_request_params("Get", {}))
function tag.get_all()
local response = client.unary_request(build_grpc_request_params("Get", {}))
---@type TagHandle[]
local handles = {}
for _, id in ipairs(response.tag_ids or {}) do
table.insert(handles, tag_handle.new(self.config_client, id))
table.insert(handles, tag_handle.new(id))
end
return handles
@ -107,24 +103,24 @@ end
---### Example
---```lua
--- -- Get tags on the focused output
---local tag = Tag:get("Tag")
---local tag = Tag.get("Tag")
---
--- -- Get tags on a specific output
---local tag_on_hdmi1 = Tag:get("Tag", Output:get_by_name("HDMI-1"))
---local tag_on_hdmi1 = Tag.get("Tag", Output:get_by_name("HDMI-1"))
---```
---
---@param name string
---@param output OutputHandle?
---
---@return TagHandle | nil
function Tag:get(name, output)
output = output or require("pinnacle.output").new(self.config_client):get_focused()
function tag.get(name, output)
output = output or require("pinnacle.output").get_focused()
if not output then
return
end
local handles = self:get_all()
local handles = tag.get_all()
for _, handle in ipairs(handles) do
local props = handle:props()
@ -142,11 +138,11 @@ end
---
---### Example
---```lua
---local tags = Tag:add(Output:get_by_name("HDMI-1"), "1", "2", "Buckle", "Shoe")
---local tags = Tag.add(Output.get_by_name("HDMI-1"), "1", "2", "Buckle", "Shoe")
---
--- -- With a table
---local tag_names = { "1", "2", "Buckle", "Shoe" }
---local tags = Tag:add(Output:get_by_name("HDMI-1"), tag_names)
---local tags = Tag.add(Output.get_by_name("HDMI-1"), tag_names)
---```
---
---@param output OutputHandle
@ -154,14 +150,14 @@ end
---
---@return TagHandle[] tags Handles to the created tags
---
---@overload fun(self: self, output: OutputHandle, tag_names: string[])
function Tag:add(output, ...)
---@overload fun(output: OutputHandle, tag_names: string[])
function tag.add(output, ...)
local tag_names = { ... }
if type(tag_names[1]) == "table" then
tag_names = tag_names[1] --[=[@as string[]]=]
end
local response = self.config_client:unary_request(build_grpc_request_params("Add", {
local response = client.unary_request(build_grpc_request_params("Add", {
output_name = output.name,
tag_names = tag_names,
}))
@ -170,7 +166,7 @@ function Tag:add(output, ...)
local handles = {}
for _, id in ipairs(response.tag_ids) do
table.insert(handles, tag_handle.new(self.config_client, id))
table.insert(handles, tag_handle.new(id))
end
return handles
@ -180,13 +176,13 @@ end
---
---### Example
---```lua
---local tags = Tag:add(Output:get_by_name("HDMI-1"), "1", "2", "Buckle", "Shoe")
---local tags = Tag.add(Output.get_by_name("HDMI-1"), "1", "2", "Buckle", "Shoe")
---
---Tag:remove(tags) -- "HDMI-1" no longer has those tags
---Tag.remove(tags) -- "HDMI-1" no longer has those tags
---```
---
---@param tags TagHandle[]
function Tag:remove(tags)
function tag.remove(tags)
---@type integer[]
local ids = {}
@ -194,7 +190,7 @@ function Tag:remove(tags)
table.insert(ids, tg.id)
end
self.config_client:unary_request(build_grpc_request_params("Remove", { tag_ids = ids }))
client.unary_request(build_grpc_request_params("Remove", { tag_ids = ids }))
end
---@class LayoutCycler
@ -222,7 +218,7 @@ end
--- "corner_top_right".
---} -- Only cycle between these four layouts
---
---local layout_cycler = Tag:new_layout_cycler()
---local layout_cycler = Tag.new_layout_cycler()
---
--- -- Assume the focused output starts with the "master_stack" layout
---layout_cycler.next() -- Layout is now "dwindle"
@ -232,14 +228,14 @@ end
---layout_cycler.next() -- Layout is now "corner_top_right"
---
--- -- Cycling on another output
---layout_cycler.next(Output:get_by_name("eDP-1"))
---layout_cycler.prev(Output:get_by_name("HDMI-1"))
---layout_cycler.next(Output.get_by_name("eDP-1"))
---layout_cycler.prev(Output.get_by_name("HDMI-1"))
---```
---
---@param layouts Layout[]
---
---@return LayoutCycler
function Tag:new_layout_cycler(layouts)
function tag.new_layout_cycler(layouts)
local indices = {}
if #layouts == 0 then
@ -252,7 +248,7 @@ function Tag:new_layout_cycler(layouts)
---@type LayoutCycler
return {
next = function(output)
local output = output or require("pinnacle.output").new(self.config_client):get_focused()
local output = output or require("pinnacle.output").get_focused()
if not output then
return
end
@ -280,7 +276,7 @@ function Tag:new_layout_cycler(layouts)
end
end,
prev = function(output)
local output = output or require("pinnacle.output").new(self.config_client):get_focused()
local output = output or require("pinnacle.output").get_focused()
if not output then
return
end
@ -315,14 +311,14 @@ end
---
---### Example
---```lua
---local tags = Tag:add(Output:get_by_name("HDMI-1"), "1", "2", "Buckle", "Shoe")
---local tags = Tag.add(Output.get_by_name("HDMI-1"), "1", "2", "Buckle", "Shoe")
---
---tags[2]:remove()
---tags[4]:remove()
--- -- "HDMI-1" now only has tags "1" and "Buckle"
---```
function TagHandle:remove()
self.config_client:unary_request(build_grpc_request_params("Remove", { tag_ids = { self.id } }))
client.unary_request(build_grpc_request_params("Remove", { tag_ids = { self.id } }))
end
local _layouts = {
@ -350,14 +346,14 @@ local _layouts = {
---### Example
---```lua
--- -- Assume the focused output has tag "Tag"
---Tag:get("Tag"):set_layout("dwindle")
---Tag.get("Tag"):set_layout("dwindle")
---```
---
---@param layout Layout
function TagHandle:set_layout(layout)
local layout = _layouts[layout]
self.config_client:unary_request(build_grpc_request_params("SetLayout", {
client.unary_request(build_grpc_request_params("SetLayout", {
tag_id = self.id,
layout = layout,
}))
@ -371,11 +367,11 @@ end
--- -- - "1": Alacritty
--- -- - "2": Firefox, Discord
--- -- - "3": Steam
---Tag:get("2"):switch_to() -- Displays Firefox and Discord
---Tag:get("3"):switch_to() -- Displays Steam
---Tag.get("2"):switch_to() -- Displays Firefox and Discord
---Tag.get("3"):switch_to() -- Displays Steam
---```
function TagHandle:switch_to()
self.config_client:unary_request(build_grpc_request_params("SwitchTo", { tag_id = self.id }))
client.unary_request(build_grpc_request_params("SwitchTo", { tag_id = self.id }))
end
---Set whether or not this tag is active.
@ -386,14 +382,14 @@ end
--- -- - "1": Alacritty
--- -- - "2": Firefox, Discord
--- -- - "3": Steam
---Tag:get("2"):set_active(true) -- Displays Firefox and Discord
---Tag:get("3"):set_active(true) -- Displays Firefox, Discord, and Steam
---Tag:get("2"):set_active(false) -- Displays Steam
---Tag.get("2"):set_active(true) -- Displays Firefox and Discord
---Tag.get("3"):set_active(true) -- Displays Firefox, Discord, and Steam
---Tag.get("2"):set_active(false) -- Displays Steam
---```
---
---@param active boolean
function TagHandle:set_active(active)
self.config_client:unary_request(build_grpc_request_params("SetActive", { tag_id = self.id, set = active }))
client.unary_request(build_grpc_request_params("SetActive", { tag_id = self.id, set = active }))
end
---Toggle this tag's active state.
@ -404,11 +400,11 @@ end
--- -- - "1": Alacritty
--- -- - "2": Firefox, Discord
--- -- - "3": Steam
---Tag:get("2"):toggle_active() -- Displays Firefox and Discord
---Tag:get("2"):toggle_active() -- Displays nothing
---Tag.get("2"):toggle_active() -- Displays Firefox and Discord
---Tag.get("2"):toggle_active() -- Displays nothing
---```
function TagHandle:toggle_active()
self.config_client:unary_request(build_grpc_request_params("SetActive", { tag_id = self.id, toggle = {} }))
client.unary_request(build_grpc_request_params("SetActive", { tag_id = self.id, toggle = {} }))
end
---@class TagProperties
@ -420,13 +416,12 @@ end
---
---@return TagProperties
function TagHandle:props()
local response = self.config_client:unary_request(build_grpc_request_params("GetProperties", { tag_id = self.id }))
local response = client.unary_request(build_grpc_request_params("GetProperties", { tag_id = self.id }))
return {
active = response.active,
name = response.name,
output = response.output_name
and require("pinnacle.output").handle.new(self.config_client, response.output_name),
output = response.output_name and require("pinnacle.output").handle.new(response.output_name),
}
end
@ -457,26 +452,13 @@ function TagHandle:output()
return self:props().output
end
---@nodoc
---@return Tag
function tag.new(config_client)
---@type Tag
local self = {
config_client = config_client,
}
setmetatable(self, { __index = Tag })
return self
end
---@nodoc
---Create a new `TagHandle` from an id.
---@param config_client Client
---@param tag_id integer
---@return TagHandle
function tag_handle.new(config_client, tag_id)
function tag_handle.new(tag_id)
---@type TagHandle
local self = {
config_client = config_client,
id = tag_id,
}
setmetatable(self, { __index = TagHandle })
@ -484,15 +466,14 @@ function tag_handle.new(config_client, tag_id)
end
---@nodoc
---@param config_client Client
---@param tag_ids integer[]
---@return TagHandle[]
function tag_handle.new_from_table(config_client, tag_ids)
function tag_handle.new_from_table(tag_ids)
---@type TagHandle[]
local handles = {}
for _, id in ipairs(tag_ids) do
table.insert(handles, tag_handle.new(config_client, id))
table.insert(handles, tag_handle.new(id))
end
return handles

View file

@ -2,8 +2,10 @@
-- 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/.
local client = require("pinnacle.grpc.client")
---The protobuf absolute path prefix
local prefix = "pinnacle.window." .. require("pinnacle").version .. "."
local prefix = "pinnacle.window." .. client.version .. "."
local service = prefix .. "WindowService"
---@type table<string, { request_type: string?, response_type: string? }>
@ -59,38 +61,30 @@ local window_handle = {}
---You can retrieve window handles through the various `get` functions in the `Window` module.
---@classmod
---@class WindowHandle
---@field private config_client Client
---@field id integer
local WindowHandle = {}
---@nodoc
---@class WindowModule
---@field private handle WindowHandleModule
local window = {}
window.handle = window_handle
---Window management.
---
---This module helps you deal with setting windows to fullscreen and maximized, setting their size,
---moving them between tags, and various other actions.
---@class Window
---@field private config_client Client
local Window = {}
local window = {}
---Get all windows.
---
---### Example
---```lua
---local windows = Window:get_all()
---local windows = Window.get_all()
---for _, window in ipairs(windows) do
--- print(window:props().class)
---end
---```
---@return WindowHandle[] windows Handles to all windows
function Window:get_all()
local response = self.config_client:unary_request(build_grpc_request_params("Get", {}))
function window.get_all()
local response = client.unary_request(build_grpc_request_params("Get", {}))
local handles = window_handle.new_from_table(self.config_client, response.window_ids or {})
local handles = window_handle.new_from_table(response.window_ids or {})
return handles
end
@ -99,14 +93,14 @@ end
---
---### Example
---```lua
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- print(focused:props().class)
---end
---```
---@return WindowHandle | nil window A handle to the currently focused window
function Window:get_focused()
local handles = self:get_all()
function window.get_focused()
local handles = window.get_all()
for _, handle in ipairs(handles) do
if handle:props().focused then
@ -124,14 +118,14 @@ end
---
---### Example
---```lua
---Input:mousebind({ "super" }, "btn_left", function()
--- Window:begin_move("btn_left")
---Input.mousebind({ "super" }, "btn_left", function()
--- Window.begin_move("btn_left")
---end)
---```
---@param button MouseButton The button that will initiate the move
function Window:begin_move(button)
function window.begin_move(button)
local button = require("pinnacle.input").btn[button]
self.config_client:unary_request(build_grpc_request_params("MoveGrab", { button = button }))
client.unary_request(build_grpc_request_params("MoveGrab", { button = button }))
end
---Begin resizing this window using the specified mouse button.
@ -141,14 +135,14 @@ end
---
---### Example
---```lua
---Input:mousebind({ "super" }, "btn_right", function()
--- Window:begin_resize("btn_right")
---Input.mousebind({ "super" }, "btn_right", function()
--- Window.begin_resize("btn_right")
---end)
---```
---@param button MouseButton The button that will initiate the resize
function Window:begin_resize(button)
function window.begin_resize(button)
local button = require("pinnacle.input").btn[button]
self.config_client:unary_request(build_grpc_request_params("ResizeGrab", { button = button }))
client.unary_request(build_grpc_request_params("ResizeGrab", { button = button }))
end
---@class WindowRuleCondition
@ -204,7 +198,7 @@ local _fullscreen_or_maximized_keys = {
---### Examples
---```lua
--- -- A simple window rule. This one will cause Firefox to open on tag "Browser".
---Window:add_window_rule({
---Window.add_window_rule({
--- cond = { classes = { "firefox" } },
--- rule = { tags = { "Browser" } },
---})
@ -212,7 +206,7 @@ local _fullscreen_or_maximized_keys = {
--- -- To apply rules when *all* provided conditions are true, use `all`.
--- -- `all` takes an array of conditions and checks if all are true.
--- -- The following will open Steam fullscreen only if it opens on tag "5".
---Window:add_window_rule({
---Window.add_window_rule({
--- cond = {
--- all = {
--- {
@ -226,7 +220,7 @@ local _fullscreen_or_maximized_keys = {
---
--- -- The outermost block of a `cond` is implicitly an `all` block.
--- -- Thus, the above can be shortened to:
---Window:add_window_rule({
---Window.add_window_rule({
--- cond = {
--- class = "steam",
--- tag = Tag:get("5"),
@ -236,7 +230,7 @@ local _fullscreen_or_maximized_keys = {
---
--- -- `any` also exists to allow at least one provided condition to match.
--- -- The following will open either xterm or Alacritty floating.
---Window:add_window_rule({
---Window.add_window_rule({
--- cond = {
--- any = { { classes = { "xterm", "Alacritty" } } }
--- },
@ -246,7 +240,7 @@ local _fullscreen_or_maximized_keys = {
--- -- You can arbitrarily nest `any` and `all` to achieve desired logic.
--- -- The following will open Discord, Thunderbird, or Firefox floating if they
--- -- open on either *all* of tags "A", "B", and "C" or both tags "1" and "2".
---Window:add_window_rule({
---Window.add_window_rule({
--- cond = {
--- all = { -- This `all` block is needed because the outermost block cannot be an array.
--- { any = {
@ -270,7 +264,7 @@ local _fullscreen_or_maximized_keys = {
---```
---
---@param rule { cond: WindowRuleCondition, rule: WindowRule } The condition and rule
function Window:add_window_rule(rule)
function window.add_window_rule(rule)
if rule.cond.tags then
local ids = {}
for _, tg in ipairs(rule.cond.tags) do
@ -295,7 +289,7 @@ function Window:add_window_rule(rule)
rule.rule.fullscreen_or_maximized = _fullscreen_or_maximized[rule.rule.fullscreen_or_maximized]
end
self.config_client:unary_request(build_grpc_request_params("AddWindowRule", {
client.unary_request(build_grpc_request_params("AddWindowRule", {
cond = rule.cond,
rule = rule.rule,
}))
@ -305,11 +299,11 @@ end
---
---### Example
---```lua
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then focused:close() end
---```
function WindowHandle:close()
self.config_client:unary_request(build_grpc_request_params("Close", { window_id = self.id }))
client.unary_request(build_grpc_request_params("Close", { window_id = self.id }))
end
---Set this window's location and/or size.
@ -328,7 +322,7 @@ end
---
---### Example
---```lua
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- focused:set_floating(true) -- `set_geometry` only applies to floating geometry.
---
@ -339,14 +333,14 @@ end
---```
---@param geo { x: integer?, y: integer, width: integer?, height: integer? } The new location and/or size
function WindowHandle:set_geometry(geo)
self.config_client:unary_request(build_grpc_request_params("SetGeometry", { window_id = self.id, geometry = geo }))
client.unary_request(build_grpc_request_params("SetGeometry", { window_id = self.id, geometry = geo }))
end
---Set this window to fullscreen or not.
---
---### Example
---```lua
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- focused:set_fullscreen(true)
--- focused:set_fullscreen(false)
@ -355,29 +349,27 @@ end
---
---@param fullscreen boolean
function WindowHandle:set_fullscreen(fullscreen)
self.config_client:unary_request(
build_grpc_request_params("SetFullscreen", { window_id = self.id, set = fullscreen })
)
client.unary_request(build_grpc_request_params("SetFullscreen", { window_id = self.id, set = fullscreen }))
end
---Toggle this window to and from fullscreen.
---
---### Example
---```lua
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- focused:toggle_fullscreen()
---end
---```
function WindowHandle:toggle_fullscreen()
self.config_client:unary_request(build_grpc_request_params("SetFullscreen", { window_id = self.id, toggle = {} }))
client.unary_request(build_grpc_request_params("SetFullscreen", { window_id = self.id, toggle = {} }))
end
---Set this window to maximized or not.
---
---### Example
---```lua
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- focused:set_maximized(true)
--- focused:set_maximized(false)
@ -386,29 +378,27 @@ end
---
---@param maximized boolean
function WindowHandle:set_maximized(maximized)
self.config_client:unary_request(
build_grpc_request_params("SetMaximized", { window_id = self.id, set = maximized })
)
client.unary_request(build_grpc_request_params("SetMaximized", { window_id = self.id, set = maximized }))
end
---Toggle this window to and from maximized.
---
---### Example
---```lua
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- focused:toggle_maximized()
---end
---```
function WindowHandle:toggle_maximized()
self.config_client:unary_request(build_grpc_request_params("SetMaximized", { window_id = self.id, toggle = {} }))
client.unary_request(build_grpc_request_params("SetMaximized", { window_id = self.id, toggle = {} }))
end
---Set this window to floating or not.
---
---### Example
---```lua
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- focused:set_floating(true)
--- focused:set_floating(false)
@ -417,20 +407,20 @@ end
---
---@param floating boolean
function WindowHandle:set_floating(floating)
self.config_client:unary_request(build_grpc_request_params("SetFloating", { window_id = self.id, set = floating }))
client.unary_request(build_grpc_request_params("SetFloating", { window_id = self.id, set = floating }))
end
---Toggle this window to and from floating.
---
---### Example
---```lua
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- focused:toggle_floating()
---end
---```
function WindowHandle:toggle_floating()
self.config_client:unary_request(build_grpc_request_params("SetFloating", { window_id = self.id, toggle = {} }))
client.unary_request(build_grpc_request_params("SetFloating", { window_id = self.id, toggle = {} }))
end
---Move this window to the specified tag.
@ -440,15 +430,15 @@ end
---### Example
---```lua
--- -- Assume the focused output has the tag "Tag"
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- focused:move_to_tag(Tag:get("Tag"))
--- focused:move_to_tag(Tag.get("Tag"))
---end
---```
---
---@param tag TagHandle The tag to move this window to
function WindowHandle:move_to_tag(tag)
self.config_client:unary_request(build_grpc_request_params("MoveToTag", { window_id = self.id, tag_id = tag.id }))
client.unary_request(build_grpc_request_params("MoveToTag", { window_id = self.id, tag_id = tag.id }))
end
---Tag or untag the given tag on this window.
@ -456,9 +446,9 @@ end
---### Example
---```lua
--- -- Assume the focused output has the tag "Tag"
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- local tag = Tag:get("Tag")
--- local tag = Tag.get("Tag")
---
--- focused:set_tag(tag, true)
--- -- `focused` now has tag "Tag"
@ -470,9 +460,7 @@ end
---@param tag TagHandle The tag to set or unset
---@param set boolean
function WindowHandle:set_tag(tag, set)
self.config_client:unary_request(
build_grpc_request_params("SetTag", { window_id = self.id, tag_id = tag.id, set = set })
)
client.unary_request(build_grpc_request_params("SetTag", { window_id = self.id, tag_id = tag.id, set = set }))
end
---Toggle the given tag on this window.
@ -480,9 +468,9 @@ end
---### Example
---```lua
--- -- Assume the focused output has the tag "Tag"
---local focused = Window:get_focused()
---local focused = Window.get_focused()
---if focused then
--- local tag = Tag:get("Tag")
--- local tag = Tag.get("Tag")
--- focused:set_tag(tag, false)
---
--- focused:toggle_tag(tag)
@ -494,9 +482,7 @@ end
---
---@param tag TagHandle The tag to toggle
function WindowHandle:toggle_tag(tag)
self.config_client:unary_request(
build_grpc_request_params("SetTag", { window_id = self.id, tag_id = tag.id, toggle = {} })
)
client.unary_request(build_grpc_request_params("SetTag", { window_id = self.id, tag_id = tag.id, toggle = {} }))
end
---@class WindowProperties
@ -512,13 +498,11 @@ end
---
---@return WindowProperties
function WindowHandle:props()
local response =
self.config_client:unary_request(build_grpc_request_params("GetProperties", { window_id = self.id }))
local response = client.unary_request(build_grpc_request_params("GetProperties", { window_id = self.id }))
response.fullscreen_or_maximized = _fullscreen_or_maximized_keys[response.fullscreen_or_maximized]
response.tags = response.tag_ids
and require("pinnacle.tag").handle.new_from_table(self.config_client, response.tag_ids)
response.tags = response.tag_ids and require("pinnacle.tag").handle.new_from_table(response.tag_ids)
response.tag_ids = nil
return response
@ -587,27 +571,13 @@ function WindowHandle:tags()
return self:props().tags
end
---@nodoc
---@param config_client Client
---@return Window
function window.new(config_client)
---@type Window
local self = {
config_client = config_client,
}
setmetatable(self, { __index = Window })
return self
end
---@nodoc
---Create a new `WindowHandle` from an id.
---@param config_client Client
---@param window_id integer
---@return WindowHandle
function window_handle.new(config_client, window_id)
function window_handle.new(window_id)
---@type WindowHandle
local self = {
config_client = config_client,
id = window_id,
}
setmetatable(self, { __index = WindowHandle })
@ -615,16 +585,15 @@ function window_handle.new(config_client, window_id)
end
---@nodoc
---@param config_client Client
---@param window_ids integer[]
---
---@return WindowHandle[]
function window_handle.new_from_table(config_client, window_ids)
function window_handle.new_from_table(window_ids)
---@type WindowHandle[]
local handles = {}
for _, id in ipairs(window_ids) do
table.insert(handles, window_handle.new(config_client, id))
table.insert(handles, window_handle.new(id))
end
return handles