Files
crylia-theme/awesome/src/modules/network_controller/init.lua
2022-12-11 17:30:18 +01:00

439 lines
14 KiB
Lua

------------------------------------
-- This is the network controller --
------------------------------------
-- Awesome Libs
local awful = require("awful")
local dbus_proxy = require("src.lib.lua-dbus_proxy.src.dbus_proxy")
local dpi = require("beautiful").xresources.apply_dpi
local gtable = require("gears").table
local gtimer = require("gears").timer
local gshape = require("gears").shape
local gcolor = require("gears").color
local gears = require("gears")
local lgi = require("lgi")
local wibox = require("wibox")
local NM = require("lgi").NM
local base = require("wibox.widget.base")
local rubato = require("src.lib.rubato")
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 network = { mt = {} }
network.NMState = {
UNKNOWN = 0,
ASLEEP = 10,
DISCONNECTED = 20,
DISCONNECTING = 30,
CONNECTING = 40,
CONNECTED_LOCAL = 50,
CONNECTED_SITE = 60,
CONNECTED_GLOBAL = 70,
}
network.DeviceType = {
ETHERNET = 1,
WIFI = 2
}
network.DeviceState = {
UNKNOWN = 0,
UNMANAGED = 10,
UNAVAILABLE = 20,
DISCONNECTED = 30,
PREPARE = 40,
CONFIG = 50,
NEED_AUTH = 60,
IP_CONFIG = 70,
IP_CHECK = 80,
SECONDARIES = 90,
ACTIVATED = 100,
DEACTIVATING = 110,
FAILED = 120
}
function network:get_wifi_proxy()
local devices = self._private.NetworkManager:GetDevices()
if (not devices) or (#devices == 0) then return end
for _, path in ipairs(devices) do
local NetworkManagerDevice = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.Device",
path = path
}
if NetworkManagerDevice.DeviceType == network.DeviceType.WIFI then
self._private.NetworkManagerDevice = NetworkManagerDevice
self._private.NetworkManagerDeviceWireless = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.Device.Wireless",
path = path
}
self._private.NetworkManagerDevice:connect_signal(function(proxy, new_state, old_state, reason)
local NetworkManagerAccessPoint = 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(NetworkManagerAccessPoint.HwAddress) .. "::state", new_state, old_state)
if new_state == network.DeviceState.ACTIVATED then
local ssid = NM.utils_ssid_to_utf8(NetworkManagerAccessPoint.Ssid)
self:emit_signal("NM::AccessPointConnected", ssid, NetworkManagerAccessPoint.Strength)
print("AP Connected: ", ssid, NetworkManagerAccessPoint.Strength)
end
end, "StateChanged")
end
end
end
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
---Scan for access points and create a widget for each one.
function network:scan_access_points()
if not self._private.NetworkManagerDeviceWireless then return end
local ap_list = self:get_children_by_id("wifi_ap_list")[1]
ap_list:reset()
self._private.NetworkManagerDeviceWireless:RequestScanAsync(function(proxy, context, success, failure)
if failure then
return
end
-- Get every access point even those who hide their ssid
for _, ap in ipairs(self._private.NetworkManagerDeviceWireless:GetAllAccessPoints()) do
-- Create a new proxy for every ap
local NetworkManagerAccessPoint = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.NetworkManager.AccessPoint",
path = ap
}
-- We are only interested in those with a ssid
if NetworkManagerAccessPoint.Ssid then
ap_list:add(access_point {
NetworkManagerAccessPoint = NetworkManagerAccessPoint,
NetworkManagerDevice = self._private.NetworkManagerDevice,
NetworkManagerSettings = self._private.NetworkManagerSettings,
NetworkManager = self._private.NetworkManager,
NetworkManagerDeviceWireless = self._private.NetworkManagerDeviceWireless
})
end
end
table.sort(ap_list, function(a, b)
return a.NetworkManagerAccessPoint.Strength > b.NetworkManagerAccessPoint.Strength
end)
end, { call_id = "my-id" }, {})
end
function network:is_ap_active(ap)
return ap.path == self._private.NetworkManagerDeviceWireless.ActiveAccessPoint
end
---Toggles networking on or off
function network:toggle_wifi()
local enable = not self._private.NetworkManager.WirelessEnabled
if enable then
self._private.NetworkManager.Enable(true)
end
self._private.NetworkManager:Set("org.freedesktop.NetworkManager", "WirelessEnabled", lgi.GLib.Variant("b", enable))
self._private.NetworkManager.WirelessEnabled = { signature = "b", value = enable }
end
function network.new(args)
args = args or {}
local ret = base.make_widget_from_value(wibox.widget {
{
{
{
{
{
{
{
{
resize = false,
image = gcolor.recolor_image(icondir .. "menu-down.svg",
Theme_config.network_manager.wifi_icon_color),
widget = wibox.widget.imagebox,
valign = "center",
halign = "center",
id = "icon"
},
id = "center",
halign = "center",
valign = "center",
widget = wibox.container.place,
},
{
{
text = "Wifi Networks",
widget = wibox.widget.textbox,
id = "ap_name"
},
margins = dpi(5),
widget = wibox.container.margin
},
id = "wifi",
layout = wibox.layout.fixed.horizontal
},
id = "wifi_bg",
bg = Theme_config.network_manager.wifi_bg,
fg = Theme_config.network_manager.wifi_fg,
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(4))
end,
widget = wibox.container.background
},
id = "wifi_margin",
widget = wibox.container.margin
},
{
id = "wifi_list",
{
{
step = dpi(50),
spacing = dpi(10),
layout = require("src.lib.overflow_widget.overflow").vertical,
scrollbar_width = 0,
id = "wifi_ap_list"
},
id = "margin",
margins = dpi(10),
widget = wibox.container.margin
},
border_color = Theme_config.network_manager.ap_border_color,
border_width = Theme_config.network_manager.ap_border_width,
shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, false, false, true, true, dpi(4))
end,
widget = wibox.container.background,
forced_height = 0
},
{
{ -- 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
{
{
image = gcolor.recolor_image(icondir .. "refresh.svg",
Theme_config.network_manager.refresh_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 = "refresh"
},
layout = wibox.layout.align.horizontal
},
widget = wibox.container.margin,
top = dpi(10),
id = "action_buttons"
},
id = "layout1",
layout = wibox.layout.fixed.vertical
},
id = "margin",
margins = dpi(15),
widget = wibox.container.margin
},
shape = function(cr, width, height)
gshape.rounded_rect(cr, width, height, dpi(8))
end,
border_color = Theme_config.network_manager.border_color,
border_width = Theme_config.network_manager.border_width,
bg = Theme_config.network_manager.bg,
id = "background",
widget = wibox.container.background
},
width = dpi(400),
strategy = "exact",
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",
}
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",
}
ret._private.NetworkManagerProperties = dbus_proxy.Proxy:new {
bus = dbus_proxy.Bus.SYSTEM,
name = "org.freedesktop.NetworkManager",
interface = "org.freedesktop.DBus.Properties",
path = "/org/freedesktop/NetworkManager",
}
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()
end
}
end
end
end, "PropertiesChanged")
ret:get_wifi_proxy()
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) ]]
--#endregion
--#region Dropdown logic
local wifi_margin = ret:get_children_by_id("wifi_margin")[1]
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 {
duration = 0.2,
pos = wifi_list.forced_height,
easing = rubato.linear,
subscribed = function(v)
wifi_list.forced_height = v
end
}
wifi_margin:buttons(gtable.join(
awful.button({}, 1, nil,
function()
if wifi_list.forced_height == 0 then
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
rubato_timer.target = dpi(size)
wifi_margin.wifi_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
end
wifi.icon:set_image(gcolor.recolor_image(icondir .. "menu-up.svg",
Theme_config.network_manager.wifi_icon_color))
else
rubato_timer.target = 0
wifi_margin.wifi_bg.shape = function(cr, width, height)
gshape.partially_rounded_rect(cr, width, height, true, true, true, true, dpi(4))
end
wifi.icon:set_image(gcolor.recolor_image(icondir .. "menu-down.svg",
Theme_config.network_manager.wifi_icon_color))
end
end
)
))
--#endregion
local refresh_button = ret:get_children_by_id("refresh")[1]
refresh_button:buttons(gtable.join(
awful.button({}, 1, nil,
function()
ret:scan_access_points()
end
)
))
Hover_signal(refresh_button)
return ret
end
function network.mt:__call(...)
return network.new(...)
end
return setmetatable(network, network.mt)