Add revelation
Update and add bling task_preview, tag_preview and window_switcher Add catppuccin-macchiato Use my weather key Update keybindings Update autorun Fix sliders
This commit is contained in:
parent
4f850f7173
commit
2401cfcee2
56 changed files with 2040 additions and 858 deletions
532
home/.config/awesome/libs/awesome_switcher.lua
Normal file
532
home/.config/awesome/libs/awesome_switcher.lua
Normal file
|
@ -0,0 +1,532 @@
|
|||
local cairo = require("lgi").cairo
|
||||
local mouse = mouse
|
||||
local screen = screen
|
||||
local wibox = require('wibox')
|
||||
local table = table
|
||||
local keygrabber = keygrabber
|
||||
local math = require('math')
|
||||
local awful = require('awful')
|
||||
local gears = require("gears")
|
||||
local timer = gears.timer
|
||||
local client = client
|
||||
awful.client = require('awful.client')
|
||||
|
||||
local naughty = require("naughty")
|
||||
local string = string
|
||||
local tostring = tostring
|
||||
local tonumber = tonumber
|
||||
local debug = debug
|
||||
local pairs = pairs
|
||||
local unpack = unpack or table.unpack
|
||||
|
||||
local surface = cairo.ImageSurface(cairo.Format.RGB24,20,20)
|
||||
local cr = cairo.Context(surface)
|
||||
|
||||
local _M = {}
|
||||
|
||||
-- settings
|
||||
|
||||
_M.settings = {
|
||||
preview_box = true,
|
||||
preview_box_bg = "#18192611",
|
||||
preview_box_border = "#18192611",
|
||||
preview_box_fps = 30,
|
||||
preview_box_delay = 100,
|
||||
preview_box_title_font = {"Ubuntu","italic","normal"},
|
||||
preview_box_title_font_size_factor = 0.8,
|
||||
preview_box_title_color = {202,211,245,1},
|
||||
|
||||
client_opacity = true,
|
||||
client_opacity_value_selected = 1,
|
||||
client_opacity_value_in_focus = 0.5,
|
||||
client_opacity_value = 0.5,
|
||||
|
||||
cycle_raise_client = true,
|
||||
}
|
||||
|
||||
-- Create a wibox to contain all the client-widgets
|
||||
_M.preview_wbox = wibox({ width = screen[mouse.screen].geometry.width })
|
||||
_M.preview_wbox.border_width = 3
|
||||
_M.preview_wbox.ontop = true
|
||||
_M.preview_wbox.visible = false
|
||||
|
||||
_M.preview_live_timer = timer({ timeout = 1/_M.settings.preview_box_fps })
|
||||
_M.preview_widgets = {}
|
||||
|
||||
_M.altTabTable = {}
|
||||
_M.altTabIndex = 1
|
||||
|
||||
_M.source = string.sub(debug.getinfo(1,'S').source, 2)
|
||||
_M.path = string.sub(_M.source, 1, string.find(_M.source, "/[^/]*$"))
|
||||
_M.noicon = _M.path .. "noicon.png"
|
||||
|
||||
-- simple function for counting the size of a table
|
||||
function _M.tableLength(T)
|
||||
local count = 0
|
||||
for _ in pairs(T) do count = count + 1 end
|
||||
return count
|
||||
end
|
||||
|
||||
-- this function returns the list of clients to be shown.
|
||||
function _M.getClients()
|
||||
local clients = {}
|
||||
|
||||
-- Get focus history for current tag
|
||||
local s = mouse.screen;
|
||||
local idx = 0
|
||||
local c = awful.client.focus.history.get(s, idx)
|
||||
|
||||
while c do
|
||||
table.insert(clients, c)
|
||||
|
||||
idx = idx + 1
|
||||
c = awful.client.focus.history.get(s, idx)
|
||||
end
|
||||
|
||||
-- Minimized clients will not appear in the focus history
|
||||
-- Find them by cycling through all clients, and adding them to the list
|
||||
-- if not already there.
|
||||
-- This will preserve the history AND enable you to focus on minimized clients
|
||||
|
||||
local t = s.selected_tag
|
||||
local all = client.get(s)
|
||||
|
||||
for i = 1, #all do
|
||||
local c = all[i]
|
||||
local ctags = c:tags();
|
||||
|
||||
-- check if the client is on the current tag
|
||||
local isCurrentTag = false
|
||||
for j = 1, #ctags do
|
||||
if t == ctags[j] then
|
||||
isCurrentTag = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if isCurrentTag then
|
||||
-- check if client is already in the history
|
||||
-- if not, add it
|
||||
local addToTable = true
|
||||
for k = 1, #clients do
|
||||
if clients[k] == c then
|
||||
addToTable = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if addToTable then
|
||||
table.insert(clients, c)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return clients
|
||||
end
|
||||
|
||||
-- here we populate altTabTable using the list of clients taken from
|
||||
-- _M.getClients(). In case we have altTabTable with some value, the list of the
|
||||
-- old known clients is restored.
|
||||
function _M.populateAltTabTable()
|
||||
local clients = _M.getClients()
|
||||
|
||||
if _M.tableLength(_M.altTabTable) then
|
||||
for ci = 1, #clients do
|
||||
for ti = 1, #_M.altTabTable do
|
||||
if _M.altTabTable[ti].client == clients[ci] then
|
||||
_M.altTabTable[ti].client.opacity = _M.altTabTable[ti].opacity
|
||||
_M.altTabTable[ti].client.minimized = _M.altTabTable[ti].minimized
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
_M.altTabTable = {}
|
||||
|
||||
for i = 1, #clients do
|
||||
table.insert(_M.altTabTable, {
|
||||
client = clients[i],
|
||||
minimized = clients[i].minimized,
|
||||
opacity = clients[i].opacity
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- If the length of list of clients is not equal to the length of altTabTable,
|
||||
-- we need to repopulate the array and update the UI. This function does this
|
||||
-- check.
|
||||
function _M.clientsHaveChanged()
|
||||
local clients = _M.getClients()
|
||||
return _M.tableLength(clients) ~= _M.tableLength(_M.altTabTable)
|
||||
end
|
||||
|
||||
function _M.createPreviewText(client)
|
||||
if client.class then
|
||||
return " " .. client.class
|
||||
else
|
||||
return " " .. client.name
|
||||
end
|
||||
end
|
||||
|
||||
-- Preview is created here.
|
||||
function _M.clientOpacity()
|
||||
if not _M.settings.client_opacity then return end
|
||||
|
||||
local opacity = _M.settings.client_opacity_value
|
||||
if opacity > 1 then opacity = 1 end
|
||||
for i,data in pairs(_M.altTabTable) do
|
||||
data.client.opacity = opacity
|
||||
end
|
||||
|
||||
if client.focus == _M.altTabTable[_M.altTabIndex].client then
|
||||
-- Let's normalize the value up to 1.
|
||||
local opacityFocusSelected = _M.settings.client_opacity_value_selected + _M.settings.client_opacity_value_in_focus
|
||||
if opacityFocusSelected > 1 then opacityFocusSelected = 1 end
|
||||
client.focus.opacity = opacityFocusSelected
|
||||
else
|
||||
-- Let's normalize the value up to 1.
|
||||
local opacityFocus = _M.settings.client_opacity_value_in_focus
|
||||
if opacityFocus > 1 then opacityFocus = 1 end
|
||||
local opacitySelected = _M.settings.client_opacity_value_selected
|
||||
if opacitySelected > 1 then opacitySelected = 1 end
|
||||
|
||||
client.focus.opacity = opacityFocus
|
||||
_M.altTabTable[_M.altTabIndex].client.opacity = opacitySelected
|
||||
end
|
||||
end
|
||||
|
||||
-- This is called any _M.settings.preview_box_fps milliseconds. In case the list
|
||||
-- of clients is changed, we need to redraw the whole preview box. Otherwise, a
|
||||
-- simple widget::updated signal is enough
|
||||
function _M.updatePreview()
|
||||
if _M.clientsHaveChanged() then
|
||||
_M.populateAltTabTable()
|
||||
_M.preview()
|
||||
end
|
||||
|
||||
for i = 1, #_M.preview_widgets do
|
||||
_M.preview_widgets[i]:emit_signal("widget::updated")
|
||||
end
|
||||
end
|
||||
|
||||
function _M.cycle(dir)
|
||||
-- Switch to next client
|
||||
_M.altTabIndex = _M.altTabIndex + dir
|
||||
if _M.altTabIndex > #_M.altTabTable then
|
||||
_M.altTabIndex = 1 -- wrap around
|
||||
elseif _M.altTabIndex < 1 then
|
||||
_M.altTabIndex = #_M.altTabTable -- wrap around
|
||||
end
|
||||
|
||||
_M.updatePreview()
|
||||
|
||||
_M.altTabTable[_M.altTabIndex].client.minimized = false
|
||||
|
||||
if not _M.settings.preview_box and not _M.settings.client_opacity then
|
||||
client.focus = _M.altTabTable[_M.altTabIndex].client
|
||||
end
|
||||
|
||||
if _M.settings.client_opacity and _M.preview_wbox.visible then
|
||||
_M.clientOpacity()
|
||||
end
|
||||
|
||||
if _M.settings.cycle_raise_client == true then
|
||||
_M.altTabTable[_M.altTabIndex].client:raise()
|
||||
end
|
||||
end
|
||||
|
||||
function _M.preview()
|
||||
if not _M.settings.preview_box then return end
|
||||
|
||||
-- Apply settings
|
||||
_M.preview_wbox:set_bg(_M.settings.preview_box_bg)
|
||||
_M.preview_wbox.border_color = _M.settings.preview_box_border
|
||||
|
||||
-- Make the wibox the right size, based on the number of clients
|
||||
local n = math.max(7, #_M.altTabTable)
|
||||
local W = screen[mouse.screen].geometry.width -- + 2 * _M.preview_wbox.border_width
|
||||
local w = W / n -- widget width
|
||||
local h = w * 0.75 -- widget height
|
||||
local textboxHeight = w * 0.125
|
||||
|
||||
local x = screen[mouse.screen].geometry.x - _M.preview_wbox.border_width
|
||||
local y = screen[mouse.screen].geometry.y + (screen[mouse.screen].geometry.height - h - textboxHeight) / 2
|
||||
_M.preview_wbox:geometry({x = x, y = y, width = W, height = h + textboxHeight})
|
||||
|
||||
-- create a list that holds the clients to preview, from left to right
|
||||
local leftRightTab = {}
|
||||
local leftRightTabToAltTabIndex = {} -- save mapping from leftRightTab to altTabTable as well
|
||||
local nLeft
|
||||
local nRight
|
||||
if #_M.altTabTable == 2 then
|
||||
nLeft = 0
|
||||
nRight = 2
|
||||
else
|
||||
nLeft = math.floor(#_M.altTabTable / 2)
|
||||
nRight = math.ceil(#_M.altTabTable / 2)
|
||||
end
|
||||
|
||||
for i = 1, nLeft do
|
||||
table.insert(leftRightTab, _M.altTabTable[#_M.altTabTable - nLeft + i].client)
|
||||
table.insert(leftRightTabToAltTabIndex, #_M.altTabTable - nLeft + i)
|
||||
end
|
||||
for i = 1, nRight do
|
||||
table.insert(leftRightTab, _M.altTabTable[i].client)
|
||||
table.insert(leftRightTabToAltTabIndex, i)
|
||||
end
|
||||
|
||||
-- determine fontsize -> find maximum classname-length
|
||||
local text, textWidth, textHeight, maxText
|
||||
local maxTextWidth = 0
|
||||
local maxTextHeight = 0
|
||||
local bigFont = textboxHeight / 2
|
||||
cr:set_font_size(fontSize)
|
||||
for i = 1, #leftRightTab do
|
||||
text = _M.createPreviewText(leftRightTab[i])
|
||||
textWidth = cr:text_extents(text).width
|
||||
textHeight = cr:text_extents(text).height
|
||||
if textWidth > maxTextWidth or textHeight > maxTextHeight then
|
||||
maxTextHeight = textHeight
|
||||
maxTextWidth = textWidth
|
||||
maxText = text
|
||||
end
|
||||
end
|
||||
|
||||
while true do
|
||||
cr:set_font_size(bigFont)
|
||||
textWidth = cr:text_extents(maxText).width
|
||||
textHeight = cr:text_extents(maxText).height
|
||||
|
||||
if textWidth < w - textboxHeight and textHeight < textboxHeight then
|
||||
break
|
||||
end
|
||||
|
||||
bigFont = bigFont - 1
|
||||
end
|
||||
local smallFont = bigFont * _M.settings.preview_box_title_font_size_factor
|
||||
|
||||
_M.preview_widgets = {}
|
||||
|
||||
-- create all the widgets
|
||||
for i = 1, #leftRightTab do
|
||||
_M.preview_widgets[i] = wibox.widget.base.make_widget()
|
||||
_M.preview_widgets[i].fit = function(preview_widget, width, height)
|
||||
return w, h
|
||||
end
|
||||
local c = leftRightTab[i]
|
||||
_M.preview_widgets[i].draw = function(preview_widget, preview_wbox, cr, width, height)
|
||||
if width ~= 0 and height ~= 0 then
|
||||
|
||||
local a = 0.8
|
||||
local overlay = 0.6
|
||||
local fontSize = smallFont
|
||||
if c == _M.altTabTable[_M.altTabIndex].client then
|
||||
a = 0.9
|
||||
overlay = 0
|
||||
fontSize = bigFont
|
||||
end
|
||||
|
||||
local sx, sy, tx, ty
|
||||
|
||||
-- Icons
|
||||
local icon
|
||||
if c.icon == nil then
|
||||
icon = gears.surface(gears.surface.load(_M.noicon))
|
||||
else
|
||||
icon = gears.surface(c.icon)
|
||||
end
|
||||
|
||||
local iconboxWidth = 0.9 * textboxHeight
|
||||
local iconboxHeight = iconboxWidth
|
||||
|
||||
-- Titles
|
||||
cr:select_font_face(unpack(_M.settings.preview_box_title_font))
|
||||
cr:set_font_face(cr:get_font_face())
|
||||
cr:set_font_size(fontSize)
|
||||
|
||||
text = _M.createPreviewText(c)
|
||||
textWidth = cr:text_extents(text).width
|
||||
textHeight = cr:text_extents(text).height
|
||||
|
||||
local titleboxWidth = textWidth + iconboxWidth
|
||||
local titleboxHeight = textboxHeight
|
||||
|
||||
-- Draw icons
|
||||
tx = (w - titleboxWidth) / 2
|
||||
ty = h
|
||||
sx = iconboxWidth / icon.width
|
||||
sy = iconboxHeight / icon.height
|
||||
|
||||
cr:translate(tx, ty)
|
||||
cr:scale(sx, sy)
|
||||
cr:set_source_surface(icon, 0, 0)
|
||||
cr:paint()
|
||||
cr:scale(1/sx, 1/sy)
|
||||
cr:translate(-tx, -ty)
|
||||
|
||||
-- Draw titles
|
||||
tx = tx + iconboxWidth
|
||||
ty = h + (textboxHeight + textHeight) / 2
|
||||
|
||||
cr:set_source_rgba(unpack(_M.settings.preview_box_title_color))
|
||||
cr:move_to(tx, ty)
|
||||
cr:show_text(text)
|
||||
cr:stroke()
|
||||
|
||||
-- Draw previews
|
||||
local cg = c:geometry()
|
||||
if cg.width > cg.height then
|
||||
sx = a * w / cg.width
|
||||
sy = math.min(sx, a * h / cg.height)
|
||||
else
|
||||
sy = a * h / cg.height
|
||||
sx = math.min(sy, a * h / cg.width)
|
||||
end
|
||||
|
||||
tx = (w - sx * cg.width) / 2
|
||||
ty = (h - sy * cg.height) / 2
|
||||
|
||||
local tmp = gears.surface(c.content)
|
||||
cr:translate(tx, ty)
|
||||
cr:scale(sx, sy)
|
||||
cr:set_source_surface(tmp, 0, 0)
|
||||
cr:paint()
|
||||
tmp:finish()
|
||||
|
||||
-- Overlays
|
||||
cr:scale(1/sx, 1/sy)
|
||||
cr:translate(-tx, -ty)
|
||||
cr:set_source_rgba(0,0,0,overlay)
|
||||
cr:rectangle(tx, ty, sx * cg.width, sy * cg.height)
|
||||
cr:fill()
|
||||
end
|
||||
end
|
||||
|
||||
-- Add mouse handler
|
||||
_M.preview_widgets[i]:connect_signal("mouse::enter", function()
|
||||
_M.cycle(leftRightTabToAltTabIndex[i] - _M.altTabIndex)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Spacers left and right
|
||||
local spacer = wibox.widget.base.make_widget()
|
||||
spacer.fit = function(leftSpacer, width, height)
|
||||
return (W - w * #_M.altTabTable) / 2, _M.preview_wbox.height
|
||||
end
|
||||
spacer.draw = function(preview_widget, preview_wbox, cr, width, height) end
|
||||
|
||||
--layout
|
||||
preview_layout = wibox.layout.fixed.horizontal()
|
||||
|
||||
preview_layout:add(spacer)
|
||||
for i = 1, #leftRightTab do
|
||||
preview_layout:add(_M.preview_widgets[i])
|
||||
end
|
||||
preview_layout:add(spacer)
|
||||
|
||||
_M.preview_wbox:set_widget(preview_layout)
|
||||
end
|
||||
|
||||
|
||||
-- This starts the timer for updating and it shows the preview UI.
|
||||
function _M.showPreview()
|
||||
_M.preview_live_timer.timeout = 1 / _M.settings.preview_box_fps
|
||||
_M.preview_live_timer:connect_signal("timeout", _M.updatePreview)
|
||||
_M.preview_live_timer:start()
|
||||
|
||||
_M.preview()
|
||||
_M.preview_wbox.visible = true
|
||||
|
||||
_M.clientOpacity()
|
||||
end
|
||||
|
||||
function _M.switch(dir, mod_key1, release_key, mod_key2, key_switch)
|
||||
_M.populateAltTabTable()
|
||||
|
||||
if #_M.altTabTable == 0 then
|
||||
return
|
||||
elseif #_M.altTabTable == 1 then
|
||||
_M.altTabTable[1].client.minimized = false
|
||||
_M.altTabTable[1].client:raise()
|
||||
return
|
||||
end
|
||||
|
||||
-- reset index
|
||||
_M.altTabIndex = 1
|
||||
|
||||
-- preview delay timer
|
||||
local previewDelay = _M.settings.preview_box_delay / 1000
|
||||
_M.previewDelayTimer = timer({timeout = previewDelay})
|
||||
_M.previewDelayTimer:connect_signal("timeout", function()
|
||||
_M.previewDelayTimer:stop()
|
||||
_M.showPreview()
|
||||
end)
|
||||
_M.previewDelayTimer:start()
|
||||
|
||||
-- Now that we have collected all windows, we should run a keygrabber
|
||||
-- as long as the user is alt-tabbing:
|
||||
keygrabber.run(
|
||||
function (mod, key, event)
|
||||
-- Stop alt-tabbing when the alt-key is released
|
||||
if gears.table.hasitem(mod, mod_key1) then
|
||||
if (key == release_key or key == "Escape") and event == "release" then
|
||||
if _M.preview_wbox.visible == true then
|
||||
_M.preview_wbox.visible = false
|
||||
_M.preview_live_timer:stop()
|
||||
else
|
||||
_M.previewDelayTimer:stop()
|
||||
end
|
||||
|
||||
if key == "Escape" then
|
||||
for i = 1, #_M.altTabTable do
|
||||
_M.altTabTable[i].client.opacity = _M.altTabTable[i].opacity
|
||||
_M.altTabTable[i].client.minimized = _M.altTabTable[i].minimized
|
||||
end
|
||||
else
|
||||
-- Raise clients in order to restore history
|
||||
local c
|
||||
for i = 1, _M.altTabIndex - 1 do
|
||||
c = _M.altTabTable[_M.altTabIndex - i].client
|
||||
if not _M.altTabTable[i].minimized then
|
||||
c:raise()
|
||||
client.focus = c
|
||||
end
|
||||
end
|
||||
|
||||
-- raise chosen client on top of all
|
||||
c = _M.altTabTable[_M.altTabIndex].client
|
||||
c:raise()
|
||||
client.focus = c
|
||||
|
||||
-- restore minimized clients
|
||||
for i = 1, #_M.altTabTable do
|
||||
if i ~= _M.altTabIndex and _M.altTabTable[i].minimized then
|
||||
_M.altTabTable[i].client.minimized = true
|
||||
end
|
||||
_M.altTabTable[i].client.opacity = _M.altTabTable[i].opacity
|
||||
end
|
||||
end
|
||||
|
||||
keygrabber.stop()
|
||||
|
||||
elseif key == key_switch and event == "press" then
|
||||
if gears.table.hasitem(mod, mod_key2) then
|
||||
-- Move to previous client on Shift-Tab
|
||||
_M.cycle(-1)
|
||||
else
|
||||
-- Move to next client on each Tab-press
|
||||
_M.cycle( 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
)
|
||||
|
||||
-- switch to next client
|
||||
_M.cycle(dir)
|
||||
|
||||
end -- function altTab
|
||||
|
||||
return {switch = _M.switch, settings = _M.settings}
|
Loading…
Add table
Add a link
Reference in a new issue