Make window API functions non-nil

This does not apply to functions that return an array; you'll have to do a for loop or check for nil on index in that case.
This commit is contained in:
Ottatop 2023-10-18 20:08:55 -05:00
parent ed5447d5b6
commit 17ca00f6be
6 changed files with 98 additions and 140 deletions

View file

@ -61,14 +61,14 @@
---@field Spawn { stdout: string?, stderr: string?, exit_code: integer?, exit_msg: string? }? ---@field Spawn { stdout: string?, stderr: string?, exit_code: integer?, exit_msg: string? }?
---@field ConnectForAllOutputs { output_name: string }? ---@field ConnectForAllOutputs { output_name: string }?
---@alias WindowId integer ---@alias WindowId integer | "None"
---@alias TagId integer ---@alias TagId integer
---@alias RequestId integer ---@alias RequestId integer
---@alias OutputName string ---@alias OutputName string
---@class RequestResponse ---@class RequestResponse
--Windows --Windows
---@field Window { window_id: WindowId|nil }? ---@field Window { window_id: WindowId }?
---@field Windows { window_ids: WindowId[] }? ---@field Windows { window_ids: WindowId[] }?
---@field WindowProps { size: integer[]?, loc: integer[]?, class: string?, title: string?, focused: boolean?, floating: boolean?, fullscreen_or_maximized: FullscreenOrMaximized? }? ---@field WindowProps { size: integer[]?, loc: integer[]?, class: string?, title: string?, focused: boolean?, floating: boolean?, fullscreen_or_maximized: FullscreenOrMaximized? }?
--Outputs --Outputs

View file

@ -18,8 +18,9 @@ require("pinnacle").setup(function(pinnacle)
local output = pinnacle.output -- Output management local output = pinnacle.output -- Output management
-- Every key supported by xkbcommon. -- Every key supported by xkbcommon.
-- Support for just putting in a string of a key is intended.
local keys = input.keys local keys = input.keys
-- Mouse buttons
local buttons = input.buttons
---@type Modifier ---@type Modifier
local mod_key = "Ctrl" -- This is set to `Ctrl` instead of `Super` to not conflict with your WM/DE keybinds 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" local terminal = "alacritty"
process.set_env("MOZ_ENABLE_WAYLAND", "1")
-- Outputs ----------------------------------------------------------------------- -- Outputs -----------------------------------------------------------------------
-- You can set your own monitor layout as I have done below for my monitors. -- 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 lg = output.get_by_name("DP-2") --[[@as Output]]
-- local dell = output.get_by_name("DP-3") --[[@as Output]] -- local dell = output.get_by_name("DP-3") --[[@as Output]]
-- --
-- dell:set_loc_left_of(lg, "bottom") -- 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 ---------------------------------------------------------------------- -- 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 -- mod_key + Alt + q quits the compositor
input.keybind({ mod_key, "Alt" }, keys.q, pinnacle.quit) input.keybind({ mod_key, "Alt" }, keys.q, pinnacle.quit)
@ -85,16 +106,40 @@ require("pinnacle").setup(function(pinnacle)
-- Tags --------------------------------------------------------------------------- -- Tags ---------------------------------------------------------------------------
local tags = { "1", "2", "3", "4", "5" }
output.connect_for_all(function(op) output.connect_for_all(function(op)
-- Add tags 1, 2, 3, 4 and 5 on all monitors, and toggle tag 1 active by default -- 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") -- 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) end)
---@type Layout[] -- Layout cycling
local layouts = {
-- 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", "MasterStack",
"Dwindle", "Dwindle",
"Spiral", "Spiral",
@ -102,124 +147,29 @@ require("pinnacle").setup(function(pinnacle)
"CornerTopRight", "CornerTopRight",
"CornerBottomLeft", "CornerBottomLeft",
"CornerBottomRight", "CornerBottomRight",
}
local indices = {}
-- Window rules
window.rules.add({
cond = { class = "kitty" },
rule = { floating_or_tiled = "Floating" },
}) })
-- Layout cycling input.keybind({ mod_key }, keys.space, layout_cycler.next)
-- Yes, this is overly complicated and yes, I'll cook up a way to make it less so. input.keybind({ mod_key, "Shift" }, keys.space, layout_cycler.prev)
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.KEY_1, function() -- Tag manipulation
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)
input.keybind({ mod_key, "Shift" }, keys.KEY_1, function() for _, tag_name in pairs(tags) do
tag.toggle("1") -- mod_key + 1-5 switches tags
end) input.keybind({ mod_key }, tag_name, function()
input.keybind({ mod_key, "Shift" }, keys.KEY_2, function() tag.switch_to(tag_name)
tag.toggle("2") end)
end) -- mod_key + Shift + 1-5 toggles tags
input.keybind({ mod_key, "Shift" }, keys.KEY_3, function() input.keybind({ mod_key, "Shift" }, tag_name, function()
tag.toggle("3") tag.toggle(tag_name)
end) end)
input.keybind({ mod_key, "Shift" }, keys.KEY_4, function() -- mod_key + Alt + 1-5 moves windows to tags
tag.toggle("4") input.keybind({ mod_key, "Alt" }, tag_name, function()
end) local _ = window.get_focused() and window:get_focused():move_to_tag(tag_name)
input.keybind({ mod_key, "Shift" }, keys.KEY_5, function() end)
tag.toggle("5") -- mod_key + Shift + Alt + 1-5 toggles tags on windows
end) input.keybind({ mod_key, "Shift", "Alt" }, tag_name, function()
local _ = window.get_focused() and window.get_focused():toggle_tag(tag_name)
-- I check for nil this way because I don't want stylua to take up like 80 lines on `if win ~= nil` end)
input.keybind({ mod_key, "Alt" }, keys.KEY_1, function() end
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)
end) end)

View file

@ -20,7 +20,7 @@ local window = {
---You can retrieve window handles through the various `get` functions in the `Window` module. ---You can retrieve window handles through the various `get` functions in the `Window` module.
---@classmod ---@classmod
---@class WindowHandle ---@class WindowHandle
---@field private _id integer The internal id of this window ---@field private _id WindowId The internal id of this window
local window_handle = {} local window_handle = {}
---@param window_id WindowId ---@param window_id WindowId
@ -225,7 +225,7 @@ function window.get_by_title(title)
end end
---Get the currently focused window. ---Get the currently focused window.
---@return WindowHandle|nil ---@return WindowHandle
function window.get_focused() function window.get_focused()
-- TODO: get focused on output -- TODO: get focused on output
local windows = window.get_all() local windows = window.get_all()
@ -236,7 +236,7 @@ function window.get_focused()
end end
end end
return nil return create_window("None")
end end
---Get all windows. ---Get all windows.

View file

@ -3,7 +3,6 @@
use std::collections::HashMap; use std::collections::HashMap;
use crate::{ use crate::{
backend::Backend,
config::api::msg::{CallbackId, Modifier, ModifierMask, MouseEdge, OutgoingMsg}, config::api::msg::{CallbackId, Modifier, ModifierMask, MouseEdge, OutgoingMsg},
focus::FocusTarget, focus::FocusTarget,
state::WithState, state::WithState,
@ -16,7 +15,6 @@ use smithay::{
KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent, KeyState, KeyboardKeyEvent, PointerAxisEvent, PointerButtonEvent, PointerMotionEvent,
}, },
libinput::LibinputInputBackend, libinput::LibinputInputBackend,
session::Session,
}, },
desktop::{layer_map_for_output, space::SpaceElement}, desktop::{layer_map_for_output, space::SpaceElement},
input::{ input::{

View file

@ -110,7 +110,16 @@ impl State {
if let Some(height) = height { if let Some(height) = height {
window_size.h = 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) { if let Some(output) = window.output(self) {
self.update_windows(&output); self.update_windows(&output);
self.schedule_render(&output); self.schedule_render(&output);

View file

@ -18,14 +18,22 @@ use crate::{
use super::WindowElement; use super::WindowElement;
/// A unique identifier for each window.
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] #[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); static WINDOW_ID_COUNTER: AtomicU32 = AtomicU32::new(0);
impl WindowId { impl WindowId {
/// Get the next available window id. This always starts at 0.
pub fn next() -> Self { 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. /// 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 { impl Default for WindowElementState {
fn default() -> Self { fn default() -> Self {
Self { Self {