From 7bb865312816f0e166e2cc8f8e80db49cc323a97 Mon Sep 17 00:00:00 2001 From: Aire-One Date: Wed, 4 Dec 2024 23:36:33 +0100 Subject: [PATCH] feat(dock): initial dock implementation This commit is more a showcase to demonstrate how we can use the slot package to build custom UI. It includes a minimal UPower service and slot's parameters binding and reusable UI modules. I feel like this is going the right direction. We still have some improvement margin, but the code is well separated in layers. We can easily connect to the service in different contexts. --- src/awesomerc/init.lua | 31 +++++++++++++++++++ src/awesomerc/slots/dock.lua | 47 +++++++++++++++++++++++++++++ src/awesomerc/ui/battery-widget.lua | 22 ++++++++++++++ src/awesomerc/ui/box.lua | 45 +++++++++++++++++++++++++++ src/awesomerc/ui/dock.lua | 38 +++++++++++++++++++++++ 5 files changed, 183 insertions(+) create mode 100644 src/awesomerc/slots/dock.lua create mode 100644 src/awesomerc/ui/battery-widget.lua create mode 100644 src/awesomerc/ui/box.lua create mode 100644 src/awesomerc/ui/dock.lua diff --git a/src/awesomerc/init.lua b/src/awesomerc/init.lua index 4505058..269a66e 100644 --- a/src/awesomerc/init.lua +++ b/src/awesomerc/init.lua @@ -59,6 +59,37 @@ slot { slot = my_slots.build_desktop_decoration, } +--------- +-- Minimum code example to create a UPower service +local lgi = require "lgi" +local upower = lgi.require "UPowerGlib" +local gears = require "gears" + +local function create_upower_service() + local service = gears.object() + service.device = upower.Client():get_display_device() + service.device.on_notify = function(d) + service:emit_signal("upower::update", d) + end + gears.timer.delayed_call(service.emit_signal, service, "upower::update", service.device) + return service +end + +local upower_service = create_upower_service() +--------- +-- Load the dock module +local dock = require "awesomerc.slots.dock" + +slot { + target = capi.screen, + signal = "request::desktop_decoration", + slot = dock.create_desktop_decoration, + slot_params = { + upower_service = upower_service, + }, +} +--------- + slot { target = capi.client, signal = "request::default_mousebindings", diff --git a/src/awesomerc/slots/dock.lua b/src/awesomerc/slots/dock.lua new file mode 100644 index 0000000..4fc93ea --- /dev/null +++ b/src/awesomerc/slots/dock.lua @@ -0,0 +1,47 @@ +local battery_widget = require "awesomerc.ui.battery-widget" +local box = require "awesomerc.ui.box" +local slot = require "awesome-slot" +local ui_dock = require "awesomerc.ui.dock" +local wibox = require "wibox" + +local dock = {} + +function dock.create_desktop_decoration(params) + local upower_service = params.upower_service + + local battery = battery_widget() + slot { + target = upower_service, + signal = "upower::update", + slot = function() + return function(_, device) + battery.battery = device.percentage + end + end, + } + + return function(screen) + screen.dock = ui_dock { + screen = screen, + left_widget = { + box { + screen = screen, + bg = "#FF0000", + fg = "#FFFFFF", + widget = battery, + }, + layout = wibox.layout.fixed.horizontal, + }, + middle_widget = { + markup = "middle", + widget = wibox.widget.textbox, + }, + right_widget = { + markup = "right", + widget = wibox.widget.textbox, + }, + } + end +end + +return dock diff --git a/src/awesomerc/ui/battery-widget.lua b/src/awesomerc/ui/battery-widget.lua new file mode 100644 index 0000000..cb4aa84 --- /dev/null +++ b/src/awesomerc/ui/battery-widget.lua @@ -0,0 +1,22 @@ +local gears = require "gears" +local wibox = require "wibox" + +local battery_widget = {} + +function battery_widget:set_battery(percentage) + self.markup = percentage +end + +function battery_widget.create() + local self = wibox.widget { + widget = wibox.widget.textbox, + } + + return gears.table.crush(self, battery_widget) +end + +return setmetatable(battery_widget, { + __call = function(_) + return battery_widget.create() + end, +}) diff --git a/src/awesomerc/ui/box.lua b/src/awesomerc/ui/box.lua new file mode 100644 index 0000000..cbc2997 --- /dev/null +++ b/src/awesomerc/ui/box.lua @@ -0,0 +1,45 @@ +local background = require "wibox.container.background" +local beautiful = require "beautiful" +local margin = require "wibox.container.margin" +local shape = require "gears.shape" +local widget = require "wibox.widget" + +local abs = math.abs +local dpi = beautiful.xresources.apply_dpi + +local box = {} + +-- 10 is an arbitrary value I found after some tests :shrug: +local CIRCLE_TO_BAR_THRESHOLD = 10 + +function box.shape(cr, width, height) + local s = abs(width - height) > CIRCLE_TO_BAR_THRESHOLD and shape.rounded_bar or shape.circle + + return s(cr, width, height) +end + +function box.new(args) + local box_widget = widget { + { + widget = margin, + draw_empty = false, + top = dpi(beautiful.bar_box_padding_y, args.screen), + bottom = dpi(beautiful.bar_box_padding_y, args.screen), + right = dpi(beautiful.bar_box_padding_x, args.screen), + left = dpi(beautiful.bar_box_padding_x, args.screen), + args.widget, + }, + bg = args.bg, + fg = args.fg, + shape = box.shape, + widget = background, + } + + return box_widget +end + +return setmetatable(box, { + __call = function(_, ...) + return box.new(...) + end, +}) diff --git a/src/awesomerc/ui/dock.lua b/src/awesomerc/ui/dock.lua new file mode 100644 index 0000000..aaad874 --- /dev/null +++ b/src/awesomerc/ui/dock.lua @@ -0,0 +1,38 @@ +local beautiful = require "beautiful" +local wibar = require "awful.wibar" +local wibox = require "wibox" + +local dpi = beautiful.xresources.apply_dpi + +local dock = {} + +function dock.new(args) + local self = wibar { + screen = args.screen, + position = "top", + height = dpi(beautiful.bar_height, args.screen), + width = beautiful.bar_width, -- Width is a percentage of the screen size + margins = { + top = dpi(4), + bottom = dpi(4), + left = dpi(4), + right = dpi(4), + }, + bg = "#000000", + fg = "#FFFFFF", + widget = { + args.left_widget, + args.middle_widget, + args.right_widget, + layout = wibox.layout.align.horizontal, + }, + } + + return self +end + +return setmetatable(dock, { + __call = function(_, ...) + return dock.new(...) + end, +})