mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-18 22:26:12 +01:00
Change config objects to modules
This commit is contained in:
parent
8f73819aed
commit
fa2eed1adc
8 changed files with 284 additions and 376 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 })
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue