rewritten network module, not finished yet
This commit is contained in:
805
awesome/src/modules/network/init.lua
Normal file
805
awesome/src/modules/network/init.lua
Normal file
@@ -0,0 +1,805 @@
|
|||||||
|
local setmetatable = setmetatable
|
||||||
|
local table = table
|
||||||
|
local pairs = pairs
|
||||||
|
local ipairs = ipairs
|
||||||
|
|
||||||
|
local base = require('wibox.widget.base')
|
||||||
|
local beautiful = require('beautiful')
|
||||||
|
local dpi = beautiful.xresources.apply_dpi
|
||||||
|
local gcolor = require('gears.color')
|
||||||
|
local gfilesystem = require('gears.filesystem')
|
||||||
|
local gshape = require('gears.shape')
|
||||||
|
local wibox = require('wibox')
|
||||||
|
local gtable = require('gears.table')
|
||||||
|
local abutton = require('awful.button')
|
||||||
|
local apopup = require('awful.popup')
|
||||||
|
local aplacement = require('awful.placement')
|
||||||
|
|
||||||
|
local rubato = require('src.lib.rubato')
|
||||||
|
|
||||||
|
local dnd_widget = require('awful.widget.toggle_widget')
|
||||||
|
local networkManager = require('src.tools.network')()
|
||||||
|
local inputbox = require('src.modules.inputbox')
|
||||||
|
local context_menu = require('src.modules.context_menu')
|
||||||
|
|
||||||
|
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/network/'
|
||||||
|
|
||||||
|
local capi = {
|
||||||
|
mouse = mouse,
|
||||||
|
}
|
||||||
|
|
||||||
|
local network = {}
|
||||||
|
|
||||||
|
--- Called when a connection does not exist yet and the user needs to ender a password
|
||||||
|
--- And Autoconnect or not.
|
||||||
|
---@param ap AccessPoint The access point to connect to
|
||||||
|
---@param callback function The callback to call when the conenct button is pressed
|
||||||
|
function network:open_connection_form(ap, callback)
|
||||||
|
if self.form_popup then
|
||||||
|
self.form_popup.visible = false
|
||||||
|
end
|
||||||
|
--Password inputbox
|
||||||
|
local password = inputbox {
|
||||||
|
mouse_focus = true,
|
||||||
|
text = 'testtext',
|
||||||
|
}
|
||||||
|
|
||||||
|
--New form widget
|
||||||
|
local w = base.make_widget_from_value {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{ -- Header
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
{ -- SSID
|
||||||
|
{
|
||||||
|
widget = wibox.widget.textbox,
|
||||||
|
text = ap.SSID,
|
||||||
|
halign = 'center',
|
||||||
|
valign = 'center',
|
||||||
|
},
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
margins = dpi(5),
|
||||||
|
},
|
||||||
|
{ -- Close button
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
image = gcolor.recolor_image(icondir .. 'close.svg', beautiful.colorscheme.bg),
|
||||||
|
resize = true,
|
||||||
|
valign = 'center',
|
||||||
|
halign = 'center',
|
||||||
|
},
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
margins = dpi(5),
|
||||||
|
},
|
||||||
|
widget = wibox.container.background,
|
||||||
|
id = 'close_button',
|
||||||
|
bg = beautiful.colorscheme.bg_red,
|
||||||
|
shape = beautiful.shape[8],
|
||||||
|
},
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
width = dpi(30),
|
||||||
|
height = dpi(30),
|
||||||
|
strategy = 'exact',
|
||||||
|
},
|
||||||
|
layout = wibox.layout.align.horizontal,
|
||||||
|
},
|
||||||
|
widget = wibox.container.background,
|
||||||
|
fg = beautiful.colorscheme.bg_red,
|
||||||
|
},
|
||||||
|
{ -- Form
|
||||||
|
{ -- Password text
|
||||||
|
widget = wibox.widget.textbox,
|
||||||
|
text = 'Password',
|
||||||
|
halign = 'center',
|
||||||
|
valign = 'center',
|
||||||
|
},
|
||||||
|
{ -- Spacing
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
left = dpi(20),
|
||||||
|
right = dpi(20),
|
||||||
|
},
|
||||||
|
{ -- Passwort inputbox
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
password.widget,
|
||||||
|
step = dpi(50),
|
||||||
|
scrollbar_width = 0,
|
||||||
|
id = 'scroll',
|
||||||
|
layout = require('src.lib.overflow_widget.overflow').horizontal,
|
||||||
|
},
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
left = dpi(5),
|
||||||
|
right = dpi(5),
|
||||||
|
},
|
||||||
|
widget = wibox.container.place,
|
||||||
|
halign = 'left',
|
||||||
|
},
|
||||||
|
widget = wibox.container.background,
|
||||||
|
bg = beautiful.colorscheme.bg,
|
||||||
|
fg = beautiful.colorscheme.fg,
|
||||||
|
border_color = beautiful.colorscheme.border_color,
|
||||||
|
border_width = dpi(2),
|
||||||
|
shape = beautiful.shape[8],
|
||||||
|
id = 'password_container',
|
||||||
|
},
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
strategy = 'exact',
|
||||||
|
width = dpi(300),
|
||||||
|
height = dpi(50),
|
||||||
|
},
|
||||||
|
layout = wibox.layout.align.horizontal,
|
||||||
|
},
|
||||||
|
{ -- Actions
|
||||||
|
{ -- Auto Connect
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
checked = false,
|
||||||
|
shape = beautiful.shape[4],
|
||||||
|
color = beautiful.colorscheme.bg,
|
||||||
|
paddings = dpi(3),
|
||||||
|
check_color = beautiful.colorscheme.bg_red,
|
||||||
|
border_color = beautiful.colorscheme.bg_red,
|
||||||
|
border_width = dpi(2),
|
||||||
|
id = 'checkbox',
|
||||||
|
widget = wibox.widget.checkbox,
|
||||||
|
},
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
strategy = 'exact',
|
||||||
|
width = dpi(30),
|
||||||
|
height = dpi(30),
|
||||||
|
},
|
||||||
|
widget = wibox.container.place,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
widget = wibox.widget.textbox,
|
||||||
|
text = 'Auto connect',
|
||||||
|
halign = 'center',
|
||||||
|
valign = 'center',
|
||||||
|
},
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
spacing = dpi(10),
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
{ -- Connect
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
widget = wibox.widget.textbox,
|
||||||
|
text = 'Connect',
|
||||||
|
valign = 'center',
|
||||||
|
halign = 'center',
|
||||||
|
},
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
margins = dpi(10),
|
||||||
|
},
|
||||||
|
widget = wibox.container.background,
|
||||||
|
bg = beautiful.colorscheme.bg_blue,
|
||||||
|
fg = beautiful.colorscheme.bg,
|
||||||
|
shape = beautiful.shape[8],
|
||||||
|
id = 'connect_button',
|
||||||
|
},
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
margins = dpi(10),
|
||||||
|
},
|
||||||
|
layout = wibox.layout.align.horizontal,
|
||||||
|
},
|
||||||
|
layout = wibox.layout.fixed.vertical,
|
||||||
|
spacing = dpi(20),
|
||||||
|
},
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
margins = dpi(10),
|
||||||
|
},
|
||||||
|
bg = beautiful.colorscheme.bg,
|
||||||
|
fg = beautiful.colorscheme.fg,
|
||||||
|
widget = wibox.container.background,
|
||||||
|
},
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
strategy = 'max',
|
||||||
|
height = dpi(400),
|
||||||
|
width = dpi(600),
|
||||||
|
buttons = gtable.join {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
password:unfocus()
|
||||||
|
end),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Popup for the form
|
||||||
|
self.form_popup = apopup {
|
||||||
|
widget = w,
|
||||||
|
visible = true,
|
||||||
|
type = 'dialog',
|
||||||
|
screen = capi.mouse.screen,
|
||||||
|
border_color = beautiful.colorscheme.border_color,
|
||||||
|
border_width = dpi(2),
|
||||||
|
ontop = true,
|
||||||
|
placement = aplacement.centered,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Automatically scroll to the right when typing to keep the password visible
|
||||||
|
local scroll_layout = w:get_children_by_id('scroll')[1]
|
||||||
|
password:connect_signal('inputbox::keypressed', function(_, m, k)
|
||||||
|
scroll_layout:set_scroll_factor(1)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Connect button pressed when the user is done typing and ready to connect
|
||||||
|
--TODO: Don't just close the form, try to connect first and check if the password is correct or not
|
||||||
|
local connect_button = w:get_children_by_id('connect_button')[1]
|
||||||
|
connect_button:buttons(gtable.join {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
local res = {
|
||||||
|
autoconnect = w:get_children_by_id('checkbox')[1].checked,
|
||||||
|
passwd = password:get_text(),
|
||||||
|
ssid = ap.SSID,
|
||||||
|
security = ap.Security,
|
||||||
|
}
|
||||||
|
|
||||||
|
password:unfocus()
|
||||||
|
|
||||||
|
networkManager:ConnectToAccessPointAsync(ap, self.device, networkManager.NetworkManagerSettings:NewConnectionProfile(res), function(succ)
|
||||||
|
if succ then
|
||||||
|
w = nil
|
||||||
|
self.form_popup.visible = false
|
||||||
|
else
|
||||||
|
--TODO: Add a little text under/above the password box and make it visible here telling the user that the password was
|
||||||
|
--TODO: wrong
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Autoconnect true/false
|
||||||
|
local checkbox = w:get_children_by_id('checkbox')[1]
|
||||||
|
checkbox:buttons(gtable.join {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
checkbox.checked = not checkbox.checked
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Close the form and do nothing
|
||||||
|
local close_button = w:get_children_by_id('close_button')[1]
|
||||||
|
close_button:buttons(gtable.join {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
password:unfocus()
|
||||||
|
w = nil
|
||||||
|
self.form_popup.visible = false
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Focus the inputbox when clicked
|
||||||
|
--TODO: Add some keys to the inputbox to make it possible to lose focus on enter/escape etc
|
||||||
|
local password_container = w:get_children_by_id('password_container')[1]
|
||||||
|
password_container:buttons(gtable.join {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
password:focus()
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
---Sort the wifi list by active access point first, then by strength descending
|
||||||
|
function network:resort_wifi_list()
|
||||||
|
local wifi_list = self:get_children_by_id('wifi_list')[1]
|
||||||
|
|
||||||
|
--Make sure that the active AP is always on top, there is only one active AP
|
||||||
|
table.sort(wifi_list.children, function(a, b)
|
||||||
|
if self.device:IsApActive(a) then
|
||||||
|
return true
|
||||||
|
elseif self.device:IsApActive(b) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return a.Strength > b.Strength
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
---If an Access Point is lost then remove it from the list
|
||||||
|
---@param ap AccessPoint Lost AP
|
||||||
|
---@return boolean deleted
|
||||||
|
function network:delete_ap_from_list(ap)
|
||||||
|
local wifi_list = self:get_children_by_id('wifi_list')[1]
|
||||||
|
for i, w in ipairs(wifi_list.children) do
|
||||||
|
if w.object_path == ap then
|
||||||
|
table.remove(wifi_list.children, i)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---If an access point needs to be added to the list
|
||||||
|
---@param ap AccessPoint
|
||||||
|
function network:add_ap_to_list(ap)
|
||||||
|
if not ap then return end
|
||||||
|
local wifi_list = self:get_children_by_id('wifi_list')[1]
|
||||||
|
local fg, bg
|
||||||
|
|
||||||
|
if self.device:IsApActive(ap) then
|
||||||
|
fg = beautiful.colorscheme.bg
|
||||||
|
bg = beautiful.colorscheme.bg_red
|
||||||
|
else
|
||||||
|
fg = beautiful.colorscheme.bg_red
|
||||||
|
bg = beautiful.colorscheme.bg
|
||||||
|
end
|
||||||
|
|
||||||
|
-- New AP widget
|
||||||
|
local w = base.make_widget_from_value {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
id = 'icon_role',
|
||||||
|
image = gcolor.recolor_image(icondir .. 'wifi-strength-1.svg', fg),
|
||||||
|
resize = true,
|
||||||
|
valign = 'center',
|
||||||
|
halign = 'center',
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
},
|
||||||
|
strategy = 'max',
|
||||||
|
width = dpi(24),
|
||||||
|
height = dpi(24),
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
text = ap.SSID,
|
||||||
|
widget = wibox.widget.textbox,
|
||||||
|
},
|
||||||
|
strategy = 'exact',
|
||||||
|
width = dpi(300),
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
},
|
||||||
|
width = dpi(260),
|
||||||
|
height = dpi(40),
|
||||||
|
strategy = 'max',
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
},
|
||||||
|
spacing = dpi(10),
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
},
|
||||||
|
{ -- Spacing
|
||||||
|
width = dpi(10),
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
resize = false,
|
||||||
|
id = 'con_icon',
|
||||||
|
image = gcolor.recolor_image(icondir .. 'link-off.svg', fg),
|
||||||
|
valign = 'center',
|
||||||
|
halign = 'center',
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
},
|
||||||
|
strategy = 'max',
|
||||||
|
height = dpi(24),
|
||||||
|
width = dpi(24),
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
},
|
||||||
|
margins = dpi(5),
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
},
|
||||||
|
layout = wibox.layout.align.horizontal,
|
||||||
|
},
|
||||||
|
margins = dpi(5),
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
},
|
||||||
|
shape = beautiful.shape[4],
|
||||||
|
bg = bg,
|
||||||
|
fg = fg,
|
||||||
|
border_color = beautiful.colorscheme.border_color,
|
||||||
|
border_width = dpi(2),
|
||||||
|
widget = wibox.container.background,
|
||||||
|
Strength = ap.Strength,
|
||||||
|
object_path = ap.object_path,
|
||||||
|
}
|
||||||
|
|
||||||
|
local icon = w:get_children_by_id('icon_role')[1]
|
||||||
|
local con_icon = w:get_children_by_id('con_icon')[1]
|
||||||
|
|
||||||
|
-- Update the strength icon and resort the list afterwards
|
||||||
|
ap:connect_signal('NetworkManagerAccessPoint::Strength', function(_, strength)
|
||||||
|
local s
|
||||||
|
if strength >= 80 then
|
||||||
|
s = 5
|
||||||
|
elseif strength >= 60 and strength < 80 then
|
||||||
|
s = 4
|
||||||
|
elseif strength >= 40 and strength < 60 then
|
||||||
|
s = 3
|
||||||
|
elseif strength >= 20 and strength < 40 then
|
||||||
|
s = 2
|
||||||
|
else
|
||||||
|
s = 1
|
||||||
|
end
|
||||||
|
w.Strength = strength
|
||||||
|
icon.image = gcolor.recolor_image(icondir .. 'wifi-strength-' .. s .. '.svg', fg)
|
||||||
|
|
||||||
|
self:resort_wifi_list()
|
||||||
|
end)
|
||||||
|
-- Manually fire once to set the icon, as some AP's need a few seconds to update
|
||||||
|
ap:emit_signal('NetworkManagerAccessPoint::Strength', ap.Strength)
|
||||||
|
|
||||||
|
-- Update the active connection, and the old one (color and icon change)
|
||||||
|
self.device:connect_signal('NetworkManagerDeviceWireless::ActiveAccessPoint', function(_, old_ap, new_ap)
|
||||||
|
local function active_ap_signal(_, strength)
|
||||||
|
self:emit_signal('ActiveAccessPointStrength', strength)
|
||||||
|
--!Why does the above signal not work outside of this module?
|
||||||
|
--This is a workaournd until I foundout why it doesn't work
|
||||||
|
awesome.emit_signal('ActiveAccessPointStrength', strength)
|
||||||
|
end
|
||||||
|
|
||||||
|
if old_ap == ap.object_path then
|
||||||
|
w.bg = beautiful.colorscheme.bg
|
||||||
|
w.fg = beautiful.colorscheme.bg_red
|
||||||
|
bg = beautiful.colorscheme.bg
|
||||||
|
fg = beautiful.colorscheme.bg_red
|
||||||
|
con_icon.image = gcolor.recolor_image(icondir .. 'link-off.svg', fg)
|
||||||
|
icon.image = gcolor.recolor_image(icondir .. 'wifi-strength-1.svg', fg)
|
||||||
|
ap:disconnect_signal('NetworkManagerAccessPoint::Strength', active_ap_signal)
|
||||||
|
end
|
||||||
|
if new_ap == ap.object_path then
|
||||||
|
w.bg = beautiful.colorscheme.bg_red
|
||||||
|
w.fg = beautiful.colorscheme.bg
|
||||||
|
fg = beautiful.colorscheme.bg
|
||||||
|
bg = beautiful.colorscheme.bg_red
|
||||||
|
con_icon.image = gcolor.recolor_image(icondir .. 'link.svg', fg)
|
||||||
|
icon.image = gcolor.recolor_image(icondir .. 'wifi-strength-1.svg', fg)
|
||||||
|
ap:connect_signal('NetworkManagerAccessPoint::Strength', active_ap_signal)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
-- Again manually update
|
||||||
|
self.device:emit_signal('NetworkManagerDeviceWireless::ActiveAccessPoint', nil, self.device.NetworkManagerDeviceWireless.ActiveAccessPoint)
|
||||||
|
|
||||||
|
-- Context menu for connecting, disconnecting, etc.
|
||||||
|
--TODO: Needs to update its entries when the active AP changes to it has a disconnect button
|
||||||
|
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 = self.device:IsApActive(ap) and 'Disconnect' or 'Connect',
|
||||||
|
icon = self.device:IsApActive(ap) and gcolor.recolor_image(icondir .. 'link-off.svg', bg) or gcolor.recolor_image(icondir .. 'link.svg', fg),
|
||||||
|
callback = function()
|
||||||
|
if self.device:IsApActive(ap) then
|
||||||
|
networkManager:DisconnectFromAP();
|
||||||
|
else
|
||||||
|
networkManager:ConnectToAccessPointAsync(ap, self.device, nil, function(res)
|
||||||
|
if not res then
|
||||||
|
self:open_connection_form(ap, function(res)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name = 'Remove connection',
|
||||||
|
icon = gcolor.recolor_image(icondir .. 'delete.svg', bg),
|
||||||
|
callback = function()
|
||||||
|
for path, value in pairs(networkManager.NetworkManagerSettings.ConnectionList or {}) do
|
||||||
|
if ap.SSID == value:GetSettings().connection.id then
|
||||||
|
networkManager.NetworkManagerSettings:RemoveConnection(value)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Hide context menu on leave
|
||||||
|
cm:connect_signal('mouse::leave', function()
|
||||||
|
cm.visible = false
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Left click should try to connect/disconnect to AP
|
||||||
|
--TODO: Check if active ap is clicked and try to disconnect, instead of trying to reconnect to the same AP
|
||||||
|
-- Right click toggles the context menu
|
||||||
|
w:buttons(gtable.join {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
networkManager:ConnectToAccessPointAsync(ap, self.device, nil, function(res)
|
||||||
|
if not res then
|
||||||
|
self:open_connection_form(ap, function(res)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end),
|
||||||
|
abutton({}, 3, function()
|
||||||
|
cm:toggle()
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
|
-- Add ap into table
|
||||||
|
table.insert(wifi_list.children, w)
|
||||||
|
|
||||||
|
-- Resort after adding the new AP
|
||||||
|
self:resort_wifi_list()
|
||||||
|
end
|
||||||
|
|
||||||
|
---Check if an AP is already in the list by comparing its object path
|
||||||
|
---@param ap AccessPoint
|
||||||
|
---@return boolean inlist Is in list or not
|
||||||
|
function network:is_ap_in_list(ap)
|
||||||
|
if not ap then return false end
|
||||||
|
local wifi_list = self:get_children_by_id('wifi_list')[1]
|
||||||
|
for _, w in ipairs(wifi_list.children) do
|
||||||
|
if w.object_path == ap.object_path then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---Add the list to the widget hierarchy, and clears the previous entries
|
||||||
|
---Usually used when the user requests a new scan
|
||||||
|
---@param ap_list table<ap_list>
|
||||||
|
function network:set_wifi_list(ap_list)
|
||||||
|
if not ap_list or #ap_list < 1 then return end
|
||||||
|
local wifi_list = self:get_children_by_id('wifi_list')[1]
|
||||||
|
wifi_list:reset()
|
||||||
|
|
||||||
|
for _, ap in ipairs(ap_list) do
|
||||||
|
self:add_ap_to_list(ap)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(network, {
|
||||||
|
__call = function(self)
|
||||||
|
|
||||||
|
local dnd = dnd_widget {
|
||||||
|
color = beautiful.colorscheme.bg_red,
|
||||||
|
size = dpi(40),
|
||||||
|
}
|
||||||
|
|
||||||
|
local w = base.make_widget_from_value {
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
resize = false,
|
||||||
|
id = 'wifi_icon',
|
||||||
|
image = gcolor.recolor_image(icondir .. 'menu-down.svg', beautiful.colorscheme.bg_red),
|
||||||
|
},
|
||||||
|
widget = wibox.container.place,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{
|
||||||
|
text = 'Wifi Networks',
|
||||||
|
widget = wibox.widget.textbox,
|
||||||
|
},
|
||||||
|
margins = dpi(5),
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
},
|
||||||
|
layout = wibox.layout.fixed.horizontal,
|
||||||
|
},
|
||||||
|
id = 'wifi_list_bar',
|
||||||
|
bg = beautiful.colorscheme.bg1,
|
||||||
|
fg = beautiful.colorscheme.bg_red,
|
||||||
|
shape = beautiful.shape[4],
|
||||||
|
widget = wibox.container.background,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
step = dpi(50),
|
||||||
|
spacing = dpi(10),
|
||||||
|
scrollbar_width = 0,
|
||||||
|
id = 'wifi_list',
|
||||||
|
layout = require('src.lib.overflow_widget.overflow').vertical,
|
||||||
|
},
|
||||||
|
margins = dpi(10),
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
},
|
||||||
|
border_color = beautiful.colorscheme.border_color,
|
||||||
|
border_width = dpi(2),
|
||||||
|
shape = function(cr, width, height)
|
||||||
|
gshape.partially_rounded_rect(cr, width, height, false, false, true, true, dpi(4))
|
||||||
|
end,
|
||||||
|
widget = wibox.container.background,
|
||||||
|
},
|
||||||
|
id = 'wifi_list_height',
|
||||||
|
strategy = 'exact',
|
||||||
|
height = 0,
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
dnd,
|
||||||
|
widget = wibox.container.place,
|
||||||
|
},
|
||||||
|
nil,
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
image = gcolor.recolor_image(icondir .. 'refresh.svg', beautiful.colorscheme.bg_red),
|
||||||
|
resize = false,
|
||||||
|
valign = 'center',
|
||||||
|
halign = 'center',
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
},
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
margins = dpi(5),
|
||||||
|
},
|
||||||
|
id = 'refresh_button',
|
||||||
|
border_color = beautiful.colorscheme.border_color,
|
||||||
|
border_width = dpi(2),
|
||||||
|
bg = beautiful.colorscheme.bg,
|
||||||
|
shape = beautiful.shape[4],
|
||||||
|
widget = wibox.container.background,
|
||||||
|
},
|
||||||
|
layout = wibox.layout.align.horizontal,
|
||||||
|
},
|
||||||
|
top = dpi(10),
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
},
|
||||||
|
layout = wibox.layout.fixed.vertical,
|
||||||
|
},
|
||||||
|
margins = dpi(15),
|
||||||
|
widget = wibox.container.margin,
|
||||||
|
},
|
||||||
|
shape = beautiful.shape[8],
|
||||||
|
border_color = beautiful.colorscheme.border_color,
|
||||||
|
bg = beautiful.colorscheme.bg,
|
||||||
|
border_width = dpi(2),
|
||||||
|
widget = wibox.container.background,
|
||||||
|
},
|
||||||
|
strategy = 'exact',
|
||||||
|
width = dpi(400),
|
||||||
|
widget = wibox.container.constraint,
|
||||||
|
}
|
||||||
|
gtable.crush(self, w)
|
||||||
|
|
||||||
|
--- Get the current wifi device.
|
||||||
|
---! In theory its not needed to update, why would the wifi card change? Needs validation.
|
||||||
|
self.device = networkManager:get_wireless_device()
|
||||||
|
|
||||||
|
local wifi_list = w:get_children_by_id('wifi_list')[1]
|
||||||
|
local wifi_list_height = w:get_children_by_id('wifi_list_height')[1]
|
||||||
|
local wifi_list_bar = w:get_children_by_id('wifi_list_bar')[1]
|
||||||
|
local wifi_icon = w:get_children_by_id('wifi_icon')[1]
|
||||||
|
|
||||||
|
-- Dropdown animation
|
||||||
|
local wifi_list_anim = rubato.timed {
|
||||||
|
duration = 0.2,
|
||||||
|
pos = wifi_list_height.height,
|
||||||
|
clamp_position = true,
|
||||||
|
rate = 24,
|
||||||
|
subscribed = function(v)
|
||||||
|
wifi_list_height.height = v
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Dropdown toggle
|
||||||
|
wifi_list_bar:buttons(gtable.join {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
if wifi_list_height.height == 0 then
|
||||||
|
local size = (wifi_list.children and #wifi_list.children or 0) * dpi(50)
|
||||||
|
if size > dpi(330) then
|
||||||
|
size = dpi(330)
|
||||||
|
end
|
||||||
|
wifi_list_anim.target = dpi(size)
|
||||||
|
wifi_list_bar.shape = function(cr, width, height)
|
||||||
|
gshape.partially_rounded_rect(cr, width, height, true, true, false, false, dpi(4))
|
||||||
|
end
|
||||||
|
if #wifi_list.children > 0 then
|
||||||
|
wifi_icon:set_image(gcolor.recolor_image(icondir .. 'menu-up.svg',
|
||||||
|
beautiful.colorscheme.bg_red))
|
||||||
|
else
|
||||||
|
wifi_icon:set_image(gcolor.recolor_image(icondir .. 'menu-down.svg',
|
||||||
|
beautiful.colorscheme.bg_red))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
wifi_list_anim.target = 0
|
||||||
|
wifi_list_bar.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',
|
||||||
|
beautiful.colorscheme.bg_red))
|
||||||
|
end
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
|
||||||
|
--- Manual rescan request, this gets all AP's and updates the list
|
||||||
|
local refresh_button = w:get_children_by_id('refresh_button')[1]
|
||||||
|
refresh_button:buttons(gtable.join {
|
||||||
|
abutton({}, 1, nil, function()
|
||||||
|
local wifi_device = networkManager:get_wireless_device()
|
||||||
|
if not wifi_device then return end
|
||||||
|
|
||||||
|
wifi_device:RequestScan(function(ap_list)
|
||||||
|
self:set_wifi_list(ap_list)
|
||||||
|
end)
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
do
|
||||||
|
local wifi_device = networkManager:get_wireless_device()
|
||||||
|
if not wifi_device then return end
|
||||||
|
|
||||||
|
wifi_device:RequestScan(function(ap_list)
|
||||||
|
self:set_wifi_list(ap_list)
|
||||||
|
end)
|
||||||
|
|
||||||
|
dnd:buttons(gtable.join {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
networkManager:toggle_wifi()
|
||||||
|
end),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Automatically toggle the Wifi toggle when the wifi state changed
|
||||||
|
networkManager:connect_signal('NetworkManager::WirelessEnabled', function(_, enabled)
|
||||||
|
if enabled then
|
||||||
|
dnd:set_enabled()
|
||||||
|
else
|
||||||
|
dnd:set_disabled()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
---TODO:Toggle a general network switch, where should the widget be added?
|
||||||
|
networkManager:connect_signal('NetworkManager::NetworkingEnabled', function(_, enabled)
|
||||||
|
--[[ if enabled then
|
||||||
|
dnd:set_enabled()
|
||||||
|
else
|
||||||
|
dnd:set_disabled()
|
||||||
|
end ]]
|
||||||
|
end)
|
||||||
|
--- Automatically delete a lost AP from the list
|
||||||
|
self.device:connect_signal('NetworkManagerDeviceWireless::AccessPointRemoved', function(_, ap)
|
||||||
|
self:delete_ap_from_list(ap)
|
||||||
|
end)
|
||||||
|
--- Automatically add a new AP to the list, if it is not already in the list
|
||||||
|
self.device:connect_signal('NetworkManagerDeviceWireless::AccessPointAdded', function(_, ap)
|
||||||
|
if not self:is_ap_in_list(ap) then
|
||||||
|
self:add_ap_to_list(ap)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
--- Automatically resort the list when the active AP changed
|
||||||
|
--- This is needed because otherwise the active AP would be where the new one currently is in the list
|
||||||
|
self.device:connect_signal('NetworkManagerDeviceWireless::ActiveAccessPoint', function()
|
||||||
|
self:resort_wifi_list()
|
||||||
|
end)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end,
|
||||||
|
})
|
||||||
@@ -1,377 +0,0 @@
|
|||||||
------------------------------------
|
|
||||||
-- This is the network controller --
|
|
||||||
------------------------------------
|
|
||||||
|
|
||||||
-- Awesome Libs
|
|
||||||
local abutton = require('awful.button')
|
|
||||||
local awidget = require('awful.widget')
|
|
||||||
local beautiful = require('beautiful')
|
|
||||||
local dpi = require('beautiful').xresources.apply_dpi
|
|
||||||
local gtable = require('gears').table
|
|
||||||
local gfilesystem = require('gears').filesystem
|
|
||||||
local gcolor = require('gears').color
|
|
||||||
local lgi = require('lgi')
|
|
||||||
local wibox = require('wibox')
|
|
||||||
local base = require('wibox.widget.base')
|
|
||||||
local NM = lgi.NM
|
|
||||||
|
|
||||||
-- Third party libs
|
|
||||||
local dbus_proxy = require('src.lib.lua-dbus_proxy.src.dbus_proxy')
|
|
||||||
|
|
||||||
-- Own libs
|
|
||||||
local ap_form = require('src.modules.network_controller.ap_form')
|
|
||||||
local cm = require('src.modules.context_menu')
|
|
||||||
local hover = require('src.tools.hover')
|
|
||||||
|
|
||||||
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/network/'
|
|
||||||
|
|
||||||
local access_point = { mt = {} }
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
function access_point:get_access_point_connections(ssid)
|
|
||||||
local cn = {}
|
|
||||||
|
|
||||||
local connections = self.NetworkManagerSettings:ListConnections()
|
|
||||||
for _, connection_path in ipairs(connections) do
|
|
||||||
local NetworkManagerSettingsConnection = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = 'org.freedesktop.NetworkManager',
|
|
||||||
interface = 'org.freedesktop.NetworkManager.Settings.Connection',
|
|
||||||
path = connection_path,
|
|
||||||
}
|
|
||||||
|
|
||||||
if NetworkManagerSettingsConnection.Filename:find(ssid) then
|
|
||||||
table.insert(cn, NetworkManagerSettingsConnection)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return cn
|
|
||||||
end
|
|
||||||
|
|
||||||
function access_point:create_profile(ap, password, auto_connect)
|
|
||||||
local s_wsec = {}
|
|
||||||
local security = flags_to_security(ap.Flags, ap.WpaFlags, ap.RsnFlags)
|
|
||||||
if security ~= '' then
|
|
||||||
if security:match('WPA') 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', 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', password)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return {
|
|
||||||
['connection'] = {
|
|
||||||
-- ["interface-name"] = lgi.GLib.Variant("s", ap.device_interface),
|
|
||||||
['uuid'] = lgi.GLib.Variant('s', string.gsub('xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', '[xy]', function(c)
|
|
||||||
local v = (c == 'x') and math.random(0, 0xf) or math.random(8, 0xb)
|
|
||||||
return string.format('%x', v)
|
|
||||||
end)),
|
|
||||||
['id'] = lgi.GLib.Variant('s', NM.utils_ssid_to_utf8(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,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function access_point:disconnect()
|
|
||||||
self.NetworkManager:DeactivateConnection(self.NetworkManagerDevice.ActiveConnection)
|
|
||||||
end
|
|
||||||
|
|
||||||
function access_point:connect(ap, password, auto_connect)
|
|
||||||
local connections = self:get_access_point_connections(NM.utils_ssid_to_utf8(ap.Ssid))
|
|
||||||
local profile = self:create_profile(self.NetworkManagerAccessPoint, password, auto_connect)
|
|
||||||
|
|
||||||
if #connections == 0 then
|
|
||||||
self.NetworkManager:AddAndActivateConnectionAsync(function(proxy, context, success, fail)
|
|
||||||
if fail ~= nil then
|
|
||||||
self:emit_signal('NetworkManager::failed', tostring(fail), tostring(fail.code))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self:emit_signal('NetworkManager::connected', success)
|
|
||||||
end, { call_id = 'my-id' }, profile, self.NetworkManagerDevice.object_path,
|
|
||||||
self.NetworkManagerAccessPoint.object_path)
|
|
||||||
--88ALYLNxo9Kk*RwRxMfN
|
|
||||||
else
|
|
||||||
connections[1]:Update(profile)
|
|
||||||
self.NetworkManager:ActivateConnectionAsync(function(proxy, context, success, failure)
|
|
||||||
if failure then
|
|
||||||
self:emit_signal('NM::AccessPointFailed', tostring(failure))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
self:emit_signal('NM::AccessPointConnected', NM.utils_ssid_to_utf8(ap.Ssid))
|
|
||||||
end,
|
|
||||||
{ call_id = 'my-id' }, connections[1].object_path, self.NetworkManagerDevice.object_path,
|
|
||||||
self.NetworkManagerAccessPoint.object_path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function access_point:toggle_connection(ap, password, auto_connect)
|
|
||||||
if self:is_ap_active(ap) then
|
|
||||||
self:disconnect()
|
|
||||||
else
|
|
||||||
self:connect(ap, password, auto_connect)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function access_point:is_ap_active(ap)
|
|
||||||
return ap.object_path == self.NetworkManagerDeviceWireless.ActiveAccessPoint
|
|
||||||
end
|
|
||||||
|
|
||||||
function access_point.new(args)
|
|
||||||
args = args or {}
|
|
||||||
|
|
||||||
if not args.NetworkManagerAccessPoint then return end
|
|
||||||
|
|
||||||
local ssid_text = awidget.inputbox {
|
|
||||||
text = NM.utils_ssid_to_utf8(args.NetworkManagerAccessPoint.Ssid) or
|
|
||||||
args.NetworkManagerAccessPoint.hw_address or 'Unknown',
|
|
||||||
halign = 'left',
|
|
||||||
valign = 'center',
|
|
||||||
}
|
|
||||||
|
|
||||||
local ret = base.make_widget_from_value(wibox.widget {
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
image = gcolor.recolor_image(
|
|
||||||
icondir .. 'wifi-strength-' .. math.floor(args.NetworkManagerAccessPoint.Strength / 25) + 1 .. '.svg',
|
|
||||||
beautiful.colorscheme.bg_red),
|
|
||||||
id = 'icon',
|
|
||||||
resize = true,
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
{
|
|
||||||
ssid_text,
|
|
||||||
widget = wibox.container.constraint,
|
|
||||||
strategy = 'exact',
|
|
||||||
width = dpi(300),
|
|
||||||
id = 'alias',
|
|
||||||
},
|
|
||||||
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 = '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 = beautiful.colorscheme.bg,
|
|
||||||
fg = beautiful.colorscheme.bg_red,
|
|
||||||
border_color = beautiful.colorscheme.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
id = 'background',
|
|
||||||
shape = beautiful.shape[8],
|
|
||||||
widget = wibox.container.background,
|
|
||||||
})
|
|
||||||
|
|
||||||
assert(type(ret) == 'table', 'access_point:ret is not a table')
|
|
||||||
|
|
||||||
gtable.crush(ret, access_point, true)
|
|
||||||
|
|
||||||
ret.NetworkManagerAccessPoint = args.NetworkManagerAccessPoint
|
|
||||||
ret.NetworkManagerSettings = args.NetworkManagerSettings
|
|
||||||
ret.NetworkManagerDeviceWireless = args.NetworkManagerDeviceWireless
|
|
||||||
ret.NetworkManagerDevice = args.NetworkManagerDevice
|
|
||||||
ret.NetworkManager = args.NetworkManager
|
|
||||||
|
|
||||||
ret.NetworkManagerAccessPointProperties = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = 'org.freedesktop.NetworkManager',
|
|
||||||
interface = 'org.freedesktop.DBus.Properties',
|
|
||||||
path = ret.NetworkManagerAccessPoint.object_path,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Update the access point strength
|
|
||||||
ret.NetworkManagerAccessPointProperties:connect_signal(function(_, properties, data)
|
|
||||||
if data.Strength then
|
|
||||||
awesome.emit_signal('NM::AccessPointStrength', data.Strength)
|
|
||||||
if ret.is_ap_active(ret.NetworkManagerAccessPoint) then
|
|
||||||
ret:get_children_by_id('icon')[1].image = gcolor.recolor_image(
|
|
||||||
icondir .. 'wifi-strength-' .. math.floor(data.Strength / 25) + 1 .. '.svg',
|
|
||||||
beautiful.colorscheme.bg)
|
|
||||||
else
|
|
||||||
ret:get_children_by_id('icon')[1].image = gcolor.recolor_image(
|
|
||||||
icondir .. 'wifi-strength-' .. math.floor(data.Strength / 25) + 1 .. '.svg',
|
|
||||||
beautiful.colorscheme.bg_red)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end, 'PropertiesChanged')
|
|
||||||
|
|
||||||
if ret:is_ap_active(ret.NetworkManagerAccessPoint) then
|
|
||||||
ret.bg = beautiful.colorscheme.bg_red
|
|
||||||
ret.fg = beautiful.colorscheme.bg
|
|
||||||
ret:get_children_by_id('icon')[1].image = gcolor.recolor_image(
|
|
||||||
icondir .. 'wifi-strength-' .. math.floor(ret.NetworkManagerAccessPoint.Strength / 25) + 1 .. '.svg',
|
|
||||||
beautiful.colorscheme.bg)
|
|
||||||
ret:get_children_by_id('con')[1].image = gcolor.recolor_image(
|
|
||||||
icondir .. 'link.svg', beautiful.colorscheme.bg)
|
|
||||||
else
|
|
||||||
ret.bg = beautiful.colorscheme.bg
|
|
||||||
ret.fg = beautiful.colorscheme.bg_red
|
|
||||||
ret:get_children_by_id('icon')[1].image = gcolor.recolor_image(
|
|
||||||
icondir .. 'wifi-strength-' .. math.floor(ret.NetworkManagerAccessPoint.Strength / 25) + 1 .. '.svg',
|
|
||||||
beautiful.colorscheme.bg_red)
|
|
||||||
ret:get_children_by_id('con')[1].image = gcolor.recolor_image(
|
|
||||||
icondir .. 'link.svg', beautiful.colorscheme.bg_red)
|
|
||||||
end
|
|
||||||
|
|
||||||
ret.ap_form = ap_form {
|
|
||||||
screen = args.screen,
|
|
||||||
NetworkManagerAccessPoint = args.NetworkManagerAccessPoint,
|
|
||||||
ap = ret,
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.cm = cm {
|
|
||||||
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 = {
|
|
||||||
{ -- Connect/Disconnect a device
|
|
||||||
name = 'ret.device.Connected' and 'Disconnect' or 'Connect',
|
|
||||||
icon = gcolor.recolor_image('ret.device.Connected' and icondir .. 'link-off.svg' or
|
|
||||||
icondir .. 'link.svg',
|
|
||||||
beautiful.colorscheme.bg_red),
|
|
||||||
callback = function()
|
|
||||||
ret:toggle_connection(ret.NetworkManagerAccessPoint)
|
|
||||||
end,
|
|
||||||
id = 'connected',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
ret:buttons(gtable.join(
|
|
||||||
abutton({}, 1, nil,
|
|
||||||
function()
|
|
||||||
if ret:is_ap_active(ret.NetworkManagerAccessPoint) then
|
|
||||||
ret:disconnect()
|
|
||||||
else
|
|
||||||
ret.ap_form:popup_toggle()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
),
|
|
||||||
abutton({}, 3, nil,
|
|
||||||
function()
|
|
||||||
ret.cm:toggle()
|
|
||||||
end
|
|
||||||
)
|
|
||||||
))
|
|
||||||
|
|
||||||
hover.bg_hover { widget = ret }
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function access_point.mt:__call(...)
|
|
||||||
return access_point.new(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(access_point, access_point.mt)
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
local abutton = require('awful.button')
|
|
||||||
local aplacement = require('awful.placement')
|
|
||||||
local apopup = require('awful.popup')
|
|
||||||
local awidget = require('awful.widget')
|
|
||||||
local beautiful = require('beautiful')
|
|
||||||
local dpi = require('beautiful').xresources.apply_dpi
|
|
||||||
local gtable = require('gears.table')
|
|
||||||
local gcolor = require('gears.color')
|
|
||||||
local gshape = require('gears.shape')
|
|
||||||
local gfilesystem = require('gears.filesystem')
|
|
||||||
local NM = require('lgi').NM
|
|
||||||
local wibox = require('wibox')
|
|
||||||
|
|
||||||
local hover = require('src.tools.hover')
|
|
||||||
|
|
||||||
local icondir = gfilesystem.get_configuration_dir() .. 'src/assets/icons/network/'
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
awesome = awesome,
|
|
||||||
mouse = mouse,
|
|
||||||
mousegrabber = mousegrabber,
|
|
||||||
}
|
|
||||||
|
|
||||||
local ap_form = { mt = {} }
|
|
||||||
|
|
||||||
function ap_form:popup_toggle()
|
|
||||||
self.visible = not self.visible
|
|
||||||
end
|
|
||||||
|
|
||||||
function ap_form.new(args)
|
|
||||||
args = args or {}
|
|
||||||
args.screen = args.screen
|
|
||||||
|
|
||||||
local password = awidget.inputbox { hint_text = 'Password...' }
|
|
||||||
|
|
||||||
local ret = apopup {
|
|
||||||
widget = {
|
|
||||||
{
|
|
||||||
{ -- Header
|
|
||||||
{
|
|
||||||
nil,
|
|
||||||
{
|
|
||||||
{
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
text = NM.utils_ssid_to_utf8(args.NetworkManagerAccessPoint.Ssid),
|
|
||||||
font = beautiful.user_config.font .. ' extra bold 16',
|
|
||||||
halign = 'center',
|
|
||||||
valign = 'center',
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = dpi(5),
|
|
||||||
},
|
|
||||||
{ -- Close button
|
|
||||||
{
|
|
||||||
{
|
|
||||||
widget = wibox.widget.imagebox,
|
|
||||||
image = gcolor.recolor_image(icondir .. 'close.svg', beautiful.colorscheme.bg),
|
|
||||||
resize = false,
|
|
||||||
valign = 'center',
|
|
||||||
halign = 'center',
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = dpi(5),
|
|
||||||
},
|
|
||||||
widget = wibox.container.background,
|
|
||||||
shape = beautiful.shape[8],
|
|
||||||
id = 'close_button',
|
|
||||||
bg = beautiful.colorscheme.bg_red,
|
|
||||||
},
|
|
||||||
layout = wibox.layout.align.horizontal,
|
|
||||||
},
|
|
||||||
widget = wibox.container.background,
|
|
||||||
bg = beautiful.colorscheme.bg,
|
|
||||||
fg = beautiful.colorscheme.bg_red,
|
|
||||||
},
|
|
||||||
{ -- Form
|
|
||||||
{ -- Password
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
text = 'Password',
|
|
||||||
halign = 'center',
|
|
||||||
valign = 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
left = dpi(20),
|
|
||||||
right = dpi(20),
|
|
||||||
},
|
|
||||||
-- Change to inputtextbox container
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
password,
|
|
||||||
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 = beautiful.colorscheme.bg,
|
|
||||||
fg = beautiful.colorscheme.fg,
|
|
||||||
border_color = beautiful.colorscheme.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
shape = gshape.rounded_rect,
|
|
||||||
forced_width = 300,
|
|
||||||
forced_height = 50,
|
|
||||||
id = 'password_container',
|
|
||||||
},
|
|
||||||
layout = wibox.layout.align.horizontal,
|
|
||||||
},
|
|
||||||
{ -- Actions
|
|
||||||
{ -- Auto connect
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
checked = false,
|
|
||||||
shape = beautiful.shape[4],
|
|
||||||
color = beautiful.colorscheme.bg,
|
|
||||||
paddings = dpi(3),
|
|
||||||
check_color = beautiful.colorscheme.bg_red,
|
|
||||||
border_color = beautiful.colorscheme.bg_red,
|
|
||||||
border_width = dpi(2),
|
|
||||||
id = 'checkbox',
|
|
||||||
widget = wibox.widget.checkbox,
|
|
||||||
},
|
|
||||||
widget = wibox.container.constraint,
|
|
||||||
strategy = 'exact',
|
|
||||||
width = dpi(30),
|
|
||||||
height = dpi(30),
|
|
||||||
},
|
|
||||||
widget = wibox.container.place,
|
|
||||||
halign = 'center',
|
|
||||||
valign = 'center',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
text = 'Auto connect',
|
|
||||||
halign = 'center',
|
|
||||||
valign = 'center',
|
|
||||||
},
|
|
||||||
spacing = dpi(10),
|
|
||||||
layout = wibox.layout.fixed.horizontal,
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
{ -- Connect
|
|
||||||
{
|
|
||||||
{
|
|
||||||
{
|
|
||||||
widget = wibox.widget.textbox,
|
|
||||||
text = 'Connect',
|
|
||||||
halign = 'center',
|
|
||||||
valign = 'center',
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = dpi(10),
|
|
||||||
},
|
|
||||||
widget = wibox.container.background,
|
|
||||||
bg = beautiful.colorscheme.bg_blue,
|
|
||||||
fg = beautiful.colorscheme.bg,
|
|
||||||
shape = beautiful.shape[8],
|
|
||||||
id = 'connect_button',
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = dpi(10),
|
|
||||||
},
|
|
||||||
layout = wibox.layout.align.horizontal,
|
|
||||||
},
|
|
||||||
spacing = dpi(20),
|
|
||||||
layout = wibox.layout.fixed.vertical,
|
|
||||||
},
|
|
||||||
widget = wibox.container.margin,
|
|
||||||
margins = dpi(10),
|
|
||||||
},
|
|
||||||
placement = aplacement.centered,
|
|
||||||
ontop = true,
|
|
||||||
visible = false,
|
|
||||||
width = dpi(600),
|
|
||||||
height = dpi(400),
|
|
||||||
bg = beautiful.colorscheme.bg,
|
|
||||||
fg = beautiful.colorscheme.fg,
|
|
||||||
border_color = beautiful.colorscheme.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
type = 'dialog',
|
|
||||||
screen = args.screen,
|
|
||||||
}
|
|
||||||
|
|
||||||
local password_container = ret.widget:get_children_by_id('password_container')[1]
|
|
||||||
|
|
||||||
gtable.crush(ret, ap_form, true)
|
|
||||||
|
|
||||||
-- Focus the searchbar when its left clicked
|
|
||||||
password_container:buttons(gtable.join {
|
|
||||||
abutton({}, 1, function()
|
|
||||||
password:focus()
|
|
||||||
end),
|
|
||||||
})
|
|
||||||
|
|
||||||
--#region Hover signals to change the cursor to a text cursor
|
|
||||||
local old_cursor, old_wibox
|
|
||||||
password_container: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)
|
|
||||||
password_container:connect_signal('mouse::leave', function()
|
|
||||||
old_wibox.cursor = old_cursor
|
|
||||||
old_wibox = nil
|
|
||||||
end)
|
|
||||||
--#endregion
|
|
||||||
|
|
||||||
local checkbox = ret.widget:get_children_by_id('checkbox')[1]
|
|
||||||
checkbox:connect_signal('button::press', function()
|
|
||||||
checkbox.checked = not checkbox.checked
|
|
||||||
end)
|
|
||||||
|
|
||||||
local close_button = ret.widget:get_children_by_id('close_button')[1]
|
|
||||||
close_button:connect_signal('button::press', function()
|
|
||||||
ret:popup_toggle()
|
|
||||||
end)
|
|
||||||
hover.bg_hover { widget = close_button }
|
|
||||||
|
|
||||||
local connect_button = ret.widget:get_children_by_id('connect_button')[1]
|
|
||||||
connect_button:connect_signal('button::press', function()
|
|
||||||
password:stop()
|
|
||||||
args.ap:connect(args.NetworkManagerAccessPoint, password:get_text(),
|
|
||||||
ret.widget:get_children_by_id('checkbox')[1].checked)
|
|
||||||
ret:popup_toggle()
|
|
||||||
end)
|
|
||||||
hover.bg_hover { widget = connect_button }
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function ap_form.mt:__call(...)
|
|
||||||
return ap_form.new(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(ap_form, ap_form.mt)
|
|
||||||
@@ -1,488 +0,0 @@
|
|||||||
------------------------------------
|
|
||||||
-- This is the network controller --
|
|
||||||
------------------------------------
|
|
||||||
|
|
||||||
-- Awesome Libs
|
|
||||||
local abutton = require('awful.button')
|
|
||||||
local base = require('wibox.widget.base')
|
|
||||||
local dbus_proxy = require('src.lib.lua-dbus_proxy.src.dbus_proxy')
|
|
||||||
local beautiful = require('beautiful')
|
|
||||||
local dpi = require('beautiful').xresources.apply_dpi
|
|
||||||
local gcolor = require('gears.color')
|
|
||||||
local gfilesystem = require('gears.filesystem')
|
|
||||||
local gshape = require('gears.shape')
|
|
||||||
local gtable = require('gears.table')
|
|
||||||
local gtimer = require('gears.timer')
|
|
||||||
local lgi = require('lgi')
|
|
||||||
local NM = lgi.NM
|
|
||||||
local naughty = require('naughty')
|
|
||||||
local wibox = require('wibox')
|
|
||||||
|
|
||||||
-- Third party libs
|
|
||||||
local rubato = require('src.lib.rubato')
|
|
||||||
local hover = require('src.tools.hover')
|
|
||||||
|
|
||||||
-- Local libs
|
|
||||||
local access_point = require('src.modules.network_controller.access_point')
|
|
||||||
local dnd_widget = require('awful.widget.toggle_widget')
|
|
||||||
|
|
||||||
local icondir = gfilesystem.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,
|
|
||||||
}
|
|
||||||
|
|
||||||
---Get the wifi and or ethernet proxy and connect to their PropertiesChanged signal
|
|
||||||
-- The signals will return the following
|
|
||||||
-- wifi: { "Bitrate", "Strength" }
|
|
||||||
-- ethernet: { "Carrier", "Speed" }
|
|
||||||
function network:get_active_device()
|
|
||||||
--Get all devices
|
|
||||||
local devices = self._private.NetworkManager:GetDevices()
|
|
||||||
if (not devices) or (#devices == 0) then return end
|
|
||||||
-- Loop trough every found device
|
|
||||||
for _, path in ipairs(devices) do
|
|
||||||
--Create a new proxy for every device
|
|
||||||
local NetworkManagerDevice = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = 'org.freedesktop.NetworkManager',
|
|
||||||
interface = 'org.freedesktop.NetworkManager.Device',
|
|
||||||
path = path,
|
|
||||||
}
|
|
||||||
|
|
||||||
--Check if the device is either a wifi or ethernet device, and if its activated
|
|
||||||
-- if its activated then its currently in use
|
|
||||||
if (NetworkManagerDevice.DeviceType == network.DeviceType.WIFI) and
|
|
||||||
(NetworkManagerDevice.State == network.DeviceState.ACTIVATED) then
|
|
||||||
-- Set the wifi device as the main device
|
|
||||||
self._private.NetworkManagerDevice = NetworkManagerDevice
|
|
||||||
--New wifi proxy to check the bitrate
|
|
||||||
self._private.NetworkManagerDeviceWireless = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = 'org.freedesktop.NetworkManager',
|
|
||||||
interface = 'org.freedesktop.NetworkManager.Device.Wireless',
|
|
||||||
path = path,
|
|
||||||
}
|
|
||||||
-- Watch PropertiesChanged and update the bitrate
|
|
||||||
local NetworkManagerDeviceWirelessProperties = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = 'org.freedesktop.NetworkManager',
|
|
||||||
interface = 'org.freedesktop.DBus.Properties',
|
|
||||||
path = self._private.NetworkManagerDeviceWireless.object_path,
|
|
||||||
}
|
|
||||||
|
|
||||||
NetworkManagerDeviceWirelessProperties:connect_signal(function(_, properties, data)
|
|
||||||
if data.Bitrate then
|
|
||||||
self:emit_signal('NM::Bitrate', data.Bitrate)
|
|
||||||
end
|
|
||||||
end, 'PropertiesChanged')
|
|
||||||
-- Watch the StateChanged signal, update and notify when a new AP is connected
|
|
||||||
self._private.NetworkManagerDevice:connect_signal(function(proxy, new_state)
|
|
||||||
local NetworkManagerAccessPoint = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = 'org.freedesktop.NetworkManager',
|
|
||||||
interface = 'org.freedesktop.NetworkManager.AccessPoint',
|
|
||||||
path = self._private.NetworkManagerDeviceWireless.ActiveAccessPoint,
|
|
||||||
}
|
|
||||||
|
|
||||||
if new_state == network.DeviceState.ACTIVATED then
|
|
||||||
local ssid = NM.utils_ssid_to_utf8(NetworkManagerAccessPoint.Ssid)
|
|
||||||
self:emit_signal('NM::AccessPointConnected', ssid, NetworkManagerAccessPoint.Strength)
|
|
||||||
end
|
|
||||||
end, 'StateChanged')
|
|
||||||
|
|
||||||
elseif (NetworkManagerDevice.DeviceType == network.DeviceType.ETHERNET) and
|
|
||||||
(NetworkManagerDevice.State == network.DeviceState.ACTIVATED) then
|
|
||||||
self._private.NetworkManagerDevice = NetworkManagerDevice
|
|
||||||
self._private.NetworkManagerDeviceWired = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = 'org.freedesktop.NetworkManager',
|
|
||||||
interface = 'org.freedesktop.NetworkManager.Device.Wired',
|
|
||||||
path = path,
|
|
||||||
}
|
|
||||||
if self._private.NetworkManagerDevice.State == network.DeviceState.ACTIVATED then
|
|
||||||
awesome.emit_signal('NM::EthernetStatus', true, self._private.NetworkManagerDeviceWired.Speed)
|
|
||||||
end
|
|
||||||
-- Connect to the StateChanged signal and notify when the wired connection is ready
|
|
||||||
self._private.NetworkManagerDevice:connect_signal(function(_, new_state)
|
|
||||||
if new_state == network.DeviceState.ACTIVATED then
|
|
||||||
awesome.emit_signal('NM::EthernetStatus', true, self._private.NetworkManagerDeviceWired.Speed)
|
|
||||||
elseif new_state == network.DeviceState.DISCONNECTED then
|
|
||||||
awesome.emit_signal('NM::EthernetStatus', false)
|
|
||||||
end
|
|
||||||
end, 'StateChanged')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function network:get_active_ap_ssid()
|
|
||||||
local d = dbus_proxy.Proxy:new {
|
|
||||||
bus = dbus_proxy.Bus.SYSTEM,
|
|
||||||
name = 'org.freedesktop.NetworkManager',
|
|
||||||
interface = 'org.freedesktop.NetworkManager.Device.Wireless',
|
|
||||||
path = self._private.NetworkManagerDeviceWireless.ActiveAccessPoint,
|
|
||||||
}
|
|
||||||
|
|
||||||
return NM.utils_ssid_to_utf8(d.Ssid)
|
|
||||||
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()
|
|
||||||
local ap_table = {}
|
|
||||||
self._private.NetworkManagerDeviceWireless:RequestScanAsync(function(_, _, _, failure)
|
|
||||||
if failure then
|
|
||||||
naughty.notification {
|
|
||||||
app_icon = icondir .. 'ethernet.svg',
|
|
||||||
app_name = 'Network Manager',
|
|
||||||
title = 'Error: Scan failed!',
|
|
||||||
message = 'Failed to scan for access points.\n' .. failure,
|
|
||||||
icon = gcolor.recolor_image(icondir .. 'ethernet.svg', beautiful.colorscheme.bg),
|
|
||||||
timeout = 5,
|
|
||||||
}
|
|
||||||
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 NM.utils_ssid_to_utf8(NetworkManagerAccessPoint.Ssid) and NetworkManagerAccessPoint.Strength then
|
|
||||||
if (ap_table[NetworkManagerAccessPoint.Ssid] == nil) or
|
|
||||||
NetworkManagerAccessPoint.Strength > ap_table[NetworkManagerAccessPoint.Ssid].Strength then
|
|
||||||
ap_table[NetworkManagerAccessPoint.Ssid] = NetworkManagerAccessPoint
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--sort ap_table first by strength
|
|
||||||
local sorted_ap_table = {}
|
|
||||||
for _, NetworkManagerAccessPoint in pairs(ap_table) do
|
|
||||||
table.insert(sorted_ap_table, NetworkManagerAccessPoint)
|
|
||||||
end
|
|
||||||
--sort the table by strength but have the active_ap at the top
|
|
||||||
table.sort(sorted_ap_table, function(a, b)
|
|
||||||
if a.object_path == self._private.NetworkManagerDeviceWireless.ActiveAccessPoint then
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
return a.Strength > b.Strength
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
for _, NetworkManagerAccessPoint in ipairs(sorted_ap_table) do
|
|
||||||
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, { call_id = 'my-id' }, {})
|
|
||||||
end
|
|
||||||
|
|
||||||
---Toggles networking on or off
|
|
||||||
function network:toggle_wifi()
|
|
||||||
local enable = not self._private.NetworkManager.WirelessEnabled
|
|
||||||
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',
|
|
||||||
beautiful.colorscheme.bg_red),
|
|
||||||
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 = beautiful.colorscheme.bg1,
|
|
||||||
fg = beautiful.colorscheme.bg_red,
|
|
||||||
shape = beautiful.shape[4],
|
|
||||||
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 = beautiful.colorscheme.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
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 = beautiful.colorscheme.bg_red,
|
|
||||||
size = dpi(40),
|
|
||||||
},
|
|
||||||
id = 'dnd',
|
|
||||||
widget = wibox.container.place,
|
|
||||||
valign = 'center',
|
|
||||||
halign = 'center',
|
|
||||||
},
|
|
||||||
nil,
|
|
||||||
{ -- refresh
|
|
||||||
{
|
|
||||||
{
|
|
||||||
image = gcolor.recolor_image(icondir .. 'refresh.svg',
|
|
||||||
beautiful.colorscheme.bg_red),
|
|
||||||
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 = beautiful.colorscheme.border_color,
|
|
||||||
shape = beautiful.shape[4],
|
|
||||||
bg = beautiful.colorscheme.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 = beautiful.shape[8],
|
|
||||||
border_color = beautiful.colorscheme.border_color,
|
|
||||||
border_width = dpi(2),
|
|
||||||
bg = beautiful.colorscheme.bg,
|
|
||||||
id = 'background',
|
|
||||||
widget = wibox.container.background,
|
|
||||||
},
|
|
||||||
width = dpi(400),
|
|
||||||
strategy = 'exact',
|
|
||||||
widget = wibox.container.constraint,
|
|
||||||
})
|
|
||||||
|
|
||||||
assert(type(ret) == 'table', 'NetworkManager is not running')
|
|
||||||
|
|
||||||
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.WirelessEnabled ~= nil and ret._private.WirelessEnabled ~= data.WirelessEnabled then
|
|
||||||
ret._private.WirelessEnabled = data.WirelessEnabled
|
|
||||||
|
|
||||||
if ret._private.WirelessEnabled then
|
|
||||||
dnd:set_enabled()
|
|
||||||
else
|
|
||||||
dnd:set_disabled()
|
|
||||||
end
|
|
||||||
|
|
||||||
ret:emit_signal('NetworkManager::status', 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_active_device()
|
|
||||||
|
|
||||||
ret:scan_access_points()
|
|
||||||
|
|
||||||
if ret._private.NetworkManager.WirelessEnabled then
|
|
||||||
dnd:set_enabled()
|
|
||||||
else
|
|
||||||
dnd:set_disabled()
|
|
||||||
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(
|
|
||||||
abutton({}, 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',
|
|
||||||
beautiful.colorscheme.bg_red))
|
|
||||||
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',
|
|
||||||
beautiful.colorscheme.bg_red))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
))
|
|
||||||
hover.bg_hover { widget = wifi_margin.wifi_bg }
|
|
||||||
--#endregion
|
|
||||||
|
|
||||||
local refresh_button = ret:get_children_by_id('refresh')[1]
|
|
||||||
refresh_button:buttons(gtable.join(
|
|
||||||
abutton({}, 1, nil, function()
|
|
||||||
ret:scan_access_points()
|
|
||||||
end)
|
|
||||||
))
|
|
||||||
hover.bg_hover { widget = refresh_button }
|
|
||||||
|
|
||||||
return ret
|
|
||||||
end
|
|
||||||
|
|
||||||
function network.mt:__call(...)
|
|
||||||
return network.new(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(network, network.mt)
|
|
||||||
Reference in New Issue
Block a user