From 17ca00f6be7274a7ffde8bf45246e851d7256036 Mon Sep 17 00:00:00 2001 From: Ottatop Date: Wed, 18 Oct 2023 20:08:55 -0500 Subject: [PATCH] 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. --- api/lua/msg.lua | 4 +- api/lua/test_config.lua | 196 ++++++++++++++----------------------- api/lua/window.lua | 6 +- src/input.rs | 2 - src/state/api_handlers.rs | 11 ++- src/window/window_state.rs | 19 ++-- 6 files changed, 98 insertions(+), 140 deletions(-) diff --git a/api/lua/msg.lua b/api/lua/msg.lua index 612d1fc..4e7aa5b 100644 --- a/api/lua/msg.lua +++ b/api/lua/msg.lua @@ -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 diff --git a/api/lua/test_config.lua b/api/lua/test_config.lua index cd59682..ac0b956 100644 --- a/api/lua/test_config.lua +++ b/api/lua/test_config.lua @@ -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) diff --git a/api/lua/window.lua b/api/lua/window.lua index 29bf317..8dbe0dc 100644 --- a/api/lua/window.lua +++ b/api/lua/window.lua @@ -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. diff --git a/src/input.rs b/src/input.rs index 3212a91..52b5a4b 100644 --- a/src/input.rs +++ b/src/input.rs @@ -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::{ diff --git a/src/state/api_handlers.rs b/src/state/api_handlers.rs index 0a0d161..0b40e18 100644 --- a/src/state/api_handlers.rs +++ b/src/state/api_handlers.rs @@ -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); diff --git a/src/window/window_state.rs b/src/window/window_state.rs index 7f352e6..a1a609b 100644 --- a/src/window/window_state.rs +++ b/src/window/window_state.rs @@ -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 {