New Setup 📦
This commit is contained in:
parent
d16174b447
commit
415dbd08a1
10194 changed files with 1368647 additions and 4 deletions
1053
home/.config/awesome/libs/bling/widget/app_launcher/init.lua
Normal file
1053
home/.config/awesome/libs/bling/widget/app_launcher/init.lua
Normal file
File diff suppressed because it is too large
Load diff
656
home/.config/awesome/libs/bling/widget/app_launcher/prompt.lua
Normal file
656
home/.config/awesome/libs/bling/widget/app_launcher/prompt.lua
Normal file
|
@ -0,0 +1,656 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- Modified Prompt module.
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @copyright 2008 Julien Danjou
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
local akey = require("awful.key")
|
||||
local keygrabber = require("awful.keygrabber")
|
||||
local gobject = require("gears.object")
|
||||
local gdebug = require('gears.debug')
|
||||
local gtable = require("gears.table")
|
||||
local gcolor = require("gears.color")
|
||||
local gstring = require("gears.string")
|
||||
local gfs = require("gears.filesystem")
|
||||
local wibox = require("wibox")
|
||||
local beautiful = require("beautiful")
|
||||
local io = io
|
||||
local table = table
|
||||
local math = math
|
||||
local ipairs = ipairs
|
||||
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
|
||||
local capi = { selection = selection }
|
||||
|
||||
local prompt = { mt = {} }
|
||||
|
||||
--- Private data
|
||||
local data = {}
|
||||
data.history = {}
|
||||
|
||||
local function itera(inc,a, i)
|
||||
i = i + inc
|
||||
local v = a[i]
|
||||
if v then return i,v end
|
||||
end
|
||||
|
||||
local function history_check_load(id, max)
|
||||
if id and id ~= "" and not data.history[id] then
|
||||
data.history[id] = { max = 50, table = {} }
|
||||
|
||||
if max then
|
||||
data.history[id].max = max
|
||||
end
|
||||
|
||||
local f = io.open(id, "r")
|
||||
if not f then return end
|
||||
|
||||
-- Read history file
|
||||
for line in f:lines() do
|
||||
if gtable.hasitem(data.history[id].table, line) == nil then
|
||||
table.insert(data.history[id].table, line)
|
||||
if #data.history[id].table >= data.history[id].max then
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
local function is_word_char(c)
|
||||
if string.find(c, "[{[(,.:;_-+=@/ ]") then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local function cword_start(s, pos)
|
||||
local i = pos
|
||||
if i > 1 then
|
||||
i = i - 1
|
||||
end
|
||||
while i >= 1 and not is_word_char(s:sub(i, i)) do
|
||||
i = i - 1
|
||||
end
|
||||
while i >= 1 and is_word_char(s:sub(i, i)) do
|
||||
i = i - 1
|
||||
end
|
||||
if i <= #s then
|
||||
i = i + 1
|
||||
end
|
||||
return i
|
||||
end
|
||||
|
||||
local function cword_end(s, pos)
|
||||
local i = pos
|
||||
while i <= #s and not is_word_char(s:sub(i, i)) do
|
||||
i = i + 1
|
||||
end
|
||||
while i <= #s and is_word_char(s:sub(i, i)) do
|
||||
i = i + 1
|
||||
end
|
||||
return i
|
||||
end
|
||||
|
||||
local function history_save(id)
|
||||
if data.history[id] then
|
||||
gfs.make_parent_directories(id)
|
||||
local f = io.open(id, "w")
|
||||
if not f then
|
||||
gdebug.print_warning("Failed to write the history to "..id)
|
||||
return
|
||||
end
|
||||
for i = 1, math.min(#data.history[id].table, data.history[id].max) do
|
||||
f:write(data.history[id].table[i] .. "\n")
|
||||
end
|
||||
f:close()
|
||||
end
|
||||
end
|
||||
|
||||
local function history_items(id)
|
||||
if data.history[id] then
|
||||
return #data.history[id].table
|
||||
else
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
local function history_add(id, command)
|
||||
if data.history[id] and command ~= "" then
|
||||
local index = gtable.hasitem(data.history[id].table, command)
|
||||
if index == nil then
|
||||
table.insert(data.history[id].table, command)
|
||||
|
||||
-- Do not exceed our max_cmd
|
||||
if #data.history[id].table > data.history[id].max then
|
||||
table.remove(data.history[id].table, 1)
|
||||
end
|
||||
|
||||
history_save(id)
|
||||
else
|
||||
-- Bump this command to the end of history
|
||||
table.remove(data.history[id].table, index)
|
||||
table.insert(data.history[id].table, command)
|
||||
history_save(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function have_multibyte_char_at(text, position)
|
||||
return text:sub(position, position):wlen() == -1
|
||||
end
|
||||
|
||||
local function prompt_text_with_cursor(args)
|
||||
local char, spacer, text_start, text_end, ret
|
||||
local text = args.text or ""
|
||||
local _prompt = args.prompt or ""
|
||||
local underline = args.cursor_ul or "none"
|
||||
|
||||
if args.select_all then
|
||||
if #text == 0 then char = " " else char = gstring.xml_escape(text) end
|
||||
spacer = " "
|
||||
text_start = ""
|
||||
text_end = ""
|
||||
elseif #text < args.cursor_pos then
|
||||
char = " "
|
||||
spacer = ""
|
||||
text_start = gstring.xml_escape(text)
|
||||
text_end = ""
|
||||
else
|
||||
local offset = 0
|
||||
if have_multibyte_char_at(text, args.cursor_pos) then
|
||||
offset = 1
|
||||
end
|
||||
char = gstring.xml_escape(text:sub(args.cursor_pos, args.cursor_pos + offset))
|
||||
spacer = " "
|
||||
text_start = gstring.xml_escape(text:sub(1, args.cursor_pos - 1))
|
||||
text_end = gstring.xml_escape(text:sub(args.cursor_pos + 1 + offset))
|
||||
end
|
||||
|
||||
local cursor_color = gcolor.ensure_pango_color(args.cursor_color)
|
||||
local text_color = gcolor.ensure_pango_color(args.text_color)
|
||||
|
||||
if args.highlighter then
|
||||
text_start, text_end = args.highlighter(text_start, text_end)
|
||||
end
|
||||
|
||||
ret = _prompt .. text_start .. "<span background=\"" .. cursor_color ..
|
||||
"\" foreground=\"" .. text_color .. "\" underline=\"" .. underline ..
|
||||
"\">" .. char .. "</span>" .. text_end .. spacer
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
local function update(self)
|
||||
self.textbox:set_font(self.font)
|
||||
self.textbox:set_markup(prompt_text_with_cursor{
|
||||
text = self.command, text_color = self.fg_cursor, cursor_color = self.bg_cursor,
|
||||
cursor_pos = self._private_cur_pos, cursor_ul = self.ul_cursor, select_all = self.select_all,
|
||||
prompt = self.prompt, highlighter = self.highlighter })
|
||||
end
|
||||
|
||||
local function exec(self, cb, command_to_history)
|
||||
self.textbox:set_markup("")
|
||||
history_add(self.history_path, command_to_history)
|
||||
keygrabber.stop(self._private.grabber)
|
||||
if cb then cb(self.command) end
|
||||
if self.done_callback then
|
||||
self.done_callback()
|
||||
end
|
||||
end
|
||||
|
||||
function prompt:start()
|
||||
-- The cursor position
|
||||
if self.reset_on_stop == true or self._private_cur_pos == nil then
|
||||
self._private_cur_pos = (self.select_all and 1) or self.text:wlen() + 1
|
||||
end
|
||||
if self.reset_on_stop == true then self.text = "" self.command = "" end
|
||||
|
||||
self.textbox:set_font(self.font)
|
||||
self.textbox:set_markup(prompt_text_with_cursor{
|
||||
text = self.reset_on_stop and self.text or self.command, text_color = self.fg_cursor, cursor_color = self.bg_cursor,
|
||||
cursor_pos = self._private_cur_pos, cursor_ul = self.ul_cursor, select_all = self.select_all,
|
||||
prompt = self.prompt, highlighter = self.highlighter})
|
||||
|
||||
self._private.search_term = nil
|
||||
|
||||
history_check_load(self.history_path, self.history_max)
|
||||
local history_index = history_items(self.history_path) + 1
|
||||
|
||||
-- The completion element to use on completion request.
|
||||
local ncomp = 1
|
||||
|
||||
local command_before_comp
|
||||
local cur_pos_before_comp
|
||||
|
||||
self._private.grabber = keygrabber.run(function(modifiers, key, event)
|
||||
-- Convert index array to hash table
|
||||
local mod = {}
|
||||
for _, v in ipairs(modifiers) do mod[v] = true end
|
||||
|
||||
if event ~= "press" then
|
||||
if self.keyreleased_callback then
|
||||
self.keyreleased_callback(mod, key, self.command)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
-- Call the user specified callback. If it returns true as
|
||||
-- the first result then return from the function. Treat the
|
||||
-- second and third results as a new command and new prompt
|
||||
-- to be set (if provided)
|
||||
if self.keypressed_callback then
|
||||
local user_catched, new_command, new_prompt =
|
||||
self.keypressed_callback(mod, key, self.command)
|
||||
if new_command or new_prompt then
|
||||
if new_command then
|
||||
self.command = new_command
|
||||
end
|
||||
if new_prompt then
|
||||
self.prompt = new_prompt
|
||||
end
|
||||
update(self)
|
||||
end
|
||||
if user_catched then
|
||||
if self.changed_callback then
|
||||
self.changed_callback(self.command)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local filtered_modifiers = {}
|
||||
|
||||
-- User defined cases
|
||||
if self.hooks[key] then
|
||||
-- Remove caps and num lock
|
||||
for _, m in ipairs(modifiers) do
|
||||
if not gtable.hasitem(akey.ignore_modifiers, m) then
|
||||
table.insert(filtered_modifiers, m)
|
||||
end
|
||||
end
|
||||
|
||||
for _,v in ipairs(self.hooks[key]) do
|
||||
if #filtered_modifiers == #v[1] then
|
||||
local match = true
|
||||
for _,v2 in ipairs(v[1]) do
|
||||
match = match and mod[v2]
|
||||
end
|
||||
if match then
|
||||
local cb
|
||||
local ret, quit = v[3](self.command)
|
||||
local original_command = self.command
|
||||
|
||||
-- Support both a "simple" and a "complex" way to
|
||||
-- control if the prompt should quit.
|
||||
quit = quit == nil and (ret ~= true) or (quit~=false)
|
||||
|
||||
-- Allow the callback to change the command
|
||||
self.command = (ret ~= true) and ret or self.command
|
||||
|
||||
-- Quit by default, but allow it to be disabled
|
||||
if ret and type(ret) ~= "boolean" then
|
||||
cb = self.exe_callback
|
||||
if not quit then
|
||||
self._private_cur_pos = ret:wlen() + 1
|
||||
update(self)
|
||||
end
|
||||
elseif quit then
|
||||
-- No callback.
|
||||
cb = function() end
|
||||
end
|
||||
|
||||
-- Execute the callback
|
||||
if cb then
|
||||
exec(self, cb, original_command)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Get out cases
|
||||
if (mod.Control and (key == "c" or key == "g"))
|
||||
or (not mod.Control and key == "Escape") then
|
||||
self:stop()
|
||||
return false
|
||||
elseif (mod.Control and (key == "j" or key == "m"))
|
||||
-- or (not mod.Control and key == "Return")
|
||||
-- or (not mod.Control and key == "KP_Enter")
|
||||
then
|
||||
exec(self, self.exe_callback, self.command)
|
||||
-- We already unregistered ourselves so we don't want to return
|
||||
-- true, otherwise we may unregister someone else.
|
||||
return
|
||||
end
|
||||
|
||||
-- Control cases
|
||||
if mod.Control then
|
||||
self.select_all = nil
|
||||
if key == "v" then
|
||||
local selection = capi.selection()
|
||||
if selection then
|
||||
-- Remove \n
|
||||
local n = selection:find("\n")
|
||||
if n then
|
||||
selection = selection:sub(1, n - 1)
|
||||
end
|
||||
self.command = self.command:sub(1, self._private_cur_pos - 1) .. selection .. self.command:sub(self._private_cur_pos)
|
||||
self._private_cur_pos = self._private_cur_pos + #selection
|
||||
end
|
||||
elseif key == "a" then
|
||||
self._private_cur_pos = 1
|
||||
elseif key == "b" then
|
||||
if self._private_cur_pos > 1 then
|
||||
self._private_cur_pos = self._private_cur_pos - 1
|
||||
if have_multibyte_char_at(self.command, self._private_cur_pos) then
|
||||
self._private_cur_pos = self._private_cur_pos - 1
|
||||
end
|
||||
end
|
||||
elseif key == "d" then
|
||||
if self._private_cur_pos <= #self.command then
|
||||
self.command = self.command:sub(1, self._private_cur_pos - 1) .. self.command:sub(self._private_cur_pos + 1)
|
||||
end
|
||||
elseif key == "p" then
|
||||
if history_index > 1 then
|
||||
history_index = history_index - 1
|
||||
|
||||
self.command = data.history[self.history_path].table[history_index]
|
||||
self._private_cur_pos = #self.command + 2
|
||||
end
|
||||
elseif key == "n" then
|
||||
if history_index < history_items(self.history_path) then
|
||||
history_index = history_index + 1
|
||||
|
||||
self.command = data.history[self.history_path].table[history_index]
|
||||
self._private_cur_pos = #self.command + 2
|
||||
elseif history_index == history_items(self.history_path) then
|
||||
history_index = history_index + 1
|
||||
|
||||
self.command = ""
|
||||
self._private_cur_pos = 1
|
||||
end
|
||||
elseif key == "e" then
|
||||
self._private_cur_pos = #self.command + 1
|
||||
elseif key == "r" then
|
||||
self._private.search_term = self._private.search_term or self.command:sub(1, self._private_cur_pos - 1)
|
||||
for i,v in (function(a,i) return itera(-1,a,i) end), data.history[self.history_path].table, history_index do
|
||||
if v:find(self._private.search_term,1,true) ~= nil then
|
||||
self.command=v
|
||||
history_index=i
|
||||
self._private_cur_pos=#self.command+1
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif key == "s" then
|
||||
self._private.search_term = self._private.search_term or self.command:sub(1, self._private_cur_pos - 1)
|
||||
for i,v in (function(a,i) return itera(1,a,i) end), data.history[self.history_path].table, history_index do
|
||||
if v:find(self._private.search_term,1,true) ~= nil then
|
||||
self.command=v
|
||||
history_index=i
|
||||
self._private_cur_pos=#self.command+1
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif key == "f" then
|
||||
if self._private_cur_pos <= #self.command then
|
||||
if have_multibyte_char_at(self.command, self._private_cur_pos) then
|
||||
self._private_cur_pos = self._private_cur_pos + 2
|
||||
else
|
||||
self._private_cur_pos = self._private_cur_pos + 1
|
||||
end
|
||||
end
|
||||
elseif key == "h" then
|
||||
if self._private_cur_pos > 1 then
|
||||
local offset = 0
|
||||
if have_multibyte_char_at(self.command, self._private_cur_pos - 1) then
|
||||
offset = 1
|
||||
end
|
||||
self.command = self.command:sub(1, self._private_cur_pos - 2 - offset) .. self.command:sub(self._private_cur_pos)
|
||||
self._private_cur_pos = self._private_cur_pos - 1 - offset
|
||||
end
|
||||
elseif key == "k" then
|
||||
self.command = self.command:sub(1, self._private_cur_pos - 1)
|
||||
elseif key == "u" then
|
||||
self.command = self.command:sub(self._private_cur_pos, #self.command)
|
||||
self._private_cur_pos = 1
|
||||
elseif key == "Prior" then
|
||||
self._private.search_term = self.command:sub(1, self._private_cur_pos - 1) or ""
|
||||
for i,v in (function(a,i) return itera(-1,a,i) end), data.history[self.history_path].table, history_index do
|
||||
if v:find(self._private.search_term,1,true) == 1 then
|
||||
self.command=v
|
||||
history_index=i
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif key == "Next" then
|
||||
self._private.search_term = self.command:sub(1, self._private_cur_pos - 1) or ""
|
||||
for i,v in (function(a,i) return itera(1,a,i) end), data.history[self.history_path].table, history_index do
|
||||
if v:find(self._private.search_term,1,true) == 1 then
|
||||
self.command=v
|
||||
history_index=i
|
||||
break
|
||||
end
|
||||
end
|
||||
elseif key == "w" or key == "BackSpace" then
|
||||
local wstart = 1
|
||||
local wend = 1
|
||||
local cword_start_pos = 1
|
||||
local cword_end_pos = 1
|
||||
while wend < self._private_cur_pos do
|
||||
wend = self.command:find("[{[(,.:;_-+=@/ ]", wstart)
|
||||
if not wend then wend = #self.command + 1 end
|
||||
if self._private_cur_pos >= wstart and self._private_cur_pos <= wend + 1 then
|
||||
cword_start_pos = wstart
|
||||
cword_end_pos = self._private_cur_pos - 1
|
||||
break
|
||||
end
|
||||
wstart = wend + 1
|
||||
end
|
||||
self.command = self.command:sub(1, cword_start_pos - 1) .. self.command:sub(cword_end_pos + 1)
|
||||
self._private_cur_pos = cword_start_pos
|
||||
elseif key == "Delete" then
|
||||
-- delete from history only if:
|
||||
-- we are not dealing with a new command
|
||||
-- the user has not edited an existing entry
|
||||
if self.command == data.history[self.history_path].table[history_index] then
|
||||
table.remove(data.history[self.history_path].table, history_index)
|
||||
if history_index <= history_items(self.history_path) then
|
||||
self.command = data.history[self.history_path].table[history_index]
|
||||
self._private_cur_pos = #self.command + 2
|
||||
elseif history_index > 1 then
|
||||
history_index = history_index - 1
|
||||
|
||||
self.command = data.history[self.history_path].table[history_index]
|
||||
self._private_cur_pos = #self.command + 2
|
||||
else
|
||||
self.command = ""
|
||||
self._private_cur_pos = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif mod.Mod1 or mod.Mod3 then
|
||||
if key == "b" then
|
||||
self._private_cur_pos = cword_start(self.command, self._private_cur_pos)
|
||||
elseif key == "f" then
|
||||
self._private_cur_pos = cword_end(self.command, self._private_cur_pos)
|
||||
elseif key == "d" then
|
||||
self.command = self.command:sub(1, self._private_cur_pos - 1) .. self.command:sub(cword_end(self.command, self._private_cur_pos))
|
||||
elseif key == "BackSpace" then
|
||||
local wstart = cword_start(self.command, self._private_cur_pos)
|
||||
self.command = self.command:sub(1, wstart - 1) .. self.command:sub(self._private_cur_pos)
|
||||
self._private_cur_pos = wstart
|
||||
end
|
||||
else
|
||||
if self.completion_callback then
|
||||
if key == "Tab" or key == "ISO_Left_Tab" then
|
||||
if key == "ISO_Left_Tab" or mod.Shift then
|
||||
if ncomp == 1 then return end
|
||||
if ncomp == 2 then
|
||||
self.command = command_before_comp
|
||||
self.textbox:set_font(self.font)
|
||||
self.textbox:set_markup(prompt_text_with_cursor{
|
||||
text = command_before_comp, text_color = self.fg_cursor, cursor_color = self.bg_cursor,
|
||||
cursor_pos = self._private_cur_pos, cursor_ul = self.ul_cursor, select_all = self.select_all,
|
||||
prompt = self.prompt })
|
||||
self._private_cur_pos = cur_pos_before_comp
|
||||
ncomp = 1
|
||||
return
|
||||
end
|
||||
|
||||
ncomp = ncomp - 2
|
||||
elseif ncomp == 1 then
|
||||
command_before_comp = self.command
|
||||
cur_pos_before_comp = self._private_cur_pos
|
||||
end
|
||||
local matches
|
||||
self.command, self._private_cur_pos, matches = self.completion_callback(command_before_comp, cur_pos_before_comp, ncomp)
|
||||
ncomp = ncomp + 1
|
||||
key = ""
|
||||
-- execute if only one match found and autoexec flag set
|
||||
if matches and #matches == 1 and args.autoexec then
|
||||
exec(self, self.exe_callback)
|
||||
return
|
||||
end
|
||||
elseif key ~= "Shift_L" and key ~= "Shift_R" then
|
||||
ncomp = 1
|
||||
end
|
||||
end
|
||||
|
||||
-- Typin cases
|
||||
if mod.Shift and key == "Insert" then
|
||||
local selection = capi.selection()
|
||||
if selection then
|
||||
-- Remove \n
|
||||
local n = selection:find("\n")
|
||||
if n then
|
||||
selection = selection:sub(1, n - 1)
|
||||
end
|
||||
self.command = self.command:sub(1, self._private_cur_pos - 1) .. selection .. self.command:sub(self._private_cur_pos)
|
||||
self._private_cur_pos = self._private_cur_pos + #selection
|
||||
end
|
||||
elseif key == "Home" then
|
||||
self._private_cur_pos = 1
|
||||
elseif key == "End" then
|
||||
self._private_cur_pos = #self.command + 1
|
||||
elseif key == "BackSpace" then
|
||||
if self._private_cur_pos > 1 then
|
||||
local offset = 0
|
||||
if have_multibyte_char_at(self.command, self._private_cur_pos - 1) then
|
||||
offset = 1
|
||||
end
|
||||
self.command = self.command:sub(1, self._private_cur_pos - 2 - offset) .. self.command:sub(self._private_cur_pos)
|
||||
self._private_cur_pos = self._private_cur_pos - 1 - offset
|
||||
end
|
||||
elseif key == "Delete" then
|
||||
self.command = self.command:sub(1, self._private_cur_pos - 1) .. self.command:sub(self._private_cur_pos + 1)
|
||||
elseif key == "Left" then
|
||||
self._private_cur_pos = self._private_cur_pos - 1
|
||||
elseif key == "Right" then
|
||||
self._private_cur_pos = self._private_cur_pos + 1
|
||||
elseif key == "Prior" then
|
||||
if history_index > 1 then
|
||||
history_index = history_index - 1
|
||||
|
||||
self.command = data.history[self.history_path].table[history_index]
|
||||
self._private_cur_pos = #self.command + 2
|
||||
end
|
||||
elseif key == "Next" then
|
||||
if history_index < history_items(self.history_path) then
|
||||
history_index = history_index + 1
|
||||
|
||||
self.command = data.history[self.history_path].table[history_index]
|
||||
self._private_cur_pos = #self.command + 2
|
||||
elseif history_index == history_items(self.history_path) then
|
||||
history_index = history_index + 1
|
||||
|
||||
self.command = ""
|
||||
self._private_cur_pos = 1
|
||||
end
|
||||
else
|
||||
-- wlen() is UTF-8 aware but #key is not,
|
||||
-- so check that we have one UTF-8 char but advance the cursor of # position
|
||||
if key:wlen() == 1 then
|
||||
if self.select_all then self.command = "" end
|
||||
self.command = self.command:sub(1, self._private_cur_pos - 1) .. key .. self.command:sub(self._private_cur_pos)
|
||||
self._private_cur_pos = self._private_cur_pos + #key
|
||||
end
|
||||
end
|
||||
if self._private_cur_pos < 1 then
|
||||
self._private_cur_pos = 1
|
||||
elseif self._private_cur_pos > #self.command + 1 then
|
||||
self._private_cur_pos = #self.command + 1
|
||||
end
|
||||
self.select_all = nil
|
||||
end
|
||||
|
||||
update(self)
|
||||
if self.changed_callback then
|
||||
self.changed_callback(self.command)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function prompt:stop()
|
||||
keygrabber.stop(self._private.grabber)
|
||||
history_save(self.history_path)
|
||||
if self.done_callback then self.done_callback() end
|
||||
return false
|
||||
end
|
||||
|
||||
local function new(args)
|
||||
args = args or {}
|
||||
|
||||
args.command = args.text or ""
|
||||
args.prompt = args.prompt or ""
|
||||
args.text = args.text or ""
|
||||
args.font = args.font or beautiful.prompt_font or beautiful.font
|
||||
args.bg_cursor = args.bg_cursor or beautiful.prompt_bg_cursor or beautiful.bg_focus or "white"
|
||||
args.fg_cursor = args.fg_cursor or beautiful.prompt_fg_cursor or beautiful.fg_focus or "black"
|
||||
args.ul_cursor = args.ul_cursor or nil
|
||||
args.reset_on_stop = args.reset_on_stop == nil and true or args.reset_on_stop
|
||||
args.select_all = args.select_all or nil
|
||||
args.highlighter = args.highlighter or nil
|
||||
args.hooks = args.hooks or {}
|
||||
args.keypressed_callback = args.keypressed_callback or nil
|
||||
args.changed_callback = args.changed_callback or nil
|
||||
args.done_callback = args.done_callback or nil
|
||||
args.history_max = args.history_max or nil
|
||||
args.history_path = args.history_path or nil
|
||||
args.completion_callback = args.completion_callback or nil
|
||||
args.exe_callback = args.exe_callback or nil
|
||||
args.textbox = args.textbox or wibox.widget.textbox()
|
||||
|
||||
-- Build the hook map
|
||||
local hooks = {}
|
||||
for _,v in ipairs(args.hooks) do
|
||||
if #v == 3 then
|
||||
local _,key,callback = unpack(v)
|
||||
if type(callback) == "function" then
|
||||
hooks[key] = hooks[key] or {}
|
||||
hooks[key][#hooks[key]+1] = v
|
||||
else
|
||||
gdebug.print_warning("The hook's 3rd parameter has to be a function.")
|
||||
end
|
||||
else
|
||||
gdebug.print_warning("The hook has to have 3 parameters.")
|
||||
end
|
||||
end
|
||||
args.hooks = hooks
|
||||
|
||||
local ret = gobject({})
|
||||
ret._private = {}
|
||||
gtable.crush(ret, prompt)
|
||||
gtable.crush(ret, args)
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
function prompt.mt:__call(...)
|
||||
return new(...)
|
||||
end
|
||||
|
||||
return setmetatable(prompt, prompt.mt)
|
7
home/.config/awesome/libs/bling/widget/init.lua
Normal file
7
home/.config/awesome/libs/bling/widget/init.lua
Normal file
|
@ -0,0 +1,7 @@
|
|||
return {
|
||||
tag_preview = require(... .. ".tag_preview"),
|
||||
task_preview = require(... .. ".task_preview"),
|
||||
window_switcher = require(... .. ".window_switcher"),
|
||||
tabbed_misc = require(... .. ".tabbed_misc"),
|
||||
app_launcher = require(... .. ".app_launcher"),
|
||||
}
|
57
home/.config/awesome/libs/bling/widget/tabbar/boxes.lua
Normal file
57
home/.config/awesome/libs/bling/widget/tabbar/boxes.lua
Normal file
|
@ -0,0 +1,57 @@
|
|||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local wibox = require("wibox")
|
||||
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
local bg_normal = beautiful.tabbar_bg_normal or beautiful.bg_normal or "#ffffff"
|
||||
local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000"
|
||||
local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000"
|
||||
local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff"
|
||||
local bg_focus_inactive = beautiful.tabbar_bg_focus_inactive or bg_focus
|
||||
local fg_focus_inactive = beautiful.tabbar_fg_focus_inactive or fg_focus
|
||||
local bg_normal_inactive = beautiful.tabbar_bg_normal_inactive or bg_normal
|
||||
local fg_normal_inactive = beautiful.tabbar_fg_normal_inactive or fg_normal
|
||||
local font = beautiful.tabbar_font or beautiful.font or "Hack 15"
|
||||
local size = beautiful.tabbar_size or 40
|
||||
local position = beautiful.tabbar_position or "bottom"
|
||||
|
||||
local function create(c, focused_bool, buttons, inactive_bool)
|
||||
local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
|
||||
local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
|
||||
if focused_bool then
|
||||
bg_temp = inactive_bool and bg_focus_inactive or bg_focus
|
||||
fg_temp = inactive_bool and fg_focus_inactive or fg_focus
|
||||
end
|
||||
local wid_temp = wibox.widget({
|
||||
{
|
||||
{
|
||||
awful.widget.clienticon(c),
|
||||
left = 10,
|
||||
right = 10,
|
||||
bottom = 10,
|
||||
top = 10,
|
||||
widget = wibox.container.margin(),
|
||||
},
|
||||
widget = wibox.container.place(),
|
||||
},
|
||||
buttons = buttons,
|
||||
bg = bg_temp,
|
||||
widget = wibox.container.background(),
|
||||
})
|
||||
return wid_temp
|
||||
end
|
||||
|
||||
local layout = wibox.layout.fixed.horizontal
|
||||
if position == "left" or position == "right" then
|
||||
layout = wibox.layout.fixed.vertical
|
||||
end
|
||||
|
||||
return {
|
||||
layout = layout,
|
||||
create = create,
|
||||
position = position,
|
||||
size = size,
|
||||
bg_normal = bg_normal,
|
||||
bg_focus = bg_normal,
|
||||
}
|
60
home/.config/awesome/libs/bling/widget/tabbar/default.lua
Normal file
60
home/.config/awesome/libs/bling/widget/tabbar/default.lua
Normal file
|
@ -0,0 +1,60 @@
|
|||
local gears = require("gears")
|
||||
local wibox = require("wibox")
|
||||
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
local bg_normal = beautiful.tabbar_bg_normal or beautiful.bg_normal or "#ffffff"
|
||||
local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000"
|
||||
local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000"
|
||||
local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff"
|
||||
local bg_focus_inactive = beautiful.tabbar_bg_focus_inactive or bg_focus
|
||||
local fg_focus_inactive = beautiful.tabbar_fg_focus_inactive or fg_focus
|
||||
local bg_normal_inactive = beautiful.tabbar_bg_normal_inactive or bg_normal
|
||||
local fg_normal_inactive = beautiful.tabbar_fg_normal_inactive or fg_normal
|
||||
local font = beautiful.tabbar_font or beautiful.font or "Hack 15"
|
||||
local size = beautiful.tabbar_size or 20
|
||||
local position = beautiful.tabbar_position or "top"
|
||||
|
||||
local function create(c, focused_bool, buttons, inactive_bool)
|
||||
local flexlist = wibox.layout.flex.horizontal()
|
||||
local title_temp = c.name or c.class or "-"
|
||||
local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
|
||||
local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
|
||||
if focused_bool then
|
||||
bg_temp = inactive_bool and bg_focus_inactive or bg_focus
|
||||
fg_temp = inactive_bool and fg_focus_inactive or fg_focus
|
||||
end
|
||||
local text_temp = wibox.widget.textbox()
|
||||
text_temp.align = "center"
|
||||
text_temp.valign = "center"
|
||||
text_temp.font = font
|
||||
text_temp.markup = "<span foreground='"
|
||||
.. fg_temp
|
||||
.. "'>"
|
||||
.. title_temp
|
||||
.. "</span>"
|
||||
c:connect_signal("property::name", function(_)
|
||||
local title_temp = c.name or c.class or "-"
|
||||
text_temp.markup = "<span foreground='"
|
||||
.. fg_temp
|
||||
.. "'>"
|
||||
.. title_temp
|
||||
.. "</span>"
|
||||
end)
|
||||
local wid_temp = wibox.widget({
|
||||
text_temp,
|
||||
buttons = buttons,
|
||||
bg = bg_temp,
|
||||
widget = wibox.container.background(),
|
||||
})
|
||||
return wid_temp
|
||||
end
|
||||
|
||||
return {
|
||||
layout = wibox.layout.flex.horizontal,
|
||||
create = create,
|
||||
position = position,
|
||||
size = size,
|
||||
bg_normal = bg_normal,
|
||||
bg_focus = bg_focus,
|
||||
}
|
271
home/.config/awesome/libs/bling/widget/tabbar/modern.lua
Normal file
271
home/.config/awesome/libs/bling/widget/tabbar/modern.lua
Normal file
|
@ -0,0 +1,271 @@
|
|||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local wibox = require("wibox")
|
||||
local beautiful = require("beautiful")
|
||||
local xresources = require("beautiful.xresources")
|
||||
local dpi = xresources.apply_dpi
|
||||
local helpers = require(tostring(...):match(".*bling") .. ".helpers")
|
||||
|
||||
local bg_normal = beautiful.tabbar_bg_normal or beautiful.bg_normal or "#ffffff"
|
||||
local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000"
|
||||
local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000"
|
||||
local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff"
|
||||
local bg_focus_inactive = beautiful.tabbar_bg_focus_inactive or bg_focus
|
||||
local fg_focus_inactive = beautiful.tabbar_fg_focus_inactive or fg_focus
|
||||
local bg_normal_inactive = beautiful.tabbar_bg_normal_inactive or bg_normal
|
||||
local fg_normal_inactive = beautiful.tabbar_fg_normal_inactive or fg_normal
|
||||
local font = beautiful.tabbar_font or beautiful.font or "Hack 15"
|
||||
local size = beautiful.tabbar_size or dpi(40)
|
||||
local border_radius = beautiful.mstab_border_radius
|
||||
or beautiful.border_radius
|
||||
or 6
|
||||
local position = beautiful.tabbar_position or "top"
|
||||
local close_color = beautiful.tabbar_color_close
|
||||
or beautiful.xcolor1
|
||||
or "#f9929b"
|
||||
local min_color = beautiful.tabbar_color_min or beautiful.xcolor3 or "#fbdf90"
|
||||
local float_color = beautiful.tabbar_color_float
|
||||
or beautiful.xcolor5
|
||||
or "#ccaced"
|
||||
|
||||
-- Helper to create buttons
|
||||
local function create_title_button(c, color_focus, color_unfocus)
|
||||
local tb_color = wibox.widget({
|
||||
wibox.widget.textbox(),
|
||||
forced_width = dpi(8),
|
||||
forced_height = dpi(8),
|
||||
bg = color_focus,
|
||||
shape = gears.shape.circle,
|
||||
widget = wibox.container.background,
|
||||
})
|
||||
|
||||
local tb = wibox.widget({
|
||||
tb_color,
|
||||
width = dpi(25),
|
||||
height = dpi(25),
|
||||
strategy = "min",
|
||||
layout = wibox.layout.constraint,
|
||||
})
|
||||
|
||||
local function update()
|
||||
if client.focus == c then
|
||||
tb_color.bg = color_focus
|
||||
else
|
||||
tb_color.bg = color_unfocus
|
||||
end
|
||||
end
|
||||
update()
|
||||
c:connect_signal("focus", update)
|
||||
c:connect_signal("unfocus", update)
|
||||
|
||||
tb:connect_signal("mouse::enter", function()
|
||||
tb_color.bg = color_focus .. "70"
|
||||
end)
|
||||
|
||||
tb:connect_signal("mouse::leave", function()
|
||||
tb_color.bg = color_focus
|
||||
end)
|
||||
|
||||
tb.visible = true
|
||||
return tb
|
||||
end
|
||||
|
||||
local function create(c, focused_bool, buttons, inactive_bool)
|
||||
-- local flexlist = wibox.layout.flex.horizontal()
|
||||
local title_temp = c.name or c.class or "-"
|
||||
local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
|
||||
local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
|
||||
if focused_bool then
|
||||
bg_temp = inactive_bool and bg_focus_inactive or bg_focus
|
||||
fg_temp = inactive_bool and fg_focus_inactive or fg_focus
|
||||
end
|
||||
local text_temp = wibox.widget.textbox()
|
||||
text_temp.align = "center"
|
||||
text_temp.valign = "center"
|
||||
text_temp.font = font
|
||||
text_temp.markup = "<span foreground='"
|
||||
.. fg_temp
|
||||
.. "'>"
|
||||
.. title_temp
|
||||
.. "</span>"
|
||||
c:connect_signal("property::name", function(_)
|
||||
local title_temp = c.name or c.class or "-"
|
||||
text_temp.markup = "<span foreground='"
|
||||
.. fg_temp
|
||||
.. "'>"
|
||||
.. title_temp
|
||||
.. "</span>"
|
||||
end)
|
||||
|
||||
local tab_content = wibox.widget({
|
||||
{
|
||||
awful.widget.clienticon(c),
|
||||
top = dpi(6),
|
||||
left = dpi(15),
|
||||
bottom = dpi(6),
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
text_temp,
|
||||
nill,
|
||||
expand = "none",
|
||||
layout = wibox.layout.align.horizontal,
|
||||
})
|
||||
|
||||
local close = create_title_button(c, close_color, bg_normal)
|
||||
close:connect_signal("button::press", function()
|
||||
c:kill()
|
||||
end)
|
||||
|
||||
local floating = create_title_button(c, float_color, bg_normal)
|
||||
floating:connect_signal("button::press", function()
|
||||
c.floating = not c.floating
|
||||
end)
|
||||
|
||||
local min = create_title_button(c, min_color, bg_normal)
|
||||
min:connect_signal("button::press", function()
|
||||
c.minimized = true
|
||||
end)
|
||||
|
||||
if focused_bool then
|
||||
tab_content = wibox.widget({
|
||||
{
|
||||
awful.widget.clienticon(c),
|
||||
top = dpi(10),
|
||||
left = dpi(15),
|
||||
bottom = dpi(10),
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
text_temp,
|
||||
{
|
||||
{ min, floating, close, layout = wibox.layout.fixed.horizontal },
|
||||
top = dpi(10),
|
||||
right = dpi(10),
|
||||
bottom = dpi(10),
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
expand = "none",
|
||||
layout = wibox.layout.align.horizontal,
|
||||
})
|
||||
end
|
||||
|
||||
local main_content = nil
|
||||
local left_shape = nil
|
||||
local right_shape = nil
|
||||
|
||||
if position == "top" then
|
||||
main_content = wibox.widget({
|
||||
{
|
||||
tab_content,
|
||||
bg = bg_temp,
|
||||
shape = helpers.shape.prrect(
|
||||
border_radius,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
),
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
top = dpi(8),
|
||||
widget = wibox.container.margin,
|
||||
})
|
||||
|
||||
left_shape = helpers.shape.prrect(
|
||||
border_radius,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
false
|
||||
)
|
||||
right_shape = helpers.shape.prrect(
|
||||
border_radius,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
)
|
||||
else
|
||||
main_content = wibox.widget({
|
||||
{
|
||||
tab_content,
|
||||
bg = bg_temp,
|
||||
shape = helpers.shape.prrect(
|
||||
border_radius,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
),
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
bottom = dpi(8),
|
||||
widget = wibox.container.margin,
|
||||
})
|
||||
|
||||
left_shape = helpers.shape.prrect(
|
||||
border_radius,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
)
|
||||
right_shape = helpers.shape.prrect(
|
||||
border_radius,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false
|
||||
)
|
||||
end
|
||||
|
||||
local wid_temp = wibox.widget({
|
||||
buttons = buttons,
|
||||
{
|
||||
{
|
||||
{
|
||||
wibox.widget.textbox(),
|
||||
bg = bg_normal,
|
||||
shape = left_shape,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
bg = bg_temp,
|
||||
shape = gears.rectangle,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
width = border_radius + (border_radius / 2),
|
||||
height = size,
|
||||
strategy = "exact",
|
||||
layout = wibox.layout.constraint,
|
||||
},
|
||||
main_content,
|
||||
{
|
||||
{
|
||||
{
|
||||
wibox.widget.textbox(),
|
||||
bg = bg_normal,
|
||||
shape = right_shape,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
bg = bg_temp,
|
||||
shape = gears.rectangle,
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
width = border_radius + (border_radius / 2),
|
||||
height = size,
|
||||
strategy = "exact",
|
||||
layout = wibox.layout.constraint,
|
||||
},
|
||||
|
||||
layout = wibox.layout.align.horizontal,
|
||||
})
|
||||
return wid_temp
|
||||
end
|
||||
|
||||
return {
|
||||
layout = wibox.layout.flex.horizontal,
|
||||
create = create,
|
||||
position = position,
|
||||
size = size,
|
||||
bg_normal = bg_normal,
|
||||
bg_focus = bg_focus,
|
||||
}
|
81
home/.config/awesome/libs/bling/widget/tabbar/pure.lua
Normal file
81
home/.config/awesome/libs/bling/widget/tabbar/pure.lua
Normal file
|
@ -0,0 +1,81 @@
|
|||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local wibox = require("wibox")
|
||||
local gcolor = require("gears.color")
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
local bg_normal = beautiful.tabbar_bg_normal or beautiful.bg_normal or "#ffffff"
|
||||
local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000"
|
||||
local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000"
|
||||
local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff"
|
||||
local bg_focus_inactive = beautiful.tabbar_bg_focus_inactive or bg_focus
|
||||
local fg_focus_inactive = beautiful.tabbar_fg_focus_inactive or fg_focus
|
||||
local bg_normal_inactive = beautiful.tabbar_bg_normal_inactive or bg_normal
|
||||
local fg_normal_inactive = beautiful.tabbar_fg_normal_inactive or fg_normal
|
||||
local font = beautiful.tabbar_font or beautiful.font or "Hack 15"
|
||||
local size = beautiful.tabbar_size or 20
|
||||
local position = beautiful.tabbar_position or "top"
|
||||
|
||||
local function create(c, focused_bool, buttons, inactive_bool)
|
||||
local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
|
||||
local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
|
||||
if focused_bool then
|
||||
bg_temp = inactive_bool and bg_focus_inactive or bg_focus
|
||||
fg_temp = inactive_bool and fg_focus_inactive or fg_focus
|
||||
end
|
||||
|
||||
local wid_temp = wibox.widget({
|
||||
{
|
||||
{ -- Left
|
||||
wibox.widget.base.make_widget(
|
||||
awful.titlebar.widget.iconwidget(c)
|
||||
),
|
||||
buttons = buttons,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
{ -- Title
|
||||
wibox.widget.base.make_widget(
|
||||
awful.titlebar.widget.titlewidget(c)
|
||||
),
|
||||
buttons = buttons,
|
||||
widget = wibox.container.place,
|
||||
},
|
||||
{ -- Right
|
||||
focused_bool and wibox.widget.base.make_widget(
|
||||
awful.titlebar.widget.floatingbutton(c)
|
||||
) or nil,
|
||||
focused_bool and wibox.widget.base.make_widget(
|
||||
awful.titlebar.widget.stickybutton(c)
|
||||
) or nil,
|
||||
focused_bool and wibox.widget.base.make_widget(
|
||||
awful.titlebar.widget.ontopbutton(c)
|
||||
) or nil,
|
||||
focused_bool and wibox.widget.base.make_widget(
|
||||
awful.titlebar.widget.maximizedbutton(c)
|
||||
) or nil,
|
||||
focused_bool and wibox.widget.base.make_widget(
|
||||
awful.titlebar.widget.minimizebutton(c)
|
||||
) or nil,
|
||||
focused_bool and wibox.widget.base.make_widget(
|
||||
awful.titlebar.widget.closebutton(c)
|
||||
) or nil,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
layout = wibox.layout.align.horizontal,
|
||||
},
|
||||
bg = bg_temp,
|
||||
fg = fg_temp,
|
||||
widget = wibox.container.background,
|
||||
})
|
||||
|
||||
return wid_temp
|
||||
end
|
||||
|
||||
return {
|
||||
layout = wibox.layout.flex.horizontal,
|
||||
create = create,
|
||||
position = position,
|
||||
size = size,
|
||||
bg_normal = bg_normal,
|
||||
bg_focus = bg_focus,
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
local wibox = require("wibox")
|
||||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local beautiful = require("beautiful")
|
||||
local dpi = require("beautiful.xresources").apply_dpi
|
||||
|
||||
local function tabobj_support(self, c, index, clients)
|
||||
-- Self is the background widget in this context
|
||||
if not c.bling_tabbed and #c.bling_tabbed.clients > 1 then
|
||||
return
|
||||
end
|
||||
|
||||
local group = c.bling_tabbed
|
||||
|
||||
-- TODO: Allow customization here
|
||||
local layout_v = wibox.widget {
|
||||
vertical_spacing = dpi(2),
|
||||
horizontal_spacing = dpi(2),
|
||||
layout = wibox.layout.grid.horizontal,
|
||||
forced_num_rows = 2,
|
||||
forced_num_cols = 2,
|
||||
homogeneous = true
|
||||
}
|
||||
|
||||
local wrapper = wibox.widget({
|
||||
layout_v,
|
||||
id = "click_role",
|
||||
widget = wibox.container.margin,
|
||||
margins = dpi(5),
|
||||
})
|
||||
|
||||
-- To get the ball rolling.
|
||||
for idx, c in ipairs(group.clients) do
|
||||
if not (c and c.icon) then goto skip end
|
||||
|
||||
-- Add to the last layout
|
||||
layout_v:add(wibox.widget {
|
||||
{
|
||||
widget = awful.widget.clienticon,
|
||||
client = c
|
||||
},
|
||||
widget = wibox.container.constraint,
|
||||
width = dpi(24),
|
||||
height = dpi(24)
|
||||
})
|
||||
::skip::
|
||||
end
|
||||
self.widget = wrapper
|
||||
end
|
||||
|
||||
return tabobj_support
|
|
@ -0,0 +1,9 @@
|
|||
return {
|
||||
titlebar_indicator = require(
|
||||
tostring(...):match(".*bling")
|
||||
.. ".widget.tabbed_misc.titlebar_indicator"
|
||||
),
|
||||
custom_tasklist = require(
|
||||
tostring(...):match(".*bling") .. ".widget.tabbed_misc.custom_tasklist"
|
||||
),
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
local wibox = require("wibox")
|
||||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local beautiful = require("beautiful")
|
||||
local dpi = require("beautiful.xresources").apply_dpi
|
||||
local tabbed_module = require(
|
||||
tostring(...):match(".*bling") .. ".module.tabbed"
|
||||
)
|
||||
|
||||
-- Just check if a table contains a value.
|
||||
local function tbl_contains(tbl, item)
|
||||
for _, v in ipairs(tbl) do
|
||||
if v == item then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Needs to be run, every time a new titlbear is created
|
||||
return function(c, opts)
|
||||
-- Args & Fallback -- Widget templates are in their original loactions
|
||||
opts = gears.table.crush({
|
||||
layout_spacing = dpi(4),
|
||||
icon_size = dpi(20),
|
||||
icon_margin = dpi(4),
|
||||
bg_color_focus = "#ff0000",
|
||||
bg_color = "#00000000",
|
||||
fg_color = "#fafafa",
|
||||
fg_color_focus = "#e0e0e0",
|
||||
icon_shape = function(cr, w, h)
|
||||
gears.shape.rounded_rect(cr, w, h, 0)
|
||||
end,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
}, gears.table.join(
|
||||
opts,
|
||||
beautiful.bling_tabbed_misc_titlebar_indicator
|
||||
))
|
||||
|
||||
-- Container to store icons
|
||||
local tabbed_icons = wibox.widget({
|
||||
layout = opts.layout,
|
||||
spacing = opts.layout_spacing,
|
||||
})
|
||||
|
||||
awesome.connect_signal("bling::tabbed::client_removed", function(_, removed_c)
|
||||
-- Remove from list
|
||||
for idx, icon in ipairs(tabbed_icons.children) do
|
||||
if icon._client == removed_c then
|
||||
tabbed_icons:remove(idx)
|
||||
end
|
||||
end
|
||||
|
||||
-- Empty list
|
||||
if removed_c == c then
|
||||
tabbed_icons:reset()
|
||||
end
|
||||
end)
|
||||
|
||||
local function recreate(group)
|
||||
if tbl_contains(group.clients, c) then
|
||||
tabbed_icons:reset()
|
||||
local focused = group.clients[group.focused_idx]
|
||||
|
||||
-- Autohide?
|
||||
if #group.clients == 1 then
|
||||
return
|
||||
end
|
||||
|
||||
for idx, client in ipairs(group.clients) do
|
||||
local widget = wibox.widget(
|
||||
opts.widget_template or {
|
||||
{
|
||||
{
|
||||
{
|
||||
id = "icon_role",
|
||||
forced_width = opts.icon_size,
|
||||
forced_height = opts.icon_size,
|
||||
widget = awful.widget.clienticon,
|
||||
},
|
||||
margins = opts.icon_margin,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
shape = opts.icon_shape,
|
||||
id = "bg_role",
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
halign = "center",
|
||||
valign = "center",
|
||||
widget = wibox.container.place,
|
||||
})
|
||||
|
||||
widget._client = client
|
||||
|
||||
-- No creation call back since this would be called on creation & every time the widget updated.
|
||||
if opts.widget_template and opts.widget_template.update_callback then
|
||||
opts.widget_template.update_callback(widget, client, group)
|
||||
end
|
||||
|
||||
-- Add icons & etc
|
||||
for _, w in ipairs(widget:get_children_by_id("icon_role")) do
|
||||
-- TODO: Allow fallback icon?
|
||||
w.image = client.icon
|
||||
w.client = client
|
||||
end
|
||||
|
||||
for _, w in ipairs(widget:get_children_by_id("bg_role")) do
|
||||
w:add_button(awful.button({}, 1, function()
|
||||
tabbed_module.switch_to(group, idx)
|
||||
end))
|
||||
if client == focused then
|
||||
w.bg = opts.bg_color_focus
|
||||
w.fg = opts.fg_color_focus
|
||||
else
|
||||
w.bg = opts.bg_color
|
||||
w.fg = opts.fg_color
|
||||
end
|
||||
end
|
||||
|
||||
for _, w in ipairs(widget:get_children_by_id("text_role")) do
|
||||
w.text = client.name
|
||||
end
|
||||
|
||||
tabbed_icons:add(widget)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
awesome.connect_signal("bling::tabbed::client_added", recreate)
|
||||
awesome.connect_signal("bling::tabbed::changed_focus", recreate)
|
||||
|
||||
return tabbed_icons
|
||||
end
|
246
home/.config/awesome/libs/bling/widget/tag_preview.lua
Normal file
246
home/.config/awesome/libs/bling/widget/tag_preview.lua
Normal file
|
@ -0,0 +1,246 @@
|
|||
--
|
||||
-- Provides:
|
||||
-- bling::tag_preview::update -- first line is the signal
|
||||
-- t (tag) -- indented lines are function parameters
|
||||
-- bling::tag_preview::visibility
|
||||
-- s (screen)
|
||||
-- v (boolean)
|
||||
--
|
||||
local awful = require("awful")
|
||||
local wibox = require("wibox")
|
||||
local helpers = require(tostring(...):match(".*bling") .. ".helpers")
|
||||
local gears = require("gears")
|
||||
local beautiful = require("beautiful")
|
||||
local dpi = beautiful.xresources.apply_dpi
|
||||
local cairo = require("lgi").cairo
|
||||
|
||||
local function draw_widget(
|
||||
t,
|
||||
tag_preview_image,
|
||||
scale,
|
||||
screen_radius,
|
||||
client_radius,
|
||||
client_opacity,
|
||||
client_bg,
|
||||
client_border_color,
|
||||
client_border_width,
|
||||
widget_bg,
|
||||
widget_border_color,
|
||||
widget_border_width,
|
||||
geo,
|
||||
margin,
|
||||
background_image
|
||||
)
|
||||
local client_list = wibox.layout.manual()
|
||||
client_list.forced_height = geo.height
|
||||
client_list.forced_width = geo.width
|
||||
local tag_screen = t.screen
|
||||
for i, c in ipairs(t:clients()) do
|
||||
if not c.hidden and not c.minimized then
|
||||
|
||||
|
||||
local img_box = wibox.widget ({
|
||||
resize = true,
|
||||
forced_height = 100 * scale,
|
||||
forced_width = 100 * scale,
|
||||
widget = wibox.widget.imagebox,
|
||||
})
|
||||
|
||||
-- If fails to set image, fallback to a awesome icon
|
||||
if not pcall(function() img_box.image = gears.surface.load(c.icon) end) then
|
||||
img_box.image = beautiful.theme_assets.awesome_icon (24, "#222222", "#fafafa")
|
||||
end
|
||||
|
||||
if tag_preview_image then
|
||||
if c.prev_content or t.selected then
|
||||
local content
|
||||
if t.selected then
|
||||
content = gears.surface(c.content)
|
||||
else
|
||||
content = gears.surface(c.prev_content)
|
||||
end
|
||||
local cr = cairo.Context(content)
|
||||
local x, y, w, h = cr:clip_extents()
|
||||
local img = cairo.ImageSurface.create(
|
||||
cairo.Format.ARGB32,
|
||||
w - x,
|
||||
h - y
|
||||
)
|
||||
cr = cairo.Context(img)
|
||||
cr:set_source_surface(content, 0, 0)
|
||||
cr.operator = cairo.Operator.SOURCE
|
||||
cr:paint()
|
||||
|
||||
img_box = wibox.widget({
|
||||
image = gears.surface.load(img),
|
||||
resize = true,
|
||||
opacity = client_opacity,
|
||||
forced_height = math.floor(c.height * scale),
|
||||
forced_width = math.floor(c.width * scale),
|
||||
widget = wibox.widget.imagebox,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
local client_box = wibox.widget({
|
||||
{
|
||||
nil,
|
||||
{
|
||||
nil,
|
||||
img_box,
|
||||
nil,
|
||||
expand = "outside",
|
||||
layout = wibox.layout.align.horizontal,
|
||||
},
|
||||
nil,
|
||||
expand = "outside",
|
||||
widget = wibox.layout.align.vertical,
|
||||
},
|
||||
forced_height = math.floor(c.height * scale),
|
||||
forced_width = math.floor(c.width * scale),
|
||||
bg = client_bg,
|
||||
shape_border_color = client_border_color,
|
||||
shape_border_width = client_border_width,
|
||||
shape = helpers.shape.rrect(client_radius),
|
||||
widget = wibox.container.background,
|
||||
})
|
||||
|
||||
client_box.point = {
|
||||
x = math.floor((c.x - geo.x) * scale),
|
||||
y = math.floor((c.y - geo.y) * scale),
|
||||
}
|
||||
|
||||
client_list:add(client_box)
|
||||
end
|
||||
end
|
||||
|
||||
return wibox.widget {
|
||||
{
|
||||
background_image,
|
||||
{
|
||||
{
|
||||
{
|
||||
{
|
||||
client_list,
|
||||
forced_height = geo.height,
|
||||
forced_width = geo.width,
|
||||
widget = wibox.container.place,
|
||||
},
|
||||
layout = wibox.layout.align.horizontal,
|
||||
},
|
||||
layout = wibox.layout.align.vertical,
|
||||
},
|
||||
margins = margin,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
layout = wibox.layout.stack
|
||||
},
|
||||
bg = widget_bg,
|
||||
shape_border_width = widget_border_width,
|
||||
shape_border_color = widget_border_color,
|
||||
shape = helpers.shape.rrect(screen_radius),
|
||||
widget = wibox.container.background,
|
||||
}
|
||||
end
|
||||
|
||||
local enable = function(opts)
|
||||
local opts = opts or {}
|
||||
|
||||
local tag_preview_image = opts.show_client_content or false
|
||||
local widget_x = opts.x or dpi(20)
|
||||
local widget_y = opts.y or dpi(20)
|
||||
local scale = opts.scale or 0.2
|
||||
local work_area = opts.honor_workarea or false
|
||||
local padding = opts.honor_padding or false
|
||||
local placement_fn = opts.placement_fn or nil
|
||||
local background_image = opts.background_widget or nil
|
||||
|
||||
local margin = beautiful.tag_preview_widget_margin or dpi(0)
|
||||
local screen_radius = beautiful.tag_preview_widget_border_radius or dpi(0)
|
||||
local client_radius = beautiful.tag_preview_client_border_radius or dpi(0)
|
||||
local client_opacity = beautiful.tag_preview_client_opacity or 0.5
|
||||
local client_bg = beautiful.tag_preview_client_bg or "#000000"
|
||||
local client_border_color = beautiful.tag_preview_client_border_color
|
||||
or "#ffffff"
|
||||
local client_border_width = beautiful.tag_preview_client_border_width
|
||||
or dpi(3)
|
||||
local widget_bg = beautiful.tag_preview_widget_bg or "#000000"
|
||||
local widget_border_color = beautiful.tag_preview_widget_border_color
|
||||
or "#ffffff"
|
||||
local widget_border_width = beautiful.tag_preview_widget_border_width
|
||||
or dpi(3)
|
||||
|
||||
local tag_preview_box = awful.popup({
|
||||
type = "dropdown_menu",
|
||||
visible = false,
|
||||
ontop = true,
|
||||
placement = placement_fn,
|
||||
widget = wibox.container.background,
|
||||
input_passthrough = true,
|
||||
bg = "#00000000",
|
||||
})
|
||||
|
||||
tag.connect_signal("property::selected", function(t)
|
||||
-- Awesome switches up tags on startup really fast it seems, probably depends on what rules you have set
|
||||
-- which can cause the c.content to not show the correct image
|
||||
gears.timer
|
||||
{
|
||||
timeout = 0.1,
|
||||
call_now = false,
|
||||
autostart = true,
|
||||
single_shot = true,
|
||||
callback = function()
|
||||
if t.selected == true then
|
||||
for _, c in ipairs(t:clients()) do
|
||||
c.prev_content = gears.surface.duplicate_surface(c.content)
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
end)
|
||||
|
||||
awesome.connect_signal("bling::tag_preview::update", function(t)
|
||||
local geo = t.screen:get_bounding_geometry({
|
||||
honor_padding = padding,
|
||||
honor_workarea = work_area,
|
||||
})
|
||||
|
||||
tag_preview_box.maximum_width = scale * geo.width + margin * 2
|
||||
tag_preview_box.maximum_height = scale * geo.height + margin * 2
|
||||
|
||||
|
||||
tag_preview_box.widget = draw_widget(
|
||||
t,
|
||||
tag_preview_image,
|
||||
scale,
|
||||
screen_radius,
|
||||
client_radius,
|
||||
client_opacity,
|
||||
client_bg,
|
||||
client_border_color,
|
||||
client_border_width,
|
||||
widget_bg,
|
||||
widget_border_color,
|
||||
widget_border_width,
|
||||
geo,
|
||||
margin,
|
||||
background_image
|
||||
)
|
||||
end)
|
||||
|
||||
awesome.connect_signal("bling::tag_preview::visibility", function(s, v)
|
||||
if not placement_fn then
|
||||
tag_preview_box.x = s.geometry.x + widget_x
|
||||
tag_preview_box.y = s.geometry.y + widget_y
|
||||
end
|
||||
|
||||
if v == false then
|
||||
tag_preview_box.widget = nil
|
||||
collectgarbage("collect")
|
||||
end
|
||||
|
||||
tag_preview_box.visible = v
|
||||
end)
|
||||
end
|
||||
|
||||
return {enable = enable, draw_widget = draw_widget}
|
199
home/.config/awesome/libs/bling/widget/task_preview.lua
Normal file
199
home/.config/awesome/libs/bling/widget/task_preview.lua
Normal file
|
@ -0,0 +1,199 @@
|
|||
--
|
||||
-- Provides:
|
||||
-- bling::task_preview::visibility
|
||||
-- s (screen)
|
||||
-- v (boolean)
|
||||
-- c (client)
|
||||
--
|
||||
local awful = require("awful")
|
||||
local wibox = require("wibox")
|
||||
local helpers = require(tostring(...):match(".*bling") .. ".helpers")
|
||||
local gears = require("gears")
|
||||
local beautiful = require("beautiful")
|
||||
local dpi = beautiful.xresources.apply_dpi
|
||||
local cairo = require("lgi").cairo
|
||||
|
||||
-- TODO: rename structure to something better?
|
||||
local function draw_widget(
|
||||
c,
|
||||
widget_template,
|
||||
screen_radius,
|
||||
widget_bg,
|
||||
widget_border_color,
|
||||
widget_border_width,
|
||||
margin,
|
||||
widget_width,
|
||||
widget_height
|
||||
)
|
||||
if not pcall(function()
|
||||
return type(c.content)
|
||||
end) then
|
||||
return
|
||||
end
|
||||
|
||||
local content = nil
|
||||
if c.active then
|
||||
content = gears.surface(c.content)
|
||||
elseif c.prev_content then
|
||||
content = gears.surface(c.prev_content)
|
||||
end
|
||||
|
||||
local img = nil
|
||||
if content ~= nil then
|
||||
local cr = cairo.Context(content)
|
||||
local x, y, w, h = cr:clip_extents()
|
||||
img = cairo.ImageSurface.create(cairo.Format.ARGB32, w - x, h - y)
|
||||
cr = cairo.Context(img)
|
||||
cr:set_source_surface(content, 0, 0)
|
||||
cr.operator = cairo.Operator.SOURCE
|
||||
cr:paint()
|
||||
end
|
||||
|
||||
local widget = wibox.widget({
|
||||
(widget_template or {
|
||||
{
|
||||
{
|
||||
{
|
||||
{
|
||||
id = "icon_role",
|
||||
resize = true,
|
||||
forced_height = dpi(20),
|
||||
forced_width = dpi(20),
|
||||
widget = wibox.widget.imagebox,
|
||||
},
|
||||
{
|
||||
{
|
||||
id = "name_role",
|
||||
align = "center",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
left = dpi(4),
|
||||
right = dpi(4),
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
layout = wibox.layout.align.horizontal,
|
||||
},
|
||||
{
|
||||
{
|
||||
{
|
||||
id = "image_role",
|
||||
resize = true,
|
||||
clip_shape = helpers.shape.rrect(screen_radius),
|
||||
widget = wibox.widget.imagebox,
|
||||
},
|
||||
valign = "center",
|
||||
halign = "center",
|
||||
widget = wibox.container.place,
|
||||
},
|
||||
top = margin * 0.25,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
fill_space = true,
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
},
|
||||
margins = margin,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
bg = widget_bg,
|
||||
shape_border_width = widget_border_width,
|
||||
shape_border_color = widget_border_color,
|
||||
shape = helpers.shape.rrect(screen_radius),
|
||||
widget = wibox.container.background,
|
||||
}),
|
||||
width = widget_width,
|
||||
height = widget_height,
|
||||
widget = wibox.container.constraint,
|
||||
})
|
||||
|
||||
-- TODO: have something like a create callback here?
|
||||
|
||||
for _, w in ipairs(widget:get_children_by_id("image_role")) do
|
||||
w.image = img -- TODO: copy it with gears.surface.xxx or something
|
||||
end
|
||||
|
||||
for _, w in ipairs(widget:get_children_by_id("name_role")) do
|
||||
w.text = c.name
|
||||
end
|
||||
|
||||
for _, w in ipairs(widget:get_children_by_id("icon_role")) do
|
||||
w.image = c.icon -- TODO: detect clienticon
|
||||
end
|
||||
|
||||
return widget
|
||||
end
|
||||
|
||||
local enable = function(opts)
|
||||
local opts = opts or {}
|
||||
|
||||
local widget_x = opts.x or dpi(20)
|
||||
local widget_y = opts.y or dpi(20)
|
||||
local widget_height = opts.height or dpi(200)
|
||||
local widget_width = opts.width or dpi(200)
|
||||
local placement_fn = opts.placement_fn or nil
|
||||
|
||||
local margin = beautiful.task_preview_widget_margin or dpi(0)
|
||||
local screen_radius = beautiful.task_preview_widget_border_radius or dpi(0)
|
||||
local widget_bg = beautiful.task_preview_widget_bg or "#000000"
|
||||
local widget_border_color = beautiful.task_preview_widget_border_color
|
||||
or "#ffffff"
|
||||
local widget_border_width = beautiful.task_preview_widget_border_width
|
||||
or dpi(3)
|
||||
|
||||
local task_preview_box = awful.popup({
|
||||
type = "dropdown_menu",
|
||||
visible = false,
|
||||
ontop = true,
|
||||
placement = placement_fn,
|
||||
widget = wibox.container.background, -- A dummy widget to make awful.popup not scream
|
||||
input_passthrough = true,
|
||||
bg = "#00000000",
|
||||
})
|
||||
|
||||
tag.connect_signal("property::selected", function(t)
|
||||
-- Awesome switches up tags on startup really fast it seems, probably depends on what rules you have set
|
||||
-- which can cause the c.content to not show the correct image
|
||||
gears.timer
|
||||
{
|
||||
timeout = 0.1,
|
||||
call_now = false,
|
||||
autostart = true,
|
||||
single_shot = true,
|
||||
callback = function()
|
||||
if t.selected == true then
|
||||
for _, c in ipairs(t:clients()) do
|
||||
c.prev_content = gears.surface.duplicate_surface(c.content)
|
||||
end
|
||||
end
|
||||
end
|
||||
}
|
||||
end)
|
||||
|
||||
awesome.connect_signal("bling::task_preview::visibility", function(s, v, c)
|
||||
if v then
|
||||
-- Update task preview contents
|
||||
task_preview_box.widget = draw_widget(
|
||||
c,
|
||||
opts.structure,
|
||||
screen_radius,
|
||||
widget_bg,
|
||||
widget_border_color,
|
||||
widget_border_width,
|
||||
margin,
|
||||
widget_width,
|
||||
widget_height
|
||||
)
|
||||
else
|
||||
task_preview_box.widget = nil
|
||||
collectgarbage("collect")
|
||||
end
|
||||
|
||||
if not placement_fn then
|
||||
task_preview_box.x = s.geometry.x + widget_x
|
||||
task_preview_box.y = s.geometry.y + widget_y
|
||||
end
|
||||
|
||||
task_preview_box.visible = v
|
||||
end)
|
||||
end
|
||||
|
||||
return { enable = enable, draw_widget = draw_widget }
|
461
home/.config/awesome/libs/bling/widget/window_switcher.lua
Normal file
461
home/.config/awesome/libs/bling/widget/window_switcher.lua
Normal file
|
@ -0,0 +1,461 @@
|
|||
local cairo = require("lgi").cairo
|
||||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local wibox = require("wibox")
|
||||
local beautiful = require("beautiful")
|
||||
local helpers = require(tostring(...):match(".*bling") .. ".helpers")
|
||||
local dpi = beautiful.xresources.apply_dpi
|
||||
|
||||
local window_switcher_first_client -- The client that was focused when the window_switcher was activated
|
||||
local window_switcher_minimized_clients = {} -- The clients that were minimized when the window switcher was activated
|
||||
local window_switcher_grabber
|
||||
|
||||
local get_num_clients = function()
|
||||
local minimized_clients_in_tag = 0
|
||||
local matcher = function(c)
|
||||
return awful.rules.match(
|
||||
c,
|
||||
{
|
||||
minimized = true,
|
||||
skip_taskbar = false,
|
||||
hidden = false,
|
||||
first_tag = awful.screen.focused().selected_tag,
|
||||
}
|
||||
)
|
||||
end
|
||||
for c in awful.client.iterate(matcher) do
|
||||
minimized_clients_in_tag = minimized_clients_in_tag + 1
|
||||
end
|
||||
return minimized_clients_in_tag + #awful.screen.focused().clients
|
||||
end
|
||||
|
||||
local window_switcher_hide = function(window_switcher_box)
|
||||
-- Add currently focused client to history
|
||||
if client.focus then
|
||||
local window_switcher_last_client = client.focus
|
||||
awful.client.focus.history.add(window_switcher_last_client)
|
||||
-- Raise client that was focused originally
|
||||
-- Then raise last focused client
|
||||
if
|
||||
window_switcher_first_client and window_switcher_first_client.valid
|
||||
then
|
||||
window_switcher_first_client:raise()
|
||||
window_switcher_last_client:raise()
|
||||
end
|
||||
end
|
||||
|
||||
-- Minimize originally minimized clients
|
||||
local s = awful.screen.focused()
|
||||
for _, c in pairs(window_switcher_minimized_clients) do
|
||||
if c and c.valid and not (client.focus and client.focus == c) then
|
||||
c.minimized = true
|
||||
end
|
||||
end
|
||||
-- Reset helper table
|
||||
window_switcher_minimized_clients = {}
|
||||
|
||||
-- Resume recording focus history
|
||||
awful.client.focus.history.enable_tracking()
|
||||
-- Stop and hide window_switcher
|
||||
awful.keygrabber.stop(window_switcher_grabber)
|
||||
window_switcher_box.visible = false
|
||||
window_switcher_box.widget = nil
|
||||
collectgarbage("collect")
|
||||
end
|
||||
|
||||
local function draw_widget(
|
||||
type,
|
||||
background,
|
||||
border_width,
|
||||
border_radius,
|
||||
border_color,
|
||||
clients_spacing,
|
||||
client_icon_horizontal_spacing,
|
||||
client_width,
|
||||
client_height,
|
||||
client_margins,
|
||||
thumbnail_margins,
|
||||
thumbnail_scale,
|
||||
name_margins,
|
||||
name_valign,
|
||||
name_forced_width,
|
||||
name_font,
|
||||
name_normal_color,
|
||||
name_focus_color,
|
||||
icon_valign,
|
||||
icon_width,
|
||||
mouse_keys,
|
||||
filterClients
|
||||
)
|
||||
filterClients = filterClients or awful.widget.tasklist.filter.currenttags
|
||||
local tasklist_widget = type == "thumbnail"
|
||||
and awful.widget.tasklist({
|
||||
screen = awful.screen.focused(),
|
||||
filter = filterClients,
|
||||
buttons = mouse_keys,
|
||||
style = {
|
||||
font = name_font,
|
||||
fg_normal = name_normal_color,
|
||||
fg_focus = name_focus_color,
|
||||
},
|
||||
layout = {
|
||||
layout = wibox.layout.flex.horizontal,
|
||||
spacing = clients_spacing,
|
||||
},
|
||||
widget_template = {
|
||||
widget = wibox.container.background,
|
||||
id = "bg_role",
|
||||
forced_width = client_width,
|
||||
forced_height = client_height,
|
||||
create_callback = function(self, c, _, __)
|
||||
local content = gears.surface(c.content)
|
||||
local cr = cairo.Context(content)
|
||||
local x, y, w, h = cr:clip_extents()
|
||||
local img = cairo.ImageSurface.create(
|
||||
cairo.Format.ARGB32,
|
||||
w - x,
|
||||
h - y
|
||||
)
|
||||
cr = cairo.Context(img)
|
||||
cr:set_source_surface(content, 0, 0)
|
||||
cr.operator = cairo.Operator.SOURCE
|
||||
cr:paint()
|
||||
self:get_children_by_id("thumbnail")[1].image =
|
||||
gears.surface.load(
|
||||
img
|
||||
)
|
||||
end,
|
||||
{
|
||||
{
|
||||
{
|
||||
horizontal_fit_policy = thumbnail_scale == true
|
||||
and "fit"
|
||||
or "auto",
|
||||
vertical_fit_policy = thumbnail_scale == true
|
||||
and "fit"
|
||||
or "auto",
|
||||
id = "thumbnail",
|
||||
widget = wibox.widget.imagebox,
|
||||
},
|
||||
margins = thumbnail_margins,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
{
|
||||
{
|
||||
{
|
||||
id = "icon_role",
|
||||
widget = wibox.widget.imagebox,
|
||||
},
|
||||
forced_width = icon_width,
|
||||
valign = icon_valign,
|
||||
widget = wibox.container.place,
|
||||
},
|
||||
{
|
||||
{
|
||||
forced_width = name_forced_width,
|
||||
valign = name_valign,
|
||||
id = "text_role",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
margins = name_margins,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
spacing = client_icon_horizontal_spacing,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
layout = wibox.layout.flex.vertical,
|
||||
},
|
||||
},
|
||||
})
|
||||
or awful.widget.tasklist({
|
||||
screen = awful.screen.focused(),
|
||||
filter = filterClients,
|
||||
buttons = mouse_keys,
|
||||
style = {
|
||||
font = name_font,
|
||||
fg_normal = name_normal_color,
|
||||
fg_focus = name_focus_color,
|
||||
},
|
||||
layout = {
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
spacing = clients_spacing,
|
||||
},
|
||||
widget_template = {
|
||||
widget = wibox.container.background,
|
||||
id = "bg_role",
|
||||
forced_width = client_width,
|
||||
forced_height = client_height,
|
||||
{
|
||||
{
|
||||
{
|
||||
id = "icon_role",
|
||||
widget = wibox.widget.imagebox,
|
||||
},
|
||||
forced_width = icon_width,
|
||||
valign = icon_valign,
|
||||
widget = wibox.container.place,
|
||||
},
|
||||
{
|
||||
{
|
||||
forced_width = name_forced_width,
|
||||
valign = name_valign,
|
||||
id = "text_role",
|
||||
widget = wibox.widget.textbox,
|
||||
},
|
||||
margins = name_margins,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
spacing = client_icon_horizontal_spacing,
|
||||
layout = wibox.layout.fixed.horizontal,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return wibox.widget({
|
||||
{
|
||||
tasklist_widget,
|
||||
margins = client_margins,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
shape_border_width = border_width,
|
||||
shape_border_color = border_color,
|
||||
bg = background,
|
||||
shape = helpers.shape.rrect(border_radius),
|
||||
widget = wibox.container.background,
|
||||
})
|
||||
end
|
||||
|
||||
local enable = function(opts)
|
||||
local opts = opts or {}
|
||||
|
||||
local type = opts.type or "thumbnail"
|
||||
local background = beautiful.window_switcher_widget_bg or "#000000"
|
||||
local border_width = beautiful.window_switcher_widget_border_width or dpi(3)
|
||||
local border_radius = beautiful.window_switcher_widget_border_radius
|
||||
or dpi(0)
|
||||
local border_color = beautiful.window_switcher_widget_border_color
|
||||
or "#ffffff"
|
||||
local clients_spacing = beautiful.window_switcher_clients_spacing or dpi(20)
|
||||
local client_icon_horizontal_spacing = beautiful.window_switcher_client_icon_horizontal_spacing
|
||||
or dpi(5)
|
||||
local client_width = beautiful.window_switcher_client_width
|
||||
or dpi(type == "thumbnail" and 150 or 500)
|
||||
local client_height = beautiful.window_switcher_client_height
|
||||
or dpi(type == "thumbnail" and 250 or 50)
|
||||
local client_margins = beautiful.window_switcher_client_margins or dpi(10)
|
||||
local thumbnail_margins = beautiful.window_switcher_thumbnail_margins
|
||||
or dpi(5)
|
||||
local thumbnail_scale = beautiful.thumbnail_scale or false
|
||||
local name_margins = beautiful.window_switcher_name_margins or dpi(10)
|
||||
local name_valign = beautiful.window_switcher_name_valign or "center"
|
||||
local name_forced_width = beautiful.window_switcher_name_forced_width
|
||||
or dpi(type == "thumbnail" and 200 or 550)
|
||||
local name_font = beautiful.window_switcher_name_font or beautiful.font
|
||||
local name_normal_color = beautiful.window_switcher_name_normal_color
|
||||
or "#FFFFFF"
|
||||
local name_focus_color = beautiful.window_switcher_name_focus_color
|
||||
or "#FF0000"
|
||||
local icon_valign = beautiful.window_switcher_icon_valign or "center"
|
||||
local icon_width = beautiful.window_switcher_icon_width or dpi(40)
|
||||
|
||||
local hide_window_switcher_key = opts.hide_window_switcher_key or "Escape"
|
||||
|
||||
local select_client_key = opts.select_client_key or 1
|
||||
local minimize_key = opts.minimize_key or "n"
|
||||
local unminimize_key = opts.unminimize_key or "N"
|
||||
local kill_client_key = opts.kill_client_key or "q"
|
||||
|
||||
local cycle_key = opts.cycle_key or "Tab"
|
||||
|
||||
local previous_key = opts.previous_key or "Left"
|
||||
local next_key = opts.next_key or "Right"
|
||||
|
||||
local vim_previous_key = opts.vim_previous_key or "h"
|
||||
local vim_next_key = opts.vim_next_key or "l"
|
||||
|
||||
local scroll_previous_key = opts.scroll_previous_key or 4
|
||||
local scroll_next_key = opts.scroll_next_key or 5
|
||||
|
||||
local cycleClientsByIdx = opts.cycleClientsByIdx or awful.client.focus.byidx
|
||||
local filterClients = opts.filterClients or awful.widget.tasklist.filter.currenttags
|
||||
|
||||
local window_switcher_box = awful.popup({
|
||||
bg = "#00000000",
|
||||
visible = false,
|
||||
ontop = true,
|
||||
placement = awful.placement.centered,
|
||||
screen = awful.screen.focused(),
|
||||
widget = wibox.container.background, -- A dummy widget to make awful.popup not scream
|
||||
widget = {
|
||||
{
|
||||
draw_widget(),
|
||||
margins = client_margins,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
shape_border_width = border_width,
|
||||
shape_border_color = border_color,
|
||||
bg = background,
|
||||
shape = helpers.shape.rrect(border_radius),
|
||||
widget = wibox.container.background,
|
||||
},
|
||||
})
|
||||
|
||||
local mouse_keys = gears.table.join(
|
||||
awful.button({
|
||||
modifiers = { "Any" },
|
||||
button = select_client_key,
|
||||
on_press = function(c)
|
||||
client.focus = c
|
||||
end,
|
||||
}),
|
||||
|
||||
awful.button({
|
||||
modifiers = { "Any" },
|
||||
button = scroll_previous_key,
|
||||
on_press = function()
|
||||
cycleClientsByIdx(-1)
|
||||
end,
|
||||
}),
|
||||
|
||||
awful.button({
|
||||
modifiers = { "Any" },
|
||||
button = scroll_next_key,
|
||||
on_press = function()
|
||||
cycleClientsByIdx(1)
|
||||
end,
|
||||
})
|
||||
)
|
||||
|
||||
local keyboard_keys = {
|
||||
[hide_window_switcher_key] = function()
|
||||
window_switcher_hide(window_switcher_box)
|
||||
end,
|
||||
|
||||
[minimize_key] = function()
|
||||
if client.focus then
|
||||
client.focus.minimized = true
|
||||
end
|
||||
end,
|
||||
[unminimize_key] = function()
|
||||
if awful.client.restore() then
|
||||
client.focus = awful.client.restore()
|
||||
end
|
||||
end,
|
||||
[kill_client_key] = function()
|
||||
if client.focus then
|
||||
client.focus:kill()
|
||||
end
|
||||
end,
|
||||
|
||||
[cycle_key] = function()
|
||||
cycleClientsByIdx(1)
|
||||
end,
|
||||
|
||||
[previous_key] = function()
|
||||
cycleClientsByIdx(1)
|
||||
end,
|
||||
[next_key] = function()
|
||||
cycleClientsByIdx(-1)
|
||||
end,
|
||||
|
||||
[vim_previous_key] = function()
|
||||
cycleClientsByIdx(1)
|
||||
end,
|
||||
[vim_next_key] = function()
|
||||
cycleClientsByIdx(-1)
|
||||
end,
|
||||
}
|
||||
|
||||
window_switcher_box:connect_signal("property::width", function()
|
||||
if window_switcher_box.visible and get_num_clients() == 0 then
|
||||
window_switcher_hide(window_switcher_box)
|
||||
end
|
||||
end)
|
||||
|
||||
window_switcher_box:connect_signal("property::height", function()
|
||||
if window_switcher_box.visible and get_num_clients() == 0 then
|
||||
window_switcher_hide(window_switcher_box)
|
||||
end
|
||||
end)
|
||||
|
||||
awesome.connect_signal("bling::window_switcher::turn_on", function()
|
||||
local number_of_clients = get_num_clients()
|
||||
if number_of_clients == 0 then
|
||||
return
|
||||
end
|
||||
|
||||
-- Store client that is focused in a variable
|
||||
window_switcher_first_client = client.focus
|
||||
|
||||
-- Stop recording focus history
|
||||
awful.client.focus.history.disable_tracking()
|
||||
|
||||
-- Go to previously focused client (in the tag)
|
||||
awful.client.focus.history.previous()
|
||||
|
||||
-- Track minimized clients
|
||||
-- Unminimize them
|
||||
-- Lower them so that they are always below other
|
||||
-- originally unminimized windows
|
||||
local clients = awful.screen.focused().selected_tag:clients()
|
||||
for _, c in pairs(clients) do
|
||||
if c.minimized then
|
||||
table.insert(window_switcher_minimized_clients, c)
|
||||
c.minimized = false
|
||||
c:lower()
|
||||
end
|
||||
end
|
||||
|
||||
-- Start the keygrabber
|
||||
window_switcher_grabber = awful.keygrabber.run(function(_, key, event)
|
||||
if event == "release" then
|
||||
-- Hide if the modifier was released
|
||||
-- We try to match Super or Alt or Control since we do not know which keybind is
|
||||
-- used to activate the window switcher (the keybind is set by the user in keys.lua)
|
||||
if
|
||||
key:match("Super")
|
||||
or key:match("Alt")
|
||||
or key:match("Control")
|
||||
then
|
||||
window_switcher_hide(window_switcher_box)
|
||||
end
|
||||
-- Do nothing
|
||||
return
|
||||
end
|
||||
|
||||
-- Run function attached to key, if it exists
|
||||
if keyboard_keys[key] then
|
||||
keyboard_keys[key]()
|
||||
end
|
||||
end)
|
||||
|
||||
window_switcher_box.widget = draw_widget(
|
||||
type,
|
||||
background,
|
||||
border_width,
|
||||
border_radius,
|
||||
border_color,
|
||||
clients_spacing,
|
||||
client_icon_horizontal_spacing,
|
||||
client_width,
|
||||
client_height,
|
||||
client_margins,
|
||||
thumbnail_margins,
|
||||
thumbnail_scale,
|
||||
name_margins,
|
||||
name_valign,
|
||||
name_forced_width,
|
||||
name_font,
|
||||
name_normal_color,
|
||||
name_focus_color,
|
||||
icon_valign,
|
||||
icon_width,
|
||||
mouse_keys,
|
||||
filterClients
|
||||
)
|
||||
window_switcher_box.screen = awful.screen.focused()
|
||||
window_switcher_box.visible = true
|
||||
end)
|
||||
end
|
||||
|
||||
return { enable = enable }
|
Loading…
Add table
Add a link
Reference in a new issue