finished application laucnher and bluetooth widget
@@ -8,16 +8,15 @@
|
|||||||
---------------------------------------------------------------------------
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
local setmetatable = setmetatable
|
local setmetatable = setmetatable
|
||||||
local abutton = require("awful.button")
|
|
||||||
local beautiful = require("beautiful")
|
local beautiful = require("beautiful")
|
||||||
local gtable = require("gears.table")
|
local gtable = require("gears.table")
|
||||||
local base = require("wibox.widget.base")
|
local base = require("wibox.widget.base")
|
||||||
local gstring = require("gears.string")
|
local gstring = require("gears.string")
|
||||||
local keygrabber = require("awful.keygrabber")
|
local akeygrabber = require("awful.keygrabber")
|
||||||
local wtemplate = require("wibox.template")
|
local akey = require("awful.key")
|
||||||
|
local textbox = require("wibox.widget.textbox")
|
||||||
|
|
||||||
local capi =
|
local capi = {
|
||||||
{
|
|
||||||
selection = selection,
|
selection = selection,
|
||||||
mousegrabber = mousegrabber,
|
mousegrabber = mousegrabber,
|
||||||
mouse = mouse,
|
mouse = mouse,
|
||||||
@@ -31,8 +30,7 @@ local function text_with_cursor(text, cursor_pos, self)
|
|||||||
|
|
||||||
local cursor_fg = beautiful.inputbox_cursor_fg or "#313131"
|
local cursor_fg = beautiful.inputbox_cursor_fg or "#313131"
|
||||||
local cursor_bg = beautiful.inputbox_cursor_bg or "#0dccfc"
|
local cursor_bg = beautiful.inputbox_cursor_bg or "#0dccfc"
|
||||||
local text_color = beautiful.inputbox_fg or "#ffffff"
|
local placeholder_text = self.hint_text or ""
|
||||||
local placeholder_text = beautiful.inputbox_placeholder_text or "Type here..."
|
|
||||||
local placeholder_fg = beautiful.inputbox_placeholder_fg or "#777777"
|
local placeholder_fg = beautiful.inputbox_placeholder_fg or "#777777"
|
||||||
local highlight_bg = beautiful.inputbox_highlight_bg or "#35ffe4"
|
local highlight_bg = beautiful.inputbox_highlight_bg or "#35ffe4"
|
||||||
local highlight_fg = beautiful.inputbox_highlight_fg or "#000000"
|
local highlight_fg = beautiful.inputbox_highlight_fg or "#000000"
|
||||||
@@ -41,16 +39,17 @@ local function text_with_cursor(text, cursor_pos, self)
|
|||||||
return "<span foreground='" .. placeholder_fg .. "'>" .. placeholder_text .. "</span>"
|
return "<span foreground='" .. placeholder_fg .. "'>" .. placeholder_text .. "</span>"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local offset = 0
|
||||||
|
if text:sub(cursor_pos - 1, cursor_pos - 1) == -1 then
|
||||||
|
offset = 1
|
||||||
|
end
|
||||||
|
|
||||||
if #text < cursor_pos then
|
if #text < cursor_pos then
|
||||||
char = " "
|
char = " "
|
||||||
spacer = ""
|
spacer = ""
|
||||||
text_start = gstring.xml_escape(text)
|
text_start = gstring.xml_escape(text)
|
||||||
text_end = ""
|
text_end = ""
|
||||||
else
|
else
|
||||||
local offset = 0
|
|
||||||
if #text:sub(cursor_pos, cursor_pos) == -1 then
|
|
||||||
offset = 1
|
|
||||||
end
|
|
||||||
char = gstring.xml_escape(text:sub(cursor_pos, cursor_pos + offset))
|
char = gstring.xml_escape(text:sub(cursor_pos, cursor_pos + offset))
|
||||||
spacer = " "
|
spacer = " "
|
||||||
text_start = gstring.xml_escape(text:sub(1, cursor_pos - 1))
|
text_start = gstring.xml_escape(text:sub(1, cursor_pos - 1))
|
||||||
@@ -64,14 +63,12 @@ local function text_with_cursor(text, cursor_pos, self)
|
|||||||
self._private.highlight.cur_pos_end))
|
self._private.highlight.cur_pos_end))
|
||||||
local text_end_highlight = gstring.xml_escape(text:sub(self._private.highlight.cur_pos_end + 1))
|
local text_end_highlight = gstring.xml_escape(text:sub(self._private.highlight.cur_pos_end + 1))
|
||||||
|
|
||||||
return "<span foreground='" .. text_color .. "'>" .. text_start_highlight .. "</span>" ..
|
return text_start_highlight ..
|
||||||
"<span foreground='" .. highlight_fg .. "' background='" .. highlight_bg .. "'>" ..
|
"<span foreground='" .. highlight_fg .. "' background='" .. highlight_bg .. "'>" ..
|
||||||
text_highlighted ..
|
text_highlighted .. "</span>" .. text_end_highlight
|
||||||
"</span>" .. "<span foreground='" .. text_color .. "'>" .. text_end_highlight .. "</span>"
|
|
||||||
else
|
else
|
||||||
return "<span foreground='" .. text_color .. "'>" .. text_start .. "</span>" ..
|
return text_start .. "<span background='" .. cursor_bg .. "' foreground='" .. cursor_fg .. "'>" ..
|
||||||
"<span background='" .. cursor_bg .. "' foreground='" .. cursor_fg .. "'>" ..
|
char .. "</span>" .. text_end .. spacer
|
||||||
char .. "</span>" .. "<span foreground='" .. text_color .. "'>" .. text_end .. spacer .. "</span>"
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -91,99 +88,6 @@ end
|
|||||||
|
|
||||||
inputbox.set_widget = base.set_widget_common
|
inputbox.set_widget = base.set_widget_common
|
||||||
|
|
||||||
function inputbox:set_widget_template(widget_template)
|
|
||||||
self._private.widget_template = widget_template
|
|
||||||
self:set_widget(widget_template)
|
|
||||||
end
|
|
||||||
|
|
||||||
function inputbox:get_widget()
|
|
||||||
return self._private.widget
|
|
||||||
end
|
|
||||||
|
|
||||||
function inputbox:get_children()
|
|
||||||
return { self._private.widget }
|
|
||||||
end
|
|
||||||
|
|
||||||
function inputbox:set_children(children)
|
|
||||||
self:set_widget(children[1])
|
|
||||||
end
|
|
||||||
|
|
||||||
function inputbox:reset()
|
|
||||||
self._private.widget_template = nil
|
|
||||||
self:set_widget(nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The inputbox border color
|
|
||||||
--
|
|
||||||
-- @DOC_awful_widget_inputbox_border_color_EXAMPLE@
|
|
||||||
--
|
|
||||||
-- @property border_color
|
|
||||||
-- @tparam[opt=gears.color] string border_color
|
|
||||||
-- @see gears.color
|
|
||||||
-- @propemits true false
|
|
||||||
-- @propbeautiful
|
|
||||||
function inputbox:set_border_color(v)
|
|
||||||
self._private.border_color = v
|
|
||||||
self:emit_signal("property::border_color", v)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The inputbox border width
|
|
||||||
--
|
|
||||||
-- @DOC_awful_widget_inputbox_border_width_EXAMPLE@
|
|
||||||
--
|
|
||||||
-- @property border_width
|
|
||||||
-- @tparam[opt=0] number|nil border_width
|
|
||||||
-- @negativeallowed false
|
|
||||||
-- @propertyunit pixel
|
|
||||||
-- @propemits true false
|
|
||||||
-- @propbeautiful
|
|
||||||
function inputbox:set_border_width(v)
|
|
||||||
self._private.border_width = v
|
|
||||||
self:emit_signal("property::border_width", v)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The inputbox background color
|
|
||||||
--
|
|
||||||
-- @DOC_awful_widget_inputbox_bg_EXAMPLE@
|
|
||||||
--
|
|
||||||
-- @property bg
|
|
||||||
-- @tparam[opt=gears.color] string foreground
|
|
||||||
-- @see gears.color
|
|
||||||
-- @propemits true false
|
|
||||||
-- @propbeautiful
|
|
||||||
function inputbox:set_bg(v)
|
|
||||||
self._private.bg = v
|
|
||||||
self:emit_signal("property::bg", v)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The text foreground color
|
|
||||||
--
|
|
||||||
-- @DOC_awful_widget_inputbox_fg_EXAMPLE@
|
|
||||||
--
|
|
||||||
-- @property string
|
|
||||||
-- @tparam[opt=gears.color] string foreground
|
|
||||||
-- @see gears.color
|
|
||||||
-- @propemits true false
|
|
||||||
-- @propbeautiful
|
|
||||||
function inputbox:set_fg(v)
|
|
||||||
self._private.fg = v
|
|
||||||
self:emit_signal("property::fg", v)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The shape of the inputbox
|
|
||||||
--
|
|
||||||
-- @DOC_awful_widget_inputbox_shape_EXAMPLE@
|
|
||||||
--
|
|
||||||
-- @property shape
|
|
||||||
-- @tparam[opt=gears.shape.rectangle] shape|nil shape
|
|
||||||
-- @see gears.shape
|
|
||||||
-- @propemits true false
|
|
||||||
-- @propbeautiful
|
|
||||||
function inputbox:set_shape(v)
|
|
||||||
self._private.shape = v
|
|
||||||
self:emit_signal("property::shape", v)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Clears the current text
|
--- Clears the current text
|
||||||
function inputbox:clear()
|
function inputbox:clear()
|
||||||
self:set_text("")
|
self:set_text("")
|
||||||
@@ -195,35 +99,23 @@ end
|
|||||||
|
|
||||||
function inputbox:set_text(text)
|
function inputbox:set_text(text)
|
||||||
self._private.text = text
|
self._private.text = text
|
||||||
|
self.markup = text_with_cursor(self:get_text(), #self:get_text(), self)
|
||||||
self:emit_signal("property::text", text)
|
self:emit_signal("property::text", text)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Stop the keygrabber and mousegrabber
|
--- Stop the keygrabber and mousegrabber
|
||||||
function inputbox:stop()
|
function inputbox:stop()
|
||||||
|
if (not self.akeygrabber) or (not self.akeygrabber.is_running) then return end
|
||||||
self:emit_signal("stopped")
|
self:emit_signal("stopped")
|
||||||
keygrabber.stop()
|
self.akeygrabber.stop()
|
||||||
capi.mousegrabber.stop()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function inputbox:focus()
|
function inputbox:focus()
|
||||||
keygrabber.stop()
|
if (not self.akeygrabber) or (not self.akeygrabber.is_running) then
|
||||||
if not keygrabber.is_running then
|
akeygrabber.stop()
|
||||||
self:run()
|
self:run()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Stops the mousegrabber when not clicked on the widget
|
|
||||||
--[[ capi.mousegrabber.run(
|
|
||||||
function(m)
|
|
||||||
if m.buttons[1] then
|
|
||||||
if capi.mouse.current_wibox ~= self:get_widget().widget then
|
|
||||||
self:emit_signal("keygrabber::stop", "")
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end, "left_ptr"
|
|
||||||
) ]]
|
|
||||||
|
|
||||||
self:connect_signal("button::press", function()
|
self:connect_signal("button::press", function()
|
||||||
if capi.mouse.current_widget ~= self then
|
if capi.mouse.current_widget ~= self then
|
||||||
self:emit_signal("keygrabber::stop", "")
|
self:emit_signal("keygrabber::stop", "")
|
||||||
@@ -231,61 +123,40 @@ function inputbox:focus()
|
|||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[ local function widget_update(text, cursor_pos, widget)
|
|
||||||
text = text or ""
|
|
||||||
cursor_pos = cursor_pos or 1
|
|
||||||
widget:set_text(text)
|
|
||||||
widget:emit_signal("property::markup", text)
|
|
||||||
end ]]
|
|
||||||
|
|
||||||
--- Init the inputbox and start the keygrabber
|
--- Init the inputbox and start the keygrabber
|
||||||
function inputbox:run()
|
function inputbox:run()
|
||||||
|
|
||||||
if not self._private.text then self._private.text = "" end
|
if not self._private.text then self._private.text = "" end
|
||||||
|
|
||||||
-- Init the cursor position, but causes on refocus the cursor to move to the left
|
-- Init the cursor position, but causes on refocus the cursor to move to the left
|
||||||
local cursor_pos = #self:get_text() + 1
|
local cursor_pos = #self:get_text() + 1
|
||||||
|
|
||||||
self:emit_signal("started")
|
|
||||||
|
|
||||||
-- Init and reset(when refocused) the highlight
|
-- Init and reset(when refocused) the highlight
|
||||||
self._private.highlight = {}
|
self._private.highlight = {}
|
||||||
|
|
||||||
-- Emitted when the keygrabber is stopped
|
self.akeygrabber = akeygrabber {
|
||||||
self:connect_signal("cancel", function()
|
autostart = true,
|
||||||
self:stop()
|
start_callback = function()
|
||||||
self:emit_signal("stopped")
|
self:emit_signal("started")
|
||||||
end)
|
end,
|
||||||
|
stop_callback = function(_, stop_key)
|
||||||
-- Emitted when the keygrabber should submit the text
|
if stop_key == "Return" then
|
||||||
self:connect_signal("submit", function(text)
|
self:emit_signal("submit", self:get_text(), stop_key)
|
||||||
self:stop()
|
-- Only reset text on enter as on escape you might want to continue later
|
||||||
self:emit_signal("stopped", text)
|
|
||||||
end)
|
|
||||||
|
|
||||||
self:emit_signal("key_pressed", "B", "A")
|
|
||||||
|
|
||||||
|
|
||||||
keygrabber.run(function(mod, key, event)
|
|
||||||
local mod_keys = {}
|
|
||||||
for _, v in ipairs(mod) do
|
|
||||||
mod_keys[v] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if not (event == "press") then return end
|
|
||||||
--Escape cases
|
|
||||||
-- Just quit and leave the text as is
|
|
||||||
if (not mod_keys.Control) and (key == "Escape") then
|
|
||||||
self:emit_signal("cancel")
|
|
||||||
elseif (not mod_keys.Control and key == "KP_Enter") or (not mod_keys.Control and key == "Return") then
|
|
||||||
self:emit_signal("submit", self:get_text())
|
|
||||||
self:set_text("")
|
self:set_text("")
|
||||||
|
else
|
||||||
|
self:emit_signal("stopped", stop_key)
|
||||||
end
|
end
|
||||||
|
end,
|
||||||
-- All shift, control or key cases
|
stop_key = { "Escape", "Return" },
|
||||||
if mod_keys.Shift then
|
keybindings = {
|
||||||
if key == "Left" then
|
--lShift, rShift = #50, #62
|
||||||
|
--lControl, rControl = #37, #105
|
||||||
|
akey {
|
||||||
|
modifiers = { "Shift" },
|
||||||
|
key = "Left", -- left
|
||||||
|
on_press = function()
|
||||||
if cursor_pos > 1 then
|
if cursor_pos > 1 then
|
||||||
|
local offset = (self._private.text:sub(cursor_pos - 1, cursor_pos - 1):wlen() == -1) and 1 or 0
|
||||||
if not self._private.highlight.cur_pos_start then
|
if not self._private.highlight.cur_pos_start then
|
||||||
self._private.highlight.cur_pos_start = cursor_pos - 1
|
self._private.highlight.cur_pos_start = cursor_pos - 1
|
||||||
end
|
end
|
||||||
@@ -296,12 +167,24 @@ function inputbox:run()
|
|||||||
if self._private.highlight.cur_pos_start < cursor_pos then
|
if self._private.highlight.cur_pos_start < cursor_pos then
|
||||||
self._private.highlight.cur_pos_end = self._private.highlight.cur_pos_end - 1
|
self._private.highlight.cur_pos_end = self._private.highlight.cur_pos_end - 1
|
||||||
else
|
else
|
||||||
self._private.highlight.cur_pos_start = self._private.highlight.cur_pos_start - 1
|
self._private.highlight.cur_pos_start = self._private.highlight.cur_pos_start
|
||||||
end
|
end
|
||||||
|
|
||||||
cursor_pos = cursor_pos - 1
|
cursor_pos = cursor_pos - 1
|
||||||
end
|
end
|
||||||
elseif key == "Right" then
|
if cursor_pos < 1 then
|
||||||
|
cursor_pos = 1
|
||||||
|
elseif cursor_pos > #self._private.text + 1 then
|
||||||
|
cursor_pos = #self._private.text + 1
|
||||||
|
end
|
||||||
|
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
|
||||||
|
self:emit_signal("inputbox::key_pressed", "Shift", "Left")
|
||||||
|
end
|
||||||
|
},
|
||||||
|
akey {
|
||||||
|
modifiers = { "Shift" },
|
||||||
|
key = "Right", -- right
|
||||||
|
on_press = function()
|
||||||
if #self._private.text >= cursor_pos then
|
if #self._private.text >= cursor_pos then
|
||||||
if not self._private.highlight.cur_pos_end then
|
if not self._private.highlight.cur_pos_end then
|
||||||
self._private.highlight.cur_pos_end = cursor_pos - 1
|
self._private.highlight.cur_pos_end = cursor_pos - 1
|
||||||
@@ -320,23 +203,32 @@ function inputbox:run()
|
|||||||
self._private.highlight = {}
|
self._private.highlight = {}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
if cursor_pos < 1 then
|
||||||
if key:wlen() == 1 then
|
cursor_pos = 1
|
||||||
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
|
elseif cursor_pos > #self._private.text + 1 then
|
||||||
string.upper(key) .. self._private.text:sub(cursor_pos))
|
cursor_pos = #self._private.text + 1
|
||||||
cursor_pos = cursor_pos + 1
|
|
||||||
end
|
end
|
||||||
|
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
|
||||||
|
self:emit_signal("inputbox::key_pressed", "Shift", "Right")
|
||||||
end
|
end
|
||||||
elseif mod_keys.Control then
|
},
|
||||||
if key == "a" then
|
akey {
|
||||||
|
modifiers = { "Control" },
|
||||||
|
key = "a", -- a
|
||||||
|
on_press = function()
|
||||||
-- Mark the entire text
|
-- Mark the entire text
|
||||||
self._private.highlight = {
|
self._private.highlight = {
|
||||||
cur_pos_start = 1,
|
cur_pos_start = 1,
|
||||||
cur_pos_end = #self._private.text
|
cur_pos_end = #self._private.text
|
||||||
}
|
}
|
||||||
elseif key == "c" then
|
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
|
||||||
-- TODO: Copy the highlighted text when the selection setter gets implemented
|
self:emit_signal("inputbox::key_pressed", "Control", "a")
|
||||||
elseif key == "v" then
|
end
|
||||||
|
},
|
||||||
|
akey {
|
||||||
|
modifiers = { "Control" },
|
||||||
|
key = "v", -- v
|
||||||
|
on_press = function()
|
||||||
local sel = capi.selection()
|
local sel = capi.selection()
|
||||||
if sel then
|
if sel then
|
||||||
sel = sel:gsub("\n", "")
|
sel = sel:gsub("\n", "")
|
||||||
@@ -354,10 +246,29 @@ function inputbox:run()
|
|||||||
cursor_pos = cursor_pos + #sel
|
cursor_pos = cursor_pos + #sel
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif key == "x" then
|
|
||||||
--TODO: "cut". Copy selected then clear text, this requires to add the c function first.
|
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
|
||||||
self._private.highlight = {}
|
self:emit_signal("inputbox::key_pressed", "Control", "v")
|
||||||
elseif key == "Left" then
|
end
|
||||||
|
},
|
||||||
|
akey {
|
||||||
|
modifiers = { "Control" },
|
||||||
|
key = "c", -- c
|
||||||
|
on_press = function()
|
||||||
|
--TODO
|
||||||
|
end
|
||||||
|
},
|
||||||
|
akey {
|
||||||
|
modifiers = { "Control" },
|
||||||
|
key = "x", -- x
|
||||||
|
on_press = function()
|
||||||
|
--TODO
|
||||||
|
end
|
||||||
|
},
|
||||||
|
akey {
|
||||||
|
modifiers = { "Control" },
|
||||||
|
key = "Left", -- left
|
||||||
|
on_press = function()
|
||||||
-- Find all spaces
|
-- Find all spaces
|
||||||
local spaces = {}
|
local spaces = {}
|
||||||
local t, i = self._private.text, 0
|
local t, i = self._private.text, 0
|
||||||
@@ -375,16 +286,39 @@ function inputbox:run()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
cursor_pos = cp
|
cursor_pos = cp
|
||||||
elseif key == "Right" then
|
if cursor_pos < 1 then
|
||||||
|
cursor_pos = 1
|
||||||
|
elseif cursor_pos > #self._private.text + 1 then
|
||||||
|
cursor_pos = #self._private.text + 1
|
||||||
|
end
|
||||||
|
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
|
||||||
|
self:emit_signal("inputbox::key_pressed", "Control", "Left")
|
||||||
|
end
|
||||||
|
},
|
||||||
|
akey {
|
||||||
|
modifiers = { "Control" },
|
||||||
|
key = "Right", -- right
|
||||||
|
on_press = function()
|
||||||
local next_space = self._private.text:sub(cursor_pos):find("%s")
|
local next_space = self._private.text:sub(cursor_pos):find("%s")
|
||||||
if next_space then
|
if next_space then
|
||||||
cursor_pos = cursor_pos + next_space
|
cursor_pos = cursor_pos + next_space
|
||||||
else
|
else
|
||||||
cursor_pos = #self._private.text + 1
|
cursor_pos = #self._private.text + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if cursor_pos < 1 then
|
||||||
|
cursor_pos = 1
|
||||||
|
elseif cursor_pos > #self._private.text + 1 then
|
||||||
|
cursor_pos = #self._private.text + 1
|
||||||
end
|
end
|
||||||
else
|
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
|
||||||
if key == "BackSpace" then
|
self:emit_signal("inputbox::key_pressed", "Control", "Right")
|
||||||
|
end
|
||||||
|
},
|
||||||
|
akey {
|
||||||
|
modifiers = {},
|
||||||
|
key = "BackSpace", --BackSpace
|
||||||
|
on_press = function()
|
||||||
-- If text is highlighted delete that, else just delete the character to the left
|
-- If text is highlighted delete that, else just delete the character to the left
|
||||||
if self._private.highlight and self._private.highlight.cur_pos_start and
|
if self._private.highlight and self._private.highlight.cur_pos_start and
|
||||||
self._private.highlight.cur_pos_end then
|
self._private.highlight.cur_pos_end then
|
||||||
@@ -395,12 +329,21 @@ function inputbox:run()
|
|||||||
cursor_pos = #text_start + 1
|
cursor_pos = #text_start + 1
|
||||||
else
|
else
|
||||||
if cursor_pos > 1 then
|
if cursor_pos > 1 then
|
||||||
self:set_text(self._private.text:sub(1, cursor_pos - 2) ..
|
local offset = (self._private.text:sub(cursor_pos - 1, cursor_pos - 1):wlen() == -1) and 1 or
|
||||||
|
0
|
||||||
|
self:set_text(self._private.text:sub(1, cursor_pos - 2 - offset) ..
|
||||||
self._private.text:sub(cursor_pos))
|
self._private.text:sub(cursor_pos))
|
||||||
cursor_pos = cursor_pos - 1
|
cursor_pos = cursor_pos - 1 - offset
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif key == "Delete" then
|
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
|
||||||
|
self:emit_signal("inputbox::key_pressed", nil, "BackSpace")
|
||||||
|
end
|
||||||
|
},
|
||||||
|
akey {
|
||||||
|
modifiers = {},
|
||||||
|
key = "Delete", --delete
|
||||||
|
on_press = function()
|
||||||
-- If text is highlighted delete that, else just delete the character to the right
|
-- If text is highlighted delete that, else just delete the character to the right
|
||||||
if self._private.highlight and self._private.highlight.cur_pos_start and
|
if self._private.highlight and self._private.highlight.cur_pos_start and
|
||||||
self._private.highlight.cur_pos_end then
|
self._private.highlight.cur_pos_end then
|
||||||
@@ -415,42 +358,58 @@ function inputbox:run()
|
|||||||
self._private.text:sub(cursor_pos + 1))
|
self._private.text:sub(cursor_pos + 1))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif key == "Left" then
|
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
|
||||||
|
self:emit_signal("inputbox::key_pressed", nil, "Delete")
|
||||||
|
end
|
||||||
|
},
|
||||||
|
akey {
|
||||||
|
modifiers = {},
|
||||||
|
key = "Left", --left
|
||||||
|
on_press = function()
|
||||||
-- Move cursor ro the left
|
-- Move cursor ro the left
|
||||||
if cursor_pos > 1 then
|
if cursor_pos > 1 then
|
||||||
cursor_pos = cursor_pos - 1
|
cursor_pos = cursor_pos - 1
|
||||||
end
|
end
|
||||||
self._private.highlight = {}
|
self._private.highlight = {}
|
||||||
elseif key == "Right" then
|
end
|
||||||
|
},
|
||||||
|
akey {
|
||||||
|
modifiers = {},
|
||||||
|
key = "Right", --right
|
||||||
|
on_press = function()
|
||||||
-- Move cursor to the right
|
-- Move cursor to the right
|
||||||
if cursor_pos <= #self._private.text then
|
if cursor_pos <= #self._private.text then
|
||||||
cursor_pos = cursor_pos + 1
|
cursor_pos = cursor_pos + 1
|
||||||
end
|
end
|
||||||
self._private.highlight = {}
|
self._private.highlight = {}
|
||||||
else
|
end
|
||||||
-- Print every alphanumeric key
|
},
|
||||||
-- It seems like gears.xmlescape doesn't support non alphanumeric characters
|
--self.keybindings
|
||||||
|
},
|
||||||
|
keypressed_callback = function(_, modifiers, key)
|
||||||
|
if modifiers[1] == "Shift" then
|
||||||
|
if key:wlen() == 1 then
|
||||||
|
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
|
||||||
|
string.upper(key) .. self._private.text:sub(cursor_pos))
|
||||||
|
cursor_pos = cursor_pos + #key
|
||||||
|
end
|
||||||
|
elseif modifiers[1] == "Mod2" or "" then
|
||||||
if key:wlen() == 1 then
|
if key:wlen() == 1 then
|
||||||
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
|
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
|
||||||
key .. self._private.text:sub(cursor_pos))
|
key .. self._private.text:sub(cursor_pos))
|
||||||
cursor_pos = cursor_pos + 1
|
cursor_pos = cursor_pos + #key
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Make sure the cursor cannot go out of bounds
|
|
||||||
if cursor_pos < 1 then
|
if cursor_pos < 1 then
|
||||||
cursor_pos = 1
|
cursor_pos = 1
|
||||||
elseif cursor_pos > #self._private.text + 1 then
|
elseif cursor_pos > #self._private.text + 1 then
|
||||||
cursor_pos = #self._private.text + 1
|
cursor_pos = #self._private.text + 1
|
||||||
end
|
end
|
||||||
|
self.markup = text_with_cursor(self:get_text(), cursor_pos, self)
|
||||||
|
self:emit_signal("inputbox::key_pressed", modifiers, key)
|
||||||
end
|
end
|
||||||
-- Update cycle
|
|
||||||
self:get_widget():update {
|
|
||||||
text = text_with_cursor(self:get_text(), cursor_pos, self)
|
|
||||||
}
|
}
|
||||||
-- using self:emit_signal... results in nil tables beeing send
|
|
||||||
awesome.emit_signal("inputbox::key_pressed", mod_keys, key)
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates a new inputbox widget
|
--- Creates a new inputbox widget
|
||||||
@@ -467,51 +426,16 @@ end
|
|||||||
-- @treturn awful.widget.inputbox The inputbox widget.
|
-- @treturn awful.widget.inputbox The inputbox widget.
|
||||||
-- @constructorfct awful.widget.inputbox
|
-- @constructorfct awful.widget.inputbox
|
||||||
function inputbox.new(args)
|
function inputbox.new(args)
|
||||||
|
-- directly pass a possible default text(this is not meant to be a hint)
|
||||||
|
local w = textbox()
|
||||||
|
|
||||||
local w = base.make_widget(nil, nil, { enable_properties = true })
|
--gtable.crush(w, args)
|
||||||
|
|
||||||
gtable.crush(w, inputbox, true)
|
gtable.crush(w, inputbox, true)
|
||||||
|
|
||||||
w:set_widget(wtemplate.make_from_value(args.widget_template))
|
w.keybindings = args.keybindings or {}
|
||||||
|
w.hint_text = args.hint_text
|
||||||
|
|
||||||
w:buttons(
|
w.markup = args.text or text_with_cursor("", 1, w)
|
||||||
gtable.join {
|
|
||||||
abutton({}, 1, function()
|
|
||||||
w:focus()
|
|
||||||
end),
|
|
||||||
abutton({}, 3, function()
|
|
||||||
-- TODO: Figure out how to paste with highlighted support
|
|
||||||
-- Maybe with a signal?
|
|
||||||
end)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Change the cursor to "xterm" on hover over
|
|
||||||
local old_cursor, old_wibox
|
|
||||||
w:connect_signal(
|
|
||||||
"mouse::enter",
|
|
||||||
function()
|
|
||||||
local wid = capi.mouse.current_wibox
|
|
||||||
if wid then
|
|
||||||
old_cursor, old_wibox = wid.cursor, wid
|
|
||||||
wid.cursor = "xterm"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Change the cursor back once leaving the widget
|
|
||||||
w:connect_signal(
|
|
||||||
"mouse::leave",
|
|
||||||
function()
|
|
||||||
old_wibox.cursor = old_cursor
|
|
||||||
old_wibox = nil
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Initialize the text and placeholder with a first update
|
|
||||||
w:get_widget():update {
|
|
||||||
text = text_with_cursor("", 1, w)
|
|
||||||
}
|
|
||||||
return w
|
return w
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
163
awesome/awful/widget/toggle_widget.lua
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
local base = require("wibox.widget.base")
|
||||||
|
local gtable = require("gears.table")
|
||||||
|
local gcolor = require("gears.color")
|
||||||
|
local dpi = require("beautiful").xresources.apply_dpi
|
||||||
|
local wibox = require("wibox")
|
||||||
|
local gshape = require("gears.shape")
|
||||||
|
local rubato = require("src.lib.rubato")
|
||||||
|
local abutton = require("awful.button")
|
||||||
|
|
||||||
|
local toggle_widget = { mt = {} }
|
||||||
|
|
||||||
|
function toggle_widget:layout(_, width, height)
|
||||||
|
if self._private.widget then
|
||||||
|
return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function toggle_widget:fit(context, width, height)
|
||||||
|
local w, h = 0, 0
|
||||||
|
if self._private.widget then
|
||||||
|
w, h = base.fit_widget(self, context, self._private.widget, width, height)
|
||||||
|
end
|
||||||
|
return w, h
|
||||||
|
end
|
||||||
|
|
||||||
|
toggle_widget.set_widget = base.set_widget_common
|
||||||
|
|
||||||
|
function toggle_widget:get_widget()
|
||||||
|
return self._private.widget
|
||||||
|
end
|
||||||
|
|
||||||
|
function toggle_widget:set_enabled()
|
||||||
|
self.active = true
|
||||||
|
self.toggle_button.border_color = self.color
|
||||||
|
self.newcolor = self.color
|
||||||
|
self.rubato_timed.target = 39
|
||||||
|
end
|
||||||
|
|
||||||
|
function toggle_widget:set_disabled()
|
||||||
|
self.active = not self.active
|
||||||
|
self.toggle_button.border_color = Theme_config.dnd.border_disabled
|
||||||
|
self.newcolor = Theme_config.dnd.disabled
|
||||||
|
self.rubato_timed.target = 5
|
||||||
|
end
|
||||||
|
|
||||||
|
function toggle_widget:toggle_animation(pos, color)
|
||||||
|
if pos > 39 then return end
|
||||||
|
return function(_, _, cr, width, height)
|
||||||
|
cr:set_source(gcolor(Theme_config.dnd.bg))
|
||||||
|
cr:paint()
|
||||||
|
cr:set_source(gcolor(color))
|
||||||
|
cr:move_to(pos, 0)
|
||||||
|
local x = pos
|
||||||
|
local y = 5
|
||||||
|
local newwidth = width / 2 - 10
|
||||||
|
local newheight = height - 10
|
||||||
|
|
||||||
|
local radius = height / 6.0
|
||||||
|
local degrees = math.pi / 180.0
|
||||||
|
|
||||||
|
cr:new_sub_path()
|
||||||
|
cr:arc(x + newwidth - radius, y + radius, radius, -90 * degrees, 0 * degrees)
|
||||||
|
cr:arc(x + newwidth - radius, y + newheight - radius, radius, 0 * degrees, 90 * degrees)
|
||||||
|
cr:arc(x + radius, y + newheight - radius, radius, 90 * degrees, 180 * degrees)
|
||||||
|
cr:arc(x + radius, y + radius, radius, 180 * degrees, 270 * degrees)
|
||||||
|
cr:close_path()
|
||||||
|
cr:fill()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function toggle_widget.new(args)
|
||||||
|
args = args or {}
|
||||||
|
|
||||||
|
local ret = base.make_widget(nil, nil, {
|
||||||
|
enable_properties = true,
|
||||||
|
})
|
||||||
|
|
||||||
|
gtable.crush(ret, toggle_widget, true)
|
||||||
|
|
||||||
|
ret.newcolor = Theme_config.dnd.disabled
|
||||||
|
ret.color = args.color
|
||||||
|
|
||||||
|
ret.toggle_button = wibox.widget {
|
||||||
|
{
|
||||||
|
widget = wibox.widget {
|
||||||
|
fit = function(_, width, height)
|
||||||
|
return width, height
|
||||||
|
end,
|
||||||
|
draw = ret:toggle_animation(0, ret.newcolor),
|
||||||
|
},
|
||||||
|
id = "background",
|
||||||
|
},
|
||||||
|
active = false,
|
||||||
|
widget = wibox.container.background,
|
||||||
|
bg = Theme_config.dnd.bg,
|
||||||
|
border_color = Theme_config.dnd.border_disabled,
|
||||||
|
border_width = dpi(2),
|
||||||
|
forced_height = args.size,
|
||||||
|
forced_width = args.size * 2,
|
||||||
|
shape = function(cr, width, height)
|
||||||
|
gshape.rounded_rect(cr, width, height, dpi(10))
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.rubato_timed = rubato.timed {
|
||||||
|
duration = 0.2,
|
||||||
|
pos = 5,
|
||||||
|
subscribed = function(pos)
|
||||||
|
ret.toggle_button:get_children_by_id("background")[1].draw = ret:toggle_animation(pos, ret.newcolor)
|
||||||
|
ret.toggle_button:emit_signal("widget::redraw_needed")
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
ret:set_widget(wibox.widget {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
args.text and {
|
||||||
|
text = args.text,
|
||||||
|
valign = "center",
|
||||||
|
align = "center",
|
||||||
|
widget = wibox.widget.textbox,
|
||||||
|
id = "clearall"
|
||||||
|
} or nil,
|
||||||
|
ret.toggle_button,
|
||||||
|
spacing = args.text and dpi(10) or dpi(0),
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
id = "layout12"
|
||||||
|
},
|
||||||
|
id = "background4",
|
||||||
|
fg = args.fg,
|
||||||
|
shape = function(cr, width, height)
|
||||||
|
gshape.rounded_rect(cr, width, height, dpi(12))
|
||||||
|
end,
|
||||||
|
widget = wibox.container.background
|
||||||
|
},
|
||||||
|
id = "place",
|
||||||
|
widget = wibox.container.place,
|
||||||
|
valign = "bottom",
|
||||||
|
halign = "right",
|
||||||
|
})
|
||||||
|
|
||||||
|
ret.toggle_button:buttons(
|
||||||
|
gtable.join(
|
||||||
|
abutton({}, 1, function()
|
||||||
|
if ret.active then
|
||||||
|
ret:set_disabled()
|
||||||
|
else
|
||||||
|
ret:set_enabled()
|
||||||
|
end
|
||||||
|
ret:emit_signal("dnd::toggle", ret.active)
|
||||||
|
end
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
|
function toggle_widget.mt:__call(...)
|
||||||
|
return toggle_widget.new(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(toggle_widget, toggle_widget.mt)
|
||||||
@@ -17,10 +17,9 @@ screen = screen
|
|||||||
selection = selection
|
selection = selection
|
||||||
tag = tag
|
tag = tag
|
||||||
|
|
||||||
-- Do not touch as this is used to share some variables between files
|
-- Do not touch as this is used to share some variable settings files
|
||||||
Global_config = {}
|
Global_config = {}
|
||||||
|
|
||||||
|
|
||||||
require("src.theme.user_config")
|
require("src.theme.user_config")
|
||||||
require("src.theme.theme_config")
|
require("src.theme.theme_config")
|
||||||
require("src.tools.gio_icon_lookup")
|
require("src.tools.gio_icon_lookup")
|
||||||
@@ -33,6 +32,4 @@ require("src.core.rules")
|
|||||||
require("src.bindings.global_buttons")
|
require("src.bindings.global_buttons")
|
||||||
require("src.bindings.bind_to_tags")
|
require("src.bindings.bind_to_tags")
|
||||||
require("src.modules.init")
|
require("src.modules.init")
|
||||||
require("src.tools.helpers.init")
|
|
||||||
--require("src.tools.auto_starter")(User_config.autostart)
|
--require("src.tools.auto_starter")(User_config.autostart)
|
||||||
--require("src.tools.dbus.bluetooth_dbus")()
|
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M2,7V8.5H3V17H4.5V7C3.7,7 2.8,7 2,7M6,7V7L6,16H7V17H14V16H22V7H6M17.5,9A2.5,2.5 0 0,1 20,11.5A2.5,2.5 0 0,1 17.5,14A2.5,2.5 0 0,1 15,11.5A2.5,2.5 0 0,1 17.5,9Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M2,7V8.5H3V17H4.5V7C3.7,7 2.8,7 2,7M6,7V7L6,16H7V17H14V16H22V7H6M17.5,9A2.5,2.5 0 0,1 20,11.5A2.5,2.5 0 0,1 17.5,14A2.5,2.5 0 0,1 15,11.5A2.5,2.5 0 0,1 17.5,9Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 454 B After Width: | Height: | Size: 463 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,1C7,1 3,5 3,10V17A3,3 0 0,0 6,20H9V12H5V10A7,7 0 0,1 12,3A7,7 0 0,1 19,10V12H15V20H18A3,3 0 0,0 21,17V10C21,5 16.97,1 12,1Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M12,1C7,1 3,5 3,10V17A3,3 0 0,0 6,20H9V12H5V10A7,7 0 0,1 12,3A7,7 0 0,1 19,10V12H15V20H18A3,3 0 0,0 21,17V10C21,5 16.97,1 12,1Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 422 B After Width: | Height: | Size: 431 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,1C7,1 3,5 3,10V17A3,3 0 0,0 6,20H9V12H5V10A7,7 0 0,1 12,3A7,7 0 0,1 19,10V12H15V20H19V21H12V23H18A3,3 0 0,0 21,20V10C21,5 16.97,1 12,1Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M12,1C7,1 3,5 3,10V17A3,3 0 0,0 6,20H9V12H5V10A7,7 0 0,1 12,3A7,7 0 0,1 19,10V12H15V20H19V21H12V23H18A3,3 0 0,0 21,20V10C21,5 16.97,1 12,1Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 434 B After Width: | Height: | Size: 443 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M13,5.83L14.88,7.71L13.28,9.31L14.69,10.72L17.71,7.7L12,2H11V7.03L13,9.03M5.41,4L4,5.41L10.59,12L5,17.59L6.41,19L11,14.41V22H12L16.29,17.71L18.59,20L20,18.59M13,18.17V14.41L14.88,16.29" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M13,5.83L14.88,7.71L13.28,9.31L14.69,10.72L17.71,7.7L12,2H11V7.03L13,9.03M5.41,4L4,5.41L10.59,12L5,17.59L6.41,19L11,14.41V22H12L16.29,17.71L18.59,20L20,18.59M13,18.17V14.41L14.88,16.29" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 479 B After Width: | Height: | Size: 486 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M14.88,16.29L13,18.17V14.41M13,5.83L14.88,7.71L13,9.58M17.71,7.71L12,2H11V9.58L6.41,5L5,6.41L10.59,12L5,17.58L6.41,19L11,14.41V22H12L17.71,16.29L13.41,12L17.71,7.71Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M14.88,16.29L13,18.17V14.41M13,5.83L14.88,7.71L13,9.58M17.71,7.71L12,2H11V9.58L6.41,5L5,6.41L10.59,12L5,17.58L6.41,19L11,14.41V22H12L17.71,16.29L13.41,12L17.71,7.71Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 460 B After Width: | Height: | Size: 467 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M4,5H7L9,3H15L17,5H20A2,2 0 0,1 22,7V19A2,2 0 0,1 20,21H4A2,2 0 0,1 2,19V7A2,2 0 0,1 4,5M13.09,9.45L11.05,12.18L12.6,14.25L11.73,14.91L9.27,11.64L6,16H18L13.09,9.45Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M4,5H7L9,3H15L17,5H20A2,2 0 0,1 22,7V19A2,2 0 0,1 20,21H4A2,2 0 0,1 2,19V7A2,2 0 0,1 4,5M13.09,9.45L11.05,12.18L12.6,14.25L11.73,14.91L9.27,11.64L6,16H18L13.09,9.45Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 460 B After Width: | Height: | Size: 469 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M4,4H7L9,2H15L17,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4M12,7A5,5 0 0,0 7,12A5,5 0 0,0 12,17A5,5 0 0,0 17,12A5,5 0 0,0 12,7M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M4,4H7L9,2H15L17,4H20A2,2 0 0,1 22,6V18A2,2 0 0,1 20,20H4A2,2 0 0,1 2,18V6A2,2 0 0,1 4,4M12,7A5,5 0 0,0 7,12A5,5 0 0,0 12,17A5,5 0 0,0 17,12A5,5 0 0,0 12,7M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 518 B After Width: | Height: | Size: 527 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M4,6H20V16H4M20,18A2,2 0 0,0 22,16V6C22,4.89 21.1,4 20,4H4C2.89,4 2,4.89 2,6V16A2,2 0 0,0 4,18H0V20H24V18H20Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M4,6H20V16H4M20,18A2,2 0 0,0 22,16V6C22,4.89 21.1,4 20,4H4C2.89,4 2,4.89 2,6V16A2,2 0 0,0 4,18H0V20H24V18H20Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 404 B After Width: | Height: | Size: 413 B |
1
awesome/src/assets/icons/bluetooth/delete.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M6,19C6,20.1 6.9,21 8,21H16C17.1,21 18,20.1 18,19V7H6V19M8,9H16V19H8V9M15.5,4L14.5,3H9.5L8.5,4H5V6H19V4H15.5Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 188 B |
1
awesome/src/assets/icons/bluetooth/edit.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14.06,9L15,9.94L5.92,19H5V18.08L14.06,9M17.66,3C17.41,3 17.15,3.1 16.96,3.29L15.13,5.12L18.88,8.87L20.71,7.04C21.1,6.65 21.1,6 20.71,5.63L18.37,3.29C18.17,3.09 17.92,3 17.66,3M14.06,6.19L3,17.25V21H6.75L17.81,9.94L14.06,6.19Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 305 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M7.97,16L5,19C4.67,19.3 4.23,19.5 3.75,19.5A1.75,1.75 0 0,1 2,17.75V17.5L3,10.12C3.21,7.81 5.14,6 7.5,6H16.5C18.86,6 20.79,7.81 21,10.12L22,17.5V17.75A1.75,1.75 0 0,1 20.25,19.5C19.77,19.5 19.33,19.3 19,19L16.03,16H7.97M7,8V10H5V11H7V13H8V11H10V10H8V8H7M16.5,8A0.75,0.75 0 0,0 15.75,8.75A0.75,0.75 0 0,0 16.5,9.5A0.75,0.75 0 0,0 17.25,8.75A0.75,0.75 0 0,0 16.5,8M14.75,9.75A0.75,0.75 0 0,0 14,10.5A0.75,0.75 0 0,0 14.75,11.25A0.75,0.75 0 0,0 15.5,10.5A0.75,0.75 0 0,0 14.75,9.75M18.25,9.75A0.75,0.75 0 0,0 17.5,10.5A0.75,0.75 0 0,0 18.25,11.25A0.75,0.75 0 0,0 19,10.5A0.75,0.75 0 0,0 18.25,9.75M16.5,11.5A0.75,0.75 0 0,0 15.75,12.25A0.75,0.75 0 0,0 16.5,13A0.75,0.75 0 0,0 17.25,12.25A0.75,0.75 0 0,0 16.5,11.5Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M7.97,16L5,19C4.67,19.3 4.23,19.5 3.75,19.5A1.75,1.75 0 0,1 2,17.75V17.5L3,10.12C3.21,7.81 5.14,6 7.5,6H16.5C18.86,6 20.79,7.81 21,10.12L22,17.5V17.75A1.75,1.75 0 0,1 20.25,19.5C19.77,19.5 19.33,19.3 19,19L16.03,16H7.97M7,8V10H5V11H7V13H8V11H10V10H8V8H7M16.5,8A0.75,0.75 0 0,0 15.75,8.75A0.75,0.75 0 0,0 16.5,9.5A0.75,0.75 0 0,0 17.25,8.75A0.75,0.75 0 0,0 16.5,8M14.75,9.75A0.75,0.75 0 0,0 14,10.5A0.75,0.75 0 0,0 14.75,11.25A0.75,0.75 0 0,0 15.5,10.5A0.75,0.75 0 0,0 14.75,9.75M18.25,9.75A0.75,0.75 0 0,0 17.5,10.5A0.75,0.75 0 0,0 18.25,11.25A0.75,0.75 0 0,0 19,10.5A0.75,0.75 0 0,0 18.25,9.75M16.5,11.5A0.75,0.75 0 0,0 15.75,12.25A0.75,0.75 0 0,0 16.5,13A0.75,0.75 0 0,0 17.25,12.25A0.75,0.75 0 0,0 16.5,11.5Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1006 B After Width: | Height: | Size: 1015 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,10H17V8H19M19,13H17V11H19M16,10H14V8H16M16,13H14V11H16M16,17H8V15H16M7,10H5V8H7M7,13H5V11H7M8,11H10V13H8M8,8H10V10H8M11,11H13V13H11M11,8H13V10H11M20,5H4C2.89,5 2,5.89 2,7V17A2,2 0 0,0 4,19H20A2,2 0 0,0 22,17V7C22,5.89 21.1,5 20,5Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M19,10H17V8H19M19,13H17V11H19M16,10H14V8H16M16,13H14V11H16M16,17H8V15H16M7,10H5V8H7M7,13H5V11H7M8,11H10V13H8M8,8H10V10H8M11,11H13V13H11M11,8H13V10H11M20,5H4C2.89,5 2,5.89 2,7V17A2,2 0 0,0 4,19H20A2,2 0 0,0 22,17V7C22,5.89 21.1,5 20,5Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 529 B After Width: | Height: | Size: 538 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M11,1.07C7.05,1.56 4,4.92 4,9H11M4,15A8,8 0 0,0 12,23A8,8 0 0,0 20,15V11H4M13,1.07V9H20C20,4.92 16.94,1.56 13,1.07Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M11,1.07C7.05,1.56 4,4.92 4,9H11M4,15A8,8 0 0,0 12,23A8,8 0 0,0 20,15V11H4M13,1.07V9H20C20,4.92 16.94,1.56 13,1.07Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 410 B After Width: | Height: | Size: 419 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M19,18H5V6H19M21,4H3C1.89,4 1,4.89 1,6V18A2,2 0 0,0 3,20H21A2,2 0 0,0 23,18V6C23,4.89 22.1,4 21,4Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M19,18H5V6H19M21,4H3C1.89,4 1,4.89 1,6V18A2,2 0 0,0 3,20H21A2,2 0 0,0 23,18V6C23,4.89 22.1,4 21,4Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 393 B After Width: | Height: | Size: 402 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M17,7H13V8.9H17C18.71,8.9 20.1,10.29 20.1,12C20.1,13.43 19.12,14.63 17.79,15L19.25,16.44C20.88,15.61 22,13.95 22,12A5,5 0 0,0 17,7M16,11H13.81L15.81,13H16V11M2,4.27L5.11,7.38C3.29,8.12 2,9.91 2,12A5,5 0 0,0 7,17H11V15.1H7C5.29,15.1 3.9,13.71 3.9,12C3.9,10.41 5.11,9.1 6.66,8.93L8.73,11H8V13H10.73L13,15.27V17H14.73L18.74,21L20,19.74L3.27,3L2,4.27Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M17,7H13V8.9H17C18.71,8.9 20.1,10.29 20.1,12C20.1,13.43 19.12,14.63 17.79,15L19.25,16.44C20.88,15.61 22,13.95 22,12A5,5 0 0,0 17,7M16,11H13.81L15.81,13H16V11M2,4.27L5.11,7.38C3.29,8.12 2,9.91 2,12A5,5 0 0,0 7,17H11V15.1H7C5.29,15.1 3.9,13.71 3.9,12C3.9,10.41 5.11,9.1 6.66,8.93L8.73,11H8V13H10.73L13,15.27V17H14.73L18.74,21L20,19.74L3.27,3L2,4.27Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 642 B After Width: | Height: | Size: 649 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M3.9,12C3.9,10.29 5.29,8.9 7,8.9H11V7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H11V15.1H7C5.29,15.1 3.9,13.71 3.9,12M8,13H16V11H8V13M17,7H13V8.9H17C18.71,8.9 20.1,10.29 20.1,12C20.1,13.71 18.71,15.1 17,15.1H13V17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M3.9,12C3.9,10.29 5.29,8.9 7,8.9H11V7H7A5,5 0 0,0 2,12A5,5 0 0,0 7,17H11V15.1H7C5.29,15.1 3.9,13.71 3.9,12M8,13H16V11H8V13M17,7H13V8.9H17C18.71,8.9 20.1,10.29 20.1,12C20.1,13.71 18.71,15.1 17,15.1H13V17H17A5,5 0 0,0 22,12A5,5 0 0,0 17,7Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 532 B After Width: | Height: | Size: 539 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M7,10L12,15L17,10H7Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M7,10L12,15L17,10H7Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 315 B After Width: | Height: | Size: 322 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M7,15L12,10L17,15H7Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M7,15L12,10L17,15H7Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 315 B After Width: | Height: | Size: 322 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M13,2.05V4.05C17.39,4.59 20.5,8.58 19.96,12.97C19.5,16.61 16.64,19.5 13,19.93V21.93C18.5,21.38 22.5,16.5 21.95,11C21.5,6.25 17.73,2.5 13,2.03V2.05M5.67,19.74C7.18,21 9.04,21.79 11,22V20C9.58,19.82 8.23,19.25 7.1,18.37L5.67,19.74M7.1,5.74C8.22,4.84 9.57,4.26 11,4.06V2.06C9.05,2.25 7.19,3 5.67,4.26L7.1,5.74M5.69,7.1L4.26,5.67C3,7.19 2.25,9.04 2.05,11H4.05C4.24,9.58 4.8,8.23 5.69,7.1M4.06,13H2.06C2.26,14.96 3.03,16.81 4.27,18.33L5.69,16.9C4.81,15.77 4.24,14.42 4.06,13M10,16.5L16,12L10,7.5V16.5Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M13,2.05V4.05C17.39,4.59 20.5,8.58 19.96,12.97C19.5,16.61 16.64,19.5 13,19.93V21.93C18.5,21.38 22.5,16.5 21.95,11C21.5,6.25 17.73,2.5 13,2.03V2.05M5.67,19.74C7.18,21 9.04,21.79 11,22V20C9.58,19.82 8.23,19.25 7.1,18.37L5.67,19.74M7.1,5.74C8.22,4.84 9.57,4.26 11,4.06V2.06C9.05,2.25 7.19,3 5.67,4.26L7.1,5.74M5.69,7.1L4.26,5.67C3,7.19 2.25,9.04 2.05,11H4.05C4.24,9.58 4.8,8.23 5.69,7.1M4.06,13H2.06C2.26,14.96 3.03,16.81 4.27,18.33L5.69,16.9C4.81,15.77 4.24,14.42 4.06,13M10,16.5L16,12L10,7.5V16.5Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 791 B After Width: | Height: | Size: 800 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M12,3C7.79,3 3.7,4.41 0.38,7C4.41,12.06 7.89,16.37 12,21.5C16.08,16.42 20.24,11.24 23.65,7C20.32,4.41 16.22,3 12,3Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M12,3C7.79,3 3.7,4.41 0.38,7C4.41,12.06 7.89,16.37 12,21.5C16.08,16.42 20.24,11.24 23.65,7C20.32,4.41 16.22,3 12,3Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 410 B After Width: | Height: | Size: 419 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M17,19H7V5H17M17,1H7C5.89,1 5,1.89 5,3V21A2,2 0 0,0 7,23H17A2,2 0 0,0 19,21V3C19,1.89 18.1,1 17,1Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M17,19H7V5H17M17,1H7C5.89,1 5,1.89 5,3V21A2,2 0 0,0 7,23H17A2,2 0 0,0 19,21V3C19,1.89 18.1,1 17,1Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 393 B After Width: | Height: | Size: 402 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M16.56,5.44L15.11,6.89C16.84,7.94 18,9.83 18,12A6,6 0 0,1 12,18A6,6 0 0,1 6,12C6,9.83 7.16,7.94 8.88,6.88L7.44,5.44C5.36,6.88 4,9.28 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12C20,9.28 18.64,6.88 16.56,5.44M13,3H11V13H13" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24">
|
||||||
|
<path d="M16.56,5.44L15.11,6.89C16.84,7.94 18,9.83 18,12A6,6 0 0,1 12,18A6,6 0 0,1 6,12C6,9.83 7.16,7.94 8.88,6.88L7.44,5.44C5.36,6.88 4,9.28 4,12A8,8 0 0,0 12,20A8,8 0 0,0 20,12C20,9.28 18.64,6.88 16.56,5.44M13,3H11V13H13" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 508 B After Width: | Height: | Size: 515 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M18,3H6V7H18M19,12A1,1 0 0,1 18,11A1,1 0 0,1 19,10A1,1 0 0,1 20,11A1,1 0 0,1 19,12M16,19H8V14H16M19,8H5A3,3 0 0,0 2,11V17H6V21H18V17H22V11A3,3 0 0,0 19,8Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M18,3H6V7H18M19,12A1,1 0 0,1 18,11A1,1 0 0,1 19,10A1,1 0 0,1 20,11A1,1 0 0,1 19,12M16,19H8V14H16M19,8H5A3,3 0 0,0 2,11V17H6V21H18V17H22V11A3,3 0 0,0 19,8Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 449 B After Width: | Height: | Size: 458 B |
@@ -1 +1,3 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z" /></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path d="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 289 B After Width: | Height: | Size: 294 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M4.2,10.7L19.8,5L20.5,6.9L6.4,12H19A2,2 0 0,1 21,14V18A2,2 0 0,1 19,20H5A2,2 0 0,1 3,18V12.5C3,11.7 3.5,10.9 4.2,10.7M17,17H19V15H17V17M5,17H15V15H5V17Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M4.2,10.7L19.8,5L20.5,6.9L6.4,12H19A2,2 0 0,1 21,14V18A2,2 0 0,1 19,20H5A2,2 0 0,1 3,18V12.5C3,11.7 3.5,10.9 4.2,10.7M17,17H19V15H17V17M5,17H15V15H5V17Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 447 B After Width: | Height: | Size: 456 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M21,17H3V5H21M21,3H3A2,2 0 0,0 1,5V17A2,2 0 0,0 3,19H8V21H16V19H21A2,2 0 0,0 23,17V5A2,2 0 0,0 21,3Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M21,17H3V5H21M21,3H3A2,2 0 0,0 1,5V17A2,2 0 0,0 3,19H8V21H16V19H21A2,2 0 0,0 23,17V5A2,2 0 0,0 21,3Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 395 B After Width: | Height: | Size: 404 B |
1
awesome/src/assets/icons/bluetooth/trusted.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23,12L20.6,9.2L20.9,5.5L17.3,4.7L15.4,1.5L12,3L8.6,1.5L6.7,4.7L3.1,5.5L3.4,9.2L1,12L3.4,14.8L3.1,18.5L6.7,19.3L8.6,22.5L12,21L15.4,22.5L17.3,19.3L20.9,18.5L20.6,14.8L23,12M18.7,16.9L16,17.5L14.6,19.9L12,18.8L9.4,19.9L8,17.5L5.3,16.9L5.5,14.1L3.7,12L5.5,9.9L5.3,7.1L8,6.5L9.4,4.1L12,5.2L14.6,4.1L16,6.5L18.7,7.1L18.5,9.9L20.3,12L18.5,14.1L18.7,16.9M16.6,7.6L18,9L10,17L6,13L7.4,11.6L10,14.2L16.6,7.6Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 479 B |
1
awesome/src/assets/icons/bluetooth/untrusted.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23,12L20.56,14.78L20.9,18.46L17.29,19.28L15.4,22.46L12,21L8.6,22.47L6.71,19.29L3.1,18.47L3.44,14.78L1,12L3.44,9.21L3.1,5.53L6.71,4.72L8.6,1.54L12,3L15.4,1.54L17.29,4.72L20.9,5.54L20.56,9.22L23,12M20.33,12L18.5,9.89L18.74,7.1L16,6.5L14.58,4.07L12,5.18L9.42,4.07L8,6.5L5.26,7.09L5.5,9.88L3.67,12L5.5,14.1L5.26,16.9L8,17.5L9.42,19.93L12,18.81L14.58,19.92L16,17.5L18.74,16.89L18.5,14.1L20.33,12Z" /></svg>
|
||||||
|
After Width: | Height: | Size: 471 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M21,16H3V4H21M21,2H3C1.89,2 1,2.89 1,4V16A2,2 0 0,0 3,18H10V20H8V22H16V20H14V18H21A2,2 0 0,0 23,16V4C23,2.89 22.1,2 21,2Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M21,16H3V4H21M21,2H3C1.89,2 1,2.89 1,4V16A2,2 0 0,0 3,18H10V20H8V22H16V20H14V18H21A2,2 0 0,0 23,16V4C23,2.89 22.1,2 21,2Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 416 B After Width: | Height: | Size: 425 B |
@@ -1 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="24" height="24" viewBox="0 0 24 24"><path d="M6,12A6,6 0 0,1 12,6A6,6 0 0,1 18,12A6,6 0 0,1 12,18A6,6 0 0,1 6,12M20,12C20,9.45 18.81,7.19 16.95,5.73L16,0H8L7.05,5.73C5.19,7.19 4,9.45 4,12C4,14.54 5.19,16.81 7.05,18.27L8,24H16L16.95,18.27C18.81,16.81 20,14.54 20,12Z" /></svg>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="128" height="128" viewBox="0 0 24 24">
|
||||||
|
<path d="M6,12A6,6 0 0,1 12,6A6,6 0 0,1 18,12A6,6 0 0,1 12,18A6,6 0 0,1 6,12M20,12C20,9.45 18.81,7.19 16.95,5.73L16,0H8L7.05,5.73C5.19,7.19 4,9.45 4,12C4,14.54 5.19,16.81 7.05,18.27L8,24H16L16.95,18.27C18.81,16.81 20,14.54 20,12Z" />
|
||||||
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 515 B After Width: | Height: | Size: 524 B |
4
awesome/src/assets/icons/network/close.svg
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#00000000">
|
||||||
|
<path d="M0 0h24v24H0z" />
|
||||||
|
<path fill="#f5f5f5" d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 273 B |
3
awesome/src/assets/icons/network/refresh.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
||||||
|
<path d="M17.65,6.35C16.2,4.9 14.21,4 12,4A8,8 0 0,0 4,12A8,8 0 0,0 12,20C15.73,20 18.84,17.45 19.73,14H17.65C16.83,16.33 14.61,18 12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6C13.66,6 15.14,6.69 16.22,7.78L13,11H20V4L17.65,6.35Z" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 294 B |
@@ -8,6 +8,7 @@ local gears = require("gears")
|
|||||||
local menubar = require('menubar')
|
local menubar = require('menubar')
|
||||||
local naughty = require("naughty")
|
local naughty = require("naughty")
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
local wtemplate = require("wibox.template")
|
||||||
|
|
||||||
local rubato = require("src.lib.rubato")
|
local rubato = require("src.lib.rubato")
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ naughty.connect_signal(
|
|||||||
n.message = string.format("<span foreground='%s'>%s</span>", Theme_config.notification.fg_normal_message,
|
n.message = string.format("<span foreground='%s'>%s</span>", Theme_config.notification.fg_normal_message,
|
||||||
n.message) or ""
|
n.message) or ""
|
||||||
n.bg = Theme_config.notification.bg_normal
|
n.bg = Theme_config.notification.bg_normal
|
||||||
n.timeout = n.timeout or Theme_config.notification.timeout
|
n.timeout = n.timeout or Theme_config.notification.timeout or 3
|
||||||
end
|
end
|
||||||
|
|
||||||
local use_image = false
|
local use_image = false
|
||||||
@@ -91,10 +92,10 @@ naughty.connect_signal(
|
|||||||
use_image = true
|
use_image = true
|
||||||
end
|
end
|
||||||
|
|
||||||
local action_template_widget = {}
|
local action_template_widget
|
||||||
|
|
||||||
if use_image then
|
if use_image then
|
||||||
action_template_widget = {
|
action_template_widget = wibox.template {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -127,7 +128,7 @@ naughty.connect_signal(
|
|||||||
widget = wibox.container.margin
|
widget = wibox.container.margin
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
action_template_widget = {
|
action_template_widget = wibox.template {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -176,7 +177,8 @@ naughty.connect_signal(
|
|||||||
arc_start = 10
|
arc_start = 10
|
||||||
end
|
end
|
||||||
|
|
||||||
local w_template = wibox.widget {
|
local w_template = wibox.template {
|
||||||
|
widget = wibox.widget {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -339,9 +341,13 @@ naughty.connect_signal(
|
|||||||
border_width = Theme_config.notification.border_width,
|
border_width = Theme_config.notification.border_width,
|
||||||
shape = Theme_config.notification.shape_inside,
|
shape = Theme_config.notification.shape_inside,
|
||||||
widget = wibox.container.background
|
widget = wibox.container.background
|
||||||
}
|
},
|
||||||
|
update_callback = function()
|
||||||
|
|
||||||
local close = w_template:get_children_by_id("background1")[1]
|
end
|
||||||
|
}
|
||||||
|
local close = w_template:get_widget().max_size.min_size.widget_layout.arc_app_bg.arc_app_layout.arc_app_layout_2.arc_margin
|
||||||
|
.const1.background1
|
||||||
local arc = close.arc_chart
|
local arc = close.arc_chart
|
||||||
|
|
||||||
local timeout = n.timeout
|
local timeout = n.timeout
|
||||||
@@ -359,7 +365,7 @@ naughty.connect_signal(
|
|||||||
|
|
||||||
rubato_timer.target = 0
|
rubato_timer.target = 0
|
||||||
|
|
||||||
w_template:connect_signal(
|
w_template:get_widget():connect_signal(
|
||||||
"mouse::enter",
|
"mouse::enter",
|
||||||
function()
|
function()
|
||||||
n.timeout = 99999
|
n.timeout = 99999
|
||||||
@@ -367,7 +373,7 @@ naughty.connect_signal(
|
|||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
w_template:connect_signal(
|
w_template:get_widget():connect_signal(
|
||||||
"mouse::leave",
|
"mouse::leave",
|
||||||
function()
|
function()
|
||||||
n.timeout = rubato_timer.pos
|
n.timeout = rubato_timer.pos
|
||||||
@@ -379,16 +385,11 @@ naughty.connect_signal(
|
|||||||
|
|
||||||
Hover_signal(close)
|
Hover_signal(close)
|
||||||
|
|
||||||
close:connect_signal(
|
close:connect_signal("button::press", function()
|
||||||
"button::press",
|
|
||||||
function()
|
|
||||||
n:destroy()
|
n:destroy()
|
||||||
end
|
end)
|
||||||
)
|
|
||||||
|
|
||||||
w_template:connect_signal(
|
w_template:get_widget():connect_signal("button::press", function(_, _, _, key)
|
||||||
"button::press",
|
|
||||||
function(_, _, _, key)
|
|
||||||
if key == 3 then
|
if key == 3 then
|
||||||
n:destroy()
|
n:destroy()
|
||||||
end
|
end
|
||||||
@@ -404,8 +405,7 @@ naughty.connect_signal(
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
)
|
|
||||||
|
|
||||||
local box = naughty.layout.box {
|
local box = naughty.layout.box {
|
||||||
notification = n,
|
notification = n,
|
||||||
|
|||||||
@@ -34,13 +34,6 @@ capi.client.connect_signal(
|
|||||||
if capi.awesome.startup and not c.size_hints.user_porition and not c.size_hints.program_position then
|
if capi.awesome.startup and not c.size_hints.user_porition and not c.size_hints.program_position then
|
||||||
awful.placement.no_offscreen(c)
|
awful.placement.no_offscreen(c)
|
||||||
end
|
end
|
||||||
c.shape = function(cr, width, height)
|
|
||||||
if c.fullscreen or c.maximized then
|
|
||||||
gears.shape.rectangle(cr, width, height)
|
|
||||||
else
|
|
||||||
gears.shape.rounded_rect(cr, width, height, 10)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if c.class == "Brave-browser" then
|
if c.class == "Brave-browser" then
|
||||||
c.floating = false
|
c.floating = false
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,135 +0,0 @@
|
|||||||
local awful = require("awful")
|
|
||||||
local gears = require("gears")
|
|
||||||
local dbus_proxy = require("src.lib.dbus_proxy")
|
|
||||||
local lgi = require("lgi")
|
|
||||||
local naughty = require("naughty")
|
|
||||||
|
|
||||||
return function()
|
|
||||||
|
|
||||||
local function get_device_info(object_path)
|
|
||||||
if object_path ~= nil and object_path:match("/org/bluez/hci0/dev") then
|
|
||||||
local device = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.bluez",
|
|
||||||
interface = "org.bluez.Device1",
|
|
||||||
path = object_path
|
|
||||||
}
|
|
||||||
|
|
||||||
local battery = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.bluez",
|
|
||||||
interface = "org.bluez.Battery1",
|
|
||||||
path = object_path
|
|
||||||
}
|
|
||||||
|
|
||||||
local device_properties = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.bluez",
|
|
||||||
interface = "org.freedesktop.DBus.Properties",
|
|
||||||
path = object_path
|
|
||||||
}
|
|
||||||
awesome.emit_signal("bluetooth::scan")
|
|
||||||
if device.Name ~= nil or device.Alias ~= nil then
|
|
||||||
device_properties:connect_signal(function()
|
|
||||||
awesome.emit_signal("bluetooth::device_changed", device, battery)
|
|
||||||
end, "PropertiesChanged")
|
|
||||||
awesome.emit_signal("bluetooth::device_changed", device, battery)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"lsusb | grep Bluetooth",
|
|
||||||
function(stdout)
|
|
||||||
stdout = stdout:gsub("\n", "")
|
|
||||||
if stdout ~= "" or stdout == nil then
|
|
||||||
local ObjectManager = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.bluez",
|
|
||||||
interface = "org.freedesktop.DBus.ObjectManager",
|
|
||||||
path = "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
local Adapter = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.bluez",
|
|
||||||
interface = "org.bluez.Adapter1",
|
|
||||||
path = "/org/bluez/hci0"
|
|
||||||
}
|
|
||||||
|
|
||||||
local AdapterProperties = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.bluez",
|
|
||||||
interface = "org.freedesktop.DBus.Properties",
|
|
||||||
path = "/org/bluez/hci0"
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectManager:connect_signal(
|
|
||||||
function(interface)
|
|
||||||
get_device_info(interface)
|
|
||||||
end,
|
|
||||||
"InterfacesAdded"
|
|
||||||
)
|
|
||||||
|
|
||||||
ObjectManager:connect_signal(
|
|
||||||
function(interface)
|
|
||||||
awesome.emit_signal("device_removed", interface)
|
|
||||||
end,
|
|
||||||
"InterfacesRemoved"
|
|
||||||
)
|
|
||||||
|
|
||||||
Adapter:connect_signal(
|
|
||||||
function(data)
|
|
||||||
if data.Powered ~= nil then
|
|
||||||
awesome.emit_signal("state", data.Powered)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
"PropertiesChanged"
|
|
||||||
)
|
|
||||||
|
|
||||||
awesome.connect_signal(
|
|
||||||
"bluetooth::scan",
|
|
||||||
function()
|
|
||||||
Adapter:StartDiscovery()
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
AdapterProperties:connect_signal(
|
|
||||||
function(data)
|
|
||||||
if data.Powered ~= nil then
|
|
||||||
if data.Powered then
|
|
||||||
Adapter:StartDiscovery()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
"PropertiesChanged"
|
|
||||||
)
|
|
||||||
|
|
||||||
awesome.connect_signal("toggle_bluetooth",
|
|
||||||
function()
|
|
||||||
local is_powered = Adapter.Powered
|
|
||||||
Adapter:Set(
|
|
||||||
"org.bluez.Adapter1",
|
|
||||||
"Powered",
|
|
||||||
lgi.GLib.Variant("b", not is_powered)
|
|
||||||
)
|
|
||||||
Adapter.Powered = { signature = "b", value = not is_powered }
|
|
||||||
awesome.emit_signal("state", Adapter.Powered)
|
|
||||||
end)
|
|
||||||
|
|
||||||
gears.timer.delayed_call(
|
|
||||||
function()
|
|
||||||
local objects = ObjectManager:GetManagedObjects()
|
|
||||||
|
|
||||||
for object_path, _ in pairs(objects) do
|
|
||||||
get_device_info(object_path)
|
|
||||||
end
|
|
||||||
|
|
||||||
awesome.emit_signal("state", Adapter.Powered)
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -44,6 +44,47 @@ function application_grid:get_widget()
|
|||||||
return self._private.widget
|
return self._private.widget
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function levenshtein_distance(str1, str2)
|
||||||
|
local len1 = string.len(str1)
|
||||||
|
local len2 = string.len(str2)
|
||||||
|
local matrix = {}
|
||||||
|
local cost = 0
|
||||||
|
|
||||||
|
if (len1 == 0) then
|
||||||
|
return len2
|
||||||
|
elseif (len2 == 0) then
|
||||||
|
return len1
|
||||||
|
elseif (str1 == str2) then
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 0, len1, 1 do
|
||||||
|
matrix[i] = {}
|
||||||
|
matrix[i][0] = i
|
||||||
|
end
|
||||||
|
for j = 0, len2, 1 do
|
||||||
|
matrix[0][j] = j
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, len1, 1 do
|
||||||
|
for j = 1, len2, 1 do
|
||||||
|
if str1:byte(i) == str2:byte(j) then
|
||||||
|
cost = 0
|
||||||
|
else
|
||||||
|
cost = 1
|
||||||
|
end
|
||||||
|
|
||||||
|
matrix[i][j] = math.min(
|
||||||
|
matrix[i - 1][j] + 1,
|
||||||
|
matrix[i][j - 1] + 1,
|
||||||
|
matrix[i - 1][j - 1] + cost
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return matrix[len1][len2]
|
||||||
|
end
|
||||||
|
|
||||||
function application_grid:get_applications_from_file()
|
function application_grid:get_applications_from_file()
|
||||||
local list = {}
|
local list = {}
|
||||||
local app_info = Gio.AppInfo
|
local app_info = Gio.AppInfo
|
||||||
@@ -101,6 +142,7 @@ function application_grid:get_applications_from_file()
|
|||||||
border_width = Theme_config.application_launcher.application.border_width,
|
border_width = Theme_config.application_launcher.application.border_width,
|
||||||
bg = Theme_config.application_launcher.application.bg,
|
bg = Theme_config.application_launcher.application.bg,
|
||||||
fg = Theme_config.application_launcher.application.fg,
|
fg = Theme_config.application_launcher.application.fg,
|
||||||
|
desktop_file = Gio.DesktopAppInfo.get_filename(desktop_app_info) or "",
|
||||||
shape = function(cr, width, height)
|
shape = function(cr, width, height)
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(8))
|
gears.shape.rounded_rect(cr, width, height, dpi(8))
|
||||||
end,
|
end,
|
||||||
@@ -256,29 +298,64 @@ function application_grid:set_applications(search_filter)
|
|||||||
layout = wibox.layout.grid
|
layout = wibox.layout.grid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local dir = gfilesystem.get_configuration_dir() .. "src/config/applications.json"
|
||||||
|
if not gfilesystem.file_readable(dir) then return end
|
||||||
|
|
||||||
|
local handler = io.open(dir, "r")
|
||||||
|
if not handler then return end
|
||||||
|
local dock_encoded = handler:read("a") or "{}"
|
||||||
|
local dock = json:decode(dock_encoded)
|
||||||
|
if type(dock) ~= "table" then return end
|
||||||
|
local mylist = {}
|
||||||
for _, application in ipairs(self.app_list) do
|
for _, application in ipairs(self.app_list) do
|
||||||
-- Match the filter
|
-- Match the filter
|
||||||
if string.match(string.lower(application.name or ""), string.lower(filter)) or
|
if string.match(string.lower(application.name or ""), string.lower(filter)) or
|
||||||
string.match(string.lower(application.categories or ""), string.lower(filter)) or
|
string.match(string.lower(application.categories or ""), string.lower(filter)) or
|
||||||
string.match(string.lower(application.keywords or ""), string.lower(filter)) then
|
string.match(string.lower(application.keywords or ""), string.lower(filter)) then
|
||||||
grid:add(application)
|
|
||||||
|
|
||||||
-- Get the current position in the grid of the application as a table
|
if #dock == 0 then
|
||||||
local pos = grid:get_widget_position(application)
|
application.counter = 0
|
||||||
|
end
|
||||||
|
for _, app in ipairs(dock) do
|
||||||
|
if app.desktop_file == application.desktop_file then
|
||||||
|
application.counter = app.counter or 0
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
application.counter = 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Check if the curser is currently at the same position as the application
|
table.insert(mylist, application)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(mylist, function(a, b)
|
||||||
|
return levenshtein_distance(filter, a.name) < levenshtein_distance(filter, b.name)
|
||||||
|
end)
|
||||||
|
--sort mytable by counter
|
||||||
|
table.sort(mylist, function(a, b)
|
||||||
|
return a.counter > b.counter
|
||||||
|
end)
|
||||||
|
|
||||||
|
for _, app in ipairs(mylist) do
|
||||||
|
grid:add(app)
|
||||||
|
|
||||||
|
-- Get the current position in the grid of the app as a table
|
||||||
|
local pos = grid:get_widget_position(app)
|
||||||
|
|
||||||
|
-- Check if the curser is currently at the same position as the app
|
||||||
capi.awesome.connect_signal(
|
capi.awesome.connect_signal(
|
||||||
"update::selected",
|
"update::selected",
|
||||||
function()
|
function()
|
||||||
if self._private.curser.y == pos.row and self._private.curser.x == pos.col then
|
if self._private.curser.y == pos.row and self._private.curser.x == pos.col then
|
||||||
application.border_color = Theme_config.application_launcher.application.border_color_active
|
app.border_color = Theme_config.application_launcher.application.border_color_active
|
||||||
else
|
else
|
||||||
application.border_color = Theme_config.application_launcher.application.border_color
|
app.border_color = Theme_config.application_launcher.application.border_color
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
capi.awesome.emit_signal("update::selected")
|
capi.awesome.emit_signal("update::selected")
|
||||||
self:set_widget(grid)
|
self:set_widget(grid)
|
||||||
end
|
end
|
||||||
@@ -292,7 +369,6 @@ function application_grid:move_up()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function application_grid:move_down()
|
function application_grid:move_down()
|
||||||
print(self._private.curser.y)
|
|
||||||
self._private.curser.y = self._private.curser.y + 1
|
self._private.curser.y = self._private.curser.y + 1
|
||||||
local grid_rows, _ = self:get_widget():get_dimension()
|
local grid_rows, _ = self:get_widget():get_dimension()
|
||||||
if self._private.curser.y > grid_rows then
|
if self._private.curser.y > grid_rows then
|
||||||
@@ -322,6 +398,35 @@ function application_grid:execute()
|
|||||||
local selected_widget = self:get_widget():get_widgets_at(self._private.curser.y,
|
local selected_widget = self:get_widget():get_widgets_at(self._private.curser.y,
|
||||||
self._private.curser.x)[1]
|
self._private.curser.x)[1]
|
||||||
Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(selected_widget.exec, nil, 0))
|
Gio.AppInfo.launch_uris_async(Gio.AppInfo.create_from_commandline(selected_widget.exec, nil, 0))
|
||||||
|
|
||||||
|
local dir = gfilesystem.get_configuration_dir() .. "src/config/applications.json"
|
||||||
|
if not gfilesystem.file_readable(dir) then return end
|
||||||
|
|
||||||
|
local handler = io.open(dir, "r")
|
||||||
|
if not handler then return end
|
||||||
|
local dock_encoded = handler:read("a") or "{}"
|
||||||
|
local dock = json:decode(dock_encoded)
|
||||||
|
if type(dock) ~= "table" then return end
|
||||||
|
for _, prog in ipairs(dock) do
|
||||||
|
if prog.desktop_file:match(selected_widget.desktop_file) then
|
||||||
|
prog.counter = prog.counter + 1
|
||||||
|
goto continue
|
||||||
|
end
|
||||||
|
end
|
||||||
|
do
|
||||||
|
local prog = {
|
||||||
|
name = selected_widget.name,
|
||||||
|
desktop_file = selected_widget.desktop_file,
|
||||||
|
counter = 1
|
||||||
|
}
|
||||||
|
table.insert(dock, prog)
|
||||||
|
end
|
||||||
|
::continue::
|
||||||
|
handler:close()
|
||||||
|
handler = io.open(dir, "w")
|
||||||
|
if not handler then return end
|
||||||
|
handler:write(json:encode_pretty(dock))
|
||||||
|
handler:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
function application_grid:reset()
|
function application_grid:reset()
|
||||||
@@ -344,10 +449,17 @@ function application_grid.new(args)
|
|||||||
y = 1
|
y = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- Create folder and file if it doesn't exist
|
||||||
|
local dir = gfilesystem.get_configuration_dir() .. "src/config"
|
||||||
|
gfilesystem.make_directories(dir)
|
||||||
|
dir = dir .. "/applications.json"
|
||||||
|
if not gfilesystem.file_readable(dir) then
|
||||||
|
os.execute("touch " .. dir)
|
||||||
|
end
|
||||||
|
|
||||||
w:get_applications_from_file()
|
w:get_applications_from_file()
|
||||||
|
|
||||||
w:set_applications()
|
w:set_applications()
|
||||||
|
|
||||||
return w
|
return w
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ local wibox = require("wibox")
|
|||||||
local gshape = require("gears.shape")
|
local gshape = require("gears.shape")
|
||||||
local gtable = require("gears.table")
|
local gtable = require("gears.table")
|
||||||
local gobject = require("gears.object")
|
local gobject = require("gears.object")
|
||||||
|
local abutton = require("awful.button")
|
||||||
|
|
||||||
local capi = {
|
local capi = {
|
||||||
awesome = awesome,
|
awesome = awesome,
|
||||||
@@ -18,39 +19,6 @@ local capi = {
|
|||||||
|
|
||||||
local application_launcher = { mt = {} }
|
local application_launcher = { mt = {} }
|
||||||
|
|
||||||
application_launcher.searchbar = awful.widget.inputbox {
|
|
||||||
widget_template = wibox.template {
|
|
||||||
widget = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
halign = "left",
|
|
||||||
valign = "center",
|
|
||||||
id = "text_role",
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = 5,
|
|
||||||
id = "marg"
|
|
||||||
},
|
|
||||||
widget = wibox.container.constraint,
|
|
||||||
strategy = "exact",
|
|
||||||
width = 400,
|
|
||||||
height = 50,
|
|
||||||
id = "const"
|
|
||||||
},
|
|
||||||
widget = wibox.container.background,
|
|
||||||
bg = "#212121",
|
|
||||||
fg = "#F0F0F0",
|
|
||||||
border_color = "#414141",
|
|
||||||
border_width = 2,
|
|
||||||
shape = gshape.rounded_rect,
|
|
||||||
},
|
|
||||||
update_callback = function(template_widget, args)
|
|
||||||
template_widget.widget.const.marg.text_role.markup = args.text
|
|
||||||
end
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
application_launcher.application_grid = require("src.modules.application_launcher.application") {}
|
application_launcher.application_grid = require("src.modules.application_launcher.application") {}
|
||||||
|
|
||||||
@@ -62,10 +30,58 @@ function application_launcher.new(args)
|
|||||||
|
|
||||||
gtable.crush(ret, application_launcher, true)
|
gtable.crush(ret, application_launcher, true)
|
||||||
|
|
||||||
|
local searchbar = awful.widget.inputbox {
|
||||||
|
hint_text = "Search...",
|
||||||
|
valign = "center",
|
||||||
|
halign = "left",
|
||||||
|
}
|
||||||
|
|
||||||
|
searchbar:buttons(
|
||||||
|
gtable.join {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
searchbar:focus()
|
||||||
|
end)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
local old_cursor, old_wibox
|
||||||
|
searchbar:connect_signal("mouse::enter", function()
|
||||||
|
local wid = capi.mouse.current_wibox
|
||||||
|
if wid then
|
||||||
|
old_cursor, old_wibox = wid.cursor, wid
|
||||||
|
wid.cursor = "xterm"
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
searchbar:connect_signal("mouse::leave", function()
|
||||||
|
old_wibox.cursor = old_cursor
|
||||||
|
old_wibox = nil
|
||||||
|
end)
|
||||||
|
|
||||||
local applicaton_launcher = wibox.widget {
|
local applicaton_launcher = wibox.widget {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
ret.searchbar,
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
searchbar,
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
margins = 5,
|
||||||
|
id = "marg"
|
||||||
|
},
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
strategy = "exact",
|
||||||
|
width = 400,
|
||||||
|
height = 50,
|
||||||
|
id = "const"
|
||||||
|
},
|
||||||
|
widget = wibox.container.background,
|
||||||
|
bg = Theme_config.application_launcher.searchbar.bg,
|
||||||
|
fg = Theme_config.application_launcher.searchbar.fg,
|
||||||
|
border_color = Theme_config.application_launcher.searchbar.border_color,
|
||||||
|
border_width = Theme_config.application_launcher.searchbar.border_width,
|
||||||
|
shape = gshape.rounded_rect,
|
||||||
|
id = "searchbar_bg"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
ret.application_grid,
|
ret.application_grid,
|
||||||
spacing = dpi(10),
|
spacing = dpi(10),
|
||||||
@@ -101,52 +117,70 @@ function application_launcher.new(args)
|
|||||||
border_width = Theme_config.application_launcher.border_width
|
border_width = Theme_config.application_launcher.border_width
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local searchbar_bg = applicaton_launcher:get_children_by_id("searchbar_bg")[1]
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
capi.awesome.connect_signal(
|
||||||
"application_launcher::show",
|
"application_launcher::show",
|
||||||
function()
|
function()
|
||||||
|
capi.awesome.emit_signal("update::selected")
|
||||||
if capi.mouse.screen == args.screen then
|
if capi.mouse.screen == args.screen then
|
||||||
ret.application_container.visible = not ret.application_container.visible
|
ret.application_container.visible = not ret.application_container.visible
|
||||||
end
|
end
|
||||||
if ret.application_container.visible then
|
if ret.application_container.visible then
|
||||||
ret.searchbar:focus()
|
searchbar_bg.border_color = Theme_config.application_launcher.searchbar.border_active
|
||||||
|
searchbar:focus()
|
||||||
else
|
else
|
||||||
|
searchbar:set_text("")
|
||||||
awful.keygrabber.stop()
|
awful.keygrabber.stop()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
ret.searchbar:connect_signal(
|
searchbar:connect_signal(
|
||||||
"submit",
|
"submit",
|
||||||
function(text)
|
function(_, text)
|
||||||
ret.application_grid:execute()
|
ret.application_grid:execute()
|
||||||
capi.awesome.emit_signal("application_launcher::show")
|
capi.awesome.emit_signal("application_launcher::show")
|
||||||
|
searchbar:set_text("")
|
||||||
|
ret.application_grid:set_applications(searchbar:get_text())
|
||||||
|
searchbar_bg.border_color = Theme_config.application_launcher.searchbar.border_color
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
ret.searchbar:connect_signal(
|
searchbar:connect_signal(
|
||||||
"stopped",
|
"stopped",
|
||||||
function()
|
function(_, stop_key)
|
||||||
ret.searchbar:get_widget().widget.border_color = Theme_config.application_launcher.searchbar.border_color
|
if stop_key == "Escape" then
|
||||||
|
capi.awesome.emit_signal("application_launcher::show")
|
||||||
|
end
|
||||||
|
searchbar:set_text("")
|
||||||
|
ret.application_grid:set_applications(searchbar:get_text())
|
||||||
|
searchbar_bg.border_color = Theme_config.application_launcher.searchbar.border_color
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
ret.searchbar:connect_signal(
|
searchbar:connect_signal(
|
||||||
"started",
|
"started",
|
||||||
function()
|
function()
|
||||||
ret.searchbar:get_widget().widget.border_color = Theme_config.application_launcher.searchbar.border_active
|
searchbar_bg.border_color = Theme_config.application_launcher.searchbar.border_active
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
awesome.connect_signal(
|
searchbar:connect_signal(
|
||||||
"inputbox::key_pressed",
|
"inputbox::key_pressed",
|
||||||
function(modkey, key)
|
function(_, modkey, key)
|
||||||
if key == "Escape" then
|
if key == "Escape" then
|
||||||
ret.searchbar:stop()
|
searchbar:stop()
|
||||||
capi.awesome.emit_signal("application_launcher::show")
|
capi.awesome.emit_signal("application_launcher::show")
|
||||||
ret.application_grid:reset()
|
ret.application_grid:reset()
|
||||||
ret.searchbar:set_text("")
|
searchbar:set_text("")
|
||||||
elseif key == "Down" or key == "Right" then
|
elseif key == "Down" or key == "Right" then
|
||||||
ret.searchbar:stop()
|
if key == "Down" then
|
||||||
|
ret.application_grid:move_down()
|
||||||
|
elseif key == "Right" then
|
||||||
|
ret.application_grid:move_right()
|
||||||
|
end
|
||||||
|
searchbar:stop()
|
||||||
awful.keygrabber.run(function(mod, key2, event)
|
awful.keygrabber.run(function(mod, key2, event)
|
||||||
if event == "press" then
|
if event == "press" then
|
||||||
if key2 == "Down" then
|
if key2 == "Down" then
|
||||||
@@ -155,7 +189,7 @@ function application_launcher.new(args)
|
|||||||
local old_y = ret.application_grid._private.curser.y
|
local old_y = ret.application_grid._private.curser.y
|
||||||
ret.application_grid:move_up()
|
ret.application_grid:move_up()
|
||||||
if old_y - ret.application_grid._private.curser.y == 0 then
|
if old_y - ret.application_grid._private.curser.y == 0 then
|
||||||
ret.searchbar:focus()
|
searchbar:focus()
|
||||||
end
|
end
|
||||||
elseif key2 == "Left" then
|
elseif key2 == "Left" then
|
||||||
ret.application_grid:move_left()
|
ret.application_grid:move_left()
|
||||||
@@ -166,17 +200,20 @@ function application_launcher.new(args)
|
|||||||
ret.application_grid:execute()
|
ret.application_grid:execute()
|
||||||
capi.awesome.emit_signal("application_launcher::show")
|
capi.awesome.emit_signal("application_launcher::show")
|
||||||
ret.application_grid:reset()
|
ret.application_grid:reset()
|
||||||
ret.searchbar:set_text("")
|
searchbar:set_text("")
|
||||||
|
ret.application_grid:set_applications(searchbar:get_text())
|
||||||
elseif key2 == "Escape" then
|
elseif key2 == "Escape" then
|
||||||
capi.awesome.emit_signal("application_launcher::show")
|
capi.awesome.emit_signal("application_launcher::show")
|
||||||
ret.application_grid:reset()
|
ret.application_grid:reset()
|
||||||
ret.searchbar:set_text("")
|
searchbar:set_text("")
|
||||||
|
ret.application_grid:set_applications(searchbar:get_text())
|
||||||
awful.keygrabber.stop()
|
awful.keygrabber.stop()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
searchbar_bg.border_color = Theme_config.application_launcher.searchbar.border_color
|
||||||
end
|
end
|
||||||
ret.application_grid:set_applications(ret.searchbar:get_text())
|
ret.application_grid:set_applications(searchbar:get_text())
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,252 +0,0 @@
|
|||||||
-------------------------------------------------------
|
|
||||||
-- This is the seachbar for the application launcher --
|
|
||||||
-------------------------------------------------------
|
|
||||||
|
|
||||||
-- Awesome Libs
|
|
||||||
local awful = require("awful")
|
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
|
||||||
local gears = require("gears")
|
|
||||||
local gstring = gears.string
|
|
||||||
local keygrabber = require("awful.keygrabber")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
awesome = awesome,
|
|
||||||
mouse = mouse,
|
|
||||||
}
|
|
||||||
|
|
||||||
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/application_launcher/searchbar/"
|
|
||||||
|
|
||||||
local kgrabber
|
|
||||||
|
|
||||||
return function()
|
|
||||||
|
|
||||||
local searchbar = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{ -- Search icon
|
|
||||||
{
|
|
||||||
{
|
|
||||||
resize = false,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
image = gears.color.recolor_image(icondir .. "search.svg",
|
|
||||||
Theme_config.application_launcher.searchbar.icon_color),
|
|
||||||
widget = wibox.widget.imagebox
|
|
||||||
},
|
|
||||||
bg = Theme_config.application_launcher.searchbar.icon_background,
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
strategy = "exact",
|
|
||||||
width = dpi(30),
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
fg = Theme_config.application_launcher.searchbar.fg_hint,
|
|
||||||
markup = "Search",
|
|
||||||
valign = "center",
|
|
||||||
align = "center",
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
id = "search_hint"
|
|
||||||
},
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
id = "s_margin"
|
|
||||||
},
|
|
||||||
widget = wibox.layout.fixed.horizontal,
|
|
||||||
id = "s_layout"
|
|
||||||
},
|
|
||||||
bg = Theme_config.application_launcher.searchbar.bg,
|
|
||||||
fg = Theme_config.application_launcher.searchbar.fg,
|
|
||||||
border_color = Theme_config.application_launcher.searchbar.border_color,
|
|
||||||
border_width = Theme_config.application_launcher.searchbar.border_width,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
shape = Theme_config.application_launcher.searchbar.shape,
|
|
||||||
id = "s_background"
|
|
||||||
},
|
|
||||||
width = dpi(400),
|
|
||||||
height = dpi(40),
|
|
||||||
strategy = "exact",
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
}
|
|
||||||
|
|
||||||
local old_wibox, old_cursor
|
|
||||||
local mouse_enter = function()
|
|
||||||
local w = capi.mouse.current_wibox
|
|
||||||
if w then
|
|
||||||
old_cursor, old_wibox = w.cursor, w
|
|
||||||
w.cursor = "xterm"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local mouse_leave = function()
|
|
||||||
old_wibox.cursor = old_cursor
|
|
||||||
old_wibox = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
searchbar:disconnect_signal("mouse::enter", mouse_enter)
|
|
||||||
searchbar:disconnect_signal("mouse::leave", mouse_leave)
|
|
||||||
searchbar:connect_signal("mouse::enter", mouse_enter)
|
|
||||||
searchbar:connect_signal("mouse::leave", mouse_leave)
|
|
||||||
|
|
||||||
local function have_multibyte_char_at(text, position)
|
|
||||||
return #text:sub(position, position) == -1
|
|
||||||
end
|
|
||||||
|
|
||||||
local search_text = searchbar:get_children_by_id("search_hint")[1]
|
|
||||||
|
|
||||||
local function promt_text_with_cursor(text, cursor_pos)
|
|
||||||
local char, spacer, text_start, text_end
|
|
||||||
|
|
||||||
local cursor_color = Theme_config.application_launcher.searchbar.bg_cursor
|
|
||||||
local text_color = Theme_config.application_launcher.searchbar.fg_cursor
|
|
||||||
|
|
||||||
if text == "" then
|
|
||||||
return "<span foreground='" .. Theme_config.application_launcher.searchbar.fg_hint .. "'>Search</span>"
|
|
||||||
end
|
|
||||||
|
|
||||||
if #text < cursor_pos then
|
|
||||||
char = " "
|
|
||||||
spacer = ""
|
|
||||||
text_start = gstring.xml_escape(text)
|
|
||||||
text_end = ""
|
|
||||||
else
|
|
||||||
local offset = 0
|
|
||||||
if have_multibyte_char_at(text, cursor_pos) then
|
|
||||||
offset = 1
|
|
||||||
end
|
|
||||||
char = gstring.xml_escape(text:sub(cursor_pos, cursor_pos + offset))
|
|
||||||
spacer = " "
|
|
||||||
text_start = gstring.xml_escape(text:sub(1, cursor_pos - 1))
|
|
||||||
text_end = gstring.xml_escape(text:sub(cursor_pos + offset + 1))
|
|
||||||
end
|
|
||||||
|
|
||||||
return text_start ..
|
|
||||||
"<span background='" ..
|
|
||||||
cursor_color .. "' foreground='" .. text_color .. "'>" .. char .. "</span>" .. text_end .. spacer
|
|
||||||
end
|
|
||||||
|
|
||||||
local text_string = ""
|
|
||||||
|
|
||||||
---Start a new keygrabber to simulate an input textbox
|
|
||||||
local function keygrabber_start()
|
|
||||||
local cur_pos = #text_string + 1
|
|
||||||
|
|
||||||
--Draws the string on each keypress
|
|
||||||
local function update()
|
|
||||||
search_text:set_markup(promt_text_with_cursor(text_string, cur_pos))
|
|
||||||
--Send the string over to the application to filter applications
|
|
||||||
capi.awesome.emit_signal("update::application_list", text_string)
|
|
||||||
end
|
|
||||||
|
|
||||||
update()
|
|
||||||
|
|
||||||
kgrabber = keygrabber.run(
|
|
||||||
function(modifiers, key, event)
|
|
||||||
capi.awesome.connect_signal("searchbar::stop", function()
|
|
||||||
keygrabber.stop(kgrabber)
|
|
||||||
capi.awesome.emit_signal("application_launcher::kgrabber_start")
|
|
||||||
end)
|
|
||||||
|
|
||||||
local mod = {}
|
|
||||||
for _, v in ipairs(modifiers) do
|
|
||||||
mod[v] = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if event ~= "press" then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
--Escape cases
|
|
||||||
if (mod.Control and (key == "c" or key == "g"))
|
|
||||||
or (not mod.Control and key == "Escape") then
|
|
||||||
keygrabber.stop(kgrabber)
|
|
||||||
search_text:set_markup(promt_text_with_cursor("", 1))
|
|
||||||
text_string = ""
|
|
||||||
capi.awesome.emit_signal("application_launcher::show")
|
|
||||||
elseif (not mod.Control and key == "Return") or
|
|
||||||
(not mod.Control and key == "KP_Enter") then
|
|
||||||
keygrabber.stop(kgrabber)
|
|
||||||
searchbar.s_background.border_color = Theme_config.application_launcher.searchbar.border_color
|
|
||||||
searchbar.s_background.fg = Theme_config.application_launcher.searchbar.fg_hint
|
|
||||||
search_text:set_markup(promt_text_with_cursor("", 1))
|
|
||||||
text_string = ""
|
|
||||||
capi.awesome.emit_signal("application_launcher::execute")
|
|
||||||
capi.awesome.emit_signal("application_launcher::show")
|
|
||||||
end
|
|
||||||
|
|
||||||
if mod.Control then
|
|
||||||
elseif mod.Mod1 or mod.Mod3 then
|
|
||||||
else
|
|
||||||
--Delete character to the left and move cursor
|
|
||||||
if key == "BackSpace" then
|
|
||||||
if cur_pos > 1 then
|
|
||||||
local offset = 0
|
|
||||||
if have_multibyte_char_at(text_string, cur_pos - 1) then
|
|
||||||
offset = 1
|
|
||||||
end
|
|
||||||
text_string = text_string:sub(1, cur_pos - 2 - offset) .. text_string:sub(cur_pos)
|
|
||||||
cur_pos = cur_pos - 1 - offset
|
|
||||||
end
|
|
||||||
update()
|
|
||||||
--Delete character to the right
|
|
||||||
elseif key == "Delete" then
|
|
||||||
text_string = text_string:sub(1, cur_pos - 1) .. text_string:sub(cur_pos + 1)
|
|
||||||
update()
|
|
||||||
-- Move cursor to the left
|
|
||||||
elseif key == "Left" then
|
|
||||||
--cur_pos = cur_pos - 1
|
|
||||||
capi.awesome.emit_signal("application::left")
|
|
||||||
-- Move cursor to the right
|
|
||||||
elseif key == "Right" then
|
|
||||||
--cur_pos = cur_pos + 1
|
|
||||||
capi.awesome.emit_signal("application::right")
|
|
||||||
elseif key == "Up" then
|
|
||||||
capi.awesome.emit_signal("application::up")
|
|
||||||
elseif key == "Down" then
|
|
||||||
capi.awesome.emit_signal("application::down")
|
|
||||||
else
|
|
||||||
--Add key at cursor position
|
|
||||||
if key:wlen() == 1 then
|
|
||||||
text_string = text_string:sub(1, cur_pos - 1) .. key .. text_string:sub(cur_pos)
|
|
||||||
cur_pos = cur_pos + #key
|
|
||||||
end
|
|
||||||
update()
|
|
||||||
end
|
|
||||||
--Make sure cursor can't leave string bounds
|
|
||||||
if cur_pos < 1 then
|
|
||||||
cur_pos = 1
|
|
||||||
elseif cur_pos > #text_string + 1 then
|
|
||||||
cur_pos = #text_string + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
--Start the keygrabber when the searchbar is left clicked
|
|
||||||
searchbar:buttons(gears.table.join(
|
|
||||||
awful.button({}, 1, function()
|
|
||||||
if not awful.keygrabber.is_running then
|
|
||||||
searchbar.s_background.border_color = Theme_config.application_launcher.searchbar.border_active
|
|
||||||
searchbar.s_background.fg = Theme_config.application_launcher.searchbar.fg
|
|
||||||
search_text:set_markup(promt_text_with_cursor("", 1))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
))
|
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"searchbar::start",
|
|
||||||
function()
|
|
||||||
if not awful.keygrabber.is_running then
|
|
||||||
keygrabber_start()
|
|
||||||
searchbar.s_background.border_color = Theme_config.application_launcher.searchbar.border_active
|
|
||||||
searchbar.s_background.fg = Theme_config.application_launcher.searchbar.fg
|
|
||||||
search_text:set_markup(promt_text_with_cursor("", 1))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
return searchbar
|
|
||||||
end
|
|
||||||
@@ -5,52 +5,106 @@
|
|||||||
-- Awesome Libs
|
-- Awesome Libs
|
||||||
local awful = require("awful")
|
local awful = require("awful")
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
local dpi = require("beautiful").xresources.apply_dpi
|
||||||
local gobject = require("gears").object
|
|
||||||
local gtable = require("gears").table
|
local gtable = require("gears").table
|
||||||
local gcolor = require("gears").color
|
local gcolor = require("gears").color
|
||||||
local gshape = require("gears").shape
|
local gshape = require("gears").shape
|
||||||
local gfilesystem = require("gears").filesystem
|
local gfilesystem = require("gears").filesystem
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
local base = require("wibox.widget.base")
|
||||||
|
local lgi = require("lgi")
|
||||||
|
local dbus_proxy = require("dbus_proxy")
|
||||||
|
|
||||||
local capi = {
|
local context_menu = require("src.modules.context_menu")
|
||||||
awesome = awesome,
|
|
||||||
}
|
|
||||||
|
|
||||||
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/bluetooth/"
|
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/bluetooth/"
|
||||||
|
|
||||||
|
local capi = {
|
||||||
|
awesome = awesome
|
||||||
|
}
|
||||||
|
|
||||||
local device = { mt = {} }
|
local device = { mt = {} }
|
||||||
|
|
||||||
function device:connect()
|
function device:layout(_, width, height)
|
||||||
self.device:Connect()
|
if self._private.widget then
|
||||||
self.widget:get_children_by_id("con")[1].image = gcolor.recolor_image(icondir .. "link.svg",
|
return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
|
||||||
Theme_config.bluetooth_controller.icon_color_dark)
|
end
|
||||||
capi.awesome.emit_signal("bluetooth::disconnect", device)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function device:disconnect()
|
function device:fit(context, width, height)
|
||||||
self.device:Disconnect()
|
local w, h = 0, 0
|
||||||
self.widget:get_children_by_id("con")[1].image = gcolor.recolor_image(icondir .. "link-off.svg",
|
if self._private.widget then
|
||||||
Theme_config.bluetooth_controller.icon_color_dark)
|
w, h = base.fit_widget(self, context, self._private.widget, width, height)
|
||||||
capi.awesome.emit_signal("bluetooth::connect", device)
|
end
|
||||||
|
return w, h
|
||||||
|
end
|
||||||
|
|
||||||
|
device.set_widget = base.set_widget_common
|
||||||
|
|
||||||
|
function device:get_widget()
|
||||||
|
return self._private.widget
|
||||||
|
end
|
||||||
|
|
||||||
|
function device:toggle_connect()
|
||||||
|
if not self.device.Connected then
|
||||||
|
|
||||||
|
--TODO: Implement device passcode support, I have no idea how to get the
|
||||||
|
--TODO: Methods from Agent1 implemented
|
||||||
|
--[[ self._private.AgentManager1 = dbus_proxy.Proxy:new {
|
||||||
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
|
name = "org.bluez",
|
||||||
|
path = "/org/bluez",
|
||||||
|
interface = "org.bluez.AgentManager1"
|
||||||
|
}
|
||||||
|
|
||||||
|
self._private.Agent1 = dbus_proxy.Proxy:new {
|
||||||
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
|
name = "org.bluez",
|
||||||
|
path = "/org/bluez",
|
||||||
|
interface = "org.bluez.Agent1",
|
||||||
|
}
|
||||||
|
|
||||||
|
self._private.AgentManager1:RegisterAgent(self._private.Agent1.object_path, "")
|
||||||
|
self._private.AgentManager1:RequestDefaultAgent(self._private.Agent1.object_path) ]]
|
||||||
|
|
||||||
|
self.device:ConnectAsync()
|
||||||
|
else
|
||||||
|
self.device:DisconnectAsync()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function device:toggle_pair()
|
||||||
|
if self.device.Paired then
|
||||||
|
self.device:PairAsync()
|
||||||
|
else
|
||||||
|
self.device:CancelPairingAsync()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function device:toggle_trusted()
|
||||||
|
self.device:Set("org.bluez.Device1", "Trusted", lgi.GLib.Variant("b", not self.device.Trusted))
|
||||||
|
self.device.Trusted = { signature = "b", value = not self.device.Trusted }
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function device:rename(newname)
|
||||||
|
self.device:Set("org.bluez.Device1", "Alias", lgi.GLib.Variant("s", newname))
|
||||||
|
self.device.Alias = { signature = "s", value = newname }
|
||||||
|
return self.device:Get("org.bluez.Device1", "Alias")
|
||||||
end
|
end
|
||||||
|
|
||||||
function device.new(args)
|
function device.new(args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
args.device = args.device or {}
|
args.device = args.device or {}
|
||||||
args.battery = args.battery or {}
|
|
||||||
|
|
||||||
local ret = gobject { enable_properties = true, enable_auto_signals = true }
|
|
||||||
gtable.crush(ret, device, true)
|
|
||||||
|
|
||||||
if args.device then
|
|
||||||
ret.device = args.device
|
|
||||||
end
|
|
||||||
if args.battery then
|
|
||||||
ret.battery = args.battery
|
|
||||||
end
|
|
||||||
|
|
||||||
local icon = device.Icon or "bluetooth-on"
|
local icon = device.Icon or "bluetooth-on"
|
||||||
local device_widget = wibox.widget {
|
|
||||||
|
local inputbox = awful.widget.inputbox {
|
||||||
|
text = args.device.Alias or args.device.Name,
|
||||||
|
halign = "left",
|
||||||
|
valign = "center",
|
||||||
|
}
|
||||||
|
|
||||||
|
local ret = base.make_widget_from_value(wibox.widget {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -75,9 +129,11 @@ function device.new(args)
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = ret.device.Alias or ret.device.Name,
|
inputbox,
|
||||||
id = "alias",
|
widget = wibox.container.constraint,
|
||||||
widget = wibox.widget.textbox
|
strategy = "min",
|
||||||
|
width = dpi(400),
|
||||||
|
id = "const"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text = "Connecting...",
|
text = "Connecting...",
|
||||||
@@ -150,33 +206,133 @@ function device.new(args)
|
|||||||
shape = function(cr, width, height)
|
shape = function(cr, width, height)
|
||||||
gshape.rounded_rect(cr, width, height, dpi(4))
|
gshape.rounded_rect(cr, width, height, dpi(4))
|
||||||
end,
|
end,
|
||||||
device = ret.device,
|
|
||||||
widget = wibox.container.background
|
widget = wibox.container.background
|
||||||
|
})
|
||||||
|
|
||||||
|
gtable.crush(ret, device, true)
|
||||||
|
|
||||||
|
if args.device then
|
||||||
|
ret.device = args.device
|
||||||
|
end
|
||||||
|
|
||||||
|
ret:get_children_by_id("con")[1].image = gcolor.recolor_image(ret.device.Connected and icondir .. "link.svg" or
|
||||||
|
icondir .. "link-off.svg",
|
||||||
|
Theme_config.bluetooth_controller.icon_color_dark)
|
||||||
|
|
||||||
|
local cm = context_menu {
|
||||||
|
widget_template = wibox.widget {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
resize = true,
|
||||||
|
valign = "center",
|
||||||
|
halign = "center",
|
||||||
|
id = "icon_role",
|
||||||
|
},
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
stragety = "exact",
|
||||||
|
width = dpi(24),
|
||||||
|
height = dpi(24),
|
||||||
|
id = "const"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
widget = wibox.widget.textbox,
|
||||||
|
valign = "center",
|
||||||
|
halign = "left",
|
||||||
|
id = "text_role"
|
||||||
|
},
|
||||||
|
layout = wibox.layout.fixed.horizontal
|
||||||
|
},
|
||||||
|
widget = wibox.container.margin
|
||||||
|
},
|
||||||
|
widget = wibox.container.background,
|
||||||
|
}, spacing = dpi(10),
|
||||||
|
entries = {
|
||||||
|
{
|
||||||
|
name = ret.device.Connected and "Disconnect" or "Connect",
|
||||||
|
icon = gcolor.recolor_image(ret.device.Connected and icondir .. "bluetooth-off.svg" or
|
||||||
|
icondir .. "bluetooth-on.svg",
|
||||||
|
Theme_config.bluetooth_controller.icon_color),
|
||||||
|
callback = function()
|
||||||
|
ret:toggle_connect()
|
||||||
|
end,
|
||||||
|
id = "connected"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "Pair",
|
||||||
|
icon = gcolor.recolor_image(ret.device.Paired and icondir .. "link-off.svg" or
|
||||||
|
icondir .. "link.svg",
|
||||||
|
Theme_config.bluetooth_controller.icon_color),
|
||||||
|
callback = function()
|
||||||
|
ret:toggle_pair()
|
||||||
|
end
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = ret.device.Trusted and "Untrust" or "Trust",
|
||||||
|
icon = gcolor.recolor_image(ret.device.Trusted and icondir .. "untrusted.svg" or icondir .. "trusted.svg",
|
||||||
|
Theme_config.bluetooth_controller.icon_color),
|
||||||
|
callback = function()
|
||||||
|
ret:toggle_trusted()
|
||||||
|
end,
|
||||||
|
id = "trusted"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "Rename",
|
||||||
|
icon = gcolor.recolor_image(icondir .. "edit.svg", Theme_config.bluetooth_controller.icon_color),
|
||||||
|
callback = function()
|
||||||
|
inputbox:focus()
|
||||||
|
inputbox:connect_signal("submit", function(text)
|
||||||
|
text = text:get_text()
|
||||||
|
inputbox.markup = ret:rename(text)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = "Remove",
|
||||||
|
icon = gcolor.recolor_image(icondir .. "delete.svg", Theme_config.bluetooth_controller.icon_color),
|
||||||
|
callback = function()
|
||||||
|
args.remove_callback(ret.device)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ret.device.Connected then
|
ret:buttons(
|
||||||
device_widget:get_children_by_id("con")[1].image = gcolor.recolor_image(icondir .. "link.svg",
|
|
||||||
Theme_config.bluetooth_controller.icon_color_dark)
|
|
||||||
else
|
|
||||||
device_widget:get_children_by_id("con")[1].image = gcolor.recolor_image(icondir .. "link-off.svg",
|
|
||||||
Theme_config.bluetooth_controller.icon_color_dark)
|
|
||||||
end
|
|
||||||
|
|
||||||
device_widget:buttons(
|
|
||||||
gtable.join(
|
gtable.join(
|
||||||
awful.button({}, 1, function()
|
awful.button({}, 1, function()
|
||||||
if ret.device.Connected then
|
ret:toggle_connect()
|
||||||
ret:disconnect()
|
end),
|
||||||
else
|
awful.button({}, 3, function()
|
||||||
ret:connect()
|
for _, value in ipairs(cm.widget.children) do
|
||||||
|
value.id = value.id or ""
|
||||||
|
if value.id:match("connected") then
|
||||||
|
value:get_children_by_id("text_role")[1].text = ret.device.Connected and "Disconnect" or "Connect"
|
||||||
|
value:get_children_by_id("icon_role")[1].image = gcolor.recolor_image(ret.device.Connected and
|
||||||
|
icondir .. "bluetooth-off.svg" or icondir .. "bluetooth-on.svg",
|
||||||
|
Theme_config.bluetooth_controller.icon_color)
|
||||||
|
elseif value.id:match("trusted") then
|
||||||
|
value:get_children_by_id("text_role")[1].text = ret.device.Trusted and "Untrust" or "Trust"
|
||||||
|
value:get_children_by_id("icon_role")[1].image = gcolor.recolor_image(ret.device.Trusted and
|
||||||
|
icondir .. "untrusted.svg" or icondir .. "trusted.svg", Theme_config.bluetooth_controller.icon_color)
|
||||||
|
elseif value.id:match("paired") then
|
||||||
|
value:get_children_by_id("icon_role")[1].image = gcolor.recolor_image(ret.device.Paired and
|
||||||
|
icondir .. "link-off.svg" or icondir .. "link.svg", Theme_config.bluetooth_controller.icon_color)
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
cm:toggle()
|
||||||
end)
|
end)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
Hover_signal(device_widget)
|
capi.awesome.connect_signal(ret.device.object_path .. "_updated", function(d)
|
||||||
|
ret:get_children_by_id("con")[1].image = gcolor.recolor_image(d.Connected and icondir .. "link.svg" or
|
||||||
|
icondir .. "link-off.svg",
|
||||||
|
Theme_config.bluetooth_controller.icon_color_dark)
|
||||||
|
end)
|
||||||
|
|
||||||
ret.widget = device_widget
|
Hover_signal(ret)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,12 +5,16 @@
|
|||||||
-- Awesome Libs
|
-- Awesome Libs
|
||||||
local awful = require("awful")
|
local awful = require("awful")
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
local dpi = require("beautiful").xresources.apply_dpi
|
||||||
local gobject = require("gears").object
|
|
||||||
local gtable = require("gears").table
|
local gtable = require("gears").table
|
||||||
local gcolor = require("gears").color
|
local gcolor = require("gears").color
|
||||||
local gshape = require("gears").shape
|
local gshape = require("gears").shape
|
||||||
local gfilesystem = require("gears").filesystem
|
local gfilesystem = require("gears").filesystem
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
local base = require("wibox.widget.base")
|
||||||
|
local dbus_proxy = require("dbus_proxy")
|
||||||
|
local lgi = require("lgi")
|
||||||
|
local gtimer = require("gears.timer")
|
||||||
|
local naughty = require("naughty")
|
||||||
|
|
||||||
local bt_device = require("src.modules.bluetooth.device")
|
local bt_device = require("src.modules.bluetooth.device")
|
||||||
|
|
||||||
@@ -18,54 +22,218 @@ local rubato = require("src.lib.rubato")
|
|||||||
|
|
||||||
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/bluetooth/"
|
local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/bluetooth/"
|
||||||
|
|
||||||
|
local dnd_widget = require("awful.widget.toggle_widget")
|
||||||
|
|
||||||
local capi = {
|
local capi = {
|
||||||
awesome = awesome,
|
awesome = awesome,
|
||||||
mouse = mouse,
|
mouse = mouse,
|
||||||
mousegrabber = mousegrabber,
|
mousegrabber = mousegrabber,
|
||||||
}
|
}
|
||||||
|
|
||||||
local bluetooth = { mt = {} }
|
local bluetooth = { mt = {} }
|
||||||
|
|
||||||
bluetooth.devices = {
|
function bluetooth:layout(_, width, height)
|
||||||
paired = { layout = wibox.layout.fixed.vertical },
|
if self._private.widget then
|
||||||
discovered = { layout = wibox.layout.fixed.vertical }
|
return { base.place_widget_at(self._private.widget, 0, 0, width, height) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:fit(context, width, height)
|
||||||
|
local w, h = 0, 0
|
||||||
|
if self._private.widget then
|
||||||
|
w, h = base.fit_widget(self, context, self._private.widget, width, height)
|
||||||
|
end
|
||||||
|
return w, h
|
||||||
|
end
|
||||||
|
|
||||||
|
bluetooth.set_widget = base.set_widget_common
|
||||||
|
|
||||||
|
function bluetooth:get_widget()
|
||||||
|
return self._private.widget
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:get_paired_devices()
|
||||||
|
return self:get_children_by_id("connected_device_list")[1].children
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:get_discovered_devices()
|
||||||
|
return self:get_children_by_id("discovered_device_list")[1].children
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:remove_device_information(device)
|
||||||
|
-- Either disconnect async and have to remove the device "twice"
|
||||||
|
-- or do it sync but awesome freezes for a second or two
|
||||||
|
print("bruh?")
|
||||||
|
device:DisconnectAsync(function(_, _, out, err)
|
||||||
|
print(out, err)
|
||||||
|
self._private.Adapter1:RemoveDevice(device.object_path)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:add_device(device, object_path)
|
||||||
|
|
||||||
|
local plist = self:get_children_by_id("connected_device_list")[1]
|
||||||
|
local dlist = self:get_children_by_id("discovered_device_list")[1]
|
||||||
|
|
||||||
|
for _, value in pairs(dlist.children) do
|
||||||
|
-- I'm not sure why Connected is in both cases true when its a new connection but eh just take it, it works
|
||||||
|
if value.device.Address:match(device.Address) and (device.Connected ~= value.device.Connected) then
|
||||||
|
print("Bad ", value.device.Alias)
|
||||||
|
return
|
||||||
|
elseif value.device.Address:match(device.Address) and (device.Connected == value.device.Connected) then
|
||||||
|
print("Good ", value.device.Alias)
|
||||||
|
dlist:remove_widgets(value)
|
||||||
|
plist:add(plist:add(bt_device {
|
||||||
|
device = device,
|
||||||
|
path = object_path,
|
||||||
|
remove_callback = function()
|
||||||
|
self:remove_device_information(device)
|
||||||
|
end,
|
||||||
|
}))
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, value in pairs(plist.children) do
|
||||||
|
if value.device.Address:match(device.Address) then return end
|
||||||
|
end
|
||||||
|
|
||||||
|
if device.Paired then
|
||||||
|
plist:add(bt_device {
|
||||||
|
device = device,
|
||||||
|
path = object_path,
|
||||||
|
remove_callback = function()
|
||||||
|
self:remove_device_information(device)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
else
|
||||||
|
dlist:add(bt_device {
|
||||||
|
device = device,
|
||||||
|
path = object_path,
|
||||||
|
remove_callback = function()
|
||||||
|
self:remove_device_information(device)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:remove_device(object_path)
|
||||||
|
local plist = self:get_children_by_id("connected_device_list")[1]
|
||||||
|
local dlist = self:get_children_by_id("discovered_device_list")[1]
|
||||||
|
for _, d in ipairs(dlist.children) do
|
||||||
|
if d.device.object_path == object_path then
|
||||||
|
dlist:remove_widgets(d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, d in ipairs(plist.children) do
|
||||||
|
if d.device.object_path == object_path then
|
||||||
|
plist:remove_widgets(d)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:update_device(new_device, object_path)
|
||||||
|
for _, device in ipairs(self.devices.paired:get_children()) do
|
||||||
|
if device.path == object_path then
|
||||||
|
device.device:update(new_device)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, device in ipairs(self.devices.discovered:get_children()) do
|
||||||
|
if device.path == object_path then
|
||||||
|
device.device:update(new_device)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:scan()
|
||||||
|
self._private.Adapter1:StartDiscovery()
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:stop_scan()
|
||||||
|
self._private.Adapter1:StopDiscovery()
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:toggle()
|
||||||
|
local powered = self._private.Adapter1.Powered
|
||||||
|
|
||||||
|
self._private.Adapter1:Set("org.bluez.Adapter1", "Powered", lgi.GLib.Variant("b", not powered))
|
||||||
|
self._private.Adapter1.Powered = {
|
||||||
|
signature = "b",
|
||||||
|
value = not powered
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:open_settings()
|
||||||
|
awful.spawn("blueman-manager")
|
||||||
|
end
|
||||||
|
|
||||||
|
function bluetooth:get_device_info(object_path)
|
||||||
|
if (not object_path) or (not object_path:match("/org/bluez/hci0/dev")) then return end
|
||||||
|
|
||||||
|
local Device1 = dbus_proxy.Proxy:new {
|
||||||
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
|
name = "org.bluez",
|
||||||
|
interface = "org.bluez.Device1",
|
||||||
|
path = object_path
|
||||||
}
|
}
|
||||||
|
|
||||||
function bluetooth:get_devices()
|
local Device1Properties = dbus_proxy.Proxy:new {
|
||||||
return self.devices
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
|
name = "org.bluez",
|
||||||
|
interface = "org.freedesktop.DBus.Properties",
|
||||||
|
path = object_path
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not Device1.Name) or (Device1.Name == "") then return end
|
||||||
|
|
||||||
|
local just_notified = false
|
||||||
|
|
||||||
|
local notify_timer = gtimer {
|
||||||
|
timeout = 3,
|
||||||
|
autostart = false,
|
||||||
|
single_shot = true,
|
||||||
|
callback = function()
|
||||||
|
just_notified = false
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
Device1Properties:connect_signal(function(_, _, changed_props)
|
||||||
|
if changed_props["Connected"] ~= nil then
|
||||||
|
if not just_notified then
|
||||||
|
naughty.notification({
|
||||||
|
app_icon = icondir .. "bluetooth-on.svg",
|
||||||
|
app_name = "Bluetooth",
|
||||||
|
title = Device1.Name,
|
||||||
|
icon = gcolor.recolor_image(icondir .. Device1.Icon .. ".svg", Theme_config.bluetooth_controller.icon_color),
|
||||||
|
timeout = 5,
|
||||||
|
message = "Device " ..
|
||||||
|
Device1.Name .. " is now " .. (changed_props["Connected"] and "connected" or "disconnected"),
|
||||||
|
category = Device1.Connected and "device.added" or "device.removed",
|
||||||
|
})
|
||||||
|
just_notified = true
|
||||||
|
notify_timer:start()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
capi.awesome.emit_signal(object_path .. "_updated", Device1)
|
||||||
|
end, "PropertiesChanged")
|
||||||
|
|
||||||
|
self:add_device(Device1, object_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function add_device(self, device, battery)
|
local function send_state_notification(powered)
|
||||||
--Check if the device is already in the list
|
naughty.notification {
|
||||||
for _, status in pairs(self.devices) do
|
app_icon = gcolor.recolor_image(icondir .. "bluetooth-on.svg", Theme_config.bluetooth_controller.icon_color),
|
||||||
for _, dev in ipairs(status) do
|
app_name = "Bluetooth",
|
||||||
if dev.device.Address == device.Address then
|
title = "Bluetooth",
|
||||||
return
|
message = powered and "Enabled" or "Disabled",
|
||||||
end
|
icon = gcolor.recolor_image(powered and icondir .. "bluetooth-on.svg" or icondir .. "bluetooth-off.svg",
|
||||||
end
|
Theme_config.bluetooth_controller.icon_color),
|
||||||
end
|
category = powered and "device.added" or "device.removed",
|
||||||
if device.Paired then
|
}
|
||||||
table.insert(self.devices.paired, bt_device.new { device = device, battery = battery }.widget)
|
|
||||||
else
|
|
||||||
table.insert(self.devices.discovered, bt_device.new { device = device, battery = battery }.widget)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function remove_device(self, device)
|
|
||||||
for i, dev in pairs(self.devices) do
|
|
||||||
if dev.Address == device.Address then
|
|
||||||
table.remove(self.devices, i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function bluetooth.new(args)
|
function bluetooth.new(args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
|
|
||||||
local ret = gobject { enable_properties = true, enable_auto_signals = true }
|
local ret = base.make_widget_from_value(wibox.widget {
|
||||||
gtable.crush(ret, bluetooth, true)
|
|
||||||
|
|
||||||
local bluetooth_container = wibox.widget {
|
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -198,29 +366,15 @@ function bluetooth.new(args)
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
{ -- action buttons
|
{ -- action buttons
|
||||||
{ -- turn off
|
|
||||||
{
|
{
|
||||||
{
|
dnd_widget {
|
||||||
image = gcolor.recolor_image(icondir .. "power.svg",
|
color = Theme_config.bluetooth_controller.power_bg,
|
||||||
Theme_config.bluetooth_controller.power_icon_color),
|
size = dpi(40)
|
||||||
resize = false,
|
},
|
||||||
|
id = "dnd",
|
||||||
|
widget = wibox.container.place,
|
||||||
valign = "center",
|
valign = "center",
|
||||||
halign = "center",
|
halign = "center"
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
id = "icon"
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = dpi(5),
|
|
||||||
id = "center"
|
|
||||||
},
|
|
||||||
border_width = dpi(2),
|
|
||||||
border_color = Theme_config.bluetooth_controller.border_color,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gshape.rounded_rect(cr, width, height, dpi(4))
|
|
||||||
end,
|
|
||||||
bg = Theme_config.bluetooth_controller.power_bg,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
id = "power",
|
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
{ -- refresh
|
{ -- refresh
|
||||||
@@ -236,16 +390,16 @@ function bluetooth.new(args)
|
|||||||
widget = wibox.container.margin,
|
widget = wibox.container.margin,
|
||||||
margins = dpi(5),
|
margins = dpi(5),
|
||||||
},
|
},
|
||||||
border_width = dpi(2),
|
|
||||||
border_color = Theme_config.bluetooth_controller.border_color,
|
|
||||||
shape = function(cr, width, height)
|
shape = function(cr, width, height)
|
||||||
gshape.rounded_rect(cr, width, height, dpi(4))
|
gshape.rounded_rect(cr, width, height, dpi(4))
|
||||||
end,
|
end,
|
||||||
bg = Theme_config.bluetooth_controller.refresh_bg,
|
bg = Theme_config.bluetooth_controller.refresh_bg,
|
||||||
|
id = "scan",
|
||||||
widget = wibox.container.background
|
widget = wibox.container.background
|
||||||
},
|
},
|
||||||
layout = wibox.layout.align.horizontal
|
layout = wibox.layout.align.horizontal
|
||||||
},
|
},
|
||||||
|
id = "marg_dnd",
|
||||||
widget = wibox.container.margin,
|
widget = wibox.container.margin,
|
||||||
top = dpi(10),
|
top = dpi(10),
|
||||||
},
|
},
|
||||||
@@ -266,28 +420,91 @@ function bluetooth.new(args)
|
|||||||
widget = wibox.container.background
|
widget = wibox.container.background
|
||||||
},
|
},
|
||||||
width = dpi(400),
|
width = dpi(400),
|
||||||
|
forced_width = dpi(400),
|
||||||
strategy = "exact",
|
strategy = "exact",
|
||||||
widget = wibox.container.constraint
|
widget = wibox.container.constraint
|
||||||
|
})
|
||||||
|
|
||||||
|
local dnd = ret:get_children_by_id("dnd")[1]:get_widget()
|
||||||
|
|
||||||
|
dnd:connect_signal("dnd::toggle", function(enable)
|
||||||
|
ret:toggle()
|
||||||
|
end)
|
||||||
|
|
||||||
|
gtable.crush(ret, bluetooth, true)
|
||||||
|
|
||||||
|
--#region Bluetooth Proxies
|
||||||
|
-- Create a proxy for the freedesktop ObjectManager
|
||||||
|
ret._private.ObjectManager = dbus_proxy.Proxy:new {
|
||||||
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
|
name = "org.bluez",
|
||||||
|
interface = "org.freedesktop.DBus.ObjectManager",
|
||||||
|
path = "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
-- Create a proxy for the bluez Adapter1 interface
|
||||||
"bluetooth::device_changed",
|
ret._private.Adapter1 = dbus_proxy.Proxy:new {
|
||||||
function(device, battery)
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
add_device(ret, device, battery)
|
name = "org.bluez",
|
||||||
remove_device(ret, device)
|
interface = "org.bluez.Adapter1",
|
||||||
bluetooth_container:get_children_by_id("connected_device_list")[1].children = ret:get_devices().paired
|
path = "/org/bluez/hci0"
|
||||||
bluetooth_container:get_children_by_id("discovered_device_list")[1].children = ret:get_devices().discovered
|
}
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
local connected_margin = bluetooth_container:get_children_by_id("connected_margin")[1]
|
-- Create a proxy for the bluez Adapter1 Properties interface
|
||||||
local connected_list = bluetooth_container:get_children_by_id("connected_list")[1]
|
ret._private.Adapter1Properties = dbus_proxy.Proxy:new {
|
||||||
local connected = bluetooth_container:get_children_by_id("connected")[1].center
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
|
name = "org.bluez",
|
||||||
|
interface = "org.freedesktop.DBus.Properties",
|
||||||
|
path = "/org/bluez/hci0"
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Connect to the ObjectManager's InterfacesAdded signal
|
||||||
|
ret._private.ObjectManager:connect_signal(function(_, interface)
|
||||||
|
ret:get_device_info(interface)
|
||||||
|
end, "InterfacesAdded")
|
||||||
|
|
||||||
|
-- Connect to the ObjectManager's InterfacesRemoved signal
|
||||||
|
ret._private.ObjectManager:connect_signal(function(_, interface)
|
||||||
|
ret:remove_device(interface)
|
||||||
|
end, "InterfacesRemoved")
|
||||||
|
|
||||||
|
-- Connect to the Adapter1's PropertiesChanged signal
|
||||||
|
ret._private.Adapter1Properties:connect_signal(function(_, _, data)
|
||||||
|
if data.Powered ~= nil then
|
||||||
|
send_state_notification(data.Powered)
|
||||||
|
if data.Powered then
|
||||||
|
dnd:set_enabled()
|
||||||
|
ret:scan()
|
||||||
|
else
|
||||||
|
dnd:set_disabled()
|
||||||
|
end
|
||||||
|
ret:emit_signal("bluetooth::status", data.Powered)
|
||||||
|
end
|
||||||
|
end, "PropertiesChanged")
|
||||||
|
|
||||||
|
gtimer.delayed_call(function()
|
||||||
|
for path, _ in pairs(ret._private.ObjectManager:GetManagedObjects()) do
|
||||||
|
ret:get_device_info(path)
|
||||||
|
end
|
||||||
|
if ret._private.Adapter1.Powered then
|
||||||
|
dnd:set_enabled()
|
||||||
|
ret:scan()
|
||||||
|
else
|
||||||
|
dnd:set_disabled()
|
||||||
|
end
|
||||||
|
ret:emit_signal("bluetooth::status", ret._private.Adapter1.Powered)
|
||||||
|
send_state_notification(ret._private.Adapter1.Powered)
|
||||||
|
end)
|
||||||
|
--#endregion
|
||||||
|
|
||||||
|
--#region Dropdown logic
|
||||||
|
local connected_margin = ret:get_children_by_id("connected_margin")[1]
|
||||||
|
local connected_list = ret:get_children_by_id("connected_list")[1]
|
||||||
|
local connected = ret:get_children_by_id("connected")[1].center
|
||||||
|
|
||||||
connected_margin:connect_signal(
|
connected_margin:connect_signal(
|
||||||
"button::press",
|
"button::press",
|
||||||
function()
|
function()
|
||||||
capi.awesome.emit_signal("bluetooth::scan")
|
|
||||||
local rubato_timer = rubato.timed {
|
local rubato_timer = rubato.timed {
|
||||||
duration = 0.2,
|
duration = 0.2,
|
||||||
pos = connected_list.forced_height,
|
pos = connected_list.forced_height,
|
||||||
@@ -297,7 +514,7 @@ function bluetooth.new(args)
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
if connected_list.forced_height == 0 then
|
if connected_list.forced_height == 0 then
|
||||||
local size = (#ret:get_devices().paired * 60) + 1
|
local size = (#ret:get_paired_devices() * 60) + 1
|
||||||
if size < 210 then
|
if size < 210 then
|
||||||
rubato_timer.target = dpi(size)
|
rubato_timer.target = dpi(size)
|
||||||
end
|
end
|
||||||
@@ -317,16 +534,14 @@ function bluetooth.new(args)
|
|||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|
||||||
local discovered_margin = bluetooth_container:get_children_by_id("discovered_margin")[1]
|
local discovered_margin = ret:get_children_by_id("discovered_margin")[1]
|
||||||
local discovered_list = bluetooth_container:get_children_by_id("discovered_list")[1]
|
local discovered_list = ret:get_children_by_id("discovered_list")[1]
|
||||||
local discovered_bg = bluetooth_container:get_children_by_id("discovered_bg")[1]
|
local discovered_bg = ret:get_children_by_id("discovered_bg")[1]
|
||||||
local discovered = bluetooth_container:get_children_by_id("discovered")[1].center
|
local discovered = ret:get_children_by_id("discovered")[1].center
|
||||||
|
|
||||||
discovered_margin:connect_signal(
|
discovered_margin:connect_signal(
|
||||||
"button::press",
|
"button::press",
|
||||||
function()
|
function()
|
||||||
capi.awesome.emit_signal("bluetooth::scan")
|
|
||||||
|
|
||||||
local rubato_timer = rubato.timed {
|
local rubato_timer = rubato.timed {
|
||||||
duration = 0.2,
|
duration = 0.2,
|
||||||
pos = discovered_list.forced_height,
|
pos = discovered_list.forced_height,
|
||||||
@@ -337,7 +552,7 @@ function bluetooth.new(args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if discovered_list.forced_height == 0 then
|
if discovered_list.forced_height == 0 then
|
||||||
local size = (#ret:get_devices().discovered * 60) + 1
|
local size = (#ret:get_discovered_devices() * 60) + 1
|
||||||
if size > 210 then
|
if size > 210 then
|
||||||
size = 210
|
size = 210
|
||||||
end
|
end
|
||||||
@@ -357,52 +572,17 @@ function bluetooth.new(args)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
--#endregion
|
||||||
|
|
||||||
ret.widget = awful.popup {
|
ret:get_children_by_id("scan")[1]:buttons({
|
||||||
widget = bluetooth_container,
|
awful.button({}, 1, function()
|
||||||
ontop = true,
|
ret:scan()
|
||||||
bg = Theme_config.bluetooth_controller.container_bg,
|
end)
|
||||||
stretch = false,
|
})
|
||||||
visible = false,
|
|
||||||
screen = args.screen,
|
|
||||||
placement = function(c) awful.placement.align(c,
|
|
||||||
{ position = "top_right", margins = { right = dpi(360), top = dpi(60) } })
|
|
||||||
end,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gshape.rounded_rect(cr, width, height, dpi(12))
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
awesome.connect_signal(
|
Hover_signal(ret:get_children_by_id("scan")[1])
|
||||||
"bluetooth_controller::toggle",
|
|
||||||
function()
|
|
||||||
if ret.widget.screen == capi.mouse.screen then
|
|
||||||
ret.widget.visible = not ret.widget.visible
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
|
return ret
|
||||||
ret.widget:connect_signal(
|
|
||||||
"mouse::leave",
|
|
||||||
function()
|
|
||||||
capi.mousegrabber.run(
|
|
||||||
function()
|
|
||||||
capi.awesome.emit_signal("bluetooth_controller::toggle", args.screen)
|
|
||||||
capi.mousegrabber.stop()
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
"arrow"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
ret.widget:connect_signal(
|
|
||||||
"mouse::enter",
|
|
||||||
function()
|
|
||||||
capi.mousegrabber.stop()
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function bluetooth.mt:__call(...)
|
function bluetooth.mt:__call(...)
|
||||||
|
|||||||
@@ -1,513 +0,0 @@
|
|||||||
--------------------------------------
|
|
||||||
-- This is the bluetooth controller --
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
-- Awesome Libs
|
|
||||||
local awful = require("awful")
|
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
|
||||||
local gears = require("gears")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
|
|
||||||
local rubato = require("src.lib.rubato")
|
|
||||||
|
|
||||||
local icondir = awful.util.getdir("config") .. "src/assets/icons/bluetooth/"
|
|
||||||
|
|
||||||
return function(s)
|
|
||||||
|
|
||||||
local function create_device(device, battery)
|
|
||||||
local icon = device.Icon or "bluetooth-on"
|
|
||||||
local device_widget = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
image = gears.color.recolor_image(
|
|
||||||
icondir .. icon .. ".svg", Theme_config.bluetooth_controller.icon_color),
|
|
||||||
id = "icon",
|
|
||||||
resize = false,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
forced_width = dpi(24),
|
|
||||||
forced_height = dpi(24),
|
|
||||||
widget = wibox.widget.imagebox
|
|
||||||
},
|
|
||||||
id = "icon_container",
|
|
||||||
strategy = "max",
|
|
||||||
width = dpi(24),
|
|
||||||
height = dpi(24),
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
text = device.Alias or device.Name,
|
|
||||||
id = "alias",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text = "Connecting...",
|
|
||||||
id = "connecting",
|
|
||||||
visible = false,
|
|
||||||
font = User_config.font.specify .. ", regular 10",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
},
|
|
||||||
id = "alias_container",
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
width = dpi(260),
|
|
||||||
height = dpi(40),
|
|
||||||
strategy = "max",
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
},
|
|
||||||
spacing = dpi(10),
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
{ -- Spacing
|
|
||||||
forced_width = dpi(10),
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
id = "con",
|
|
||||||
resize = false,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
forced_width = dpi(24),
|
|
||||||
forced_height = dpi(24),
|
|
||||||
widget = wibox.widget.imagebox
|
|
||||||
},
|
|
||||||
id = "place",
|
|
||||||
strategy = "max",
|
|
||||||
width = dpi(24),
|
|
||||||
height = dpi(24),
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
},
|
|
||||||
id = "margin",
|
|
||||||
margins = dpi(2),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "backgr",
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
|
||||||
end,
|
|
||||||
bg = Theme_config.bluetooth_controller.con_button_color,
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
id = "margin0",
|
|
||||||
margin = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "device_layout",
|
|
||||||
layout = wibox.layout.align.horizontal
|
|
||||||
},
|
|
||||||
id = "device_margin",
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
bg = Theme_config.bluetooth_controller.device_bg,
|
|
||||||
fg = Theme_config.bluetooth_controller.device_fg,
|
|
||||||
border_color = Theme_config.bluetooth_controller.device_border_color,
|
|
||||||
border_width = Theme_config.bluetooth_controller.device_border_width,
|
|
||||||
id = "background",
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
|
||||||
end,
|
|
||||||
widget = wibox.container.background
|
|
||||||
}
|
|
||||||
|
|
||||||
--! using :Connect freezes awesome, either find a solution or switch to console commands
|
|
||||||
if device.Connected then
|
|
||||||
device_widget:get_children_by_id("con")[1].image = gears.color.recolor_image(icondir .. "link-off.svg",
|
|
||||||
Theme_config.bluetooth_controller.icon_color_dark)
|
|
||||||
device_widget:connect_signal(
|
|
||||||
"button::press",
|
|
||||||
function(_, _, _, key)
|
|
||||||
if key == 1 then
|
|
||||||
device:Disconnect()
|
|
||||||
awesome.emit_signal("bluetooth::connect", device)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
else
|
|
||||||
device_widget:get_children_by_id("con")[1].image = gears.color.recolor_image(icondir .. "link.svg",
|
|
||||||
Theme_config.bluetooth_controller.icon_color_dark)
|
|
||||||
device_widget:connect_signal(
|
|
||||||
"button::press",
|
|
||||||
function(_, _, _, key)
|
|
||||||
if key == 1 then
|
|
||||||
device:Connect()
|
|
||||||
awesome.emit_signal("bluetooth::disconnect", device)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
Hover_signal(device_widget)
|
|
||||||
return device_widget
|
|
||||||
end
|
|
||||||
|
|
||||||
local connected_devices_list = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
step = dpi(50),
|
|
||||||
spacing = dpi(10),
|
|
||||||
layout = require("src.lib.overflow_widget.overflow").vertical,
|
|
||||||
scrollbar_width = 0,
|
|
||||||
id = "connected_device_list"
|
|
||||||
},
|
|
||||||
id = "margin",
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "place",
|
|
||||||
height = dpi(200),
|
|
||||||
strategy = "max",
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
},
|
|
||||||
id = "connected_device_background",
|
|
||||||
border_color = Theme_config.bluetooth_controller.con_device_border_color,
|
|
||||||
border_width = Theme_config.bluetooth_controller.con_device_border_width,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.partially_rounded_rect(cr, width, height, false, false, true, true, dpi(4))
|
|
||||||
end,
|
|
||||||
widget = wibox.container.background
|
|
||||||
}
|
|
||||||
|
|
||||||
local discovered_devices_list = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
spacing = dpi(10),
|
|
||||||
step = dpi(50),
|
|
||||||
layout = require("src.lib.overflow_widget.overflow").vertical,
|
|
||||||
scrollbar_width = 0,
|
|
||||||
id = "discovered_device_list"
|
|
||||||
},
|
|
||||||
id = "margin",
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "place",
|
|
||||||
height = dpi(200),
|
|
||||||
strategy = "max",
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
},
|
|
||||||
id = "discovered_device_background",
|
|
||||||
border_color = Theme_config.bluetooth_controller.con_device_border_color,
|
|
||||||
border_width = Theme_config.bluetooth_controller.con_device_border_width,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.partially_rounded_rect(cr, width, height, false, false, true, true, dpi(4))
|
|
||||||
end,
|
|
||||||
widget = wibox.container.background
|
|
||||||
}
|
|
||||||
|
|
||||||
local bluetooth_container = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
resize = false,
|
|
||||||
image = gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
||||||
Theme_config.bluetooth_controller.connected_icon_color),
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
id = "icon"
|
|
||||||
},
|
|
||||||
id = "center",
|
|
||||||
halign = "center",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.container.place,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
text = "Paired Devices",
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
id = "device_name"
|
|
||||||
},
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "connected",
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
id = "connected_bg",
|
|
||||||
bg = Theme_config.bluetooth_controller.connected_bg,
|
|
||||||
fg = Theme_config.bluetooth_controller.connected_fg,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
|
||||||
end,
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
id = "connected_margin",
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id = "connected_list",
|
|
||||||
widget = connected_devices_list,
|
|
||||||
forced_height = 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
resize = false,
|
|
||||||
image = gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
||||||
Theme_config.bluetooth_controller.discovered_icon_color),
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
id = "icon",
|
|
||||||
},
|
|
||||||
id = "center",
|
|
||||||
halign = "center",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.container.place,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
text = "Nearby Devices",
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
id = "device_name"
|
|
||||||
},
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "discovered",
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
id = "discovered_bg",
|
|
||||||
bg = Theme_config.bluetooth_controller.discovered_bg,
|
|
||||||
fg = Theme_config.bluetooth_controller.discovered_fg,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
|
||||||
end,
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
id = "discovered_margin",
|
|
||||||
top = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id = "discovered_list",
|
|
||||||
widget = discovered_devices_list,
|
|
||||||
forced_height = 0
|
|
||||||
},
|
|
||||||
id = "layout1",
|
|
||||||
layout = wibox.layout.fixed.vertical
|
|
||||||
},
|
|
||||||
id = "margin",
|
|
||||||
margins = dpi(15),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(8))
|
|
||||||
end,
|
|
||||||
border_color = Theme_config.bluetooth_controller.container_border_color,
|
|
||||||
border_width = Theme_config.bluetooth_controller.container_border_width,
|
|
||||||
bg = Theme_config.bluetooth_controller.container_bg,
|
|
||||||
id = "background",
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
width = dpi(400),
|
|
||||||
strategy = "exact",
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Main container
|
|
||||||
local bluetooth_controller_container = awful.popup {
|
|
||||||
widget = wibox.container.background,
|
|
||||||
ontop = true,
|
|
||||||
bg = Theme_config.bluetooth_controller.container_bg,
|
|
||||||
stretch = false,
|
|
||||||
visible = false,
|
|
||||||
screen = s,
|
|
||||||
placement = function(c) awful.placement.align(c,
|
|
||||||
{ position = "top_right", margins = { right = dpi(380), top = dpi(60) } })
|
|
||||||
end,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(12))
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
local connected_devices, nearby_devices = {}, {}
|
|
||||||
|
|
||||||
-- function to check if a device is already in the list
|
|
||||||
local function is_device_in_list(device)
|
|
||||||
for i = 1, #connected_devices do
|
|
||||||
if connected_devices[i].Address == device.Address then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
awesome.connect_signal(
|
|
||||||
"bluetooth::device_changed",
|
|
||||||
function(device, battery)
|
|
||||||
if not is_device_in_list(device) then
|
|
||||||
-- add device and battery to list
|
|
||||||
if device.Paired then
|
|
||||||
table.insert(connected_devices, device)
|
|
||||||
else
|
|
||||||
table.insert(nearby_devices, device)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (#connected_devices + #nearby_devices) > 0 then
|
|
||||||
local cd_list, dd_list = {}, {}
|
|
||||||
for _, d in pairs(connected_devices) do
|
|
||||||
if d.Paired then
|
|
||||||
table.insert(cd_list, create_device(d))
|
|
||||||
else
|
|
||||||
table.insert(dd_list, create_device(d))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for _, d in pairs(nearby_devices) do
|
|
||||||
if d.Paired then
|
|
||||||
table.insert(cd_list, create_device(d, battery))
|
|
||||||
else
|
|
||||||
table.insert(dd_list, create_device(d, battery))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
connected_devices_list:get_children_by_id("connected_device_list")[1].children = cd_list
|
|
||||||
discovered_devices_list:get_children_by_id("discovered_device_list")[1].children = dd_list
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Variables for easier access and better readability
|
|
||||||
local connected_margin = bluetooth_container:get_children_by_id("connected_margin")[1]
|
|
||||||
local connected_list = bluetooth_container:get_children_by_id("connected_list")[1]
|
|
||||||
local connected_bg = bluetooth_container:get_children_by_id("connected_bg")[1]
|
|
||||||
local connected = bluetooth_container:get_children_by_id("connected")[1].center
|
|
||||||
|
|
||||||
-- Click event for the microphone dropdown
|
|
||||||
connected_margin:connect_signal(
|
|
||||||
"button::press",
|
|
||||||
function()
|
|
||||||
local rubato_timer = rubato.timed {
|
|
||||||
duration = 0.4,
|
|
||||||
intro = 0.1,
|
|
||||||
outro = 0.1,
|
|
||||||
pos = connected_list.forced_height,
|
|
||||||
easing = rubato.linear,
|
|
||||||
subscribed = function(v)
|
|
||||||
connected_list.forced_height = v
|
|
||||||
end
|
|
||||||
}
|
|
||||||
if connected_list.forced_height == 0 then
|
|
||||||
local size = (#connected_devices * 45) + ((#connected_devices - 1) * 10)
|
|
||||||
if size < 210 then
|
|
||||||
rubato_timer.target = dpi(size)
|
|
||||||
else
|
|
||||||
rubato_timer.target = dpi(210)
|
|
||||||
end
|
|
||||||
connected_margin.connected_bg.shape = function(cr, width, height)
|
|
||||||
gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
|
|
||||||
end
|
|
||||||
connected.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg",
|
|
||||||
Theme_config.bluetooth_controller.connected_icon_color))
|
|
||||||
else
|
|
||||||
rubato_timer.target = 0
|
|
||||||
connected_bg.shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, 4)
|
|
||||||
end
|
|
||||||
connected.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
||||||
Theme_config.bluetooth_controller.connected_icon_color))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Variables for easier access and better readability
|
|
||||||
local discovered_margin = bluetooth_container:get_children_by_id("discovered_margin")[1]
|
|
||||||
local discovered_list = bluetooth_container:get_children_by_id("discovered_list")[1]
|
|
||||||
local discovered_bg = bluetooth_container:get_children_by_id("discovered_bg")[1]
|
|
||||||
local discovered = bluetooth_container:get_children_by_id("discovered")[1].center
|
|
||||||
|
|
||||||
-- Click event for the microphone dropdown
|
|
||||||
discovered_margin:connect_signal(
|
|
||||||
"button::press",
|
|
||||||
function()
|
|
||||||
local rubato_timer = rubato.timed {
|
|
||||||
duration = 0.4,
|
|
||||||
intro = 0.1,
|
|
||||||
outro = 0.1,
|
|
||||||
pos = discovered_list.forced_height,
|
|
||||||
easing = rubato.linear,
|
|
||||||
subscribed = function(v)
|
|
||||||
discovered_list.forced_height = v
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
if discovered_list.forced_height == 0 then
|
|
||||||
local size = (#nearby_devices * dpi(45)) + ((#nearby_devices - 1) * dpi(10))
|
|
||||||
if size < 210 then
|
|
||||||
rubato_timer.target = dpi(size)
|
|
||||||
else
|
|
||||||
rubato_timer.target = dpi(20)
|
|
||||||
end
|
|
||||||
discovered_margin.discovered_bg.shape = function(cr, width, height)
|
|
||||||
gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
|
|
||||||
end
|
|
||||||
discovered.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg",
|
|
||||||
Theme_config.bluetooth_controller.discovered_icon_color))
|
|
||||||
else
|
|
||||||
rubato_timer.target = 0
|
|
||||||
discovered_bg.shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, 4)
|
|
||||||
end
|
|
||||||
discovered.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
||||||
Theme_config.bluetooth_controller.discovered_icon_color))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- When the mouse leaves the popup it stops the mousegrabber and hides the popup.
|
|
||||||
bluetooth_controller_container:connect_signal(
|
|
||||||
"mouse::leave",
|
|
||||||
function()
|
|
||||||
mousegrabber.run(
|
|
||||||
function()
|
|
||||||
awesome.emit_signal("bluetooth_controller::toggle", s)
|
|
||||||
mousegrabber.stop()
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
"arrow"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
bluetooth_controller_container:connect_signal(
|
|
||||||
"mouse::enter",
|
|
||||||
function()
|
|
||||||
mousegrabber.stop()
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Draw the popup
|
|
||||||
bluetooth_controller_container:setup {
|
|
||||||
bluetooth_container,
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Toggle container visibility
|
|
||||||
awesome.connect_signal(
|
|
||||||
"bluetooth_controller::toggle",
|
|
||||||
function(scr)
|
|
||||||
if scr == s then
|
|
||||||
bluetooth_controller_container.visible = not bluetooth_controller_container.visible
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
---------------------------------------
|
|
||||||
-- This is the brightness_osd module --
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
-- Awesome Libs
|
|
||||||
local awful = require("awful")
|
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
|
||||||
local gears = require("gears")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
awesome = awesome,
|
|
||||||
mouse = mouse,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Icon directory path
|
|
||||||
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/brightness/"
|
|
||||||
|
|
||||||
return function(s)
|
|
||||||
|
|
||||||
local brightness_osd_widget = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{ -- Brightness Icon
|
|
||||||
image = gears.color.recolor_image(icondir .. "brightness-high.svg", Theme_config.brightness_osd.icon_color),
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
resize = false,
|
|
||||||
id = "icon",
|
|
||||||
widget = wibox.widget.imagebox
|
|
||||||
},
|
|
||||||
{ -- Brightness Bar
|
|
||||||
{
|
|
||||||
{
|
|
||||||
id = "progressbar1",
|
|
||||||
color = Theme_config.brightness_osd.bar_bg_active,
|
|
||||||
background_color = Theme_config.brightness_osd.bar_bg,
|
|
||||||
max_value = 100,
|
|
||||||
value = 0,
|
|
||||||
forced_height = dpi(6),
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_bar(cr, width, height, dpi(6))
|
|
||||||
end,
|
|
||||||
widget = wibox.widget.progressbar
|
|
||||||
},
|
|
||||||
id = "progressbar_container2",
|
|
||||||
halign = "center",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.container.place
|
|
||||||
},
|
|
||||||
id = "progressbar_container",
|
|
||||||
width = dpi(240),
|
|
||||||
heigth = dpi(20),
|
|
||||||
stragety = "max",
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
},
|
|
||||||
id = "layout1",
|
|
||||||
spacing = dpi(10),
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
id = "margin",
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
forced_width = dpi(300),
|
|
||||||
forced_height = dpi(80),
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(12))
|
|
||||||
end,
|
|
||||||
border_color = Theme_config.brightness_osd.border_color,
|
|
||||||
border_width = Theme_config.brightness_osd.border_width,
|
|
||||||
fg = Theme_config.brightness_osd.fg,
|
|
||||||
bg = Theme_config.brightness_osd.bg,
|
|
||||||
widget = wibox.container.background
|
|
||||||
}
|
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"brightness::get",
|
|
||||||
function(brightness)
|
|
||||||
print(brightness)
|
|
||||||
brightness_osd_widget:get_children_by_id("progressbar1")[1].value = brightness
|
|
||||||
|
|
||||||
local icon = icondir .. "brightness"
|
|
||||||
if brightness >= 0 and brightness < 34 then
|
|
||||||
icon = icon .. "-low"
|
|
||||||
elseif brightness >= 34 and brightness < 67 then
|
|
||||||
icon = icon .. "-medium"
|
|
||||||
elseif brightness >= 67 then
|
|
||||||
icon = icon .. "-high"
|
|
||||||
end
|
|
||||||
brightness_osd_widget:get_children_by_id("icon")[1]:set_image(gears.color.recolor_image(icon .. ".svg",
|
|
||||||
Theme_config.brightness_osd.icon_color))
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
local brightness_container = awful.popup {
|
|
||||||
widget = {},
|
|
||||||
ontop = true,
|
|
||||||
stretch = false,
|
|
||||||
visible = false,
|
|
||||||
screen = s,
|
|
||||||
placement = function(c) awful.placement.bottom_left(c, { margins = dpi(20) }) end,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(14))
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
local hide_brightness_osd = gears.timer {
|
|
||||||
timeout = 2,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
brightness_container.visible = false
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
brightness_container:setup {
|
|
||||||
brightness_osd_widget,
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
}
|
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"brightness::rerun",
|
|
||||||
function()
|
|
||||||
if capi.mouse.screen == s then
|
|
||||||
brightness_container.visible = true
|
|
||||||
if hide_brightness_osd.started then
|
|
||||||
hide_brightness_osd:again()
|
|
||||||
else
|
|
||||||
hide_brightness_osd:start()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
---------------------------------------
|
|
||||||
-- This is the brightness_osd module --
|
|
||||||
---------------------------------------
|
|
||||||
|
|
||||||
-- Awesome Libs
|
|
||||||
local awful = require("awful")
|
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
|
||||||
local gears = require("gears")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
awesome = awesome,
|
|
||||||
mouse = mouse,
|
|
||||||
}
|
|
||||||
|
|
||||||
return function(args)
|
|
||||||
if not args then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_entries()
|
|
||||||
|
|
||||||
local menu_entries = { layout = wibox.layout.fixed.vertical, spacing = dpi(10) }
|
|
||||||
|
|
||||||
if args.entries then
|
|
||||||
for _, entry in ipairs(args.entries) do
|
|
||||||
local menu_entry = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{ -- Icon
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
image = gears.color.recolor_image(entry.icon, Theme_config.context_menu.entry.icon_color),
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
resize = true,
|
|
||||||
icon = entry.icon,
|
|
||||||
id = "icon"
|
|
||||||
},
|
|
||||||
widget = wibox.container.constraint,
|
|
||||||
stragety = "exact",
|
|
||||||
width = dpi(24),
|
|
||||||
height = dpi(24),
|
|
||||||
id = "const"
|
|
||||||
},
|
|
||||||
{ -- Text
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
text = entry.name,
|
|
||||||
id = "name"
|
|
||||||
},
|
|
||||||
id = "lay",
|
|
||||||
spacing = dpi(5),
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
id = "mar"
|
|
||||||
},
|
|
||||||
bg = Theme_config.context_menu.entry.bg,
|
|
||||||
fg = Theme_config.context_menu.entry.fg,
|
|
||||||
shape = Theme_config.context_menu.entry.shape,
|
|
||||||
border_width = Theme_config.context_menu.entry.border_width,
|
|
||||||
border_color = Theme_config.context_menu.entry.border_color,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
id = "menu_entry"
|
|
||||||
}
|
|
||||||
|
|
||||||
menu_entry:buttons(gears.table.join(
|
|
||||||
awful.button({
|
|
||||||
modifiers = {},
|
|
||||||
button = 1,
|
|
||||||
on_release = function()
|
|
||||||
capi.awesome.emit_signal("context_menu::hide")
|
|
||||||
entry.callback()
|
|
||||||
end
|
|
||||||
})
|
|
||||||
))
|
|
||||||
|
|
||||||
Hover_signal(menu_entry, nil, Theme_config.context_menu.entry.hover_fg,
|
|
||||||
Theme_config.context_menu.entry.hover_border, Theme_config.context_menu.entry.icon_color,
|
|
||||||
Theme_config.context_menu.entry.icon_color_hover)
|
|
||||||
table.insert(menu_entries, menu_entry)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return menu_entries
|
|
||||||
end
|
|
||||||
|
|
||||||
local menu = awful.popup {
|
|
||||||
widget = {
|
|
||||||
get_entries(),
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
bg = Theme_config.context_menu.bg,
|
|
||||||
fg = Theme_config.context_menu.fg,
|
|
||||||
border_width = Theme_config.context_menu.border_width,
|
|
||||||
border_color = Theme_config.context_menu.border_color,
|
|
||||||
shape = Theme_config.context_menu.shape,
|
|
||||||
x = capi.mouse.coords().x,
|
|
||||||
y = capi.mouse.coords().y,
|
|
||||||
visible = false,
|
|
||||||
ontop = true,
|
|
||||||
placement = awful.placement.no_offscreen,
|
|
||||||
}
|
|
||||||
|
|
||||||
menu:connect_signal("mouse::leave", function()
|
|
||||||
capi.awesome.emit_signal("context_menu::hide")
|
|
||||||
end)
|
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"context_menu::hide",
|
|
||||||
function()
|
|
||||||
menu.visible = false
|
|
||||||
end
|
|
||||||
)
|
|
||||||
return menu
|
|
||||||
end
|
|
||||||
@@ -52,7 +52,7 @@ function context_menu:make_entries(wtemplate, entries, spacing)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, entry in ipairs(entries) do
|
for key, entry in pairs(entries) do
|
||||||
-- TODO: Figure out how to make a new widget from etemplate
|
-- TODO: Figure out how to make a new widget from etemplate
|
||||||
local menu_entry = wibox.widget {
|
local menu_entry = wibox.widget {
|
||||||
{
|
{
|
||||||
@@ -124,7 +124,8 @@ function context_menu:make_entries(wtemplate, entries, spacing)
|
|||||||
if not entry.submenu then
|
if not entry.submenu then
|
||||||
entry.callback()
|
entry.callback()
|
||||||
end
|
end
|
||||||
self.visible = false
|
capi.awesome.emit_signal("submenu::close")
|
||||||
|
capi.awesome.emit_signal("cm::hide")
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -169,10 +170,8 @@ function context_menu:make_entries(wtemplate, entries, spacing)
|
|||||||
menu_entry.popup.visible = false
|
menu_entry.popup.visible = false
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
menu_entries[key] = menu_entry
|
||||||
table.insert(menu_entries, menu_entry)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return menu_entries
|
return menu_entries
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -182,6 +181,8 @@ function context_menu:toggle()
|
|||||||
self.visible = not self.visible
|
self.visible = not self.visible
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- This is terribly done but I don't know how to do it better since
|
||||||
|
-- the awful.popup.widget needs to know itself which I don't think is possible
|
||||||
function context_menu.new(args)
|
function context_menu.new(args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
|
|
||||||
@@ -202,6 +203,11 @@ function context_menu.new(args)
|
|||||||
y = capi.mouse.coords().y - 10
|
y = capi.mouse.coords().y - 10
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- I literally have no clue how to do it better, it doesn't really matter anyways
|
||||||
|
capi.awesome.connect_signal("cm::hide", function()
|
||||||
|
ret.visible = false
|
||||||
|
end)
|
||||||
|
|
||||||
gtable.crush(ret, context_menu, true)
|
gtable.crush(ret, context_menu, true)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|||||||
@@ -62,10 +62,7 @@ return function(s, widgets)
|
|||||||
bg = Theme_config.center_bar.bg,
|
bg = Theme_config.center_bar.bg,
|
||||||
visible = true,
|
visible = true,
|
||||||
maximum_width = dpi(500),
|
maximum_width = dpi(500),
|
||||||
placement = function(c) awful.placement.top(c, { margins = dpi(10) }) end,
|
placement = function(c) awful.placement.top(c, { margins = dpi(10) }) end
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
top_center:struts {
|
top_center:struts {
|
||||||
|
|||||||
@@ -257,10 +257,7 @@ return function(screen)
|
|||||||
screen = screen,
|
screen = screen,
|
||||||
type = "dock",
|
type = "dock",
|
||||||
height = dpi(User_config.dock_icon_size + 10),
|
height = dpi(User_config.dock_icon_size + 10),
|
||||||
placement = function(c) awful.placement.bottom(c, { margins = dpi(10) }) end,
|
placement = function(c) awful.placement.bottom(c, { margins = dpi(10) }) end
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(16))
|
|
||||||
end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- A fakedock to send a signal when the mouse is over it
|
--- A fakedock to send a signal when the mouse is over it
|
||||||
|
|||||||
@@ -57,10 +57,7 @@ return function(s, w)
|
|||||||
bg = Theme_config.left_bar.bg,
|
bg = Theme_config.left_bar.bg,
|
||||||
visible = true,
|
visible = true,
|
||||||
maximum_width = dpi(650),
|
maximum_width = dpi(650),
|
||||||
placement = function(c) awful.placement.top_left(c, { margins = dpi(10) }) end,
|
placement = function(c) awful.placement.top_left(c, { margins = dpi(10) }) end
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
top_left:struts {
|
top_left:struts {
|
||||||
|
|||||||
@@ -56,10 +56,7 @@ return function(s, w)
|
|||||||
bg = Theme_config.right_bar.bg,
|
bg = Theme_config.right_bar.bg,
|
||||||
visible = true,
|
visible = true,
|
||||||
screen = s,
|
screen = s,
|
||||||
placement = function(c) awful.placement.top_right(c, { margins = dpi(10) }) end,
|
placement = function(c) awful.placement.top_right(c, { margins = dpi(10) }) end
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end
|
|
||||||
}
|
}
|
||||||
|
|
||||||
top_right:struts {
|
top_right:struts {
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ function context_menu.new(args)
|
|||||||
local ret = gobject {}
|
local ret = gobject {}
|
||||||
gtable.crush(ret, context_menu, true)
|
gtable.crush(ret, context_menu, true)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
capi.awesome.connect_signal("context_menu:show", function()
|
capi.awesome.connect_signal("context_menu:show", function()
|
||||||
ret:toggle()
|
ret:toggle()
|
||||||
mousegrabber.run(function()
|
mousegrabber.run(function()
|
||||||
@@ -44,7 +42,7 @@ function context_menu.new(args)
|
|||||||
end, nil)
|
end, nil)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
return w
|
return ret
|
||||||
end
|
end
|
||||||
|
|
||||||
function context_menu.mt:__call(...)
|
function context_menu.mt:__call(...)
|
||||||
|
|||||||
@@ -17,13 +17,11 @@ awful.screen.connect_for_each_screen(
|
|||||||
User_config.layouts[1]
|
User_config.layouts[1]
|
||||||
)
|
)
|
||||||
|
|
||||||
require("src.modules.desktop.context_menu") { screen = s }
|
|
||||||
require("src.modules.desktop.desktop") { screen = s }
|
require("src.modules.desktop.desktop") { screen = s }
|
||||||
require("src.modules.powermenu.powermenu")(s)
|
require("src.modules.powermenu.powermenu")(s)
|
||||||
require("src.modules.audio.volume_osd") { screen = s }
|
require("src.modules.audio.volume_osd") { screen = s }
|
||||||
--require("src.modules.audio.volume_controller") { screen = s }
|
--require("src.modules.audio.volume_controller") { screen = s }
|
||||||
require("src.modules.brightness.brightness_osd")(s)
|
require("src.modules.brightness.brightness_osd")(s)
|
||||||
require("src.modules.bluetooth.init") { screen = s }
|
|
||||||
require("src.modules.titlebar.titlebar")
|
require("src.modules.titlebar.titlebar")
|
||||||
require("src.modules.crylia_bar.init")(s)
|
require("src.modules.crylia_bar.init")(s)
|
||||||
--require("src.modules.crylia_wibox.init")(s)
|
--require("src.modules.crylia_wibox.init")(s)
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ local gfilesystem = require("gears").filesystem
|
|||||||
local gobject = require("gears").object
|
local gobject = require("gears").object
|
||||||
local gcolor = require("gears").color
|
local gcolor = require("gears").color
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
local base = require("wibox.widget.base")
|
||||||
|
local NM = require("lgi").NM
|
||||||
|
|
||||||
local ap_form = require("src.modules.network_controller.ap_form")
|
local ap_form = require("src.modules.network_controller.ap_form")
|
||||||
|
|
||||||
@@ -17,39 +19,28 @@ local icondir = gfilesystem.get_configuration_dir() .. "src/assets/icons/network
|
|||||||
|
|
||||||
local access_point = { mt = {} }
|
local access_point = { mt = {} }
|
||||||
|
|
||||||
access_point.connected = false
|
|
||||||
|
|
||||||
function access_point.new(args)
|
function access_point.new(args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
|
|
||||||
if not args.access_point then return end
|
if not args.NetworkManagerAccessPoint then return end
|
||||||
|
|
||||||
local ret = gobject { enable_properties = true, enable_auto_signals = true }
|
|
||||||
gtable.crush(ret, access_point, true)
|
|
||||||
|
|
||||||
local strength = args.access_point.strength or 0
|
|
||||||
|
|
||||||
--normalize strength between 1 and 4
|
|
||||||
strength = math.floor(strength / 25) + 1
|
|
||||||
|
|
||||||
local icon = "wifi-strength-" .. strength .. ".svg"
|
|
||||||
|
|
||||||
local bg, fg, icon_color = Theme_config.network_manager.access_point.bg, Theme_config.network_manager.access_point.fg,
|
local bg, fg, icon_color = Theme_config.network_manager.access_point.bg, Theme_config.network_manager.access_point.fg,
|
||||||
Theme_config.network_manager.access_point.icon_color
|
Theme_config.network_manager.access_point.icon_color
|
||||||
|
|
||||||
if args.active == args.access_point.access_point_path then
|
--[[ if get_active_access_point() == args.NetworkManagerAccessPoint.access_point_path then
|
||||||
bg, fg, icon_color = Theme_config.network_manager.access_point.fg, Theme_config.network_manager.access_point.bg,
|
bg, fg, icon_color = Theme_config.network_manager.access_point.fg, Theme_config.network_manager.access_point.bg,
|
||||||
Theme_config.network_manager.access_point.icon_color2
|
Theme_config.network_manager.access_point.icon_color2
|
||||||
end
|
end ]]
|
||||||
|
|
||||||
local ap_widget = wibox.widget {
|
local ret = base.make_widget_from_value(wibox.widget {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
image = gcolor.recolor_image(
|
image = gcolor.recolor_image(
|
||||||
icondir .. icon, icon_color),
|
icondir .. "wifi-strength-" .. math.floor(args.NetworkManagerAccessPoint.Strength / 25) + 1 .. ".svg",
|
||||||
|
icon_color),
|
||||||
id = "icon",
|
id = "icon",
|
||||||
resize = true,
|
resize = true,
|
||||||
valign = "center",
|
valign = "center",
|
||||||
@@ -67,7 +58,8 @@ function access_point.new(args)
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
text = args.access_point.ssid or args.access_point.hw_address or "Unknown",
|
text = NM.utils_ssid_to_utf8(args.NetworkManagerAccessPoint.Ssid) or
|
||||||
|
args.NetworkManagerAccessPoint.hw_address or "Unknown",
|
||||||
id = "alias",
|
id = "alias",
|
||||||
widget = wibox.widget.textbox
|
widget = wibox.widget.textbox
|
||||||
},
|
},
|
||||||
@@ -132,31 +124,32 @@ function access_point.new(args)
|
|||||||
border_width = Theme_config.network_manager.access_point.border_width,
|
border_width = Theme_config.network_manager.access_point.border_width,
|
||||||
id = "background",
|
id = "background",
|
||||||
shape = Theme_config.network_manager.access_point.device_shape,
|
shape = Theme_config.network_manager.access_point.device_shape,
|
||||||
device = ret.access_point,
|
|
||||||
widget = wibox.container.background
|
widget = wibox.container.background
|
||||||
}
|
})
|
||||||
|
|
||||||
ap_form { screen = args.screen, SSID = args.access_point.ssid }
|
gtable.crush(ret, access_point, true)
|
||||||
|
|
||||||
ap_widget:buttons(
|
ret.NetworkManagerAccessPoint = args.NetworkManagerAccessPoint
|
||||||
|
|
||||||
|
ret.ap_form = ap_form { screen = args.screen, ssid = NM.utils_ssid_to_utf8(ret.NetworkManagerAccessPoint.Ssid) }
|
||||||
|
|
||||||
|
ret:buttons(
|
||||||
gtable.join(
|
gtable.join(
|
||||||
awful.button(
|
awful.button(
|
||||||
{},
|
{},
|
||||||
1,
|
1,
|
||||||
nil,
|
nil,
|
||||||
function()
|
function()
|
||||||
ap_form:popup_toggle()
|
ret.ap_form:popup_toggle()
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
ap_widget:get_children_by_id("con")[1].image = gcolor.recolor_image(
|
ret:get_children_by_id("con")[1].image = gcolor.recolor_image(
|
||||||
icondir .. "link.svg", icon_color)
|
icondir .. "link.svg", icon_color)
|
||||||
|
|
||||||
Hover_signal(ap_widget)
|
Hover_signal(ret)
|
||||||
|
|
||||||
ret.widget = ap_widget
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,44 +15,16 @@ local capi = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
local ap_form = { mt = {} }
|
local ap_form = { mt = {} }
|
||||||
ap_form._private = {}
|
|
||||||
|
|
||||||
ap_form.settigns_form = {
|
function ap_form:popup_toggle()
|
||||||
ssid = awful.widget.inputbox {
|
self.visible = not self.visible
|
||||||
widget_template = wibox.template {
|
|
||||||
widget = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
halign = "left",
|
|
||||||
valign = "center",
|
|
||||||
id = "text_role",
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = 5,
|
|
||||||
id = "marg"
|
|
||||||
},
|
|
||||||
widget = wibox.container.constraint,
|
|
||||||
strategy = "exact",
|
|
||||||
width = 400,
|
|
||||||
height = 50,
|
|
||||||
id = "const"
|
|
||||||
},
|
|
||||||
widget = wibox.container.background,
|
|
||||||
bg = "#212121",
|
|
||||||
fg = "#F0F0F0",
|
|
||||||
border_color = "#414141",
|
|
||||||
border_width = 2,
|
|
||||||
shape = gshape.rounded_rect,
|
|
||||||
forced_width = 300,
|
|
||||||
forced_height = 50,
|
|
||||||
},
|
|
||||||
update_callback = function(template_widget, args)
|
|
||||||
template_widget.widget.const.marg.text_role.markup = args.text
|
|
||||||
end
|
end
|
||||||
}
|
|
||||||
},
|
function ap_form.new(args)
|
||||||
|
args = args or {}
|
||||||
|
args.screen = args.screen or awful.screen.preferred()
|
||||||
|
|
||||||
|
local settigns_form = {
|
||||||
password = awful.widget.inputbox {
|
password = awful.widget.inputbox {
|
||||||
widget_template = wibox.template {
|
widget_template = wibox.template {
|
||||||
widget = wibox.widget {
|
widget = wibox.widget {
|
||||||
@@ -90,28 +62,17 @@ ap_form.settigns_form = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function ap_form:popup_toggle()
|
local ret = awful.popup {
|
||||||
self._private.popup.visible = not self._private.popup.visible
|
|
||||||
end
|
|
||||||
|
|
||||||
function ap_form.new(args)
|
|
||||||
args = args or {}
|
|
||||||
args.screen = args.screen or awful.screen.preferred()
|
|
||||||
local ret = gobject {}
|
|
||||||
ret._private = {}
|
|
||||||
gtable.crush(ret, ap_form, true)
|
|
||||||
|
|
||||||
gtable.crush(ret, args)
|
|
||||||
|
|
||||||
ret._private.popup = awful.popup {
|
|
||||||
widget = {
|
widget = {
|
||||||
|
{
|
||||||
{ -- Header
|
{ -- Header
|
||||||
{
|
{
|
||||||
nil,
|
nil,
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
widget = wibox.widget.textbox,
|
widget = wibox.widget.textbox,
|
||||||
text = args.SSID,
|
text = args.ssid,
|
||||||
|
font = User_config.font.specify .. ",extra bold 16",
|
||||||
halign = "center",
|
halign = "center",
|
||||||
valign = "center",
|
valign = "center",
|
||||||
},
|
},
|
||||||
@@ -128,8 +89,10 @@ function ap_form.new(args)
|
|||||||
halign = "center",
|
halign = "center",
|
||||||
},
|
},
|
||||||
widget = wibox.container.margin,
|
widget = wibox.container.margin,
|
||||||
|
margins = dpi(5),
|
||||||
},
|
},
|
||||||
widget = wibox.container.background,
|
widget = wibox.container.background,
|
||||||
|
shape = Theme_config.network_manager.form.close_icon_shape,
|
||||||
id = "close_button",
|
id = "close_button",
|
||||||
bg = Theme_config.network_manager.form.close_bg
|
bg = Theme_config.network_manager.form.close_bg
|
||||||
},
|
},
|
||||||
@@ -140,43 +103,34 @@ function ap_form.new(args)
|
|||||||
fg = Theme_config.network_manager.form.header_fg,
|
fg = Theme_config.network_manager.form.header_fg,
|
||||||
},
|
},
|
||||||
{ -- Form
|
{ -- Form
|
||||||
{ -- SSID
|
|
||||||
{
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
text = "SSID",
|
|
||||||
halign = "center",
|
|
||||||
valign = "center"
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
-- Change to inputtextbox container
|
|
||||||
ret.settigns_form.ssid,
|
|
||||||
layout = wibox.layout.align.horizontal
|
|
||||||
},
|
|
||||||
{ -- Password
|
{ -- Password
|
||||||
{
|
|
||||||
widget = wibox.widget.textbox,
|
widget = wibox.widget.textbox,
|
||||||
text = "Password",
|
text = "Password",
|
||||||
halign = "center",
|
halign = "center",
|
||||||
valign = "center"
|
valign = "center"
|
||||||
},
|
},
|
||||||
nil,
|
{
|
||||||
-- Change to inputtextbox container
|
widget = wibox.container.margin,
|
||||||
ret.settigns_form.password,
|
left = dpi(20),
|
||||||
layout = wibox.layout.align.horizontal
|
right = dpi(20),
|
||||||
},
|
},
|
||||||
spacing = dpi(10),
|
-- Change to inputtextbox container
|
||||||
layout = wibox.layout.fixed.vertical
|
settigns_form.password,
|
||||||
|
layout = wibox.layout.align.horizontal
|
||||||
},
|
},
|
||||||
{ -- Actions
|
{ -- Actions
|
||||||
{ -- Auto connect
|
{ -- Auto connect
|
||||||
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
checked = false,
|
checked = false,
|
||||||
shape = Theme_config.network_manager.form.checkbox_shape,
|
shape = Theme_config.network_manager.form.checkbox_shape,
|
||||||
color = Theme_config.network_manager.form.checkbox_bg,
|
color = Theme_config.network_manager.form.checkbox_fg,
|
||||||
check_color = Theme_config.network_manager.form.checkbox_fg,
|
paddings = dpi(3),
|
||||||
check_border_color = Theme_config.network_manager.form.check_border_color,
|
check_color = Theme_config.network_manager.form.checkbox_bg,
|
||||||
check_border_width = Theme_config.network_manager.form.check_border_width,
|
border_color = Theme_config.network_manager.form.checkbox_bg,
|
||||||
|
border_width = 2,
|
||||||
|
id = "checkbox",
|
||||||
widget = wibox.widget.checkbox
|
widget = wibox.widget.checkbox
|
||||||
},
|
},
|
||||||
widget = wibox.container.constraint,
|
widget = wibox.container.constraint,
|
||||||
@@ -184,16 +138,22 @@ function ap_form.new(args)
|
|||||||
width = dpi(30),
|
width = dpi(30),
|
||||||
height = dpi(30)
|
height = dpi(30)
|
||||||
},
|
},
|
||||||
|
widget = wibox.container.place,
|
||||||
|
halign = "center",
|
||||||
|
valign = "center"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
widget = wibox.widget.textbox,
|
widget = wibox.widget.textbox,
|
||||||
text = "Auto connect",
|
text = "Auto connect",
|
||||||
halign = "center",
|
halign = "center",
|
||||||
valign = "center"
|
valign = "center"
|
||||||
},
|
},
|
||||||
|
spacing = dpi(10),
|
||||||
layout = wibox.layout.fixed.horizontal
|
layout = wibox.layout.fixed.horizontal
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
{ -- Connect
|
{ -- Connect
|
||||||
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
widget = wibox.widget.textbox,
|
widget = wibox.widget.textbox,
|
||||||
@@ -201,16 +161,25 @@ function ap_form.new(args)
|
|||||||
halign = "center",
|
halign = "center",
|
||||||
valign = "center"
|
valign = "center"
|
||||||
},
|
},
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
margins = dpi(10),
|
||||||
|
},
|
||||||
widget = wibox.container.background,
|
widget = wibox.container.background,
|
||||||
bg = Theme_config.network_manager.form.button_bg,
|
bg = Theme_config.network_manager.form.button_bg,
|
||||||
fg = Theme_config.network_manager.form.button_fg,
|
fg = Theme_config.network_manager.form.button_fg,
|
||||||
|
shape = Theme_config.network_manager.form.button_shape,
|
||||||
|
id = "connect_button",
|
||||||
},
|
},
|
||||||
widget = wibox.container.margin,
|
widget = wibox.container.margin,
|
||||||
margins = dpi(10),
|
margins = dpi(10),
|
||||||
},
|
},
|
||||||
layout = wibox.layout.align.horizontal
|
layout = wibox.layout.align.horizontal
|
||||||
},
|
},
|
||||||
layout = wibox.layout.align.vertical
|
spacing = dpi(20),
|
||||||
|
layout = wibox.layout.fixed.vertical
|
||||||
|
},
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
margins = dpi(10)
|
||||||
},
|
},
|
||||||
placement = awful.placement.centered,
|
placement = awful.placement.centered,
|
||||||
ontop = true,
|
ontop = true,
|
||||||
@@ -220,37 +189,36 @@ function ap_form.new(args)
|
|||||||
bg = Theme_config.network_manager.form.bg,
|
bg = Theme_config.network_manager.form.bg,
|
||||||
fg = Theme_config.network_manager.form.fg,
|
fg = Theme_config.network_manager.form.fg,
|
||||||
shape = Theme_config.network_manager.form.shape,
|
shape = Theme_config.network_manager.form.shape,
|
||||||
|
border_color = Theme_config.network_manager.form.border_color,
|
||||||
|
border_width = Theme_config.network_manager.form.border_width,
|
||||||
type = "dialog",
|
type = "dialog",
|
||||||
screen = args.screen,
|
screen = args.screen,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret._private.popup.widget:get_children_by_id("close_button")[1]:connect_signal("button::press", function()
|
gtable.crush(ret, ap_form, true)
|
||||||
ret:popup_toggle()
|
|
||||||
|
local checkbox = ret.widget:get_children_by_id("checkbox")[1]
|
||||||
|
checkbox:connect_signal("button::press", function()
|
||||||
|
checkbox.checked = not checkbox.checked
|
||||||
end)
|
end)
|
||||||
|
|
||||||
ret.settigns_form.ssid:connect_signal(
|
local close_button = ret.widget:get_children_by_id("close_button")[1]
|
||||||
"submit",
|
close_button:connect_signal("button::press", function()
|
||||||
function(text)
|
ret:popup_toggle()
|
||||||
end
|
end)
|
||||||
)
|
Hover_signal(close_button)
|
||||||
|
|
||||||
ret.settigns_form.ssid:connect_signal(
|
local connect_button = ret.widget:get_children_by_id("connect_button")[1]
|
||||||
"stopped",
|
connect_button:connect_signal("button::press", function()
|
||||||
function()
|
ret:emit_signal("ap_form::connect", {
|
||||||
end
|
ssid = args.ssid,
|
||||||
)
|
password = settigns_form.password:get_text(),
|
||||||
|
auto_connect = ret.widget:get_children_by_id("checkbox")[1].checked
|
||||||
ret.settigns_form.password:connect_signal(
|
})
|
||||||
"submit",
|
print("Connect to " .. args.ssid:get_text(), "\nPassword: " .. settigns_form.password:get_text(),
|
||||||
function(text)
|
"\nAuto connect: " .. tostring(ret.widget:get_children_by_id("checkbox")[1].checked))
|
||||||
end
|
end)
|
||||||
)
|
Hover_signal(connect_button)
|
||||||
|
|
||||||
ret.settigns_form.password:connect_signal(
|
|
||||||
"stopped",
|
|
||||||
function()
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -14,23 +14,23 @@ local gcolor = require("gears").color
|
|||||||
local gears = require("gears")
|
local gears = require("gears")
|
||||||
local lgi = require("lgi")
|
local lgi = require("lgi")
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
|
||||||
local NM = require("lgi").NM
|
local NM = require("lgi").NM
|
||||||
|
local base = require("wibox.widget.base")
|
||||||
|
|
||||||
local rubato = require("src.lib.rubato")
|
local rubato = require("src.lib.rubato")
|
||||||
|
|
||||||
local access_point = require("src.modules.network_controller.access_point")
|
local access_point = require("src.modules.network_controller.access_point")
|
||||||
|
local dnd_widget = require("awful.widget.toggle_widget")
|
||||||
|
|
||||||
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/network/"
|
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/network/"
|
||||||
|
|
||||||
|
|
||||||
local capi = {
|
local capi = {
|
||||||
awesome = awesome,
|
awesome = awesome,
|
||||||
}
|
}
|
||||||
|
|
||||||
local network = { mt = {} }
|
local network = { mt = {} }
|
||||||
|
|
||||||
network.access_points = { layout = wibox.layout.fixed.vertical }
|
|
||||||
|
|
||||||
network.NMState = {
|
network.NMState = {
|
||||||
UNKNOWN = 0,
|
UNKNOWN = 0,
|
||||||
ASLEEP = 10,
|
ASLEEP = 10,
|
||||||
@@ -81,37 +81,45 @@ local function flags_to_security(flags, wpa_flags, rsn_flags)
|
|||||||
return (str:gsub("^%s", ""))
|
return (str:gsub("^%s", ""))
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_wifi_proxy(self)
|
local function generate_uuid()
|
||||||
local devices = self._private.client_proxy:GetDevices()
|
return string.gsub('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', '[xy]', function(c)
|
||||||
for _, device in ipairs(devices) do
|
local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
|
||||||
local device_proxy = dbus_proxy.Proxy:new {
|
return string.format('%x', v)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function network:get_wifi_proxy()
|
||||||
|
local devices = self._private.NetworkManager:GetDevices()
|
||||||
|
for _, path in ipairs(devices) do
|
||||||
|
local NetworkManagerDevice = dbus_proxy.Proxy:new {
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
name = "org.freedesktop.NetworkManager",
|
name = "org.freedesktop.NetworkManager",
|
||||||
interface = "org.freedesktop.NetworkManager.Device",
|
interface = "org.freedesktop.NetworkManager.Device",
|
||||||
path = device
|
path = path
|
||||||
}
|
}
|
||||||
|
|
||||||
if device_proxy.DeviceType == network.DeviceType.WIFI then
|
if NetworkManagerDevice.DeviceType == network.DeviceType.WIFI then
|
||||||
self._private.device_proxy = device_proxy
|
self._private.NetworkManagerDevice = NetworkManagerDevice
|
||||||
self._private.wifi_proxy = dbus_proxy.Proxy:new {
|
self._private.NetworkManagerDeviceWireless = dbus_proxy.Proxy:new {
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
name = "org.freedesktop.NetworkManager",
|
name = "org.freedesktop.NetworkManager",
|
||||||
interface = "org.freedesktop.NetworkManager.Device.Wireless",
|
interface = "org.freedesktop.NetworkManager.Device.Wireless",
|
||||||
path = device
|
path = path
|
||||||
}
|
}
|
||||||
|
|
||||||
self._private.device_proxy:connect_signal(function(proxy, new_state, old_state, reason)
|
self._private.NetworkManagerDevice:connect_signal(function(proxy, new_state, old_state, reason)
|
||||||
local active_access_point_proxy = dbus_proxy.Proxy:new {
|
local NetworkManagerAccessPoint = dbus_proxy.Proxy:new {
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
name = "org.freedesktop.NetworkManager",
|
name = "org.freedesktop.NetworkManager",
|
||||||
interface = "org.freedesktop.NetworkManager.AccessPoint",
|
interface = "org.freedesktop.NetworkManager.AccessPoint",
|
||||||
path = self._private.wifi_proxy.ActiveAccessPoint
|
path = self._private.wifi_proxy.ActiveAccessPoint
|
||||||
}
|
}
|
||||||
|
|
||||||
self:emit_signal(tostring(active_access_point_proxy.HwAddress) .. "::state", new_state, old_state)
|
self:emit_signal(tostring(NetworkManagerAccessPoint.HwAddress) .. "::state", new_state, old_state)
|
||||||
if new_state == network.DeviceState.ACTIVATED then
|
if new_state == network.DeviceState.ACTIVATED then
|
||||||
local ssid = NM.utils_ssid_to_utf8(active_access_point_proxy.Ssid)
|
local ssid = NM.utils_ssid_to_utf8(NetworkManagerAccessPoint.Ssid)
|
||||||
self:emit_signal("NM::AccessPointConnected", ssid, active_access_point_proxy.Strength)
|
self:emit_signal("NM::AccessPointConnected", ssid, NetworkManagerAccessPoint.Strength)
|
||||||
|
print("AP Connected: ", ssid, NetworkManagerAccessPoint.Strength)
|
||||||
end
|
end
|
||||||
end, "StateChanged")
|
end, "StateChanged")
|
||||||
end
|
end
|
||||||
@@ -119,8 +127,7 @@ local function get_wifi_proxy(self)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function network.device_state_to_string(state)
|
function network.device_state_to_string(state)
|
||||||
local device_state_to_string =
|
local device_state_to_string = {
|
||||||
{
|
|
||||||
[0] = "Unknown",
|
[0] = "Unknown",
|
||||||
[10] = "Unmanaged",
|
[10] = "Unmanaged",
|
||||||
[20] = "Unavailable",
|
[20] = "Unavailable",
|
||||||
@@ -139,63 +146,30 @@ function network.device_state_to_string(state)
|
|||||||
return device_state_to_string[state]
|
return device_state_to_string[state]
|
||||||
end
|
end
|
||||||
|
|
||||||
local function get_access_point_connections(self, ssid)
|
function network:get_access_point_connections(ssid)
|
||||||
local connection_proxies = {}
|
local cn = {}
|
||||||
|
|
||||||
local connections = self._private.settings_proxy:ListConnections()
|
local connections = self._private.NetworkManagerSettings:ListConnections()
|
||||||
for _, connection_path in ipairs(connections) do
|
for _, connection_path in ipairs(connections) do
|
||||||
local connection_proxy = dbus_proxy.Proxy:new {
|
local NetworkManagerSettingsConnection = dbus_proxy.Proxy:new {
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
name = "org.freedesktop.NetworkManager",
|
name = "org.freedesktop.NetworkManager",
|
||||||
interface = "org.freedesktop.NetworkManager.Settings.Connection",
|
interface = "org.freedesktop.NetworkManager.Settings.Connection",
|
||||||
path = connection_path
|
path = connection_path
|
||||||
}
|
}
|
||||||
|
|
||||||
if connection_proxy.Filename:find(ssid) then
|
if NetworkManagerSettingsConnection.Filename:find(ssid) then
|
||||||
table.insert(connection_proxies, connection_proxy)
|
table.insert(cn, NetworkManagerSettingsConnection)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return connection_proxies
|
return cn
|
||||||
end
|
end
|
||||||
|
|
||||||
local function generate_uuid()
|
function network:create_profile(ap, password, auto_connect)
|
||||||
local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
|
||||||
local uuid = string.gsub(template, '[xy]', function(c)
|
|
||||||
local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
|
|
||||||
return string.format('%x', v)
|
|
||||||
end)
|
|
||||||
return uuid
|
|
||||||
end
|
|
||||||
|
|
||||||
local function create_profile(ap, password, auto_connect)
|
|
||||||
local s_con =
|
|
||||||
{
|
|
||||||
-- ["interface-name"] = lgi.GLib.Variant("s", ap.device_interface),
|
|
||||||
["uuid"] = lgi.GLib.Variant("s", generate_uuid()),
|
|
||||||
["id"] = lgi.GLib.Variant("s", ap.ssid),
|
|
||||||
["type"] = lgi.GLib.Variant("s", "802-11-wireless"),
|
|
||||||
["autoconnect"] = lgi.GLib.Variant("b", auto_connect),
|
|
||||||
}
|
|
||||||
|
|
||||||
local s_ip4 =
|
|
||||||
{
|
|
||||||
["method"] = lgi.GLib.Variant("s", "auto")
|
|
||||||
}
|
|
||||||
|
|
||||||
local s_ip6 =
|
|
||||||
{
|
|
||||||
["method"] = lgi.GLib.Variant("s", "auto"),
|
|
||||||
}
|
|
||||||
|
|
||||||
local s_wifi =
|
|
||||||
{
|
|
||||||
["mode"] = lgi.GLib.Variant("s", "infrastructure"),
|
|
||||||
}
|
|
||||||
|
|
||||||
local s_wsec = {}
|
local s_wsec = {}
|
||||||
if ap.security ~= "" then
|
if ap.security ~= "" then
|
||||||
if ap.security:match("WPA") ~= nil then
|
if ap.security:match("WPA") then
|
||||||
s_wsec["key-mgmt"] = lgi.GLib.Variant("s", "wpa-psk")
|
s_wsec["key-mgmt"] = lgi.GLib.Variant("s", "wpa-psk")
|
||||||
s_wsec["auth-alg"] = lgi.GLib.Variant("s", "open")
|
s_wsec["auth-alg"] = lgi.GLib.Variant("s", "open")
|
||||||
--s_wsec["psk"] = lgi.GLib.Variant("s", helpers.string.trim(password))
|
--s_wsec["psk"] = lgi.GLib.Variant("s", helpers.string.trim(password))
|
||||||
@@ -207,108 +181,85 @@ local function create_profile(ap, password, auto_connect)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return {
|
return {
|
||||||
["connection"] = s_con,
|
["connection"] = {
|
||||||
["ipv4"] = s_ip4,
|
-- ["interface-name"] = lgi.GLib.Variant("s", ap.device_interface),
|
||||||
["ipv6"] = s_ip6,
|
["uuid"] = lgi.GLib.Variant("s", generate_uuid()),
|
||||||
["802-11-wireless"] = s_wifi,
|
["id"] = lgi.GLib.Variant("s", ap.ssid),
|
||||||
|
["type"] = lgi.GLib.Variant("s", "802-11-wireless"),
|
||||||
|
["autoconnect"] = lgi.GLib.Variant("b", auto_connect),
|
||||||
|
},
|
||||||
|
["ipv4"] = {
|
||||||
|
["method"] = lgi.GLib.Variant("s", "auto")
|
||||||
|
},
|
||||||
|
["ipv6"] = {
|
||||||
|
["method"] = lgi.GLib.Variant("s", "auto"),
|
||||||
|
},
|
||||||
|
["802-11-wireless"] = {
|
||||||
|
["mode"] = lgi.GLib.Variant("s", "infrastructure"),
|
||||||
|
},
|
||||||
["802-11-wireless-security"] = s_wsec
|
["802-11-wireless-security"] = s_wsec
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---Scan for access points and create a widget for each one.
|
||||||
function network:scan_access_points()
|
function network:scan_access_points()
|
||||||
self._private.access_points = {}
|
local ap_list = self:get_children_by_id("wifi_ap_list")[1]
|
||||||
|
|
||||||
self._private.wifi_proxy:RequestScanAsync(function(proxy, context, success, failure)
|
self._private.NetworkManagerDeviceWireless:RequestScanAsync(function(proxy, context, success, failure)
|
||||||
if failure ~= nil then
|
if failure then
|
||||||
self.access_points = { layout = wibox.layout.fixed.vertical }
|
-- Send an error notification
|
||||||
self:emit_signal("NM::AccessPointsFound", self.access_points[1].ssid)
|
print("AP Scan failed: ", failure)
|
||||||
self:emit_signal("NM::ScanFailed", tostring(failure))
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local access_points = self._private.wifi_proxy:GetAllAccessPoints()
|
-- Get every access point even those who hide their ssid
|
||||||
|
print(#self._private.NetworkManagerDeviceWireless:GetAllAccessPoints())
|
||||||
|
for _, ap in ipairs(self._private.NetworkManagerDeviceWireless:GetAllAccessPoints()) do
|
||||||
|
|
||||||
self._private.access_points = {}
|
-- Create a new proxy for every ap
|
||||||
if (not access_point) or (#access_points == 0) then
|
local NetworkManagerAccessPoint = dbus_proxy.Proxy:new {
|
||||||
self.access_points = { layout = wibox.layout.fixed.vertical }
|
|
||||||
self:emit_signal("NM::AccessPointsFound", self.access_points[1].ssid)
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, ap in ipairs(access_points) do
|
|
||||||
local access_point_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
name = "org.freedesktop.NetworkManager",
|
name = "org.freedesktop.NetworkManager",
|
||||||
interface = "org.freedesktop.NetworkManager.AccessPoint",
|
interface = "org.freedesktop.NetworkManager.AccessPoint",
|
||||||
path = ap
|
path = ap
|
||||||
}
|
}
|
||||||
|
--[[ for _, ap2 in ipairs(ap_list.children) do
|
||||||
if access_point_proxy.Ssid then
|
if ap2.NetworkManagerAccessPoint.HwAddress:match(ap.HwAddress or "") then
|
||||||
local appSsid = access_point_proxy.Ssid or ""
|
goto continue
|
||||||
local ssid = NM.utils_ssid_to_utf8(appSsid) or ""
|
|
||||||
local security = flags_to_security(access_point_proxy.Flags, access_point_proxy.WpaFlags)
|
|
||||||
local password = ""
|
|
||||||
local connections = get_access_point_connections(self, ssid)
|
|
||||||
|
|
||||||
for _, connection in ipairs(connections) do
|
|
||||||
if connection.Filename:find(ssid) then
|
|
||||||
local secrets = connection:GetSecrets("802-11-wireless-security")
|
|
||||||
if secrets then
|
|
||||||
password = secrets["802-11-wireless-security"].psk
|
|
||||||
end
|
end
|
||||||
|
end ]]
|
||||||
|
|
||||||
|
print("AP Found: ", NetworkManagerAccessPoint.HwAddress, NM.utils_ssid_to_utf8(NetworkManagerAccessPoint.Ssid),
|
||||||
|
NetworkManagerAccessPoint.Strength)
|
||||||
|
|
||||||
|
|
||||||
|
-- We are only interested in those with a ssid
|
||||||
|
if NetworkManagerAccessPoint.Ssid then
|
||||||
|
ap_list:add(access_point { NetworkManagerAccessPoint = NetworkManagerAccessPoint })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
table.insert(self._private.access_points, {
|
table.sort(ap_list, function(a, b)
|
||||||
ssid = ssid,
|
return a.NetworkManagerAccessPoint.Strength > b.NetworkManagerAccessPoint.Strength
|
||||||
security = security,
|
|
||||||
password = password,
|
|
||||||
strength = access_point_proxy.Strength,
|
|
||||||
hw_address = access_point_proxy.HwAddress,
|
|
||||||
device_interface = self._private.device_proxy.Interface,
|
|
||||||
device_path = self._private.device_proxy.object_path,
|
|
||||||
access_point_path = ap
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self.access_points = { layout = wibox.layout.fixed.vertical }
|
|
||||||
|
|
||||||
local seen = {}
|
|
||||||
for _, ap2 in ipairs(self._private.access_points) do
|
|
||||||
if not seen[ap2.ssid] then
|
|
||||||
seen[ap2.ssid] = true
|
|
||||||
table.insert(self.access_points,
|
|
||||||
access_point.new { access_point = ap2, active = self._private.wifi_proxy.ActiveAccessPoint }.widget)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
table.sort(self._private.access_points, function(a, b)
|
|
||||||
return a.strength > b.strength
|
|
||||||
end)
|
end)
|
||||||
|
print("AP_Anzahl: ", #ap_list.children)
|
||||||
self:emit_signal("NM::AccessPointsFound", self.access_points[1].ssid)
|
|
||||||
end, { call_id = "my-id" }, {})
|
end, { call_id = "my-id" }, {})
|
||||||
end
|
end
|
||||||
|
|
||||||
function network:toggle()
|
|
||||||
self.container.visible = not self.container.visible
|
|
||||||
end
|
|
||||||
|
|
||||||
function network:is_ap_active(ap)
|
function network:is_ap_active(ap)
|
||||||
print(self._private.wifi_proxy.ActiveAccessPoint)
|
|
||||||
return ap.path == self._private.wifi_proxy.ActiveAccessPoint
|
return ap.path == self._private.wifi_proxy.ActiveAccessPoint
|
||||||
end
|
end
|
||||||
|
|
||||||
function network:disconnect_ap()
|
function network:disconnect_ap()
|
||||||
self._private.client_proxy:DeactivateConnection(self._private.device_proxy.ActiveConnection)
|
self._private.NetworkManager:DeactivateConnection(self._private.NetworkManagerDevice.ActiveConnection)
|
||||||
end
|
end
|
||||||
|
|
||||||
function network:connect_ap(ap, pw, auto_connect)
|
function network:connect_ap(ap, pw, auto_connect)
|
||||||
local connections = get_access_point_connections(self, ap.ssid)
|
local connections = self:get_access_point_connections(ap.ssid)
|
||||||
local profile = create_profile(ap, pw, auto_connect)
|
local profile = self:create_profile(ap, pw, auto_connect)
|
||||||
|
|
||||||
if #connections == 0 then
|
if #connections == 0 then
|
||||||
self._private.client_proxy:AddAndActivateConnectionAsync(function(proxy, context, success, failure)
|
self._private.NetworkManager:AddAndActivateConnectionAsync(function(proxy, context, success, failure)
|
||||||
if failure then
|
if failure then
|
||||||
self:emit_signal("NM::AccessPointFailed", tostring(failure))
|
self:emit_signal("NM::AccessPointFailed", tostring(failure))
|
||||||
return
|
return
|
||||||
@@ -318,7 +269,7 @@ function network:connect_ap(ap, pw, auto_connect)
|
|||||||
end, { call_id = "my-id", profile, ap.device_proxy_path, ap.path })
|
end, { call_id = "my-id", profile, ap.device_proxy_path, ap.path })
|
||||||
else
|
else
|
||||||
connections[1]:Update(profile)
|
connections[1]:Update(profile)
|
||||||
self._private.client_proxy:ActivateConnectionAsync(function(proxy, context, success, failure)
|
self._private.NetworkManager:ActivateConnectionAsync(function(proxy, context, success, failure)
|
||||||
if failure then
|
if failure then
|
||||||
self:emit_signal("NM::AccessPointFailed", tostring(failure))
|
self:emit_signal("NM::AccessPointFailed", tostring(failure))
|
||||||
return
|
return
|
||||||
@@ -337,89 +288,21 @@ function network:toggle_access_point(ap, password, auto_connect)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function network:toggle_wireless()
|
---Toggles networking on or off
|
||||||
local enable = not self._private.client_proxy.WirelessEnabled
|
function network:toggle_wifi()
|
||||||
|
local enable = not self._private.NetworkManager.WirelessEnabled
|
||||||
if enable then
|
if enable then
|
||||||
self._private.client_proxy:Enable(true)
|
self._private.NetworkManager.Enable(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
self._private.client_proxy:Set("org.freedesktop.NetworkManager", "WirelessEnabled", lgi.GLib.Variant("b", enable))
|
self._private.NetworkManager:Set("org.freedesktop.NetworkManager", "WirelessEnabled", lgi.GLib.Variant("b", enable))
|
||||||
|
self._private.NetworkManager.WirelessEnabled = { signature = "b", value = enable }
|
||||||
return enable
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function network.new(args)
|
function network.new(args)
|
||||||
args = args or {}
|
args = args or {}
|
||||||
|
|
||||||
local ret = gobject {}
|
local ret = base.make_widget_from_value(wibox.widget {
|
||||||
|
|
||||||
gtable.crush(ret, network, true)
|
|
||||||
|
|
||||||
ret._private = {}
|
|
||||||
|
|
||||||
ret._private.client_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager",
|
|
||||||
path = "/org/freedesktop/NetworkManager",
|
|
||||||
}
|
|
||||||
|
|
||||||
ret._private.settings_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager.Settings",
|
|
||||||
path = "/org/freedesktop/NetworkManager/Settings",
|
|
||||||
}
|
|
||||||
|
|
||||||
local property_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.DBus.Properties",
|
|
||||||
path = "/org/freedesktop/NetworkManager",
|
|
||||||
}
|
|
||||||
|
|
||||||
-- dbus proxy signals are in reversed order (function, signal)
|
|
||||||
property_proxy:connect_signal(function(_, properties, data)
|
|
||||||
if data.WirelessEnables ~= nil and ret._private.WirelessEnabled ~= data.WirelessEnabled then
|
|
||||||
ret._private.WirelessEnabled = data.WirelessEnabled
|
|
||||||
ret:emit_signal("NM::WirelessStateChanged", ret._private.WirelessEnabled)
|
|
||||||
|
|
||||||
if data.WirelessEnabled then
|
|
||||||
gtimer {
|
|
||||||
timeout = 5,
|
|
||||||
autostart = true,
|
|
||||||
call_now = false,
|
|
||||||
single_shot = true,
|
|
||||||
callback = function()
|
|
||||||
ret:get_access_points()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end, "PropertiesChanged")
|
|
||||||
|
|
||||||
get_wifi_proxy(ret)
|
|
||||||
|
|
||||||
ret:scan_access_points()
|
|
||||||
|
|
||||||
gtimer.delayed_call(function()
|
|
||||||
ret:emit_signal("NM::WirelessStateChanged", ret._private.client_proxy.WirelessEnabled)
|
|
||||||
|
|
||||||
local active_access_point = ret._private.wifi_proxy.ActiveAccessPoint
|
|
||||||
if ret._private.device_proxy.State == network.DeviceState.ACTIVATED and active_access_point ~= "/" then
|
|
||||||
local active_access_point_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager.AccessPoint",
|
|
||||||
path = active_access_point,
|
|
||||||
}
|
|
||||||
|
|
||||||
local ssid = NM.utils_ssid_to_utf8(active_access_point_proxy.Ssid)
|
|
||||||
ret:emit_signal("NM:AccessPointConnected", ssid, active_access_point_proxy.Strength)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
local network_widget = wibox.widget {
|
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -488,6 +371,17 @@ function network.new(args)
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
{ -- action buttons
|
{ -- action buttons
|
||||||
|
{
|
||||||
|
dnd_widget {
|
||||||
|
color = Theme_config.network_manager.power_icon_color,
|
||||||
|
size = dpi(40)
|
||||||
|
},
|
||||||
|
id = "dnd",
|
||||||
|
widget = wibox.container.place,
|
||||||
|
valign = "center",
|
||||||
|
halign = "center"
|
||||||
|
},
|
||||||
|
nil,
|
||||||
{ -- refresh
|
{ -- refresh
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -512,31 +406,6 @@ function network.new(args)
|
|||||||
widget = wibox.container.background,
|
widget = wibox.container.background,
|
||||||
id = "refresh"
|
id = "refresh"
|
||||||
},
|
},
|
||||||
nil,
|
|
||||||
{ -- airplane mode
|
|
||||||
{
|
|
||||||
{
|
|
||||||
image = gcolor.recolor_image(icondir .. "airplane-off.svg",
|
|
||||||
Theme_config.network_manager.airplane_icon_color),
|
|
||||||
resize = false,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
id = "icon"
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = dpi(5),
|
|
||||||
id = "center",
|
|
||||||
},
|
|
||||||
border_width = dpi(2),
|
|
||||||
border_color = Theme_config.network_manager.border_color,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gshape.rounded_rect(cr, width, height, dpi(4))
|
|
||||||
end,
|
|
||||||
bg = Theme_config.network_manager.refresh_bg,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
id = "airplane"
|
|
||||||
},
|
|
||||||
layout = wibox.layout.align.horizontal
|
layout = wibox.layout.align.horizontal
|
||||||
},
|
},
|
||||||
widget = wibox.container.margin,
|
widget = wibox.container.margin,
|
||||||
@@ -562,54 +431,82 @@ function network.new(args)
|
|||||||
width = dpi(400),
|
width = dpi(400),
|
||||||
strategy = "exact",
|
strategy = "exact",
|
||||||
widget = wibox.container.constraint
|
widget = wibox.container.constraint
|
||||||
|
})
|
||||||
|
|
||||||
|
local dnd = ret:get_children_by_id("dnd")[1]:get_widget()
|
||||||
|
|
||||||
|
dnd:connect_signal("dnd::toggle", function(enable)
|
||||||
|
ret:toggle_wifi()
|
||||||
|
end)
|
||||||
|
|
||||||
|
gtable.crush(ret, network, true)
|
||||||
|
|
||||||
|
--#region Wifi Proxies
|
||||||
|
|
||||||
|
ret._private.NetworkManager = dbus_proxy.Proxy:new {
|
||||||
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
|
name = "org.freedesktop.NetworkManager",
|
||||||
|
interface = "org.freedesktop.NetworkManager",
|
||||||
|
path = "/org/freedesktop/NetworkManager",
|
||||||
}
|
}
|
||||||
|
|
||||||
local refresh_button = network_widget:get_children_by_id("refresh")[1]
|
ret._private.NetworkManagerSettings = dbus_proxy.Proxy:new {
|
||||||
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
|
name = "org.freedesktop.NetworkManager",
|
||||||
|
interface = "org.freedesktop.NetworkManager.Settings",
|
||||||
|
path = "/org/freedesktop/NetworkManager/Settings",
|
||||||
|
}
|
||||||
|
|
||||||
refresh_button:buttons(
|
ret._private.NetworkManagerProperties = dbus_proxy.Proxy:new {
|
||||||
gtable.join(
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
awful.button(
|
name = "org.freedesktop.NetworkManager",
|
||||||
{},
|
interface = "org.freedesktop.DBus.Properties",
|
||||||
1,
|
path = "/org/freedesktop/NetworkManager",
|
||||||
nil,
|
}
|
||||||
function()
|
|
||||||
|
ret._private.NetworkManagerProperties:connect_signal(function(_, properties, data)
|
||||||
|
if data.WirelessEnables ~= nil and ret._private.WirelessEnabled ~= data.WirelessEnabled then
|
||||||
|
ret._private.WirelessEnabled = data.WirelessEnabled
|
||||||
|
|
||||||
|
ret:emit_signal("NetworkManager::status", ret._private.WirelessEnabled)
|
||||||
|
print(ret._private.WirelessEnabled)
|
||||||
|
|
||||||
|
if data.WirelessEnabled then
|
||||||
|
gtimer {
|
||||||
|
timeout = 5,
|
||||||
|
autostart = true,
|
||||||
|
call_now = false,
|
||||||
|
single_shot = true,
|
||||||
|
callback = function()
|
||||||
ret:scan_access_points()
|
ret:scan_access_points()
|
||||||
end
|
end
|
||||||
)
|
}
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
Hover_signal(refresh_button)
|
|
||||||
|
|
||||||
local airplane_button = network_widget:get_children_by_id("airplane")[1]
|
|
||||||
|
|
||||||
airplane_button:buttons(
|
|
||||||
gtable.join(
|
|
||||||
awful.button(
|
|
||||||
{},
|
|
||||||
1,
|
|
||||||
nil,
|
|
||||||
function()
|
|
||||||
if ret:toggle_wireless() then
|
|
||||||
airplane_button.center.icon.image = gcolor.recolor_image(icondir
|
|
||||||
.. "airplane-off.svg",
|
|
||||||
Theme_config.network_manager.airplane_icon_color)
|
|
||||||
else
|
|
||||||
airplane_button.center.icon.image = gcolor.recolor_image(icondir
|
|
||||||
.. "airplane-on.svg",
|
|
||||||
Theme_config.network_manager.airplane_icon_color)
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end, "PropertiesChanged")
|
||||||
|
|
||||||
|
ret:get_wifi_proxy()
|
||||||
|
|
||||||
ret:scan_access_points()
|
ret:scan_access_points()
|
||||||
|
|
||||||
|
gtimer.delayed_call(function()
|
||||||
|
local active_access_point = ret._private.NetworkManagerDeviceWireless.ActiveAccessPoint
|
||||||
|
if ret._private.NetworkManager.State == network.DeviceState.ACTIVATED and active_access_point ~= "/" then
|
||||||
|
local active_access_point_proxy = dbus_proxy.Proxy:new {
|
||||||
|
bus = dbus_proxy.Bus.SYSTEM,
|
||||||
|
name = "org.freedesktop.NetworkManager",
|
||||||
|
interface = "org.freedesktop.NetworkManager.AccessPoint",
|
||||||
|
path = active_access_point,
|
||||||
|
}
|
||||||
end
|
end
|
||||||
)
|
end)
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
Hover_signal(airplane_button)
|
--#endregion
|
||||||
|
|
||||||
local wifi_margin = network_widget:get_children_by_id("wifi_margin")[1]
|
--#region Dropdown logic
|
||||||
local wifi_list = network_widget:get_children_by_id("wifi_list")[1]
|
local wifi_margin = ret:get_children_by_id("wifi_margin")[1]
|
||||||
local wifi = network_widget:get_children_by_id("wifi")[1].center
|
local wifi_list = ret:get_children_by_id("wifi_list")[1]
|
||||||
|
local wifi = ret:get_children_by_id("wifi")[1].center
|
||||||
|
|
||||||
local rubato_timer = rubato.timed {
|
local rubato_timer = rubato.timed {
|
||||||
duration = 0.2,
|
duration = 0.2,
|
||||||
@@ -620,15 +517,14 @@ function network.new(args)
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
wifi_margin:buttons(
|
wifi_margin:buttons(gtable.join(
|
||||||
gtable.join(
|
awful.button({}, 1, nil,
|
||||||
awful.button(
|
|
||||||
{},
|
|
||||||
1,
|
|
||||||
nil,
|
|
||||||
function()
|
function()
|
||||||
if wifi_list.forced_height == 0 then
|
if wifi_list.forced_height == 0 then
|
||||||
local size = (#ret.access_points * 49) + 1
|
if not ret:get_children_by_id("wifi_ap_list")[1].children then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local size = (5 * 49) + 1
|
||||||
|
|
||||||
size = size > 210 and 210 or size
|
size = size > 210 and 210 or size
|
||||||
|
|
||||||
@@ -648,36 +544,20 @@ function network.new(args)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
)
|
))
|
||||||
)
|
--#endregion
|
||||||
|
|
||||||
ret.widget = awful.popup {
|
local refresh_button = ret:get_children_by_id("refresh")[1]
|
||||||
widget = network_widget,
|
refresh_button:buttons(gtable.join(
|
||||||
bg = Theme_config.network_manager.bg,
|
awful.button({}, 1, nil,
|
||||||
screen = args.screen,
|
function()
|
||||||
stretch = false,
|
|
||||||
visible = false,
|
|
||||||
ontop = true,
|
|
||||||
placement = function(c) awful.placement.align(c,
|
|
||||||
{ position = "top_right", margins = { right = dpi(350), top = dpi(60) } })
|
|
||||||
end,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(12))
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
capi.awesome.connect_signal("NM::toggle_container", function()
|
|
||||||
ret.widget.visible = not ret.widget.visible
|
|
||||||
ret:scan_access_points()
|
ret:scan_access_points()
|
||||||
end)
|
end
|
||||||
|
)
|
||||||
|
))
|
||||||
|
Hover_signal(refresh_button)
|
||||||
|
|
||||||
capi.awesome.connect_signal("NM::toggle_wifi", function()
|
return ret
|
||||||
ret:toggle_wireless()
|
|
||||||
end)
|
|
||||||
|
|
||||||
ret:connect_signal("NM::AccessPointsFound", function(tab)
|
|
||||||
network_widget:get_children_by_id("wifi_ap_list")[1].children = ret.access_points
|
|
||||||
end)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function network.mt:__call(...)
|
function network.mt:__call(...)
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ local awful = require("awful")
|
|||||||
local dpi = require("beautiful").xresources.apply_dpi
|
local dpi = require("beautiful").xresources.apply_dpi
|
||||||
local gears = require("gears")
|
local gears = require("gears")
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
local dnd_widget = require("awful.widget.toggle_widget")
|
||||||
local rubato = require("src.lib.rubato")
|
|
||||||
|
|
||||||
local capi = {
|
local capi = {
|
||||||
awesome = awesome,
|
awesome = awesome,
|
||||||
@@ -19,6 +18,17 @@ local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/no
|
|||||||
|
|
||||||
return function(s)
|
return function(s)
|
||||||
|
|
||||||
|
local dnd = dnd_widget({
|
||||||
|
text = "Do not disturb",
|
||||||
|
color = Theme_config.notification_center.dnd_color,
|
||||||
|
fg = Theme_config.notification_center.dnd_fg,
|
||||||
|
size = dpi(40)
|
||||||
|
})
|
||||||
|
|
||||||
|
dnd:get_widget():connect_signal("dnd::toggle", function(enabled)
|
||||||
|
User_config.dnd = enabled
|
||||||
|
end)
|
||||||
|
|
||||||
--#region Activation area
|
--#region Activation area
|
||||||
|
|
||||||
local activation_area = awful.popup {
|
local activation_area = awful.popup {
|
||||||
@@ -90,121 +100,6 @@ return function(s)
|
|||||||
halign = "right",
|
halign = "right",
|
||||||
}
|
}
|
||||||
|
|
||||||
local color = Theme_config.notification_center.dnd.disabled
|
|
||||||
|
|
||||||
local function toggle_animation(pos)
|
|
||||||
if pos > 43 then return end
|
|
||||||
return function(_, _, cr, width, height)
|
|
||||||
cr:set_source(gears.color(Theme_config.notification_center.dnd.bg));
|
|
||||||
cr:paint();
|
|
||||||
cr:set_source(gears.color(color))
|
|
||||||
cr:move_to(pos, 0)
|
|
||||||
local x = pos
|
|
||||||
local y = 5
|
|
||||||
local newwidth = width / 2 - 10
|
|
||||||
local newheight = height - 10
|
|
||||||
|
|
||||||
local radius = height / 6.0
|
|
||||||
local degrees = math.pi / 180.0;
|
|
||||||
|
|
||||||
cr:new_sub_path()
|
|
||||||
cr:arc(x + newwidth - radius, y + radius, radius, -90 * degrees, 0 * degrees)
|
|
||||||
cr:arc(x + newwidth - radius, y + newheight - radius, radius, 0 * degrees, 90 * degrees)
|
|
||||||
cr:arc(x + radius, y + newheight - radius, radius, 90 * degrees, 180 * degrees)
|
|
||||||
cr:arc(x + radius, y + radius, radius, 180 * degrees, 270 * degrees)
|
|
||||||
cr:close_path()
|
|
||||||
cr:fill()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local rubato_timed
|
|
||||||
|
|
||||||
local toggle_button = wibox.widget {
|
|
||||||
{
|
|
||||||
widget = wibox.widget {
|
|
||||||
fit = function(_, width, height)
|
|
||||||
return width, height
|
|
||||||
end,
|
|
||||||
draw = toggle_animation(0),
|
|
||||||
},
|
|
||||||
id = "background",
|
|
||||||
},
|
|
||||||
active = false,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
bg = Theme_config.notification_center.dnd.bg,
|
|
||||||
border_color = Theme_config.notification_center.dnd.border_disabled,
|
|
||||||
border_width = dpi(2),
|
|
||||||
forced_height = dpi(40),
|
|
||||||
forced_width = dpi(80),
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(10))
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle_button:buttons(
|
|
||||||
gears.table.join(
|
|
||||||
awful.button({}, 1, function()
|
|
||||||
if toggle_button.active then
|
|
||||||
toggle_button.active = not toggle_button.active
|
|
||||||
toggle_button.border_color = Theme_config.notification_center.dnd.border_disabled
|
|
||||||
color = Theme_config.notification_center.dnd.disabled
|
|
||||||
User_config.dnd = false
|
|
||||||
rubato_timed.target = 5
|
|
||||||
else
|
|
||||||
toggle_button.active = not toggle_button.active
|
|
||||||
toggle_button.border_color = Theme_config.notification_center.dnd.border_enabled
|
|
||||||
color = Theme_config.notification_center.dnd.enabled
|
|
||||||
User_config.dnd = true
|
|
||||||
rubato_timed.target = 43
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
rubato_timed = rubato.timed {
|
|
||||||
duration = 0.5,
|
|
||||||
pos = 5,
|
|
||||||
subscribed = function(pos)
|
|
||||||
toggle_button:get_children_by_id("background")[1].draw = toggle_animation(pos)
|
|
||||||
toggle_button:emit_signal("widget::redraw_needed")
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
local dnd = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
text = "Do Not Disturb",
|
|
||||||
valign = "center",
|
|
||||||
align = "center",
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
id = "clearall"
|
|
||||||
},
|
|
||||||
toggle_button,
|
|
||||||
spacing = dpi(10),
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
id = "layout12"
|
|
||||||
},
|
|
||||||
id = "background4",
|
|
||||||
fg = Theme_config.notification_center.dnd.fg,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(12))
|
|
||||||
end,
|
|
||||||
forced_height = dpi(40),
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
id = "margin3",
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "place",
|
|
||||||
widget = wibox.container.place,
|
|
||||||
valign = "bottom",
|
|
||||||
halign = "right",
|
|
||||||
}
|
|
||||||
|
|
||||||
local no_notification_widget = wibox.widget {
|
local no_notification_widget = wibox.widget {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -287,8 +182,13 @@ return function(s)
|
|||||||
height = dpi(400),
|
height = dpi(400),
|
||||||
widget = wibox.container.constraint
|
widget = wibox.container.constraint
|
||||||
},
|
},
|
||||||
|
{
|
||||||
{
|
{
|
||||||
dnd,
|
dnd,
|
||||||
|
widget = wibox.container.place,
|
||||||
|
valign = "center",
|
||||||
|
halign = "center"
|
||||||
|
},
|
||||||
nil,
|
nil,
|
||||||
clear_all_widget,
|
clear_all_widget,
|
||||||
layout = wibox.layout.align.horizontal
|
layout = wibox.layout.align.horizontal
|
||||||
|
|||||||
@@ -1,249 +0,0 @@
|
|||||||
--------------------------------
|
|
||||||
-- This is the network widget --
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
-- Awesome Libs
|
|
||||||
local awful = require("awful")
|
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
|
||||||
local gears = require("gears")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
awesome = awesome,
|
|
||||||
mouse = mouse,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Icon directory path
|
|
||||||
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/powermenu/"
|
|
||||||
|
|
||||||
return function(s)
|
|
||||||
|
|
||||||
-- Profile picture imagebox
|
|
||||||
local profile_picture = wibox.widget {
|
|
||||||
image = icondir .. "defaultpfp.svg",
|
|
||||||
resize = true,
|
|
||||||
forced_height = dpi(200),
|
|
||||||
clip_shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(30))
|
|
||||||
end,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
widget = wibox.widget.imagebox
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Username textbox
|
|
||||||
local profile_name = wibox.widget {
|
|
||||||
align = 'center',
|
|
||||||
valign = 'center',
|
|
||||||
text = " ",
|
|
||||||
font = "JetBrains Mono Bold 30",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Get the profile script from /var/lib/AccountsService/icons/${USER}
|
|
||||||
-- and copy it to the assets folder
|
|
||||||
-- TODO: If the user doesnt have AccountsService look into $HOME/.faces
|
|
||||||
local update_profile_picture = function()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"./.config/awesome/src/scripts/pfp.sh 'userPfp'",
|
|
||||||
function(stdout)
|
|
||||||
if stdout then
|
|
||||||
profile_picture:set_image(stdout:gsub("\n", ""))
|
|
||||||
else
|
|
||||||
profile_picture:set_image(icondir .. "defaultpfp.svg")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
update_profile_picture()
|
|
||||||
|
|
||||||
-- Get the full username(if set) and the username + hostname
|
|
||||||
local update_user_name = function()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
"./.config/awesome/src/scripts/pfp.sh 'userName' '" .. User_config.namestyle .. "'",
|
|
||||||
function(stdout)
|
|
||||||
if stdout:gsub("\n", "") == "Rick Astley" then
|
|
||||||
profile_picture:set_image(gears.filesystem.get_configuration_dir() .. "src/assets/userpfp/" .. "rickastley.jpg")
|
|
||||||
end
|
|
||||||
profile_name:set_text(stdout)
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
update_user_name()
|
|
||||||
|
|
||||||
-- Universal Button widget
|
|
||||||
local button = function(name, icon, bg_color, callback)
|
|
||||||
local item = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
-- TODO: using gears.color to recolor a SVG will make it look super low res
|
|
||||||
-- currently I recolor it in the .svg file directly, but later implement
|
|
||||||
-- a better way to recolor a SVG
|
|
||||||
image = icon,
|
|
||||||
resize = true,
|
|
||||||
forced_height = dpi(30),
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
widget = wibox.widget.imagebox
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text = name,
|
|
||||||
font = "JetBrains Mono Bold 30",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
},
|
|
||||||
widget = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
fg = Theme_config.powermenu.button_fg,
|
|
||||||
bg = bg_color,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(10))
|
|
||||||
end,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
id = 'background'
|
|
||||||
},
|
|
||||||
layout = wibox.layout.align.vertical
|
|
||||||
}
|
|
||||||
|
|
||||||
item:connect_signal(
|
|
||||||
"button::release",
|
|
||||||
function()
|
|
||||||
callback()
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
return item
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Create the power menu actions
|
|
||||||
local suspend_command = function()
|
|
||||||
awful.spawn("systemctl suspend")
|
|
||||||
capi.awesome.emit_signal("module::powermenu:hide")
|
|
||||||
end
|
|
||||||
|
|
||||||
local logout_command = function()
|
|
||||||
capi.awesome.quit()
|
|
||||||
end
|
|
||||||
|
|
||||||
local lock_command = function()
|
|
||||||
awful.spawn("dm-tool lock")
|
|
||||||
capi.awesome.emit_signal("module::powermenu:hide")
|
|
||||||
end
|
|
||||||
|
|
||||||
local shutdown_command = function()
|
|
||||||
awful.spawn("shutdown now")
|
|
||||||
capi.awesome.emit_signal("module::powermenu:hide")
|
|
||||||
end
|
|
||||||
|
|
||||||
local reboot_command = function()
|
|
||||||
awful.spawn("reboot")
|
|
||||||
capi.awesome.emit_signal("module::powermenu:hide")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Create the buttons with their command and name etc
|
|
||||||
local shutdown_button = button("Shutdown", icondir .. "shutdown.svg", Theme_config.powermenu.shutdown_button_bg,
|
|
||||||
shutdown_command)
|
|
||||||
local reboot_button = button("Reboot", icondir .. "reboot.svg", Theme_config.powermenu.reboot_button_bg, reboot_command)
|
|
||||||
local suspend_button = button("Suspend", icondir .. "suspend.svg", Theme_config.powermenu.suspend_button_bg,
|
|
||||||
suspend_command)
|
|
||||||
local logout_button = button("Logout", icondir .. "logout.svg", Theme_config.powermenu.logout_button_bg, logout_command)
|
|
||||||
local lock_button = button("Lock", icondir .. "lock.svg", Theme_config.powermenu.lock_button_bg, lock_command)
|
|
||||||
|
|
||||||
-- Signals to change color on hover
|
|
||||||
Hover_signal(shutdown_button.background)
|
|
||||||
Hover_signal(reboot_button.background)
|
|
||||||
Hover_signal(suspend_button.background)
|
|
||||||
Hover_signal(logout_button.background)
|
|
||||||
Hover_signal(lock_button.background)
|
|
||||||
|
|
||||||
-- The powermenu widget
|
|
||||||
local powermenu = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
profile_picture,
|
|
||||||
profile_name,
|
|
||||||
spacing = dpi(50),
|
|
||||||
layout = wibox.layout.fixed.vertical
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
shutdown_button,
|
|
||||||
reboot_button,
|
|
||||||
logout_button,
|
|
||||||
lock_button,
|
|
||||||
suspend_button,
|
|
||||||
spacing = dpi(30),
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
halign = "center",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.container.place
|
|
||||||
},
|
|
||||||
layout = wibox.layout.fixed.vertical
|
|
||||||
},
|
|
||||||
halign = "center",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.container.place
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Container for the widget, covers the entire screen
|
|
||||||
local powermenu_container = wibox {
|
|
||||||
widget = powermenu,
|
|
||||||
screen = s,
|
|
||||||
type = "splash",
|
|
||||||
visible = false,
|
|
||||||
ontop = true,
|
|
||||||
bg = Theme_config.powermenu.container_bg,
|
|
||||||
height = s.geometry.height,
|
|
||||||
width = s.geometry.width,
|
|
||||||
x = s.geometry.x,
|
|
||||||
y = s.geometry.y
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Close on rightclick
|
|
||||||
powermenu_container:buttons(
|
|
||||||
gears.table.join(
|
|
||||||
awful.button(
|
|
||||||
{},
|
|
||||||
3,
|
|
||||||
function()
|
|
||||||
capi.awesome.emit_signal("module::powermenu:hide")
|
|
||||||
end
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Close on Escape
|
|
||||||
local powermenu_keygrabber = awful.keygrabber {
|
|
||||||
autostart = false,
|
|
||||||
stop_event = 'release',
|
|
||||||
keypressed_callback = function(self, mod, key, command)
|
|
||||||
if key == 'Escape' then
|
|
||||||
capi.awesome.emit_signal("module::powermenu:hide")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Signals
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"module::powermenu:show",
|
|
||||||
function()
|
|
||||||
if s == capi.mouse.screen then
|
|
||||||
powermenu_container.visible = true
|
|
||||||
powermenu_keygrabber:start()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"module::powermenu:hide",
|
|
||||||
function()
|
|
||||||
powermenu_keygrabber:stop()
|
|
||||||
powermenu_container.visible = false
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
@@ -1,447 +0,0 @@
|
|||||||
-----------------------------------
|
|
||||||
-- This is the titlebar module --
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
-- Awesome Libs
|
|
||||||
local awful = require("awful")
|
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
|
||||||
local gears = require("gears")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
awesome = awesome,
|
|
||||||
client = client
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Icon directory path
|
|
||||||
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/titlebar/"
|
|
||||||
|
|
||||||
awful.titlebar.enable_tooltip = true
|
|
||||||
awful.titlebar.fallback_name = 'Client'
|
|
||||||
|
|
||||||
-- Normal AND Focus(active/inactive) have to be set or errors will appear in stdout
|
|
||||||
Theme.titlebar_close_button_normal = icondir .. "close.svg"
|
|
||||||
Theme.titlebar_close_button_focus = icondir .. "close.svg"
|
|
||||||
Theme.titlebar_minimize_button_normal = icondir .. "minimize.svg"
|
|
||||||
Theme.titlebar_minimize_button_focus = icondir .. "minimize.svg"
|
|
||||||
Theme.titlebar_maximized_button_normal = icondir .. "maximize.svg"
|
|
||||||
Theme.titlebar_maximized_button_active = icondir .. "maximize.svg"
|
|
||||||
Theme.titlebar_maximized_button_inactive = icondir .. "maximize.svg"
|
|
||||||
|
|
||||||
local create_buttons = function(c)
|
|
||||||
local buttons = gears.table.join(
|
|
||||||
awful.button(
|
|
||||||
{},
|
|
||||||
1,
|
|
||||||
function()
|
|
||||||
c:activate { context = 'titlebar', action = 'mouse_move' }
|
|
||||||
end
|
|
||||||
),
|
|
||||||
awful.button(
|
|
||||||
{},
|
|
||||||
3,
|
|
||||||
function()
|
|
||||||
c:activate { context = 'titlebar', action = 'mouse_resize' }
|
|
||||||
end
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return buttons
|
|
||||||
end
|
|
||||||
|
|
||||||
local create_titlebar = function(c, size, position)
|
|
||||||
local close_button = awful.titlebar.widget.closebutton(c)
|
|
||||||
local minimize_button = awful.titlebar.widget.minimizebutton(c)
|
|
||||||
local maximize_button = awful.titlebar.widget.maximizedbutton(c)
|
|
||||||
|
|
||||||
local tb
|
|
||||||
|
|
||||||
if position == "left" then
|
|
||||||
local titlebar = awful.titlebar(c, {
|
|
||||||
position = "left",
|
|
||||||
bg = Theme_config.titlebar.bg,
|
|
||||||
size = size
|
|
||||||
})
|
|
||||||
|
|
||||||
tb = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
close_button,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
border_color = Theme_config.titlebar.close_button.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
shape = function(cr, height, width)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end,
|
|
||||||
id = "closebutton"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
maximize_button,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
border_color = Theme_config.titlebar.maximize_button.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
shape = function(cr, height, width)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end,
|
|
||||||
id = "maximizebutton"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
minimize_button,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
border_color = Theme_config.titlebar.minimize_button.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
shape = function(cr, height, width)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end,
|
|
||||||
id = "minimizebutton"
|
|
||||||
},
|
|
||||||
spacing = dpi(10),
|
|
||||||
layout = wibox.layout.fixed.vertical,
|
|
||||||
id = "spacing"
|
|
||||||
},
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
id = "margin"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buttons = create_buttons(c),
|
|
||||||
layout = wibox.layout.flex.vertical
|
|
||||||
},
|
|
||||||
{
|
|
||||||
awful.titlebar.widget.iconwidget(c),
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
layout = wibox.layout.align.vertical,
|
|
||||||
id = "main"
|
|
||||||
}
|
|
||||||
|
|
||||||
titlebar:setup { tb, layout = wibox.layout.fixed.horizontal }
|
|
||||||
|
|
||||||
elseif position == "top" then
|
|
||||||
local titlebar = awful.titlebar(c, {
|
|
||||||
position = "top",
|
|
||||||
bg = Theme_config.titlebar.bg,
|
|
||||||
size = size
|
|
||||||
})
|
|
||||||
|
|
||||||
tb = wibox.widget {
|
|
||||||
{
|
|
||||||
awful.titlebar.widget.iconwidget(c),
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
awful.titlebar.widget.titlewidget(c),
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
layout = wibox.container.place,
|
|
||||||
},
|
|
||||||
buttons = create_buttons(c),
|
|
||||||
fill_space = true,
|
|
||||||
layout = wibox.layout.stack
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
minimize_button,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
border_color = Theme_config.titlebar.minimize_button.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
shape = function(cr, height, width)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end,
|
|
||||||
id = "minimizebutton"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
maximize_button,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
border_color = Theme_config.titlebar.maximize_button.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
shape = function(cr, height, width)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end,
|
|
||||||
id = "maximizebutton"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
close_button,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
border_color = Theme_config.titlebar.close_button.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
shape = function(cr, height, width)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end,
|
|
||||||
id = "closebutton"
|
|
||||||
},
|
|
||||||
spacing = dpi(10),
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
id = "spacing"
|
|
||||||
},
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
id = "margin"
|
|
||||||
},
|
|
||||||
layout = wibox.layout.align.horizontal,
|
|
||||||
id = "main"
|
|
||||||
}
|
|
||||||
|
|
||||||
titlebar:setup { tb, layout = wibox.layout.fixed.vertical }
|
|
||||||
end
|
|
||||||
|
|
||||||
if not tb then return end
|
|
||||||
|
|
||||||
close_button:connect_signal(
|
|
||||||
"mouse::enter",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.titlebar.close_button.hover_border
|
|
||||||
local cb = tb:get_children_by_id("closebutton")[1]
|
|
||||||
cb.border_color = Theme_config.titlebar.close_button.hover_border
|
|
||||||
cb.bg = Theme_config.titlebar.close_button.hover_bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
close_button:connect_signal(
|
|
||||||
"mouse::leave",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.window.border_normal
|
|
||||||
local cb = tb:get_children_by_id("closebutton")[1]
|
|
||||||
cb.border_color = Theme_config.titlebar.close_button.border_color
|
|
||||||
cb.bg = Theme_config.titlebar.close_button.bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
minimize_button:connect_signal(
|
|
||||||
"mouse::enter",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.titlebar.minimize_button.hover_border
|
|
||||||
local mb = tb:get_children_by_id("minimizebutton")[1]
|
|
||||||
mb.border_color = Theme_config.titlebar.minimize_button.hover_border
|
|
||||||
mb.bg = Theme_config.titlebar.minimize_button.hover_bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
minimize_button:connect_signal(
|
|
||||||
"mouse::leave",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.window.border_normal
|
|
||||||
local mb = tb:get_children_by_id("minimizebutton")[1]
|
|
||||||
mb.border_color = Theme_config.titlebar.minimize_button.border_color
|
|
||||||
mb.bg = Theme_config.titlebar.minimize_button.bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
maximize_button:connect_signal(
|
|
||||||
"mouse::enter",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.titlebar.maximize_button.hover_border
|
|
||||||
local mb = tb:get_children_by_id("maximizebutton")[1]
|
|
||||||
mb.border_color = Theme_config.titlebar.maximize_button.hover_border
|
|
||||||
mb.bg = Theme_config.titlebar.maximize_button.hover_bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
maximize_button:connect_signal(
|
|
||||||
"mouse::leave",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.window.border_normal
|
|
||||||
local mb = tb:get_children_by_id("maximizebutton")[1]
|
|
||||||
mb.border_color = Theme_config.titlebar.maximize_button.border_color
|
|
||||||
mb.bg = Theme_config.titlebar.maximize_button.bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
local create_titlebar_dialog_modal = function(c, size, position)
|
|
||||||
local close_button = awful.titlebar.widget.closebutton(c)
|
|
||||||
local minimize_button = awful.titlebar.widget.minimizebutton(c)
|
|
||||||
local maximize_button = awful.titlebar.widget.maximizedbutton(c)
|
|
||||||
|
|
||||||
local tb
|
|
||||||
|
|
||||||
if position == "left" then
|
|
||||||
local titlebar = awful.titlebar(c, {
|
|
||||||
position = "left",
|
|
||||||
bg = Theme_config.titlebar.bg,
|
|
||||||
size = size
|
|
||||||
})
|
|
||||||
|
|
||||||
tb = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
close_button,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
border_color = Theme_config.titlebar.close_button.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
shape = function(cr, height, width)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end,
|
|
||||||
id = "closebutton"
|
|
||||||
},
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
id = "margin"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
buttons = create_buttons(c),
|
|
||||||
layout = wibox.layout.flex.vertical
|
|
||||||
},
|
|
||||||
{
|
|
||||||
awful.titlebar.widget.iconwidget(c),
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
layout = wibox.layout.align.vertical,
|
|
||||||
id = "main"
|
|
||||||
}
|
|
||||||
|
|
||||||
titlebar:setup { tb, layout = wibox.layout.fixed.horizontal }
|
|
||||||
|
|
||||||
elseif position == "top" then
|
|
||||||
local titlebar = awful.titlebar(c, {
|
|
||||||
position = "top",
|
|
||||||
bg = Theme_config.titlebar.bg,
|
|
||||||
size = size
|
|
||||||
})
|
|
||||||
|
|
||||||
tb = wibox.widget {
|
|
||||||
{
|
|
||||||
awful.titlebar.widget.iconwidget(c),
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
awful.titlebar.widget.titlewidget(c),
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
layout = wibox.container.place,
|
|
||||||
},
|
|
||||||
buttons = create_buttons(c),
|
|
||||||
fill_space = true,
|
|
||||||
layout = wibox.layout.stack
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
close_button,
|
|
||||||
widget = wibox.container.background,
|
|
||||||
border_color = Theme_config.titlebar.close_button.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
shape = function(cr, height, width)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
|
||||||
end,
|
|
||||||
id = "closebutton"
|
|
||||||
},
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
id = "margin"
|
|
||||||
},
|
|
||||||
layout = wibox.layout.align.horizontal,
|
|
||||||
id = "main"
|
|
||||||
}
|
|
||||||
|
|
||||||
titlebar:setup { tb, layout = wibox.layout.fixed.vertical }
|
|
||||||
end
|
|
||||||
|
|
||||||
if not tb then return end
|
|
||||||
|
|
||||||
close_button:connect_signal(
|
|
||||||
"mouse::enter",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.titlebar.close_button.hover_border
|
|
||||||
local cb = tb:get_children_by_id("closebutton")[1]
|
|
||||||
cb.border_color = Theme_config.titlebar.close_button.hover_border
|
|
||||||
cb.bg = Theme_config.titlebar.close_button.hover_bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
close_button:connect_signal(
|
|
||||||
"mouse::leave",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.window.border_normal
|
|
||||||
local cb = tb:get_children_by_id("closebutton")[1]
|
|
||||||
cb.border_color = Theme_config.titlebar.close_button.border_color
|
|
||||||
cb.bg = Theme_config.titlebar.close_button.bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
minimize_button:connect_signal(
|
|
||||||
"mouse::enter",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.titlebar.minimize_button.hover_border
|
|
||||||
local mb = tb:get_children_by_id("minimizebutton")[1]
|
|
||||||
mb.border_color = Theme_config.titlebar.minimize_button.hover_border
|
|
||||||
mb.bg = Theme_config.titlebar.minimize_button.hover_bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
minimize_button:connect_signal(
|
|
||||||
"mouse::leave",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.window.border_normal
|
|
||||||
local mb = tb:get_children_by_id("minimizebutton")[1]
|
|
||||||
mb.border_color = Theme_config.titlebar.minimize_button.border_color
|
|
||||||
mb.bg = Theme_config.titlebar.minimize_button.bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
maximize_button:connect_signal(
|
|
||||||
"mouse::enter",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.titlebar.maximize_button.hover_border
|
|
||||||
local mb = tb:get_children_by_id("maximizebutton")[1]
|
|
||||||
mb.border_color = Theme_config.titlebar.maximize_button.hover_border
|
|
||||||
mb.bg = Theme_config.titlebar.maximize_button.hover_bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
maximize_button:connect_signal(
|
|
||||||
"mouse::leave",
|
|
||||||
function()
|
|
||||||
c.border_color = Theme_config.window.border_normal
|
|
||||||
local mb = tb:get_children_by_id("maximizebutton")[1]
|
|
||||||
mb.border_color = Theme_config.titlebar.maximize_button.border_color
|
|
||||||
mb.bg = Theme_config.titlebar.maximize_button.bg
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
capi.client.connect_signal(
|
|
||||||
"request::titlebars",
|
|
||||||
function(c)
|
|
||||||
if c.type == "dialog" then
|
|
||||||
create_titlebar_dialog_modal(c, dpi(35), User_config.titlebar_position)
|
|
||||||
elseif c.type == "modal" then
|
|
||||||
create_titlebar_dialog_modal(c, dpi(35), User_config.titlebar_position)
|
|
||||||
else
|
|
||||||
create_titlebar(c, dpi(35), User_config.titlebar_position)
|
|
||||||
end
|
|
||||||
|
|
||||||
if not c.floating or c.maximized or c.fullscreen then
|
|
||||||
if User_config.titlebar_position == "left" then
|
|
||||||
awful.titlebar.hide(c, "left")
|
|
||||||
elseif User_config.titlebar_position == "top" then
|
|
||||||
awful.titlebar.hide(c, "top")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
capi.client.connect_signal(
|
|
||||||
"property::floating",
|
|
||||||
function(c)
|
|
||||||
if c.floating and not (c.maximized or c.fullscreen) then
|
|
||||||
if User_config.titlebar_position == "left" then
|
|
||||||
awful.titlebar.show(c, "left")
|
|
||||||
elseif User_config.titlebar_position == "top" then
|
|
||||||
awful.titlebar.show(c, "top")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if User_config.titlebar_position == "left" then
|
|
||||||
awful.titlebar.hide(c, "left")
|
|
||||||
elseif User_config.titlebar_position == "top" then
|
|
||||||
awful.titlebar.hide(c, "top")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
@@ -1,725 +0,0 @@
|
|||||||
-----------------------------------
|
|
||||||
-- This is the volume controller --
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
-- Awesome Libs
|
|
||||||
local awful = require("awful")
|
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
|
||||||
local gears = require("gears")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
awesome = awesome,
|
|
||||||
mousegrabber = mousegrabber,
|
|
||||||
}
|
|
||||||
|
|
||||||
local rubato = require("src.lib.rubato")
|
|
||||||
|
|
||||||
-- Icon directory path
|
|
||||||
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/audio/"
|
|
||||||
|
|
||||||
-- Returns the volume controller
|
|
||||||
return function(s)
|
|
||||||
|
|
||||||
-- Function to create source/sink devices
|
|
||||||
local function create_device(name, node, sink)
|
|
||||||
local device = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
id = "icon",
|
|
||||||
resize = false,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
widget = wibox.widget.imagebox
|
|
||||||
},
|
|
||||||
spacing = dpi(10),
|
|
||||||
{
|
|
||||||
text = name,
|
|
||||||
id = "node",
|
|
||||||
widget = wibox.widget.textbox
|
|
||||||
},
|
|
||||||
id = "device_layout",
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
id = "device_margin",
|
|
||||||
margins = dpi(9),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "background",
|
|
||||||
bg = Theme_config.volume_controller.device_bg,
|
|
||||||
border_color = Theme_config.volume_controller.device_border_color,
|
|
||||||
border_width = Theme_config.volume_controller.device_border_width,
|
|
||||||
shape = Theme_config.volume_controller.device_shape,
|
|
||||||
widget = wibox.container.background
|
|
||||||
}
|
|
||||||
if sink == true then
|
|
||||||
device:connect_signal(
|
|
||||||
"button::press",
|
|
||||||
function(_, _, _, key)
|
|
||||||
if key == 1 then
|
|
||||||
if node then
|
|
||||||
awful.spawn("./.config/awesome/src/scripts/vol.sh set_sink " .. node)
|
|
||||||
capi.awesome.emit_signal("update::bg_sink", node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"update::bg_sink",
|
|
||||||
function(new_node)
|
|
||||||
if node == new_node then
|
|
||||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg",
|
|
||||||
Theme_config.volume_controller.device_icon_color)
|
|
||||||
device.bg = Theme_config.volume_controller.device_headphones_selected_bg
|
|
||||||
device.fg = Theme_config.volume_controller.device_headphones_selected_fg
|
|
||||||
Hover_signal(device)
|
|
||||||
else
|
|
||||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg",
|
|
||||||
Theme_config.volume_controller.device_headphones_selected_icon_color)
|
|
||||||
device.bg = Theme_config.volume_controller.device_bg
|
|
||||||
device.fg = Theme_config.volume_controller.device_headphones_fg
|
|
||||||
Hover_signal(device)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
[[ pactl get-default-sink ]],
|
|
||||||
function(stdout)
|
|
||||||
local node_active = stdout:gsub("\n", "")
|
|
||||||
if node == node_active then
|
|
||||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg",
|
|
||||||
Theme_config.volume_controller.device_icon_color)
|
|
||||||
device.bg = Theme_config.volume_controller.device_headphones_selected_bg
|
|
||||||
device.fg = Theme_config.volume_controller.device_headphones_selected_fg
|
|
||||||
Hover_signal(device)
|
|
||||||
else
|
|
||||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "headphones.svg",
|
|
||||||
Theme_config.volume_controller.device_headphones_selected_icon_color)
|
|
||||||
device.bg = Theme_config.volume_controller.device_bg
|
|
||||||
device.fg = Theme_config.volume_controller.device_headphones_fg
|
|
||||||
Hover_signal(device)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
capi.awesome.emit_signal("update::bg_sink", node)
|
|
||||||
else
|
|
||||||
device:connect_signal(
|
|
||||||
"button::press",
|
|
||||||
function(_, _, _, key)
|
|
||||||
if key == 1 then
|
|
||||||
if node then
|
|
||||||
awful.spawn("./.config/awesome/src/scripts/mic.sh set_source " .. node)
|
|
||||||
capi.awesome.emit_signal("update::bg_source", node)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"update::bg_source",
|
|
||||||
function(new_node)
|
|
||||||
if node == new_node then
|
|
||||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg",
|
|
||||||
Theme_config.volume_controller.device_icon_color)
|
|
||||||
device.bg = Theme_config.volume_controller.device_microphone_selected_bg
|
|
||||||
device.fg = Theme_config.volume_controller.device_microphone_selected_fg
|
|
||||||
Hover_signal(device)
|
|
||||||
else
|
|
||||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg",
|
|
||||||
Theme_config.volume_controller.device_microphone_selected_icon_color)
|
|
||||||
device.bg = Theme_config.volume_controller.device_bg
|
|
||||||
device.fg = Theme_config.volume_controller.device_microphone_fg
|
|
||||||
Hover_signal(device)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
[[ pactl get-default-source ]],
|
|
||||||
function(stdout)
|
|
||||||
local node_active = stdout:gsub("\n", "")
|
|
||||||
if node == node_active then
|
|
||||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg",
|
|
||||||
Theme_config.volume_controller.device_icon_color)
|
|
||||||
device.bg = Theme_config.volume_controller.device_microphone_selected_bg
|
|
||||||
device.fg = Theme_config.volume_controller.device_microphone_selected_fg
|
|
||||||
Hover_signal(device)
|
|
||||||
else
|
|
||||||
device:get_children_by_id("icon")[1].image = gears.color.recolor_image(icondir .. "microphone.svg",
|
|
||||||
Theme_config.volume_controller.device_microphone_selected_icon_color)
|
|
||||||
device.bg = Theme_config.volume_controller.device_bg
|
|
||||||
device.fg = Theme_config.volume_controller.device_microphone_fg
|
|
||||||
Hover_signal(device)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
capi.awesome.emit_signal("update::bg_source", node)
|
|
||||||
end
|
|
||||||
return device
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Container for the source devices
|
|
||||||
local dropdown_list_volume = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
spacing = dpi(10),
|
|
||||||
layout = require("src.lib.overflow_widget.overflow").vertical,
|
|
||||||
scrollbar_width = 0,
|
|
||||||
step = dpi(50),
|
|
||||||
id = "volume_device_list",
|
|
||||||
},
|
|
||||||
id = "margin",
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "place",
|
|
||||||
height = dpi(200),
|
|
||||||
strategy = "max",
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
},
|
|
||||||
border_color = Theme_config.volume_controller.list_border_color,
|
|
||||||
border_width = Theme_config.volume_controller.list_border_width,
|
|
||||||
id = "volume_device_background",
|
|
||||||
shape = Theme_config.volume_controller.list_shape,
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
left = dpi(10),
|
|
||||||
right = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Container for the sink devices
|
|
||||||
local dropdown_list_microphone = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
spacing = dpi(10),
|
|
||||||
layout = require("src.lib.overflow_widget.overflow").vertical,
|
|
||||||
id = "volume_device_list",
|
|
||||||
scrollbar_width = 0,
|
|
||||||
step = dpi(50),
|
|
||||||
},
|
|
||||||
id = "margin",
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "place",
|
|
||||||
height = dpi(200),
|
|
||||||
strategy = "max",
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
},
|
|
||||||
id = "volume_device_background",
|
|
||||||
border_color = Theme_config.volume_controller.list_border_color,
|
|
||||||
border_width = Theme_config.volume_controller.list_border_width,
|
|
||||||
shape = Theme_config.volume_controller.list_shape,
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
left = dpi(10),
|
|
||||||
right = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
}
|
|
||||||
|
|
||||||
local volume_controller = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
-- Audio Device selector
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
resize = false,
|
|
||||||
image = gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
||||||
Theme_config.volume_controller.device_headphones_selected_icon_color),
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
id = "icon"
|
|
||||||
},
|
|
||||||
id = "center",
|
|
||||||
halign = "center",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.container.place,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
text = "Output Device",
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
id = "device_name"
|
|
||||||
},
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "audio_volume",
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
id = "audio_bg",
|
|
||||||
bg = Theme_config.volume_controller.list_bg,
|
|
||||||
fg = Theme_config.volume_controller.list_headphones_fg,
|
|
||||||
shape = Theme_config.volume_controller.list_shape,
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
id = "audio_selector_margin",
|
|
||||||
left = dpi(10),
|
|
||||||
right = dpi(10),
|
|
||||||
top = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id = "volume_list",
|
|
||||||
widget = dropdown_list_volume,
|
|
||||||
forced_height = 0
|
|
||||||
},
|
|
||||||
-- Microphone selector
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
resize = false,
|
|
||||||
image = gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
||||||
Theme_config.volume_controller.device_microphone_selected_icon_color),
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
id = "icon",
|
|
||||||
},
|
|
||||||
id = "center",
|
|
||||||
halign = "center",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.container.place,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
text = "Input Device",
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
id = "device_name"
|
|
||||||
},
|
|
||||||
margins = dpi(5),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "mic_volume",
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
id = "mic_bg",
|
|
||||||
bg = Theme_config.volume_controller.list_bg,
|
|
||||||
fg = Theme_config.volume_controller.list_microphone_fg,
|
|
||||||
shape = Theme_config.volume_controller.selector_shape,
|
|
||||||
widget = wibox.container.background
|
|
||||||
},
|
|
||||||
id = "mic_selector_margin",
|
|
||||||
left = dpi(10),
|
|
||||||
right = dpi(10),
|
|
||||||
top = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id = "mic_list",
|
|
||||||
widget = dropdown_list_microphone,
|
|
||||||
forced_height = 0
|
|
||||||
},
|
|
||||||
-- Audio volume slider
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
resize = false,
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
image = gears.color.recolor_image(icondir .. "volume-high.svg", Theme_config.volume_controller.volume_fg),
|
|
||||||
id = "icon",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
bar_shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(5))
|
|
||||||
end,
|
|
||||||
bar_height = dpi(5),
|
|
||||||
bar_color = Theme_config.volume_controller.border_color,
|
|
||||||
bar_active_color = Theme_config.volume_controller.volume_fg,
|
|
||||||
handle_color = Theme_config.volume_controller.volume_fg,
|
|
||||||
handle_shape = gears.shape.circle,
|
|
||||||
handle_border_color = Theme_config.volume_controller.volume_fg,
|
|
||||||
handle_width = dpi(12),
|
|
||||||
maximum = 100,
|
|
||||||
forced_height = dpi(26),
|
|
||||||
widget = wibox.widget.slider,
|
|
||||||
id = "slider"
|
|
||||||
},
|
|
||||||
left = dpi(5),
|
|
||||||
id = "slider_margin",
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "audio_volume",
|
|
||||||
layout = wibox.layout.align.horizontal
|
|
||||||
},
|
|
||||||
id = "audio_volume_margin",
|
|
||||||
top = dpi(10),
|
|
||||||
left = dpi(10),
|
|
||||||
right = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
-- Microphone volume slider
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
resize = false,
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
image = gears.color.recolor_image(icondir .. "microphone.svg", Theme_config.volume_controller.microphone_fg),
|
|
||||||
id = "icon"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
bar_shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(5))
|
|
||||||
end,
|
|
||||||
bar_height = dpi(5),
|
|
||||||
bar_color = Theme_config.volume_controller.device_border_color,
|
|
||||||
bar_active_color = Theme_config.volume_controller.microphone_fg,
|
|
||||||
handle_color = Theme_config.volume_controller.microphone_fg,
|
|
||||||
handle_shape = gears.shape.circle,
|
|
||||||
handle_border_color = Theme_config.volume_controller.microphone_fg,
|
|
||||||
handle_width = dpi(12),
|
|
||||||
maximum = 100,
|
|
||||||
forced_height = dpi(26),
|
|
||||||
widget = wibox.widget.slider,
|
|
||||||
id = "slider"
|
|
||||||
},
|
|
||||||
left = dpi(5),
|
|
||||||
id = "slider_margin",
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "mic_volume",
|
|
||||||
layout = wibox.layout.align.horizontal
|
|
||||||
},
|
|
||||||
id = "mic_volume_margin",
|
|
||||||
left = dpi(10),
|
|
||||||
right = dpi(10),
|
|
||||||
top = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
id = "controller_layout",
|
|
||||||
layout = wibox.layout.fixed.vertical
|
|
||||||
},
|
|
||||||
id = "controller_margin",
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
bg = Theme_config.volume_controller.bg,
|
|
||||||
border_color = Theme_config.volume_controller.border_color,
|
|
||||||
border_width = Theme_config.volume_controller.border_width,
|
|
||||||
shape = Theme_config.volume_controller.shape,
|
|
||||||
forced_width = dpi(400),
|
|
||||||
widget = wibox.container.background
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Variables for easier access and better readability
|
|
||||||
local audio_selector_margin = volume_controller:get_children_by_id("audio_selector_margin")[1]
|
|
||||||
local volume_list = volume_controller:get_children_by_id("volume_list")[1]
|
|
||||||
local audio_bg = volume_controller:get_children_by_id("audio_bg")[1]
|
|
||||||
local audio_volume = volume_controller:get_children_by_id("audio_volume")[1].center
|
|
||||||
|
|
||||||
-- Click event for the audio dropdown
|
|
||||||
audio_selector_margin:connect_signal(
|
|
||||||
"button::press",
|
|
||||||
function(_, _, _, key)
|
|
||||||
if key == 1 then
|
|
||||||
local rubato_timer = rubato.timed {
|
|
||||||
duration = 0.4,
|
|
||||||
intro = 0.1,
|
|
||||||
outro = 0.1,
|
|
||||||
pos = volume_list.forced_height,
|
|
||||||
easing = rubato.linear,
|
|
||||||
subscribed = function(v)
|
|
||||||
volume_list.forced_height = v
|
|
||||||
end
|
|
||||||
}
|
|
||||||
if volume_list.forced_height == 0 then
|
|
||||||
rubato_timer.target = dpi(200)
|
|
||||||
audio_bg.shape = function(cr, width, height)
|
|
||||||
gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
|
|
||||||
end
|
|
||||||
audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg",
|
|
||||||
Theme_config.volume_controller.device_headphones_selected_icon_color))
|
|
||||||
else
|
|
||||||
rubato_timer.target = 0
|
|
||||||
audio_bg.shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
|
||||||
end
|
|
||||||
audio_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
||||||
Theme_config.volume_controller.device_headphones_selected_icon_color))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Variables for easier access and better readability
|
|
||||||
local mic_selector_margin = volume_controller:get_children_by_id("mic_selector_margin")[1]
|
|
||||||
local mic_list = volume_controller:get_children_by_id("mic_list")[1]
|
|
||||||
local mic_bg = volume_controller:get_children_by_id("mic_bg")[1]
|
|
||||||
local mic_volume = volume_controller:get_children_by_id("mic_volume")[1].center
|
|
||||||
|
|
||||||
-- Click event for the microphone dropdown
|
|
||||||
mic_selector_margin:connect_signal(
|
|
||||||
"button::press",
|
|
||||||
function(_, _, _, key)
|
|
||||||
if key == 1 then
|
|
||||||
local rubato_timer = rubato.timed {
|
|
||||||
duration = 0.4,
|
|
||||||
intro = 0.1,
|
|
||||||
outro = 0.1,
|
|
||||||
pos = mic_list.forced_height,
|
|
||||||
easing = rubato.linear,
|
|
||||||
subscribed = function(v)
|
|
||||||
mic_list.forced_height = v
|
|
||||||
end
|
|
||||||
}
|
|
||||||
if mic_list.forced_height == 0 then
|
|
||||||
rubato_timer.target = dpi(200)
|
|
||||||
mic_selector_margin.mic_bg.shape = function(cr, width, height)
|
|
||||||
gears.shape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
|
|
||||||
end
|
|
||||||
mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-up.svg",
|
|
||||||
Theme_config.volume_controller.device_microphone_selected_icon_color))
|
|
||||||
else
|
|
||||||
rubato_timer.target = 0
|
|
||||||
mic_bg.shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(4))
|
|
||||||
end
|
|
||||||
mic_volume.icon:set_image(gears.color.recolor_image(icondir .. "menu-down.svg",
|
|
||||||
Theme_config.volume_controller.device_microphone_selected_icon_color))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
local audio_slider_margin = volume_controller:get_children_by_id("audio_volume_margin")[1].audio_volume.slider_margin.slider
|
|
||||||
|
|
||||||
-- Volume slider change event
|
|
||||||
audio_slider_margin:connect_signal(
|
|
||||||
"property::value",
|
|
||||||
function()
|
|
||||||
awful.spawn.with_shell("pactl set-sink-volume @DEFAULT_SINK@ " .. tonumber(audio_slider_margin.value) .. "%")
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
local mic_slider_margin = volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider
|
|
||||||
|
|
||||||
-- Microphone slider change event
|
|
||||||
mic_slider_margin:connect_signal(
|
|
||||||
"property::value",
|
|
||||||
function()
|
|
||||||
awful.spawn("pactl set-source-volume @DEFAULT_SOURCE@ " .. tonumber(mic_slider_margin.value) .. "%")
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Main container
|
|
||||||
local volume_controller_container = awful.popup {
|
|
||||||
widget = wibox.container.background,
|
|
||||||
ontop = true,
|
|
||||||
bg = Theme_config.volume_controller.bg,
|
|
||||||
stretch = false,
|
|
||||||
visible = false,
|
|
||||||
screen = s,
|
|
||||||
placement = function(c) awful.placement.align(c,
|
|
||||||
{ position = "top_right", margins = { right = dpi(305), top = dpi(60) } })
|
|
||||||
end,
|
|
||||||
shape = Theme_config.volume_controller.shape,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Get all source devices
|
|
||||||
local function get_source_devices()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
[[
|
|
||||||
pactl list sinks | grep -E 'node.name|device.description|alsa.card_name' | awk '{gsub(/"/, ""); for(i = 1;i < NF;i++) printf $i " "; print $NF}'
|
|
||||||
]],
|
|
||||||
function(stdout)
|
|
||||||
local device_list = {}
|
|
||||||
local was_alsa = false
|
|
||||||
local node_names, alsa_names = {}, {}
|
|
||||||
for val in stdout:gmatch("[^\n]+") do
|
|
||||||
if val:match("alsa%.card_name") then
|
|
||||||
table.insert(alsa_names, val:match("alsa%.card_name%s=%s(.*)"))
|
|
||||||
was_alsa = true
|
|
||||||
elseif val:match("device%.description") and not was_alsa then
|
|
||||||
table.insert(alsa_names, val:match("device%.description%s=%s(.*)"))
|
|
||||||
was_alsa = false
|
|
||||||
else
|
|
||||||
was_alsa = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if val:match("node%.name") then
|
|
||||||
table.insert(node_names, val:match("node%.name%s=%s(.*)"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for k = 1, #alsa_names, 1 do
|
|
||||||
device_list[#device_list + 1] = create_device(alsa_names[k], node_names[k], true)
|
|
||||||
end
|
|
||||||
dropdown_list_volume:get_children_by_id("volume_device_list")[1].children = device_list
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get all input devices
|
|
||||||
local function get_input_devices()
|
|
||||||
awful.spawn.easy_async_with_shell(
|
|
||||||
[[
|
|
||||||
pactl list sources | grep -E "node.name|device.description|alsa.card_name" | awk '{gsub(/"/, ""); for(i = 1;i < NF;i++) printf $i " "; print $NF}'
|
|
||||||
]],
|
|
||||||
function(stdout)
|
|
||||||
local device_list = {}
|
|
||||||
local was_alsa = false
|
|
||||||
local node_names, alsa_names = {}, {}
|
|
||||||
|
|
||||||
for val in stdout:gmatch("[^\n]+") do
|
|
||||||
if val:match("alsa%.card_name") then
|
|
||||||
table.insert(alsa_names, val:match("alsa%.card_name%s=%s(.*)"))
|
|
||||||
was_alsa = true
|
|
||||||
elseif val:match("device%.description") and not was_alsa then
|
|
||||||
table.insert(alsa_names, val:match("device%.description%s=%s(.*)"))
|
|
||||||
was_alsa = false
|
|
||||||
else
|
|
||||||
was_alsa = false
|
|
||||||
end
|
|
||||||
|
|
||||||
if val:match("node%.name") then
|
|
||||||
table.insert(node_names, val:match("node%.name%s=%s(.*)"))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for k = 1, #alsa_names, 1 do
|
|
||||||
device_list[#device_list + 1] = create_device(alsa_names[k], node_names[k], false)
|
|
||||||
end
|
|
||||||
dropdown_list_microphone:get_children_by_id("volume_device_list")[1].children = device_list
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"audio::device_changed",
|
|
||||||
function()
|
|
||||||
get_input_devices()
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
|
|
||||||
"microphone::device_changed",
|
|
||||||
function()
|
|
||||||
get_source_devices()
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Set the volume and icon
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
|
|
||||||
"audio::get",
|
|
||||||
function(muted, volume)
|
|
||||||
if muted then
|
|
||||||
volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.icon:set_image(gears.color
|
|
||||||
.recolor_image(icondir .. "volume-mute.svg", Theme_config.volume_controller.volume_fg))
|
|
||||||
else
|
|
||||||
volume = tonumber(volume)
|
|
||||||
if not volume then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local icon = icondir .. "volume"
|
|
||||||
if volume < 1 then
|
|
||||||
icon = icon .. "-mute"
|
|
||||||
elseif volume >= 1 and volume < 34 then
|
|
||||||
icon = icon .. "-low"
|
|
||||||
elseif volume >= 34 and volume < 67 then
|
|
||||||
icon = icon .. "-medium"
|
|
||||||
elseif volume >= 67 then
|
|
||||||
icon = icon .. "-high"
|
|
||||||
end
|
|
||||||
|
|
||||||
volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.slider_margin.slider:
|
|
||||||
set_value(volume)
|
|
||||||
volume_controller.controller_margin.controller_layout.audio_volume_margin.audio_volume.icon:set_image(gears.color
|
|
||||||
.recolor_image(icon
|
|
||||||
.. ".svg", Theme_config.volume_controller.volume_fg))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Get microphone volume
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"microphone::get",
|
|
||||||
function(muted, volume)
|
|
||||||
if muted then
|
|
||||||
--volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider:set_value(tonumber(0))
|
|
||||||
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir
|
|
||||||
.. "microphone-off.svg", Theme_config.volume_controller.microphone_fg))
|
|
||||||
else
|
|
||||||
volume = tonumber(volume)
|
|
||||||
if not volume then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.slider_margin.slider:set_value(tonumber(volume))
|
|
||||||
if volume > 0 then
|
|
||||||
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir
|
|
||||||
.. "microphone.svg", Theme_config.volume_controller.microphone_fg))
|
|
||||||
else
|
|
||||||
volume_controller:get_children_by_id("mic_volume_margin")[1].mic_volume.icon:set_image(gears.color.recolor_image(icondir
|
|
||||||
.. "microphone-off.svg", Theme_config.volume_controller.microphone_fg))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- When the mouse leaves the popup it stops the mousegrabber and hides the popup.
|
|
||||||
volume_controller_container:connect_signal(
|
|
||||||
"mouse::leave",
|
|
||||||
function()
|
|
||||||
capi.mousegrabber.run(
|
|
||||||
function()
|
|
||||||
capi.awesome.emit_signal("volume_controller::toggle", s)
|
|
||||||
capi.mousegrabber.stop()
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
"arrow"
|
|
||||||
)
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
volume_controller_container:connect_signal(
|
|
||||||
"mouse::enter",
|
|
||||||
function()
|
|
||||||
capi.mousegrabber.stop()
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
-- Grabs all keys and hides popup when anything is pressed
|
|
||||||
-- TODO: Make it possible to navigate and select using the kb
|
|
||||||
awful.keygrabber {
|
|
||||||
autostart = false,
|
|
||||||
stop_event = 'release',
|
|
||||||
keypressed_callback = function()
|
|
||||||
capi.awesome.emit_signal("volume_controller::toggle", s)
|
|
||||||
capi.mousegrabber.stop()
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Draw the popup
|
|
||||||
volume_controller_container:setup {
|
|
||||||
volume_controller,
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Toggle container visibility
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"volume_controller::toggle",
|
|
||||||
function(scr)
|
|
||||||
if scr == s then
|
|
||||||
volume_controller_container.visible = not volume_controller_container.visible
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
-----------------------------------
|
|
||||||
-- This is the volume_old module --
|
|
||||||
-----------------------------------
|
|
||||||
|
|
||||||
-- Awesome Libs
|
|
||||||
local awful = require("awful")
|
|
||||||
local dpi = require("beautiful").xresources.apply_dpi
|
|
||||||
local gears = require("gears")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
awesome = awesome,
|
|
||||||
mouse = mouse,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Icon directory path
|
|
||||||
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/audio/"
|
|
||||||
|
|
||||||
-- Returns the volume_osd
|
|
||||||
return function(s)
|
|
||||||
|
|
||||||
local volume_osd_widget = wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{ -- Volume Icon
|
|
||||||
image = gears.color.recolor_image(icondir .. "volume-high.svg", Theme_config.volume_osd.icon_color),
|
|
||||||
valign = "center",
|
|
||||||
halign = "center",
|
|
||||||
resize = false,
|
|
||||||
id = "icon",
|
|
||||||
widget = wibox.widget.imagebox
|
|
||||||
},
|
|
||||||
{ -- Volume Bar
|
|
||||||
{
|
|
||||||
{
|
|
||||||
id = "progressbar1",
|
|
||||||
color = Theme_config.volume_osd.bar_bg_active,
|
|
||||||
background_color = Theme_config.volume_osd.bar_bg,
|
|
||||||
max_value = 100,
|
|
||||||
value = 50,
|
|
||||||
forced_height = dpi(6),
|
|
||||||
shape = function(cr, width, heigth)
|
|
||||||
gears.shape.rounded_bar(cr, width, heigth, dpi(6))
|
|
||||||
end,
|
|
||||||
widget = wibox.widget.progressbar
|
|
||||||
},
|
|
||||||
id = "progressbar_container2",
|
|
||||||
halign = "center",
|
|
||||||
valign = "center",
|
|
||||||
widget = wibox.container.place
|
|
||||||
},
|
|
||||||
id = "progressbar_container",
|
|
||||||
width = dpi(240),
|
|
||||||
heigth = dpi(20),
|
|
||||||
stragety = "max",
|
|
||||||
widget = wibox.container.constraint
|
|
||||||
},
|
|
||||||
id = "layout1",
|
|
||||||
spacing = dpi(10),
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
},
|
|
||||||
id = "margin",
|
|
||||||
margins = dpi(10),
|
|
||||||
widget = wibox.container.margin
|
|
||||||
},
|
|
||||||
forced_width = dpi(300),
|
|
||||||
forced_height = dpi(80),
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(12))
|
|
||||||
end,
|
|
||||||
border_color = Theme_config.volume_osd.border_color,
|
|
||||||
border_width = Theme_config.volume_osd.border_width,
|
|
||||||
fg = Theme_config.volume_osd.fg,
|
|
||||||
bg = Theme_config.volume_osd.bg,
|
|
||||||
widget = wibox.container.background
|
|
||||||
}
|
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"audio::get",
|
|
||||||
function(muted, volume)
|
|
||||||
if muted then
|
|
||||||
volume_osd_widget:get_children_by_id("icon")[1]
|
|
||||||
:set_image(gears.color.recolor_image(
|
|
||||||
icondir .. "volume-mute" .. ".svg", Theme_config.volume_osd.icon_color))
|
|
||||||
volume_osd_widget:get_children_by_id("progressbar1")[1].value = tonumber(0)
|
|
||||||
else
|
|
||||||
volume = tonumber(volume)
|
|
||||||
if not volume then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
volume_osd_widget:get_children_by_id("progressbar1")[1].value = tonumber(volume)
|
|
||||||
local icon = icondir .. "volume"
|
|
||||||
if volume < 1 then
|
|
||||||
icon = icon .. "-mute"
|
|
||||||
elseif volume >= 1 and volume < 34 then
|
|
||||||
icon = icon .. "-low"
|
|
||||||
elseif volume >= 34 and volume < 67 then
|
|
||||||
icon = icon .. "-medium"
|
|
||||||
elseif volume >= 67 then
|
|
||||||
icon = icon .. "-high"
|
|
||||||
end
|
|
||||||
volume_osd_widget:get_children_by_id("icon")[1]:set_image(gears.color.recolor_image(icon .. ".svg",
|
|
||||||
Theme_config.volume_osd.icon_color))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
local volume_container = awful.popup {
|
|
||||||
widget = {},
|
|
||||||
ontop = true,
|
|
||||||
stretch = false,
|
|
||||||
visible = false,
|
|
||||||
screen = s,
|
|
||||||
placement = function(c) awful.placement.bottom_left(c, { margins = dpi(20) }) end,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(14))
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
local hide_volume_osd = gears.timer {
|
|
||||||
timeout = 2,
|
|
||||||
autostart = true,
|
|
||||||
callback = function()
|
|
||||||
volume_container.visible = false
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
volume_container:setup {
|
|
||||||
volume_osd_widget,
|
|
||||||
layout = wibox.layout.fixed.horizontal
|
|
||||||
}
|
|
||||||
|
|
||||||
capi.awesome.connect_signal(
|
|
||||||
"widget::volume_osd:rerun",
|
|
||||||
function()
|
|
||||||
if capi.mouse.screen == s then
|
|
||||||
volume_container.visible = true
|
|
||||||
if hide_volume_osd.started then
|
|
||||||
hide_volume_osd:again()
|
|
||||||
else
|
|
||||||
hide_volume_osd:start()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
@@ -59,6 +59,12 @@ Theme_config.date = {
|
|||||||
fg = color["Grey900"]
|
fg = color["Grey900"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Theme_config.dnd = {
|
||||||
|
bg = color["Grey900"],
|
||||||
|
disabled = color["Grey800"],
|
||||||
|
border_disabled = color["Grey800"],
|
||||||
|
}
|
||||||
|
|
||||||
Theme_config.gpu_usage = {
|
Theme_config.gpu_usage = {
|
||||||
bg = color["Green200"],
|
bg = color["Green200"],
|
||||||
fg = color["Grey900"]
|
fg = color["Grey900"]
|
||||||
@@ -250,6 +256,19 @@ Theme_config.network_manager = {
|
|||||||
icon_fg = color["Grey900"],
|
icon_fg = color["Grey900"],
|
||||||
border_color = color["Grey800"],
|
border_color = color["Grey800"],
|
||||||
border_width = dpi(2),
|
border_width = dpi(2),
|
||||||
|
button_bg = color["Blue200"],
|
||||||
|
button_fg = color["Grey900"],
|
||||||
|
checkbox_fg = color["Grey900"],
|
||||||
|
checkbox_bg = color["DeepOrange200"],
|
||||||
|
checkbox_shape = function(cr, width, height)
|
||||||
|
gears.shape.rounded_rect(cr, width, height, dpi(6))
|
||||||
|
end,
|
||||||
|
button_shape = function(cr, width, height)
|
||||||
|
gears.shape.rounded_rect(cr, width, height, dpi(8))
|
||||||
|
end,
|
||||||
|
close_icon_shape = function(cr, width, height)
|
||||||
|
gears.shape.rounded_rect(cr, width, height, dpi(8))
|
||||||
|
end,
|
||||||
shape = function(cr, width, height)
|
shape = function(cr, width, height)
|
||||||
gears.shape.rounded_rect(cr, width, height, dpi(8))
|
gears.shape.rounded_rect(cr, width, height, dpi(8))
|
||||||
end
|
end
|
||||||
@@ -294,6 +313,8 @@ Theme_config.notification_center = {
|
|||||||
border_color = color["Grey800"],
|
border_color = color["Grey800"],
|
||||||
border_width = dpi(4),
|
border_width = dpi(4),
|
||||||
spacing_color = color["Grey800"],
|
spacing_color = color["Grey800"],
|
||||||
|
dnd_color = color["Purple200"],
|
||||||
|
dnd_fg = color["Pink200"],
|
||||||
|
|
||||||
-- Clear all button
|
-- Clear all button
|
||||||
clear_all_button = {
|
clear_all_button = {
|
||||||
@@ -301,16 +322,6 @@ Theme_config.notification_center = {
|
|||||||
fg = color["Grey900"]
|
fg = color["Grey900"]
|
||||||
},
|
},
|
||||||
|
|
||||||
-- DnD button
|
|
||||||
dnd = {
|
|
||||||
bg = color["Grey900"],
|
|
||||||
fg = color["Pink200"],
|
|
||||||
disabled = color["Grey700"],
|
|
||||||
enabled = color["Purple200"],
|
|
||||||
border_disabled = color["Grey800"],
|
|
||||||
border_enabled = color["Purple200"]
|
|
||||||
},
|
|
||||||
|
|
||||||
-- Notification_list
|
-- Notification_list
|
||||||
notification_list = {
|
notification_list = {
|
||||||
timer_fg = color["Teal200"],
|
timer_fg = color["Teal200"],
|
||||||
@@ -431,7 +442,7 @@ Theme_config.bluetooth_controller = {
|
|||||||
refresh_icon_color = color["Grey900"],
|
refresh_icon_color = color["Grey900"],
|
||||||
refresh_bg = color["LightBlue200"],
|
refresh_bg = color["LightBlue200"],
|
||||||
power_icon_color = color["Grey900"],
|
power_icon_color = color["Grey900"],
|
||||||
power_bg = color["Blue200"]
|
power_bg = color["Blue200"],
|
||||||
}
|
}
|
||||||
|
|
||||||
Theme_config.brightness_osd = {
|
Theme_config.brightness_osd = {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ User_config = {
|
|||||||
Flatpak application: flatpak run com.example.App
|
Flatpak application: flatpak run com.example.App
|
||||||
]] --
|
]] --
|
||||||
autostart = {
|
autostart = {
|
||||||
"picom --experimental-backends",
|
"picom",
|
||||||
"xfce4-power-manager",
|
"xfce4-power-manager",
|
||||||
"light-locker --lock-on-suspend --lock-on-lid &",
|
"light-locker --lock-on-suspend --lock-on-lid &",
|
||||||
"/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1",
|
"/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1",
|
||||||
|
|||||||
@@ -1,18 +1,13 @@
|
|||||||
local awful = require("awful")
|
local awful = require("awful")
|
||||||
local pulse = require("pulseaudio_dbus")
|
|
||||||
|
|
||||||
local capi = {
|
local capi = {
|
||||||
awesome = awesome,
|
awesome = awesome,
|
||||||
}
|
}
|
||||||
|
|
||||||
local lgi = require("lgi")
|
local lgi = require("lgi")
|
||||||
local pulseaudio = require("lua_libpulse_glib")
|
|
||||||
|
|
||||||
local pa = pulseaudio.new()
|
|
||||||
|
|
||||||
local ctx = pa:context("awesome")
|
|
||||||
|
|
||||||
print(ctx)
|
|
||||||
--[[ ctx:connect(nil, function(state)
|
--[[ ctx:connect(nil, function(state)
|
||||||
if state == 4 then
|
if state == 4 then
|
||||||
print("Connection is ready")
|
print("Connection is ready")
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
require("src.tools.helpers.cpu_temp")
|
|
||||||
--!Find a better way that doesn't need manual GC since it has a huge performance impact
|
|
||||||
--require("src.tools.helpers.cpu_usage")
|
|
||||||
require("src.tools.helpers.cpu_freq")
|
|
||||||
require("src.tools.helpers.ram")
|
|
||||||
require("src.tools.helpers.gpu_usage")
|
|
||||||
require("src.tools.helpers.gpu_temp")
|
|
||||||
require("src.tools.helpers.audio")
|
|
||||||
require("src.tools.helpers.backlight")
|
|
||||||
@@ -1,440 +0,0 @@
|
|||||||
-------------------------------------------
|
|
||||||
-- @author https://github.com/Kasper24
|
|
||||||
-- @copyright 2021-2022 Kasper24
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
local lgi = require("lgi")
|
|
||||||
local NM = lgi.NM
|
|
||||||
local awful = require("awful")
|
|
||||||
local gobject = require("gears.object")
|
|
||||||
local gtable = require("gears.table")
|
|
||||||
local gtimer = require("gears.timer")
|
|
||||||
local dbus_proxy = require("services.dbus_proxy")
|
|
||||||
|
|
||||||
local network = {}
|
|
||||||
local instance = nil
|
|
||||||
|
|
||||||
network.NMState = {
|
|
||||||
UNKNOWN = 0, -- Networking state is unknown. This indicates a daemon error that
|
|
||||||
-- makes it unable to reasonably assess the state. In such event the applications
|
|
||||||
-- are expected to assume Internet connectivity might be present and not disable
|
|
||||||
-- controls that require network access. The graphical shells may hide the network
|
|
||||||
-- accessibility indicator altogether since no meaningful status indication can be provided.
|
|
||||||
ASLEEP = 10, -- Networking is not enabled, the system is being suspended or resumed from suspend.
|
|
||||||
DISCONNECTED = 20, -- There is no active network connection. The graphical
|
|
||||||
-- shell should indicate no network connectivity and the applications
|
|
||||||
-- should not attempt to access the network.
|
|
||||||
DISCONNECTING = 30, -- Network connections are being cleaned up.
|
|
||||||
-- The applications should tear down their network sessions.
|
|
||||||
CONNECTING = 40, -- A network connection is being started The graphical
|
|
||||||
-- shell should indicate the network is being connected while the
|
|
||||||
-- applications should still make no attempts to connect the network.
|
|
||||||
CONNECTED_LOCAL = 50, -- There is only local IPv4 and/or IPv6 connectivity,
|
|
||||||
-- but no default route to access the Internet. The graphical
|
|
||||||
-- shell should indicate no network connectivity.
|
|
||||||
CONNECTED_SITE = 60, -- There is only site-wide IPv4 and/or IPv6 connectivity.
|
|
||||||
-- This means a default route is available, but the Internet connectivity check
|
|
||||||
-- (see "Connectivity" property) did not succeed. The graphical shell
|
|
||||||
-- should indicate limited network connectivity.
|
|
||||||
CONNECTED_GLOBAL = 70, -- There is global IPv4 and/or IPv6 Internet connectivity
|
|
||||||
-- This means the Internet connectivity check succeeded, the graphical shell should
|
|
||||||
-- indicate full network connectivity.
|
|
||||||
}
|
|
||||||
|
|
||||||
network.DeviceType = {
|
|
||||||
ETHERNET = 1,
|
|
||||||
WIFI = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
network.DeviceState = {
|
|
||||||
UNKNOWN = 0, -- the device's state is unknown
|
|
||||||
UNMANAGED = 10, -- the device is recognized, but not managed by NetworkManager
|
|
||||||
UNAVAILABLE = 20, --the device is managed by NetworkManager,
|
|
||||||
--but is not available for use. Reasons may include the wireless switched off,
|
|
||||||
--missing firmware, no ethernet carrier, missing supplicant or modem manager, etc.
|
|
||||||
DISCONNECTED = 30, -- the device can be activated,
|
|
||||||
--but is currently idle and not connected to a network.
|
|
||||||
PREPARE = 40, -- the device is preparing the connection to the network.
|
|
||||||
-- This may include operations like changing the MAC address,
|
|
||||||
-- setting physical link properties, and anything else required
|
|
||||||
-- to connect to the requested network.
|
|
||||||
CONFIG = 50, -- the device is connecting to the requested network.
|
|
||||||
-- This may include operations like associating with the Wi-Fi AP,
|
|
||||||
-- dialing the modem, connecting to the remote Bluetooth device, etc.
|
|
||||||
NEED_AUTH = 60, -- the device requires more information to continue
|
|
||||||
-- connecting to the requested network. This includes secrets like WiFi passphrases,
|
|
||||||
-- login passwords, PIN codes, etc.
|
|
||||||
IP_CONFIG = 70, -- the device is requesting IPv4 and/or IPv6 addresses
|
|
||||||
-- and routing information from the network.
|
|
||||||
IP_CHECK = 80, -- the device is checking whether further action
|
|
||||||
-- is required for the requested network connection.
|
|
||||||
-- This may include checking whether only local network access is available,
|
|
||||||
-- whether a captive portal is blocking access to the Internet, etc.
|
|
||||||
SECONDARIES = 90, -- the device is waiting for a secondary connection
|
|
||||||
-- (like a VPN) which must activated before the device can be activated
|
|
||||||
ACTIVATED = 100, -- the device has a network connection, either local or global.
|
|
||||||
DEACTIVATING = 110, -- a disconnection from the current network connection
|
|
||||||
-- was requested, and the device is cleaning up resources used for that connection.
|
|
||||||
-- The network connection may still be valid.
|
|
||||||
FAILED = 120 -- the device failed to connect to
|
|
||||||
-- the requested network and is cleaning up the connection request
|
|
||||||
}
|
|
||||||
|
|
||||||
function network.device_state_to_string(state)
|
|
||||||
local device_state_to_string =
|
|
||||||
{
|
|
||||||
[0] = "Unknown",
|
|
||||||
[10] = "Unmanaged",
|
|
||||||
[20] = "Unavailable",
|
|
||||||
[30] = "Disconnected",
|
|
||||||
[40] = "Prepare",
|
|
||||||
[50] = "Config",
|
|
||||||
[60] = "Need Auth",
|
|
||||||
[70] = "IP Config",
|
|
||||||
[80] = "IP Check",
|
|
||||||
[90] = "Secondaries",
|
|
||||||
[100] = "Activated",
|
|
||||||
[110] = "Deactivated",
|
|
||||||
[120] = "Failed"
|
|
||||||
}
|
|
||||||
|
|
||||||
return device_state_to_string[state]
|
|
||||||
end
|
|
||||||
|
|
||||||
local function flags_to_security(flags, wpa_flags, rsn_flags)
|
|
||||||
local str = ""
|
|
||||||
if flags == 1 and wpa_flags == 0 and rsn_flags == 0 then
|
|
||||||
str = str .. " WEP"
|
|
||||||
end
|
|
||||||
if wpa_flags ~= 0 then
|
|
||||||
str = str .. " WPA1"
|
|
||||||
end
|
|
||||||
if not rsn_flags ~= 0 then
|
|
||||||
str = str .. " WPA2"
|
|
||||||
end
|
|
||||||
if wpa_flags == 512 or rsn_flags == 512 then
|
|
||||||
str = str .. " 802.1X"
|
|
||||||
end
|
|
||||||
|
|
||||||
return (str:gsub("^%s", ""))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function generate_uuid()
|
|
||||||
local template = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'
|
|
||||||
local uuid = string.gsub(template, '[xy]', function(c)
|
|
||||||
local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
|
|
||||||
return string.format('%x', v)
|
|
||||||
end)
|
|
||||||
return uuid
|
|
||||||
end
|
|
||||||
|
|
||||||
local function create_profile(access_point, password, auto_connect)
|
|
||||||
local s_con =
|
|
||||||
{
|
|
||||||
-- ["interface-name"] = lgi.GLib.Variant("s", access_point.device_interface),
|
|
||||||
["uuid"] = lgi.GLib.Variant("s", generate_uuid()),
|
|
||||||
["id"] = lgi.GLib.Variant("s", access_point.ssid),
|
|
||||||
["type"] = lgi.GLib.Variant("s", "802-11-wireless"),
|
|
||||||
["autoconnect"] = lgi.GLib.Variant("b", auto_connect),
|
|
||||||
}
|
|
||||||
|
|
||||||
local s_ip4 =
|
|
||||||
{
|
|
||||||
["method"] = lgi.GLib.Variant("s", "auto")
|
|
||||||
}
|
|
||||||
|
|
||||||
local s_ip6 =
|
|
||||||
{
|
|
||||||
["method"] = lgi.GLib.Variant("s", "auto"),
|
|
||||||
}
|
|
||||||
|
|
||||||
local s_wifi =
|
|
||||||
{
|
|
||||||
["mode"] = lgi.GLib.Variant("s", "infrastructure"),
|
|
||||||
}
|
|
||||||
|
|
||||||
local s_wsec = {}
|
|
||||||
if access_point.security ~= "" then
|
|
||||||
if access_point.security:match("WPA") ~= nil then
|
|
||||||
s_wsec["key-mgmt"] = lgi.GLib.Variant("s", "wpa-psk")
|
|
||||||
s_wsec["auth-alg"] = lgi.GLib.Variant("s", "open")
|
|
||||||
s_wsec["psk"] = lgi.GLib.Variant("s", helpers.string.trim(password))
|
|
||||||
else
|
|
||||||
s_wsec["key-mgmt"] = lgi.GLib.Variant("s", "None")
|
|
||||||
s_wsec["wep-key-type"] = lgi.GLib.Variant("s", NM.WepKeyType.PASSPHRASE)
|
|
||||||
s_wsec["wep-key0"] = lgi.GLib.Variant("s", helpers.string.trim(password))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
["connection"] = s_con,
|
|
||||||
["ipv4"] = s_ip4,
|
|
||||||
["ipv6"] = s_ip6,
|
|
||||||
["802-11-wireless"] = s_wifi,
|
|
||||||
["802-11-wireless-security"] = s_wsec
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function on_wifi_device_state_changed(self, proxy, new_state, old_state, reason)
|
|
||||||
local active_access_point_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager.AccessPoint",
|
|
||||||
path = self._private.wifi_proxy.ActiveAccessPoint
|
|
||||||
}
|
|
||||||
|
|
||||||
self:emit_signal(tostring(active_access_point_proxy.HwAddress) .. "::state", new_state, old_state)
|
|
||||||
if new_state == network.DeviceState.ACTIVATED then
|
|
||||||
local ssid = NM.utils_ssid_to_utf8(active_access_point_proxy.Ssid)
|
|
||||||
self:emit_signal("access_point::connected", ssid, active_access_point_proxy.Strength)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_access_point_connections(self, ssid)
|
|
||||||
local connection_proxies = {}
|
|
||||||
|
|
||||||
local connections = self._private.settings_proxy:ListConnections()
|
|
||||||
for _, connection_path in ipairs(connections) do
|
|
||||||
local connection_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager.Settings.Connection",
|
|
||||||
path = connection_path
|
|
||||||
}
|
|
||||||
|
|
||||||
if string.find(connection_proxy.Filename, ssid) then
|
|
||||||
table.insert(connection_proxies, connection_proxy)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return connection_proxies
|
|
||||||
end
|
|
||||||
|
|
||||||
local function get_wifi_proxy(self)
|
|
||||||
local devices = self._private.client_proxy:GetDevices()
|
|
||||||
for _, device_path in ipairs(devices) do
|
|
||||||
local device_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager.Device",
|
|
||||||
path = device_path
|
|
||||||
}
|
|
||||||
|
|
||||||
if device_proxy.DeviceType == network.DeviceType.WIFI then
|
|
||||||
self._private.device_proxy = device_proxy
|
|
||||||
self._private.wifi_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager.Device.Wireless",
|
|
||||||
path = device_path
|
|
||||||
}
|
|
||||||
|
|
||||||
self._private.device_proxy:connect_signal("StateChanged", function(proxy, new_state, old_state, reason)
|
|
||||||
on_wifi_device_state_changed(self, proxy, new_state, old_state, reason)
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function network:scan_access_points()
|
|
||||||
self._private.access_points = {}
|
|
||||||
|
|
||||||
self._private.wifi_proxy:RequestScanAsync(function(proxy, context, success, failure)
|
|
||||||
if failure ~= nil then
|
|
||||||
print("Rescan wifi failed: ", failure)
|
|
||||||
print("Rescan wifi failed error code: ", failure.code)
|
|
||||||
self:emit_signal("scan_access_points::failed", tostring(failure), tostring(failure.code))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local access_points = self._private.wifi_proxy:GetAccessPoints()
|
|
||||||
for _, access_point_path in ipairs(access_points) do
|
|
||||||
local access_point_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager.AccessPoint",
|
|
||||||
path = access_point_path
|
|
||||||
}
|
|
||||||
|
|
||||||
-- for _, access_point in ipairs(self._private.access_points) do
|
|
||||||
-- if access_point.hw_address == access_point_proxy.HwAddress then
|
|
||||||
-- print("duplicates")
|
|
||||||
-- return
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
|
|
||||||
if access_point_proxy.Ssid ~= nil then
|
|
||||||
local ssid = NM.utils_ssid_to_utf8(access_point_proxy.Ssid)
|
|
||||||
local security = flags_to_security(access_point_proxy.Flags, access_point_proxy.WpaFlags,
|
|
||||||
access_point_proxy.RsnFlags)
|
|
||||||
local password = ""
|
|
||||||
local connections = get_access_point_connections(self, ssid)
|
|
||||||
|
|
||||||
for _, connection in ipairs(connections) do
|
|
||||||
if string.find(connection.Filename, ssid) then
|
|
||||||
local secrets = connection:GetSecrets("802-11-wireless-security")
|
|
||||||
if secrets ~= nil then
|
|
||||||
password = secrets["802-11-wireless-security"].psk
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(self._private.access_points, {
|
|
||||||
raw_ssid = access_point_proxy.Ssid,
|
|
||||||
ssid = ssid,
|
|
||||||
security = security,
|
|
||||||
password = password,
|
|
||||||
strength = access_point_proxy.Strength,
|
|
||||||
path = access_point_path,
|
|
||||||
hw_address = access_point_proxy.HwAddress,
|
|
||||||
device_interface = self._private.device_proxy.Interface,
|
|
||||||
device_proxy_path = self._private.device_proxy.object_path,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
table.sort(self._private.access_points, function(a, b)
|
|
||||||
return a.strength > b.strength
|
|
||||||
end)
|
|
||||||
|
|
||||||
self:emit_signal("scan_access_points::success", self._private.access_points)
|
|
||||||
end, { call_id = "my-id" }, {})
|
|
||||||
end
|
|
||||||
|
|
||||||
function network:connect_to_access_point(access_point, password, auto_connect)
|
|
||||||
local connections = get_access_point_connections(self, access_point.ssid)
|
|
||||||
local profile = create_profile(access_point, password, auto_connect)
|
|
||||||
|
|
||||||
-- No connection profiles, need to create one
|
|
||||||
if #connections == 0 then
|
|
||||||
-- AddAndActivateConnectionAsync doesn't actually verify that the profile is valid
|
|
||||||
-- The NetworkManager libary has methods to verify manually, but they are not exposed to DBus
|
|
||||||
-- so instead I'm using the 2 seperate methods
|
|
||||||
self._private.client_proxy:AddAndActivateConnectionAsync(function(proxy, context, success, failure)
|
|
||||||
if failure ~= nil then
|
|
||||||
print("Failed to activate connection: ", failure)
|
|
||||||
print("Failed to activate connection error code: ", failure.code)
|
|
||||||
self:emit_signal("activate_access_point::failed", tostring(failure), tostring(failure.code))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self:emit_signal("activate_access_point::success", access_point.ssid)
|
|
||||||
end, { call_id = "my-id" }, profile, access_point.device_proxy_path, access_point.path)
|
|
||||||
else
|
|
||||||
connections[1]:Update(profile)
|
|
||||||
self._private.client_proxy:ActivateConnectionAsync(function(proxy, context, success, failure)
|
|
||||||
if failure ~= nil then
|
|
||||||
print("Failed to activate connection: ", failure)
|
|
||||||
print("Failed to activate connection error code: ", failure.code)
|
|
||||||
self:emit_signal("activate_access_point::failed", tostring(failure), tostring(failure.code))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self:emit_signal("activate_access_point::success", access_point.ssid)
|
|
||||||
|
|
||||||
end, { call_id = "my-id" }, connections[1].object_path, access_point.device_proxy_path, access_point.path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function network:is_access_point_active(access_point)
|
|
||||||
return access_point.path == self._private.wifi_proxy.ActiveAccessPoint
|
|
||||||
end
|
|
||||||
|
|
||||||
function network:disconnect_from_access_point()
|
|
||||||
self._private.client_proxy:DeactivateConnection(self._private.device_proxy.ActiveConnection)
|
|
||||||
end
|
|
||||||
|
|
||||||
function network:toggle_access_point(access_point, password, auto_connect)
|
|
||||||
if self:is_access_point_active(access_point) then
|
|
||||||
self:disconnect_from_access_point()
|
|
||||||
else
|
|
||||||
self:connect_to_access_point(access_point, password, auto_connect)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function network:toggle_wireless_state()
|
|
||||||
local enable = not self._private.client_proxy.WirelessEnabled
|
|
||||||
if enable == true then
|
|
||||||
self:set_network_state(true)
|
|
||||||
end
|
|
||||||
|
|
||||||
self._private.client_proxy:Set("org.freedesktop.NetworkManager", "WirelessEnabled", lgi.GLib.Variant("b", enable))
|
|
||||||
self._private.client_proxy.WirelessEnabled = { signature = "b", value = enable }
|
|
||||||
end
|
|
||||||
|
|
||||||
function network:set_network_state(state)
|
|
||||||
self._private.client_proxy:Enable(state)
|
|
||||||
end
|
|
||||||
|
|
||||||
function network:open_settings()
|
|
||||||
awful.spawn("nm-connection-editor", false)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function new()
|
|
||||||
local ret = gobject {}
|
|
||||||
gtable.crush(ret, network, true)
|
|
||||||
|
|
||||||
ret._private = {}
|
|
||||||
ret._private.access_points = {}
|
|
||||||
|
|
||||||
ret._private.client_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager",
|
|
||||||
path = "/org/freedesktop/NetworkManager"
|
|
||||||
}
|
|
||||||
|
|
||||||
ret._private.settings_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager.Settings",
|
|
||||||
path = "/org/freedesktop/NetworkManager/Settings"
|
|
||||||
}
|
|
||||||
|
|
||||||
local client_properties_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.DBus.Properties",
|
|
||||||
path = "/org/freedesktop/NetworkManager"
|
|
||||||
}
|
|
||||||
|
|
||||||
client_properties_proxy:connect_signal("PropertiesChanged", function(self, interface, data)
|
|
||||||
if data.WirelessEnabled ~= nil and ret._private.WirelessEnabled ~= data.WirelessEnabled then
|
|
||||||
ret._private.WirelessEnabled = data.WirelessEnabled
|
|
||||||
ret:emit_signal("wireless_state", data.WirelessEnabled)
|
|
||||||
|
|
||||||
if data.WirelessEnabled == true then
|
|
||||||
gtimer { timeout = 5, autostart = true, call_now = false, single_shot = true, callback = function()
|
|
||||||
ret:scan_access_points()
|
|
||||||
end }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
get_wifi_proxy(ret)
|
|
||||||
ret:scan_access_points()
|
|
||||||
|
|
||||||
gtimer.delayed_call(function()
|
|
||||||
ret:emit_signal("wireless_state", ret._private.client_proxy.WirelessEnabled)
|
|
||||||
|
|
||||||
local active_access_point = ret._private.wifi_proxy.ActiveAccessPoint
|
|
||||||
if ret._private.device_proxy.State == network.DeviceState.ACTIVATED and active_access_point ~= "/" then
|
|
||||||
local active_access_point_proxy = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = "org.freedesktop.NetworkManager",
|
|
||||||
interface = "org.freedesktop.NetworkManager.AccessPoint",
|
|
||||||
path = active_access_point
|
|
||||||
}
|
|
||||||
|
|
||||||
local ssid = NM.utils_ssid_to_utf8(active_access_point_proxy.Ssid)
|
|
||||||
ret:emit_signal("access_point::connected", ssid, active_access_point_proxy.Strength)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
if not instance then
|
|
||||||
instance = new()
|
|
||||||
end
|
|
||||||
return instance
|
|
||||||
@@ -7,6 +7,8 @@ local dpi = require("beautiful").xresources.apply_dpi
|
|||||||
local gears = require("gears")
|
local gears = require("gears")
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
|
||||||
|
require("src.tools.helpers.audio")
|
||||||
|
|
||||||
local capi = {
|
local capi = {
|
||||||
awesome = awesome,
|
awesome = awesome,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,22 @@ local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/bl
|
|||||||
|
|
||||||
-- Returns the bluetooth widget
|
-- Returns the bluetooth widget
|
||||||
return function(s)
|
return function(s)
|
||||||
|
|
||||||
|
local bt_widget = require("src.modules.bluetooth.init") { screen = s }
|
||||||
|
|
||||||
|
local bluetooth_container = awful.popup {
|
||||||
|
widget = bt_widget:get_widget(),
|
||||||
|
ontop = true,
|
||||||
|
bg = Theme_config.bluetooth_controller.container_bg,
|
||||||
|
stretch = false,
|
||||||
|
visible = false,
|
||||||
|
forced_width = dpi(400),
|
||||||
|
screen = s,
|
||||||
|
shape = function(cr, width, height)
|
||||||
|
gears.shape.rounded_rect(cr, width, height, dpi(12))
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
local bluetooth_widget = wibox.widget {
|
local bluetooth_widget = wibox.widget {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -43,24 +59,23 @@ return function(s)
|
|||||||
end,
|
end,
|
||||||
widget = wibox.container.background
|
widget = wibox.container.background
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bt_widget:connect_signal("bluetooth::status", function(status)
|
||||||
|
bluetooth_widget:get_children_by_id("icon")[1].image = gears.color.recolor_image(status._private.Adapter1.Powered and
|
||||||
|
icondir .. "bluetooth-on.svg" or icondir .. "bluetooth-off.svg", Theme_config.bluetooth.fg)
|
||||||
|
end)
|
||||||
|
|
||||||
-- Hover signal to change color when mouse is over
|
-- Hover signal to change color when mouse is over
|
||||||
Hover_signal(bluetooth_widget)
|
Hover_signal(bluetooth_widget)
|
||||||
|
|
||||||
capi.awesome.connect_signal("state", function(state)
|
|
||||||
if state then
|
|
||||||
bluetooth_widget:get_children_by_id("icon")[1]:set_image(gears.color.recolor_image(icondir .. "bluetooth-on.svg",
|
|
||||||
Theme_config.bluetooth.fg))
|
|
||||||
else
|
|
||||||
bluetooth_widget:get_children_by_id("icon")[1]:set_image(gears.color.recolor_image(icondir .. "bluetooth-off.svg",
|
|
||||||
Theme_config.bluetooth.fg))
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
bluetooth_widget:connect_signal(
|
bluetooth_widget:connect_signal(
|
||||||
"button::press",
|
"button::press",
|
||||||
function(_, _, _, key)
|
function(_, _, _, key)
|
||||||
if key == 1 then
|
if key == 1 then
|
||||||
capi.awesome.emit_signal("bluetooth_controller::toggle", s)
|
local geo = mouse.current_wibox:geometry()
|
||||||
|
bluetooth_container.x = geo.x
|
||||||
|
bluetooth_container.y = geo.y + dpi(55)
|
||||||
|
bluetooth_container.visible = not bluetooth_container.visible
|
||||||
else
|
else
|
||||||
capi.awesome.emit_signal("toggle_bluetooth")
|
capi.awesome.emit_signal("toggle_bluetooth")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ local wibox = require("wibox")
|
|||||||
local color = require("src.lib.color")
|
local color = require("src.lib.color")
|
||||||
local rubato = require("src.lib.rubato")
|
local rubato = require("src.lib.rubato")
|
||||||
|
|
||||||
|
require("src.tools.helpers.cpu_freq")
|
||||||
|
require("src.tools.helpers.cpu_temp")
|
||||||
|
--!Has to be disabled until rewritten to perform better require("src.tools.helpers.cpu_usage")
|
||||||
|
|
||||||
local capi = {
|
local capi = {
|
||||||
awesome = awesome,
|
awesome = awesome,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ return function(s)
|
|||||||
awful.button({}, 1, function()
|
awful.button({}, 1, function()
|
||||||
local geo = mouse.current_wibox:geometry()
|
local geo = mouse.current_wibox:geometry()
|
||||||
calendar_popup.x = geo.x
|
calendar_popup.x = geo.x
|
||||||
calendar_popup.y = geo.y + Global_config.top_struts
|
calendar_popup.y = geo.y + dpi(55)
|
||||||
calendar_popup.visible = not calendar_popup.visible
|
calendar_popup.visible = not calendar_popup.visible
|
||||||
end)
|
end)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ local wibox = require("wibox")
|
|||||||
local color = require("src.lib.color")
|
local color = require("src.lib.color")
|
||||||
local rubato = require("src.lib.rubato")
|
local rubato = require("src.lib.rubato")
|
||||||
|
|
||||||
|
require("src.tools.helpers.gpu_temp")
|
||||||
|
require("src.tools.helpers.gpu_usage")
|
||||||
|
|
||||||
local capi = {
|
local capi = {
|
||||||
awesome = awesome,
|
awesome = awesome,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ local capi = {
|
|||||||
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/kblayout/"
|
local icondir = gears.filesystem.get_configuration_dir() .. "src/assets/icons/kblayout/"
|
||||||
|
|
||||||
return function(s)
|
return function(s)
|
||||||
|
|
||||||
local kblayout_widget = wibox.widget {
|
local kblayout_widget = wibox.widget {
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,8 +24,10 @@ local interfaces = {
|
|||||||
|
|
||||||
local network_mode = nil
|
local network_mode = nil
|
||||||
|
|
||||||
|
local nm_widget = require("src.modules.network_controller.init")
|
||||||
|
|
||||||
-- Returns the network widget
|
-- Returns the network widget
|
||||||
return function()
|
return function(s)
|
||||||
local startup = true
|
local startup = true
|
||||||
local reconnect_startup = true
|
local reconnect_startup = true
|
||||||
local wifi_strength
|
local wifi_strength
|
||||||
@@ -331,6 +333,21 @@ return function()
|
|||||||
end
|
end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local network_container = awful.popup {
|
||||||
|
widget = nm_widget {},
|
||||||
|
bg = Theme_config.network_manager.bg,
|
||||||
|
screen = s,
|
||||||
|
stretch = false,
|
||||||
|
visible = false,
|
||||||
|
ontop = true,
|
||||||
|
placement = function(c) awful.placement.align(c,
|
||||||
|
{ position = "top_right", margins = { right = dpi(350), top = dpi(60) } })
|
||||||
|
end,
|
||||||
|
shape = function(cr, width, height)
|
||||||
|
gears.shape.rounded_rect(cr, width, height, dpi(12))
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
-- Signals
|
-- Signals
|
||||||
Hover_signal(network_widget)
|
Hover_signal(network_widget)
|
||||||
|
|
||||||
@@ -341,7 +358,7 @@ return function()
|
|||||||
1,
|
1,
|
||||||
nil,
|
nil,
|
||||||
function()
|
function()
|
||||||
capi.awesome.emit_signal("NM::toggle_container")
|
network_container.visible = not network_container.visible
|
||||||
end
|
end
|
||||||
),
|
),
|
||||||
awful.button(
|
awful.button(
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ local gears = require("gears")
|
|||||||
local watch = awful.widget.watch
|
local watch = awful.widget.watch
|
||||||
local wibox = require("wibox")
|
local wibox = require("wibox")
|
||||||
|
|
||||||
|
require("src.tools.helpers.ram")
|
||||||
|
|
||||||
local capi = {
|
local capi = {
|
||||||
awesome = awesome,
|
awesome = awesome,
|
||||||
}
|
}
|
||||||
|
|||||||
40
awesome/todo.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
|
||||||
|
# TODO list for my AwesomeWM rice
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
|
||||||
|
### Applicationlauncher [100% Done]
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
- Automatically collects all .desktop files that are marked as visible and displays them
|
||||||
|
- Execute application
|
||||||
|
- Search for an application
|
||||||
|
- Right click context menu
|
||||||
|
- Options to execute as sudo, pin to dock or add to desktop
|
||||||
|
- Infinite scoll (well technically, infinite if you installed infinite apps lol)
|
||||||
|
- Algorithm to select the best search match
|
||||||
|
- Keep track of most launched applications and serve them over others
|
||||||
|
|
||||||
|
### Bluetooth [95% Done]
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
- Connecting/Disconnecting a device
|
||||||
|
- Finding other devices and grouping them into paired and not paired
|
||||||
|
- Removing them from beeing Paired
|
||||||
|
- Trusting/Untrusting a device
|
||||||
|
- Toggle Bluetooth on/off
|
||||||
|
- Scan again for devices
|
||||||
|
- Update as soon a new device is found
|
||||||
|
- When removed put it into the discovered list from paired
|
||||||
|
- Renaming a device
|
||||||
|
- Pairing a new device
|
||||||
|
- Dropdown with multiple options per device
|
||||||
|
|
||||||
|
#### TODO
|
||||||
|
|
||||||
|
- Getting and asking for a passcode
|
||||||
|
- "Greying out" non avaiable options in the dropdown
|
||||||
|
|
||||||
|
## Widgets
|
||||||
395
awesome/wibox/widget/inputbox.lua
Normal file
@@ -0,0 +1,395 @@
|
|||||||
|
---------------------------------------------------------------------------
|
||||||
|
-- A widget to write text in
|
||||||
|
--@DOC_wibox_widget_defaults_inputtextbox_EXAMPLE@
|
||||||
|
--
|
||||||
|
-- @author Rene Kievits
|
||||||
|
-- @copyright 2022 Rene Kievits
|
||||||
|
-- @widgetmod wibox.widget.inputbox
|
||||||
|
-- @supermodule wibox.widget.textbox
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
local base = require("wibox.widget.base")
|
||||||
|
local gdebug = require("gears.debug")
|
||||||
|
local gfs = require("gears.filesystem")
|
||||||
|
local gobject = require("gears.object")
|
||||||
|
local gstring = require("gears.string")
|
||||||
|
local beautiful = require("beautiful")
|
||||||
|
local keygrabber = require("awful.keygrabber")
|
||||||
|
local lgi = require("lgi")
|
||||||
|
local gtable = require("gears.table")
|
||||||
|
local wibox = require("wibox")
|
||||||
|
local abutton = require("awful.button")
|
||||||
|
local setmetatable = setmetatable
|
||||||
|
|
||||||
|
local capi =
|
||||||
|
{
|
||||||
|
selection = selection,
|
||||||
|
mousegrabber = mousegrabber,
|
||||||
|
mouse = mouse,
|
||||||
|
}
|
||||||
|
|
||||||
|
local inputbox = { mt = {} }
|
||||||
|
|
||||||
|
local function text_with_cursor(text, cursor_pos, self)
|
||||||
|
local char, spacer, text_start, text_end
|
||||||
|
|
||||||
|
local cursor_fg = beautiful.inputbox_cursor_fg or "#313131"
|
||||||
|
local cursor_bg = beautiful.inputbox_cursor_bg or "#0dccfc"
|
||||||
|
local text_color = beautiful.inputbox_fg or "#ffffff"
|
||||||
|
local placeholder_text = beautiful.inputbox_placeholder_text or "Type here..."
|
||||||
|
local placeholder_fg = beautiful.inputbox_placeholder_fg or "#777777"
|
||||||
|
local highlight_bg = beautiful.inputbox_highlight_bg or "#35ffe4"
|
||||||
|
local highlight_fg = beautiful.inputbox_highlight_fg or "#000000"
|
||||||
|
|
||||||
|
if text == "" then
|
||||||
|
return "<span foreground='" .. placeholder_fg .. "'>" .. placeholder_text .. "</span>"
|
||||||
|
end
|
||||||
|
|
||||||
|
if #text < cursor_pos then
|
||||||
|
char = " "
|
||||||
|
spacer = ""
|
||||||
|
text_start = gstring.xml_escape(text)
|
||||||
|
text_end = ""
|
||||||
|
else
|
||||||
|
local offset = 0
|
||||||
|
if #text:sub(cursor_pos, cursor_pos) == -1 then
|
||||||
|
offset = 1
|
||||||
|
end
|
||||||
|
char = gstring.xml_escape(text:sub(cursor_pos, cursor_pos + offset))
|
||||||
|
spacer = " "
|
||||||
|
text_start = gstring.xml_escape(text:sub(1, cursor_pos - 1))
|
||||||
|
text_end = gstring.xml_escape(text:sub(cursor_pos + offset + 1))
|
||||||
|
end
|
||||||
|
|
||||||
|
if self._private.highlight and self._private.highlight.cur_pos_start and self._private.highlight.cur_pos_end then
|
||||||
|
-- split the text into 3 parts based on the highlight and cursor position
|
||||||
|
local text_start_highlight = gstring.xml_escape(text:sub(1, self._private.highlight.cur_pos_start - 1))
|
||||||
|
local text_highlighted = gstring.xml_escape(text:sub(self._private.highlight.cur_pos_start,
|
||||||
|
self._private.highlight.cur_pos_end))
|
||||||
|
local text_end_highlight = gstring.xml_escape(text:sub(self._private.highlight.cur_pos_end + 1))
|
||||||
|
|
||||||
|
return "<span foreground='" .. text_color .. "'>" .. text_start_highlight .. "</span>" ..
|
||||||
|
"<span foreground='" .. highlight_fg .. "' background='" .. highlight_bg .. "'>" ..
|
||||||
|
text_highlighted ..
|
||||||
|
"</span>" .. "<span foreground='" .. text_color .. "'>" .. text_end_highlight .. "</span>"
|
||||||
|
else
|
||||||
|
return "<span foreground='" .. text_color .. "'>" .. text_start .. "</span>" ..
|
||||||
|
"<span background='" .. cursor_bg .. "' foreground='" .. cursor_fg .. "'>" ..
|
||||||
|
char .. "</span>" .. "<span foreground='" .. text_color .. "'>" .. text_end .. spacer .. "</span>"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Clears the current text
|
||||||
|
function inputbox:clear()
|
||||||
|
self:set_text("")
|
||||||
|
end
|
||||||
|
|
||||||
|
function inputbox:get_text()
|
||||||
|
return self._private.text or ""
|
||||||
|
end
|
||||||
|
|
||||||
|
function inputbox:set_text(text)
|
||||||
|
self._private.text = text
|
||||||
|
self:emit_signal("property::text", text)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Stop the keygrabber and mousegrabber
|
||||||
|
function inputbox:stop()
|
||||||
|
self:emit_signal("stopped")
|
||||||
|
keygrabber.stop()
|
||||||
|
capi.mousegrabber.stop()
|
||||||
|
end
|
||||||
|
|
||||||
|
function inputbox:focus()
|
||||||
|
keygrabber.stop()
|
||||||
|
if not keygrabber.is_running then
|
||||||
|
self:run()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Stops the mousegrabber when not clicked on the widget
|
||||||
|
--[[ capi.mousegrabber.run(
|
||||||
|
function(m)
|
||||||
|
if m.buttons[1] then
|
||||||
|
if capi.mouse.current_wibox ~= self:get_widget().widget then
|
||||||
|
self:emit_signal("keygrabber::stop", "")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end, "left_ptr"
|
||||||
|
) ]]
|
||||||
|
|
||||||
|
self:connect_signal("button::press", function()
|
||||||
|
if capi.mouse.current_widget ~= self then
|
||||||
|
self:emit_signal("keygrabber::stop", "")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function inputbox:run()
|
||||||
|
|
||||||
|
if not self._private.text then self._private.text = "" end
|
||||||
|
|
||||||
|
-- Init the cursor position, but causes on refocus the cursor to move to the left
|
||||||
|
local cursor_pos = #self:get_text() + 1
|
||||||
|
|
||||||
|
self:emit_signal("started")
|
||||||
|
|
||||||
|
-- Init and reset(when refocused) the highlight
|
||||||
|
self._private.highlight = {}
|
||||||
|
|
||||||
|
-- Emitted when the keygrabber is stopped
|
||||||
|
self:connect_signal("cancel", function()
|
||||||
|
self:stop()
|
||||||
|
self:emit_signal("stopped")
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Emitted when the keygrabber should submit the text
|
||||||
|
self:connect_signal("submit", function(text)
|
||||||
|
self:stop()
|
||||||
|
self:emit_signal("stopped", text)
|
||||||
|
end)
|
||||||
|
|
||||||
|
self:emit_signal("key_pressed", "B", "A")
|
||||||
|
|
||||||
|
|
||||||
|
keygrabber.run(function(mod, key, event)
|
||||||
|
local mod_keys = {}
|
||||||
|
for _, v in ipairs(mod) do
|
||||||
|
mod_keys[v] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if not (event == "press") then return end
|
||||||
|
--Escape cases
|
||||||
|
-- Just quit and leave the text as is
|
||||||
|
if (not mod_keys.Control) and (key == "Escape") then
|
||||||
|
self:emit_signal("cancel")
|
||||||
|
elseif (not mod_keys.Control and key == "KP_Enter") or (not mod_keys.Control and key == "Return") then
|
||||||
|
self:emit_signal("submit", self:get_text())
|
||||||
|
self:set_text("")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- All shift, control or key cases
|
||||||
|
if mod_keys.Shift then
|
||||||
|
if key == "Left" then
|
||||||
|
if cursor_pos > 1 then
|
||||||
|
if not self._private.highlight.cur_pos_start then
|
||||||
|
self._private.highlight.cur_pos_start = cursor_pos - 1
|
||||||
|
end
|
||||||
|
if not self._private.highlight.cur_pos_end then
|
||||||
|
self._private.highlight.cur_pos_end = cursor_pos
|
||||||
|
end
|
||||||
|
|
||||||
|
if self._private.highlight.cur_pos_start < cursor_pos then
|
||||||
|
self._private.highlight.cur_pos_end = self._private.highlight.cur_pos_end - 1
|
||||||
|
else
|
||||||
|
self._private.highlight.cur_pos_start = self._private.highlight.cur_pos_start - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
cursor_pos = cursor_pos - 1
|
||||||
|
end
|
||||||
|
elseif key == "Right" then
|
||||||
|
if #self._private.text >= cursor_pos then
|
||||||
|
if not self._private.highlight.cur_pos_end then
|
||||||
|
self._private.highlight.cur_pos_end = cursor_pos - 1
|
||||||
|
end
|
||||||
|
if not self._private.highlight.cur_pos_start then
|
||||||
|
self._private.highlight.cur_pos_start = cursor_pos
|
||||||
|
end
|
||||||
|
|
||||||
|
if self._private.highlight.cur_pos_end <= cursor_pos then
|
||||||
|
self._private.highlight.cur_pos_end = self._private.highlight.cur_pos_end + 1
|
||||||
|
else
|
||||||
|
self._private.highlight.cur_pos_start = self._private.highlight.cur_pos_start + 1
|
||||||
|
end
|
||||||
|
cursor_pos = cursor_pos + 1
|
||||||
|
if cursor_pos > #self._private.text + 1 then
|
||||||
|
self._private.highlight = {}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if key:wlen() == 1 then
|
||||||
|
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
|
||||||
|
string.upper(key) .. self._private.text:sub(cursor_pos))
|
||||||
|
cursor_pos = cursor_pos + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif mod_keys.Control then
|
||||||
|
if key == "a" then
|
||||||
|
-- Mark the entire text
|
||||||
|
self._private.highlight = {
|
||||||
|
cur_pos_start = 1,
|
||||||
|
cur_pos_end = #self._private.text
|
||||||
|
}
|
||||||
|
elseif key == "c" then
|
||||||
|
-- TODO: Copy the highlighted text when the selection setter gets implemented
|
||||||
|
elseif key == "v" then
|
||||||
|
local sel = capi.selection()
|
||||||
|
if sel then
|
||||||
|
sel = sel:gsub("\n", "")
|
||||||
|
if self._private.highlight and self._private.highlight.cur_pos_start and
|
||||||
|
self._private.highlight.cur_pos_end then
|
||||||
|
-- insert the text into the selected part
|
||||||
|
local text_start = self._private.text:sub(1, self._private.highlight.cur_pos_start - 1)
|
||||||
|
local text_end = self._private.text:sub(self._private.highlight.cur_pos_end + 1)
|
||||||
|
self:set_text(text_start .. sel .. text_end)
|
||||||
|
self._private.highlight = {}
|
||||||
|
cursor_pos = #text_start + #sel + 1
|
||||||
|
else
|
||||||
|
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
|
||||||
|
sel .. self._private.text:sub(cursor_pos))
|
||||||
|
cursor_pos = cursor_pos + #sel
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif key == "x" then
|
||||||
|
--TODO: "cut". Copy selected then clear text, this requires to add the c function first.
|
||||||
|
self._private.highlight = {}
|
||||||
|
elseif key == "Left" then
|
||||||
|
-- Find all spaces
|
||||||
|
local spaces = {}
|
||||||
|
local t, i = self._private.text, 0
|
||||||
|
|
||||||
|
while t:find("%s") do
|
||||||
|
i = t:find("%s")
|
||||||
|
table.insert(spaces, i)
|
||||||
|
t = t:sub(1, i - 1) .. "-" .. t:sub(i + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
local cp = 1
|
||||||
|
for _, v in ipairs(spaces) do
|
||||||
|
if (v < cursor_pos) then
|
||||||
|
cp = v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
cursor_pos = cp
|
||||||
|
elseif key == "Right" then
|
||||||
|
local next_space = self._private.text:sub(cursor_pos):find("%s")
|
||||||
|
if next_space then
|
||||||
|
cursor_pos = cursor_pos + next_space
|
||||||
|
else
|
||||||
|
cursor_pos = #self._private.text + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if key == "BackSpace" then
|
||||||
|
-- If text is highlighted delete that, else just delete the character to the left
|
||||||
|
if self._private.highlight and self._private.highlight.cur_pos_start and
|
||||||
|
self._private.highlight.cur_pos_end then
|
||||||
|
local text_start = self._private.text:sub(1, self._private.highlight.cur_pos_start - 1)
|
||||||
|
local text_end = self._private.text:sub(self._private.highlight.cur_pos_end + 1)
|
||||||
|
self:set_text(text_start .. text_end)
|
||||||
|
self._private.highlight = {}
|
||||||
|
cursor_pos = #text_start + 1
|
||||||
|
else
|
||||||
|
if cursor_pos > 1 then
|
||||||
|
self:set_text(self._private.text:sub(1, cursor_pos - 2) ..
|
||||||
|
self._private.text:sub(cursor_pos))
|
||||||
|
cursor_pos = cursor_pos - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif key == "Delete" then
|
||||||
|
-- If text is highlighted delete that, else just delete the character to the right
|
||||||
|
if self._private.highlight and self._private.highlight.cur_pos_start and
|
||||||
|
self._private.highlight.cur_pos_end then
|
||||||
|
local text_start = self._private.text:sub(1, self._private.highlight.cur_pos_start - 1)
|
||||||
|
local text_end = self._private.text:sub(self._private.highlight.cur_pos_end + 1)
|
||||||
|
self:set_text(text_start .. text_end)
|
||||||
|
self._private.highlight = {}
|
||||||
|
cursor_pos = #text_start + 1
|
||||||
|
else
|
||||||
|
if cursor_pos <= #self._private.text then
|
||||||
|
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
|
||||||
|
self._private.text:sub(cursor_pos + 1))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif key == "Left" then
|
||||||
|
-- Move cursor ro the left
|
||||||
|
if cursor_pos > 1 then
|
||||||
|
cursor_pos = cursor_pos - 1
|
||||||
|
end
|
||||||
|
self._private.highlight = {}
|
||||||
|
elseif key == "Right" then
|
||||||
|
-- Move cursor to the right
|
||||||
|
if cursor_pos <= #self._private.text then
|
||||||
|
cursor_pos = cursor_pos + 1
|
||||||
|
end
|
||||||
|
self._private.highlight = {}
|
||||||
|
else
|
||||||
|
-- Print every alphanumeric key
|
||||||
|
-- It seems like gears.xmlescape doesn't support non alphanumeric characters
|
||||||
|
if key:wlen() == 1 then
|
||||||
|
self:set_text(self._private.text:sub(1, cursor_pos - 1) ..
|
||||||
|
key .. self._private.text:sub(cursor_pos))
|
||||||
|
cursor_pos = cursor_pos + #key
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Make sure the cursor cannot go out of bounds
|
||||||
|
if cursor_pos < 1 then
|
||||||
|
cursor_pos = 1
|
||||||
|
elseif cursor_pos > #self._private.text + 1 then
|
||||||
|
cursor_pos = #self._private.text + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Update cycle
|
||||||
|
self.text = text_with_cursor(self:get_text(), cursor_pos, self)
|
||||||
|
|
||||||
|
-- using self:emit_signal... results in nil tables beeing send
|
||||||
|
awesome.emit_signal("inputbox::key_pressed", mod_keys, key)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function inputbox.new(args)
|
||||||
|
args = args or {}
|
||||||
|
|
||||||
|
local w = wibox.widget.textbox(args.text or "")
|
||||||
|
|
||||||
|
gtable.crush(w, inputbox, true)
|
||||||
|
|
||||||
|
w:buttons(
|
||||||
|
gtable.join {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
w:focus()
|
||||||
|
end),
|
||||||
|
abutton({}, 3, function()
|
||||||
|
-- TODO: Figure out how to paste with highlighted support
|
||||||
|
-- Maybe with a signal?
|
||||||
|
end)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Change the cursor to "xterm" on hover over
|
||||||
|
local old_cursor, old_wibox
|
||||||
|
w:connect_signal(
|
||||||
|
"mouse::enter",
|
||||||
|
function()
|
||||||
|
local wid = capi.mouse.current_wibox
|
||||||
|
if wid then
|
||||||
|
old_cursor, old_wibox = wid.cursor, wid
|
||||||
|
wid.cursor = "xterm"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Change the cursor back once leaving the widget
|
||||||
|
w:connect_signal(
|
||||||
|
"mouse::leave",
|
||||||
|
function()
|
||||||
|
old_wibox.cursor = old_cursor
|
||||||
|
old_wibox = nil
|
||||||
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
w.text = text_with_cursor("", 1, w)
|
||||||
|
|
||||||
|
|
||||||
|
return w
|
||||||
|
end
|
||||||
|
|
||||||
|
function inputbox.mt:__call(...)
|
||||||
|
return inputbox.new(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(inputbox, inputbox.mt)
|
||||||
|
|
||||||
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
@@ -1,282 +0,0 @@
|
|||||||
---------------------------------------------------------------------------
|
|
||||||
-- A widget to write text in
|
|
||||||
--@DOC_wibox_widget_defaults_inputtextbox_EXAMPLE@
|
|
||||||
--
|
|
||||||
-- @author Rene Kievits
|
|
||||||
-- @copyright 2022, Rene Kievits
|
|
||||||
-- @widgetmod wibox.widget.inputtextbox
|
|
||||||
-- @supermodule wibox.widget.base
|
|
||||||
---------------------------------------------------------------------------
|
|
||||||
|
|
||||||
local base = require("wibox.widget.base")
|
|
||||||
local gdebug = require("gears.debug")
|
|
||||||
local gfs = require("gears.filesystem")
|
|
||||||
local gobject = require("gears.object")
|
|
||||||
local gstring = require("gears.string")
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local keygrabber = require("awful.keygrabber")
|
|
||||||
local lgi = require("lgi")
|
|
||||||
local gtable = require("gears.table")
|
|
||||||
local wibox = require("wibox")
|
|
||||||
local setmetatable = setmetatable
|
|
||||||
|
|
||||||
local inputtextbox = { mt = {} }
|
|
||||||
|
|
||||||
--Private data
|
|
||||||
local data = {}
|
|
||||||
data.history = {}
|
|
||||||
|
|
||||||
local search_term = nil
|
|
||||||
local function itera(inc, a, i)
|
|
||||||
i = i + inc
|
|
||||||
local v = a[i]
|
|
||||||
if v then return i, v end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Load history file in history table
|
|
||||||
-- @param id The data.history identifier which is the path to the filename.
|
|
||||||
-- @param[opt] max The maximum number of entried in file.
|
|
||||||
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
|
|
||||||
|
|
||||||
for line in f:lines() do
|
|
||||||
if gtable.hasitem(data.histroy[id].table, line) then
|
|
||||||
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
|
|
||||||
|
|
||||||
--- Save history table in history file
|
|
||||||
-- @param id The data.history identifier
|
|
||||||
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
|
|
||||||
|
|
||||||
--- Return the number of items in history table regarding the id
|
|
||||||
-- @param id The data.history identifier
|
|
||||||
-- @return the number of items in history table, -1 if history is disabled
|
|
||||||
local function history_items(id)
|
|
||||||
if data.history[id] then
|
|
||||||
return #data.history[id].table
|
|
||||||
else
|
|
||||||
return -1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Add an entry to the history file
|
|
||||||
-- @param id The data.history identifier
|
|
||||||
-- @param command The command to add
|
|
||||||
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 text_with_cursor(args)
|
|
||||||
local char, spacer, text_start, text_end, ret
|
|
||||||
local text = args.text or ""
|
|
||||||
local hint = args.hint or ""
|
|
||||||
local cursor = args.cursor or ""
|
|
||||||
local indicator = args.indicator or "|"
|
|
||||||
|
|
||||||
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 + offset + 1))
|
|
||||||
end
|
|
||||||
|
|
||||||
if args.highlighter then
|
|
||||||
text_start, text_end = args.highlighter(text_start, text_end)
|
|
||||||
end
|
|
||||||
|
|
||||||
if #text == 0 then
|
|
||||||
ret = hint .. spacer
|
|
||||||
else
|
|
||||||
ret = text_start .. indicator .. text_end .. spacer
|
|
||||||
end
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
local function update(self)
|
|
||||||
self.textbox:set_font(self.font)
|
|
||||||
self.textbox:set_markup(text_with_cursor {
|
|
||||||
text = self.text,
|
|
||||||
hint = self.hint,
|
|
||||||
cursor = self.cursor,
|
|
||||||
cursor_pos = self.cursor_pos,
|
|
||||||
select_all = self.select_all,
|
|
||||||
indicator = self.indicator,
|
|
||||||
highlighter = self.highlighter,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
function inputtextbox:start()
|
|
||||||
self.textbox:set_font(self.font)
|
|
||||||
self.textbox:set_markup(text_with_cursor {
|
|
||||||
text = self.text,
|
|
||||||
hint = self.hint,
|
|
||||||
cursor = self.cursor,
|
|
||||||
cursor_pos = self.cursor_pos,
|
|
||||||
select_all = self.select_all,
|
|
||||||
indicator = self.indicator,
|
|
||||||
highlighter = self.highlighter,
|
|
||||||
})
|
|
||||||
|
|
||||||
self._private.grabber = keygrabber.run(
|
|
||||||
function(modifierts, key, event)
|
|
||||||
local mod = {}
|
|
||||||
for _, v in ipairs(modifierts) do mod[v] = true 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")) then
|
|
||||||
--callback
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function inputtextbox:stop()
|
|
||||||
keygrabber.stop(self._private.grabber)
|
|
||||||
history_save(self.history_path)
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Create a new inputtextbox
|
|
||||||
--
|
|
||||||
-- @tparam[opt=""] string text The hint text when there is no input
|
|
||||||
-- @treturn table A new inputtextbox widget
|
|
||||||
-- @constructorfct wibox.widget.inputtextbox
|
|
||||||
local function new(args)
|
|
||||||
args = args or {}
|
|
||||||
|
|
||||||
args.callback = args.callback or nil
|
|
||||||
args.hint = args.hint or ""
|
|
||||||
args.font = args.font or beautiful.inputtextbox_font or beautiful.font
|
|
||||||
args.bg = args.bg or beautiful.inputtextbox_bg or beautiful.bg_normal
|
|
||||||
args.fg_hint = args.fg_hint or beautiful.inputtextbox_fg_hint or beautiful.fg_normal or "#888888"
|
|
||||||
args.fg = args.fg or beautiful.inputtextbox_fg or beautiful.fg_normal
|
|
||||||
args.cursor = args.cursor or "fleur"
|
|
||||||
args.select_all = args.select_all or false
|
|
||||||
args.highlighter = args.highlighter or nil
|
|
||||||
|
|
||||||
local textbox = wibox.widget.textbox()
|
|
||||||
textbox:set_text(args.hint or "")
|
|
||||||
--textbox:set_fg(args.fg_hint or beautiful.fg_hint or "#888888")
|
|
||||||
--textbox:set_bg(args.bg_normal or beautiful.bg_normal or "#212121")
|
|
||||||
|
|
||||||
local ret = gobject({})
|
|
||||||
ret._private = {}
|
|
||||||
gtable.crush(ret, inputtextbox)
|
|
||||||
gtable.crush(ret, args)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function inputtextbox.mt.__call(...)
|
|
||||||
return new(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(inputtextbox, inputtextbox.mt)
|
|
||||||
|
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
|
||||||