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 ConnectForAllOutputs { output_name: string }?
---@alias WindowId integer
---@alias WindowId integer | "None"
---@alias TagId integer
---@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

View file

@ -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)

View file

@ -20,7 +20,7 @@ local window = {
---You can retrieve window handles through the various `get` functions in the `Window` module.
---@classmod
---@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 = {}
---@param window_id WindowId
@ -225,7 +225,7 @@ function window.get_by_title(title)
end
---Get the currently focused window.
---@return WindowHandle|nil
---@return WindowHandle
function window.get_focused()
-- TODO: get focused on output
local windows = window.get_all()
@ -236,7 +236,7 @@ function window.get_focused()
end
end
return nil
return create_window("None")
end
---Get all windows.

View file

@ -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::{

View file

@ -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);

View file

@ -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 {