-- Standard awesome library local gears = require("gears") local awful = require("awful") -- Theme handling library local beautiful = require("beautiful") local dpi = beautiful.xresources.apply_dpi -- Notification library local naughty = require("naughty") -- Widget library local wibox = require("wibox") -- rubato local rubato = require("module.rubato") -- Helpers local helpers = require("helpers") -- Lock local lock_screen = require("ui.lockscreen") -- Lock Screen ---------------- lock_screen_box = wibox({visible = false, ontop = true, type = "splash", screen = screen.primary}) awful.placement.maximize(lock_screen_box) lock_screen_box.bg = beautiful.xbackground .. "22" -- Add lockscreen to each screen awful.screen.connect_for_each_screen(function(s) if s == screen.primary then s.mylockscreen = lock_screen_box else s.mylockscreen = helpers.screen_mask(s, beautiful.lock_screen_bg or beautiful.exit_screen_bg or beautiful.xbackground) end end) -- Vars local char = "I T L I S A S A M P M A C Q U A R T E R D C T W E N T Y F I V E X H A L F S T E N F T O P A S T E R U N I N E O N E S I X T H R E E F O U R F I V E T W O E I G H T E L E V E N S E V E N T W E L V E T E N S E O C L O C K" local pos_map = { ["it"] = {1, 2}, ["is"] = {4, 5}, ["a"] = {12, 12}, ["quarter"] = {14, 20}, ["twenty"] = {23,28}, ["five"] = {29, 32}, ["half"] = {34, 37}, ["ten"] = {39, 41}, ["past"] = {45, 48}, ["to"] = {43, 44}, ["1"] = {56, 58}, ["2"] = {75, 77}, ["3"] = {62, 66}, ["4"] = {67, 70}, ["5"] = {71, 74}, ["6"] = {59, 61}, ["7"] = {89, 93}, ["8"] = {78, 82}, ["9"] = {52, 55}, ["10"] = {100, 102}, ["11"] = {83, 88}, ["12"] = {94, 99}, ["oclock"] = {105, 110} } local char_map = { ["it"] = {}, ["is"] = {}, ["a"] = {}, ["quarter"] = {}, ["twenty"] = {}, ["five"] = {}, ["half"] = {}, ["ten"] = {}, ["past"] = {}, ["to"] = {}, ["1"] = {}, ["2"] = {}, ["3"] = {}, ["4"] = {}, ["5"] = {}, ["6"] = {}, ["7"] = {}, ["8"] = {}, ["9"] = {}, ["10"] = {}, ["11"] = {}, ["12"] = {}, ["oclock"] = {} } local reset_map = {4, 12, 14, 23, 29, 34, 39, 43, 45, 52, 56, 59, 62, 67, 71, 75, 78, 83, 89, 94, 100, 105} function split_str(s, delimiter) result = {}; for match in (s..delimiter):gmatch("(.-)"..delimiter) do table.insert(result, match); end return result; end local time_char = split_str(char, " ") -- Helpers local time = wibox.widget{ forced_num_cols = 11, spacing = beautiful.useless_gap, layout = wibox.layout.grid } local function create_text_widget(index, w) local text_widget = wibox.widget{ id = "t"..index, markup = w, font = beautiful.font_name .. "bold 18", align = "center", valign = "center", forced_width = dpi(25), forced_height = dpi(30), widget = wibox.widget.textbox } time:add(text_widget) return text_widget end local var_count = 0 for i, m in pairs(time_char) do -- local text = helpers.colorize_text(m, "#162026") local text = helpers.colorize_text(m, beautiful.xcolor8 .. "55") var_count = var_count + 1 local create_dummy_text = true for j, k in pairs(pos_map) do if i >= pos_map[j][1] and i <= pos_map[j][2] then char_map[j][var_count] = create_text_widget(i, text) create_dummy_text = false end for _, n in pairs(reset_map) do if i == n then var_count = 1 end end end if create_dummy_text then create_text_widget(i, text) end end local function activate_word(w) for i, m in pairs(char_map[w]) do local text = m.text m.markup = helpers.colorize_text(text, beautiful.xforeground) end end local function deactivate_word(w) for i, m in pairs(char_map[w]) do local text = m.text m.markup = helpers.colorize_text(text, beautiful.xcolor8 .. "55") end end local function reset_time() for j, k in pairs(char_map) do deactivate_word(j) end activate_word("it") activate_word("is") end gears.timer { timeout = 1, call_now = true, autostart = true, callback = function() local time = os.date('%I' .. ':%M') local h,m = time:match('(%d+):(%d+)') local min = tonumber(m) local hour = tonumber(h) reset_time() if min >= 0 and min <= 2 or min >= 58 and min <= 59 then activate_word("oclock") elseif min >= 3 and min <= 7 or min >= 53 and min <= 57 then activate_word("five") elseif min >= 8 and min <= 12 or min >= 48 and min <= 52 then activate_word("ten") elseif min >= 13 and min <= 17 or min >= 43 and min <= 47 then activate_word("a") activate_word("quarter") elseif min >= 18 and min <= 22 or min >= 38 and min <= 42 then activate_word("twenty") elseif min >= 23 and min <= 27 or min >= 33 and min <= 37 then activate_word("twenty") activate_word("five") elseif min >= 28 and min <= 32 then activate_word("half") end if min >= 3 and min <= 32 then activate_word("past") elseif min >= 33 and min <= 57 then activate_word("to") end local hh if min >= 0 and min <= 30 then hh = hour else hh = hour + 1 end if hh > 12 then hh = hh - 12 end activate_word(tostring(hh)) end } -- Lock animation local lock_screen_symbol = "" local lock_screen_fail_symbol = "" local lock_animation_icon = wibox.widget { -- Set forced size to prevent flickering when the icon rotates forced_height = dpi(80), forced_width = dpi(80), font = beautiful.icon_font_name .. "Outlined 24", align = "center", valign = "center", widget = wibox.widget.textbox(lock_screen_symbol) } local lock_animation_widget_rotate = wibox.container.rotate() local arc = function() return function(cr, width, height) gears.shape.arc(cr, width, height, dpi(5), 0, math.pi/3, true, true) end end local lock_animation_arc = wibox.widget { shape = arc(), bg = "#00000000", forced_width = dpi(50), forced_height = dpi(50), widget = wibox.container.background } local lock_animation = { { lock_animation_arc, widget = lock_animation_widget_rotate }, lock_animation_icon, layout = wibox.layout.stack } -- Lock helper functions local characters_entered = 0 local function reset() characters_entered = 0; lock_animation_icon.markup = helpers.colorize_text(lock_screen_symbol, beautiful.xcolor7) lock_animation_widget_rotate.direction = "north" lock_animation_arc.bg = "#00000000" end local function fail() characters_entered = 0; lock_animation_icon.text = lock_screen_fail_symbol lock_animation_widget_rotate.direction = "north" lock_animation_arc.bg = "#00000000" end local animation_colors = { -- Rainbow sequence =) beautiful.xcolor1, beautiful.xcolor5, beautiful.xcolor4, beautiful.xcolor6, beautiful.xcolor2, beautiful.xcolor3, } local animation_directions = {"north", "west", "south", "east"} -- Function that "animates" every key press local function key_animation(char_inserted) local color local direction = animation_directions[(characters_entered % 4) + 1] if char_inserted then color = animation_colors[(characters_entered % 6) + 1] lock_animation_icon.text = lock_screen_symbol else if characters_entered == 0 then reset() else color = beautiful.xcolor7 .. "55" end end lock_animation_arc.bg = color lock_animation_widget_rotate.direction = direction end local function set_visibility(v) for s in screen do s.mylockscreen.visible = v end end -- Get input from user local some_textbox = wibox.widget.textbox() local function grab_password() awful.prompt.run { hooks = { -- Custom escape behaviour: Do not cancel input with Escape -- Instead, this will just clear any input received so far. {{ }, 'Escape', function(_) reset() grab_password() end }, -- Fix for Control+Delete crashing the keygrabber {{ 'Control' }, 'Delete', function () reset() grab_password() end} }, keypressed_callback = function(mod, key, cmd) -- Only count single character keys (thus preventing -- "Shift", "Escape", etc from triggering the animation) if #key == 1 then characters_entered = characters_entered + 1 key_animation(true) elseif key == "BackSpace" then if characters_entered > 0 then characters_entered = characters_entered - 1 end key_animation(false) end -- Debug -- naughty.notify { title = 'You pressed:', text = key } end, exe_callback = function(input) -- Check input if lock_screen.authenticate(input) then -- YAY reset() set_visibility(false) else -- NAY fail() grab_password() end end, textbox = some_textbox, } end function lock_screen_show() set_visibility(true) grab_password() end lock_screen_box:setup { -- Horizontal centering nil, { -- Vertical centering nil, { helpers.vertical_pad(dpi(80)), time, { nil, { notifs, batt, date, spacing = dpi(30), layout = wibox.layout.fixed.horizontal }, visible = false, expand = "none", layout = wibox.layout.align.horizontal }, lock_animation, spacing = dpi(60), layout = wibox.layout.fixed.vertical }, expand = "none", layout = wibox.layout.align.vertical }, expand = "none", layout = wibox.layout.align.horizontal }