mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-27 21:58:18 +01:00
Merge pull request #106 from pinnacle-comp/api_renaming
Make Lua API more nil-safe
This commit is contained in:
commit
36261d146b
13 changed files with 485 additions and 582 deletions
|
@ -60,13 +60,7 @@ require("pinnacle").setup(function(pinnacle)
|
|||
|
||||
-- mod_key + Alt + c closes the focused window
|
||||
input.keybind({ mod_key, "Alt" }, keys.c, function()
|
||||
-- The commented out line may crash the config process if you have no windows open.
|
||||
-- There is no nil warning here due to limitations in Lua LS type checking, so check for nil as shown below.
|
||||
-- window.get_focused():close()
|
||||
local win = window.get_focused()
|
||||
if win ~= nil then
|
||||
win:close()
|
||||
end
|
||||
window.get_focused():close()
|
||||
end)
|
||||
|
||||
-- mod_key + return spawns a terminal
|
||||
|
@ -78,26 +72,17 @@ require("pinnacle").setup(function(pinnacle)
|
|||
|
||||
-- mod_key + Alt + Space toggle floating on the focused window
|
||||
input.keybind({ mod_key, "Alt" }, keys.space, function()
|
||||
local win = window.get_focused()
|
||||
if win ~= nil then
|
||||
win:toggle_floating()
|
||||
end
|
||||
window.get_focused():toggle_floating()
|
||||
end)
|
||||
|
||||
-- mod_key + f toggles fullscreen on the focused window
|
||||
input.keybind({ mod_key }, keys.f, function()
|
||||
local win = window.get_focused()
|
||||
if win ~= nil then
|
||||
win:toggle_fullscreen()
|
||||
end
|
||||
window.get_focused():toggle_fullscreen()
|
||||
end)
|
||||
|
||||
-- mod_key + m toggles maximized on the focused window
|
||||
input.keybind({ mod_key }, keys.m, function()
|
||||
local win = window.get_focused()
|
||||
if win ~= nil then
|
||||
win:toggle_maximized()
|
||||
end
|
||||
window.get_focused():toggle_maximized()
|
||||
end)
|
||||
|
||||
-- Tags ---------------------------------------------------------------------------
|
||||
|
@ -161,11 +146,11 @@ require("pinnacle").setup(function(pinnacle)
|
|||
end)
|
||||
-- mod_key + Alt + 1-5 moves windows to tags
|
||||
input.keybind({ mod_key, "Alt" }, tag_name, function()
|
||||
local _ = window.get_focused() and window:get_focused():move_to_tag(tag_name)
|
||||
window:get_focused():move_to_tag(tag_name)
|
||||
end)
|
||||
-- mod_key + Shift + Alt + 1-5 toggles tags on windows
|
||||
input.keybind({ mod_key, "Shift", "Alt" }, tag_name, function()
|
||||
local _ = window.get_focused() and window.get_focused():toggle_tag(tag_name)
|
||||
window.get_focused():toggle_tag(tag_name)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
|
|
@ -61,14 +61,14 @@
|
|||
---@field Spawn { stdout: string?, stderr: string?, exit_code: integer?, exit_msg: string? }?
|
||||
---@field ConnectForAllOutputs { output_name: string }?
|
||||
|
||||
---@alias WindowId integer
|
||||
---@alias TagId integer
|
||||
---@alias WindowId integer | "None"
|
||||
---@alias TagId integer | "None"
|
||||
---@alias RequestId integer
|
||||
---@alias OutputName string
|
||||
|
||||
---@class RequestResponse
|
||||
--Windows
|
||||
---@field Window { window_id: WindowId|nil }?
|
||||
---@field Window { window_id: WindowId }?
|
||||
---@field Windows { window_ids: WindowId[] }?
|
||||
---@field WindowProps { size: integer[]?, loc: integer[]?, class: string?, title: string?, focused: boolean?, floating: boolean?, fullscreen_or_maximized: FullscreenOrMaximized? }?
|
||||
--Outputs
|
||||
|
|
|
@ -7,40 +7,40 @@
|
|||
---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 OutputModule
|
||||
local output_module = {}
|
||||
|
||||
---An output object.
|
||||
---
|
||||
---This is a representation of your actual output to the config process.
|
||||
---It serves to make it easier to deal with your outputs, defining methods for getting properties and
|
||||
---helpers for things like positioning multiple monitors.
|
||||
---
|
||||
---This can be retrieved through that various `get` functions in the `OutputModule`.
|
||||
---@classmod
|
||||
---@class Output A display.
|
||||
---@field private _name string The name of this output (or rather, of its connector).
|
||||
---@class Output
|
||||
local output = {}
|
||||
|
||||
---@param params Output|string
|
||||
---@return Output|nil
|
||||
---An output handle.
|
||||
---
|
||||
---This is a handle to one of your monitors.
|
||||
---It serves to make it easier to deal with them, defining methods for getting properties and
|
||||
---helpers for things like positioning multiple monitors.
|
||||
---
|
||||
---This can be retrieved through the various `get` functions in the `Output` module.
|
||||
---@classmod
|
||||
---@class OutputHandle A handle to a display.
|
||||
---@field private _name OutputName The name of this output (or rather, of its connector).
|
||||
local output_handle = {}
|
||||
|
||||
---@param params OutputHandle|string
|
||||
---@return OutputHandle
|
||||
local function create_output_from_params(params)
|
||||
if type(params) == "table" then
|
||||
return params
|
||||
end
|
||||
|
||||
return output_module.get_by_name(params --[[@as string]])
|
||||
return output.get_by_name(params --[[@as string]])
|
||||
end
|
||||
|
||||
---Create a new output object from a name.
|
||||
---Create a new output handle from a name.
|
||||
---The name is the unique identifier for each output.
|
||||
---@param name string
|
||||
---@return Output
|
||||
---@return OutputHandle
|
||||
local function create_output(name)
|
||||
---@type Output
|
||||
---@type OutputHandle
|
||||
local o = { _name = name }
|
||||
-- Copy functions over
|
||||
for k, v in pairs(output) do
|
||||
for k, v in pairs(output_handle) do
|
||||
o[k] = v
|
||||
end
|
||||
|
||||
|
@ -49,73 +49,73 @@ end
|
|||
|
||||
---Get this output's name. This is something like "eDP-1" or "HDMI-A-0".
|
||||
---@return string
|
||||
function output:name()
|
||||
function output_handle:name()
|
||||
return self._name
|
||||
end
|
||||
|
||||
---Get all tags on this output.
|
||||
---@return Tag[]
|
||||
---@see OutputModule.tags — The corresponding module function
|
||||
function output:tags()
|
||||
return output_module.tags(self)
|
||||
---@return TagHandle[]
|
||||
---@see Output.tags — The corresponding module function
|
||||
function output_handle:tags()
|
||||
return output.tags(self)
|
||||
end
|
||||
|
||||
---Add tags to this output.
|
||||
---@param ... string The names of the tags you want to add. You can also pass in a table.
|
||||
---@overload fun(self: self, tag_names: string[])
|
||||
---@see OutputModule.add_tags — The corresponding module function
|
||||
function output:add_tags(...)
|
||||
output_module.add_tags(self, ...)
|
||||
---@see Output.add_tags — The corresponding module function
|
||||
function output_handle:add_tags(...)
|
||||
output.add_tags(self, ...)
|
||||
end
|
||||
|
||||
---Get this output's make.
|
||||
---@return string|nil
|
||||
---@see OutputModule.make — The corresponding module function
|
||||
function output:make()
|
||||
return output_module.make(self)
|
||||
---@see Output.make — The corresponding module function
|
||||
function output_handle:make()
|
||||
return output.make(self)
|
||||
end
|
||||
|
||||
---Get this output's model.
|
||||
---@return string|nil
|
||||
---@see OutputModule.model — The corresponding module function
|
||||
function output:model()
|
||||
return output_module.model(self)
|
||||
---@see Output.model — The corresponding module function
|
||||
function output_handle:model()
|
||||
return output.model(self)
|
||||
end
|
||||
|
||||
---Get this output's location in the global space, in pixels.
|
||||
---@return { x: integer, y: integer }|nil
|
||||
---@see OutputModule.loc — The corresponding module function
|
||||
function output:loc()
|
||||
return output_module.loc(self)
|
||||
---@see Output.loc — The corresponding module function
|
||||
function output_handle:loc()
|
||||
return output.loc(self)
|
||||
end
|
||||
|
||||
---Get this output's resolution in pixels.
|
||||
---@return { w: integer, h: integer }|nil
|
||||
---@see OutputModule.res — The corresponding module function
|
||||
function output:res()
|
||||
return output_module.res(self)
|
||||
---@see Output.res — The corresponding module function
|
||||
function output_handle:res()
|
||||
return output.res(self)
|
||||
end
|
||||
|
||||
---Get this output's refresh rate in millihertz.
|
||||
---For example, 60Hz will be returned as 60000.
|
||||
---@return integer|nil
|
||||
---@see OutputModule.refresh_rate — The corresponding module function
|
||||
function output:refresh_rate()
|
||||
return output_module.refresh_rate(self)
|
||||
---@see Output.refresh_rate — The corresponding module function
|
||||
function output_handle:refresh_rate()
|
||||
return output.refresh_rate(self)
|
||||
end
|
||||
|
||||
---Get this output's physical size in millimeters.
|
||||
---@return { w: integer, h: integer }|nil
|
||||
---@see OutputModule.physical_size — The corresponding module function
|
||||
function output:physical_size()
|
||||
return output_module.physical_size(self)
|
||||
---@see Output.physical_size — The corresponding module function
|
||||
function output_handle:physical_size()
|
||||
return output.physical_size(self)
|
||||
end
|
||||
|
||||
---Get whether or not this output is focused. This is currently defined as having the cursor on it.
|
||||
---@return boolean|nil
|
||||
---@see OutputModule.focused — The corresponding module function
|
||||
function output:focused()
|
||||
return output_module.focused(self)
|
||||
---@see Output.focused — The corresponding module function
|
||||
function output_handle:focused()
|
||||
return output.focused(self)
|
||||
end
|
||||
|
||||
---Set this output's location.
|
||||
|
@ -139,8 +139,8 @@ end
|
|||
---dp2:set_loc({ x = 2560, y = 1440 - 1080 })
|
||||
---```
|
||||
---@param loc { x: integer?, y: integer? }
|
||||
function output:set_loc(loc)
|
||||
output_module.set_loc(self, loc)
|
||||
function output_handle:set_loc(loc)
|
||||
output.set_loc(self, loc)
|
||||
end
|
||||
|
||||
-- TODO: move this into own file or something ---------------------------------------------
|
||||
|
@ -155,8 +155,8 @@ end
|
|||
---| "center" Center the outputs vertically
|
||||
---| "right" Align the right edges of the outputs
|
||||
|
||||
---@param op1 Output
|
||||
---@param op2 Output
|
||||
---@param op1 OutputHandle
|
||||
---@param op2 OutputHandle
|
||||
---@param left_or_right "left" | "right"
|
||||
---@param alignment AlignmentVertical? How you want to align the `self` output. Defaults to `top`.
|
||||
local function set_loc_horizontal(op1, op2, left_or_right, alignment)
|
||||
|
@ -179,11 +179,11 @@ local function set_loc_horizontal(op1, op2, left_or_right, alignment)
|
|||
end
|
||||
|
||||
if alignment == "top" then
|
||||
output_module.set_loc(op1, { x = x, y = other_loc.y })
|
||||
output.set_loc(op1, { x = x, y = other_loc.y })
|
||||
elseif alignment == "center" then
|
||||
output_module.set_loc(op1, { x = x, y = other_loc.y + (other_res.h - self_res.h) // 2 })
|
||||
output.set_loc(op1, { x = x, y = other_loc.y + (other_res.h - self_res.h) // 2 })
|
||||
elseif alignment == "bottom" then
|
||||
output_module.set_loc(op1, { x = x, y = other_loc.y + (other_res.h - self_res.h) })
|
||||
output.set_loc(op1, { x = x, y = other_loc.y + (other_res.h - self_res.h) })
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -198,10 +198,10 @@ end
|
|||
--- └────────┘ └────────┘ └────────┴──────┘
|
||||
---```
|
||||
---This will fail if `op` is an invalid output.
|
||||
---@param op Output
|
||||
---@param op OutputHandle
|
||||
---@param alignment AlignmentVertical? How you want to align the `self` output. Defaults to `top`.
|
||||
---@see Output.set_loc if you need more granular control
|
||||
function output:set_loc_right_of(op, alignment)
|
||||
---@see OutputHandle.set_loc if you need more granular control
|
||||
function output_handle:set_loc_right_of(op, alignment)
|
||||
set_loc_horizontal(self, op, "right", alignment)
|
||||
end
|
||||
|
||||
|
@ -216,15 +216,15 @@ end
|
|||
--- └────────┘ └────────┘ └──────┴────────┘
|
||||
---```
|
||||
---This will fail if `op` is an invalid output.
|
||||
---@param op Output
|
||||
---@param op OutputHandle
|
||||
---@param alignment AlignmentVertical? How you want to align the `self` output. Defaults to `top`.
|
||||
---@see Output.set_loc if you need more granular control
|
||||
function output:set_loc_left_of(op, alignment)
|
||||
---@see OutputHandle.set_loc if you need more granular control
|
||||
function output_handle:set_loc_left_of(op, alignment)
|
||||
set_loc_horizontal(self, op, "left", alignment)
|
||||
end
|
||||
|
||||
---@param op1 Output
|
||||
---@param op2 Output
|
||||
---@param op1 OutputHandle
|
||||
---@param op2 OutputHandle
|
||||
---@param top_or_bottom "top" | "bottom"
|
||||
---@param alignment AlignmentHorizontal? How you want to align the `self` output. Defaults to `top`.
|
||||
local function set_loc_vertical(op1, op2, top_or_bottom, alignment)
|
||||
|
@ -247,11 +247,11 @@ local function set_loc_vertical(op1, op2, top_or_bottom, alignment)
|
|||
end
|
||||
|
||||
if alignment == "left" then
|
||||
output_module.set_loc(op1, { x = other_loc.x, y = y })
|
||||
output.set_loc(op1, { x = other_loc.x, y = y })
|
||||
elseif alignment == "center" then
|
||||
output_module.set_loc(op1, { x = other_loc.x + (other_res.w - self_res.w) // 2, y = y })
|
||||
output.set_loc(op1, { x = other_loc.x + (other_res.w - self_res.w) // 2, y = y })
|
||||
elseif alignment == "right" then
|
||||
output_module.set_loc(op1, { x = other_loc.x + (other_res.w - self_res.w), y = y })
|
||||
output.set_loc(op1, { x = other_loc.x + (other_res.w - self_res.w), y = y })
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -267,10 +267,10 @@ end
|
|||
--- └────────┘ └────────┘ └────────┘
|
||||
---```
|
||||
---This will fail if `op` is an invalid output.
|
||||
---@param op Output
|
||||
---@param op OutputHandle
|
||||
---@param alignment AlignmentHorizontal? How you want to align the `self` output. Defaults to `left`.
|
||||
---@see Output.set_loc if you need more granular control
|
||||
function output:set_loc_top_of(op, alignment)
|
||||
---@see OutputHandle.set_loc if you need more granular control
|
||||
function output_handle:set_loc_top_of(op, alignment)
|
||||
set_loc_vertical(self, op, "top", alignment)
|
||||
end
|
||||
|
||||
|
@ -286,10 +286,10 @@ end
|
|||
--- left center right
|
||||
---```
|
||||
---This will fail if `op` is an invalid output.
|
||||
---@param op Output
|
||||
---@param op OutputHandle
|
||||
---@param alignment AlignmentHorizontal? How you want to align the `self` output. Defaults to `left`.
|
||||
---@see Output.set_loc if you need more granular control
|
||||
function output:set_loc_bottom_of(op, alignment)
|
||||
---@see OutputHandle.set_loc if you need more granular control
|
||||
function output_handle:set_loc_bottom_of(op, alignment)
|
||||
set_loc_vertical(self, op, "bottom", alignment)
|
||||
end
|
||||
|
||||
|
@ -307,8 +307,8 @@ end
|
|||
---print(monitor:name()) -- should print `DP-1`
|
||||
---```
|
||||
---@param name string The name of the output.
|
||||
---@return Output|nil output The output, or nil if none have the provided name.
|
||||
function output_module.get_by_name(name)
|
||||
---@return OutputHandle output The output. If it doesn't exist, a dummy handle with the name "" will be returned.
|
||||
function output.get_by_name(name)
|
||||
local response = Request("GetOutputs")
|
||||
local output_names = response.RequestResponse.response.Outputs.output_names
|
||||
|
||||
|
@ -318,20 +318,23 @@ function output_module.get_by_name(name)
|
|||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
return create_output("")
|
||||
end
|
||||
|
||||
---Note: This may or may not be what is reported by other monitor listing utilities. Pinnacle currently fails to pick up one of my monitors' models when it is correctly picked up by tools like wlr-randr. I'll fix this in the future.
|
||||
---
|
||||
---Get outputs by their model.
|
||||
---
|
||||
---Note: This may or may not be what is reported by other monitor listing utilities.
|
||||
---Pinnacle currently fails to pick up one of my monitor's models when it is correctly
|
||||
---picked up by tools like wlr-randr. I'll fix this in the future.
|
||||
---
|
||||
---This is something like "DELL E2416H" or whatever gibberish monitor manufacturers call their displays.
|
||||
---@param model string The model of the output(s).
|
||||
---@return Output[] outputs All outputs with this model.
|
||||
function output_module.get_by_model(model)
|
||||
---@return OutputHandle[] outputs All outputs with this model.
|
||||
function output.get_by_model(model)
|
||||
local response = Request("GetOutputs")
|
||||
local output_names = response.RequestResponse.response.Outputs.output_names
|
||||
|
||||
---@type Output[]
|
||||
---@type OutputHandle[]
|
||||
local outputs = {}
|
||||
for _, output_name in pairs(output_names) do
|
||||
local o = create_output(output_name)
|
||||
|
@ -347,13 +350,13 @@ end
|
|||
---
|
||||
---@param width integer The width of the outputs, in pixels.
|
||||
---@param height integer The height of the outputs, in pixels.
|
||||
---@return Output[] outputs All outputs with this resolution.
|
||||
function output_module.get_by_res(width, height)
|
||||
---@return OutputHandle[] outputs All outputs with this resolution.
|
||||
function output.get_by_res(width, height)
|
||||
local response = Request("GetOutputs")
|
||||
|
||||
local output_names = response.RequestResponse.response.Outputs.output_names
|
||||
|
||||
---@type Output[]
|
||||
---@type OutputHandle[]
|
||||
local outputs = {}
|
||||
for _, output_name in pairs(output_names) do
|
||||
local o = create_output(output_name)
|
||||
|
@ -367,25 +370,9 @@ end
|
|||
|
||||
---Get the currently focused output. This is currently implemented as the one with the cursor on it.
|
||||
---
|
||||
---This function may return nil, which means you may get a warning if you try to use it without checking for nil.
|
||||
---Usually this function will not be nil unless you unplug all monitors, so instead of checking,
|
||||
---you can ignore the warning by either forcing the type to be non-nil with an inline comment:
|
||||
---```lua
|
||||
---local op = output.get_focused() --[[@as Output]]
|
||||
---```
|
||||
---or by disabling nil check warnings for the line:
|
||||
---```lua
|
||||
---local op = output.get_focused()
|
||||
------@diagnostic disable-next-line:need-check-nil
|
||||
---local tags_on_output = op:tags()
|
||||
---```
|
||||
---Type checking done by Lua LS isn't perfect.
|
||||
---Note that directly using the result of this function inline will *not* raise a warning, so be careful.
|
||||
---```lua
|
||||
---local tags = output.get_focused():tags() -- will NOT warn for nil
|
||||
---```
|
||||
---@return Output|nil output The output, or nil if none are focused.
|
||||
function output_module.get_focused()
|
||||
---If you have no outputs plugged in, this will return a dummy `OutputHandle` with the name "".
|
||||
---@return OutputHandle output The output, or a dummy handle if none are focused.
|
||||
function output.get_focused()
|
||||
local response = Request("GetOutputs")
|
||||
local output_names = response.RequestResponse.response.Outputs.output_names
|
||||
|
||||
|
@ -396,7 +383,7 @@ function output_module.get_focused()
|
|||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
return create_output("")
|
||||
end
|
||||
|
||||
---Connect a function to be run on all current and future outputs.
|
||||
|
@ -410,9 +397,10 @@ end
|
|||
---This is intended to prevent duplicate setup.
|
||||
---
|
||||
---Please note: this function will be run *after* Pinnacle processes your entire config.
|
||||
---For example, if you define tags in `func` but toggle them directly after `connect_for_all`, nothing will happen as the tags haven't been added yet.
|
||||
---@param func fun(output: Output) The function that will be run.
|
||||
function output_module.connect_for_all(func)
|
||||
---For example, if you define tags in `func` but toggle them directly after `connect_for_all`,
|
||||
---nothing will happen as the tags haven't been added yet.
|
||||
---@param func fun(output: OutputHandle) The function that will be run.
|
||||
function output.connect_for_all(func)
|
||||
---@param args Args
|
||||
table.insert(CallbackTable, function(args)
|
||||
local args = args.ConnectForAllOutputs
|
||||
|
@ -426,11 +414,11 @@ function output_module.connect_for_all(func)
|
|||
end
|
||||
|
||||
---Get the output the specified tag is on.
|
||||
---@param tag Tag
|
||||
---@return Output|nil
|
||||
---@see TagModule.output — A global method for fully qualified syntax (for you Rustaceans out there)
|
||||
---@see Tag.output — The corresponding object method
|
||||
function output_module.get_for_tag(tag)
|
||||
---@param tag TagHandle
|
||||
---@return OutputHandle
|
||||
---@see Tag.output — A global method for fully qualified syntax (for you Rustaceans out there)
|
||||
---@see TagHandle.output — The corresponding object method
|
||||
function output.get_for_tag(tag)
|
||||
local response = Request({
|
||||
GetTagProps = {
|
||||
tag_id = tag:id(),
|
||||
|
@ -438,26 +426,18 @@ function output_module.get_for_tag(tag)
|
|||
})
|
||||
local output_name = response.RequestResponse.response.TagProps.output_name
|
||||
|
||||
if output_name == nil then
|
||||
return nil
|
||||
else
|
||||
return create_output(output_name)
|
||||
end
|
||||
return create_output(output_name or "")
|
||||
end
|
||||
|
||||
---------Fully-qualified functions
|
||||
|
||||
---Get the specified output's make.
|
||||
---@param op Output|string The name of the output or an output object.
|
||||
---@param op OutputHandle|string The name of the output or an output handle.
|
||||
---@return string|nil
|
||||
---@see Output.make — The corresponding object method
|
||||
function output_module.make(op)
|
||||
---@see OutputHandle.make — The corresponding object method
|
||||
function output.make(op)
|
||||
local op = create_output_from_params(op)
|
||||
|
||||
if op == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local response = Request({
|
||||
GetOutputProps = {
|
||||
output_name = op:name(),
|
||||
|
@ -468,16 +448,12 @@ function output_module.make(op)
|
|||
end
|
||||
|
||||
---Get the specified output's model.
|
||||
---@param op Output|string The name of the output or an output object.
|
||||
---@param op OutputHandle|string The name of the output or an output object.
|
||||
---@return string|nil
|
||||
---@see Output.model — The corresponding object method
|
||||
function output_module.model(op)
|
||||
---@see OutputHandle.model — The corresponding object method
|
||||
function output.model(op)
|
||||
local op = create_output_from_params(op)
|
||||
|
||||
if op == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local response = Request({
|
||||
GetOutputProps = {
|
||||
output_name = op:name(),
|
||||
|
@ -488,16 +464,12 @@ function output_module.model(op)
|
|||
end
|
||||
|
||||
---Get the specified output's location in the global space, in pixels.
|
||||
---@param op Output|string The name of the output or an output object.
|
||||
---@param op OutputHandle|string The name of the output or an output object.
|
||||
---@return { x: integer, y: integer }|nil
|
||||
---@see Output.loc — The corresponding object method
|
||||
function output_module.loc(op)
|
||||
---@see OutputHandle.loc — The corresponding object method
|
||||
function output.loc(op)
|
||||
local op = create_output_from_params(op)
|
||||
|
||||
if op == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local response = Request({
|
||||
GetOutputProps = {
|
||||
output_name = op:name(),
|
||||
|
@ -512,16 +484,12 @@ function output_module.loc(op)
|
|||
end
|
||||
|
||||
---Get the specified output's resolution in pixels.
|
||||
---@param op Output|string The name of the output or an output object.
|
||||
---@param op OutputHandle|string The name of the output or an output object.
|
||||
---@return { w: integer, h: integer }|nil
|
||||
---@see Output.res — The corresponding object method
|
||||
function output_module.res(op)
|
||||
---@see OutputHandle.res — The corresponding object method
|
||||
function output.res(op)
|
||||
local op = create_output_from_params(op)
|
||||
|
||||
if op == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local response = Request({
|
||||
GetOutputProps = {
|
||||
output_name = op:name(),
|
||||
|
@ -537,16 +505,12 @@ end
|
|||
|
||||
---Get the specified output's refresh rate in millihertz.
|
||||
---For example, 60Hz will be returned as 60000.
|
||||
---@param op Output|string The name of the output or an output object.
|
||||
---@param op OutputHandle|string The name of the output or an output object.
|
||||
---@return integer|nil
|
||||
---@see Output.refresh_rate — The corresponding object method
|
||||
function output_module.refresh_rate(op)
|
||||
---@see OutputHandle.refresh_rate — The corresponding object method
|
||||
function output.refresh_rate(op)
|
||||
local op = create_output_from_params(op)
|
||||
|
||||
if op == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local response = Request({
|
||||
GetOutputProps = {
|
||||
output_name = op:name(),
|
||||
|
@ -557,16 +521,12 @@ function output_module.refresh_rate(op)
|
|||
end
|
||||
|
||||
---Get the specified output's physical size in millimeters.
|
||||
---@param op Output|string The name of the output or an output object.
|
||||
---@param op OutputHandle|string The name of the output or an output object.
|
||||
---@return { w: integer, h: integer }|nil
|
||||
---@see Output.physical_size — The corresponding object method
|
||||
function output_module.physical_size(op)
|
||||
---@see OutputHandle.physical_size — The corresponding object method
|
||||
function output.physical_size(op)
|
||||
local op = create_output_from_params(op)
|
||||
|
||||
if op == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local response = Request({
|
||||
GetOutputProps = {
|
||||
output_name = op:name(),
|
||||
|
@ -581,16 +541,12 @@ function output_module.physical_size(op)
|
|||
end
|
||||
|
||||
---Get whether or not the specified output is focused. This is currently defined as having the cursor on it.
|
||||
---@param op Output|string The name of the output or an output object.
|
||||
---@param op OutputHandle|string The name of the output or an output object.
|
||||
---@return boolean|nil
|
||||
---@see Output.focused — The corresponding object method
|
||||
function output_module.focused(op)
|
||||
---@see OutputHandle.focused — The corresponding object method
|
||||
function output.focused(op)
|
||||
local op = create_output_from_params(op)
|
||||
|
||||
if op == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
local response = Request({
|
||||
GetOutputProps = {
|
||||
output_name = op:name(),
|
||||
|
@ -601,33 +557,25 @@ function output_module.focused(op)
|
|||
end
|
||||
|
||||
---Get the specified output's tags.
|
||||
---@param op Output|string The name of the output or an output object.
|
||||
---@return Tag[]
|
||||
---@see TagModule.get_on_output — The called function
|
||||
---@see Output.tags — The corresponding object method
|
||||
function output_module.tags(op)
|
||||
---@param op OutputHandle|string The name of the output or an output object.
|
||||
---@return TagHandle[]
|
||||
---@see Tag.get_on_output — The called function
|
||||
---@see OutputHandle.tags — The corresponding object method
|
||||
function output.tags(op)
|
||||
local op = create_output_from_params(op)
|
||||
|
||||
if op == nil then
|
||||
return {}
|
||||
end
|
||||
|
||||
return require("tag").get_on_output(op)
|
||||
end
|
||||
|
||||
---Add tags to the specified output.
|
||||
---@param op Output|string The name of the output or an output object.
|
||||
---@param op OutputHandle|string The name of the output or an output object.
|
||||
---@param ... string The names of the tags you want to add. You can also pass in a table.
|
||||
---@overload fun(op: Output|string, tag_names: string[])
|
||||
---@see TagModule.add — The called function
|
||||
---@see Output.add_tags — The corresponding object method
|
||||
function output_module.add_tags(op, ...)
|
||||
---@overload fun(op: OutputHandle|string, tag_names: string[])
|
||||
---@see Tag.add — The called function
|
||||
---@see OutputHandle.add_tags — The corresponding object method
|
||||
function output.add_tags(op, ...)
|
||||
local op = create_output_from_params(op)
|
||||
|
||||
if op == nil then
|
||||
return
|
||||
end
|
||||
|
||||
require("tag").add(op, ...)
|
||||
end
|
||||
|
||||
|
@ -651,15 +599,11 @@ end
|
|||
---output.set_loc(dp1, { x = 0, y = 0 })
|
||||
---output.set_loc(dp2, { x = 2560, y = 1440 - 1080 })
|
||||
---```
|
||||
---@param op Output|string The name of the output or an output object.
|
||||
---@param op OutputHandle|string The name of the output or an output object.
|
||||
---@param loc { x: integer?, y: integer? }
|
||||
function output_module.set_loc(op, loc)
|
||||
function output.set_loc(op, loc)
|
||||
local op = create_output_from_params(op)
|
||||
|
||||
if op == nil then
|
||||
return
|
||||
end
|
||||
|
||||
SendMsg({
|
||||
SetOutputLocation = {
|
||||
output_name = op:name(),
|
||||
|
@ -669,4 +613,4 @@ function output_module.set_loc(op, loc)
|
|||
})
|
||||
end
|
||||
|
||||
return output_module
|
||||
return output
|
||||
|
|
|
@ -72,7 +72,7 @@ local function read_exact(socket_fd, count)
|
|||
return data
|
||||
end
|
||||
|
||||
---@class PinnacleModule
|
||||
---@class Pinnacle
|
||||
---The entry point to all configuration.
|
||||
local pinnacle = {
|
||||
---Key and mouse binds
|
||||
|
@ -92,9 +92,11 @@ function pinnacle.quit()
|
|||
SendMsg("Quit")
|
||||
end
|
||||
|
||||
---Configure Pinnacle. You should put mostly eveything into the config_func to avoid invalid state.
|
||||
---Configure Pinnacle. You should put mostly everything into the config_func to avoid invalid state.
|
||||
---The function takes one argument: the `PinnacleModule` table, which is how you'll access all of the available config options.
|
||||
---@param config_func fun(pinnacle: PinnacleModule)
|
||||
---
|
||||
---You can also just `require` all the individual modules, but hey, they're all passed in anyway; might as well use them!
|
||||
---@param config_func fun(pinnacle: Pinnacle)
|
||||
function pinnacle.setup(config_func)
|
||||
---@type integer
|
||||
local socket_fd = assert(socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0), "Failed to create socket")
|
||||
|
|
209
api/lua/tag.lua
209
api/lua/tag.lua
|
@ -17,22 +17,22 @@
|
|||
--- This is helpful if you, say, want to reference a browser window while coding; you toggle your
|
||||
--- browser's tag and temporarily reference it while you work without having to change screens.
|
||||
---
|
||||
---Many of the functions in this module take Tag|TagTable|TagTableNamed|string.
|
||||
---This is a convenience so you don't have to get a tag object every time you want to do
|
||||
---Many of the functions in this module take `TagConstructor`.
|
||||
---This is a convenience so you don't have to get a tag handle every time you want to do
|
||||
---something with tags.
|
||||
---
|
||||
---Instead, you can pass in either:
|
||||
---
|
||||
--- - A string of the tag's name (ex. "1")
|
||||
--- - This will get the first tag with that name on the focused output.
|
||||
--- - A table where [1] is the name and [2] is the output (or its name) (ex. { "1", output.get_by_name("DP-1") })
|
||||
--- - A table where `name` is the name and `output` is the output (or its name) (ex. { name = "1", output = "DP-1" })
|
||||
--- - This will get the first tag with that name on the specified output.
|
||||
--- - The same table as above, but keyed with `name` and `output` (ex. { name = "1", output = "DP-1" })
|
||||
--- - This is simply for those who want more clarity in their config.
|
||||
--- - A tag handle itself
|
||||
--- - If you already have a tag handle, it will be used directly.
|
||||
---
|
||||
---If you need to get tags beyond the first with the same name, use a `get` function and find what you need.
|
||||
---@class TagModule
|
||||
local tag_module = {}
|
||||
---@class Tag
|
||||
local tag = {}
|
||||
|
||||
---@alias Layout
|
||||
---| "MasterStack" # One master window on the left with all other windows stacked to the right.
|
||||
|
@ -43,27 +43,29 @@ local tag_module = {}
|
|||
---| "CornerBottomLeft" # One main corner window in the bottom left with a column of windows on the right and a row on the top.
|
||||
---| "CornerBottomRight" # One main corner window in the bottom right with a column of windows on the left and a row on the top.
|
||||
|
||||
---@alias TagTable { name: string, output: (string|Output)? }
|
||||
---@alias TagTable { name: string, output: (string|OutputHandle)? }
|
||||
|
||||
---@alias TagConstructor Tag|TagTable|string
|
||||
---@alias TagConstructor TagHandle|TagTable|string
|
||||
|
||||
---A tag object.
|
||||
---A tag handle.
|
||||
---
|
||||
---This can be retrieved through the various `get` functions in the `TagModule`.
|
||||
---This is a handle to a tag that can be passed to windows and such.
|
||||
---
|
||||
---This can be retrieved through the various `get` functions in the `Tag` module.
|
||||
---@classmod
|
||||
---@class Tag
|
||||
---@field private _id integer The internal id of this tag.
|
||||
local tag = {}
|
||||
---@class TagHandle
|
||||
---@field private _id TagId The internal id of this tag.
|
||||
local tag_handle = {}
|
||||
|
||||
---Create a tag from an id.
|
||||
---The id is the unique identifier for each tag.
|
||||
---@param id TagId
|
||||
---@return Tag
|
||||
---@return TagHandle
|
||||
local function create_tag(id)
|
||||
---@type Tag
|
||||
---@type TagHandle
|
||||
local t = { _id = id }
|
||||
-- Copy functions over
|
||||
for k, v in pairs(tag) do
|
||||
for k, v in pairs(tag_handle) do
|
||||
t[k] = v
|
||||
end
|
||||
|
||||
|
@ -72,49 +74,49 @@ end
|
|||
|
||||
---Get this tag's internal id.
|
||||
---***You probably won't need to use this.***
|
||||
---@return integer
|
||||
function tag:id()
|
||||
---@return TagId
|
||||
function tag_handle:id()
|
||||
return self._id
|
||||
end
|
||||
|
||||
---Get this tag's active status.
|
||||
---@return boolean|nil active `true` if the tag is active, `false` if not, and `nil` if the tag doesn't exist.
|
||||
---@see TagModule.active — The corresponding module function
|
||||
function tag:active()
|
||||
return tag_module.active(self)
|
||||
---@see Tag.active — The corresponding module function
|
||||
function tag_handle:active()
|
||||
return tag.active(self)
|
||||
end
|
||||
|
||||
---Get this tag's name.
|
||||
---@return string|nil name The name of this tag, or nil if it doesn't exist.
|
||||
---@see TagModule.name — The corresponding module function
|
||||
function tag:name()
|
||||
return tag_module.name(self)
|
||||
---@see Tag.name — The corresponding module function
|
||||
function tag_handle:name()
|
||||
return tag.name(self)
|
||||
end
|
||||
|
||||
---Get this tag's output.
|
||||
---@return Output|nil output The output this tag is on, or nil if the tag doesn't exist.
|
||||
---@see TagModule.output — The corresponding module function
|
||||
function tag:output()
|
||||
return tag_module.output(self)
|
||||
---@return OutputHandle output The output this tag is on, or a dummy handle if the tag doesn't exist.
|
||||
---@see Tag.output — The corresponding module function
|
||||
function tag_handle:output()
|
||||
return tag.output(self)
|
||||
end
|
||||
|
||||
---Switch to this tag.
|
||||
---@see TagModule.switch_to — The corresponding module function
|
||||
function tag:switch_to()
|
||||
tag_module.switch_to(self)
|
||||
---@see Tag.switch_to — The corresponding module function
|
||||
function tag_handle:switch_to()
|
||||
tag.switch_to(self)
|
||||
end
|
||||
|
||||
---Toggle this tag.
|
||||
---@see TagModule.toggle — The corresponding module function
|
||||
function tag:toggle()
|
||||
tag_module.toggle(self)
|
||||
---@see Tag.toggle — The corresponding module function
|
||||
function tag_handle:toggle()
|
||||
tag.toggle(self)
|
||||
end
|
||||
|
||||
---Set this tag's layout.
|
||||
---@param layout Layout
|
||||
---@see TagModule.set_layout — The corresponding module function
|
||||
function tag:set_layout(layout)
|
||||
tag_module.set_layout(self, layout)
|
||||
---@see Tag.set_layout — The corresponding module function
|
||||
function tag_handle:set_layout(layout)
|
||||
tag.set_layout(self, layout)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------
|
||||
|
@ -127,16 +129,16 @@ end
|
|||
---if op ~= nil then
|
||||
--- tag.add(op, "1", "2", "3", "4", "5") -- Add tags with names 1-5
|
||||
---end
|
||||
--
|
||||
---
|
||||
--- -- You can also pass in a table.
|
||||
---local tags = {"Terminal", "Browser", "Code", "Potato", "Email"}
|
||||
---tag.add(op, tags)
|
||||
---```
|
||||
---@param output Output The output you want these tags to be added to.
|
||||
---@param output OutputHandle The output you want these tags to be added to.
|
||||
---@param ... string The names of the new tags you want to add.
|
||||
---@overload fun(output: Output, tag_names: string[])
|
||||
---@see Output.add_tags — The corresponding object method
|
||||
function tag_module.add(output, ...)
|
||||
---@overload fun(output: OutputHandle, tag_names: string[])
|
||||
---@see OutputHandle.add_tags — The corresponding object method
|
||||
function tag.add(output, ...)
|
||||
local varargs = { ... }
|
||||
if type(varargs[1]) == "string" then
|
||||
local tag_names = varargs
|
||||
|
@ -172,14 +174,14 @@ end
|
|||
---tag.toggle({ name = "1", output = "DP-1" }) -- Toggle tag 1 on "DP-1"
|
||||
---tag.toggle({ name = "1", output = op }) -- Same as above
|
||||
---
|
||||
--- -- Using a tag object
|
||||
---local t = tag.get_by_name("1")[1] -- `t` is the first tag with the name "1"
|
||||
--- -- Using a tag handle
|
||||
---local t = tag.get("1") -- `t` is the tag with the name "1" on the focused output
|
||||
---tag.toggle(t)
|
||||
---```
|
||||
---@param t TagConstructor
|
||||
---@see Tag.toggle — The corresponding object method
|
||||
function tag_module.toggle(t)
|
||||
local t = tag_module.get(t)
|
||||
---@see TagHandle.toggle — The corresponding object method
|
||||
function tag.toggle(t)
|
||||
local t = tag.get(t)
|
||||
|
||||
if t then
|
||||
SendMsg({
|
||||
|
@ -204,14 +206,14 @@ end
|
|||
---tag.switch_to({ name = "1", output = "DP-1" }) -- Switch to tag 1 on "DP-1"
|
||||
---tag.switch_to({ name = "1", output = op }) -- Same as above
|
||||
---
|
||||
--- -- Using a tag object
|
||||
--- -- Using a tag handle
|
||||
---local t = tag.get_by_name("1")[1] -- `t` is the first tag with the name "1"
|
||||
---tag.switch_to(t)
|
||||
---```
|
||||
---@param t TagConstructor
|
||||
---@see Tag.switch_to — The corresponding object method
|
||||
function tag_module.switch_to(t)
|
||||
local t = tag_module.get(t)
|
||||
---@see TagHandle.switch_to — The corresponding object method
|
||||
function tag.switch_to(t)
|
||||
local t = tag.get(t)
|
||||
|
||||
if t then
|
||||
SendMsg({
|
||||
|
@ -233,16 +235,16 @@ end
|
|||
---tag.set_layout({ name = "1", output = "DP-1" }, "Dwindle") -- Set tag 1 on "DP-1" to "Dwindle"
|
||||
---tag.set_layout({ name = "1", output = op }, "Dwindle") -- Same as above
|
||||
---
|
||||
--- -- Using a tag object
|
||||
--- -- Using a tag handle
|
||||
---local t = tag.get_by_name("1")[1] -- `t` is the first tag with the name "1"
|
||||
---tag.set_layout(t, "Dwindle")
|
||||
---```
|
||||
---
|
||||
---@param t TagConstructor
|
||||
---@param layout Layout The layout.
|
||||
---@see Tag.set_layout — The corresponding object method
|
||||
function tag_module.set_layout(t, layout)
|
||||
local t = tag_module.get(t)
|
||||
---@see TagHandle.set_layout — The corresponding object method
|
||||
function tag.set_layout(t, layout)
|
||||
local t = tag.get(t)
|
||||
|
||||
if t then
|
||||
SendMsg({
|
||||
|
@ -265,7 +267,6 @@ end
|
|||
---### Examples
|
||||
---```lua
|
||||
---local t = tag.get("1")
|
||||
---local t = tag.get({ name = "3" })
|
||||
---local t = tag.get({ name = "1", output = "HDMI-A-0" })
|
||||
---
|
||||
---local op = output.get_by_name("DP-2")
|
||||
|
@ -274,32 +275,32 @@ end
|
|||
---end
|
||||
---```
|
||||
---@param params TagConstructor
|
||||
---@return Tag|nil
|
||||
---@return TagHandle
|
||||
---
|
||||
---@see TagModule.get_on_output
|
||||
---@see TagModule.get_by_name
|
||||
---@see TagModule.get_all
|
||||
function tag_module.get(params)
|
||||
---@see Tag.get_on_output — Get all tags on an output
|
||||
---@see Tag.get_by_name — Get all tags with some name
|
||||
---@see Tag.get_all — Get all tags
|
||||
function tag.get(params)
|
||||
-- If creating from a tag object, just return the obj
|
||||
if params.id then
|
||||
return params --[[@as Tag]]
|
||||
return params --[[@as TagHandle]]
|
||||
end
|
||||
|
||||
-- string passed in
|
||||
if type(params) == "string" then
|
||||
local op = require("output").get_focused()
|
||||
if op == nil then
|
||||
return nil
|
||||
return create_tag("None")
|
||||
end
|
||||
|
||||
local tags = tag_module.get_by_name(params)
|
||||
local tags = tag.get_by_name(params)
|
||||
for _, t in pairs(tags) do
|
||||
if t:output() and t:output():name() == op:name() then
|
||||
return t
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
return create_tag("None")
|
||||
end
|
||||
|
||||
-- TagTable was passed in
|
||||
|
@ -310,25 +311,25 @@ function tag_module.get(params)
|
|||
if op == nil then
|
||||
local o = require("output").get_focused()
|
||||
if o == nil then
|
||||
return nil
|
||||
return create_tag("None")
|
||||
end
|
||||
op = o
|
||||
elseif type(op) == "string" then
|
||||
local o = require("output").get_by_name(op)
|
||||
if o == nil then
|
||||
return nil
|
||||
return create_tag("None")
|
||||
end
|
||||
op = o
|
||||
end
|
||||
|
||||
local tags = tag_module.get_by_name(tag_name)
|
||||
local tags = tag.get_by_name(tag_name)
|
||||
for _, t in pairs(tags) do
|
||||
if t:output() and t:output():name() == op:name() then
|
||||
return t
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
return create_tag("None")
|
||||
end
|
||||
|
||||
---Get all tags on the specified output.
|
||||
|
@ -340,11 +341,11 @@ end
|
|||
--- local tags = tag.get_on_output(op) -- All tags on the focused output
|
||||
---end
|
||||
---```
|
||||
---@param output Output
|
||||
---@return Tag[]
|
||||
---@param output OutputHandle
|
||||
---@return TagHandle[]
|
||||
---
|
||||
---@see Output.tags — The corresponding object method
|
||||
function tag_module.get_on_output(output)
|
||||
function tag.get_on_output(output)
|
||||
local response = Request({
|
||||
GetOutputProps = {
|
||||
output_name = output:name(),
|
||||
|
@ -353,7 +354,7 @@ function tag_module.get_on_output(output)
|
|||
|
||||
local tag_ids = response.RequestResponse.response.OutputProps.tag_ids
|
||||
|
||||
---@type Tag[]
|
||||
---@type TagHandle[]
|
||||
local tags = {}
|
||||
|
||||
if tag_ids == nil then
|
||||
|
@ -378,11 +379,11 @@ end
|
|||
--- -- ...will have `no_tags` be empty.
|
||||
---```
|
||||
---@param name string The name of the tag(s) you want.
|
||||
---@return Tag[]
|
||||
function tag_module.get_by_name(name)
|
||||
local t_s = tag_module.get_all()
|
||||
---@return TagHandle[]
|
||||
function tag.get_by_name(name)
|
||||
local t_s = tag.get_all()
|
||||
|
||||
---@type Tag[]
|
||||
---@type TagHandle[]
|
||||
local tags = {}
|
||||
|
||||
for _, t in pairs(t_s) do
|
||||
|
@ -402,13 +403,13 @@ end
|
|||
---local tags = tag.get_all()
|
||||
--- -- ...`tags` should have 10 tags, with 5 pairs of those names across both outputs.
|
||||
---```
|
||||
---@return Tag[]
|
||||
function tag_module.get_all()
|
||||
---@return TagHandle[]
|
||||
function tag.get_all()
|
||||
local response = Request("GetTags")
|
||||
|
||||
local tag_ids = response.RequestResponse.response.Tags.tag_ids
|
||||
|
||||
---@type Tag[]
|
||||
---@type TagHandle[]
|
||||
local tags = {}
|
||||
|
||||
for _, tag_id in pairs(tag_ids) do
|
||||
|
@ -426,10 +427,10 @@ end
|
|||
---print(tag.name(tag.get_by_name("Terminal")[1]))
|
||||
--- -- ...should print `Terminal`.
|
||||
---```
|
||||
---@param t Tag
|
||||
---@param t TagHandle
|
||||
---@return string|nil
|
||||
---@see Tag.name — The corresponding object method
|
||||
function tag_module.name(t)
|
||||
---@see TagHandle.name — The corresponding object method
|
||||
function tag.name(t)
|
||||
local response = Request({
|
||||
GetTagProps = {
|
||||
tag_id = t:id(),
|
||||
|
@ -440,10 +441,10 @@ function tag_module.name(t)
|
|||
end
|
||||
|
||||
---Get whether or not the specified tag is active.
|
||||
---@param t Tag
|
||||
---@param t TagHandle
|
||||
---@return boolean|nil
|
||||
---@see Tag.active — The corresponding object method
|
||||
function tag_module.active(t)
|
||||
---@see TagHandle.active — The corresponding object method
|
||||
function tag.active(t)
|
||||
local response = Request({
|
||||
GetTagProps = {
|
||||
tag_id = t:id(),
|
||||
|
@ -454,34 +455,36 @@ function tag_module.active(t)
|
|||
end
|
||||
|
||||
---Get the output the specified tag is on.
|
||||
---@param t Tag
|
||||
---@return Output|nil
|
||||
---@see OutputModule.get_for_tag — The called function
|
||||
---@see Tag.output — The corresponding object method
|
||||
function tag_module.output(t)
|
||||
---@param t TagHandle
|
||||
---@return OutputHandle
|
||||
---@see Output.get_for_tag — The called function
|
||||
---@see TagHandle.output — The corresponding object method
|
||||
function tag.output(t)
|
||||
return require("output").get_for_tag(t)
|
||||
end
|
||||
|
||||
---@class LayoutCycler
|
||||
---@field next fun(output: (Output|OutputName)?) Change the first active tag on `output` to its next layout. If `output` is empty, the focused output is used.
|
||||
---@field prev fun(output: (Output|OutputName)?) Change the first active tag on `output` to its previous layout. If `output` is empty, the focused output is used.
|
||||
---@field next fun(output: (OutputHandle|OutputName)?) Change the first active tag on `output` to its next layout. If `output` is empty, the focused output is used.
|
||||
---@field prev fun(output: (OutputHandle|OutputName)?) Change the first active tag on `output` to its previous layout. If `output` is empty, the focused output is used.
|
||||
|
||||
---Given an array of layouts, this will create two functions; one will cycle forward the layout
|
||||
---for the provided tag, and one will cycle backward.
|
||||
---Create a `LayoutCycler` to cycle layouts on tags.
|
||||
---
|
||||
---Given an array of layouts, this will create a table with two functions;
|
||||
---one will cycle forward the layout for the active tag, and one will cycle backward.
|
||||
---
|
||||
--- ### Example
|
||||
---```lua
|
||||
---local layout_cycler = tag.layout_cycler({ "Dwindle", "Spiral", "MasterStack" })
|
||||
---
|
||||
---layout_cycler.next() -- Go to the next layout on the first tag of the focused output
|
||||
---layout_cycler.prev() -- Go to the previous layout on the first tag of the focused output
|
||||
---layout_cycler.next() -- Go to the next layout on the first active tag of the focused output
|
||||
---layout_cycler.prev() -- Go to the previous layout on the first active tag of the focused output
|
||||
---
|
||||
---layout_cycler.next("DP-1") -- Do the above but on "DP-1" instead
|
||||
---layout_cycler.prev(output.get_by_name("DP-1")) -- With an output object
|
||||
---layout_cycler.prev(output.get_by_name("DP-1")) -- With an output handle
|
||||
---```
|
||||
---@param layouts Layout[] The available layouts.
|
||||
---@return LayoutCycler layout_cycler A table with the functions `next` and `prev`, which will cycle layouts for the given tag.
|
||||
function tag_module.layout_cycler(layouts)
|
||||
function tag.layout_cycler(layouts)
|
||||
local indices = {}
|
||||
|
||||
-- Return empty functions if layouts is empty
|
||||
|
@ -493,7 +496,7 @@ function tag_module.layout_cycler(layouts)
|
|||
end
|
||||
|
||||
return {
|
||||
---@param output (Output|OutputName)?
|
||||
---@param output (OutputHandle|OutputName)?
|
||||
next = function(output)
|
||||
if type(output) == "string" then
|
||||
output = require("output").get_by_name(output)
|
||||
|
@ -531,7 +534,7 @@ function tag_module.layout_cycler(layouts)
|
|||
end
|
||||
end,
|
||||
|
||||
---@param output (Output|OutputName)?
|
||||
---@param output (OutputHandle|OutputName)?
|
||||
prev = function(output)
|
||||
if type(output) == "string" then
|
||||
output = require("output").get_by_name(output)
|
||||
|
@ -571,4 +574,4 @@ function tag_module.layout_cycler(layouts)
|
|||
}
|
||||
end
|
||||
|
||||
return tag_module
|
||||
return tag
|
||||
|
|
|
@ -18,8 +18,9 @@ require("pinnacle").setup(function(pinnacle)
|
|||
local output = pinnacle.output -- Output management
|
||||
|
||||
-- Every key supported by xkbcommon.
|
||||
-- Support for just putting in a string of a key is intended.
|
||||
local keys = input.keys
|
||||
-- Mouse buttons
|
||||
local buttons = input.buttons
|
||||
|
||||
---@type Modifier
|
||||
local mod_key = "Ctrl" -- This is set to `Ctrl` instead of `Super` to not conflict with your WM/DE keybinds
|
||||
|
@ -27,17 +28,37 @@ require("pinnacle").setup(function(pinnacle)
|
|||
|
||||
local terminal = "alacritty"
|
||||
|
||||
process.set_env("MOZ_ENABLE_WAYLAND", "1")
|
||||
|
||||
-- Outputs -----------------------------------------------------------------------
|
||||
|
||||
-- You can set your own monitor layout as I have done below for my monitors.
|
||||
|
||||
--
|
||||
-- local lg = output.get_by_name("DP-2") --[[@as Output]]
|
||||
-- local dell = output.get_by_name("DP-3") --[[@as Output]]
|
||||
--
|
||||
-- dell:set_loc_left_of(lg, "bottom")
|
||||
|
||||
-- Libinput settings -------------------------------------------------------------
|
||||
-- If you want to change settings like pointer acceleration,
|
||||
-- you can do them in `input.libinput`.
|
||||
--
|
||||
-- input.libinput.set_accel_profile("Flat")
|
||||
|
||||
-- Mousebinds --------------------------------------------------------------------
|
||||
|
||||
input.mousebind({ "Ctrl" }, buttons.left, "Press", function()
|
||||
window.begin_move(buttons.left)
|
||||
end)
|
||||
input.mousebind({ "Ctrl" }, buttons.right, "Press", function()
|
||||
window.begin_resize(buttons.right)
|
||||
end)
|
||||
|
||||
-- Keybinds ----------------------------------------------------------------------
|
||||
|
||||
input.keybind({ mod_key }, keys.t, function()
|
||||
window.get_focused():set_size({ w = 500, h = 500 })
|
||||
end)
|
||||
|
||||
-- mod_key + Alt + q quits the compositor
|
||||
input.keybind({ mod_key, "Alt" }, keys.q, pinnacle.quit)
|
||||
|
||||
|
@ -85,16 +106,40 @@ require("pinnacle").setup(function(pinnacle)
|
|||
|
||||
-- Tags ---------------------------------------------------------------------------
|
||||
|
||||
local tags = { "1", "2", "3", "4", "5" }
|
||||
|
||||
output.connect_for_all(function(op)
|
||||
-- Add tags 1, 2, 3, 4 and 5 on all monitors, and toggle tag 1 active by default
|
||||
|
||||
op:add_tags("1", "2", "3", "4", "5")
|
||||
op:add_tags(tags)
|
||||
-- Same as tag.add(op, "1", "2", "3", "4", "5")
|
||||
tag.toggle({ "1", op })
|
||||
tag.toggle({ name = "1", output = op })
|
||||
|
||||
-- Window rules
|
||||
-- Add your own window rules here. Below is an example.
|
||||
--
|
||||
-- These currently need to be added inside of `connect_for_all` because
|
||||
-- it only runs after the whole config is parsed, so any specified tags won't be available outside
|
||||
-- of this function. This means that if you have multiple monitors,
|
||||
-- these rules will be duplicated unless you write in some logic to prevent that.
|
||||
--
|
||||
-- window.rules.add({
|
||||
-- cond = { class = "kitty" },
|
||||
-- rule = { size = { 300, 300 }, location = { 50, 50 } },
|
||||
-- }, {
|
||||
-- cond = {
|
||||
-- class = "XTerm",
|
||||
-- tag = "4",
|
||||
-- },
|
||||
-- rule = { size = { 500, 800 }, floating_or_tiled = "Floating" },
|
||||
-- })
|
||||
end)
|
||||
|
||||
---@type Layout[]
|
||||
local layouts = {
|
||||
-- Layout cycling
|
||||
|
||||
-- Create a layout cycler to cycle your tag layouts. This will store which layout each tag has
|
||||
-- and change to the next or previous one in the array when the respective function is called.
|
||||
local layout_cycler = tag.layout_cycler({
|
||||
"MasterStack",
|
||||
"Dwindle",
|
||||
"Spiral",
|
||||
|
@ -102,124 +147,29 @@ require("pinnacle").setup(function(pinnacle)
|
|||
"CornerTopRight",
|
||||
"CornerBottomLeft",
|
||||
"CornerBottomRight",
|
||||
}
|
||||
local indices = {}
|
||||
|
||||
-- Window rules
|
||||
window.rules.add({
|
||||
cond = { class = "kitty" },
|
||||
rule = { floating_or_tiled = "Floating" },
|
||||
})
|
||||
|
||||
-- Layout cycling
|
||||
-- Yes, this is overly complicated and yes, I'll cook up a way to make it less so.
|
||||
input.keybind({ mod_key }, keys.space, function()
|
||||
local tags = output.get_focused():tags()
|
||||
for _, tg in pairs(tags) do
|
||||
if tg:active() then
|
||||
local name = tg:name()
|
||||
if name == nil then
|
||||
return
|
||||
end
|
||||
tg:set_layout(layouts[indices[name] or 1])
|
||||
if indices[name] == nil then
|
||||
indices[name] = 2
|
||||
else
|
||||
if indices[name] + 1 > #layouts then
|
||||
indices[name] = 1
|
||||
else
|
||||
indices[name] = indices[name] + 1
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end)
|
||||
input.keybind({ mod_key, "Shift" }, keys.space, function()
|
||||
local tags = output.get_focused():tags()
|
||||
for _, tg in pairs(tags) do
|
||||
if tg:active() then
|
||||
local name = tg:name()
|
||||
if name == nil then
|
||||
return
|
||||
end
|
||||
tg:set_layout(layouts[indices[name] or #layouts])
|
||||
if indices[name] == nil then
|
||||
indices[name] = #layouts - 1
|
||||
else
|
||||
if indices[name] - 1 < 1 then
|
||||
indices[name] = #layouts
|
||||
else
|
||||
indices[name] = indices[name] - 1
|
||||
end
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
end)
|
||||
input.keybind({ mod_key }, keys.space, layout_cycler.next)
|
||||
input.keybind({ mod_key, "Shift" }, keys.space, layout_cycler.prev)
|
||||
|
||||
input.keybind({ mod_key }, keys.KEY_1, function()
|
||||
tag.switch_to("1")
|
||||
end)
|
||||
input.keybind({ mod_key }, keys.KEY_2, function()
|
||||
tag.switch_to("2")
|
||||
end)
|
||||
input.keybind({ mod_key }, keys.KEY_3, function()
|
||||
tag.switch_to("3")
|
||||
end)
|
||||
input.keybind({ mod_key }, keys.KEY_4, function()
|
||||
tag.switch_to("4")
|
||||
end)
|
||||
input.keybind({ mod_key }, keys.KEY_5, function()
|
||||
tag.switch_to("5")
|
||||
end)
|
||||
-- Tag manipulation
|
||||
|
||||
input.keybind({ mod_key, "Shift" }, keys.KEY_1, function()
|
||||
tag.toggle("1")
|
||||
end)
|
||||
input.keybind({ mod_key, "Shift" }, keys.KEY_2, function()
|
||||
tag.toggle("2")
|
||||
end)
|
||||
input.keybind({ mod_key, "Shift" }, keys.KEY_3, function()
|
||||
tag.toggle("3")
|
||||
end)
|
||||
input.keybind({ mod_key, "Shift" }, keys.KEY_4, function()
|
||||
tag.toggle("4")
|
||||
end)
|
||||
input.keybind({ mod_key, "Shift" }, keys.KEY_5, function()
|
||||
tag.toggle("5")
|
||||
end)
|
||||
|
||||
-- I check for nil this way because I don't want stylua to take up like 80 lines on `if win ~= nil`
|
||||
input.keybind({ mod_key, "Alt" }, keys.KEY_1, function()
|
||||
local _ = window.get_focused() and window:get_focused():move_to_tag("1")
|
||||
end)
|
||||
input.keybind({ mod_key, "Alt" }, keys.KEY_2, function()
|
||||
local _ = window.get_focused() and window:get_focused():move_to_tag("2")
|
||||
end)
|
||||
input.keybind({ mod_key, "Alt" }, keys.KEY_3, function()
|
||||
local _ = window.get_focused() and window:get_focused():move_to_tag("3")
|
||||
end)
|
||||
input.keybind({ mod_key, "Alt" }, keys.KEY_4, function()
|
||||
local _ = window.get_focused() and window:get_focused():move_to_tag("4")
|
||||
end)
|
||||
input.keybind({ mod_key, "Alt" }, keys.KEY_5, function()
|
||||
local _ = window.get_focused() and window:get_focused():move_to_tag("5")
|
||||
end)
|
||||
|
||||
input.keybind({ mod_key, "Shift", "Alt" }, keys.KEY_1, function()
|
||||
local _ = window.get_focused() and window.get_focused():toggle_tag("1")
|
||||
end)
|
||||
input.keybind({ mod_key, "Shift", "Alt" }, keys.KEY_2, function()
|
||||
local _ = window.get_focused() and window.get_focused():toggle_tag("2")
|
||||
end)
|
||||
input.keybind({ mod_key, "Shift", "Alt" }, keys.KEY_3, function()
|
||||
local _ = window.get_focused() and window.get_focused():toggle_tag("3")
|
||||
end)
|
||||
input.keybind({ mod_key, "Shift", "Alt" }, keys.KEY_4, function()
|
||||
local _ = window.get_focused() and window.get_focused():toggle_tag("4")
|
||||
end)
|
||||
input.keybind({ mod_key, "Shift", "Alt" }, keys.KEY_5, function()
|
||||
local _ = window.get_focused() and window.get_focused():toggle_tag("5")
|
||||
end)
|
||||
for _, tag_name in pairs(tags) do
|
||||
-- mod_key + 1-5 switches tags
|
||||
input.keybind({ mod_key }, tag_name, function()
|
||||
tag.switch_to(tag_name)
|
||||
end)
|
||||
-- mod_key + Shift + 1-5 toggles tags
|
||||
input.keybind({ mod_key, "Shift" }, tag_name, function()
|
||||
tag.toggle(tag_name)
|
||||
end)
|
||||
-- mod_key + Alt + 1-5 moves windows to tags
|
||||
input.keybind({ mod_key, "Alt" }, tag_name, function()
|
||||
local _ = window.get_focused() and window:get_focused():move_to_tag(tag_name)
|
||||
end)
|
||||
-- mod_key + Shift + Alt + 1-5 toggles tags on windows
|
||||
input.keybind({ mod_key, "Shift", "Alt" }, tag_name, function()
|
||||
local _ = window.get_focused() and window.get_focused():toggle_tag(tag_name)
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
|
|
@ -4,29 +4,32 @@
|
|||
---
|
||||
---This module helps you deal with setting windows to fullscreen and maximized, setting their size,
|
||||
---moving them between tags, and various other actions.
|
||||
---@class WindowModule
|
||||
local window_module = {
|
||||
---@class Window
|
||||
local window = {
|
||||
---Window rules.
|
||||
rules = require("window_rules"),
|
||||
}
|
||||
|
||||
---A window object.
|
||||
---A window handle.
|
||||
---
|
||||
---This is a representation of an application window to the config process.
|
||||
---This is a handle to an application window that allows manipulation of the window.
|
||||
---
|
||||
---You can retrieve windows through the various `get` function in the `WindowModule`.
|
||||
---If the window is destroyed, the handle will become invalid and may not do
|
||||
---what you want it to.
|
||||
---
|
||||
---You can retrieve window handles through the various `get` functions in the `Window` module.
|
||||
---@classmod
|
||||
---@class Window
|
||||
---@field private _id integer The internal id of this window
|
||||
local window = {}
|
||||
---@class WindowHandle
|
||||
---@field private _id WindowId The internal id of this window
|
||||
local window_handle = {}
|
||||
|
||||
---@param window_id WindowId
|
||||
---@return Window
|
||||
---@return WindowHandle
|
||||
local function create_window(window_id)
|
||||
---@type Window
|
||||
---@type WindowHandle
|
||||
local w = { _id = window_id }
|
||||
-- Copy functions over
|
||||
for k, v in pairs(window) do
|
||||
for k, v in pairs(window_handle) do
|
||||
w[k] = v
|
||||
end
|
||||
|
||||
|
@ -37,39 +40,39 @@ end
|
|||
---
|
||||
---***You will probably not need to use this.***
|
||||
---@return WindowId
|
||||
function window:id()
|
||||
function window_handle:id()
|
||||
return self._id
|
||||
end
|
||||
|
||||
---Set this window's size.
|
||||
---
|
||||
---See `WindowModule.set_size` for examples.
|
||||
---See `Window.set_size` for examples.
|
||||
---
|
||||
---@param size { w: integer?, h: integer? }
|
||||
---@see WindowModule.set_size — The corresponding module function
|
||||
function window:set_size(size)
|
||||
window_module.set_size(self, size)
|
||||
---@see Window.set_size — The corresponding module function
|
||||
function window_handle:set_size(size)
|
||||
window.set_size(self, size)
|
||||
end
|
||||
|
||||
---Move this window to a tag, removing all other ones.
|
||||
---
|
||||
---See `WindowModule.move_to_tag` for examples.
|
||||
---See `Window.move_to_tag` for examples.
|
||||
---
|
||||
---@param t TagConstructor
|
||||
---@see WindowModule.move_to_tag — The corresponding module function
|
||||
function window:move_to_tag(t)
|
||||
window_module.move_to_tag(self, t)
|
||||
---@see Window.move_to_tag — The corresponding module function
|
||||
function window_handle:move_to_tag(t)
|
||||
window.move_to_tag(self, t)
|
||||
end
|
||||
|
||||
---Toggle the specified tag for this window.
|
||||
---
|
||||
---Note: toggling off all tags currently makes a window not respond to layouting.
|
||||
---
|
||||
---See `WindowModule.toggle_tag` for examples.
|
||||
---See `Window.toggle_tag` for examples.
|
||||
---@param t TagConstructor
|
||||
---@see WindowModule.toggle_tag — The corresponding module function
|
||||
function window:toggle_tag(t)
|
||||
window_module.toggle_tag(self, t)
|
||||
---@see Window.toggle_tag — The corresponding module function
|
||||
function window_handle:toggle_tag(t)
|
||||
window.toggle_tag(self, t)
|
||||
end
|
||||
|
||||
---Close this window.
|
||||
|
@ -77,19 +80,19 @@ end
|
|||
---This only sends a close *event* to the window and is the same as just clicking the X button in the titlebar.
|
||||
---This will trigger save prompts in applications like GIMP.
|
||||
---
|
||||
---See `WindowModule.close` for examples.
|
||||
---@see WindowModule.close — The corresponding module function
|
||||
function window:close()
|
||||
window_module.close(self)
|
||||
---See `Window.close` for examples.
|
||||
---@see Window.close — The corresponding module function
|
||||
function window_handle:close()
|
||||
window.close(self)
|
||||
end
|
||||
|
||||
---Get this window's size.
|
||||
---
|
||||
---See `WindowModule.size` for examples.
|
||||
---See `Window.size` for examples.
|
||||
---@return { w: integer, h: integer }|nil size The size of the window, or nil if it doesn't exist.
|
||||
---@see WindowModule.size — The corresponding module function
|
||||
function window:size()
|
||||
return window_module.size(self)
|
||||
---@see Window.size — The corresponding module function
|
||||
function window_handle:size()
|
||||
return window.size(self)
|
||||
end
|
||||
|
||||
---Get this window's location in the global space.
|
||||
|
@ -100,50 +103,50 @@ end
|
|||
---If you don't set the location of your monitors, they will start at (0, 0)
|
||||
---and extend rightward with their tops aligned.
|
||||
---
|
||||
---See `WindowModule.loc` for examples.
|
||||
---See `Window.loc` for examples.
|
||||
---@return { x: integer, y: integer }|nil loc The location of the window, or nil if it's not on-screen or alive.
|
||||
---@see WindowModule.loc — The corresponding module function
|
||||
function window:loc()
|
||||
return window_module.loc(self)
|
||||
---@see Window.loc — The corresponding module function
|
||||
function window_handle:loc()
|
||||
return window.loc(self)
|
||||
end
|
||||
|
||||
---Get this window's class. This is usually the name of the application.
|
||||
---
|
||||
---See `WindowModule.class` for examples.
|
||||
---See `Window.class` for examples.
|
||||
---@return string|nil class This window's class, or nil if it doesn't exist.
|
||||
---@see WindowModule.class — The corresponding module function
|
||||
function window:class()
|
||||
return window_module.class(self)
|
||||
---@see Window.class — The corresponding module function
|
||||
function window_handle:class()
|
||||
return window.class(self)
|
||||
end
|
||||
|
||||
---Get this window's title.
|
||||
---
|
||||
---See `WindowModule.title` for examples.
|
||||
---See `Window.title` for examples.
|
||||
---@return string|nil title This window's title, or nil if it doesn't exist.
|
||||
---@see WindowModule.title — The corresponding module function
|
||||
function window:title()
|
||||
return window_module.title(self)
|
||||
---@see Window.title — The corresponding module function
|
||||
function window_handle:title()
|
||||
return window.title(self)
|
||||
end
|
||||
|
||||
---Get this window's floating status.
|
||||
---@return boolean|nil
|
||||
---@see WindowModule.floating — The corresponding module function
|
||||
function window:floating()
|
||||
return window_module.floating(self)
|
||||
---@see Window.floating — The corresponding module function
|
||||
function window_handle:floating()
|
||||
return window.floating(self)
|
||||
end
|
||||
|
||||
---Get this window's fullscreen status.
|
||||
---@return boolean|nil
|
||||
---@see WindowModule.fullscreen — The corresponding module function
|
||||
function window:fullscreen()
|
||||
return window_module.fullscreen(self)
|
||||
---@see Window.fullscreen — The corresponding module function
|
||||
function window_handle:fullscreen()
|
||||
return window.fullscreen(self)
|
||||
end
|
||||
|
||||
---Get this window's maximized status.
|
||||
---@return boolean|nil
|
||||
---@see WindowModule.maximized — The corresponding module function
|
||||
function window:maximized()
|
||||
return window_module.maximized(self)
|
||||
---@see Window.maximized — The corresponding module function
|
||||
function window_handle:maximized()
|
||||
return window.maximized(self)
|
||||
end
|
||||
|
||||
---Toggle this window's floating status.
|
||||
|
@ -152,8 +155,8 @@ end
|
|||
---
|
||||
---When used on a fullscreen or maximized window, this will still change its
|
||||
---underlying floating/tiled status.
|
||||
function window:toggle_floating()
|
||||
window_module.toggle_floating(self)
|
||||
function window_handle:toggle_floating()
|
||||
window.toggle_floating(self)
|
||||
end
|
||||
|
||||
---Toggle this window's fullscreen status.
|
||||
|
@ -162,8 +165,8 @@ end
|
|||
---floating or tiled.
|
||||
---
|
||||
---When used on a non-fullscreen window, it becomes fullscreen.
|
||||
function window:toggle_fullscreen()
|
||||
window_module.toggle_fullscreen(self)
|
||||
function window_handle:toggle_fullscreen()
|
||||
window.toggle_fullscreen(self)
|
||||
end
|
||||
|
||||
---Toggle this window's maximized status.
|
||||
|
@ -172,28 +175,28 @@ end
|
|||
---floating or tiled.
|
||||
---
|
||||
---When used on a non-maximized window, it becomes maximized.
|
||||
function window:toggle_maximized()
|
||||
window_module.toggle_maximized(self)
|
||||
function window_handle:toggle_maximized()
|
||||
window.toggle_maximized(self)
|
||||
end
|
||||
|
||||
---Get whether or not this window is focused.
|
||||
---
|
||||
---See `WindowModule.focused` for examples.
|
||||
---See `Window.focused` for examples.
|
||||
---@return boolean|nil
|
||||
---@see WindowModule.focused — The corresponding module function
|
||||
function window:focused()
|
||||
return window_module.focused(self)
|
||||
---@see Window.focused — The corresponding module function
|
||||
function window_handle:focused()
|
||||
return window.focused(self)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
---Get all windows with the specified class (usually the name of the application).
|
||||
---@param class string The class. For example, Alacritty's class is "Alacritty".
|
||||
---@return Window[]
|
||||
function window_module.get_by_class(class)
|
||||
local windows = window_module.get_all()
|
||||
---@return WindowHandle[]
|
||||
function window.get_by_class(class)
|
||||
local windows = window.get_all()
|
||||
|
||||
---@type Window[]
|
||||
---@type WindowHandle[]
|
||||
local windows_ret = {}
|
||||
for _, w in pairs(windows) do
|
||||
if w:class() == class then
|
||||
|
@ -206,11 +209,11 @@ end
|
|||
|
||||
---Get all windows with the specified title.
|
||||
---@param title string The title.
|
||||
---@return Window[]
|
||||
function window_module.get_by_title(title)
|
||||
local windows = window_module.get_all()
|
||||
---@return WindowHandle[]
|
||||
function window.get_by_title(title)
|
||||
local windows = window.get_all()
|
||||
|
||||
---@type Window[]
|
||||
---@type WindowHandle[]
|
||||
local windows_ret = {}
|
||||
for _, w in pairs(windows) do
|
||||
if w:title() == title then
|
||||
|
@ -222,10 +225,11 @@ function window_module.get_by_title(title)
|
|||
end
|
||||
|
||||
---Get the currently focused window.
|
||||
---@return Window|nil
|
||||
function window_module.get_focused()
|
||||
---
|
||||
---@return WindowHandle handle A handle to the currently focused window. If there are none, this returns a dummy handle that can still be used but will be ignored by the compositor.
|
||||
function window.get_focused()
|
||||
-- TODO: get focused on output
|
||||
local windows = window_module.get_all()
|
||||
local windows = window.get_all()
|
||||
|
||||
for _, w in pairs(windows) do
|
||||
if w:focused() then
|
||||
|
@ -233,15 +237,15 @@ function window_module.get_focused()
|
|||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
return create_window("None")
|
||||
end
|
||||
|
||||
---Get all windows.
|
||||
---@return Window[]
|
||||
function window_module.get_all()
|
||||
---@return WindowHandle[]
|
||||
function window.get_all()
|
||||
local window_ids = Request("GetWindows").RequestResponse.response.Windows.window_ids
|
||||
|
||||
---@type Window[]
|
||||
---@type WindowHandle[]
|
||||
local windows = {}
|
||||
|
||||
for _, window_id in pairs(window_ids) do
|
||||
|
@ -253,10 +257,10 @@ end
|
|||
|
||||
---Toggle the tag with the given name and (optional) output for the specified window.
|
||||
---
|
||||
---@param w Window
|
||||
---@param w WindowHandle
|
||||
---@param t TagConstructor
|
||||
---@see Window.toggle_tag — The corresponding object method
|
||||
function window_module.toggle_tag(w, t)
|
||||
---@see WindowHandle.toggle_tag — The corresponding object method
|
||||
function window.toggle_tag(w, t)
|
||||
local t = require("tag").get(t)
|
||||
|
||||
if t then
|
||||
|
@ -271,10 +275,10 @@ end
|
|||
|
||||
---Move the specified window to the tag with the given name and (optional) output.
|
||||
---
|
||||
---@param w Window
|
||||
---@param w WindowHandle
|
||||
---@param t TagConstructor
|
||||
---@see Window.move_to_tag — The corresponding object method
|
||||
function window_module.move_to_tag(w, t)
|
||||
---@see WindowHandle.move_to_tag — The corresponding object method
|
||||
function window.move_to_tag(w, t)
|
||||
local t = require("tag").get(t)
|
||||
|
||||
if t then
|
||||
|
@ -293,8 +297,8 @@ end
|
|||
---
|
||||
---When used on a fullscreen or maximized window, this will still change its
|
||||
---underlying floating/tiled status.
|
||||
---@param win Window
|
||||
function window_module.toggle_floating(win)
|
||||
---@param win WindowHandle
|
||||
function window.toggle_floating(win)
|
||||
SendMsg({
|
||||
ToggleFloating = {
|
||||
window_id = win:id(),
|
||||
|
@ -308,8 +312,8 @@ end
|
|||
---floating or tiled.
|
||||
---
|
||||
---When used on a non-fullscreen window, it becomes fullscreen.
|
||||
---@param win Window
|
||||
function window_module.toggle_fullscreen(win)
|
||||
---@param win WindowHandle
|
||||
function window.toggle_fullscreen(win)
|
||||
SendMsg({
|
||||
ToggleFullscreen = {
|
||||
window_id = win:id(),
|
||||
|
@ -323,8 +327,8 @@ end
|
|||
---floating or tiled.
|
||||
---
|
||||
---When used on a non-maximized window, it becomes maximized.
|
||||
---@param win Window
|
||||
function window_module.toggle_maximized(win)
|
||||
---@param win WindowHandle
|
||||
function window.toggle_maximized(win)
|
||||
SendMsg({
|
||||
ToggleMaximized = {
|
||||
window_id = win:id(),
|
||||
|
@ -343,10 +347,10 @@ end
|
|||
--- window.set_size(win, {}) -- do absolutely nothing useful
|
||||
---end
|
||||
---```
|
||||
---@param win Window
|
||||
---@param win WindowHandle
|
||||
---@param size { w: integer?, h: integer? }
|
||||
---@see Window.set_size — The corresponding object method
|
||||
function window_module.set_size(win, size)
|
||||
---@see WindowHandle.set_size — The corresponding object method
|
||||
function window.set_size(win, size)
|
||||
SendMsg({
|
||||
SetWindowSize = {
|
||||
window_id = win:id(),
|
||||
|
@ -368,9 +372,9 @@ end
|
|||
--- window.close(win) -- close the currently focused window
|
||||
---end
|
||||
---```
|
||||
---@param win Window
|
||||
---@see Window.close — The corresponding object method
|
||||
function window_module.close(win)
|
||||
---@param win WindowHandle
|
||||
---@see WindowHandle.close — The corresponding object method
|
||||
function window.close(win)
|
||||
SendMsg({
|
||||
CloseWindow = {
|
||||
window_id = win:id(),
|
||||
|
@ -386,10 +390,10 @@ end
|
|||
---local size = window.size(win)
|
||||
--- -- ...should have size equal to `{ w = 3840, h = 2160 }`.
|
||||
---```
|
||||
---@param win Window
|
||||
---@param win WindowHandle
|
||||
---@return { w: integer, h: integer }|nil size The size of the window, or nil if it doesn't exist.
|
||||
---@see Window.size — The corresponding object method
|
||||
function window_module.size(win)
|
||||
---@see WindowHandle.size — The corresponding object method
|
||||
function window.size(win)
|
||||
local response = Request({
|
||||
GetWindowProps = {
|
||||
window_id = win:id(),
|
||||
|
@ -421,10 +425,10 @@ end
|
|||
---local loc = window.loc(win)
|
||||
--- -- ...should have loc equal to `{ x = 1920, y = 0 }`.
|
||||
---```
|
||||
---@param win Window
|
||||
---@param win WindowHandle
|
||||
---@return { x: integer, y: integer }|nil loc The location of the window, or nil if it's not on-screen or alive.
|
||||
---@see Window.loc — The corresponding object method
|
||||
function window_module.loc(win)
|
||||
---@see WindowHandle.loc — The corresponding object method
|
||||
function window.loc(win)
|
||||
local response = Request({
|
||||
GetWindowProps = {
|
||||
window_id = win:id(),
|
||||
|
@ -452,10 +456,10 @@ end
|
|||
---end
|
||||
--- -- ...should print "Alacritty".
|
||||
---```
|
||||
---@param win Window
|
||||
---@param win WindowHandle
|
||||
---@return string|nil class This window's class, or nil if it doesn't exist.
|
||||
---@see Window.class — The corresponding object method
|
||||
function window_module.class(win)
|
||||
---@see WindowHandle.class — The corresponding object method
|
||||
function window.class(win)
|
||||
local response = Request({
|
||||
GetWindowProps = {
|
||||
window_id = win:id(),
|
||||
|
@ -476,10 +480,10 @@ end
|
|||
---end
|
||||
--- -- ...should print the directory Alacritty is in or what it's running (what's in its title bar).
|
||||
---```
|
||||
---@param win Window
|
||||
---@param win WindowHandle
|
||||
---@return string|nil title This window's title, or nil if it doesn't exist.
|
||||
---@see Window.title — The corresponding object method
|
||||
function window_module.title(win)
|
||||
---@see WindowHandle.title — The corresponding object method
|
||||
function window.title(win)
|
||||
local response = Request({
|
||||
GetWindowProps = {
|
||||
window_id = win:id(),
|
||||
|
@ -490,10 +494,10 @@ function window_module.title(win)
|
|||
end
|
||||
|
||||
---Get this window's floating status.
|
||||
---@param win Window
|
||||
---@param win WindowHandle
|
||||
---@return boolean|nil
|
||||
---@see Window.floating — The corresponding object method
|
||||
function window_module.floating(win)
|
||||
---@see WindowHandle.floating — The corresponding object method
|
||||
function window.floating(win)
|
||||
local response = Request({
|
||||
GetWindowProps = {
|
||||
window_id = win:id(),
|
||||
|
@ -504,10 +508,10 @@ function window_module.floating(win)
|
|||
end
|
||||
|
||||
---Get this window's fullscreen status.
|
||||
---@param win Window
|
||||
---@param win WindowHandle
|
||||
---@return boolean|nil
|
||||
---@see Window.fullscreen — The corresponding object method
|
||||
function window_module.fullscreen(win)
|
||||
---@see WindowHandle.fullscreen — The corresponding object method
|
||||
function window.fullscreen(win)
|
||||
local response = Request({
|
||||
GetWindowProps = {
|
||||
window_id = win:id(),
|
||||
|
@ -518,10 +522,10 @@ function window_module.fullscreen(win)
|
|||
end
|
||||
|
||||
---Get this window's maximized status.
|
||||
---@param win Window
|
||||
---@param win WindowHandle
|
||||
---@return boolean|nil
|
||||
---@see Window.maximized — The corresponding object method
|
||||
function window_module.maximized(win)
|
||||
---@see WindowHandle.maximized — The corresponding object method
|
||||
function window.maximized(win)
|
||||
local response = Request({
|
||||
GetWindowProps = {
|
||||
window_id = win:id(),
|
||||
|
@ -540,10 +544,10 @@ end
|
|||
--- print(window.focused(win)) -- Should print `true`
|
||||
---end
|
||||
---```
|
||||
---@param win Window
|
||||
---@param win WindowHandle
|
||||
---@return boolean|nil
|
||||
---@see Window.focused — The corresponding object method
|
||||
function window_module.focused(win)
|
||||
---@see WindowHandle.focused — The corresponding object method
|
||||
function window.focused(win)
|
||||
local response = Request({
|
||||
GetWindowProps = {
|
||||
window_id = win:id(),
|
||||
|
@ -558,7 +562,7 @@ end
|
|||
---This will start a window move grab with the provided button on the window the pointer
|
||||
---is currently hovering over. Once `button` is let go, the move will end.
|
||||
---@param button MouseButton The button you want to trigger the move.
|
||||
function window_module.begin_move(button)
|
||||
function window.begin_move(button)
|
||||
SendMsg({
|
||||
WindowMoveGrab = {
|
||||
button = button,
|
||||
|
@ -571,7 +575,7 @@ end
|
|||
---This will start a window resize grab with the provided button on the window the
|
||||
---pointer is currently hovering over. Once `button` is let go, the resize will end.
|
||||
---@param button MouseButton
|
||||
function window_module.begin_resize(button)
|
||||
function window.begin_resize(button)
|
||||
SendMsg({
|
||||
WindowResizeGrab = {
|
||||
button = button,
|
||||
|
@ -579,4 +583,4 @@ function window_module.begin_resize(button)
|
|||
})
|
||||
end
|
||||
|
||||
return window_module
|
||||
return window
|
||||
|
|
|
@ -220,7 +220,7 @@ function window_rules.add(...)
|
|||
if rule.rule.output and type(rule.rule.output) == "table" then
|
||||
rule.rule.output = rule
|
||||
.rule
|
||||
.output--[[@as Output]]
|
||||
.output--[[@as OutputHandle]]
|
||||
:name()
|
||||
end
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
backend::Backend,
|
||||
config::api::msg::{CallbackId, Modifier, ModifierMask, MouseEdge, OutgoingMsg},
|
||||
focus::FocusTarget,
|
||||
state::WithState,
|
||||
|
@ -16,7 +15,6 @@ use smithay::{
|
|||
KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent,
|
||||
},
|
||||
libinput::LibinputInputBackend,
|
||||
session::Session,
|
||||
},
|
||||
desktop::{layer_map_for_output, space::SpaceElement},
|
||||
input::{
|
||||
|
|
|
@ -9,6 +9,9 @@ use crate::{
|
|||
tag::Tag,
|
||||
};
|
||||
|
||||
/// A unique identifier for an output.
|
||||
///
|
||||
/// An empty string represents an invalid output.
|
||||
#[derive(Debug, Hash, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
|
||||
pub struct OutputName(pub String);
|
||||
|
||||
|
|
|
@ -110,7 +110,16 @@ impl State {
|
|||
if let Some(height) = height {
|
||||
window_size.h = height;
|
||||
}
|
||||
window.change_geometry(Rectangle::from_loc_and_size(window_loc, window_size));
|
||||
use crate::window::window_state::FloatingOrTiled;
|
||||
|
||||
let rect = Rectangle::from_loc_and_size(window_loc, window_size);
|
||||
window.change_geometry(rect);
|
||||
window.with_state(|state| {
|
||||
state.floating_or_tiled = match state.floating_or_tiled {
|
||||
FloatingOrTiled::Floating(_) => FloatingOrTiled::Floating(rect),
|
||||
FloatingOrTiled::Tiled(_) => FloatingOrTiled::Tiled(Some(rect)),
|
||||
}
|
||||
});
|
||||
if let Some(output) = window.output(self) {
|
||||
self.update_windows(&output);
|
||||
self.schedule_render(&output);
|
||||
|
|
|
@ -17,11 +17,15 @@ use crate::{
|
|||
static TAG_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, serde::Serialize, serde::Deserialize)]
|
||||
pub struct TagId(u32);
|
||||
pub enum TagId {
|
||||
None,
|
||||
#[serde(untagged)]
|
||||
Some(u32),
|
||||
}
|
||||
|
||||
impl TagId {
|
||||
fn next() -> Self {
|
||||
Self(TAG_ID_COUNTER.fetch_add(1, Ordering::Relaxed))
|
||||
Self::Some(TAG_ID_COUNTER.fetch_add(1, Ordering::Relaxed))
|
||||
}
|
||||
|
||||
pub fn tag(&self, state: &State) -> Option<Tag> {
|
||||
|
|
|
@ -18,14 +18,22 @@ use crate::{
|
|||
|
||||
use super::WindowElement;
|
||||
|
||||
/// A unique identifier for each window.
|
||||
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
||||
pub struct WindowId(u32);
|
||||
pub enum WindowId {
|
||||
/// A config API returned an invalid window. It should be using this variant.
|
||||
None,
|
||||
/// A valid window id.
|
||||
#[serde(untagged)]
|
||||
Some(u32),
|
||||
}
|
||||
|
||||
static WINDOW_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
|
||||
|
||||
impl WindowId {
|
||||
/// Get the next available window id. This always starts at 0.
|
||||
pub fn next() -> Self {
|
||||
Self(WINDOW_ID_COUNTER.fetch_add(1, Ordering::Relaxed))
|
||||
Self::Some(WINDOW_ID_COUNTER.fetch_add(1, Ordering::Relaxed))
|
||||
}
|
||||
|
||||
/// Get the window that has this WindowId.
|
||||
|
@ -317,13 +325,6 @@ impl FullscreenOrMaximized {
|
|||
}
|
||||
}
|
||||
|
||||
impl WindowElementState {
|
||||
#[allow(dead_code)]
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for WindowElementState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
|
Loading…
Reference in a new issue