Scratchpad feature (#35)
This commit is contained in:
parent
1f4b1094dc
commit
da886cb1c4
|
@ -19,14 +19,16 @@ All documentation, instructions, and previews are [here](https://nooo37.github.i
|
|||
- Tiled Wallpaper
|
||||
- Wallpaper Easy Setup
|
||||
- Window Swallowing
|
||||
- Scratchpad
|
||||
- Signals
|
||||
- Playerctl
|
||||
- Widgets
|
||||
- Tag Preview
|
||||
|
||||
## TODO
|
||||
- [ ] Add a built-in option to animate scratchpads with [awestore](https://github.com/K4rakara/awestore)
|
||||
- [ ] Add external sources management for the wallpaper module (URLs, RSS feeds, NASA picture of the day, ...)
|
||||
- [ ] Scratchpad module
|
||||
- [x] Scratchpad module
|
||||
- [x] Some more documentation on the tabbed module
|
||||
- [x] Add a cool alternative tabbar style
|
||||
- [x] Add another cool tabbar style (we need more styles)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
- [Tiled Wallpaper](module/twall.md)
|
||||
- [Wallpaper Easy Setup](module/wall.md)
|
||||
- [Window Swallowing](module/swal.md)
|
||||
- [Scratchpad](module/scratch.md)
|
||||
|
||||
- Signals
|
||||
- [Playerctl](signals/pctl.md)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
## 🍃 Scratchpad <!-- {docsify-ignore} -->
|
||||
|
||||
An easy way to create multiple scratchpads.
|
||||
|
||||
### A... what?
|
||||
|
||||
You can think about a scratchpad as a window whose visibility can be toggled, but still runs in the background without being visible (or minimized) most of the time. Many people use it to have one terminal in which to perform minor tasks, but it is the most useful for windows which only need a couple seconds in between your actual activity, such as music players or chat applications.
|
||||
|
||||
### Usage
|
||||
|
||||
To initalize a scratchpad you can do something like the following:
|
||||
|
||||
```lua
|
||||
local bling = require("bling")
|
||||
|
||||
local term_scratch = bling.module.scratchpad:new {
|
||||
command = "wezterm start --class spad", -- How to spawn the scratchpad
|
||||
rule = { instance = "spad" }, -- The rule that the scratchpad will be searched by
|
||||
sticky = true, -- Whether the scratchpad should be sticky
|
||||
autoclose = true, -- Whether it should hide itself when losing focus
|
||||
floating = true, -- Whether it should be floating
|
||||
geometry = {x=360, y=90, height=900, width=1200}, -- The geometry in a floating state
|
||||
reapply = false, -- Whether all those properties should be reapplied on every new opening of the scratchpad
|
||||
dont_focus_before_close = false, -- When set to true, the scratchpad will be closed by the toggle function regardless of whether its focused or not. When set to false, the toggle function will first bring the scratchpad into focus and only close it on a second call
|
||||
}
|
||||
```
|
||||
|
||||
Once initalized, you can use the object (which in this case is named `term_scratch`) like this:
|
||||
|
||||
```lua
|
||||
term_scratch:toggle() -- toggles the scratchpads visibility
|
||||
term_scratch:turn_on() -- turns the scratchpads visibility on
|
||||
term_scratch:turn_off() -- turns the scratchpads visibility off
|
||||
```
|
|
@ -1,11 +1,12 @@
|
|||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
|
||||
local _client = {}
|
||||
|
||||
--- Turn off passed client
|
||||
-- Remove current tag from window's tags
|
||||
--
|
||||
-- @param c a client
|
||||
-- @param c A client
|
||||
function _client.turn_off(c)
|
||||
local current_tag = awful.tag.selected(c.screen)
|
||||
local ctags = {}
|
||||
|
@ -45,5 +46,40 @@ function _client.sync(to_c, from_c)
|
|||
-- TODO: Should also copy over the position in a tiling layout
|
||||
end
|
||||
|
||||
--- Checks whether the passed client is a childprocess of a given process ID
|
||||
--
|
||||
-- @param c A client
|
||||
-- @param pid The process ID
|
||||
-- @return True if the passed client is a childprocess of the given PID otherwise false
|
||||
function _client.is_child_of(c, pid)
|
||||
-- io.popen is normally discouraged. Should probably be changed
|
||||
if not c or not c.valid then return false end
|
||||
if tostring(c.pid) == tostring(pid) then return true end
|
||||
local pid_cmd = [[pstree -T -p -a -s ]] .. tostring(c.pid) ..
|
||||
[[ | sed '2q;d' | grep -o '[0-9]*$' | tr -d '\n']]
|
||||
local handle = io.popen(pid_cmd)
|
||||
local parent_pid = handle:read("*a")
|
||||
handle:close()
|
||||
return tostring(parent_pid) == tostring(pid) or
|
||||
tostring(parent_pid) == tostring(c.pid)
|
||||
end
|
||||
|
||||
--- Finds all clients that satisfy the passed rule
|
||||
--
|
||||
-- @param rule The rule to be searched for
|
||||
function _client.find(rule)
|
||||
local function matcher(c) return awful.rules.match(c, rule) end
|
||||
local clients = client.get()
|
||||
local findex = gears.table.hasitem(clients, client.focus) or 1
|
||||
local start = gears.math.cycle(#clients, findex + 1)
|
||||
|
||||
local matches = {}
|
||||
for c in awful.client.iterate(matcher, start) do
|
||||
matches[#matches + 1] = c
|
||||
end
|
||||
|
||||
return matches
|
||||
end
|
||||
|
||||
|
||||
return _client
|
||||
|
|
|
@ -3,5 +3,6 @@ return {
|
|||
tiled_wallpaper = require(... .. ".tiled_wallpaper"),
|
||||
wallpaper = require(... .. ".wallpaper"),
|
||||
flash_focus = require(... .. ".flash_focus"),
|
||||
tabbed = require(... .. ".tabbed")
|
||||
tabbed = require(... .. ".tabbed"),
|
||||
scratchpad = require(... .. ".scratchpad")
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
local awful = require("awful")
|
||||
|
||||
local helpers = require(tostring(...):match(".*bling") .. ".helpers")
|
||||
|
||||
|
||||
local Scratchpad = {}
|
||||
|
||||
--- Creates a new scratchpad object based on the argument
|
||||
--
|
||||
-- @param info A table of possible arguments
|
||||
-- @return The new scratchpad object
|
||||
function Scratchpad:new(info)
|
||||
info = info or {}
|
||||
setmetatable(info, self)
|
||||
self.__index = self
|
||||
return info
|
||||
end
|
||||
|
||||
--- Find all clients that satisfy the the rule
|
||||
--
|
||||
-- @return A list of all clients that satisfy the rule
|
||||
function Scratchpad:find()
|
||||
return helpers.client.find(self.rule)
|
||||
end
|
||||
|
||||
--- Applies the objects scratchpad properties to a given client
|
||||
--
|
||||
-- @param c A client to which to apply the properties
|
||||
function Scratchpad:apply(c)
|
||||
if not c or not c.valid then return end
|
||||
c.floating = self.floating
|
||||
c.sticky = self.sticky
|
||||
c:geometry(self.geometry)
|
||||
if self.autoclose then
|
||||
c:connect_signal("unfocus", function(c)
|
||||
c.sticky = false -- client won't turn off if sticky
|
||||
helpers.client.turn_off(c)
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
--- Turns the scratchpad on
|
||||
function Scratchpad:turn_on()
|
||||
local matches = self:find()
|
||||
if matches[1] then
|
||||
-- if a client was found, turn it on
|
||||
c = matches[1]
|
||||
if self.reapply then self:apply(c) end
|
||||
-- c.sticky was set to false in turn_off so it has to be reapplied anyway
|
||||
c.sticky = self.sticky
|
||||
helpers.client.turn_on(c)
|
||||
return
|
||||
else
|
||||
-- if no client was found, spawn one, find the corresponding window,
|
||||
-- apply the properties only once (until the next closing)
|
||||
local pid = awful.spawn.with_shell(self.command)
|
||||
local function inital_apply(c)
|
||||
if helpers.client.is_child_of(c, pid) then self:apply(c) end
|
||||
client.disconnect_signal("manage", inital_apply)
|
||||
end
|
||||
client.connect_signal("manage", inital_apply)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
--- Turns the scratchpad off
|
||||
function Scratchpad:turn_off()
|
||||
local matches = self:find()
|
||||
local c = matches[1]
|
||||
if c then
|
||||
c.sticky = false
|
||||
helpers.client.turn_off(c)
|
||||
end
|
||||
end
|
||||
|
||||
--- Turns the scratchpad off if it is focused otherwise it raises the scratchpad
|
||||
function Scratchpad:toggle()
|
||||
local is_turn_off = false
|
||||
if self.dont_focus_before_close then
|
||||
local matches = self:find()
|
||||
if matches[1] and matches[1].first_tag then
|
||||
is_turn_off = matches[1].first_tag.selected
|
||||
end
|
||||
else
|
||||
is_turn_off = client.focus and awful.rules.match(client.focus, self.rule)
|
||||
end
|
||||
|
||||
if is_turn_off then
|
||||
self:turn_off()
|
||||
else
|
||||
self:turn_on()
|
||||
end
|
||||
end
|
||||
|
||||
return Scratchpad
|
|
@ -31,14 +31,9 @@ end
|
|||
local function manage_clientspawn(c)
|
||||
-- get the last focused window to check if it is a parent window
|
||||
local parent_client=awful.client.focus.history.get(c.screen, 1)
|
||||
if not parent_client then return end
|
||||
if not parent_client or not parent_client.valid then return end
|
||||
|
||||
-- io.popen is normally discouraged. Should probably be changed
|
||||
local handle = io.popen([[pstree -T -p -a -s ]] .. tostring(c.pid) .. [[ | sed '2q;d' | grep -o '[0-9]*$' | tr -d '\n']])
|
||||
local parent_pid = handle:read("*a")
|
||||
handle:close()
|
||||
|
||||
if (tostring(parent_pid) == tostring(parent_client.pid)) and check_if_swallow(c) then
|
||||
if helpers.client.is_child_of(c, parent_client.pid) and check_if_swallow(c) then
|
||||
|
||||
c:connect_signal("unmanage", function()
|
||||
helpers.client.turn_on(parent_client)
|
||||
|
|
Loading…
Reference in New Issue