add revelation plugin

This commit is contained in:
vincent 2018-11-14 19:48:30 +01:00
parent 24516fc321
commit dbd00f469b
5 changed files with 851 additions and 1 deletions

View File

@ -13,7 +13,9 @@ local xrandr = require("xrandr")
-- Notification library
local naughty = require("naughty")
local menubar = require("menubar")
--load revelation plugin
local revelation=require("revelation")
--load hotkey_popup
local hotkeys_popup = require("awful.hotkeys_popup").widget
-- Enable hotkeys help widget for VIM and other apps
-- when client with a matching name is opened:
@ -48,6 +50,10 @@ end
-- Themes define colours, icons, font and wallpapers.
beautiful.init(awful.util.getdir("config") .. "/themes/default/theme.lua")
beautiful.useless_gap = 5
-- revelation init
revelation.init()
--
-- This is used later as the default terminal and editor to run.
local terminal = "termite"
@ -336,6 +342,8 @@ globalkeys = gears.table.join(
end,{description="toble wibox",group="awesome"}),
awful.key({ modkey, }, "s", hotkeys_popup.show_help,
{description="show help", group="awesome"}),
awful.key({ modkey, }, "e", revelation,
{descriotion="revelation shortcut",group="awesome"}),
awful.key({ modkey, }, "Left", awful.tag.viewprev,
{description = "view previous", group = "tag"}),
awful.key({ modkey, }, "Right", awful.tag.viewnext,

View File

@ -0,0 +1,165 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -0,0 +1,169 @@
# revelation.lua
Provides Mac OSX like 'Expose' view of all clients.
This is a fork from [revelation](https://github.com/bioe007/awesome-revelation)
It is modified from the original revelation.lua for incorporating with awesome 3.5 or later.
It also have some features.
**Now master branch works for both master and stable awesome WM**
## Changes since 2015-09-26
When all clients are exposing, you can zoom (__Modkey + Shift + hintbox charater__ or __right button__ of the mouse)
or kill a client (__middle button__ of the mouse) and the position of hintboxes will be updated accordingly.
## Changes since 2014-02-19
* Now the revlation is able to handle the special clients(float, fullscreen or maximized etc.)
* When you select an minimized client, the revelation will un-minimized it and then focuse on it.
* Added an option to change character ordering
## Changes after 2013-12-30
* Now it is possible, in revelation.init({...}), to change the default settings of
revelation module.
* Function `revelation(...)` now accept the parameter as a table `{rule={...}, is_excluded=...,
curr_tag_only=...}`.
1. To add specify rules `revelation({rule={...},...})`.
2. To exclude the clients matched by the rules instead of including `revelation({rule={...},
is_excluded=true})`.
3. `{...,curr_tag_only=true}` make the revelation only collect the client from current
tags.
## Changes from the original revelation
* Support awesome 3.5 or later
* Add the support of multiple screens. Now multiple 'Expose' views will be shown
on the multiple screens at the same time.
* The way of selecting and focusing the client was changed. The old way that is
navigating clients by pressing the keys "j, h, k, l" and then selecting the
client by pressing key "Enter" was deprecated. Now each client in the 'Expose'
views come with a letter surrounding by a hint box, you can select the client
by pressing the corresponding letter in the hint box. The idea and codes of this method
was copied from the module [hint](https://github.com/zackpete/hints).
* Add zoom mode. Add the function of zooming the client by pressing the right
button of the mouse.
* The unwanted clients can be excluded by the parameter`{rule={...}....}`.
## Screenshot
![screenshot](./screenshot.png)
## Usage
### Installation
(From user's awesome configuration directory, usually ~/.config/awesome)
1. Clone the repository:
git clone https://github.com/guotsuan/awesome-revelation revelation
2. Include it at the top of your rc.lua file:
`local revelation=require("revelation")`
3. **Important: Add `revelation.init()` after `beautiful.init()`**
3. Define a global keybinding (e. g. `ModKey + e`) for revelation in your rc.lua:
globalkeys = awful.util.table.join(
awful.key({ modkey, }, "Left", awful.tag.viewprev ),
awful.key({ modkey, }, "Right", awful.tag.viewnext ),
awful.key({ modkey, }, "Escape", awful.tag.history.restore),
awful.key({ modkey, }, "e", revelation),
awful.key({ modkey, }, "j",
function ()
awful.client.focus.byidx( 1)
if client.focus then client.focus:raise() end
end),
**NOTE:** Always double check the key binding syntax against the version of
Awesome which you are using.
4. Restart Awesome (usually __Modkey + Control + r__) and try the keybinding __Modkey + e__.
It should bring up all clients from the current tags on all screens and set the layout to fair.
You can focus clients with the __cursor__ keys, and then press the __left__ button to select,
or you can directly focus a client by pressing the corresponding key shown in the hint box.
Press the right mouse button to zoom the client or __Escape__ to abort.
### Configuration
Revelation's configuration is done through the init() function
There are three basic settings, shown with default values:
-- The name of the tag created for the 'exposed' view
revelation.tag_name = 'Revelation'
-- A table of matcher functions (used in client filtering)
revelation.exact = awful.rules.match
revelation.any = awful.rules.match_any
-- Character order for selecting clients
revelation.charorder = "jkluiopyhnmfdsatgvcewqzx1234567890",
The rule matching functions must conform to `awful.rules.match` prototypes.
For client matching rules, we follow the same syntax as awful.rules expects.
If `rule.any == true`, then we call the `config.match.any` function.
to change the settings, use:
revelation.init({tag_name = ..., match = {...}, charorder = ...})
### Examples
All clients:
awful.key({modkey}, "e", revelation)
To match all urxvt terminals:
awful.key({modkey}, "e", function()
revelation({rule={class="URxvt"}})
end)
To match clients with class 'foo' or 'bar':
awful.key({modkey}, "e", function()
revelation({
rule{class={"foo", "bar"},
any=true}
})
end)
To exclude the clients, we set:
awful.key({modkey}, "e", function()
revelation({rule={class="conky"}, is_excluded=true})
end)
To set only collect clients from current tag
awful.key({modkey}, "e", function()
revelation({rule={class="conky"}, is_excluded=true,
curr_tag_only=true})
end)
## Credits
### Maintenance
* Quan Guo <guotsuan@gmail.com>
* Perry Hargrave <resixian@gmail.com>
### Contributions, many thanks!
* Daniel Hahler <github@thequod.de>
* Yauhen Kirylau
* Nikola Petrov <nikolavp@gmail.com>
### Original authors
* Espen Wiborg <espenhw@grumblesmurf.org>
* Julien Danjou <julien@danjou.info>
(c) 20013-2014 Quan Guo
(c) 2009-12 Perry Hargrave
(c) 2008 Espen Wiborg, Julien Danjou

View File

@ -0,0 +1,508 @@
-- revelation.lua
--
-- Library that implements Expose like behavior.
--
-- @author Perry Hargrave resixian@gmail.com
-- @author Espen Wiborg espenhw@grumblesmurf.org
-- @author Julien Danjou julien@danjou.info
-- @auther Quan Guo guotsuan@gmail.com
--
-- @copyright 2008 Espen Wiborg, Julien Danjou
-- @copyright 2015 Quan Guo
--
local beautiful = require("beautiful")
local wibox = require("wibox")
local awful = require('awful')
local aw_rules = require('awful.rules')
local pairs = pairs
local setmetatable = setmetatable
local naughty = require("naughty")
local table = table
local clock = os.clock
local tostring = tostring
local capi = {
awesome = awesome,
tag = tag,
client = client,
keygrabber = keygrabber,
mousegrabber = mousegrabber,
mouse = mouse,
screen = screen
}
-- disable for now.
-- It seems there is not way to pass err handling function into the delayed_call()
local function debuginfo(message)
message = message or "No information available"
nid = naughty.notify({ text = tostring(message), timeout = 10 })
end
local delayed_call = (type(timer) ~= 'table' and require("gears.timer").delayed_call)
local view_only_func
local toggle_tag_func
local jump_to_func
if type(awful.client.object) == 'table' then
view_only_func = function (tag) tag:view_only() end
toggle_tag_func = function (t, c) c:toggle_tag(t) end
jump_to_func = function(c) c:jump_to() end
else
view_only_func = function (tag) awful.tag.viewonly(tag) end
toggle_tag_func = function (t, c) awful.client.toggletag(t, c) end
jump_to_func = function(c) awful.client.jumpto(c) end
end
local hintbox = {} -- Table of letter wiboxes with characters as the keys
local hintindex = {} -- Table of visible clients with the hint letter as the keys
local clients = {} --Table of clients to be exposed after fitlering
local clientData = {} -- table that holds the positions and sizes of floating clients
local revelation = {
-- Name of expose tag.
tag_name = "Revelation",
charorder = "jkluiopyhnmfdsatgvcewqzx1234567890",
-- Match function can be defined by user.
-- Must accept a `rule` and `client` and return `boolean`.
-- The rule forms follow `awful.rules` syntax except we also check the
-- special `rule.any` key. If its true, then we use the `match.any` function
-- for comparison.
match = {
exact = aw_rules.match,
any = aw_rules.match_any
},
property_to_watch={
minimized = false,
fullscreen = false,
maximized_horizontal = false,
maximized_vertical = false,
sticky = false,
ontop = false,
above = false,
below = false,
},
tags_status = {},
is_excluded = false,
curr_tag_only = false,
font = "monospace 20",
fg = beautiful.fg_normal or "#DCDCCC",
bg = beautiful.bg_normal or "#000000",
border_color=beautiful.border_focus or "#DCDCCC",
border_width=beautiful.border_width or 2,
hintsize = (type(beautiful.xresources) == 'table' and beautiful.xresources.apply_dpi(50) or 60)
}
-- Executed when user selects a client from expose view.
--
-- @param restore Function to reset the current tags view.
local function selectfn(_, t, zt)
return function(c)
revelation.restore(t, zt)
-- Focus and raise
--
if type(delayed_call) == 'function' then
capi.awesome.emit_signal("refresh")
end
if awful.util.table.hasitem(hintindex, c) then
if c.minimized then
c.minimized = false
end
jump_to_func(c)
end
end
end
-- Tags all matching clients with tag t
-- @param rule The rule. Conforms to awful.rules syntax.
-- @param clients A table of clients to check.
-- @param t The tag to give matching clients.
local function match_clients(rule, _clients, t, is_excluded)
local mfc = rule.any and revelation.match.any or revelation.match.exact
local mf = is_excluded and function(c,_rule) return not mfc(c,_rule) end or mfc
local flt
for _, c in pairs(_clients) do
if mf(c, rule) then
-- Store geometry before setting their tags
clientData[c] = {}
clientData[c]["geometry"] = c:geometry()
flt = awful.client.property.get(c, "floating")
if flt ~= nil then
clientData[c]["floating"] = flt
awful.client.property.set(c, "floating", false)
end
for k,v in pairs(revelation.property_to_watch) do
clientData[c][k] = c[k]
c[k] = v
end
toggle_tag_func(t, c)
if c:isvisible() then
table.insert(clients, c)
end
end
end
end
-- Implement Exposé (ala Mac OS X).
--
-- @param rule A table with key and value to match. [{class=""}]
function revelation.expose(args)
args = args or {}
local rule = args.rule or {}
local is_excluded = args.is_excluded or revelation.is_excluded
local curr_tag_only = args.curr_tag_only or revelation.curr_tag_only
local t={}
local zt={}
clients = {}
clientData = {}
for scr=1,capi.screen.count() do
t[scr] = awful.tag.new({revelation.tag_name},
scr, awful.layout.suit.fair)[1]
zt[scr] = awful.tag.new({revelation.tag_name.."_zoom"},
scr, awful.layout.suit.fair)[1]
if curr_tag_only then
match_clients(rule, awful.client.visible(scr), t[scr], is_excluded)
else
match_clients(rule, capi.client.get(scr), t[scr], is_excluded)
end
view_only_func(t[scr])
end
if type(delayed_call) == 'function' then
capi.awesome.emit_signal("refresh")
end
-- No need for awesome WM 3.5.6: capi.awesome.emit_signal("refresh")
--
local status, err=pcall(revelation.expose_callback, t, zt, clients)
--revelation.expose_callback(t, zt)
if not status then
debuginfo('Oops!, something is wrong in revelation.expose_callback!')
if err.msg then
debuginfo(err.msg)
end
if err.code then
debuginfo('error code is '.. tostring(err.code))
end
revelation.restore(t, zt)
end
end
function revelation.restore(t, zt)
for scr=1, capi.screen.count() do
awful.tag.history.restore(scr)
t[scr].screen = nil
end
capi.keygrabber.stop()
capi.mousegrabber.stop()
for _, c in pairs(clients) do
if clientData[c] then
for k,v in pairs(clientData[c]) do
if v ~= nil then
if k== "geometry" then
c:geometry(v)
elseif k == "floating" then
awful.client.property.set(c, "floating", v)
else
c[k]=v
end
end
end
end
end
for scr=1, capi.screen.count() do
t[scr].activated = false
zt[scr].activated = false
end
for i,j in pairs(hintindex) do
hintbox[i].visible = false
end
end
local function hintbox_display_toggle(c, show)
for char, thisclient in pairs(hintindex) do
if char and char ~= c then
hintindex[char] = thisclient
if show then
hintbox[char].visible = true
else
hintbox[char].visible = false
end
end
end
end
local function hintbox_pos(char)
local client = hintindex[char]
local geom = client:geometry()
hintbox[char].x = math.floor(geom.x + geom.width/2 - revelation.hintsize/2)
hintbox[char].y = math.floor(geom.y + geom.height/2 - revelation.hintsize/2)
end
function revelation.expose_callback(t, zt, clientlist)
hintindex = {}
for i,thisclient in pairs(clientlist) do
-- Move wiboxes to center of visible windows and populate hintindex
local char = revelation.charorder:sub(i,i)
if char and char ~= '' then
hintindex[char] = thisclient
hintbox_pos(char)
hintbox[char].visible = true
hintbox[char].screen = thisclient.screen
end
end
local zoomed = false
local zoomedClient = nil
local key_char_zoomed = nil
capi.keygrabber.run(function (mod, key, event)
local c
if event == "release" then return true end
if awful.util.table.hasitem(mod, "Shift") then
key_char = string.lower(key)
c = hintindex[key_char]
if not zoomed and c ~= nil then
--debuginfo(c.screen)
view_only_func(zt[c.screen.index or c.screen])
toggle_tag_func(zt[c.screen.index or c.screen], c)
zoomedClient = c
key_char_zoomed = key_char
zoomed = true
-- update the position of this hintbox, since it is zoomed
if type(delayed_call) == 'function' then
capi.awesome.emit_signal("refresh")
end
hintbox_pos(key_char)
hintbox_display_toggle(key_char, false)
elseif zoomedClient ~= nil then
awful.tag.history.restore(zoomedClient.screen.index or zoomedClient.screen)
toggle_tag_func(zt[zoomedClient.screen.index or zoomedClient.screen], zoomedClient)
hintbox_display_toggle(key_char_zoomed, true)
if type(delayed_call) == 'function' then
capi.awesome.emit_signal("refresh")
end
hintbox_pos(key_char_zoomed)
zoomedClient = nil
zoomed = false
key_char_zoomed = nil
end
end
if hintindex[key] then
--client.focus = hintindex[key]
--hintindex[key]:raise()
selectfn(restore,t, zt)(hintindex[key])
for i,j in pairs(hintindex) do
hintbox[i].visible = false
end
return false
end
if key == "Escape" then
if zoomedClient ~= nil then
awful.tag.history.restore(zoomedClient.screen)
toggle_tag_func(zt[zoomedClient.screen.index or zoomedClient.screen], zoomedClient)
hintbox_display_toggle(string.lower(key), true)
if type(delayed_call) == 'function' then
capi.awesome.emit_signal("refresh")
end
hintbox_pos(key_char_zoomed)
zoomedClient = nil
zoomed = false
else
for i,j in pairs(hintindex) do
hintbox[i].visible = false
end
revelation.restore(t, zt)
return false
end
end
return true
end)
local pressedMiddle = false
local lastClient = nil
capi.mousegrabber.run(function(mouse)
local c
if type(awful.client.object) == 'table' then
c = capi.mouse.current_client
else
c = awful.mouse.client_under_pointer()
end
if c then
lastClient = c
else
local current_wibox = capi.mouse.current_wibox
if current_wibox then
for i = 1, #revelation.charorder do
local char = revelation.charorder:sub(i,i)
if hintbox[char] == current_wibox then
c = lastClient
break
end
end
end
end
local key_char = awful.util.table.hasitem(hintindex, c)
if mouse.buttons[1] == true then
if c ~= nil then
selectfn(restore, t, zt)(c)
for i,j in pairs(hintindex) do
hintbox[i].visible = false
end
return false
else
return true
end
elseif mouse.buttons[2] == true and pressedMiddle == false and c ~= nil then
-- is true whenever the button is down.
pressedMiddle = true
-- extra variable needed to prevent script from spam-closing windows
--
if zoomed == true and zoomedClient ~=nil then
awful.tag.history.restore(zoomedClient.screen.index or zoomedClient.screen)
toggle_tag_func(zt[zoomedClient.screen.index or zoomedClient.screen], zoomedClient)
end
c:kill()
hintbox[key_char].visible = false
hintindex[key_char] = nil
local pos = awful.util.table.hasitem(clients, c)
table.remove(clients, pos)
if zoomed == true and zoomedClient ~=nil then
hintbox_display_toggle(key_char_zoomed, true)
zoomedClient = nil
zoomed = false
key_char_zoomed = nil
end
return true
elseif mouse.buttons[2] == false and pressedMiddle == true then
pressedMiddle = false
for key, _ in pairs(hintindex) do
hintbox_pos(key)
end
elseif mouse.buttons[3] == true then
if not zoomed and c ~= nil then
view_only_func(zt[c.screen.index or c.screen])
toggle_tag_func(zt[c.screen.index or c.screen], c)
if key_char ~= nil then
hintbox_display_toggle(key_char, false)
if type(delayed_call) == 'function' then
capi.awesome.emit_signal("refresh")
end
hintbox_pos(key_char)
end
zoomedClient = c
zoomed = true
key_char_zoomed = key_char
elseif zoomedClient ~= nil then
awful.tag.history.restore(zoomedClient.screen.index or zoomedClient.screen)
toggle_tag_func(zt[zoomedClient.screen.index or zoomedClient.screen], zoomedClient)
hintbox_display_toggle(key_char_zoomed, true)
if type(delayed_call) == 'function' then
capi.awesome.emit_signal("refresh")
end
hintbox_pos(key_char_zoomed)
zoomedClient = nil
zoomed = false
key_char_zoomed = nil
end
end
return true
--Strange but on my machine only fleur worked as a string.
--stole it from
--https://github.com/Elv13/awesome-configs/blob/master/widgets/layout/desktopLayout.lua#L175
end,"fleur")
end
-- Create the wiboxes, but don't show them
--
function revelation.init(args)
local letterbox = {}
args = args or {}
revelation.tag_name = args.tag_name or revelation.tag_name
if args.match then
revelation.match.exact = args.match.exact or revelation.match.exact
revelation.match.any = args.match.any or revelation.match.any
end
revelation.charorder = args.charorder or revelation.charorder
for i = 1, #revelation.charorder do
local char = revelation.charorder:sub(i,i)
hintbox[char] = wibox({
fg=revelation.fg,
bg=revelation.bg,
border_color=revelation.border_color,
border_width=revelation.border_width
})
hintbox[char].ontop = true
hintbox[char].width = revelation.hintsize
hintbox[char].height = revelation.hintsize
letterbox[char] = wibox.widget.textbox()
letterbox[char]:set_markup(char.upper(char))
letterbox[char]:set_font(revelation.font)
letterbox[char]:set_align("center")
hintbox[char]:set_widget(letterbox[char])
end
end
setmetatable(revelation, { __call = function(_, ...) return revelation.expose(...) end })
return revelation

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB