515 lines
17 KiB
Lua
515 lines
17 KiB
Lua
--------------------------------------
|
|
-- 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, Theme_config.bluetooth_controller.device_bg_hover,
|
|
Theme_config.bluetooth_controller.device_fg_hover)
|
|
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
|