refactor
|
@ -0,0 +1,13 @@
|
||||||
|
if os.getenv "LOCAL_LUA_DEBUGGER_VSCODE" == "1" then
|
||||||
|
require("lldebugger").start()
|
||||||
|
end
|
||||||
|
|
||||||
|
local function lua_module_paths(module_base_path)
|
||||||
|
return (module_base_path .. "/?.lua;") .. (module_base_path .. "/?/init.lua;")
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
_all = {
|
||||||
|
lpath = lua_module_paths "src",
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
"words": [
|
||||||
|
"Aire-One",
|
||||||
|
"autofocus",
|
||||||
|
"awesomerc",
|
||||||
|
"byidx",
|
||||||
|
"capi",
|
||||||
|
"closebutton",
|
||||||
|
"confdir",
|
||||||
|
"conffile",
|
||||||
|
"currenttags",
|
||||||
|
"dbus",
|
||||||
|
"drawin",
|
||||||
|
"dryrun",
|
||||||
|
"fatalwarnings",
|
||||||
|
"floatingbutton",
|
||||||
|
"fullscreen",
|
||||||
|
"getmaster",
|
||||||
|
"halign",
|
||||||
|
"iconwidget",
|
||||||
|
"imagebox",
|
||||||
|
"incmwfact",
|
||||||
|
"incncol",
|
||||||
|
"incnmaster",
|
||||||
|
"jumpto",
|
||||||
|
"keyboardlayout",
|
||||||
|
"keygrabber",
|
||||||
|
"keygroup",
|
||||||
|
"layoutbox",
|
||||||
|
"ldoc",
|
||||||
|
"lldebugger",
|
||||||
|
"lpath",
|
||||||
|
"luacheck",
|
||||||
|
"luacheckrc",
|
||||||
|
"luamon",
|
||||||
|
"luamonrc",
|
||||||
|
"luarocks",
|
||||||
|
"maximizedbutton",
|
||||||
|
"modkey",
|
||||||
|
"mousebinding",
|
||||||
|
"mousebindings",
|
||||||
|
"mousegrabber",
|
||||||
|
"noreset",
|
||||||
|
"numpad",
|
||||||
|
"numrow",
|
||||||
|
"ontop",
|
||||||
|
"ontopbutton",
|
||||||
|
"pkill",
|
||||||
|
"rcfile",
|
||||||
|
"rockspec",
|
||||||
|
"stickybutton",
|
||||||
|
"Stylua",
|
||||||
|
"systray",
|
||||||
|
"taglist",
|
||||||
|
"tasklist",
|
||||||
|
"textbox",
|
||||||
|
"textclock",
|
||||||
|
"titlebar",
|
||||||
|
"titlebars",
|
||||||
|
"titlewidget",
|
||||||
|
"unminimize",
|
||||||
|
"valign",
|
||||||
|
"viewnext",
|
||||||
|
"viewprev",
|
||||||
|
"viewtoggle",
|
||||||
|
"wibar",
|
||||||
|
"wibox",
|
||||||
|
"xephyr"
|
||||||
|
]
|
||||||
|
}
|
|
@ -5,8 +5,17 @@ root = true
|
||||||
|
|
||||||
[*]
|
[*]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 4
|
indent_size = 3
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.sh]
|
||||||
|
indent_size = 4
|
||||||
|
|
||||||
|
[Makefile]
|
||||||
|
indent_style = tab
|
||||||
|
|
44
.luacheckrc
|
@ -1,10 +1,28 @@
|
||||||
-- Only allow symbols available in all Lua versions
|
std = "lua54"
|
||||||
std = "min"
|
|
||||||
|
|
||||||
-- Get rid of "unused argument self"-warnings
|
files[".luamonrc"].std = {
|
||||||
self = false
|
globals = {
|
||||||
|
"ext",
|
||||||
|
"lang",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
files["awesomerc-dev-1.rockspec"].ignore = {
|
||||||
|
"631", -- Line is too long.
|
||||||
|
}
|
||||||
|
|
||||||
|
include_files = {
|
||||||
|
".busted",
|
||||||
|
".luacheckrc",
|
||||||
|
".luamonrc",
|
||||||
|
"*.rockspec",
|
||||||
|
"src/**/*.lua",
|
||||||
|
}
|
||||||
|
|
||||||
|
exclude_files = {
|
||||||
|
"src/awesome-wm-nice", -- Vendored code with its own .luacheckrc
|
||||||
|
}
|
||||||
|
|
||||||
-- Global objects defined by the C code
|
|
||||||
read_globals = {
|
read_globals = {
|
||||||
"awesome",
|
"awesome",
|
||||||
"button",
|
"button",
|
||||||
|
@ -21,13 +39,9 @@ read_globals = {
|
||||||
"math.atan2",
|
"math.atan2",
|
||||||
}
|
}
|
||||||
|
|
||||||
-- screen may not be read-only, because newer luacheck versions complain about
|
globals = {
|
||||||
-- screen[1].tags[1].selected = true.
|
"screen",
|
||||||
-- The same happens with the following code:
|
"mouse",
|
||||||
-- local tags = mouse.screen.tags
|
"root",
|
||||||
-- tags[7].index = 4
|
"client",
|
||||||
-- client may not be read-only due to client.focus.
|
}
|
||||||
globals = { "screen", "mouse", "root", "client" }
|
|
||||||
|
|
||||||
-- Enable cache (uses .luacheckcache relative to this rc file).
|
|
||||||
cache = true
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
ext = { "lua" }
|
||||||
|
lang = "./scripts/run.sh runAwesome"
|
|
@ -0,0 +1,6 @@
|
||||||
|
indent_type = "Spaces"
|
||||||
|
indent_width = 3
|
||||||
|
call_parentheses = "None"
|
||||||
|
|
||||||
|
[sort_requires]
|
||||||
|
enabled = true
|
|
@ -1,9 +1,10 @@
|
||||||
{
|
{
|
||||||
"recommendations": [
|
"recommendations": [
|
||||||
"editorconfig.editorconfig",
|
"streetsidesoftware.code-spell-checker",
|
||||||
"tomblind.local-lua-debugger-vscode",
|
"editorconfig.editorconfig",
|
||||||
"sumneko.lua",
|
"tomblind.local-lua-debugger-vscode",
|
||||||
"johnnymorganz.stylua",
|
"johnnymorganz.stylua",
|
||||||
"dwenegar.vscode-luacheck"
|
"dwenegar.vscode-luacheck",
|
||||||
]
|
"sumneko.lua"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,17 @@
|
||||||
{
|
{
|
||||||
"version": "0.2.0",
|
// Use IntelliSense to learn about possible attributes.
|
||||||
"configurations": [
|
// Hover to view descriptions of existing attributes.
|
||||||
{
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
"type": "lua-local",
|
"version": "0.2.0",
|
||||||
"request": "launch",
|
"configurations": [
|
||||||
"name": "Debug with Xephyr",
|
{
|
||||||
"program": {
|
"type": "lua-local",
|
||||||
"command": "${workspaceFolder}/start-xephyr.sh"
|
"request": "launch",
|
||||||
},
|
"name": "Debug with Xephyr",
|
||||||
"args": [
|
"program": {
|
||||||
"/usr/bin/Xephyr",
|
"command": "${workspaceFolder}/scripts/run.sh"
|
||||||
"/usr/bin/awesome",
|
},
|
||||||
"${workspaceFolder}/init.lua"
|
"args": ["debug"]
|
||||||
],
|
}
|
||||||
"postDebugTask": "Terminate All Tasks"
|
]
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,20 @@
|
||||||
{
|
{
|
||||||
"editor.formatOnSave": true,
|
"Lua.runtime.path": [
|
||||||
"editor.formatOnPaste": true,
|
"/usr/share/awesome/lib/?.lua",
|
||||||
"[markdown]": {
|
"/usr/share/awesome/lib/?/init.lua",
|
||||||
"editor.wordWrap": "on",
|
"${workspaceFolder}/src/?.lua",
|
||||||
"editor.renderWhitespace": "all",
|
"${workspaceFolder}/src/init.lua",
|
||||||
"editor.acceptSuggestionOnEnter": "off"
|
"${workspaceFolder}/src/?/init.lua"
|
||||||
}
|
],
|
||||||
|
"[lua]": {
|
||||||
|
"editor.defaultFormatter": "JohnnyMorganz.stylua"
|
||||||
|
},
|
||||||
|
"stylua.targetReleaseVersion": "latest",
|
||||||
|
"files.associations": {
|
||||||
|
".busted": "lua",
|
||||||
|
".luacheckrc": "lua",
|
||||||
|
".luamonrc": "lua",
|
||||||
|
"*.rockspec": "lua"
|
||||||
|
},
|
||||||
|
"Lua.runtime.version": "Lua 5.4"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
{
|
|
||||||
"version": "2.0.0",
|
|
||||||
"tasks": [
|
|
||||||
{
|
|
||||||
"label": "Terminate All Tasks",
|
|
||||||
"command": "${workspaceFolder}/start-xephyr.sh stop",
|
|
||||||
"type": "shell",
|
|
||||||
"problemMatcher": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"inputs": [
|
|
||||||
{
|
|
||||||
"id": "terminate",
|
|
||||||
"type": "command",
|
|
||||||
"command": "workbench.action.tasks.terminate",
|
|
||||||
"args": "terminateAll"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
dev:
|
||||||
|
scripts/run.sh start
|
||||||
|
|
||||||
|
test:
|
||||||
|
luarocks test
|
||||||
|
|
||||||
|
# Install the rock in the local tree (aka user home directory)
|
||||||
|
deploy:
|
||||||
|
luarocks --local build --force
|
||||||
|
mkdir -p ~/.config/awesome
|
||||||
|
cp -rv config/awesome ~/.config
|
||||||
|
|
||||||
|
try-current:
|
||||||
|
scripts/run.sh try-current
|
||||||
|
|
||||||
|
luacheck:
|
||||||
|
luacheck .
|
||||||
|
|
||||||
|
stylua:
|
||||||
|
stylua --check .
|
||||||
|
|
||||||
|
# ldoc-dryrun:
|
||||||
|
# $(eval TMP := $(shell mktemp -d))
|
||||||
|
# ldoc --fatalwarnings --dir $(TMP) .
|
||||||
|
# rm -rf $(TMP)
|
||||||
|
|
||||||
|
cspell:
|
||||||
|
cspell lint .
|
||||||
|
|
||||||
|
lint-rockspec:
|
||||||
|
luarocks lint awesomerc-dev-1.rockspec
|
||||||
|
|
||||||
|
# For now:
|
||||||
|
# - we don't run ldoc-dryrun because we don't have documentation
|
||||||
|
# - we don't run cspell because there are too many problems I don't want to fix now since the code will change
|
||||||
|
# lint: luacheck stylua ldoc-dryrun cspell lint-rockspec
|
||||||
|
lint: luacheck stylua lint-rockspec
|
|
@ -0,0 +1,77 @@
|
||||||
|
rockspec_format = "3.0"
|
||||||
|
|
||||||
|
package = "awesomerc"
|
||||||
|
version = "dev-1"
|
||||||
|
|
||||||
|
source = {
|
||||||
|
url = "git://gitea.aireone.xyz/Aire-One/awesomerc.git",
|
||||||
|
}
|
||||||
|
|
||||||
|
description = {
|
||||||
|
homepage = "https://gitea.aireone.xyz/Aire-One/awesomerc",
|
||||||
|
license = "GPL 2.0", -- TODO: git add the LICENSE file
|
||||||
|
-- Vendored awesome-wm-nice is licensed by mut-ex under the MIT license.
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies = {
|
||||||
|
"awesome-slot",
|
||||||
|
"awesome-battery_widget",
|
||||||
|
}
|
||||||
|
|
||||||
|
build = {
|
||||||
|
type = "builtin",
|
||||||
|
modules = {
|
||||||
|
["awesomerc.configuration.applications"] = "src/awesomerc/configuration/applications.lua",
|
||||||
|
["awesomerc.configuration.bindings.client_keybindings"] = "src/awesomerc/configuration/bindings/client_keybindings.lua",
|
||||||
|
["awesomerc.configuration.bindings.client_mousebindings"] = "src/awesomerc/configuration/bindings/client_mousebindings.lua",
|
||||||
|
["awesomerc.configuration.bindings.global_keybindings"] = "src/awesomerc/configuration/bindings/global_keybindings.lua",
|
||||||
|
["awesomerc.configuration.bindings.global_mousebindings"] = "src/awesomerc/configuration/bindings/global_mousebindings.lua",
|
||||||
|
["awesomerc.configuration.bindings.init"] = "src/awesomerc/configuration/bindings/init.lua",
|
||||||
|
["awesomerc.configuration.bindings.utils"] = "src/awesomerc/configuration/bindings/utils.lua",
|
||||||
|
["awesomerc.configuration.init"] = "src/awesomerc/configuration/init.lua",
|
||||||
|
["awesomerc.configuration.menu.init"] = "src/awesomerc/configuration/menu/init.lua",
|
||||||
|
["awesomerc.configuration.menu.myawesomemenu"] = "src/awesomerc/configuration/menu/myawesomemenu.lua",
|
||||||
|
["awesomerc.configuration.menu.mymainmenu"] = "src/awesomerc/configuration/menu/mymainmenu.lua",
|
||||||
|
["awesomerc.configuration.prompt_commands"] = "src/awesomerc/configuration/prompt_commands.lua",
|
||||||
|
["awesomerc.configuration.rules.client.firefox"] = "src/awesomerc/configuration/rules/client/firefox.lua",
|
||||||
|
["awesomerc.configuration.rules.client.floating"] = "src/awesomerc/configuration/rules/client/floating.lua",
|
||||||
|
["awesomerc.configuration.rules.client.global"] = "src/awesomerc/configuration/rules/client/global.lua",
|
||||||
|
["awesomerc.configuration.rules.client.init"] = "src/awesomerc/configuration/rules/client/init.lua",
|
||||||
|
["awesomerc.configuration.rules.client.titlebars"] = "src/awesomerc/configuration/rules/client/titlebars.lua",
|
||||||
|
["awesomerc.configuration.rules.init"] = "src/awesomerc/configuration/rules/init.lua",
|
||||||
|
["awesomerc.configuration.rules.notification.global"] = "src/awesomerc/configuration/rules/notification/global.lua",
|
||||||
|
["awesomerc.configuration.rules.notification.init"] = "src/awesomerc/configuration/rules/notification/init.lua",
|
||||||
|
["awesomerc.configuration.tag_layouts"] = "src/awesomerc/configuration/tag_layouts.lua",
|
||||||
|
["awesomerc.slots.init"] = "src/awesomerc/slots/init.lua",
|
||||||
|
["awesomerc.theme.init"] = "src/awesomerc/theme/init.lua",
|
||||||
|
["awesomerc.ui.desktop_decoration.bar.init"] = "src/awesomerc/ui/desktop_decoration/bar/init.lua",
|
||||||
|
["awesomerc.ui.desktop_decoration.bar.widgets.battery"] = "src/awesomerc/ui/desktop_decoration/bar/widgets/battery.lua",
|
||||||
|
["awesomerc.ui.desktop_decoration.bar.widgets.init"] = "src/awesomerc/ui/desktop_decoration/bar/widgets/init.lua",
|
||||||
|
["awesomerc.ui.desktop_decoration.bar.widgets.prompt"] = "src/awesomerc/ui/desktop_decoration/bar/widgets/prompt.lua",
|
||||||
|
["awesomerc.ui.desktop_decoration.init"] = "src/awesomerc/ui/desktop_decoration/init.lua",
|
||||||
|
["awesomerc.ui.hotkeys_popup.init"] = "src/awesomerc/ui/hotkeys_popup/init.lua",
|
||||||
|
["awesomerc.ui.menu.mymainmenu"] = "src/awesomerc/ui/menu/mymainmenu.lua",
|
||||||
|
["awesomerc.ui.titlebar.init"] = "src/awesomerc/ui/titlebar/init.lua",
|
||||||
|
["awesomerc.init"] = "src/awesomerc/init.lua",
|
||||||
|
["awesome-legacy.autofocus.init"] = "src/awesome-legacy/autofocus/init.lua",
|
||||||
|
["awesome-legacy.manage_error.init"] = "src/awesome-legacy/manage_error/init.lua",
|
||||||
|
["awesome-legacy.sloppy_focus.init"] = "src/awesome-legacy/sloppy_focus/init.lua",
|
||||||
|
["awesome-legacy.init"] = "src/awesome-legacy/init.lua",
|
||||||
|
["MyTagListWidget.TagItem_widget"] = "src/MyTagListWidget/TagItem_widget.lua",
|
||||||
|
["MyTagListWidget.init"] = "src/MyTagListWidget/init.lua",
|
||||||
|
["MyTagListWidget.mockup"] = "src/MyTagListWidget/mockup.lua",
|
||||||
|
["MyTagListWidget.tests.widget-testrc"] = "src/MyTagListWidget/tests/widget-testrc.lua",
|
||||||
|
["awesome-wm-nice.colors"] = "src/awesome-wm-nice/colors.lua",
|
||||||
|
["awesome-wm-nice.config"] = "src/awesome-wm-nice/config.lua",
|
||||||
|
["awesome-wm-nice.init"] = "src/awesome-wm-nice/init.lua",
|
||||||
|
["awesome-wm-nice.shade"] = "src/awesome-wm-nice/shade.lua",
|
||||||
|
["awesome-wm-nice.shapes"] = "src/awesome-wm-nice/shapes.lua",
|
||||||
|
["awesome-wm-nice.table"] = "src/awesome-wm-nice/table.lua",
|
||||||
|
["awesome-wm-nice.utils"] = "src/awesome-wm-nice/utils.lua",
|
||||||
|
["awesome-wm-nice.widgets"] = "src/awesome-wm-nice/widgets.lua",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
test = {
|
||||||
|
type = "busted",
|
||||||
|
}
|
Before Width: | Height: | Size: 441 B After Width: | Height: | Size: 441 B |
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 337 B |
Before Width: | Height: | Size: 596 B After Width: | Height: | Size: 596 B |
After Width: | Height: | Size: 3.7 MiB |
|
@ -0,0 +1,9 @@
|
||||||
|
-- awesome_mode: api-level=4:screen=on
|
||||||
|
|
||||||
|
if os.getenv "LOCAL_LUA_DEBUGGER_VSCODE" == "1" then
|
||||||
|
require("lldebugger").start()
|
||||||
|
end
|
||||||
|
|
||||||
|
require "luarocks.loader"
|
||||||
|
|
||||||
|
require "awesomerc"
|
|
@ -1,113 +0,0 @@
|
||||||
local akey = require "awful.key"
|
|
||||||
local aclient = require "awful.client"
|
|
||||||
|
|
||||||
local utils = require "rc.configuration.bindings.utils"
|
|
||||||
|
|
||||||
local client_keybindings = {
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "f",
|
|
||||||
description = "toggle fullscreen",
|
|
||||||
group = utils.groups.client,
|
|
||||||
on_press = function(client)
|
|
||||||
client.fullscreen = not client.fullscreen
|
|
||||||
client:raise()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "c",
|
|
||||||
description = "close",
|
|
||||||
group = utils.groups.client,
|
|
||||||
on_press = function(client)
|
|
||||||
client:kill()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.control },
|
|
||||||
key = "space",
|
|
||||||
description = "toggle floating",
|
|
||||||
group = utils.groups.client,
|
|
||||||
on_press = aclient.floating.toggle,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.control },
|
|
||||||
key = "Return",
|
|
||||||
description = "move to master",
|
|
||||||
group = utils.groups.client,
|
|
||||||
on_press = function(client)
|
|
||||||
client:swap(aclient.getmaster())
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "o",
|
|
||||||
description = "move to screen",
|
|
||||||
group = utils.groups.client,
|
|
||||||
on_press = function(client)
|
|
||||||
client:move_to_screen()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "t",
|
|
||||||
description = "toggle keep on top",
|
|
||||||
group = utils.groups.client,
|
|
||||||
on_press = function(client)
|
|
||||||
client.ontop = not client.ontop
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "n",
|
|
||||||
description = "minimize",
|
|
||||||
group = utils.groups.client,
|
|
||||||
on_press = function(client)
|
|
||||||
-- The client currently has the input focus, so it cannot be
|
|
||||||
-- minimized, since minimized clients can't have the focus.
|
|
||||||
client.minimized = true
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "m",
|
|
||||||
description = "(un)maximize",
|
|
||||||
group = utils.groups.client,
|
|
||||||
on_press = function(client)
|
|
||||||
client.maximized = not client.maximized
|
|
||||||
client:raise()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.control },
|
|
||||||
key = "m",
|
|
||||||
description = "(un)maximize vertically",
|
|
||||||
group = utils.groups.client,
|
|
||||||
on_press = function(client)
|
|
||||||
client.maximized_vertical = not client.maximized_vertical
|
|
||||||
client:raise()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.shift },
|
|
||||||
key = "m",
|
|
||||||
description = "(un)maximize horizontally",
|
|
||||||
group = utils.groups.client,
|
|
||||||
on_press = function(client)
|
|
||||||
client.maximized_horizontal = not client.maximized_horizontal
|
|
||||||
client:raise()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return client_keybindings
|
|
|
@ -1,39 +0,0 @@
|
||||||
local abutton = require "awful.button"
|
|
||||||
|
|
||||||
local utils = require "rc.configuration.bindings.utils"
|
|
||||||
|
|
||||||
local mousebindings = {
|
|
||||||
abutton {
|
|
||||||
modifiers = {},
|
|
||||||
button = abutton.names.LEFT,
|
|
||||||
on_press = function(client)
|
|
||||||
client:activate {
|
|
||||||
context = "mouse_click",
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
abutton {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
button = abutton.names.LEFT,
|
|
||||||
on_press = function(client)
|
|
||||||
client:activate {
|
|
||||||
context = "mouse_click",
|
|
||||||
action = "mouse_move",
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
abutton {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
button = abutton.names.RIGHT,
|
|
||||||
on_press = function(client)
|
|
||||||
client:activate {
|
|
||||||
context = "mouse_click",
|
|
||||||
action = "mouse_resize",
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return mousebindings
|
|
|
@ -1,223 +0,0 @@
|
||||||
local aclient = require "awful.client"
|
|
||||||
local akey = require "awful.key"
|
|
||||||
local aprompt = require "awful.prompt"
|
|
||||||
local ascreen = require "awful.screen"
|
|
||||||
local aspawn = require "awful.spawn"
|
|
||||||
local atag = require "awful.tag"
|
|
||||||
local autil = require "awful.util"
|
|
||||||
|
|
||||||
local menubar = require "menubar"
|
|
||||||
|
|
||||||
local applications = require "rc.configuration.applications"
|
|
||||||
local desktop_bar = require "rc.ui.desktop_decoration.bar"
|
|
||||||
local hotkeys_popup = require "rc.ui.hotkeys_popup"
|
|
||||||
local mymainmenu = require "rc.ui.menu.mymainmenu"
|
|
||||||
|
|
||||||
local utils = require "rc.configuration.bindings.utils"
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
awesome = _G.awesome,
|
|
||||||
client = _G.client,
|
|
||||||
}
|
|
||||||
|
|
||||||
local global_keybindings = {
|
|
||||||
|
|
||||||
-- Awesome
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "s",
|
|
||||||
description = "show help",
|
|
||||||
group = utils.groups.awesome,
|
|
||||||
on_press = function()
|
|
||||||
hotkeys_popup.show_help()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "w",
|
|
||||||
description = "show main menu",
|
|
||||||
group = utils.groups.awesome,
|
|
||||||
on_press = function()
|
|
||||||
mymainmenu():show()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.control },
|
|
||||||
key = "r",
|
|
||||||
description = "reload awesome",
|
|
||||||
group = utils.groups.awesome,
|
|
||||||
on_press = capi.awesome.restart,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.shift },
|
|
||||||
key = "q",
|
|
||||||
description = "quit awesome",
|
|
||||||
group = utils.groups.awesome,
|
|
||||||
on_press = capi.awesome.quit,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "x",
|
|
||||||
description = "lua execute prompt",
|
|
||||||
group = utils.groups.awesome,
|
|
||||||
on_press = function()
|
|
||||||
aprompt.run {
|
|
||||||
prompt = "Run Lua code: ",
|
|
||||||
textbox = desktop_bar(ascreen.focused()).promptbox.widget,
|
|
||||||
exe_callback = autil.eval,
|
|
||||||
history_path = autil.get_cache_dir() .. "/history_eval",
|
|
||||||
}
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
-- Launcher
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "Return",
|
|
||||||
description = "open a terminal",
|
|
||||||
group = utils.groups.launcher,
|
|
||||||
on_press = function()
|
|
||||||
aspawn(applications.open_terminal())
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "r",
|
|
||||||
description = "run prompt",
|
|
||||||
group = utils.groups.launcher,
|
|
||||||
on_press = function()
|
|
||||||
desktop_bar(ascreen.focused()).promptbox:run()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "p",
|
|
||||||
description = "show the menubar",
|
|
||||||
group = utils.groups.launcher,
|
|
||||||
on_press = function()
|
|
||||||
menubar.show()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
-- Client focus
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "j",
|
|
||||||
group = "client",
|
|
||||||
description = "Focus next client by index",
|
|
||||||
on_press = function()
|
|
||||||
aclient.focus.byidx(1)
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
key = "k",
|
|
||||||
group = "client",
|
|
||||||
description = "Focus previous by index",
|
|
||||||
on_press = function()
|
|
||||||
aclient.focus.byidx(-1)
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
-- Layout manipulation
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.shift },
|
|
||||||
key = "j",
|
|
||||||
group = "client",
|
|
||||||
description = "Swap with next client",
|
|
||||||
on_press = function()
|
|
||||||
aclient.swap.byidx(1)
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.shift },
|
|
||||||
key = "k",
|
|
||||||
group = "client",
|
|
||||||
description = "Swap with previous client",
|
|
||||||
on_press = function()
|
|
||||||
aclient.swap.byidx(-1)
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.shift },
|
|
||||||
key = "Right",
|
|
||||||
description = "Increase master width factor",
|
|
||||||
group = "client",
|
|
||||||
on_press = function()
|
|
||||||
atag.incmwfact(0.01)
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.shift },
|
|
||||||
key = "Left",
|
|
||||||
description = "Decrease master width factor",
|
|
||||||
group = "client",
|
|
||||||
on_press = function()
|
|
||||||
atag.incmwfact(-0.01)
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
-- Tags manipulation
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey },
|
|
||||||
keygroup = akey.keygroup.NUMROW,
|
|
||||||
description = "only view tag",
|
|
||||||
group = "tag",
|
|
||||||
on_press = function(index)
|
|
||||||
local screen = ascreen.focused()
|
|
||||||
local tag = screen.tags[index]
|
|
||||||
|
|
||||||
if tag then
|
|
||||||
tag:view_only()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.control },
|
|
||||||
keygroup = akey.keygroup.NUMROW,
|
|
||||||
description = "toggle tag",
|
|
||||||
group = "tag",
|
|
||||||
on_press = function(index)
|
|
||||||
local screen = ascreen.focused()
|
|
||||||
local tag = screen.tags[index]
|
|
||||||
|
|
||||||
if tag then
|
|
||||||
atag.viewtoggle(tag)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
akey {
|
|
||||||
modifiers = { utils.mods.modkey, utils.mods.shift },
|
|
||||||
keygroup = akey.keygroup.NUMROW,
|
|
||||||
description = "move focused client to tag",
|
|
||||||
group = "tag",
|
|
||||||
on_press = function(index)
|
|
||||||
local screen = ascreen.focused()
|
|
||||||
local client = capi.client.focus
|
|
||||||
local tag = screen.tags[index]
|
|
||||||
|
|
||||||
if client and tag then
|
|
||||||
client:move_to_tag(tag)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return global_keybindings
|
|
|
@ -1,28 +0,0 @@
|
||||||
local abutton = require "awful.button"
|
|
||||||
local atag = require "awful.tag"
|
|
||||||
|
|
||||||
local mymainmenu = require "rc.ui.menu.mymainmenu"
|
|
||||||
|
|
||||||
local global_mousebindings = {
|
|
||||||
abutton {
|
|
||||||
modifiers = {},
|
|
||||||
button = abutton.names.RIGHT,
|
|
||||||
on_press = function()
|
|
||||||
mymainmenu():toggle()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
|
|
||||||
abutton {
|
|
||||||
modifiers = {},
|
|
||||||
button = abutton.names.SCROLL_UP,
|
|
||||||
on_press = tag.viewprev,
|
|
||||||
},
|
|
||||||
|
|
||||||
abutton {
|
|
||||||
modifiers = {},
|
|
||||||
button = abutton.names.SCROLL_DOWN,
|
|
||||||
on_press = atag.viewnext,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return global_mousebindings
|
|
|
@ -1,13 +0,0 @@
|
||||||
local bindings = {}
|
|
||||||
|
|
||||||
bindings.client_keybindings =
|
|
||||||
require "rc.configuration.bindings.client_keybindings"
|
|
||||||
bindings.client_mousebindings =
|
|
||||||
require "rc.configuration.bindings.client_mousebindings"
|
|
||||||
bindings.global_keybindings =
|
|
||||||
require "rc.configuration.bindings.global_keybindings"
|
|
||||||
bindings.global_mousebindings =
|
|
||||||
require "rc.configuration.bindings.global_mousebindings"
|
|
||||||
bindings.utils = require "rc.configuration.bindings.utils"
|
|
||||||
|
|
||||||
return bindings
|
|
|
@ -1,16 +0,0 @@
|
||||||
local mods = {
|
|
||||||
control = "Control",
|
|
||||||
modkey = "Mod4",
|
|
||||||
shift = "Shift",
|
|
||||||
}
|
|
||||||
|
|
||||||
local groups = {
|
|
||||||
client = "client",
|
|
||||||
awesome = "awesome",
|
|
||||||
launcher = "launcher",
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
mods = mods,
|
|
||||||
groups = groups,
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
local rc_configuration = {}
|
|
||||||
|
|
||||||
rc_configuration.applications = require "rc.configuration.applications"
|
|
||||||
rc_configuration.bindings = require "rc.configuration.bindings"
|
|
||||||
rc_configuration.menu = require "rc.configuration.menu"
|
|
||||||
rc_configuration.rules = require "rc.configuration.rules"
|
|
||||||
rc_configuration.prompt_commands = require "rc.configuration.prompt_commands"
|
|
||||||
rc_configuration.tag_layouts = require "rc.configuration.tag_layouts"
|
|
||||||
|
|
||||||
return rc_configuration
|
|
|
@ -1,6 +0,0 @@
|
||||||
local configuration_menu = {}
|
|
||||||
|
|
||||||
configuration_menu.myawesomemenu = require "rc.configuration.menu.myawesomemenu"
|
|
||||||
configuration_menu.mymainmenu = require "rc.configuration.menu.mymainmenu"
|
|
||||||
|
|
||||||
return configuration_menu
|
|
|
@ -1,31 +0,0 @@
|
||||||
local applications = require "rc.configuration.applications"
|
|
||||||
local hotkeys_popup = require "rc.ui.hotkeys_popup"
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
awesome = _G.awesome,
|
|
||||||
}
|
|
||||||
|
|
||||||
local myawesomemenu = {
|
|
||||||
{
|
|
||||||
"hotkeys",
|
|
||||||
function()
|
|
||||||
hotkeys_popup.show_help()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
{ "manual", applications.open_man "awesome" },
|
|
||||||
{ "edit config", applications.open_editor(capi.awesome.conffile) },
|
|
||||||
{
|
|
||||||
"restart",
|
|
||||||
function()
|
|
||||||
capi.awesome.restart()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"quit",
|
|
||||||
function()
|
|
||||||
capi.awesome.quit()
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return myawesomemenu
|
|
|
@ -1,11 +0,0 @@
|
||||||
local beautiful = require "beautiful"
|
|
||||||
|
|
||||||
local applications = require "rc.configuration.applications"
|
|
||||||
local myawesomemenu = require "rc.configuration.menu.myawesomemenu"
|
|
||||||
|
|
||||||
local mymainmenu = {
|
|
||||||
{ "awesome", myawesomemenu, beautiful.awesome_icon },
|
|
||||||
{ "open terminal", applications.terminal },
|
|
||||||
}
|
|
||||||
|
|
||||||
return mymainmenu
|
|
|
@ -1,50 +0,0 @@
|
||||||
local atag = require "awful.tag"
|
|
||||||
local layout_suit = require "awful.layout.suit"
|
|
||||||
|
|
||||||
local commands = {}
|
|
||||||
|
|
||||||
commands["o"] = {
|
|
||||||
callback = function(parameters)
|
|
||||||
local tag_name = parameters[1] or "New-Tag"
|
|
||||||
|
|
||||||
atag.add(tag_name, {
|
|
||||||
layout = layout_suit.tile,
|
|
||||||
}):view_only()
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
commands["O"] = {
|
|
||||||
callback = function(parameters)
|
|
||||||
local aspawn = require "awful.spawn"
|
|
||||||
|
|
||||||
local application = parameters[1]
|
|
||||||
local tag_name = parameters[2] or application
|
|
||||||
|
|
||||||
local t = atag.add(tag_name, {
|
|
||||||
layout = layout_suit.tile,
|
|
||||||
volatile = true,
|
|
||||||
})
|
|
||||||
t:view_only()
|
|
||||||
aspawn(application, { tag = t })
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
commands["q"] = {
|
|
||||||
callback = function()
|
|
||||||
local ascreen = require "awful.screen"
|
|
||||||
|
|
||||||
local tags = ascreen.focused().selected_tags
|
|
||||||
|
|
||||||
for _, tag in ipairs(tags) do
|
|
||||||
tag.volatile = true
|
|
||||||
|
|
||||||
for _, client in ipairs(tag:clients()) do
|
|
||||||
client:kill()
|
|
||||||
end
|
|
||||||
|
|
||||||
tag:delete()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
return commands
|
|
|
@ -1,7 +0,0 @@
|
||||||
local firefox_rule = {
|
|
||||||
id = "firefox",
|
|
||||||
rule = { class = "Firefox" },
|
|
||||||
properties = { screen = 1, tag = "2" },
|
|
||||||
}
|
|
||||||
|
|
||||||
return firefox_rule
|
|
|
@ -1,28 +0,0 @@
|
||||||
local floating_rule = {
|
|
||||||
id = "floating",
|
|
||||||
rule_any = {
|
|
||||||
instance = { "copyq", "pinentry" },
|
|
||||||
class = {
|
|
||||||
"Arandr",
|
|
||||||
"Blueman-manager",
|
|
||||||
"Gpick",
|
|
||||||
"Kruler",
|
|
||||||
"Sxiv",
|
|
||||||
"Tor Browser",
|
|
||||||
"Wpa_gui",
|
|
||||||
"veromix",
|
|
||||||
"xtightvncviewer",
|
|
||||||
},
|
|
||||||
name = {
|
|
||||||
"Event Tester", -- xev.
|
|
||||||
},
|
|
||||||
role = {
|
|
||||||
"AlarmWindow", -- Thunderbird's calendar.
|
|
||||||
"ConfigManager", -- Thunderbird's about:config.
|
|
||||||
"pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
|
|
||||||
},
|
|
||||||
},
|
|
||||||
properties = { floating = true },
|
|
||||||
}
|
|
||||||
|
|
||||||
return floating_rule
|
|
|
@ -1,16 +0,0 @@
|
||||||
local aclient = require "awful.client"
|
|
||||||
local aplacement = require "awful.placement"
|
|
||||||
local ascreen = require "awful.screen"
|
|
||||||
|
|
||||||
local global_rule = {
|
|
||||||
id = "global",
|
|
||||||
rule = {},
|
|
||||||
properties = {
|
|
||||||
focus = aclient.focus.filter,
|
|
||||||
raise = true,
|
|
||||||
screen = ascreen.preferred,
|
|
||||||
placement = aplacement.no_overlap + aplacement.no_offscreen,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return global_rule
|
|
|
@ -1,8 +0,0 @@
|
||||||
local client_rules = {}
|
|
||||||
|
|
||||||
client_rules.global = require "rc.configuration.rules.client.global"
|
|
||||||
client_rules.floating = require "rc.configuration.rules.client.floating"
|
|
||||||
client_rules.titlebar = require "rc.configuration.rules.client.titlebars"
|
|
||||||
-- client_rules.firefox = require 'rc.configuration.rules.client.firefox'
|
|
||||||
|
|
||||||
return client_rules
|
|
|
@ -1,9 +0,0 @@
|
||||||
local titlebar_rule = {
|
|
||||||
id = "titlebars",
|
|
||||||
rule_any = {
|
|
||||||
type = { "normal", "dialog" },
|
|
||||||
},
|
|
||||||
properties = { titlebars_enabled = true },
|
|
||||||
}
|
|
||||||
|
|
||||||
return titlebar_rule
|
|
|
@ -1,6 +0,0 @@
|
||||||
local rules = {}
|
|
||||||
|
|
||||||
rules.client = require "rc.configuration.rules.client"
|
|
||||||
rules.notification = require "rc.configuration.rules.notification"
|
|
||||||
|
|
||||||
return rules
|
|
|
@ -1,11 +0,0 @@
|
||||||
local ascreen = require "awful.screen"
|
|
||||||
|
|
||||||
local global_rule = {
|
|
||||||
rule = {},
|
|
||||||
properties = {
|
|
||||||
screen = ascreen.preferred,
|
|
||||||
implicit_timeout = 5,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return global_rule
|
|
|
@ -1,5 +0,0 @@
|
||||||
local notification_rules = {}
|
|
||||||
|
|
||||||
notification_rules.global = require "rc.configuration.rules.notification.global"
|
|
||||||
|
|
||||||
return notification_rules
|
|
|
@ -1,19 +0,0 @@
|
||||||
local alayout = require "awful.layout"
|
|
||||||
|
|
||||||
local tag_layouts = {
|
|
||||||
alayout.suit.floating,
|
|
||||||
alayout.suit.tile,
|
|
||||||
alayout.suit.tile.left,
|
|
||||||
alayout.suit.tile.bottom,
|
|
||||||
alayout.suit.tile.top,
|
|
||||||
alayout.suit.fair,
|
|
||||||
alayout.suit.fair.horizontal,
|
|
||||||
alayout.suit.spiral,
|
|
||||||
alayout.suit.spiral.dwindle,
|
|
||||||
alayout.suit.max,
|
|
||||||
alayout.suit.max.fullscreen,
|
|
||||||
alayout.suit.magnifier,
|
|
||||||
alayout.suit.corner.nw,
|
|
||||||
}
|
|
||||||
|
|
||||||
return tag_layouts
|
|
153
init.lua
|
@ -1,153 +0,0 @@
|
||||||
-- awesome_mode: api-level=4:screen=on
|
|
||||||
|
|
||||||
if os.getenv "LOCAL_LUA_DEBUGGER_VSCODE" == "1" then
|
|
||||||
require("lldebugger").start()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- If LuaRocks is installed, make sure that packages installed through it are
|
|
||||||
-- found (e.g. lgi). If LuaRocks is not installed, do nothing.
|
|
||||||
pcall(require, "luarocks.loader")
|
|
||||||
|
|
||||||
local gtimer = require "gears.timer"
|
|
||||||
local legacy = require "awesome-legacy"
|
|
||||||
local naughty = require "naughty"
|
|
||||||
local ruled = require "ruled"
|
|
||||||
local slot = require "awesome-slot"
|
|
||||||
|
|
||||||
-- Load global awesome components from the C API
|
|
||||||
local capi = {
|
|
||||||
client = _G.client,
|
|
||||||
screen = _G.screen,
|
|
||||||
tag = _G.tag,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Beautiful needs to be initialized as soon as possible to make theme
|
|
||||||
-- variables available to the configuration module.
|
|
||||||
legacy.beautiful {
|
|
||||||
base = "default",
|
|
||||||
theme = require "rc.theme",
|
|
||||||
}
|
|
||||||
|
|
||||||
legacy.manage_error()
|
|
||||||
legacy.autofocus()
|
|
||||||
legacy.sloppy_focus()
|
|
||||||
|
|
||||||
local configuration = require "rc.configuration"
|
|
||||||
local my_slots = require "rc.slots"
|
|
||||||
|
|
||||||
-- This needs to be run after awesome has completed C API initialization and
|
|
||||||
-- the `root` object is available.
|
|
||||||
gtimer.delayed_call(function()
|
|
||||||
legacy.global_mouse_bindings(configuration.bindings.global_mousebindings)
|
|
||||||
legacy.global_keybindings(configuration.bindings.global_keybindings)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- luacheck: ignore unused variable load_wallpaper
|
|
||||||
local load_wallpaper = slot {
|
|
||||||
id = "LOAD_WALLPAPER",
|
|
||||||
connect = true,
|
|
||||||
target = capi.screen,
|
|
||||||
signal = "request::wallpaper",
|
|
||||||
slot = my_slots.wallpaper,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- luacheck: ignore unused variable default_layout
|
|
||||||
local default_layout = slot {
|
|
||||||
id = "DEFAULT_LAYOUTS",
|
|
||||||
connect = true,
|
|
||||||
target = capi.tag,
|
|
||||||
signal = "request::default_layouts",
|
|
||||||
slot = slot.slots.tag.default_layouts,
|
|
||||||
slot_params = {
|
|
||||||
layouts = configuration.tag_layouts,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
-- luacheck: ignore unused variable create_tag
|
|
||||||
local create_tag = slot {
|
|
||||||
id = "CREATE_TAGS",
|
|
||||||
connect = true,
|
|
||||||
target = capi.screen,
|
|
||||||
signal = "request::desktop_decoration",
|
|
||||||
slot = my_slots.create_tags,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- luacheck: ignore unused variable desktop_decoration
|
|
||||||
local desktop_decoration = slot {
|
|
||||||
id = "DESKTOP_DECORATION",
|
|
||||||
connect = true,
|
|
||||||
target = capi.screen,
|
|
||||||
signal = "request::desktop_decoration",
|
|
||||||
slot = my_slots.build_desktop_decoration,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- luacheck: ignore unused variable client_mousebinding
|
|
||||||
local client_mousebinding = slot {
|
|
||||||
id = "CLIENT_MOUSE_BINDINGS",
|
|
||||||
connect = true,
|
|
||||||
target = capi.client,
|
|
||||||
signal = "request::default_mousebindings",
|
|
||||||
slot = slot.slots.client.append_mousebindings,
|
|
||||||
slot_params = {
|
|
||||||
mousebindings = configuration.bindings.client_mousebindings,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
-- luacheck: ignore unused variable client_keybinding
|
|
||||||
local client_keybinding = slot {
|
|
||||||
id = "CLIENT_KEY_BINDINGS",
|
|
||||||
connect = true,
|
|
||||||
target = capi.client,
|
|
||||||
signal = "request::default_keybindings",
|
|
||||||
slot = slot.slots.client.append_keybindings,
|
|
||||||
slot_params = {
|
|
||||||
keybindings = configuration.bindings.client_keybindings,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
-- luacheck: ignore unused variable ruled_client
|
|
||||||
local ruled_client = slot {
|
|
||||||
id = "RULED_CLIENT",
|
|
||||||
connect = true,
|
|
||||||
target = ruled.client,
|
|
||||||
signal = "request::rules",
|
|
||||||
slot = slot.slots.ruled.append_client_rules,
|
|
||||||
slot_params = {
|
|
||||||
rules = configuration.rules.client,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
-- luacheck: ignore unused variable client_titlebar
|
|
||||||
local client_titlebar = slot {
|
|
||||||
id = "CLIENT_TITLEBAR",
|
|
||||||
connect = true,
|
|
||||||
target = capi.client,
|
|
||||||
signal = "request::titlebars",
|
|
||||||
slot = my_slots.build_client_titlebars,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- luacheck: ignore unused variable ruled_notification
|
|
||||||
local ruled_notification = slot {
|
|
||||||
id = "RULED_NOTIFICATION",
|
|
||||||
connect = true,
|
|
||||||
target = ruled.notification,
|
|
||||||
signal = "request::rules",
|
|
||||||
slot = slot.slots.ruled.append_notification_rules,
|
|
||||||
slot_params = {
|
|
||||||
rules = configuration.rules.notification,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
-- luacheck: ignore unused variable naughty_display
|
|
||||||
local naughty_display = slot {
|
|
||||||
id = "NAUGHTY_DISPLAY",
|
|
||||||
connect = true,
|
|
||||||
target = naughty,
|
|
||||||
signal = "request::display",
|
|
||||||
slot = my_slots.naughty_display,
|
|
||||||
}
|
|
||||||
|
|
||||||
naughty.notify {
|
|
||||||
title = "Aire-One dots",
|
|
||||||
message = "You successfully ran the Aire-One default rc!",
|
|
||||||
}
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
xephyr=/usr/bin/Xephyr
|
||||||
|
awesome=/usr/bin/awesome
|
||||||
|
|
||||||
|
# TODO: configurable
|
||||||
|
confdir=./src
|
||||||
|
rcfile=./config/awesome/rc.lua
|
||||||
|
screen=1600x900
|
||||||
|
|
||||||
|
display=:1.0
|
||||||
|
|
||||||
|
startXephyr() {
|
||||||
|
$xephyr $display -ac -br -noreset -screen $screen >/dev/null 2>&1 &
|
||||||
|
}
|
||||||
|
|
||||||
|
runAwesome() {
|
||||||
|
DISPLAY=$display $awesome \
|
||||||
|
--config $rcfile \
|
||||||
|
--search $confdir
|
||||||
|
}
|
||||||
|
|
||||||
|
case $1 in
|
||||||
|
start)
|
||||||
|
startXephyr
|
||||||
|
luamon .
|
||||||
|
pkill Xephyr
|
||||||
|
;;
|
||||||
|
runAwesome)
|
||||||
|
runAwesome
|
||||||
|
;;
|
||||||
|
debug)
|
||||||
|
startXephyr
|
||||||
|
sleep 1 # wait for Xephyr to be ready
|
||||||
|
runAwesome
|
||||||
|
;;
|
||||||
|
try-current)
|
||||||
|
startXephyr
|
||||||
|
sleep 1 # wait for Xephyr to be ready
|
||||||
|
DISPLAY=$display $awesome
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Need command"
|
||||||
|
;;
|
||||||
|
esac
|
123
slots/init.lua
|
@ -1,123 +0,0 @@
|
||||||
local abutton = require "awful.button"
|
|
||||||
local atitlebar = require "awful.titlebar"
|
|
||||||
local beautiful = require "beautiful"
|
|
||||||
local lalign = require "wibox.layout.align"
|
|
||||||
local lfixed = require "wibox.layout.fixed"
|
|
||||||
local lflex = require "wibox.layout.flex"
|
|
||||||
local naughty = require "naughty"
|
|
||||||
|
|
||||||
local slots = {}
|
|
||||||
|
|
||||||
function slots.wallpaper(screen)
|
|
||||||
local awallpaper = require "awful.wallpaper"
|
|
||||||
local beautiful = require "beautiful"
|
|
||||||
local gcolor = require "gears.color"
|
|
||||||
local gsurface = require "gears.surface"
|
|
||||||
local imagebox = require "wibox.widget.imagebox"
|
|
||||||
local cairo = require("lgi").cairo
|
|
||||||
|
|
||||||
local screen_geo = screen.geometry
|
|
||||||
local source = cairo.ImageSurface(
|
|
||||||
cairo.Format.RGB32,
|
|
||||||
screen_geo.width,
|
|
||||||
screen_geo.height
|
|
||||||
)
|
|
||||||
local cr = cairo.Context(source)
|
|
||||||
|
|
||||||
-- Load base image
|
|
||||||
local image_surface = gsurface.load_uncached(beautiful.wallpaper)
|
|
||||||
local w, h = gsurface.get_size(image_surface)
|
|
||||||
cr:scale(screen_geo.width / w, screen_geo.height / h)
|
|
||||||
cr:set_source_surface(image_surface, 0, 0)
|
|
||||||
cr:paint()
|
|
||||||
|
|
||||||
-- Add color layer
|
|
||||||
local color_pattern = gcolor.create_linear_pattern {
|
|
||||||
from = { 0, 0 },
|
|
||||||
to = { screen.width, screen.height },
|
|
||||||
stops = {
|
|
||||||
{ 0, "#26323840" },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
cr:set_source(color_pattern)
|
|
||||||
cr:paint()
|
|
||||||
|
|
||||||
awallpaper {
|
|
||||||
screen = screen,
|
|
||||||
widget = {
|
|
||||||
image = source,
|
|
||||||
widget = imagebox,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function slots.create_tags(screen)
|
|
||||||
local atag = require "awful.tag"
|
|
||||||
local gtimer = require "gears.timer"
|
|
||||||
local home_layout = require "MyTagLayout.home_layout"
|
|
||||||
|
|
||||||
local first_tag = atag.add("home", {
|
|
||||||
screen = screen,
|
|
||||||
icon = beautiful.icon_hometag,
|
|
||||||
layout = home_layout,
|
|
||||||
master_width_factor = beautiful.hometag_master_width_factor,
|
|
||||||
})
|
|
||||||
|
|
||||||
gtimer.delayed_call(function()
|
|
||||||
local spawn = require "awful.spawn"
|
|
||||||
local apps = require "configuration.applications"
|
|
||||||
|
|
||||||
first_tag:view_only()
|
|
||||||
spawn(apps.open_terminal(), { screen = screen, tag = first_tag })
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
function slots.build_desktop_decoration(screen)
|
|
||||||
local desktop_bar = require "rc.ui.desktop_decoration.bar"
|
|
||||||
|
|
||||||
desktop_bar(screen)
|
|
||||||
end
|
|
||||||
|
|
||||||
function slots.build_client_titlebars(client)
|
|
||||||
-- Mouse buttons bindings for the titlebar
|
|
||||||
local buttons = {
|
|
||||||
abutton({}, 1, function()
|
|
||||||
client:activate { context = "titlebar", action = "mouse_move" }
|
|
||||||
end),
|
|
||||||
abutton({}, 3, function()
|
|
||||||
client:activate { context = "titlebar", action = "mouse_resize" }
|
|
||||||
end),
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Titlebar UI
|
|
||||||
atitlebar(client).widget = {
|
|
||||||
{ -- Left
|
|
||||||
atitlebar.widget.iconwidget(client),
|
|
||||||
buttons = buttons,
|
|
||||||
layout = lfixed.horizontal,
|
|
||||||
},
|
|
||||||
{ -- Middle
|
|
||||||
{ -- Title
|
|
||||||
align = "center",
|
|
||||||
widget = atitlebar.widget.titlewidget(client),
|
|
||||||
},
|
|
||||||
buttons = buttons,
|
|
||||||
layout = lflex.horizontal,
|
|
||||||
},
|
|
||||||
{ -- Right
|
|
||||||
atitlebar.widget.floatingbutton(client),
|
|
||||||
atitlebar.widget.maximizedbutton(client),
|
|
||||||
atitlebar.widget.stickybutton(client),
|
|
||||||
atitlebar.widget.ontopbutton(client),
|
|
||||||
atitlebar.widget.closebutton(client),
|
|
||||||
layout = lfixed.horizontal(),
|
|
||||||
},
|
|
||||||
layout = lalign.horizontal,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function slots.naughty_display(notification)
|
|
||||||
naughty.layout.box { notification = notification }
|
|
||||||
end
|
|
||||||
|
|
||||||
return slots
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
describe("default", function()
|
||||||
|
it("should work", function()
|
||||||
|
assert.are.equal(1, 1)
|
||||||
|
end)
|
||||||
|
end)
|
|
@ -0,0 +1,59 @@
|
||||||
|
# My Tag List Widget
|
||||||
|
|
||||||
|
The standard Awesome wm API already contains a Tag List Widget implementation. However, this implementation doesn't match my needs, so here is my attempt to create my own Tag List Widget.
|
||||||
|
|
||||||
|
It is a personnal project.
|
||||||
|
|
||||||
|
# Mockup
|
||||||
|
|
||||||
|
Here are some references I'm writing to define what I think my widget should looks like. This section will introduice a mockup of the widget in a taskbar.
|
||||||
|
|
||||||
|
This mockup concept have its implementation example in the script `mockup.lua`.
|
||||||
|
|
||||||
|
## The taskbar
|
||||||
|
|
||||||
|
The widget is designed to be used in a taskbar. Here, I'll only briefly talk about the bar, keep in mind inspiration for this come from *literally **any*** desktop environment and OS you can try.
|
||||||
|
|
||||||
|
Basically, the bar will look like this:
|
||||||
|
|
||||||
|
```
|
||||||
|
+-----------------------------+
|
||||||
|
| X X X X |
|
||||||
|
+-----------------------------+
|
||||||
|
```
|
||||||
|
|
||||||
|
Every X symbols is an item of the Tag List Widget.
|
||||||
|
|
||||||
|
## Items
|
||||||
|
|
||||||
|
*(I call them "items" because I didn't find a better word :s)*
|
||||||
|
|
||||||
|
In a clasical tasklist, an item is an icon of a runing application on your desktop. Here, I want to use the *Tag* system to introduice a new way to think about it.
|
||||||
|
|
||||||
|
Every tag will be shown as a single icon. This icon should show to the user a numerous informations about the tag itself and its associated clients. In one look, the user should be able to identify tags, which are selected, how may extra-clients there is, if a client is flaged as `urgent`.
|
||||||
|
|
||||||
|
Here is a discomposition of an item:
|
||||||
|
|
||||||
|
```
|
||||||
|
+---------+ +---------+ +---------+ +---------+
|
||||||
|
| | | | | *| | |
|
||||||
|
| O | | O | | O | | O |
|
||||||
|
| | | ------- | | | | + + + |
|
||||||
|
+---------+ +---------+ +---------+ +---------+
|
||||||
|
Simple Selected Urgent Clients
|
||||||
|
```
|
||||||
|
|
||||||
|
*The frame is used to delimite the size of the item. It is not aimed to be drawned.*
|
||||||
|
|
||||||
|
Legend:
|
||||||
|
|
||||||
|
* `O` : the icon on the center of the item
|
||||||
|
* `-----` : the bottom line, shown when the tag is selected
|
||||||
|
* `*` : the notification dot drawn when the tag is marked "urgent"
|
||||||
|
* `+` : some dots to show how many additionals clients are on the tag
|
||||||
|
|
||||||
|
# References
|
||||||
|
|
||||||
|
Most of the code is based on the awful standard library and the module `awful.widget.taglist.lua`.
|
||||||
|
|
||||||
|
Special thanks to u/EmpressNoodle [for the inspiration](https://www.reddit.com/r/unixporn/comments/a900p7/awesome_mechanical_love/) and the good example of implementation on github (https://github.com/elenapan/dotfiles/blob/master/config/awesome/noodle/icon_taglist.lua).
|
|
@ -0,0 +1,139 @@
|
||||||
|
-----------------
|
||||||
|
-- MyTagListWidget - TagItem_widget
|
||||||
|
--
|
||||||
|
-- Definition of a TagItem_widget.
|
||||||
|
-- A TagItem_widget is the widget representing a tag in the TagList widget.
|
||||||
|
--
|
||||||
|
-- @author : Aire-One (Aire-One@github.com ; Aire-One@gitlab.com)
|
||||||
|
-- @copyright (C) 2019 Aire-One
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
local aplacement = require "awful.placement"
|
||||||
|
local beautiful = require "beautiful"
|
||||||
|
local empty_widget = require("wibox.widget.base").empty_widget
|
||||||
|
local gshape = require "gears.shape"
|
||||||
|
local wibox = require "wibox"
|
||||||
|
|
||||||
|
--- Set the widget's image.
|
||||||
|
-- @tparam TagItem_widget self The widget itself.
|
||||||
|
-- @tparam Image image The image to use.
|
||||||
|
local set_image = function(self, image)
|
||||||
|
self.internal_role.icon_role.image = image
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Toogle the widget's selected status.
|
||||||
|
-- Toogle the selected status will whether show the selected_line_role widget
|
||||||
|
-- or the additionals_clients_role widget.
|
||||||
|
-- @tparam TagItem_widget self The widget itself.
|
||||||
|
-- @tparam bool selected Is the widget selected?
|
||||||
|
local toogle_selected = function(self, selected)
|
||||||
|
self.internal_role.selected_line_role.visible = selected
|
||||||
|
self.internal_role.additionals_clients_role.visible = not selected
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Toogle the widget's notification dot.
|
||||||
|
-- @tparam TagItem_widget self The widget itself.
|
||||||
|
-- @tparam bool show Show the notification dot?
|
||||||
|
local toogle_notification_dot = function(self, show)
|
||||||
|
self.internal_role.notification_dot_role.visible = show
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the number of additionals clients shown in the widget.
|
||||||
|
-- @tparam TagItem_widget self The widget itself.
|
||||||
|
-- @tparam Number count The number of additionals clients.
|
||||||
|
-- (Should be >= 0 and not too high)
|
||||||
|
local set_additional_client_count = function(self, count)
|
||||||
|
count = count >= 0 and count or 0
|
||||||
|
|
||||||
|
while #self.internal_role.additionals_clients_role.children < count do
|
||||||
|
self.internal_role.additionals_clients_role:add(wibox.widget {
|
||||||
|
layout = wibox.container.background,
|
||||||
|
wibox.widget.base.empty_widget(),
|
||||||
|
bg = "#ECEFF1",
|
||||||
|
shape = gshape.circle,
|
||||||
|
forced_height = 3,
|
||||||
|
forced_width = 3,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
while #self.internal_role.additionals_clients_role.children > count do
|
||||||
|
self.internal_role.additionals_clients_role:remove(1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local tagItem_widget = {}
|
||||||
|
|
||||||
|
--- Create a new tag item widget instance.
|
||||||
|
-- @tparam Tag tag The associated tag.
|
||||||
|
-- @treturn TagItem_widget The created widget.
|
||||||
|
tagItem_widget.new = function(tag)
|
||||||
|
-- TODO: remove all constants - prefere use a `params` table to initialize them.
|
||||||
|
local w = wibox.widget {
|
||||||
|
id = "container_role",
|
||||||
|
layout = wibox.container.margin,
|
||||||
|
{
|
||||||
|
id = "internal_role",
|
||||||
|
layout = wibox.layout.manual,
|
||||||
|
{
|
||||||
|
id = "selected_line_role",
|
||||||
|
layout = wibox.container.margin,
|
||||||
|
forced_height = 2,
|
||||||
|
point = aplacement.maximize_horizontally + aplacement.bottom,
|
||||||
|
right = 2,
|
||||||
|
left = 2,
|
||||||
|
{
|
||||||
|
layout = wibox.container.background,
|
||||||
|
empty_widget(),
|
||||||
|
bg = "#ECEFF1",
|
||||||
|
shape = gshape.rounded_bar,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id = "icon_role",
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
resize = true,
|
||||||
|
image = tag.icon or beautiful.awesome_icon,
|
||||||
|
forced_height = 16,
|
||||||
|
forced_width = 16,
|
||||||
|
point = aplacement.centered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id = "notification_dot_role",
|
||||||
|
layout = wibox.container.background,
|
||||||
|
visible = false,
|
||||||
|
wibox.widget.base.empty_widget(),
|
||||||
|
bg = "#F44336",
|
||||||
|
-- shape_border_width = 1,
|
||||||
|
-- shape_border_color = '#B71C1C',
|
||||||
|
shape = gshape.circle,
|
||||||
|
forced_height = 6,
|
||||||
|
forced_width = 6,
|
||||||
|
point = aplacement.top_right,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id = "additionals_clients_role",
|
||||||
|
layout = wibox.layout.flex.horizontal,
|
||||||
|
visible = false,
|
||||||
|
forced_height = 3,
|
||||||
|
spacing = 2,
|
||||||
|
point = aplacement.bottom,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- it seems that setting the margins in the hierarchy doesn't work 🤷♂️
|
||||||
|
-- w:set_margins(0)
|
||||||
|
w.margins = 0
|
||||||
|
|
||||||
|
-- Save the tag as an internal property
|
||||||
|
w.tag = tag
|
||||||
|
|
||||||
|
w.set_image = set_image
|
||||||
|
w.toogle_selected = toogle_selected
|
||||||
|
w.toogle_notification_dot = toogle_notification_dot
|
||||||
|
w.set_additional_client_count = set_additional_client_count
|
||||||
|
|
||||||
|
return w
|
||||||
|
end
|
||||||
|
|
||||||
|
return tagItem_widget
|
|
@ -0,0 +1,209 @@
|
||||||
|
-----------------
|
||||||
|
-- MyTagListWidget
|
||||||
|
--
|
||||||
|
-- My implementationof the tag list widget for the Awesome WM.
|
||||||
|
--
|
||||||
|
-- @author : Aire-One (Aire-One@github.com ; Aire-One@gitlab.com)
|
||||||
|
-- @copyright (C) 2019 Aire-One
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
local awful = require "awful"
|
||||||
|
local beautiful = require "beautiful"
|
||||||
|
local client = client -- luacheck: ignore client
|
||||||
|
local gsurface = require "gears.surface"
|
||||||
|
local gtable = require "gears.table"
|
||||||
|
local wibox = require "wibox"
|
||||||
|
|
||||||
|
local TagItem_widget = require "MyTagListWidget.TagItem_widget"
|
||||||
|
|
||||||
|
--- Get the tag widget associated with a specific tag.
|
||||||
|
-- @tparam MyTagListWidget taglist The tag list widget to look up.
|
||||||
|
-- @tparam Tag tag The tag to look for.
|
||||||
|
-- @treturn[1] widget The tag widget (nil if none).
|
||||||
|
-- @treturn[1] number The position of the widget in the list.
|
||||||
|
-- @treturn[2] nil If the tag does not have its widget.
|
||||||
|
local get_tagwidget = function(taglist, tag)
|
||||||
|
for i, child in ipairs(taglist.children) do
|
||||||
|
if gtable.hasitem(child, tag) then
|
||||||
|
return child, i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a new tag icon widget.
|
||||||
|
-- @tparam Tag tag The targeted tag.
|
||||||
|
-- @treturn widget The created widget.
|
||||||
|
local create_tagwidget = function(tag)
|
||||||
|
local w = TagItem_widget.new(tag)
|
||||||
|
|
||||||
|
w:buttons(gtable.join(
|
||||||
|
-- Left click - Focus Tag
|
||||||
|
awful.button({}, 1, function()
|
||||||
|
tag:view_only()
|
||||||
|
end),
|
||||||
|
-- Right click - Show options
|
||||||
|
awful.button({}, 3, function()
|
||||||
|
-- TODO : design a menu
|
||||||
|
print("OPTION FOR " .. tag.name)
|
||||||
|
end)
|
||||||
|
))
|
||||||
|
|
||||||
|
return w
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Manage a client update.
|
||||||
|
-- Do everything the widget should check when client is updated.
|
||||||
|
-- @tparam MyTagListWidget self The MyTagListWidget instance to update.
|
||||||
|
-- @tparam client client The client which trigger the update.
|
||||||
|
local client_update = function(self, client) end -- luacheck: ignore
|
||||||
|
|
||||||
|
--- Manage an icon update.
|
||||||
|
-- @tparam MyTagListWidget self The MyTagListWidget instance to update.
|
||||||
|
-- @tparam Tag tag The targeted tag.
|
||||||
|
local update_icon = function(self, tag)
|
||||||
|
-- TODO : this function shouldn't retrive the widget
|
||||||
|
local w = get_tagwidget(self, tag)
|
||||||
|
if not w then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- by default, we should use the predefined tag icon
|
||||||
|
-- then master client icon
|
||||||
|
-- then default to awesome_icon
|
||||||
|
if tag.icon then
|
||||||
|
w:set_image(tag.icon)
|
||||||
|
elseif #tag:clients() > 0 then
|
||||||
|
local attach_icon = function()
|
||||||
|
w:set_image(gsurface(tag:clients()[1].icon))
|
||||||
|
end
|
||||||
|
-- first client should be masters
|
||||||
|
-- so usually, we should prioritize firsts clients
|
||||||
|
tag:clients()[1]:connect_signal("property::icon", attach_icon)
|
||||||
|
for i = 2, #tag:clients() do
|
||||||
|
tag:clients()[i]:disconnect_signal("property::icon", attach_icon)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
w:set_image(beautiful.awesome_icon)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Manage the additionals clients count on a tagItem_widget.
|
||||||
|
-- @tparam MyTagListWidget self The MyTagListWidget instance to update.
|
||||||
|
-- @tparam Tag tag The targeted tag.
|
||||||
|
local update_additionalsclient = function(self, tag)
|
||||||
|
-- TODO : this function shouldn't retrive the widget
|
||||||
|
local w = get_tagwidget(self, tag)
|
||||||
|
if not w then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO : better additionals clients count computation
|
||||||
|
-- (detect important clients and not count them)
|
||||||
|
w:set_additional_client_count(#tag:clients() - tag.master_count)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Update the widget.
|
||||||
|
-- @tparam MyTagListWidget self The MyTagListWidget instance to update.
|
||||||
|
local update_widget = function(self)
|
||||||
|
for i, tag in ipairs(self.screen.tags) do
|
||||||
|
-- w is the TagItem_widget associated with the tag.
|
||||||
|
local w = get_tagwidget(self, tag)
|
||||||
|
|
||||||
|
-- If none exists, create it.
|
||||||
|
if not w then
|
||||||
|
w = create_tagwidget(tag)
|
||||||
|
self:insert(i, w) -- add the widget at its position in the layout
|
||||||
|
end
|
||||||
|
|
||||||
|
w:toogle_selected(tag.selected)
|
||||||
|
w:toogle_notification_dot(awful.tag.getproperty(tag, "urgent"))
|
||||||
|
update_icon(self, tag)
|
||||||
|
if not tag.selected then
|
||||||
|
update_additionalsclient(self, tag)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove deleted tags:
|
||||||
|
for i, wtag in ipairs(self.children) do
|
||||||
|
if wtag.tag.screen ~= self.screen then
|
||||||
|
self:remove(i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local my_taglist_widget = {}
|
||||||
|
|
||||||
|
--- MyTagListWidget Constructor.
|
||||||
|
-- Build a new instance of MyTagListWidget.
|
||||||
|
-- @tparam table params Parameters to build the Widget.
|
||||||
|
-- @tparam screen params.screen Screen where the widget will be.
|
||||||
|
-- @treturn MyTagListWidget The new widget instance.
|
||||||
|
my_taglist_widget.new = function(params)
|
||||||
|
-- TODO : use more beautiful theming properties with params
|
||||||
|
|
||||||
|
local self = wibox.widget {
|
||||||
|
layout = wibox.layout.flex.horizontal,
|
||||||
|
screen = params.screen,
|
||||||
|
spacing = 2,
|
||||||
|
max_widget_size = 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Add publics methods
|
||||||
|
self.force_update_widget = update_widget
|
||||||
|
|
||||||
|
-- Add buttons events
|
||||||
|
self:buttons(gtable.join(
|
||||||
|
-- Scroll - Cycle through tags
|
||||||
|
awful.button({}, 4, function()
|
||||||
|
awful.tag.viewprev()
|
||||||
|
end),
|
||||||
|
awful.button({}, 5, function()
|
||||||
|
awful.tag.viewnext()
|
||||||
|
end)
|
||||||
|
))
|
||||||
|
|
||||||
|
-- Attach signals to update the widget
|
||||||
|
-- TODO : specialize signal events (ie not always call UPDATE_EVERYTHING when a shorter function can do the job)
|
||||||
|
client.connect_signal("manage", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
client.connect_signal("unmanage", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
client.connect_signal("tagged", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
client.connect_signal("untagged", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
client.connect_signal("screen", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
awful.tag.attached_connect_signal(self.screen, "property::selected", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
awful.tag.attached_connect_signal(self.screen, "property::hide", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
awful.tag.attached_connect_signal(self.screen, "property::activated", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
awful.tag.attached_connect_signal(self.screen, "property::screen", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
awful.tag.attached_connect_signal(self.screen, "property::index", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
awful.tag.attached_connect_signal(self.screen, "property::urgent", function()
|
||||||
|
self:force_update_widget()
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Build the widget with an update
|
||||||
|
update_widget(self)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
return my_taglist_widget
|
|
@ -0,0 +1,281 @@
|
||||||
|
-----------------
|
||||||
|
-- MyTagListWidget mockup
|
||||||
|
--
|
||||||
|
-- This file define a mockup of the tag list widget in a taskbar
|
||||||
|
-- as I wish to create my own.
|
||||||
|
--
|
||||||
|
-- This mockup will create a fake taskbar with a fake Tag List Widget to help
|
||||||
|
-- me for the conceptualisation of the design for my Tag List Widget.
|
||||||
|
--
|
||||||
|
-- <h1>The taskbar</h1>
|
||||||
|
-- Basically, the bar will look like this:
|
||||||
|
--
|
||||||
|
-- +---------------------+
|
||||||
|
-- | X X X X |
|
||||||
|
-- +---------------------+
|
||||||
|
--
|
||||||
|
-- Every X symbols is an item of the Tag List Widget.
|
||||||
|
--
|
||||||
|
-- <h1>Items</h1>
|
||||||
|
-- An item represente a Tag and is discomposable like this:
|
||||||
|
--
|
||||||
|
-- +---------+ +---------+ +---------+ +---------+
|
||||||
|
-- | | | | | *| | |
|
||||||
|
-- | O | | O | | O | | O |
|
||||||
|
-- | | | ------- | | | | + + + |
|
||||||
|
-- +---------+ +---------+ +---------+ +---------+
|
||||||
|
-- Simple Selected Urgent Clients
|
||||||
|
--
|
||||||
|
-- The frame is used to delimite the size of the item.
|
||||||
|
-- It is not aimed to be drawned.
|
||||||
|
--
|
||||||
|
-- * O : the icon on the center of the item
|
||||||
|
-- * ----- : the bottom line, shown when the tag is selected
|
||||||
|
-- * \* : a notification dot drawn when the tag is marked "urgent"
|
||||||
|
-- * \+ : some dots to show how many additionals clients are on the tag
|
||||||
|
--
|
||||||
|
-- @author : Aire-One (Aire-One@github.com ; Aire-One@gitlab.com)
|
||||||
|
-- @copyright (C) 2019 Aire-One
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
-- require user rc.lua as a base config
|
||||||
|
-- user rc.lua file should be on a place loaded by awesomewm
|
||||||
|
require "rc"
|
||||||
|
|
||||||
|
local awful = require "awful"
|
||||||
|
local gears = require "gears"
|
||||||
|
local wibox = require "wibox"
|
||||||
|
|
||||||
|
-- Configs
|
||||||
|
local bar_height = 20 -- used by the wibox embedding the widget
|
||||||
|
local bar_padding = 0 -- used by the wibox embedding the widget
|
||||||
|
local item_size = 20 -- size of a tag icon placeholder
|
||||||
|
local icon_size = 16 -- size of the icon itself
|
||||||
|
local selected_line_height = 3 -- size of the bar below the icon
|
||||||
|
local notification_dot_size = 6 -- size of the notification dot (request::urgent)
|
||||||
|
|
||||||
|
local screen = awful.screen.focused()
|
||||||
|
|
||||||
|
-- the taskbar is symbolized by this wibox
|
||||||
|
screen.bar = wibox {
|
||||||
|
type = "dock",
|
||||||
|
ontop = true,
|
||||||
|
visible = true,
|
||||||
|
x = 50,
|
||||||
|
y = 200,
|
||||||
|
width = 400,
|
||||||
|
height = bar_height,
|
||||||
|
}
|
||||||
|
|
||||||
|
screen.bar:setup {
|
||||||
|
-- The bar is a container.margin
|
||||||
|
layout = wibox.container.margin,
|
||||||
|
top = bar_padding / 2,
|
||||||
|
bottom = bar_padding / 2,
|
||||||
|
right = bar_padding,
|
||||||
|
left = bar_padding,
|
||||||
|
{
|
||||||
|
-- The Tag List widget
|
||||||
|
layout = wibox.layout.flex.horizontal,
|
||||||
|
spacing = 2,
|
||||||
|
max_widget_size = item_size, -- each widget will be a rectangular box
|
||||||
|
-- Every Tag is represented by this widget
|
||||||
|
{
|
||||||
|
-- first a container.margin
|
||||||
|
layout = wibox.container.margin,
|
||||||
|
top = 0,
|
||||||
|
bottom = 0,
|
||||||
|
right = 0,
|
||||||
|
left = 0,
|
||||||
|
{
|
||||||
|
-- The internal widget design
|
||||||
|
layout = wibox.layout.manual,
|
||||||
|
{
|
||||||
|
-- simple icon
|
||||||
|
-- use a predefined icon depending on the tag name
|
||||||
|
-- use a client (master client?) icon
|
||||||
|
-- use the tag name as a string (widget.textbox) ???
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
resize = true,
|
||||||
|
image = "/usr/share/icons/Adwaita/16x16/places/user-home-symbolic.symbolic.png",
|
||||||
|
forced_height = icon_size,
|
||||||
|
forced_width = icon_size,
|
||||||
|
point = awful.placement.centered,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-- first a container.margin
|
||||||
|
layout = wibox.container.margin,
|
||||||
|
top = 0,
|
||||||
|
bottom = 0,
|
||||||
|
right = 0,
|
||||||
|
left = 0,
|
||||||
|
{
|
||||||
|
-- The internal widget design
|
||||||
|
layout = wibox.layout.manual,
|
||||||
|
{
|
||||||
|
-- underline (request::selected)
|
||||||
|
-- should be placed below the tag icon
|
||||||
|
layout = wibox.container.background,
|
||||||
|
wibox.widget.base.empty_widget(),
|
||||||
|
bg = "#eeeeee",
|
||||||
|
shape = gears.shape.rounded_bar,
|
||||||
|
forced_height = selected_line_height,
|
||||||
|
point = awful.placement.maximize_horizontally + awful.placement.bottom,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
resize = true,
|
||||||
|
image = "/usr/share/icons/hicolor/16x16/apps/atom.png",
|
||||||
|
forced_height = icon_size,
|
||||||
|
forced_width = icon_size,
|
||||||
|
point = awful.placement.centered,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-- first a container.margin
|
||||||
|
layout = wibox.container.margin,
|
||||||
|
top = 0,
|
||||||
|
bottom = 0,
|
||||||
|
right = 0,
|
||||||
|
left = 0,
|
||||||
|
{
|
||||||
|
-- The internal widget design
|
||||||
|
layout = wibox.layout.manual,
|
||||||
|
{
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
resize = true,
|
||||||
|
image = "/usr/share/icons/hicolor/16x16/apps/thunderbird.png",
|
||||||
|
forced_height = icon_size,
|
||||||
|
forced_width = icon_size,
|
||||||
|
point = awful.placement.centered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-- Notification dot (request::urgent)
|
||||||
|
-- should be placed on the top of the icon
|
||||||
|
layout = wibox.container.background,
|
||||||
|
wibox.widget.base.empty_widget(),
|
||||||
|
bg = "#ff0000",
|
||||||
|
shape_border_width = 2,
|
||||||
|
shape_border_color = "#8b0000",
|
||||||
|
shape = gears.shape.circle,
|
||||||
|
forced_height = notification_dot_size,
|
||||||
|
forced_width = notification_dot_size,
|
||||||
|
point = awful.placement.top_right,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-- first a container.margin
|
||||||
|
layout = wibox.container.margin,
|
||||||
|
top = 0,
|
||||||
|
bottom = 0,
|
||||||
|
right = 0,
|
||||||
|
left = 0,
|
||||||
|
{
|
||||||
|
-- The internal widget design
|
||||||
|
layout = wibox.layout.manual,
|
||||||
|
{
|
||||||
|
-- simple icon
|
||||||
|
-- use a predefined icon depending on the tag name
|
||||||
|
-- use a client (master client?) icon
|
||||||
|
-- use the tag name as a string (widget.textbox) ???
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
resize = true,
|
||||||
|
image = "/usr/share/icons/Adwaita/16x16/apps/utilities-terminal-symbolic.symbolic.png",
|
||||||
|
forced_height = icon_size,
|
||||||
|
forced_width = icon_size,
|
||||||
|
point = awful.placement.centered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-- number of clients on the tag
|
||||||
|
layout = wibox.layout.flex.horizontal,
|
||||||
|
{
|
||||||
|
layout = wibox.container.background,
|
||||||
|
wibox.widget.base.empty_widget(),
|
||||||
|
bg = "#eeeeee",
|
||||||
|
shape = gears.shape.circle,
|
||||||
|
forced_height = 3,
|
||||||
|
forced_width = 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
layout = wibox.container.background,
|
||||||
|
wibox.widget.base.empty_widget(),
|
||||||
|
bg = "#eeeeee",
|
||||||
|
shape = gears.shape.circle,
|
||||||
|
forced_height = 3,
|
||||||
|
forced_width = 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
layout = wibox.container.background,
|
||||||
|
wibox.widget.base.empty_widget(),
|
||||||
|
bg = "#eeeeee",
|
||||||
|
shape = gears.shape.circle,
|
||||||
|
forced_height = 3,
|
||||||
|
forced_width = 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
layout = wibox.container.background,
|
||||||
|
wibox.widget.base.empty_widget(),
|
||||||
|
bg = "#eeeeee",
|
||||||
|
shape = gears.shape.circle,
|
||||||
|
forced_height = 3,
|
||||||
|
forced_width = 3,
|
||||||
|
},
|
||||||
|
forced_height = selected_line_height,
|
||||||
|
spacing = 2,
|
||||||
|
point = awful.placement.bottom,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-- first a container.margin
|
||||||
|
layout = wibox.container.margin,
|
||||||
|
top = 0,
|
||||||
|
bottom = 0,
|
||||||
|
right = 0,
|
||||||
|
left = 0,
|
||||||
|
{
|
||||||
|
-- The internal widget design
|
||||||
|
layout = wibox.layout.manual,
|
||||||
|
{
|
||||||
|
-- simple icon
|
||||||
|
-- use a predefined icon depending on the tag name
|
||||||
|
-- use a client (master client?) icon
|
||||||
|
-- use the tag name as a string (widget.textbox) ???
|
||||||
|
widget = wibox.widget.imagebox,
|
||||||
|
resize = true,
|
||||||
|
image = "/usr/share/icons/Adwaita/16x16/apps/utilities-terminal-symbolic.symbolic.png",
|
||||||
|
forced_height = icon_size,
|
||||||
|
forced_width = icon_size,
|
||||||
|
point = awful.placement.centered,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-- number of clients on the tag
|
||||||
|
layout = wibox.layout.flex.horizontal,
|
||||||
|
{
|
||||||
|
layout = wibox.container.background,
|
||||||
|
wibox.widget.base.empty_widget(),
|
||||||
|
bg = "#eeeeee",
|
||||||
|
shape = gears.shape.circle,
|
||||||
|
forced_height = 3,
|
||||||
|
forced_width = 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
layout = wibox.container.background,
|
||||||
|
wibox.widget.base.empty_widget(),
|
||||||
|
bg = "#eeeeee",
|
||||||
|
shape = gears.shape.circle,
|
||||||
|
forced_height = 3,
|
||||||
|
forced_width = 3,
|
||||||
|
},
|
||||||
|
forced_height = selected_line_height,
|
||||||
|
spacing = 2,
|
||||||
|
point = awful.placement.bottom,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
-----------------
|
||||||
|
-- tests/widget-testrc.lua
|
||||||
|
--
|
||||||
|
-- Author : Aire-One (Aire-One@github.com ; Aire-One@gitlab.com)
|
||||||
|
-- Copyright (C) 2018 Aire-One
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
-- require user rc.lua as a base config
|
||||||
|
-- user rc.lua file should be on a place loaded by awesomewm
|
||||||
|
require "rc"
|
||||||
|
|
||||||
|
-- Code to test the widget
|
||||||
|
|
||||||
|
local awful = require "awful"
|
||||||
|
local wibox = require "wibox"
|
||||||
|
|
||||||
|
local MyTagListWidget = require "MyTagListWidget"
|
||||||
|
|
||||||
|
-- build the widget on the current screen
|
||||||
|
local widget = MyTagListWidget.new { screen = awful.screen.focused() }
|
||||||
|
|
||||||
|
-- wibox to host the MyTagListWidget instance
|
||||||
|
awful.screen.w = wibox {
|
||||||
|
type = "dock",
|
||||||
|
ontop = true,
|
||||||
|
visible = true,
|
||||||
|
opacity = 1,
|
||||||
|
width = 200,
|
||||||
|
height = 30,
|
||||||
|
}
|
||||||
|
awful.screen.w:setup {
|
||||||
|
layout = wibox.container.background,
|
||||||
|
widget,
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
-----
|
||||||
|
-- autofocus module
|
||||||
|
--
|
||||||
|
-- TODO: remove this module as it's now deprecated.
|
||||||
|
-----
|
||||||
|
|
||||||
|
return require "awful.autofocus"
|
|
@ -0,0 +1,66 @@
|
||||||
|
-----
|
||||||
|
-- legacy module
|
||||||
|
--
|
||||||
|
-- This modules aims to hold all the legacy features from rc.lua
|
||||||
|
-----
|
||||||
|
|
||||||
|
local awesome_legacy = {}
|
||||||
|
|
||||||
|
function awesome_legacy.autofocus()
|
||||||
|
return require "awesome-legacy.autofocus"
|
||||||
|
end
|
||||||
|
|
||||||
|
function awesome_legacy.manage_error()
|
||||||
|
return require "awesome-legacy.manage_error"
|
||||||
|
end
|
||||||
|
|
||||||
|
function awesome_legacy.sloppy_focus()
|
||||||
|
return require "awesome-legacy.sloppy_focus"
|
||||||
|
end
|
||||||
|
|
||||||
|
function awesome_legacy.global_mouse_bindings(mousebindings)
|
||||||
|
local amouse = require "awful.mouse"
|
||||||
|
|
||||||
|
amouse.append_global_mousebindings(mousebindings)
|
||||||
|
end
|
||||||
|
|
||||||
|
function awesome_legacy.global_keybindings(keybindings)
|
||||||
|
local akeyboard = require "awful.keyboard"
|
||||||
|
|
||||||
|
akeyboard.append_global_keybindings(keybindings)
|
||||||
|
end
|
||||||
|
|
||||||
|
function awesome_legacy.beautiful(args)
|
||||||
|
local os = os
|
||||||
|
local dofile = dofile
|
||||||
|
|
||||||
|
local beautiful = require "beautiful"
|
||||||
|
local gfs = require "gears.filesystem"
|
||||||
|
local gstring = require "gears.string"
|
||||||
|
local gtable = require "gears.table"
|
||||||
|
local protected_call = require "gears.protected_call"
|
||||||
|
|
||||||
|
local default_theme = {}
|
||||||
|
|
||||||
|
if args.base then
|
||||||
|
if type(args.base) == "string" then
|
||||||
|
-- Replace the '~' by the fullpath to the home directory.
|
||||||
|
local theme_path = args.base:gsub("^~/", os.getenv "HOME" .. "/")
|
||||||
|
|
||||||
|
-- Complete the path for standard themes
|
||||||
|
if not gstring.startswith(theme_path, "/") then
|
||||||
|
theme_path = gfs.get_themes_dir() .. args.base .. "/theme.lua"
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Execute the file to get the theme table
|
||||||
|
default_theme = protected_call(dofile, theme_path)
|
||||||
|
elseif type(args.base) == "table" then
|
||||||
|
default_theme = args.base
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local theme = gtable.crush(default_theme, args.theme)
|
||||||
|
beautiful.init(theme)
|
||||||
|
end
|
||||||
|
|
||||||
|
return awesome_legacy
|
|
@ -0,0 +1,15 @@
|
||||||
|
-----
|
||||||
|
-- Error module
|
||||||
|
-----
|
||||||
|
|
||||||
|
local naughty = require "naughty"
|
||||||
|
|
||||||
|
-- Check if awesome encountered an error during startup and fell back to
|
||||||
|
-- another config (This code will only ever execute for the fallback config)
|
||||||
|
naughty.connect_signal("request::display_error", function(message, startup)
|
||||||
|
naughty.notification {
|
||||||
|
urgency = "critical",
|
||||||
|
title = "Oops, an error happened" .. (startup and " during startup!" or "!"),
|
||||||
|
message = message,
|
||||||
|
}
|
||||||
|
end)
|
|
@ -0,0 +1,15 @@
|
||||||
|
-----
|
||||||
|
-- Sloppy focus module
|
||||||
|
-----
|
||||||
|
|
||||||
|
local capi = {
|
||||||
|
client = _G.client,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Enable sloppy focus, so that focus follows mouse.
|
||||||
|
capi.client.connect_signal("mouse::enter", function(client)
|
||||||
|
client:activate {
|
||||||
|
context = "mouse_enter",
|
||||||
|
raise = false,
|
||||||
|
}
|
||||||
|
end)
|
|
@ -0,0 +1,12 @@
|
||||||
|
# EditorConfig is awesome: https://EditorConfig.org
|
||||||
|
|
||||||
|
# top-most EditorConfig file
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
insert_final_newline = true
|
|
@ -0,0 +1 @@
|
||||||
|
color_rules
|
|
@ -0,0 +1,33 @@
|
||||||
|
-- Only allow symbols available in all Lua versions
|
||||||
|
std = "min"
|
||||||
|
|
||||||
|
-- Get rid of "unused argument self"-warnings
|
||||||
|
self = false
|
||||||
|
|
||||||
|
-- Global objects defined by the C code
|
||||||
|
read_globals = {
|
||||||
|
"awesome",
|
||||||
|
"button",
|
||||||
|
"dbus",
|
||||||
|
"drawable",
|
||||||
|
"drawin",
|
||||||
|
"key",
|
||||||
|
"keygrabber",
|
||||||
|
"mousegrabber",
|
||||||
|
"selection",
|
||||||
|
"tag",
|
||||||
|
"window",
|
||||||
|
"table.unpack",
|
||||||
|
"math.atan2",
|
||||||
|
}
|
||||||
|
|
||||||
|
-- screen may not be read-only, because newer luacheck versions complain about
|
||||||
|
-- screen[1].tags[1].selected = true.
|
||||||
|
-- The same happens with the following code:
|
||||||
|
-- local tags = mouse.screen.tags
|
||||||
|
-- tags[7].index = 4
|
||||||
|
-- client may not be read-only due to client.focus.
|
||||||
|
globals = { "screen", "mouse", "root", "client" }
|
||||||
|
|
||||||
|
-- Enable cache (uses .luacheckcache relative to this rc file).
|
||||||
|
cache = true
|
|
@ -0,0 +1,22 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 mut-ex
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
|
@ -0,0 +1,257 @@
|
||||||
|
# :thumbsup:nice
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
If you would like to show your appreciation for this project,<br>please consider a donation :)<br><br>
|
||||||
|
<a href="https://www.paypal.com/donate/?business=Y4Y75KP2JBNJW¤cy_code=USD">
|
||||||
|
<img src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif" alt="PayPal donation link"/></a>
|
||||||
|
<p>
|
||||||
|
|
||||||
|
**N.B. This branch is for Awesome v4.3 git. [You can find the branch for Awesome v4.3 stable here](https://github.com/mut-ex/awesome-wm-nice/tree/awesome-4v3-stable)**
|
||||||
|
|
||||||
|
nice is an easy to use, highly configurable extension for **[Awesome WM](https://awesomewm.org/)** that adds beautiful window decorations (and extra functionality!) to clients. It...
|
||||||
|
|
||||||
|
* ...adds a **subtle 3D look**, and soft, **rounded anti-aliased, corners** to windows
|
||||||
|
* ...picks the window **decoration color based on the client content for a seamless look** , and adjusts the window title text color accordingly
|
||||||
|
* ...**auto-generates titlebar buttons** (and their states) for you based on the colors your pick *or* you can let it pick the colors for you!
|
||||||
|
* ...allows you to customize which titlebar buttons to include, their order, and their layout
|
||||||
|
* ...adds the **ability to maximize/unmaximize** floating windows by **double clicking the titlebar**, and of course, **moving them by clicking and holding**
|
||||||
|
* ...adds the ability to **"roll up"** and **"roll down"** the client window like a **window shade**! Scroll up over the titlebar to **instantly hide the window contents but keep the title bar** right where it is. And then either scroll down or click the titlebar to make the window contents visible again!
|
||||||
|
|
||||||
|
![Preview](https://raw.githubusercontent.com/mut-ex/awesome-wm-nice/master/preview.png)
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
* You need **[Awesome WM](https://awesomewm.org/)** with a working basic configuration. **This branch is for Awesome v4.3 git. [You can find the branch for Awesome v4.3 stable here](https://github.com/mut-ex/awesome-wm-nice/tree/awesome-4v3-stable)**
|
||||||
|
|
||||||
|
* You also need **[picom](https://github.com/yshui/picom)**. Make sure you have `shadow-ignore-shaped = false` in your configuration otherwise picom will not draw shadows. My recommended shadow settings are given below:
|
||||||
|
|
||||||
|
```
|
||||||
|
shadow = true;
|
||||||
|
shadow-radius = 40;
|
||||||
|
shadow-opacity = .55;
|
||||||
|
shadow-offset-x = -40;
|
||||||
|
shadow-offset-y = -20;
|
||||||
|
shadow-exclude = [
|
||||||
|
"_NET_WM_WINDOW_TYPE:a = '_NET_WM_WINDOW_TYPE_NOTIFICATION'",
|
||||||
|
"_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'",
|
||||||
|
"_GTK_FRAME_EXTENTS@:c"
|
||||||
|
];
|
||||||
|
shadow-ignore-shaped = false
|
||||||
|
```
|
||||||
|
|
||||||
|
* For **GTK** applications add the following line to **~/.config/gtk-3.0/settings.ini** under the **[Settings]** section to hide client-side window control buttons:
|
||||||
|
|
||||||
|
```
|
||||||
|
gtk-decoration-layout=menu:
|
||||||
|
```
|
||||||
|
|
||||||
|
* Within you Awesome configuration, make sure that you do not already have code in place that request default titlebars for clients. Something like this:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
client.connect_signal("request::titlebars", function(c) ... end) -- Remove this
|
||||||
|
```
|
||||||
|
|
||||||
|
* Additionally, nice only adds window decorations to clients that have the `titlebars_enabled` property set to true. So configure your client rules accordingly.
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
The easiest and quickest way to get started is by cloning this repository to your awesome configuration directory
|
||||||
|
|
||||||
|
```shell
|
||||||
|
$ cd ~/.config/awesome
|
||||||
|
$ git clone https://github.com/mut-ex/awesome-wm-nice.git nice
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
To use nice, you first need to load the module. To do that, put the following line right after `beautiful.init(...)`
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local nice = require("nice")
|
||||||
|
nice()
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are fine using the default configuration, you are all done!
|
||||||
|
|
||||||
|
nice will automatically detect and change the window decoration color to match the client. However...
|
||||||
|
|
||||||
|
* To pick the window decoration color yourself, right-click the titlebar and select **'Manually Pick Color'**
|
||||||
|
* To update the window decoration colors, right-click on the titlebar and select **'Redo Window Decorations'**
|
||||||
|
* Scroll-up with your mouse over the titlebar to "roll up" the window shade. Scroll-down over the titlebar, or left-click to "roll down" the window shade
|
||||||
|
* nice saves its color rules in the **color_rules** file within the module directory. If you wish you can manually edit it, or delete the file if you want to start again.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
You can override the defaults by passing your own configuration. For example
|
||||||
|
|
||||||
|
```lua
|
||||||
|
local nice = require("nice")
|
||||||
|
nice {
|
||||||
|
titlebar_color = "#00ff00",
|
||||||
|
|
||||||
|
-- You only need to pass the parameter you are changing
|
||||||
|
context_menu_theme = {
|
||||||
|
width = 300,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Swap the designated buttons for resizing, and opening the context menu
|
||||||
|
mb_resize = nice.MB_MIDDLE,
|
||||||
|
mb_contextmenu = nice.MB_RIGHT,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Below you will find further details explaining the configuration parameters for nice.
|
||||||
|
|
||||||
|
| Parameter | Type | Description | Default |
|
||||||
|
| --------------------- | :--: | ----------- | ------------------- |
|
||||||
|
| `titlebar_height` | integer | The height of the titlebar | `38` |
|
||||||
|
| `titlebar_radius` | integer | The radius of the top left and top right corners of the titlebar. Should be `>= 3` and `<= titlebar_height` | `9` |
|
||||||
|
| `titlebar_color` | string | The default color of the titlebar and window decorations. Should be a hex color string | `"#1e1e24"` |
|
||||||
|
| `titlebar_padding_left` | integer | The padding on the left side of the titlebar | `0` |
|
||||||
|
| `titlebar_padding_right` | integer | The padding on the right side of the titlebar | `0` |
|
||||||
|
| `titlebar_font` | string | The font and font size for text within the titlebar. See the default value for an example of the format | `"Sans 11"` |
|
||||||
|
| `win_shade_enabled` | boolean | Whether the window shade feature should be enabled | `true` |
|
||||||
|
| `no_titlebar_maximized` | boolean | Whether the titlebar should be hidden for maximized windows | `false` |
|
||||||
|
| `mb_move` | integer or named constant | Mouse button to move a window. | `nice.MB_LEFT` |
|
||||||
|
| `mb_contextmenu` | integer or named constant | Mouse button to open the nice context menu | `nice.MB_MIDDLE` |
|
||||||
|
| `mb_resize` | integer or named constant | Mouse button to resize a window | `nice.MB_RIGHT` |
|
||||||
|
| `mb_win_shade_rollup` | integer or named constant | Mouse button to roll up/hide window contents | `nice.MB_SCROLL_UP` |
|
||||||
|
| `mb_win_shade_rolldown` | integer or named constant | Mouse button to roll down/show window contents | `nice.MB_SCROLL_DOWN` |
|
||||||
|
| `button_size` | integer | The size (diameter) of the titlebar buttons | 16 |
|
||||||
|
| `button_margin_horizontal` | integer | The horizontal margin around each titlebar button. `button_margin_left` and `button_margin_right`can override this parameter. | 5 |
|
||||||
|
| `button_margin_vertical` | integer | The vertical margin above and below each titlebar button. `button_margin_top` and `button_margin_bottom` can override this parameter. | nil |
|
||||||
|
| `button_margin_top` | integer | The margin above each titlebar button | 2 |
|
||||||
|
| `button_margin_bottom` | integer | The margin below each titlebar button | nil |
|
||||||
|
| `button_margin_left` | integer | The margin to the left of each titlebar button | 0 |
|
||||||
|
| `button_margin_right` | integer | The margin to the right of each titlebar button | 0 |
|
||||||
|
| `tooltips_enabled` | boolean | If tooltip hints should be shown when the mouse cursor is hovered over a titlebar button | nil |
|
||||||
|
| `close_color` | string | The base color for the close button | "#ee4266" |
|
||||||
|
| `minimize_color` | string | The base color for the minimize button | "#ffb400" |
|
||||||
|
| `maximize_color` | string | The base color for the maximize button | "#4cbb17" |
|
||||||
|
| `floating_color` | string | The base color for the floating mode toggle button | "#f6a2ed" |
|
||||||
|
| `ontop_color` | string | The base color for the on top mode toggle button | "#f6a2ed" |
|
||||||
|
| `sticky_color` | string | The base color for the sticky mode toggle button | "#f6a2ed" |
|
||||||
|
|
||||||
|
In addition to the above mentioned parameters, there some more parameters that require a little more explanation:
|
||||||
|
|
||||||
|
### titlebar_items
|
||||||
|
|
||||||
|
`titlebar_items` — Specifies the titlebar items to include
|
||||||
|
|
||||||
|
* It should be a table with the following keys:
|
||||||
|
* `left` — Specifies the item(s) to place on the left side of the titlebar
|
||||||
|
* `middle` — Specifies the item(s) to place in the middle of the titlebar
|
||||||
|
* `right` — Specifies the items(s) to place on the right side of the titlebar
|
||||||
|
* Multiple items should be passed as an array of identifiers. For a single item simply passing the identifier is sufficient
|
||||||
|
* Valid titlebar item identifiers are:
|
||||||
|
* `"close"`
|
||||||
|
* `"minimize"`
|
||||||
|
* `"maximize"`
|
||||||
|
* `"floating"`
|
||||||
|
* `"ontop"`
|
||||||
|
* `"sticky"`
|
||||||
|
* `"title"`
|
||||||
|
* Default value for `titlebar_items` is:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
titlebar_items = {
|
||||||
|
left = {"close", "minimize", "maximize"},
|
||||||
|
middle = "title",
|
||||||
|
right = {"sticky", "ontop", "floating"},
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### context_menu_theme
|
||||||
|
|
||||||
|
`context_menu_theme` — Specifies theming parameters for the context (default right-click) menu
|
||||||
|
|
||||||
|
* It should be a table with the following keys:
|
||||||
|
* `bg_focus` — Background color of focused menu item
|
||||||
|
* `bg_normal` — Background color of not-focused menu items
|
||||||
|
* `border_color` — Color of the border around the entire menu
|
||||||
|
* `border_width` — Width of the border around the entire menu
|
||||||
|
* `fg_focus` — Foreground color of focused menu item
|
||||||
|
* `fg_normal` — Foreground color of not-focused menu items
|
||||||
|
* `font` — Font used for menu text
|
||||||
|
* `height` — Height of each menu list item
|
||||||
|
* `width` — Width of the menu
|
||||||
|
* Default value for `context_menu_theme` is:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
context_menu_theme = {
|
||||||
|
bg_focus = "#aed9e0",
|
||||||
|
bg_normal = "#5e6472",
|
||||||
|
border_color = "#00000000",
|
||||||
|
border_width = 0,
|
||||||
|
fg_focus = "#242424",
|
||||||
|
fg_normal = "#fefefa",
|
||||||
|
font = "Sans 11",
|
||||||
|
height = 27.5,
|
||||||
|
width = 250,
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### tooltip_messages
|
||||||
|
|
||||||
|
`tooltip_messages` — Specifies the hints that are shown when the mouse cursor is hovered over a titlebar button
|
||||||
|
|
||||||
|
* It should be a table with the following keys:
|
||||||
|
* `close` — Text shown when hovering over the close button
|
||||||
|
* `minimize` — Text shown when hovering over the minimize button
|
||||||
|
* `maximize_active` — Text shown when hovering over the maximize button when the window is maximized
|
||||||
|
* `maximize_inactive` — Text shown when hovering over the maximize button when the window is not maximized
|
||||||
|
* `floating_active` — Text shown when hovering over the floating button when the window is floating
|
||||||
|
* `floating_inactive` — Text shown when hovering over the floating button when the window is tiled
|
||||||
|
* `ontop_active` — Text shown when hovering over the ontop button when the window is set to be above other windows
|
||||||
|
* `ontop_inactive` — Text shown when hovering over the ontop button when the window is not set to be above other windows
|
||||||
|
* `sticky_active` — Text shown when hovering over the sticky button when the window is set to be available on all tags
|
||||||
|
* `sticky_inactive` — Text shown when hovering over the sticky button when the window is not to be available on all tags
|
||||||
|
|
||||||
|
The default value for `tooltip_messages` is:
|
||||||
|
|
||||||
|
```lua
|
||||||
|
tooltip_messages = {
|
||||||
|
close = "close",
|
||||||
|
minimize = "minimize",
|
||||||
|
maximize_active = "unmaximize",
|
||||||
|
maximize_inactive = "maximize",
|
||||||
|
floating_active = "enable tiling mode",
|
||||||
|
floating_inactive = "enable floating mode",
|
||||||
|
ontop_active = "don't keep above other windows",
|
||||||
|
ontop_inactive = "keep above other windows",
|
||||||
|
sticky_active = "disable sticky mode",
|
||||||
|
sticky_inactive = "enable sticky mode",
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Using
|
||||||
|
|
||||||
|
nice will automatically detect and change the window decoration color to match the client. However...
|
||||||
|
|
||||||
|
* If nice doesn't pick the right color or you want to specify it yourself, right-click the titlebar and select 'Manually Pick Color'
|
||||||
|
* If the client theme changes (for example if you change your terminal emulator colors), to update the window decoration colors, right-click on the titlebar and select 'Redo Window Decorations'
|
||||||
|
* Scroll-up with your mouse over the titlebar to "roll-up" the window shade. Scroll-down over the titlebar, or left-click to "roll-down" the window shade
|
||||||
|
* nice saves its color rules in the color_rules file within the module directory. If you wish you can manually edit it, or delete the file if you want to start again.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Issues
|
||||||
|
|
||||||
|
If you face any bugs or issues (or have a feature request), please feel free to open an issue on here
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
[![License](http://img.shields.io/:license-mit-blue.svg)](http://doge.mit-license.org)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,164 @@
|
||||||
|
-- => Colors
|
||||||
|
-- Provides utility functions for handling colors
|
||||||
|
-- ============================================================
|
||||||
|
local math = math
|
||||||
|
local floor = math.floor
|
||||||
|
local max = math.max
|
||||||
|
local min = math.min
|
||||||
|
local random = math.random
|
||||||
|
local gcolor = require "gears.color"
|
||||||
|
local parse_color = gcolor.parse_color
|
||||||
|
|
||||||
|
-- Returns a value that is clipped to interval edges if it falls outside the interval
|
||||||
|
local function clip(num, min_num, max_num)
|
||||||
|
return max(min(num, max_num), min_num)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Converts the given hex color to normalized rgba
|
||||||
|
local function hex2rgb(color)
|
||||||
|
-- color = color:gsub("#", "")
|
||||||
|
-- local strlen = color:len()
|
||||||
|
-- if strlen == 6 then
|
||||||
|
-- return tonumber("0x" .. color:sub(1, 2)) / 255,
|
||||||
|
-- tonumber("0x" .. color:sub(3, 4)) / 255,
|
||||||
|
-- tonumber("0x" .. color:sub(5, 6)) / 255, 1
|
||||||
|
-- end
|
||||||
|
-- if strlen == 8 then
|
||||||
|
-- return tonumber("0x" .. color:sub(1, 2)) / 255,
|
||||||
|
-- tonumber("0x" .. color:sub(3, 4)) / 255,
|
||||||
|
-- tonumber("0x" .. color:sub(5, 6)) / 255,
|
||||||
|
-- tonumber("0x" .. color:sub(7, 8)) / 255
|
||||||
|
-- end
|
||||||
|
return parse_color(color)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Converts the given hex color to hsv
|
||||||
|
local function hex2hsv(color)
|
||||||
|
local r, g, b = hex2rgb(color)
|
||||||
|
local C_max = max(r, g, b)
|
||||||
|
local C_min = min(r, g, b)
|
||||||
|
local delta = C_max - C_min
|
||||||
|
local H, S, V
|
||||||
|
if delta == 0 then
|
||||||
|
H = 0
|
||||||
|
elseif C_max == r then
|
||||||
|
H = 60 * (((g - b) / delta) % 6)
|
||||||
|
elseif C_max == g then
|
||||||
|
H = 60 * (((b - r) / delta) + 2)
|
||||||
|
elseif C_max == b then
|
||||||
|
H = 60 * (((r - g) / delta) + 4)
|
||||||
|
end
|
||||||
|
if C_max == 0 then
|
||||||
|
S = 0
|
||||||
|
else
|
||||||
|
S = delta / C_max
|
||||||
|
end
|
||||||
|
V = C_max
|
||||||
|
return H, S * 100, V * 100
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Converts the given hsv color to hex
|
||||||
|
local function hsv2hex(H, S, V)
|
||||||
|
S = S / 100
|
||||||
|
V = V / 100
|
||||||
|
if H > 360 then
|
||||||
|
H = 360
|
||||||
|
end
|
||||||
|
if H < 0 then
|
||||||
|
H = 0
|
||||||
|
end
|
||||||
|
local C = V * S
|
||||||
|
local X = C * (1 - math.abs(((H / 60) % 2) - 1))
|
||||||
|
local m = V - C
|
||||||
|
local r_, g_, b_ = 0, 0, 0
|
||||||
|
if H >= 0 and H < 60 then
|
||||||
|
r_, g_, b_ = C, X, 0
|
||||||
|
elseif H >= 60 and H < 120 then
|
||||||
|
r_, g_, b_ = X, C, 0
|
||||||
|
elseif H >= 120 and H < 180 then
|
||||||
|
r_, g_, b_ = 0, C, X
|
||||||
|
elseif H >= 180 and H < 240 then
|
||||||
|
r_, g_, b_ = 0, X, C
|
||||||
|
elseif H >= 240 and H < 300 then
|
||||||
|
r_, g_, b_ = X, 0, C
|
||||||
|
elseif H >= 300 and H < 360 then
|
||||||
|
r_, g_, b_ = C, 0, X
|
||||||
|
end
|
||||||
|
local r, g, b = (r_ + m) * 255, (g_ + m) * 255, (b_ + m) * 255
|
||||||
|
return ("#%02x%02x%02x"):format(floor(r), floor(g), floor(b))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculates the relative luminance of the given color
|
||||||
|
local function relative_luminance(color)
|
||||||
|
local r, g, b = hex2rgb(color)
|
||||||
|
local function from_sRGB(u)
|
||||||
|
return u <= 0.0031308 and 25 * u / 323 or ((200 * u + 11) / 211) ^ (12 / 5)
|
||||||
|
end
|
||||||
|
return 0.2126 * from_sRGB(r) + 0.7152 * from_sRGB(g) + 0.0722 * from_sRGB(b)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculates the contrast ratio between the two given colors
|
||||||
|
local function contrast_ratio(fg, bg)
|
||||||
|
return (relative_luminance(fg) + 0.05) / (relative_luminance(bg) + 0.05)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns true if the contrast between the two given colors is suitable
|
||||||
|
local function is_contrast_acceptable(fg, bg)
|
||||||
|
return contrast_ratio(fg, bg) >= 7 and true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns a bright-ish, saturated-ish, color of random hue
|
||||||
|
local function rand_hex(lb_angle, ub_angle)
|
||||||
|
return hsv2hex(random(lb_angle or 0, ub_angle or 360), 70, 90)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Rotates the hue of the given hex color by the specified angle (in degrees)
|
||||||
|
local function rotate_hue(color, angle)
|
||||||
|
local H, S, V = hex2hsv(color)
|
||||||
|
angle = clip(angle or 0, 0, 360)
|
||||||
|
H = (H + angle) % 360
|
||||||
|
return hsv2hex(H, S, V)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Lightens a given hex color by the specified amount
|
||||||
|
local function lighten(color, amount)
|
||||||
|
local r, g, b
|
||||||
|
r, g, b = hex2rgb(color)
|
||||||
|
r = 255 * r
|
||||||
|
g = 255 * g
|
||||||
|
b = 255 * b
|
||||||
|
r = r + floor(2.55 * amount)
|
||||||
|
g = g + floor(2.55 * amount)
|
||||||
|
b = b + floor(2.55 * amount)
|
||||||
|
r = r > 255 and 255 or r
|
||||||
|
g = g > 255 and 255 or g
|
||||||
|
b = b > 255 and 255 or b
|
||||||
|
return ("#%02x%02x%02x"):format(r, g, b)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Darkens a given hex color by the specified amount
|
||||||
|
local function darken(color, amount)
|
||||||
|
local r, g, b
|
||||||
|
r, g, b = hex2rgb(color)
|
||||||
|
r = 255 * r
|
||||||
|
g = 255 * g
|
||||||
|
b = 255 * b
|
||||||
|
r = max(0, r - floor(r * (amount / 100)))
|
||||||
|
g = max(0, g - floor(g * (amount / 100)))
|
||||||
|
b = max(0, b - floor(b * (amount / 100)))
|
||||||
|
return ("#%02x%02x%02x"):format(r, g, b)
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
clip = clip,
|
||||||
|
hex2rgb = hex2rgb,
|
||||||
|
hex2hsv = hex2hsv,
|
||||||
|
hsv2hex = hsv2hex,
|
||||||
|
relative_luminance = relative_luminance,
|
||||||
|
contrast_ratio = contrast_ratio,
|
||||||
|
is_contrast_acceptable = is_contrast_acceptable,
|
||||||
|
rand_hex = rand_hex,
|
||||||
|
rotate_hue = rotate_hue,
|
||||||
|
lighten = lighten,
|
||||||
|
darken = darken,
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
project = "awesome-wm-nice"
|
||||||
|
title = "An Awesome WM module that add MacOS-like window decorations"
|
||||||
|
|
||||||
|
all = false
|
||||||
|
dir = "doc"
|
||||||
|
format = "markdown"
|
||||||
|
pretty = "lua"
|
||||||
|
prettify_files = true
|
||||||
|
backtick_references = true
|
||||||
|
merge = true
|
||||||
|
use_markdown_titles = true
|
||||||
|
wrap = true
|
||||||
|
sort_modules = true
|
||||||
|
not_luadoc = true
|
||||||
|
|
||||||
|
file = {
|
||||||
|
"init.lua",
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Define some new ldoc tags from the AwesomeWM doc
|
||||||
|
new_type("constructorfct", "Constructor", false, "Parameters")
|
||||||
|
new_type("staticfct", "Static functions", false, "Parameters")
|
|
@ -0,0 +1,95 @@
|
||||||
|
local abutton = require "awful.button"
|
||||||
|
local gtable = require "gears.table"
|
||||||
|
|
||||||
|
local config = { mt = {}, _private = {} }
|
||||||
|
|
||||||
|
-- Titlebar
|
||||||
|
config._private.titlebar_height = 38
|
||||||
|
config._private.titlebar_radius = 9
|
||||||
|
config._private.titlebar_color = "#1E1E24"
|
||||||
|
config._private.titlebar_margin_left = 0
|
||||||
|
config._private.titlebar_margin_right = 0
|
||||||
|
config._private.titlebar_font = "Sans 11"
|
||||||
|
config._private.titlebar_items = {
|
||||||
|
left = { "close", "minimize", "maximize" },
|
||||||
|
middle = "title",
|
||||||
|
right = { "sticky", "ontop", "floating" },
|
||||||
|
}
|
||||||
|
config._private.context_menu_theme = {
|
||||||
|
bg_focus = "#aed9e0",
|
||||||
|
bg_normal = "#5e6472",
|
||||||
|
border_color = "#00000000",
|
||||||
|
border_width = 0,
|
||||||
|
fg_focus = "#242424",
|
||||||
|
fg_normal = "#fefefa",
|
||||||
|
font = "Sans 11",
|
||||||
|
height = 27.5,
|
||||||
|
width = 250,
|
||||||
|
}
|
||||||
|
config._private.win_shade_enabled = true
|
||||||
|
config._private.no_titlebar_maximized = false
|
||||||
|
config._private.mb_move = abutton.names.LEFT
|
||||||
|
config._private.mb_contextmenu = abutton.names.MIDDLE
|
||||||
|
config._private.mb_resize = abutton.names.RIGHT
|
||||||
|
config._private.mb_win_shade_rollup = abutton.names.SCROLL_UP
|
||||||
|
config._private.mb_win_shade_rolldown = abutton.names.SCROLL_DOWN
|
||||||
|
|
||||||
|
-- Titlebar Items
|
||||||
|
config._private.button_size = 16
|
||||||
|
config._private.button_margin_horizontal = 5
|
||||||
|
-- _private.button_margin_vertical
|
||||||
|
config._private.button_margin_top = 2
|
||||||
|
-- _private.button_margin_bottom = 0
|
||||||
|
-- _private.button_margin_left = 0
|
||||||
|
-- _private.button_margin_right = 0
|
||||||
|
config._private.tooltips_enabled = true
|
||||||
|
config._private.tooltip_messages = {
|
||||||
|
close = "close",
|
||||||
|
minimize = "minimize",
|
||||||
|
maximize_active = "unmaximize",
|
||||||
|
maximize_inactive = "maximize",
|
||||||
|
floating_active = "enable tiling mode",
|
||||||
|
floating_inactive = "enable floating mode",
|
||||||
|
ontop_active = "don't keep above other windows",
|
||||||
|
ontop_inactive = "keep above other windows",
|
||||||
|
sticky_active = "disable sticky mode",
|
||||||
|
sticky_inactive = "enable sticky mode",
|
||||||
|
}
|
||||||
|
config._private.close_color = "#ee4266"
|
||||||
|
config._private.minimize_color = "#ffb400"
|
||||||
|
config._private.maximize_color = "#4CBB17"
|
||||||
|
config._private.floating_color = "#f6a2ed"
|
||||||
|
config._private.ontop_color = "#f6a2ed"
|
||||||
|
config._private.sticky_color = "#f6a2ed"
|
||||||
|
|
||||||
|
function config.init(args)
|
||||||
|
-- properties that are table
|
||||||
|
local table_args = {
|
||||||
|
titlebar_items = true,
|
||||||
|
context_menu_theme = true,
|
||||||
|
tooltip_messages = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Apply changes to our _private properties
|
||||||
|
if args then
|
||||||
|
for prop, value in pairs(args) do
|
||||||
|
if table_args[prop] == true then
|
||||||
|
gtable.crush(config._private[prop], value)
|
||||||
|
elseif prop == "titlebar_radius" then
|
||||||
|
config._private[prop] = math.max(3, value)
|
||||||
|
else
|
||||||
|
config._private[prop] = value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function config.mt:__index(k)
|
||||||
|
return config._private[k]
|
||||||
|
end
|
||||||
|
|
||||||
|
function config.mt:__newindex(k, v)
|
||||||
|
config._private[k] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(config, config.mt)
|
|
@ -0,0 +1,472 @@
|
||||||
|
--[[
|
||||||
|
███╗ ██╗██╗ ██████╗███████╗
|
||||||
|
████╗ ██║██║██╔════╝██╔════╝
|
||||||
|
██╔██╗ ██║██║██║ █████╗
|
||||||
|
██║╚██╗██║██║██║ ██╔══╝
|
||||||
|
██║ ╚████║██║╚██████╗███████╗
|
||||||
|
╚═╝ ╚═══╝╚═╝ ╚═════╝╚══════╝
|
||||||
|
Author: mu-tex
|
||||||
|
License: MIT
|
||||||
|
Repository: https://github.com/mut-ex/awesome-wm-nice
|
||||||
|
]]
|
||||||
|
|
||||||
|
local awful = require "awful"
|
||||||
|
local abutton = awful.button
|
||||||
|
local wibox = require "wibox"
|
||||||
|
-- Widgets
|
||||||
|
local imagebox = wibox.widget.imagebox
|
||||||
|
-- Layouts
|
||||||
|
local wlayout = wibox.layout
|
||||||
|
local wlayout_align_horizontal = wlayout.align.horizontal
|
||||||
|
local wlayout_flex_horizontal = wlayout.flex.horizontal
|
||||||
|
-- Containers
|
||||||
|
local wcontainer = wibox.container
|
||||||
|
local wcontainer_background = wcontainer.background
|
||||||
|
local wcontainer_margin = wcontainer.margin
|
||||||
|
-- Gears
|
||||||
|
local gtimer = require "gears.timer"
|
||||||
|
local gtimer_weak_start_new = gtimer.weak_start_new
|
||||||
|
local gtable = require "gears.table"
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
|
||||||
|
-- => Math + standard Lua methods
|
||||||
|
-- ============================================================
|
||||||
|
local math = math
|
||||||
|
local abs = math.abs
|
||||||
|
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
|
||||||
|
-- => LGI
|
||||||
|
-- ============================================================
|
||||||
|
local lgi = require "lgi"
|
||||||
|
local gdk = lgi.require("Gdk", "3.0")
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
|
||||||
|
-- => nice
|
||||||
|
-- ============================================================
|
||||||
|
-- Config
|
||||||
|
local config = require "awesome-wm-nice.config"
|
||||||
|
-- Colors
|
||||||
|
local colors = require "awesome-wm-nice.colors"
|
||||||
|
local color_darken = colors.darken
|
||||||
|
local color_lighten = colors.lighten
|
||||||
|
local relative_luminance = colors.relative_luminance
|
||||||
|
-- Client Shade
|
||||||
|
local shade = require "awesome-wm-nice.shade"
|
||||||
|
-- Shapes
|
||||||
|
local shapes = require "awesome-wm-nice.shapes"
|
||||||
|
local create_corner_top_left = shapes.create_corner_top_left
|
||||||
|
local create_edge_left = shapes.create_edge_left
|
||||||
|
local create_edge_top_middle = shapes.create_edge_top_middle
|
||||||
|
local gradient = shapes.duotone_gradient_vertical
|
||||||
|
-- Utils
|
||||||
|
local utils = require "awesome-wm-nice.utils"
|
||||||
|
-- Widgets builder
|
||||||
|
local widgets = require "awesome-wm-nice.widgets"
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
|
||||||
|
gdk.init {}
|
||||||
|
|
||||||
|
-- => Local settings
|
||||||
|
-- ============================================================
|
||||||
|
local bottom_edge_height = 3
|
||||||
|
local double_click_jitter_tolerance = 4
|
||||||
|
local double_click_time_window_ms = 250
|
||||||
|
local stroke_inner_bottom_lighten_mul = 0.4
|
||||||
|
local stroke_inner_sides_lighten_mul = 0.4
|
||||||
|
local stroke_outer_top_darken_mul = 0.7
|
||||||
|
local titlebar_gradient_c1_lighten = 1
|
||||||
|
local titlebar_gradient_c2_offset = 0.5
|
||||||
|
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
|
||||||
|
local nice = {}
|
||||||
|
|
||||||
|
-- => Defaults
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
|
||||||
|
-- => Saving and loading of color rules
|
||||||
|
-- ============================================================
|
||||||
|
local t = require "awesome-wm-nice.table"
|
||||||
|
|
||||||
|
-- Load the color rules or create an empty table if there aren't any
|
||||||
|
local gfilesys = require "gears.filesystem"
|
||||||
|
local config_dir = gfilesys.get_configuration_dir()
|
||||||
|
local color_rules_filename = "color_rules"
|
||||||
|
local color_rules_filepath = config_dir .. "/nice/" .. color_rules_filename
|
||||||
|
config.color_rules = t.load(color_rules_filepath) or {}
|
||||||
|
|
||||||
|
-- Saves the contents of config.color_rules table to file
|
||||||
|
local function save_color_rules()
|
||||||
|
t.save(config.color_rules, color_rules_filepath)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Adds a color rule entry to the color_rules table for the given client and saves to file
|
||||||
|
local function set_color_rule(c, color)
|
||||||
|
config.color_rules[c.instance] = color
|
||||||
|
save_color_rules()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Fetches the color rule for the given client instance
|
||||||
|
local function get_color_rule(c)
|
||||||
|
return config.color_rules[c.instance]
|
||||||
|
end
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
|
||||||
|
function nice.get_titlebar_mouse_bindings(c)
|
||||||
|
local shade_enabled = config.win_shade_enabled
|
||||||
|
-- Add functionality for double click to (un)maximize, and single click and hold to move
|
||||||
|
local clicks = 0
|
||||||
|
local tolerance = double_click_jitter_tolerance
|
||||||
|
local buttons = {
|
||||||
|
abutton({}, config.mb_move, function()
|
||||||
|
local cx, cy = _G.mouse.coords().x, _G.mouse.coords().y
|
||||||
|
local delta = double_click_time_window_ms / 1000
|
||||||
|
clicks = clicks + 1
|
||||||
|
if clicks == 2 then
|
||||||
|
local nx, ny = _G.mouse.coords().x, _G.mouse.coords().y
|
||||||
|
-- The second click is only counted as a double click if it is
|
||||||
|
-- within the neighborhood of the first click's position, and
|
||||||
|
-- occurs within the set time window
|
||||||
|
if abs(cx - nx) <= tolerance and abs(cy - ny) <= tolerance then
|
||||||
|
if shade_enabled then
|
||||||
|
shade.shade_roll_down(c)
|
||||||
|
end
|
||||||
|
c.maximized = not c.maximized
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if shade_enabled and c._nice_window_shade_up then
|
||||||
|
-- shade.shade_roll_down(c)
|
||||||
|
awful.mouse.wibox.move(c._nice_window_shade)
|
||||||
|
else
|
||||||
|
c:activate { context = "titlebar", action = "mouse_move" }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Start a timer to clear the click count
|
||||||
|
gtimer_weak_start_new(delta, function()
|
||||||
|
clicks = 0
|
||||||
|
end)
|
||||||
|
end),
|
||||||
|
abutton({}, config.mb_contextmenu, function()
|
||||||
|
local menu_items = {}
|
||||||
|
local function add_item(text, callback)
|
||||||
|
menu_items[#menu_items + 1] = { text, callback }
|
||||||
|
end
|
||||||
|
-- TODO: Add client control options as menu entries for options that haven't had their buttons added
|
||||||
|
add_item("Redo Window Decorations", function()
|
||||||
|
c._nice_base_color = utils.get_dominant_color(c)
|
||||||
|
set_color_rule(c, c._nice_base_color)
|
||||||
|
nice.add_window_decoration(c)
|
||||||
|
end)
|
||||||
|
add_item("Manually Pick Color", function()
|
||||||
|
_G.mousegrabber.run(function(m)
|
||||||
|
if m.buttons[1] then
|
||||||
|
c._nice_base_color = utils.get_pixel_at(m.x, m.y)
|
||||||
|
set_color_rule(c, c._nice_base_color)
|
||||||
|
nice.add_window_decoration(c)
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end, "crosshair")
|
||||||
|
end)
|
||||||
|
add_item("Nevermind...", function() end)
|
||||||
|
if c._nice_right_click_menu then
|
||||||
|
c._nice_right_click_menu:hide()
|
||||||
|
end
|
||||||
|
c._nice_right_click_menu = awful.menu {
|
||||||
|
items = menu_items,
|
||||||
|
theme = config.context_menu_theme,
|
||||||
|
}
|
||||||
|
c._nice_right_click_menu:show()
|
||||||
|
end),
|
||||||
|
abutton({}, config.mb_resize, function()
|
||||||
|
c:activate { context = "mouse_click", action = "mouse_resize" }
|
||||||
|
end),
|
||||||
|
}
|
||||||
|
|
||||||
|
if config.win_shade_enabled then
|
||||||
|
buttons[#buttons + 1] = abutton({}, config.mb_win_shade_rollup, function()
|
||||||
|
shade.shade_roll_up(c)
|
||||||
|
end)
|
||||||
|
buttons[#buttons + 1] = abutton({}, config.mb_win_shade_rolldown, function()
|
||||||
|
shade.shade_roll_down(c)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
return buttons
|
||||||
|
end
|
||||||
|
|
||||||
|
-- ------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Puts all the pieces together and decorates the given client
|
||||||
|
function nice.add_window_decoration(c)
|
||||||
|
local client_color = c._nice_base_color
|
||||||
|
local client_geometry = c:geometry()
|
||||||
|
|
||||||
|
-- Closures to avoid repitition
|
||||||
|
local lighten = function(amount)
|
||||||
|
return color_lighten(client_color, amount)
|
||||||
|
end
|
||||||
|
local darken = function(amount)
|
||||||
|
return color_darken(client_color, amount)
|
||||||
|
end
|
||||||
|
-- > Color computations
|
||||||
|
local luminance = relative_luminance(client_color)
|
||||||
|
local lighten_amount = utils.rel_lighten(luminance)
|
||||||
|
local darken_amount = utils.rel_darken(luminance)
|
||||||
|
-- Inner strokes
|
||||||
|
local stroke_color_inner_top = lighten(lighten_amount)
|
||||||
|
local stroke_color_inner_sides = lighten(lighten_amount * stroke_inner_sides_lighten_mul)
|
||||||
|
local stroke_color_inner_bottom = lighten(lighten_amount * stroke_inner_bottom_lighten_mul)
|
||||||
|
-- Outer strokes
|
||||||
|
local stroke_color_outer_top = darken(darken_amount * stroke_outer_top_darken_mul)
|
||||||
|
local stroke_color_outer_sides = darken(darken_amount)
|
||||||
|
local stroke_color_outer_bottom = darken(darken_amount)
|
||||||
|
local titlebar_height = config.titlebar_height
|
||||||
|
local background_fill_top =
|
||||||
|
gradient(lighten(titlebar_gradient_c1_lighten), client_color, titlebar_height, 0, titlebar_gradient_c2_offset)
|
||||||
|
-- The top left corner of the titlebar
|
||||||
|
local corner_top_left_img = create_corner_top_left {
|
||||||
|
background_source = background_fill_top,
|
||||||
|
color = client_color,
|
||||||
|
height = titlebar_height,
|
||||||
|
radius = config.titlebar_radius,
|
||||||
|
stroke_offset_inner = 1.5,
|
||||||
|
stroke_width_inner = 1,
|
||||||
|
stroke_offset_outer = 0.5,
|
||||||
|
stroke_width_outer = 1,
|
||||||
|
stroke_source_inner = gradient(stroke_color_inner_top, stroke_color_inner_sides, titlebar_height),
|
||||||
|
stroke_source_outer = gradient(stroke_color_outer_top, stroke_color_outer_sides, titlebar_height),
|
||||||
|
}
|
||||||
|
-- The top right corner of the titlebar
|
||||||
|
local corner_top_right_img = shapes.flip(corner_top_left_img, "horizontal")
|
||||||
|
|
||||||
|
-- The middle part of the titlebar
|
||||||
|
local top_edge = create_edge_top_middle {
|
||||||
|
background_source = background_fill_top,
|
||||||
|
color = client_color,
|
||||||
|
height = titlebar_height,
|
||||||
|
stroke_color_inner = stroke_color_inner_top,
|
||||||
|
stroke_color_outer = stroke_color_outer_top,
|
||||||
|
stroke_offset_inner = 1.25,
|
||||||
|
stroke_offset_outer = 0.5,
|
||||||
|
stroke_width_inner = 2,
|
||||||
|
stroke_width_outer = 1,
|
||||||
|
width = client_geometry.width,
|
||||||
|
}
|
||||||
|
-- Create the titlebar
|
||||||
|
local titlebar = awful.titlebar(c, { size = titlebar_height, bg = "transparent" })
|
||||||
|
-- Arrange the graphics
|
||||||
|
titlebar.widget = {
|
||||||
|
imagebox(corner_top_left_img, false),
|
||||||
|
{
|
||||||
|
{
|
||||||
|
{
|
||||||
|
utils.create_titlebar_items(c, config.titlebar_items.left),
|
||||||
|
widget = wcontainer_margin,
|
||||||
|
left = config.titlebar_margin_left,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
utils.create_titlebar_items(c, config.titlebar_items.middle),
|
||||||
|
buttons = nice.get_titlebar_mouse_bindings(c),
|
||||||
|
layout = wlayout_flex_horizontal,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
utils.create_titlebar_items(c, config.titlebar_items.right),
|
||||||
|
widget = wcontainer_margin,
|
||||||
|
right = config.titlebar_margin_right,
|
||||||
|
},
|
||||||
|
layout = wlayout_align_horizontal,
|
||||||
|
},
|
||||||
|
widget = wcontainer_background,
|
||||||
|
bgimage = top_edge,
|
||||||
|
},
|
||||||
|
imagebox(corner_top_right_img, false),
|
||||||
|
layout = wlayout_align_horizontal,
|
||||||
|
}
|
||||||
|
|
||||||
|
local resize_button = {
|
||||||
|
abutton({}, 1, function()
|
||||||
|
c:activate { context = "mouse_click", action = "mouse_resize" }
|
||||||
|
end),
|
||||||
|
}
|
||||||
|
|
||||||
|
-- The left side border
|
||||||
|
local left_border_img = create_edge_left {
|
||||||
|
client_color = client_color,
|
||||||
|
height = client_geometry.height,
|
||||||
|
stroke_offset_outer = 0.5,
|
||||||
|
stroke_width_outer = 1,
|
||||||
|
stroke_color_outer = stroke_color_outer_sides,
|
||||||
|
stroke_offset_inner = 1.5,
|
||||||
|
stroke_width_inner = 1.5,
|
||||||
|
inner_stroke_color = stroke_color_inner_sides,
|
||||||
|
}
|
||||||
|
-- The right side border
|
||||||
|
local right_border_img = shapes.flip(left_border_img, "horizontal")
|
||||||
|
local left_side_border = awful.titlebar(c, {
|
||||||
|
position = "left",
|
||||||
|
size = 2,
|
||||||
|
bg = client_color,
|
||||||
|
widget = wcontainer_background,
|
||||||
|
})
|
||||||
|
left_side_border:setup {
|
||||||
|
buttons = resize_button,
|
||||||
|
widget = wcontainer_background,
|
||||||
|
bgimage = left_border_img,
|
||||||
|
}
|
||||||
|
local right_side_border = awful.titlebar(c, {
|
||||||
|
position = "right",
|
||||||
|
size = 2,
|
||||||
|
bg = client_color,
|
||||||
|
widget = wcontainer_background,
|
||||||
|
})
|
||||||
|
right_side_border:setup {
|
||||||
|
widget = wcontainer_background,
|
||||||
|
bgimage = right_border_img,
|
||||||
|
buttons = resize_button,
|
||||||
|
}
|
||||||
|
local corner_bottom_left_img = shapes.flip(
|
||||||
|
create_corner_top_left {
|
||||||
|
color = client_color,
|
||||||
|
radius = bottom_edge_height,
|
||||||
|
height = bottom_edge_height,
|
||||||
|
background_source = background_fill_top,
|
||||||
|
stroke_offset_inner = 1.5,
|
||||||
|
stroke_offset_outer = 0.5,
|
||||||
|
stroke_source_outer = gradient(
|
||||||
|
stroke_color_outer_bottom,
|
||||||
|
stroke_color_outer_sides,
|
||||||
|
bottom_edge_height,
|
||||||
|
0,
|
||||||
|
0.25
|
||||||
|
),
|
||||||
|
stroke_source_inner = gradient(stroke_color_inner_bottom, stroke_color_inner_sides, bottom_edge_height),
|
||||||
|
stroke_width_inner = 1.5,
|
||||||
|
stroke_width_outer = 2,
|
||||||
|
},
|
||||||
|
"vertical"
|
||||||
|
)
|
||||||
|
local corner_bottom_right_img = shapes.flip(corner_bottom_left_img, "horizontal")
|
||||||
|
local bottom_edge = shapes.flip(
|
||||||
|
create_edge_top_middle {
|
||||||
|
color = client_color,
|
||||||
|
height = bottom_edge_height,
|
||||||
|
background_source = background_fill_top,
|
||||||
|
stroke_color_inner = stroke_color_inner_bottom,
|
||||||
|
stroke_color_outer = stroke_color_outer_bottom,
|
||||||
|
stroke_offset_inner = 1.25,
|
||||||
|
stroke_offset_outer = 0.5,
|
||||||
|
stroke_width_inner = 1,
|
||||||
|
stroke_width_outer = 1,
|
||||||
|
width = client_geometry.width,
|
||||||
|
},
|
||||||
|
"vertical"
|
||||||
|
)
|
||||||
|
local bottom = awful.titlebar(c, {
|
||||||
|
size = bottom_edge_height,
|
||||||
|
bg = "transparent",
|
||||||
|
position = "bottom",
|
||||||
|
})
|
||||||
|
bottom.widget = wibox.widget {
|
||||||
|
imagebox(corner_bottom_left_img, false),
|
||||||
|
-- {widget = wcontainer_background, bgimage = bottom_edge},
|
||||||
|
imagebox(bottom_edge, false),
|
||||||
|
|
||||||
|
imagebox(corner_bottom_right_img, false),
|
||||||
|
layout = wlayout_align_horizontal,
|
||||||
|
buttons = resize_button,
|
||||||
|
}
|
||||||
|
if config.win_shade_enabled then
|
||||||
|
shade.add_window_shade(c, titlebar.widget, bottom.widget)
|
||||||
|
end
|
||||||
|
|
||||||
|
if config.no_titlebar_maximized then
|
||||||
|
c:connect_signal("property::maximized", function()
|
||||||
|
if c.maximized then
|
||||||
|
local curr_screen_workarea = client.focus.screen.workarea
|
||||||
|
awful.titlebar.hide(c)
|
||||||
|
c.shape = nil
|
||||||
|
c:geometry {
|
||||||
|
x = curr_screen_workarea.x,
|
||||||
|
y = curr_screen_workarea.y,
|
||||||
|
width = curr_screen_workarea.width,
|
||||||
|
height = curr_screen_workarea.height,
|
||||||
|
}
|
||||||
|
else
|
||||||
|
awful.titlebar.show(c)
|
||||||
|
-- Shape the client
|
||||||
|
c.shape = shapes.rounded_rect {
|
||||||
|
tl = config.titlebar_radius,
|
||||||
|
tr = config.titlebar_radius,
|
||||||
|
bl = 4,
|
||||||
|
br = 4,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Clean up
|
||||||
|
collectgarbage "collect"
|
||||||
|
end
|
||||||
|
|
||||||
|
function nice.apply_client_shape(c)
|
||||||
|
c.shape = shapes.rounded_rect {
|
||||||
|
tl = config.titlebar_radius,
|
||||||
|
tr = config.titlebar_radius,
|
||||||
|
bl = 4,
|
||||||
|
br = 4,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function nice.initialize(args)
|
||||||
|
config.init(args)
|
||||||
|
|
||||||
|
utils.validate_mb_bindings(config)
|
||||||
|
|
||||||
|
_G.client.connect_signal("request::titlebars", function(c)
|
||||||
|
-- Callback
|
||||||
|
c._cb_add_window_decorations = function()
|
||||||
|
gtimer_weak_start_new(0.25, function()
|
||||||
|
c._nice_base_color = utils.get_dominant_color(c)
|
||||||
|
set_color_rule(c, c._nice_base_color)
|
||||||
|
nice.add_window_decoration(c)
|
||||||
|
-- table.save(config, config_dir .. "/nice/private")
|
||||||
|
c:disconnect_signal("request::activate", c._cb_add_window_decorations)
|
||||||
|
end)
|
||||||
|
end -- _cb_add_window_decorations
|
||||||
|
|
||||||
|
-- Check if a color rule already exists...
|
||||||
|
local base_color = get_color_rule(c)
|
||||||
|
if base_color then
|
||||||
|
-- If so, use that color rule
|
||||||
|
c._nice_base_color = base_color
|
||||||
|
nice.add_window_decoration(c)
|
||||||
|
else
|
||||||
|
-- Otherwise use the default titlebar temporarily
|
||||||
|
c._nice_base_color = config.titlebar_color
|
||||||
|
nice.add_window_decoration(c)
|
||||||
|
-- Connect a signal to determine the client color and then re-decorate it
|
||||||
|
c:connect_signal("request::activate", c._cb_add_window_decorations)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Shape the client
|
||||||
|
nice.apply_client_shape(c)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Force the window decoration to be re-created when the client size change.
|
||||||
|
_G.client.connect_signal("property::size", function(c)
|
||||||
|
nice.add_window_decoration(c)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return gtable.join(nice, {
|
||||||
|
colors = colors,
|
||||||
|
config = config,
|
||||||
|
shade = shade,
|
||||||
|
shapes = shapes,
|
||||||
|
table = t,
|
||||||
|
utils = utils,
|
||||||
|
widgets = widgets,
|
||||||
|
})
|
|
@ -0,0 +1,79 @@
|
||||||
|
local config = require "awesome-wm-nice.config"
|
||||||
|
local shapes = require "awesome-wm-nice.shapes"
|
||||||
|
local wibox = require "wibox"
|
||||||
|
local wlayout_manual = require "wibox.layout.manual"
|
||||||
|
|
||||||
|
local shade = {}
|
||||||
|
|
||||||
|
-- Legacy global variables
|
||||||
|
local bottom_edge_height = 3
|
||||||
|
|
||||||
|
-- Adds a window shade to the given client
|
||||||
|
function shade.add_window_shade(c, src_top, src_bottom)
|
||||||
|
local geo = c:geometry()
|
||||||
|
local w = wibox()
|
||||||
|
w.width = geo.width
|
||||||
|
w.background = "transparent"
|
||||||
|
w.x = geo.x
|
||||||
|
w.y = geo.y
|
||||||
|
w.height = config.titlebar_height + bottom_edge_height
|
||||||
|
w.ontop = true
|
||||||
|
w.visible = false
|
||||||
|
w.shape = shapes.rounded_rect {
|
||||||
|
tl = config.titlebar_radius,
|
||||||
|
tr = config.titlebar_radius,
|
||||||
|
bl = 4,
|
||||||
|
br = 4,
|
||||||
|
}
|
||||||
|
-- Need to use a manual layout because layout fixed seems to introduce a thin gap
|
||||||
|
src_top.point = { x = 0, y = 0 }
|
||||||
|
src_top.forced_width = geo.width
|
||||||
|
src_bottom.point = { x = 0, y = config.titlebar_height }
|
||||||
|
w.widget = { src_top, src_bottom, layout = wlayout_manual }
|
||||||
|
-- Clean up resources when a client is killed
|
||||||
|
c:connect_signal("request::unmanage", function()
|
||||||
|
if c._nice_window_shade then
|
||||||
|
c._nice_window_shade.visible = false
|
||||||
|
c._nice_window_shade = nil
|
||||||
|
end
|
||||||
|
-- Clean up
|
||||||
|
collectgarbage "collect"
|
||||||
|
end)
|
||||||
|
c._nice_window_shade_up = false
|
||||||
|
c._nice_window_shade = w
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Shows the window contents
|
||||||
|
function shade.shade_roll_down(c)
|
||||||
|
if not c._nice_window_shade_up then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
c:geometry { x = c._nice_window_shade.x, y = c._nice_window_shade.y }
|
||||||
|
c:activate()
|
||||||
|
c._nice_window_shade.visible = false
|
||||||
|
c._nice_window_shade_up = false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Hides the window contents
|
||||||
|
function shade.shade_roll_up(c)
|
||||||
|
if c._nice_window_shade_up then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local w = c._nice_window_shade
|
||||||
|
local geo = c:geometry()
|
||||||
|
w.x = geo.x
|
||||||
|
w.y = geo.y
|
||||||
|
w.width = geo.width
|
||||||
|
c.minimized = true
|
||||||
|
w.visible = true
|
||||||
|
w.ontop = true
|
||||||
|
c._nice_window_shade_up = true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Toggles the window shade state
|
||||||
|
function shade.shade_toggle(c)
|
||||||
|
c.minimized = not c.minimized
|
||||||
|
c._nice_window_shade.visible = c.minimized
|
||||||
|
end
|
||||||
|
|
||||||
|
return shade
|
|
@ -0,0 +1,247 @@
|
||||||
|
-- => Shapes
|
||||||
|
-- Provides utility functions for handling cairo shapes and geometry
|
||||||
|
-- ============================================================
|
||||||
|
--
|
||||||
|
local colors = require "awesome-wm-nice.colors"
|
||||||
|
local lgi = require "lgi"
|
||||||
|
local hex2rgb = colors.hex2rgb
|
||||||
|
local cairo = lgi.cairo
|
||||||
|
local math = math
|
||||||
|
local rad = math.rad
|
||||||
|
|
||||||
|
-- Returns a shape function for a rounded rectangle with independently configurable corner radii
|
||||||
|
local function rounded_rect(args)
|
||||||
|
local r1 = args.tl or 0
|
||||||
|
local r2 = args.bl or 0
|
||||||
|
local r3 = args.br or 0
|
||||||
|
local r4 = args.tr or 0
|
||||||
|
return function(cr, width, height)
|
||||||
|
cr:new_sub_path()
|
||||||
|
cr:arc(width - r1, r1, r1, rad(-90), rad(0))
|
||||||
|
cr:arc(width - r2, height - r2, r2, rad(0), rad(90))
|
||||||
|
cr:arc(r3, height - r3, r3, rad(90), rad(180))
|
||||||
|
cr:arc(r4, r4, r4, rad(180), rad(270))
|
||||||
|
cr:close_path()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns a circle of the specified size filled with the specified color
|
||||||
|
local function circle_filled(color, size)
|
||||||
|
color = color or "#fefefa"
|
||||||
|
local surface = cairo.ImageSurface.create("ARGB32", size, size)
|
||||||
|
local cr = cairo.Context.create(surface)
|
||||||
|
cr:arc(size / 2, size / 2, size / 2, rad(0), rad(360))
|
||||||
|
cr:set_source_rgba(hex2rgb(color))
|
||||||
|
cr.antialias = cairo.Antialias.BEST
|
||||||
|
cr:fill()
|
||||||
|
-- cr:arc(
|
||||||
|
-- size / 2, size / 2, size / 2 - 0.5, rad(135), rad(270))
|
||||||
|
-- cr:set_source_rgba(hex2rgb(darken(color, 25)))
|
||||||
|
-- cr.line_width = 1
|
||||||
|
-- cr:stroke()
|
||||||
|
|
||||||
|
return surface
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns a vertical gradient pattern going from cololr_1 -> color_2
|
||||||
|
local function duotone_gradient_vertical(color_1, color_2, height, offset_1, offset_2)
|
||||||
|
local fill_pattern = cairo.Pattern.create_linear(0, 0, 0, height)
|
||||||
|
local r, g, b, a
|
||||||
|
r, g, b, a = hex2rgb(color_1)
|
||||||
|
fill_pattern:add_color_stop_rgba(offset_1 or 0, r, g, b, a)
|
||||||
|
r, g, b, a = hex2rgb(color_2)
|
||||||
|
fill_pattern:add_color_stop_rgba(offset_2 or 1, r, g, b, a)
|
||||||
|
return fill_pattern
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns a horizontal gradient pattern going from cololr_1 -> color_2
|
||||||
|
local function duotone_gradient_horizontal(color, width)
|
||||||
|
local fill_pattern = cairo.Pattern.create_linear(0, 0, width, 0)
|
||||||
|
local r, g, b, a
|
||||||
|
r, g, b, a = hex2rgb(color)
|
||||||
|
fill_pattern:add_color_stop_rgba(0, r, g, b, a)
|
||||||
|
r, g, b, a = hex2rgb(color)
|
||||||
|
fill_pattern:add_color_stop_rgba(0.5, r, g, b, a)
|
||||||
|
r, g, b, a = hex2rgb "#00000000"
|
||||||
|
fill_pattern:add_color_stop_rgba(0.6, r, g, b, a)
|
||||||
|
r, g, b, a = hex2rgb(color)
|
||||||
|
fill_pattern:add_color_stop_rgba(0.7, r, g, b, a)
|
||||||
|
r, g, b, a = hex2rgb(color)
|
||||||
|
fill_pattern:add_color_stop_rgba(1, r, g, b, a)
|
||||||
|
return fill_pattern
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Flips the given surface around the specified axis
|
||||||
|
local function flip(surface, axis)
|
||||||
|
local width = surface:get_width()
|
||||||
|
local height = surface:get_height()
|
||||||
|
local flipped = cairo.ImageSurface.create("ARGB32", width, height)
|
||||||
|
local cr = cairo.Context.create(flipped)
|
||||||
|
local source_pattern = cairo.Pattern.create_for_surface(surface)
|
||||||
|
if axis == "horizontal" then
|
||||||
|
source_pattern.matrix = cairo.Matrix { xx = -1, yy = 1, x0 = width }
|
||||||
|
elseif axis == "vertical" then
|
||||||
|
source_pattern.matrix = cairo.Matrix { xx = 1, yy = -1, y0 = height }
|
||||||
|
elseif axis == "both" then
|
||||||
|
source_pattern.matrix = cairo.Matrix {
|
||||||
|
xx = -1,
|
||||||
|
yy = -1,
|
||||||
|
x0 = width,
|
||||||
|
y0 = height,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
cr.source = source_pattern
|
||||||
|
cr:rectangle(0, 0, width, height)
|
||||||
|
cr:paint()
|
||||||
|
|
||||||
|
return flipped
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Draws the left corner of the titlebar
|
||||||
|
local function create_corner_top_left(args)
|
||||||
|
local radius = args.radius
|
||||||
|
local height = args.height
|
||||||
|
local surface = cairo.ImageSurface.create("ARGB32", radius, height)
|
||||||
|
local cr = cairo.Context.create(surface)
|
||||||
|
-- Create the corner shape and fill it with a gradient
|
||||||
|
local radius_offset = 1 -- To soften the corner
|
||||||
|
cr:move_to(0, height)
|
||||||
|
cr:line_to(0, radius - radius_offset)
|
||||||
|
cr:arc(radius + radius_offset, radius + radius_offset, radius, rad(180), rad(270))
|
||||||
|
cr:line_to(radius, height)
|
||||||
|
cr:close_path()
|
||||||
|
cr.source = args.background_source
|
||||||
|
cr.antialias = cairo.Antialias.BEST
|
||||||
|
cr:fill()
|
||||||
|
-- Next add the subtle 3D look
|
||||||
|
local function add_stroke(nargs)
|
||||||
|
local arc_radius = nargs.radius
|
||||||
|
local offset_x = nargs.offset_x
|
||||||
|
local offset_y = nargs.offset_y
|
||||||
|
cr:new_sub_path()
|
||||||
|
cr:move_to(offset_x, height)
|
||||||
|
cr:line_to(offset_x, arc_radius + offset_y)
|
||||||
|
cr:arc(arc_radius + offset_x, arc_radius + offset_y, arc_radius, rad(180), rad(270))
|
||||||
|
cr.source = nargs.source
|
||||||
|
cr.line_width = nargs.width
|
||||||
|
cr.antialias = cairo.Antialias.BEST
|
||||||
|
cr:stroke()
|
||||||
|
end
|
||||||
|
-- Outer dark stroke
|
||||||
|
add_stroke {
|
||||||
|
offset_x = args.stroke_offset_outer,
|
||||||
|
offset_y = args.stroke_offset_outer,
|
||||||
|
radius = radius + 0.5,
|
||||||
|
source = args.stroke_source_outer,
|
||||||
|
width = args.stroke_width_outer,
|
||||||
|
}
|
||||||
|
-- Inner light stroke
|
||||||
|
add_stroke {
|
||||||
|
offset_x = args.stroke_offset_inner,
|
||||||
|
offset_y = args.stroke_offset_inner,
|
||||||
|
radius = radius,
|
||||||
|
width = args.stroke_width_inner,
|
||||||
|
source = args.stroke_source_inner,
|
||||||
|
}
|
||||||
|
|
||||||
|
return surface
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Draws the middle of the titlebar
|
||||||
|
local function create_edge_top_middle(args)
|
||||||
|
local height = args.height
|
||||||
|
local width = args.width
|
||||||
|
local surface = cairo.ImageSurface.create("ARGB32", width, height)
|
||||||
|
local cr = cairo.Context.create(surface)
|
||||||
|
-- Create the background shape and fill it with a gradient
|
||||||
|
cr:rectangle(0, 0, width, height)
|
||||||
|
cr.source = args.background_source
|
||||||
|
cr:fill()
|
||||||
|
-- Then add the light and dark strokes for that 3D look
|
||||||
|
local function add_stroke(stroke_width, stroke_offset, stroke_color)
|
||||||
|
cr:new_sub_path()
|
||||||
|
cr:move_to(0, stroke_offset)
|
||||||
|
cr:line_to(width, stroke_offset)
|
||||||
|
cr.line_width = stroke_width
|
||||||
|
cr:set_source_rgb(hex2rgb(stroke_color))
|
||||||
|
cr:stroke()
|
||||||
|
end
|
||||||
|
-- Inner light stroke
|
||||||
|
add_stroke(
|
||||||
|
args.stroke_width_inner, -- 2
|
||||||
|
args.stroke_offset_inner, -- 1.25
|
||||||
|
args.stroke_color_inner -- color_lighten(client_color, utils.rel_lighten(relative_luminance(client_color)))
|
||||||
|
)
|
||||||
|
-- Outer dark stroke
|
||||||
|
add_stroke(
|
||||||
|
args.stroke_width_outer, -- 1
|
||||||
|
args.stroke_offset_outer, -- 0.5
|
||||||
|
args.stroke_color_outer -- color_darken(client_color, utils.rel_darken(relative_luminance(client_color)) * 0.7)
|
||||||
|
)
|
||||||
|
|
||||||
|
return surface
|
||||||
|
end
|
||||||
|
|
||||||
|
local function create_edge_left(args)
|
||||||
|
local height = args.height
|
||||||
|
local width = 2
|
||||||
|
-- height = height or 1080
|
||||||
|
local surface = cairo.ImageSurface.create("ARGB32", width, height)
|
||||||
|
local cr = cairo.Context.create(surface)
|
||||||
|
cr:rectangle(0, 0, 2, args.height)
|
||||||
|
cr:set_source_rgb(hex2rgb(args.client_color))
|
||||||
|
cr:fill()
|
||||||
|
-- Inner light stroke
|
||||||
|
cr:new_sub_path()
|
||||||
|
cr:move_to(args.stroke_offset_inner, 0) -- 1/5
|
||||||
|
cr:line_to(args.stroke_offset_inner, height)
|
||||||
|
cr.line_width = args.stroke_width_inner -- 1.5
|
||||||
|
cr:set_source_rgb(hex2rgb(args.inner_stroke_color))
|
||||||
|
cr:stroke()
|
||||||
|
-- Outer dark stroke
|
||||||
|
cr:new_sub_path()
|
||||||
|
cr:move_to(args.stroke_offset_outer, 0)
|
||||||
|
cr:line_to(args.stroke_offset_outer, height)
|
||||||
|
cr.line_width = args.stroke_width_outer -- 1
|
||||||
|
cr:set_source_rgb(hex2rgb(args.stroke_color_outer))
|
||||||
|
cr:stroke()
|
||||||
|
|
||||||
|
return surface
|
||||||
|
end
|
||||||
|
|
||||||
|
local function set_font(cr, font)
|
||||||
|
cr:set_font_size(font.size)
|
||||||
|
cr:select_font_face(font.font or "Inter", font.italic and 1 or 0, font.bold and 1 or 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function text_label(args)
|
||||||
|
local surface = cairo.ImageSurface.create("ARGB32", 1, 1)
|
||||||
|
local cr = cairo.Context.create(surface)
|
||||||
|
set_font(cr, args.font)
|
||||||
|
local text = args.text
|
||||||
|
local kern = args.font.kerning or 0
|
||||||
|
local ext = cr:text_extents(text)
|
||||||
|
surface = cairo.ImageSurface.create("ARGB32", ext.width + string.len(text) * kern, ext.height)
|
||||||
|
cr = cairo.Context.create(surface)
|
||||||
|
set_font(cr, args.font)
|
||||||
|
cr:move_to(0, ext.height)
|
||||||
|
cr:set_source_rgb(hex2rgb(args.color))
|
||||||
|
-- cr:show_text(text)
|
||||||
|
text:gsub(".", function(c)
|
||||||
|
-- do something with c
|
||||||
|
cr:show_text(c)
|
||||||
|
cr:rel_move_to(kern, 0)
|
||||||
|
end)
|
||||||
|
return surface
|
||||||
|
end
|
||||||
|
|
||||||
|
return {
|
||||||
|
rounded_rect = rounded_rect,
|
||||||
|
circle_filled = circle_filled,
|
||||||
|
duotone_gradient_vertical = duotone_gradient_vertical,
|
||||||
|
flip = flip,
|
||||||
|
create_corner_top_left = create_corner_top_left,
|
||||||
|
create_edge_top_middle = create_edge_top_middle,
|
||||||
|
create_edge_left = create_edge_left,
|
||||||
|
text_label = text_label,
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
--[[
|
||||||
|
Courtesy of: http://lua-users.org/wiki/SaveTableToFile
|
||||||
|
]]
|
||||||
|
local function exportstring(s)
|
||||||
|
return string.format("%q", s)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The Save Function
|
||||||
|
local function save(tbl, filename)
|
||||||
|
local charS, charE = " ", "\n"
|
||||||
|
local file, err = io.open(filename, "wb")
|
||||||
|
if err then
|
||||||
|
return err
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Initialize variables for save procedure
|
||||||
|
local tables, lookup = { tbl }, { [tbl] = 1 }
|
||||||
|
file:write("return {" .. charE)
|
||||||
|
|
||||||
|
for idx, t in ipairs(tables) do
|
||||||
|
file:write("-- Table: {" .. idx .. "}" .. charE)
|
||||||
|
file:write("{" .. charE)
|
||||||
|
local thandled = {}
|
||||||
|
|
||||||
|
for i, v in ipairs(t) do
|
||||||
|
thandled[i] = true
|
||||||
|
local stype = type(v)
|
||||||
|
-- only handle value
|
||||||
|
if stype == "table" then
|
||||||
|
if not lookup[v] then
|
||||||
|
table.insert(tables, v)
|
||||||
|
lookup[v] = #tables
|
||||||
|
end
|
||||||
|
file:write(charS .. "{" .. lookup[v] .. "}," .. charE)
|
||||||
|
elseif stype == "string" then
|
||||||
|
file:write(charS .. exportstring(v) .. "," .. charE)
|
||||||
|
elseif stype == "number" then
|
||||||
|
file:write(charS .. tostring(v) .. "," .. charE)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, v in pairs(t) do
|
||||||
|
-- escape handled values
|
||||||
|
if not thandled[i] then
|
||||||
|
local str = ""
|
||||||
|
local stype = type(i)
|
||||||
|
-- handle index
|
||||||
|
if stype == "table" then
|
||||||
|
if not lookup[i] then
|
||||||
|
table.insert(tables, i)
|
||||||
|
lookup[i] = #tables
|
||||||
|
end
|
||||||
|
str = charS .. "[{" .. lookup[i] .. "}]="
|
||||||
|
elseif stype == "string" then
|
||||||
|
str = charS .. "[" .. exportstring(i) .. "]="
|
||||||
|
elseif stype == "number" then
|
||||||
|
str = charS .. "[" .. tostring(i) .. "]="
|
||||||
|
end
|
||||||
|
|
||||||
|
if str ~= "" then
|
||||||
|
stype = type(v)
|
||||||
|
-- handle value
|
||||||
|
if stype == "table" then
|
||||||
|
if not lookup[v] then
|
||||||
|
table.insert(tables, v)
|
||||||
|
lookup[v] = #tables
|
||||||
|
end
|
||||||
|
file:write(str .. "{" .. lookup[v] .. "}," .. charE)
|
||||||
|
elseif stype == "string" then
|
||||||
|
file:write(str .. exportstring(v) .. "," .. charE)
|
||||||
|
elseif stype == "number" then
|
||||||
|
file:write(str .. tostring(v) .. "," .. charE)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
file:write("}," .. charE)
|
||||||
|
end
|
||||||
|
file:write "}"
|
||||||
|
file:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The Load Function
|
||||||
|
local function load(sfile)
|
||||||
|
local ftables, err = loadfile(sfile)
|
||||||
|
if err then
|
||||||
|
return nil, err
|
||||||
|
end
|
||||||
|
local tables = ftables()
|
||||||
|
for idx = 1, #tables do
|
||||||
|
local tolinki = {}
|
||||||
|
for i, v in pairs(tables[idx]) do
|
||||||
|
if type(v) == "table" then
|
||||||
|
tables[idx][i] = tables[v[1]]
|
||||||
|
end
|
||||||
|
if type(i) == "table" and tables[i[1]] then
|
||||||
|
table.insert(tolinki, { i, tables[i[1]] })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- link indices
|
||||||
|
for _, v in ipairs(tolinki) do
|
||||||
|
tables[idx][v[2]], tables[idx][v[1]] = tables[idx][v[1]], nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return tables[1]
|
||||||
|
end
|
||||||
|
|
||||||
|
return { save = save, load = load }
|
|
@ -0,0 +1,149 @@
|
||||||
|
local gsurface = require "gears.surface"
|
||||||
|
local lgi = require "lgi"
|
||||||
|
local wibox = require "wibox"
|
||||||
|
local widgets = require "awesome-wm-nice.widgets"
|
||||||
|
local wlayout_fixed = require "wibox.layout.fixed"
|
||||||
|
|
||||||
|
local gdk = lgi.require("Gdk", "3.0")
|
||||||
|
|
||||||
|
local utils = {}
|
||||||
|
|
||||||
|
function utils.rel_lighten(lum)
|
||||||
|
return lum * 90 + 10
|
||||||
|
end
|
||||||
|
|
||||||
|
function utils.rel_darken(lum)
|
||||||
|
return -(lum * 70) + 100
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns the hex color for the pixel at the given coordinates on the screen
|
||||||
|
function utils.get_pixel_at(x, y)
|
||||||
|
local pixbuf = gdk.pixbuf_get_from_window(gdk.get_default_root_window(), x, y, 1, 1)
|
||||||
|
local bytes = pixbuf:get_pixels()
|
||||||
|
return "#" .. bytes:gsub(".", function(c)
|
||||||
|
return ("%02x"):format(c:byte())
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Determines the dominant color of the client's top region
|
||||||
|
function utils.get_dominant_color(client)
|
||||||
|
local color
|
||||||
|
-- gsurface(client.content):write_to_png(
|
||||||
|
-- "/home/mutex/nice/" .. client.class .. "_" .. client.instance .. ".png")
|
||||||
|
local pb
|
||||||
|
local bytes
|
||||||
|
local tally = {}
|
||||||
|
local content = gsurface(client.content)
|
||||||
|
local cgeo = client:geometry()
|
||||||
|
local x_offset = 2
|
||||||
|
local y_offset = 2
|
||||||
|
local x_lim = math.floor(cgeo.width / 2)
|
||||||
|
for x_pos = 0, x_lim, 2 do
|
||||||
|
for y_pos = 0, 8, 1 do
|
||||||
|
pb = gdk.pixbuf_get_from_surface(content, x_offset + x_pos, y_offset + y_pos, 1, 1)
|
||||||
|
bytes = pb:get_pixels()
|
||||||
|
color = "#" .. bytes:gsub(".", function(c)
|
||||||
|
return ("%02x"):format(c:byte())
|
||||||
|
end)
|
||||||
|
if not tally[color] then
|
||||||
|
tally[color] = 1
|
||||||
|
else
|
||||||
|
tally[color] = tally[color] + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local mode
|
||||||
|
local mode_c = 0
|
||||||
|
for kolor, kount in pairs(tally) do
|
||||||
|
if kount > mode_c then
|
||||||
|
mode_c = kount
|
||||||
|
mode = kolor
|
||||||
|
end
|
||||||
|
end
|
||||||
|
color = mode
|
||||||
|
return color
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns a titlebar item
|
||||||
|
function utils.get_titlebar_item(c, name)
|
||||||
|
if name == "close" then
|
||||||
|
return widgets.create_titlebar_button(c, name, function()
|
||||||
|
c:kill()
|
||||||
|
end)
|
||||||
|
elseif name == "maximize" then
|
||||||
|
return widgets.create_titlebar_button(c, name, function()
|
||||||
|
c.maximized = not c.maximized
|
||||||
|
end, "maximized")
|
||||||
|
elseif name == "minimize" then
|
||||||
|
return widgets.create_titlebar_button(c, name, function()
|
||||||
|
c.minimized = true
|
||||||
|
end)
|
||||||
|
elseif name == "ontop" then
|
||||||
|
return widgets.create_titlebar_button(c, name, function()
|
||||||
|
c.ontop = not c.ontop
|
||||||
|
end, "ontop")
|
||||||
|
elseif name == "floating" then
|
||||||
|
return widgets.create_titlebar_button(c, name, function()
|
||||||
|
c.floating = not c.floating
|
||||||
|
if c.floating then
|
||||||
|
c.maximized = false
|
||||||
|
end
|
||||||
|
end, "floating")
|
||||||
|
elseif name == "sticky" then
|
||||||
|
return widgets.create_titlebar_button(c, name, function()
|
||||||
|
c.sticky = not c.sticky
|
||||||
|
return c.sticky
|
||||||
|
end, "sticky")
|
||||||
|
elseif name == "title" then
|
||||||
|
return widgets.create_titlebar_title(c)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Creates titlebar items for a given group of item names
|
||||||
|
-- group can be a string (=item name) or a table (= array of "item-name"s)
|
||||||
|
function utils.create_titlebar_items(c, group)
|
||||||
|
if not group then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
if type(group) == "string" then
|
||||||
|
return utils.get_titlebar_item(c, group)
|
||||||
|
end
|
||||||
|
local titlebar_group_items = wibox.widget {
|
||||||
|
layout = wlayout_fixed.horizontal,
|
||||||
|
}
|
||||||
|
local item
|
||||||
|
for _, name in ipairs(group) do
|
||||||
|
item = utils.get_titlebar_item(c, name)
|
||||||
|
if item then
|
||||||
|
titlebar_group_items:add(item)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return titlebar_group_items
|
||||||
|
end
|
||||||
|
|
||||||
|
function utils.validate_mb_bindings(private)
|
||||||
|
local action_mbs = {
|
||||||
|
"mb_move",
|
||||||
|
"mb_contextmenu",
|
||||||
|
"mb_resize",
|
||||||
|
"mb_win_shade_rollup",
|
||||||
|
"mb_win_shade_rolldown",
|
||||||
|
}
|
||||||
|
local mb_specified = { false, false, false, false, false }
|
||||||
|
local mb
|
||||||
|
local mb_conflict_test
|
||||||
|
for _, action_mb in ipairs(action_mbs) do
|
||||||
|
mb = private[action_mb]
|
||||||
|
if mb then
|
||||||
|
assert(mb >= 1 and mb <= 5, "Invalid mouse button specified!")
|
||||||
|
mb_conflict_test = mb_specified[mb]
|
||||||
|
if not mb_conflict_test then
|
||||||
|
mb_specified[mb] = action_mb
|
||||||
|
else
|
||||||
|
error(("%s and %s can not be bound to the same mouse button"):format(action_mb, mb_conflict_test))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return utils
|
|
@ -0,0 +1,201 @@
|
||||||
|
local abutton = require "awful.button"
|
||||||
|
local atooltip = require "awful.tooltip"
|
||||||
|
local colors = require "awesome-wm-nice.colors"
|
||||||
|
local config = require "awesome-wm-nice.config"
|
||||||
|
local get_font_height = require("beautiful").get_font_height
|
||||||
|
local imagebox = require "wibox.widget.imagebox"
|
||||||
|
local shapes = require "awesome-wm-nice.shapes"
|
||||||
|
local textbox = require "wibox.widget.textbox"
|
||||||
|
local wcontainer_constraint = require "wibox.container.constraint"
|
||||||
|
local wcontainer_margin = require "wibox.container.margin"
|
||||||
|
local wcontainer_place = require "wibox.container.place"
|
||||||
|
local wibox = require "wibox"
|
||||||
|
|
||||||
|
local widgets = {}
|
||||||
|
local cache = {}
|
||||||
|
|
||||||
|
-- Legacy global variables
|
||||||
|
local title_color_dark = "#242424"
|
||||||
|
local title_color_light = "#fefefa"
|
||||||
|
local title_unfocused_opacity = 0.7
|
||||||
|
|
||||||
|
-- Returns a color that is analogous to the last color returned
|
||||||
|
-- To make sure that the "randomly" generated colors look cohesive, only the
|
||||||
|
-- first color is truly random, the rest are generated by offseting the hue by
|
||||||
|
-- +33 degrees
|
||||||
|
local next_color = colors.rand_hex()
|
||||||
|
local function get_next_color()
|
||||||
|
local prev_color = next_color
|
||||||
|
next_color = colors.rotate_hue(prev_color, 33)
|
||||||
|
return prev_color
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns (or generates) a button image based on the given params
|
||||||
|
function widgets.create_button_image(name, is_focused, event, is_on)
|
||||||
|
local focus_state = is_focused and "focused" or "unfocused"
|
||||||
|
local key_img
|
||||||
|
-- If it is a toggle button, then the key has an extra param
|
||||||
|
if is_on ~= nil then
|
||||||
|
local toggle_state = is_on and "on" or "off"
|
||||||
|
key_img = ("%s_%s_%s_%s"):format(name, toggle_state, focus_state, event)
|
||||||
|
else
|
||||||
|
key_img = ("%s_%s_%s"):format(name, focus_state, event)
|
||||||
|
end
|
||||||
|
-- If an image already exists, then we are done
|
||||||
|
if cache[key_img] then
|
||||||
|
return cache[key_img]
|
||||||
|
end
|
||||||
|
-- The color key just has _color at the end
|
||||||
|
local key_color = key_img .. "_color"
|
||||||
|
-- If the user hasn't provided a color, then we have to generate one
|
||||||
|
if not cache[key_color] then
|
||||||
|
local key_base_color = name .. "_color"
|
||||||
|
-- Maybe the user has at least provided a base color? If not we just pick a pesudo-random color
|
||||||
|
local base_color = config[key_base_color] or get_next_color()
|
||||||
|
cache[key_base_color] = base_color
|
||||||
|
local button_color = base_color
|
||||||
|
local H = colors.hex2hsv(base_color)
|
||||||
|
-- Unfocused buttons are desaturated and darkened (except when they are being hovered over)
|
||||||
|
if not is_focused and event ~= "hover" then
|
||||||
|
button_color = colors.hsv2hex(H, 0, 50)
|
||||||
|
end
|
||||||
|
-- Then the color is lightened if the button is being hovered over, or
|
||||||
|
-- darkened if it is being pressed, otherwise it is left as is
|
||||||
|
button_color = (event == "hover") and colors.lighten(button_color, 25)
|
||||||
|
or (event == "press") and colors.darken(button_color, 25)
|
||||||
|
or button_color
|
||||||
|
-- Save the generate color because why not lol
|
||||||
|
cache[key_color] = button_color
|
||||||
|
end
|
||||||
|
local button_size = config.button_size
|
||||||
|
-- If it is a toggle button, we create an outline instead of a filled shape if it is in off state
|
||||||
|
-- config[key_img] = (is_on ~= nil and is_on == false) and
|
||||||
|
-- shapes.circle_outline(
|
||||||
|
-- config[key_color], button_size,
|
||||||
|
-- config.button_border_width) or
|
||||||
|
-- shapes.circle_filled(
|
||||||
|
-- config[key_color], button_size)
|
||||||
|
cache[key_img] = shapes.circle_filled(cache[key_color], button_size)
|
||||||
|
return cache[key_img]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Creates a titlebar button widget
|
||||||
|
function widgets.create_titlebar_button(c, name, button_callback, property)
|
||||||
|
local button_img = imagebox(nil, false)
|
||||||
|
if config.tooltips_enabled then
|
||||||
|
local tooltip = atooltip {
|
||||||
|
timer_function = function()
|
||||||
|
local prop = name .. (property and (c[property] and "_active" or "_inactive") or "")
|
||||||
|
return config.tooltip_messages[prop]
|
||||||
|
end,
|
||||||
|
delay_show = 0.5,
|
||||||
|
margins_leftright = 12,
|
||||||
|
margins_topbottom = 6,
|
||||||
|
timeout = 0.25,
|
||||||
|
align = "bottom_right",
|
||||||
|
}
|
||||||
|
tooltip:add_to_object(button_img)
|
||||||
|
end
|
||||||
|
local is_on, is_focused
|
||||||
|
local event = "normal"
|
||||||
|
local function update()
|
||||||
|
is_focused = c.active
|
||||||
|
-- If the button is for a property that can be toggled
|
||||||
|
if property then
|
||||||
|
is_on = c[property]
|
||||||
|
button_img.image = widgets.create_button_image(name, is_focused, event, is_on)
|
||||||
|
else
|
||||||
|
button_img.image = widgets.create_button_image(name, is_focused, event)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- Update the button when the client gains/loses focus
|
||||||
|
c:connect_signal("unfocus", update)
|
||||||
|
c:connect_signal("focus", update)
|
||||||
|
-- If the button is for a property that can be toggled, update it accordingly
|
||||||
|
if property then
|
||||||
|
c:connect_signal("property::" .. property, update)
|
||||||
|
end
|
||||||
|
-- Update the button on mouse hover/leave
|
||||||
|
button_img:connect_signal("mouse::enter", function()
|
||||||
|
event = "hover"
|
||||||
|
update()
|
||||||
|
end)
|
||||||
|
button_img:connect_signal("mouse::leave", function()
|
||||||
|
event = "normal"
|
||||||
|
update()
|
||||||
|
end)
|
||||||
|
-- The button is updated on both click and release, but the call back is executed on release
|
||||||
|
button_img.buttons = abutton({}, abutton.names.LEFT, function()
|
||||||
|
event = "press"
|
||||||
|
update()
|
||||||
|
end, function()
|
||||||
|
if button_callback then
|
||||||
|
event = "normal"
|
||||||
|
button_callback()
|
||||||
|
else
|
||||||
|
event = "hover"
|
||||||
|
end
|
||||||
|
update()
|
||||||
|
end)
|
||||||
|
button_img.id = "button_image"
|
||||||
|
update()
|
||||||
|
return wibox.widget {
|
||||||
|
widget = wcontainer_place,
|
||||||
|
{
|
||||||
|
widget = wcontainer_margin,
|
||||||
|
top = config.button_margin_top or config.button_margin_vertical or config.button_margin,
|
||||||
|
bottom = config.button_margin_bottom or config.button_margin_vertical or config.button_margin,
|
||||||
|
left = config.button_margin_left or config.button_margin_horizontal or config.button_margin,
|
||||||
|
right = config.button_margin_right or config.button_margin_horizontal or config.button_margin,
|
||||||
|
{
|
||||||
|
button_img,
|
||||||
|
widget = wcontainer_constraint,
|
||||||
|
height = config.button_size,
|
||||||
|
width = config.button_size,
|
||||||
|
strategy = "exact",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Returns a titlebar widget for the given client
|
||||||
|
function widgets.create_titlebar_title(c)
|
||||||
|
local client_color = c._nice_base_color
|
||||||
|
|
||||||
|
local title_widget = wibox.widget {
|
||||||
|
align = "center",
|
||||||
|
ellipsize = "middle",
|
||||||
|
opacity = c.active and 1 or title_unfocused_opacity,
|
||||||
|
valign = "center",
|
||||||
|
widget = textbox,
|
||||||
|
}
|
||||||
|
|
||||||
|
local function update()
|
||||||
|
local text_color = colors.is_contrast_acceptable(title_color_light, client_color) and title_color_light
|
||||||
|
or title_color_dark
|
||||||
|
title_widget.markup = ("<span foreground='%s' font='%s'>%s</span>"):format(
|
||||||
|
text_color,
|
||||||
|
config.titlebar_font,
|
||||||
|
c.name
|
||||||
|
)
|
||||||
|
end
|
||||||
|
c:connect_signal("property::name", update)
|
||||||
|
c:connect_signal("unfocus", function()
|
||||||
|
title_widget.opacity = title_unfocused_opacity
|
||||||
|
end)
|
||||||
|
c:connect_signal("focus", function()
|
||||||
|
title_widget.opacity = 1
|
||||||
|
end)
|
||||||
|
update()
|
||||||
|
local titlebar_font_height = get_font_height(config.titlebar_font)
|
||||||
|
local leftover_space = config.titlebar_height - titlebar_font_height
|
||||||
|
local margin_vertical = leftover_space > 1 and leftover_space / 2 or 0
|
||||||
|
return {
|
||||||
|
title_widget,
|
||||||
|
widget = wcontainer_margin,
|
||||||
|
top = margin_vertical,
|
||||||
|
bottom = margin_vertical,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
return widgets
|
|
@ -7,15 +7,15 @@ applications.browser = "firefox-nightly"
|
||||||
applications.web = "qutebrowser"
|
applications.web = "qutebrowser"
|
||||||
|
|
||||||
applications.open_terminal = function()
|
applications.open_terminal = function()
|
||||||
return applications.terminal .. " -e tmux"
|
return applications.terminal .. " -e tmux"
|
||||||
end
|
end
|
||||||
|
|
||||||
applications.open_editor = function(file)
|
applications.open_editor = function(file)
|
||||||
return applications.terminal .. " -e " .. applications.editor .. " " .. file
|
return applications.terminal .. " -e " .. applications.editor .. " " .. file
|
||||||
end
|
end
|
||||||
|
|
||||||
applications.open_man = function(file)
|
applications.open_man = function(file)
|
||||||
return applications.terminal .. " -e man " .. file
|
return applications.terminal .. " -e man " .. file
|
||||||
end
|
end
|
||||||
|
|
||||||
return applications
|
return applications
|
|
@ -0,0 +1,113 @@
|
||||||
|
local aclient = require "awful.client"
|
||||||
|
local akey = require "awful.key"
|
||||||
|
|
||||||
|
local utils = require "awesomerc.configuration.bindings.utils"
|
||||||
|
|
||||||
|
local client_keybindings = {
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "f",
|
||||||
|
description = "toggle fullscreen",
|
||||||
|
group = utils.groups.client,
|
||||||
|
on_press = function(client)
|
||||||
|
client.fullscreen = not client.fullscreen
|
||||||
|
client:raise()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "c",
|
||||||
|
description = "close",
|
||||||
|
group = utils.groups.client,
|
||||||
|
on_press = function(client)
|
||||||
|
client:kill()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.control },
|
||||||
|
key = "space",
|
||||||
|
description = "toggle floating",
|
||||||
|
group = utils.groups.client,
|
||||||
|
on_press = aclient.floating.toggle,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.control },
|
||||||
|
key = "Return",
|
||||||
|
description = "move to master",
|
||||||
|
group = utils.groups.client,
|
||||||
|
on_press = function(client)
|
||||||
|
client:swap(aclient.getmaster())
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "o",
|
||||||
|
description = "move to screen",
|
||||||
|
group = utils.groups.client,
|
||||||
|
on_press = function(client)
|
||||||
|
client:move_to_screen()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "t",
|
||||||
|
description = "toggle keep on top",
|
||||||
|
group = utils.groups.client,
|
||||||
|
on_press = function(client)
|
||||||
|
client.ontop = not client.ontop
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "n",
|
||||||
|
description = "minimize",
|
||||||
|
group = utils.groups.client,
|
||||||
|
on_press = function(client)
|
||||||
|
-- The client currently has the input focus, so it cannot be
|
||||||
|
-- minimized, since minimized clients can't have the focus.
|
||||||
|
client.minimized = true
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "m",
|
||||||
|
description = "(un)maximize",
|
||||||
|
group = utils.groups.client,
|
||||||
|
on_press = function(client)
|
||||||
|
client.maximized = not client.maximized
|
||||||
|
client:raise()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.control },
|
||||||
|
key = "m",
|
||||||
|
description = "(un)maximize vertically",
|
||||||
|
group = utils.groups.client,
|
||||||
|
on_press = function(client)
|
||||||
|
client.maximized_vertical = not client.maximized_vertical
|
||||||
|
client:raise()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.shift },
|
||||||
|
key = "m",
|
||||||
|
description = "(un)maximize horizontally",
|
||||||
|
group = utils.groups.client,
|
||||||
|
on_press = function(client)
|
||||||
|
client.maximized_horizontal = not client.maximized_horizontal
|
||||||
|
client:raise()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return client_keybindings
|
|
@ -0,0 +1,39 @@
|
||||||
|
local abutton = require "awful.button"
|
||||||
|
|
||||||
|
local utils = require "awesomerc.configuration.bindings.utils"
|
||||||
|
|
||||||
|
local mousebindings = {
|
||||||
|
abutton {
|
||||||
|
modifiers = {},
|
||||||
|
button = abutton.names.LEFT,
|
||||||
|
on_press = function(client)
|
||||||
|
client:activate {
|
||||||
|
context = "mouse_click",
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
abutton {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
button = abutton.names.LEFT,
|
||||||
|
on_press = function(client)
|
||||||
|
client:activate {
|
||||||
|
context = "mouse_click",
|
||||||
|
action = "mouse_move",
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
abutton {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
button = abutton.names.RIGHT,
|
||||||
|
on_press = function(client)
|
||||||
|
client:activate {
|
||||||
|
context = "mouse_click",
|
||||||
|
action = "mouse_resize",
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return mousebindings
|
|
@ -0,0 +1,223 @@
|
||||||
|
local aclient = require "awful.client"
|
||||||
|
local akey = require "awful.key"
|
||||||
|
local aprompt = require "awful.prompt"
|
||||||
|
local ascreen = require "awful.screen"
|
||||||
|
local aspawn = require "awful.spawn"
|
||||||
|
local atag = require "awful.tag"
|
||||||
|
local autil = require "awful.util"
|
||||||
|
|
||||||
|
local menubar = require "menubar"
|
||||||
|
|
||||||
|
local applications = require "awesomerc.configuration.applications"
|
||||||
|
local desktop_bar = require "awesomerc.ui.desktop_decoration.bar"
|
||||||
|
local hotkeys_popup = require "awesomerc.ui.hotkeys_popup"
|
||||||
|
local mymainmenu = require "awesomerc.ui.menu.mymainmenu"
|
||||||
|
|
||||||
|
local utils = require "awesomerc.configuration.bindings.utils"
|
||||||
|
|
||||||
|
local capi = {
|
||||||
|
awesome = _G.awesome,
|
||||||
|
client = _G.client,
|
||||||
|
}
|
||||||
|
|
||||||
|
local global_keybindings = {
|
||||||
|
|
||||||
|
-- Awesome
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "s",
|
||||||
|
description = "show help",
|
||||||
|
group = utils.groups.awesome,
|
||||||
|
on_press = function()
|
||||||
|
hotkeys_popup.show_help()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "w",
|
||||||
|
description = "show main menu",
|
||||||
|
group = utils.groups.awesome,
|
||||||
|
on_press = function()
|
||||||
|
mymainmenu():show()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.control },
|
||||||
|
key = "r",
|
||||||
|
description = "reload awesome",
|
||||||
|
group = utils.groups.awesome,
|
||||||
|
on_press = capi.awesome.restart,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.shift },
|
||||||
|
key = "q",
|
||||||
|
description = "quit awesome",
|
||||||
|
group = utils.groups.awesome,
|
||||||
|
on_press = capi.awesome.quit,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "x",
|
||||||
|
description = "lua execute prompt",
|
||||||
|
group = utils.groups.awesome,
|
||||||
|
on_press = function()
|
||||||
|
aprompt.run {
|
||||||
|
prompt = "Run Lua code: ",
|
||||||
|
textbox = desktop_bar(ascreen.focused()).promptbox.widget,
|
||||||
|
exe_callback = autil.eval,
|
||||||
|
history_path = autil.get_cache_dir() .. "/history_eval",
|
||||||
|
}
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Launcher
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "Return",
|
||||||
|
description = "open a terminal",
|
||||||
|
group = utils.groups.launcher,
|
||||||
|
on_press = function()
|
||||||
|
aspawn(applications.open_terminal())
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "r",
|
||||||
|
description = "run prompt",
|
||||||
|
group = utils.groups.launcher,
|
||||||
|
on_press = function()
|
||||||
|
desktop_bar(ascreen.focused()).promptbox:run()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "p",
|
||||||
|
description = "show the menubar",
|
||||||
|
group = utils.groups.launcher,
|
||||||
|
on_press = function()
|
||||||
|
menubar.show()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Client focus
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "j",
|
||||||
|
group = "client",
|
||||||
|
description = "Focus next client by index",
|
||||||
|
on_press = function()
|
||||||
|
aclient.focus.byidx(1)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
key = "k",
|
||||||
|
group = "client",
|
||||||
|
description = "Focus previous by index",
|
||||||
|
on_press = function()
|
||||||
|
aclient.focus.byidx(-1)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Layout manipulation
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.shift },
|
||||||
|
key = "j",
|
||||||
|
group = "client",
|
||||||
|
description = "Swap with next client",
|
||||||
|
on_press = function()
|
||||||
|
aclient.swap.byidx(1)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.shift },
|
||||||
|
key = "k",
|
||||||
|
group = "client",
|
||||||
|
description = "Swap with previous client",
|
||||||
|
on_press = function()
|
||||||
|
aclient.swap.byidx(-1)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.shift },
|
||||||
|
key = "Right",
|
||||||
|
description = "Increase master width factor",
|
||||||
|
group = "client",
|
||||||
|
on_press = function()
|
||||||
|
atag.incmwfact(0.01)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.shift },
|
||||||
|
key = "Left",
|
||||||
|
description = "Decrease master width factor",
|
||||||
|
group = "client",
|
||||||
|
on_press = function()
|
||||||
|
atag.incmwfact(-0.01)
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
-- Tags manipulation
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey },
|
||||||
|
keygroup = akey.keygroup.NUMROW,
|
||||||
|
description = "only view tag",
|
||||||
|
group = "tag",
|
||||||
|
on_press = function(index)
|
||||||
|
local screen = ascreen.focused()
|
||||||
|
local tag = screen.tags[index]
|
||||||
|
|
||||||
|
if tag then
|
||||||
|
tag:view_only()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.control },
|
||||||
|
keygroup = akey.keygroup.NUMROW,
|
||||||
|
description = "toggle tag",
|
||||||
|
group = "tag",
|
||||||
|
on_press = function(index)
|
||||||
|
local screen = ascreen.focused()
|
||||||
|
local tag = screen.tags[index]
|
||||||
|
|
||||||
|
if tag then
|
||||||
|
atag.viewtoggle(tag)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
akey {
|
||||||
|
modifiers = { utils.mods.modkey, utils.mods.shift },
|
||||||
|
keygroup = akey.keygroup.NUMROW,
|
||||||
|
description = "move focused client to tag",
|
||||||
|
group = "tag",
|
||||||
|
on_press = function(index)
|
||||||
|
local screen = ascreen.focused()
|
||||||
|
local client = capi.client.focus
|
||||||
|
local tag = screen.tags[index]
|
||||||
|
|
||||||
|
if client and tag then
|
||||||
|
client:move_to_tag(tag)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return global_keybindings
|
|
@ -0,0 +1,28 @@
|
||||||
|
local abutton = require "awful.button"
|
||||||
|
local atag = require "awful.tag"
|
||||||
|
|
||||||
|
local mymainmenu = require "awesomerc.ui.menu.mymainmenu"
|
||||||
|
|
||||||
|
local global_mousebindings = {
|
||||||
|
abutton {
|
||||||
|
modifiers = {},
|
||||||
|
button = abutton.names.RIGHT,
|
||||||
|
on_press = function()
|
||||||
|
mymainmenu():toggle()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
|
||||||
|
abutton {
|
||||||
|
modifiers = {},
|
||||||
|
button = abutton.names.SCROLL_UP,
|
||||||
|
on_press = tag.viewprev,
|
||||||
|
},
|
||||||
|
|
||||||
|
abutton {
|
||||||
|
modifiers = {},
|
||||||
|
button = abutton.names.SCROLL_DOWN,
|
||||||
|
on_press = atag.viewnext,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return global_mousebindings
|
|
@ -0,0 +1,9 @@
|
||||||
|
local bindings = {}
|
||||||
|
|
||||||
|
bindings.client_keybindings = require "awesomerc.configuration.bindings.client_keybindings"
|
||||||
|
bindings.client_mousebindings = require "awesomerc.configuration.bindings.client_mousebindings"
|
||||||
|
bindings.global_keybindings = require "awesomerc.configuration.bindings.global_keybindings"
|
||||||
|
bindings.global_mousebindings = require "awesomerc.configuration.bindings.global_mousebindings"
|
||||||
|
bindings.utils = require "awesomerc.configuration.bindings.utils"
|
||||||
|
|
||||||
|
return bindings
|
|
@ -0,0 +1,16 @@
|
||||||
|
local mods = {
|
||||||
|
control = "Control",
|
||||||
|
modkey = "Mod4",
|
||||||
|
shift = "Shift",
|
||||||
|
}
|
||||||
|
|
||||||
|
local groups = {
|
||||||
|
client = "client",
|
||||||
|
awesome = "awesome",
|
||||||
|
launcher = "launcher",
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
mods = mods,
|
||||||
|
groups = groups,
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
local rc_configuration = {}
|
||||||
|
|
||||||
|
rc_configuration.applications = require "awesomerc.configuration.applications"
|
||||||
|
rc_configuration.bindings = require "awesomerc.configuration.bindings"
|
||||||
|
rc_configuration.menu = require "awesomerc.configuration.menu"
|
||||||
|
rc_configuration.rules = require "awesomerc.configuration.rules"
|
||||||
|
rc_configuration.prompt_commands = require "awesomerc.configuration.prompt_commands"
|
||||||
|
rc_configuration.tag_layouts = require "awesomerc.configuration.tag_layouts"
|
||||||
|
|
||||||
|
return rc_configuration
|
|
@ -0,0 +1,6 @@
|
||||||
|
local configuration_menu = {}
|
||||||
|
|
||||||
|
configuration_menu.myawesomemenu = require "awesomerc.configuration.menu.myawesomemenu"
|
||||||
|
configuration_menu.mymainmenu = require "awesomerc.configuration.menu.mymainmenu"
|
||||||
|
|
||||||
|
return configuration_menu
|
|
@ -0,0 +1,31 @@
|
||||||
|
local applications = require "awesomerc.configuration.applications"
|
||||||
|
local hotkeys_popup = require "awesomerc.ui.hotkeys_popup"
|
||||||
|
|
||||||
|
local capi = {
|
||||||
|
awesome = _G.awesome,
|
||||||
|
}
|
||||||
|
|
||||||
|
local myawesomemenu = {
|
||||||
|
{
|
||||||
|
"hotkeys",
|
||||||
|
function()
|
||||||
|
hotkeys_popup.show_help()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
{ "manual", applications.open_man "awesome" },
|
||||||
|
{ "edit config", applications.open_editor(capi.awesome.conffile) },
|
||||||
|
{
|
||||||
|
"restart",
|
||||||
|
function()
|
||||||
|
capi.awesome.restart()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"quit",
|
||||||
|
function()
|
||||||
|
capi.awesome.quit()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return myawesomemenu
|
|
@ -0,0 +1,11 @@
|
||||||
|
local beautiful = require "beautiful"
|
||||||
|
|
||||||
|
local applications = require "awesomerc.configuration.applications"
|
||||||
|
local myawesomemenu = require "awesomerc.configuration.menu.myawesomemenu"
|
||||||
|
|
||||||
|
local mymainmenu = {
|
||||||
|
{ "awesome", myawesomemenu, beautiful.awesome_icon },
|
||||||
|
{ "open terminal", applications.terminal },
|
||||||
|
}
|
||||||
|
|
||||||
|
return mymainmenu
|
|
@ -0,0 +1,52 @@
|
||||||
|
local atag = require "awful.tag"
|
||||||
|
local layout_suit = require "awful.layout.suit"
|
||||||
|
|
||||||
|
local commands = {}
|
||||||
|
|
||||||
|
commands["o"] = {
|
||||||
|
callback = function(parameters)
|
||||||
|
local tag_name = parameters[1] or "New-Tag"
|
||||||
|
|
||||||
|
atag
|
||||||
|
.add(tag_name, {
|
||||||
|
layout = layout_suit.tile,
|
||||||
|
})
|
||||||
|
:view_only()
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
commands["O"] = {
|
||||||
|
callback = function(parameters)
|
||||||
|
local aspawn = require "awful.spawn"
|
||||||
|
|
||||||
|
local application = parameters[1]
|
||||||
|
local tag_name = parameters[2] or application
|
||||||
|
|
||||||
|
local t = atag.add(tag_name, {
|
||||||
|
layout = layout_suit.tile,
|
||||||
|
volatile = true,
|
||||||
|
})
|
||||||
|
t:view_only()
|
||||||
|
aspawn(application, { tag = t })
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
commands["q"] = {
|
||||||
|
callback = function()
|
||||||
|
local ascreen = require "awful.screen"
|
||||||
|
|
||||||
|
local tags = ascreen.focused().selected_tags
|
||||||
|
|
||||||
|
for _, tag in ipairs(tags) do
|
||||||
|
tag.volatile = true
|
||||||
|
|
||||||
|
for _, client in ipairs(tag:clients()) do
|
||||||
|
client:kill()
|
||||||
|
end
|
||||||
|
|
||||||
|
tag:delete()
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
return commands
|
|
@ -0,0 +1,7 @@
|
||||||
|
local firefox_rule = {
|
||||||
|
id = "firefox",
|
||||||
|
rule = { class = "Firefox" },
|
||||||
|
properties = { screen = 1, tag = "2" },
|
||||||
|
}
|
||||||
|
|
||||||
|
return firefox_rule
|
|
@ -0,0 +1,28 @@
|
||||||
|
local floating_rule = {
|
||||||
|
id = "floating",
|
||||||
|
rule_any = {
|
||||||
|
instance = { "copyq", "pinentry" },
|
||||||
|
class = {
|
||||||
|
"Arandr",
|
||||||
|
"Blueman-manager",
|
||||||
|
"Gpick",
|
||||||
|
"Kruler",
|
||||||
|
"Sxiv",
|
||||||
|
"Tor Browser",
|
||||||
|
"Wpa_gui",
|
||||||
|
"veromix",
|
||||||
|
"xtightvncviewer",
|
||||||
|
},
|
||||||
|
name = {
|
||||||
|
"Event Tester", -- xev.
|
||||||
|
},
|
||||||
|
role = {
|
||||||
|
"AlarmWindow", -- Thunderbird's calendar.
|
||||||
|
"ConfigManager", -- Thunderbird's about:config.
|
||||||
|
"pop-up", -- e.g. Google Chrome's (detached) Developer Tools.
|
||||||
|
},
|
||||||
|
},
|
||||||
|
properties = { floating = true },
|
||||||
|
}
|
||||||
|
|
||||||
|
return floating_rule
|
|
@ -0,0 +1,16 @@
|
||||||
|
local aclient = require "awful.client"
|
||||||
|
local aplacement = require "awful.placement"
|
||||||
|
local ascreen = require "awful.screen"
|
||||||
|
|
||||||
|
local global_rule = {
|
||||||
|
id = "global",
|
||||||
|
rule = {},
|
||||||
|
properties = {
|
||||||
|
focus = aclient.focus.filter,
|
||||||
|
raise = true,
|
||||||
|
screen = ascreen.preferred,
|
||||||
|
placement = aplacement.no_overlap + aplacement.no_offscreen,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return global_rule
|
|
@ -0,0 +1,8 @@
|
||||||
|
local client_rules = {}
|
||||||
|
|
||||||
|
client_rules.global = require "awesomerc.configuration.rules.client.global"
|
||||||
|
client_rules.floating = require "awesomerc.configuration.rules.client.floating"
|
||||||
|
client_rules.titlebar = require "awesomerc.configuration.rules.client.titlebars"
|
||||||
|
-- client_rules.firefox = require 'awesomerc.configuration.rules.client.firefox'
|
||||||
|
|
||||||
|
return client_rules
|
|
@ -0,0 +1,9 @@
|
||||||
|
local titlebar_rule = {
|
||||||
|
id = "titlebars",
|
||||||
|
rule_any = {
|
||||||
|
type = { "normal", "dialog" },
|
||||||
|
},
|
||||||
|
properties = { titlebars_enabled = true },
|
||||||
|
}
|
||||||
|
|
||||||
|
return titlebar_rule
|
|
@ -0,0 +1,6 @@
|
||||||
|
local rules = {}
|
||||||
|
|
||||||
|
rules.client = require "awesomerc.configuration.rules.client"
|
||||||
|
rules.notification = require "awesomerc.configuration.rules.notification"
|
||||||
|
|
||||||
|
return rules
|
|
@ -0,0 +1,11 @@
|
||||||
|
local ascreen = require "awful.screen"
|
||||||
|
|
||||||
|
local global_rule = {
|
||||||
|
rule = {},
|
||||||
|
properties = {
|
||||||
|
screen = ascreen.preferred,
|
||||||
|
implicit_timeout = 5,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return global_rule
|
|
@ -0,0 +1,5 @@
|
||||||
|
local notification_rules = {}
|
||||||
|
|
||||||
|
notification_rules.global = require "awesomerc.configuration.rules.notification.global"
|
||||||
|
|
||||||
|
return notification_rules
|
|
@ -0,0 +1,19 @@
|
||||||
|
local alayout = require "awful.layout"
|
||||||
|
|
||||||
|
local tag_layouts = {
|
||||||
|
alayout.suit.floating,
|
||||||
|
alayout.suit.tile,
|
||||||
|
alayout.suit.tile.left,
|
||||||
|
alayout.suit.tile.bottom,
|
||||||
|
alayout.suit.tile.top,
|
||||||
|
alayout.suit.fair,
|
||||||
|
alayout.suit.fair.horizontal,
|
||||||
|
alayout.suit.spiral,
|
||||||
|
alayout.suit.spiral.dwindle,
|
||||||
|
alayout.suit.max,
|
||||||
|
alayout.suit.max.fullscreen,
|
||||||
|
alayout.suit.magnifier,
|
||||||
|
alayout.suit.corner.nw,
|
||||||
|
}
|
||||||
|
|
||||||
|
return tag_layouts
|
|
@ -0,0 +1,162 @@
|
||||||
|
local gtimer = require "gears.timer" -- cspell:ignore gtimer
|
||||||
|
local legacy = require "awesome-legacy"
|
||||||
|
local naughty = require "naughty"
|
||||||
|
local ruled = require "ruled"
|
||||||
|
local slot = require "awesome-slot"
|
||||||
|
|
||||||
|
-- Load global awesome components from the C API
|
||||||
|
local capi = {
|
||||||
|
client = _G.client,
|
||||||
|
screen = _G.screen,
|
||||||
|
tag = _G.tag,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Beautiful needs to be initialized as soon as possible to make theme
|
||||||
|
-- variables available to the configuration module.
|
||||||
|
legacy.beautiful {
|
||||||
|
base = "default",
|
||||||
|
theme = require "awesomerc.theme",
|
||||||
|
}
|
||||||
|
|
||||||
|
legacy.manage_error()
|
||||||
|
legacy.autofocus()
|
||||||
|
legacy.sloppy_focus()
|
||||||
|
|
||||||
|
local configuration = require "awesomerc.configuration"
|
||||||
|
local my_slots = require "awesomerc.slots"
|
||||||
|
|
||||||
|
-- This needs to be run after awesome has completed C API initialization and
|
||||||
|
-- the `root` object is available.
|
||||||
|
gtimer.delayed_call(function()
|
||||||
|
legacy.global_mouse_bindings(configuration.bindings.global_mousebindings)
|
||||||
|
legacy.global_keybindings(configuration.bindings.global_keybindings)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable load_wallpaper
|
||||||
|
local load_wallpaper = slot {
|
||||||
|
id = "LOAD_WALLPAPER",
|
||||||
|
connect = true,
|
||||||
|
target = capi.screen,
|
||||||
|
signal = "request::wallpaper",
|
||||||
|
slot = my_slots.wallpaper,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable default_layout
|
||||||
|
local default_layout = slot {
|
||||||
|
id = "DEFAULT_LAYOUTS",
|
||||||
|
connect = true,
|
||||||
|
target = capi.tag,
|
||||||
|
signal = "request::default_layouts",
|
||||||
|
slot = slot.slots.tag.default_layouts,
|
||||||
|
slot_params = {
|
||||||
|
layouts = configuration.tag_layouts,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable create_tag
|
||||||
|
local create_tag = slot {
|
||||||
|
id = "CREATE_TAGS",
|
||||||
|
connect = true,
|
||||||
|
target = capi.screen,
|
||||||
|
signal = "request::desktop_decoration",
|
||||||
|
slot = my_slots.create_tags,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable desktop_decoration
|
||||||
|
local desktop_decoration = slot {
|
||||||
|
id = "DESKTOP_DECORATION",
|
||||||
|
connect = true,
|
||||||
|
target = capi.screen,
|
||||||
|
signal = "request::desktop_decoration",
|
||||||
|
slot = my_slots.build_desktop_decoration,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable client_mousebinding
|
||||||
|
local client_mousebinding = slot {
|
||||||
|
id = "CLIENT_MOUSE_BINDINGS",
|
||||||
|
connect = true,
|
||||||
|
target = capi.client,
|
||||||
|
signal = "request::default_mousebindings",
|
||||||
|
slot = slot.slots.client.append_mousebindings,
|
||||||
|
slot_params = {
|
||||||
|
mousebindings = configuration.bindings.client_mousebindings,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable client_keybinding
|
||||||
|
local client_keybinding = slot {
|
||||||
|
id = "CLIENT_KEY_BINDINGS",
|
||||||
|
connect = true,
|
||||||
|
target = capi.client,
|
||||||
|
signal = "request::default_keybindings",
|
||||||
|
slot = slot.slots.client.append_keybindings,
|
||||||
|
slot_params = {
|
||||||
|
keybindings = configuration.bindings.client_keybindings,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable ruled_client
|
||||||
|
local ruled_client = slot {
|
||||||
|
id = "RULED_CLIENT",
|
||||||
|
connect = true,
|
||||||
|
target = ruled.client,
|
||||||
|
signal = "request::rules",
|
||||||
|
slot = slot.slots.ruled.append_client_rules,
|
||||||
|
slot_params = {
|
||||||
|
rules = configuration.rules.client,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable client_titlebar
|
||||||
|
local client_titlebar = slot {
|
||||||
|
id = "CLIENT_TITLEBAR",
|
||||||
|
connect = true,
|
||||||
|
target = capi.client,
|
||||||
|
signal = "request::titlebars",
|
||||||
|
slot = my_slots.build_titlebars,
|
||||||
|
}
|
||||||
|
|
||||||
|
gtimer.delayed_call(function()
|
||||||
|
local nice_config = require "awesome-wm-nice.config"
|
||||||
|
local nice_utils = require "awesome-wm-nice.utils"
|
||||||
|
|
||||||
|
nice_config.init()
|
||||||
|
nice_utils.validate_mb_bindings(nice_config)
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable client_shape
|
||||||
|
local client_shape = slot {
|
||||||
|
id = "CLIENT_SHAPE",
|
||||||
|
connect = true,
|
||||||
|
target = capi.client,
|
||||||
|
signal = "request::manage",
|
||||||
|
slot = my_slots.client_shape,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable ruled_notification
|
||||||
|
local ruled_notification = slot {
|
||||||
|
id = "RULED_NOTIFICATION",
|
||||||
|
connect = true,
|
||||||
|
target = ruled.notification,
|
||||||
|
signal = "request::rules",
|
||||||
|
slot = slot.slots.ruled.append_notification_rules,
|
||||||
|
slot_params = {
|
||||||
|
rules = configuration.rules.notification,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
-- luacheck: ignore unused variable naughty_display
|
||||||
|
local naughty_display = slot {
|
||||||
|
id = "NAUGHTY_DISPLAY",
|
||||||
|
connect = true,
|
||||||
|
target = naughty,
|
||||||
|
signal = "request::display",
|
||||||
|
slot = my_slots.naughty_display,
|
||||||
|
}
|
||||||
|
|
||||||
|
gtimer.delayed_call(function()
|
||||||
|
naughty.notify {
|
||||||
|
title = "Aire-One dots",
|
||||||
|
message = "Welcome to the Aire-One rc!",
|
||||||
|
}
|
||||||
|
end)
|
|
@ -0,0 +1,86 @@
|
||||||
|
local alayout = require "awful.layout"
|
||||||
|
local atag = require "awful.tag"
|
||||||
|
local awallpaper = require "awful.wallpaper"
|
||||||
|
local beautiful = require "beautiful"
|
||||||
|
local desktop_bar = require "awesomerc.ui.desktop_decoration.bar"
|
||||||
|
local gcolor = require "gears.color"
|
||||||
|
local gsurface = require "gears.surface"
|
||||||
|
local gtimer = require "gears.timer"
|
||||||
|
local imagebox = require "wibox.widget.imagebox"
|
||||||
|
local lgi = require "lgi"
|
||||||
|
local naughty = require "naughty"
|
||||||
|
local nice_shapes = require "awesome-wm-nice.shapes"
|
||||||
|
local titlebar = require "awesomerc.ui.titlebar"
|
||||||
|
|
||||||
|
local cairo = lgi.cairo
|
||||||
|
|
||||||
|
local slots = {}
|
||||||
|
|
||||||
|
function slots.wallpaper(screen)
|
||||||
|
local screen_geo = screen.geometry
|
||||||
|
local source = cairo.ImageSurface(cairo.Format.RGB32, screen_geo.width, screen_geo.height)
|
||||||
|
local cr = cairo.Context(source)
|
||||||
|
|
||||||
|
-- Load base image
|
||||||
|
local image_surface = gsurface.load_uncached(beautiful.wallpaper)
|
||||||
|
local w, h = gsurface.get_size(image_surface)
|
||||||
|
cr:scale(screen_geo.width / w, screen_geo.height / h)
|
||||||
|
cr:set_source_surface(image_surface, 0, 0)
|
||||||
|
cr:paint()
|
||||||
|
|
||||||
|
-- Add color layer
|
||||||
|
local color_pattern = gcolor.create_linear_pattern {
|
||||||
|
from = { 0, 0 },
|
||||||
|
to = { screen.width, screen.height },
|
||||||
|
stops = {
|
||||||
|
{ 0, "#26323840" },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cr:set_source(color_pattern)
|
||||||
|
cr:paint()
|
||||||
|
|
||||||
|
awallpaper {
|
||||||
|
screen = screen,
|
||||||
|
widget = {
|
||||||
|
image = source,
|
||||||
|
widget = imagebox,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function slots.create_tags(screen)
|
||||||
|
local first_tag = atag.add("home", {
|
||||||
|
screen = screen,
|
||||||
|
layout = alayout.suit.tile,
|
||||||
|
icon = beautiful.icon_hometag,
|
||||||
|
gap = beautiful.gaps_hometag,
|
||||||
|
})
|
||||||
|
|
||||||
|
gtimer.delayed_call(function()
|
||||||
|
first_tag:view_only()
|
||||||
|
-- spawn(apps.open_terminal(), { screen = screen, tag = first_tag })
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function slots.build_desktop_decoration(screen)
|
||||||
|
desktop_bar(screen)
|
||||||
|
end
|
||||||
|
|
||||||
|
function slots.build_titlebars(client)
|
||||||
|
titlebar(client)
|
||||||
|
end
|
||||||
|
|
||||||
|
function slots.client_shape(client)
|
||||||
|
client.shape = nice_shapes.rounded_rect {
|
||||||
|
tl = beautiful.client_corner_radius_top,
|
||||||
|
tr = beautiful.client_corner_radius_top,
|
||||||
|
bl = beautiful.client_corner_radius_bottom,
|
||||||
|
br = beautiful.client_corner_radius_bottom,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
function slots.naughty_display(notification)
|
||||||
|
naughty.layout.box { notification = notification }
|
||||||
|
end
|
||||||
|
|
||||||
|
return slots
|
|
@ -1,17 +1,18 @@
|
||||||
local gfs = require "gears.filesystem"
|
local gfs = require "gears.filesystem"
|
||||||
|
|
||||||
local config_dir = gfs.get_configuration_dir()
|
local config_dir = gfs.get_configuration_dir()
|
||||||
local theme_dir = config_dir .. "theme/"
|
local assets_dir = config_dir .. "assets/"
|
||||||
local assets_dir = theme_dir .. "assets/"
|
|
||||||
local icons_dir = assets_dir .. "icons/"
|
local icons_dir = assets_dir .. "icons/"
|
||||||
|
|
||||||
local theme = {}
|
local theme = {}
|
||||||
|
|
||||||
--- Basic
|
--- Basic
|
||||||
theme.font = "Noto Mono 9"
|
theme.font = "Noto Mono 9"
|
||||||
|
theme.border_width = 0
|
||||||
|
|
||||||
--- Tags
|
--- Clients
|
||||||
theme.hometag_master_width_factor = 0.65
|
theme.client_corner_radius_top = 9
|
||||||
|
theme.client_corner_radius_bottom = 4
|
||||||
|
|
||||||
--- Icons
|
--- Icons
|
||||||
theme.icon_hometag = icons_dir .. "home-circle.svg"
|
theme.icon_hometag = icons_dir .. "home-circle.svg"
|
||||||
|
@ -32,7 +33,7 @@ theme.wibar_bg = "#0000"
|
||||||
|
|
||||||
--- Spacing and margins
|
--- Spacing and margins
|
||||||
-- Naming convention:
|
-- Naming convention:
|
||||||
-- <rc.ui.desktop_decoration element>_<widget element>_<property>
|
-- <awesomerc.ui.desktop_decoration element>_<widget element>_<property>
|
||||||
theme.spacing = 8
|
theme.spacing = 8
|
||||||
theme.margin = 4
|
theme.margin = 4
|
||||||
theme.padding = 4
|
theme.padding = 4
|
||||||
|
@ -51,11 +52,13 @@ theme.bar_box_padding_x = theme.padding * 2
|
||||||
theme.bar_box_padding_y = theme.padding
|
theme.bar_box_padding_y = theme.padding
|
||||||
theme.bar_box_spacing = theme.spacing
|
theme.bar_box_spacing = theme.spacing
|
||||||
|
|
||||||
|
theme.gaps_hometag = theme.padding
|
||||||
|
|
||||||
--- Widgets specific
|
--- Widgets specific
|
||||||
theme.bg_systray = "#455A64"
|
theme.bg_systray = "#455A64"
|
||||||
theme.systray_icon_spacing = 3
|
theme.systray_icon_spacing = 3
|
||||||
|
|
||||||
--- Wallpaper
|
--- Wallpaper
|
||||||
theme.wallpaper = assets_dir .. "wallpapers/pizza.jpg"
|
theme.wallpaper = assets_dir .. "wallpapers/poke.jpg"
|
||||||
|
|
||||||
return theme
|
return theme
|
|
@ -0,0 +1,241 @@
|
||||||
|
local awful = require "awful"
|
||||||
|
local awibar = require "awful.wibar"
|
||||||
|
local battery_widget = require "awesome-battery_widget"
|
||||||
|
local beautiful = require "beautiful"
|
||||||
|
|
||||||
|
local container_background = require "wibox.container.background"
|
||||||
|
local container_margin = require "wibox.container.margin"
|
||||||
|
local container_place = require "wibox.container.place"
|
||||||
|
|
||||||
|
local gshape = require "gears.shape"
|
||||||
|
|
||||||
|
local layout_align = require "wibox.layout.align"
|
||||||
|
local layout_fixed = require "wibox.layout.fixed"
|
||||||
|
|
||||||
|
local systray = require "wibox.widget.systray"
|
||||||
|
local textclock = require "wibox.widget.textclock"
|
||||||
|
local widget = require "wibox.widget"
|
||||||
|
|
||||||
|
local mycommands = require "awesomerc.configuration.prompt_commands"
|
||||||
|
local mymainmenu = require "awesomerc.ui.menu.mymainmenu"
|
||||||
|
local mytaglist = require "MyTagListWidget"
|
||||||
|
|
||||||
|
local bar_widgets = require "awesomerc.ui.desktop_decoration.bar.widgets"
|
||||||
|
local mybattery = bar_widgets.battery
|
||||||
|
local myprompt = bar_widgets.prompt
|
||||||
|
|
||||||
|
local capi = {
|
||||||
|
screen = _G.screen,
|
||||||
|
}
|
||||||
|
|
||||||
|
local abs = math.abs
|
||||||
|
local dpi = beautiful.xresources.apply_dpi
|
||||||
|
|
||||||
|
local function get_screen_id(screen)
|
||||||
|
local s = capi.screen[screen or 1]
|
||||||
|
|
||||||
|
return s.index
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Build a widget box in the bar.
|
||||||
|
-- A widget box is a combinaision of "shaped" `wibox.container/background` and
|
||||||
|
-- `wibox.container.margin` to create this nice round-colored-buttons I like.
|
||||||
|
-- @tparam args table
|
||||||
|
-- @tparam args.screen The screen where the widget will be drawn.
|
||||||
|
-- @tparam args.widget The widget to draw.
|
||||||
|
-- @tparam[opt] args.bg The box's background.
|
||||||
|
-- @tpram[opt] args.fg The box's foreground (used mainly for textbox text color).
|
||||||
|
-- @treturn wibox.container.background The builded widget.
|
||||||
|
local function build_widget(args)
|
||||||
|
local screen_id = get_screen_id(args.screen)
|
||||||
|
|
||||||
|
-- Callback for the shape function.
|
||||||
|
-- If the widget is almost a square: draw a circle. Otherwise, draw a
|
||||||
|
-- rounded_bar.
|
||||||
|
local shape_callback = function(cr, width, height)
|
||||||
|
local shape = gshape.circle
|
||||||
|
|
||||||
|
-- 10 is an arbitrary value I found after some tests :shrug:
|
||||||
|
if abs(width - height) > 10 then
|
||||||
|
shape = gshape.rounded_bar
|
||||||
|
end
|
||||||
|
|
||||||
|
return shape(cr, width, height)
|
||||||
|
end
|
||||||
|
|
||||||
|
local box_widget = widget {
|
||||||
|
{
|
||||||
|
widget = container_margin,
|
||||||
|
draw_empty = false,
|
||||||
|
top = dpi(beautiful.bar_box_padding_y, screen_id),
|
||||||
|
bottom = dpi(beautiful.bar_box_padding_y, screen_id),
|
||||||
|
right = dpi(beautiful.bar_box_padding_x, screen_id),
|
||||||
|
left = dpi(beautiful.bar_box_padding_x, screen_id),
|
||||||
|
args.widget,
|
||||||
|
},
|
||||||
|
bg = args.bg,
|
||||||
|
fg = args.fg,
|
||||||
|
shape = shape_callback,
|
||||||
|
widget = container_background,
|
||||||
|
}
|
||||||
|
|
||||||
|
return box_widget
|
||||||
|
end
|
||||||
|
|
||||||
|
local bar = { _private = { instances = {} }, mt = {} }
|
||||||
|
|
||||||
|
bar.widgets = bar_widgets
|
||||||
|
|
||||||
|
--- Get the bar instance for a given screen.
|
||||||
|
-- If no instance was found, we build a new one.
|
||||||
|
-- @tparam screen screen|integer The bar's screen.
|
||||||
|
-- @treturn wibox.wibar
|
||||||
|
function bar:instance(screen)
|
||||||
|
local screen_id = get_screen_id(screen)
|
||||||
|
local instance = self._private.instances[screen_id]
|
||||||
|
|
||||||
|
if not instance then
|
||||||
|
instance = bar.new(screen)
|
||||||
|
self._private.instances[screen_id] = instance
|
||||||
|
end
|
||||||
|
|
||||||
|
return instance
|
||||||
|
end
|
||||||
|
|
||||||
|
function bar.new(screen)
|
||||||
|
local my_bar = {}
|
||||||
|
|
||||||
|
my_bar.launcher = build_widget {
|
||||||
|
screen = screen,
|
||||||
|
bg = "#2196F3",
|
||||||
|
widget = awful.widget.launcher {
|
||||||
|
image = beautiful.icon_apps,
|
||||||
|
menu = mymainmenu(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bar.textclock = build_widget {
|
||||||
|
screen = screen,
|
||||||
|
bg = "#FF5722",
|
||||||
|
fg = "#ECEFF1",
|
||||||
|
widget = textclock "%l:%M %p",
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bar.promptbox = myprompt {
|
||||||
|
commands = mycommands,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- This widget needs to be reworded and integrated inside the project.
|
||||||
|
my_bar.taglist = mytaglist.new {
|
||||||
|
screen = screen,
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bar.battery = build_widget {
|
||||||
|
screen = screen,
|
||||||
|
bg = "#673AB7",
|
||||||
|
widget = mybattery {
|
||||||
|
screen = screen,
|
||||||
|
device_path = battery_widget.get_BAT0_device_path(),
|
||||||
|
color = "#ECEFF1",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bar.systray = build_widget {
|
||||||
|
screen = screen,
|
||||||
|
bg = "#455A64",
|
||||||
|
widget = systray(),
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bar.wibar = awibar {
|
||||||
|
screen = screen,
|
||||||
|
position = "bottom",
|
||||||
|
height = dpi(beautiful.bar_height, screen),
|
||||||
|
width = beautiful.bar_width, -- Width is a percentage of the screen size
|
||||||
|
}
|
||||||
|
|
||||||
|
my_bar.wibar:setup {
|
||||||
|
-- Bar margins
|
||||||
|
{
|
||||||
|
-- Physical bar
|
||||||
|
{
|
||||||
|
-- Bar paddings
|
||||||
|
{
|
||||||
|
-- Bar content
|
||||||
|
{
|
||||||
|
-- Left side of the bar, align on the left
|
||||||
|
{
|
||||||
|
-- box margins
|
||||||
|
{
|
||||||
|
-- Left widget boxes
|
||||||
|
my_bar.launcher,
|
||||||
|
my_bar.promptbox,
|
||||||
|
spacing = dpi(beautiful.bar_box_spacing, screen),
|
||||||
|
layout = layout_fixed.horizontal,
|
||||||
|
},
|
||||||
|
top = dpi(beautiful.bar_box_margin_y, screen),
|
||||||
|
bottom = dpi(beautiful.bar_box_margin_y, screen),
|
||||||
|
right = dpi(beautiful.bar_box_margin_x, screen),
|
||||||
|
left = dpi(beautiful.bar_box_margin_x, screen),
|
||||||
|
widget = container_margin,
|
||||||
|
},
|
||||||
|
halign = "left",
|
||||||
|
widget = container_place,
|
||||||
|
},
|
||||||
|
expand = "outside",
|
||||||
|
layout = layout_align.horizontal,
|
||||||
|
|
||||||
|
-- Middle widget is the custom taglist
|
||||||
|
-- it doesn't need box/margins/...
|
||||||
|
{
|
||||||
|
my_bar.taglist,
|
||||||
|
widget = container_place,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
-- Right side of the bar, align on the right
|
||||||
|
{
|
||||||
|
-- box margins
|
||||||
|
{
|
||||||
|
-- Right widget boxes
|
||||||
|
my_bar.systray,
|
||||||
|
my_bar.battery,
|
||||||
|
my_bar.textclock,
|
||||||
|
spacing = dpi(beautiful.bar_box_spacing, screen),
|
||||||
|
layout = layout_fixed.horizontal,
|
||||||
|
},
|
||||||
|
top = dpi(beautiful.bar_box_margin_y, screen),
|
||||||
|
bottom = dpi(beautiful.bar_box_margin_y, screen),
|
||||||
|
right = dpi(beautiful.bar_box_margin_x, screen),
|
||||||
|
left = dpi(beautiful.bar_box_margin_x, screen),
|
||||||
|
widget = container_margin,
|
||||||
|
},
|
||||||
|
halign = "right",
|
||||||
|
widget = container_place,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
top = dpi(beautiful.bar_padding_y, screen),
|
||||||
|
bottom = dpi(beautiful.bar_padding_y, screen),
|
||||||
|
right = dpi(beautiful.bar_padding_x, screen),
|
||||||
|
left = dpi(beautiful.bar_padding_x, screen),
|
||||||
|
widget = container_margin,
|
||||||
|
},
|
||||||
|
bg = beautiful.bar_bg,
|
||||||
|
shape = function(cr, width, height)
|
||||||
|
gshape.rounded_rect(cr, width, height, 10)
|
||||||
|
end,
|
||||||
|
widget = container_background,
|
||||||
|
},
|
||||||
|
top = dpi(beautiful.bar_margin_y, screen),
|
||||||
|
bottom = dpi(beautiful.bar_margin_y, screen),
|
||||||
|
right = dpi(beautiful.bar_margin_x, screen),
|
||||||
|
left = dpi(beautiful.bar_margin_x, screen),
|
||||||
|
widget = container_margin,
|
||||||
|
}
|
||||||
|
|
||||||
|
return my_bar
|
||||||
|
end
|
||||||
|
|
||||||
|
function bar.mt:__call(...)
|
||||||
|
return self:instance(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(bar, bar.mt)
|
|
@ -17,7 +17,7 @@ local beautiful = require "beautiful"
|
||||||
local gcolor = require "gears.color"
|
local gcolor = require "gears.color"
|
||||||
local imagebox = require "wibox.widget.imagebox"
|
local imagebox = require "wibox.widget.imagebox"
|
||||||
|
|
||||||
local battery_widget = require "battery-widget"
|
local battery_widget = require "awesome-battery_widget"
|
||||||
|
|
||||||
local my_battery = {}
|
local my_battery = {}
|
||||||
local mt = {}
|
local mt = {}
|
||||||
|
@ -27,25 +27,25 @@ local mt = {}
|
||||||
-- @tparam gears.color|string color The color of the drawing.
|
-- @tparam gears.color|string color The color of the drawing.
|
||||||
-- @treturn cairo.ImageSurface The generated surface for the drawing.
|
-- @treturn cairo.ImageSurface The generated surface for the drawing.
|
||||||
function my_battery.draw_battery(percentage, color)
|
function my_battery.draw_battery(percentage, color)
|
||||||
local svg_handle = rsvg.Handle.new_from_file(beautiful.icon_battery_outline)
|
local svg_handle = rsvg.Handle.new_from_file(beautiful.icon_battery_outline)
|
||||||
if not svg_handle then
|
if not svg_handle then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local surface = cairo.ImageSurface.create(cairo.Format.ARGB32, 24, 24)
|
local surface = cairo.ImageSurface.create(cairo.Format.ARGB32, 24, 24)
|
||||||
local cr = cairo.Context(surface)
|
local cr = cairo.Context(surface)
|
||||||
svg_handle:render_cairo(cr)
|
svg_handle:render_cairo(cr)
|
||||||
|
|
||||||
local max_height = 14
|
local max_height = 14
|
||||||
local x = 8
|
local x = 8
|
||||||
local width = 8
|
local width = 8
|
||||||
local height = percentage / 100 * max_height
|
local height = percentage / 100 * max_height
|
||||||
local y = 6 + max_height - height
|
local y = 6 + max_height - height
|
||||||
|
|
||||||
cr:set_source(gcolor(color))
|
cr:set_source(gcolor(color))
|
||||||
cr:rectangle(x, y, width, height)
|
cr:rectangle(x, y, width, height)
|
||||||
cr:fill()
|
cr:fill()
|
||||||
|
|
||||||
return surface
|
return surface
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Update handler for the battery widget. This is the function called
|
--- Update handler for the battery widget. This is the function called
|
||||||
|
@ -53,16 +53,16 @@ end
|
||||||
-- @tparam my_battery widget The battery widget to update.
|
-- @tparam my_battery widget The battery widget to update.
|
||||||
-- @tparam UPowerGLib.Device device The UPower device to monitor.
|
-- @tparam UPowerGLib.Device device The UPower device to monitor.
|
||||||
function my_battery.update(widget, device)
|
function my_battery.update(widget, device)
|
||||||
widget.image = my_battery.draw_battery(device.percentage, widget.color)
|
widget.image = my_battery.draw_battery(device.percentage, widget.color)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Give the widget template for the battery widget.
|
--- Give the widget template for the battery widget.
|
||||||
-- (It's a basic `wibox.widget.imagebox` for my battery implementation)
|
-- (It's a basic `wibox.widget.imagebox` for my battery implementation)
|
||||||
function my_battery.widget_template()
|
function my_battery.widget_template()
|
||||||
local widget = imagebox()
|
local widget = imagebox()
|
||||||
widget.resize = true
|
widget.resize = true
|
||||||
|
|
||||||
return widget
|
return widget
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Constructor of my battery widget!
|
--- Constructor of my battery widget!
|
||||||
|
@ -72,31 +72,32 @@ end
|
||||||
-- @tparam gears.color|string args.color Color to use to draw the battery.
|
-- @tparam gears.color|string args.color Color to use to draw the battery.
|
||||||
-- @treturn my_battery The instantiated widget.
|
-- @treturn my_battery The instantiated widget.
|
||||||
function my_battery.new(args)
|
function my_battery.new(args)
|
||||||
local widget = battery_widget {
|
local widget = battery_widget {
|
||||||
screen = args.screen,
|
screen = args.screen,
|
||||||
device_path = args.device_path,
|
-- device_path = args.device_path,
|
||||||
widget_template = my_battery.widget_template(),
|
use_display_device = true,
|
||||||
instant_update = true,
|
widget_template = my_battery.widget_template(),
|
||||||
}
|
instant_update = true,
|
||||||
|
}
|
||||||
|
|
||||||
widget.color = args.color
|
widget.color = args.color
|
||||||
|
|
||||||
widget:connect_signal("upower::update", function(w, device)
|
widget:connect_signal("upower::update", function(w, device)
|
||||||
my_battery.update(w, device)
|
my_battery.update(w, device)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
widget.tooltip = atooltip {
|
widget.tooltip = atooltip {
|
||||||
objects = { widget },
|
objects = { widget },
|
||||||
timer_function = function()
|
timer_function = function()
|
||||||
return string.format("%3d", widget.device.percentage) .. "%"
|
return string.format("%3d", widget.device.percentage) .. "%"
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
return widget
|
return widget
|
||||||
end
|
end
|
||||||
|
|
||||||
function mt:__call(...)
|
function mt:__call(...) -- luacheck: ignore unused self
|
||||||
return my_battery.new(...)
|
return my_battery.new(...)
|
||||||
end
|
end
|
||||||
|
|
||||||
return setmetatable(my_battery, mt)
|
return setmetatable(my_battery, mt)
|
|
@ -0,0 +1,6 @@
|
||||||
|
local bar_widgets = {}
|
||||||
|
|
||||||
|
bar_widgets.battery = require "awesomerc.ui.desktop_decoration.bar.widgets.battery"
|
||||||
|
bar_widgets.prompt = require "awesomerc.ui.desktop_decoration.bar.widgets.prompt"
|
||||||
|
|
||||||
|
return bar_widgets
|
|
@ -0,0 +1,72 @@
|
||||||
|
local acompletion = require "awful.completion"
|
||||||
|
local aspawn = require "awful.spawn"
|
||||||
|
local gstring = require "gears.string"
|
||||||
|
local gtable = require "gears.table"
|
||||||
|
local prompt = require "awful.widget.prompt"
|
||||||
|
|
||||||
|
local string = string
|
||||||
|
|
||||||
|
local function completion_cb(self, command_before_comp, cur_pos_before_comp, ncomp)
|
||||||
|
return acompletion.generic(command_before_comp, cur_pos_before_comp, ncomp, self.completion_keywords)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function exe_cb(self, input)
|
||||||
|
-- Exit if the input is empty
|
||||||
|
if not input or #input == 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Trim
|
||||||
|
input = string.gsub(input, "^%s*(.-)%s*$", "%1")
|
||||||
|
|
||||||
|
-- If the input is not a VI command, spawn it
|
||||||
|
if input:sub(1, 1) ~= ":" then
|
||||||
|
aspawn(input)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Parse the custom command
|
||||||
|
local command, parameters = input:gmatch ":([%w-]+)%s*(.*)"()
|
||||||
|
command = command:sub(1, 1)
|
||||||
|
parameters = gstring.split(parameters, "%s")
|
||||||
|
|
||||||
|
-- Quit if the command doesn't exist
|
||||||
|
if not self.commands[command] then
|
||||||
|
print('":' .. command .. '" not reconized as a command')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
self.commands[command].callback(parameters)
|
||||||
|
end
|
||||||
|
|
||||||
|
local my_prompt = { mt = {} }
|
||||||
|
|
||||||
|
function my_prompt.new(args)
|
||||||
|
local prompt_widget = nil
|
||||||
|
prompt_widget = prompt {
|
||||||
|
prompt = "<b></b> ", -- needs the 3 spaces
|
||||||
|
completion_callback = function(...)
|
||||||
|
return completion_cb(prompt_widget, ...)
|
||||||
|
end,
|
||||||
|
exe_callback = function(...)
|
||||||
|
return exe_cb(prompt_widget, ...)
|
||||||
|
end,
|
||||||
|
}
|
||||||
|
|
||||||
|
prompt_widget.commands = args.commands
|
||||||
|
prompt_widget.completion_keywords = gtable.join(
|
||||||
|
-- TODO: find applications list
|
||||||
|
gtable.find_keys(args.commands, function()
|
||||||
|
return true
|
||||||
|
end, false),
|
||||||
|
args.completion_keywords or {}
|
||||||
|
)
|
||||||
|
|
||||||
|
return prompt_widget
|
||||||
|
end
|
||||||
|
|
||||||
|
function my_prompt.mt:__call(...) -- luacheck: ignore unused arg self
|
||||||
|
return my_prompt.new(...)
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(my_prompt, my_prompt.mt)
|
|
@ -0,0 +1,5 @@
|
||||||
|
local desktop_decoration = {}
|
||||||
|
|
||||||
|
desktop_decoration.bar = require "awesomerc.ui.desktop_decoration.bar"
|
||||||
|
|
||||||
|
return desktop_decoration
|
|
@ -0,0 +1,12 @@
|
||||||
|
local hotkeys_popup = require "awful.hotkeys_popup"
|
||||||
|
|
||||||
|
-- luacheck: ignore unset variable keys
|
||||||
|
local keys = {
|
||||||
|
vim = require "awful.hotkeys_popup.keys.vim",
|
||||||
|
firefox = require "awful.hotkeys_popup.keys.firefox",
|
||||||
|
tmux = require "awful.hotkeys_popup.keys.tmux",
|
||||||
|
qutebrowser = require "awful.hotkeys_popup.keys.qutebrowser",
|
||||||
|
termite = require "awful.hotkeys_popup.keys.termite",
|
||||||
|
}
|
||||||
|
|
||||||
|
return hotkeys_popup
|
|
@ -0,0 +1,32 @@
|
||||||
|
local amenu = require "awful.menu"
|
||||||
|
|
||||||
|
local configuration = {
|
||||||
|
menu = require "awesomerc.configuration.menu",
|
||||||
|
}
|
||||||
|
|
||||||
|
local mymainmenu = { _private = {}, mt = {} }
|
||||||
|
|
||||||
|
function mymainmenu:instance()
|
||||||
|
local instance = self._private.instance
|
||||||
|
|
||||||
|
if not instance then
|
||||||
|
instance = mymainmenu.new()
|
||||||
|
self._private.instance = instance
|
||||||
|
end
|
||||||
|
|
||||||
|
return instance
|
||||||
|
end
|
||||||
|
|
||||||
|
function mymainmenu.new()
|
||||||
|
local menu = amenu {
|
||||||
|
items = configuration.menu.mymainmenu,
|
||||||
|
}
|
||||||
|
|
||||||
|
return menu
|
||||||
|
end
|
||||||
|
|
||||||
|
function mymainmenu.mt:__call()
|
||||||
|
return self:instance()
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(mymainmenu, mymainmenu.mt)
|
|
@ -0,0 +1,24 @@
|
||||||
|
local gtimer = require "gears.timer"
|
||||||
|
local nice = require "awesome-wm-nice"
|
||||||
|
|
||||||
|
local titlebar = { mt = {} }
|
||||||
|
|
||||||
|
function titlebar.new(client)
|
||||||
|
-- We need first to manually set the base color because of how nice is designed
|
||||||
|
client._nice_base_color = nice.config.titlebar_color
|
||||||
|
|
||||||
|
-- We need to delay the call to add_window_decoration because the client has
|
||||||
|
-- to be fully initialized first (e.g. the client's geometry has to be set)
|
||||||
|
-- for the decoration to be added correctly.
|
||||||
|
-- Note: resizing the client will not update the decoration size, so it feels
|
||||||
|
-- a bit hacky. I need to fix this.
|
||||||
|
gtimer.delayed_call(function()
|
||||||
|
nice.add_window_decoration(client)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
function titlebar.mt:__call(client) -- luacheck: ignore unused arg self
|
||||||
|
return titlebar.new(client)
|
||||||
|
end
|
||||||
|
|
||||||
|
return setmetatable(titlebar, titlebar.mt)
|
|
@ -1,33 +0,0 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
killXephyr() {
|
|
||||||
kill "$(pgrep Xephyr)" >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
trap killXephyr EXIT
|
|
||||||
|
|
||||||
if [ "$1" = "stop" ]; then
|
|
||||||
killXephyr
|
|
||||||
exit 0
|
|
||||||
fi;
|
|
||||||
|
|
||||||
xephyr=$1
|
|
||||||
awesome=$2
|
|
||||||
rc_file=$3
|
|
||||||
|
|
||||||
# Check for the first free display
|
|
||||||
for i in $(seq 1 10); do
|
|
||||||
if [ ! -f "/tmp/.X${i}-lock" ]; then
|
|
||||||
D=$i;
|
|
||||||
break;
|
|
||||||
fi;
|
|
||||||
done
|
|
||||||
|
|
||||||
# Start Xephyr
|
|
||||||
$xephyr :"$D" -name xephyr_"$D" -ac -br -noreset -screen 1600x900 >/dev/null 2>&1 &
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
# Start Awesome
|
|
||||||
DISPLAY=:$D.0 $awesome \
|
|
||||||
--config "$rc_file"
|
|
||||||
|
|
Before Width: | Height: | Size: 4.1 MiB |
|
@ -1,247 +0,0 @@
|
||||||
local awibar = require "awful.wibar"
|
|
||||||
local awful = require "awful"
|
|
||||||
local battery_widget = require "battery-widget"
|
|
||||||
local beautiful = require "beautiful"
|
|
||||||
|
|
||||||
local container_background = require "wibox.container.background"
|
|
||||||
local container_margin = require "wibox.container.margin"
|
|
||||||
local container_place = require "wibox.container.place"
|
|
||||||
|
|
||||||
local gshape = require "gears.shape"
|
|
||||||
|
|
||||||
local layout_align = require "wibox.layout.align"
|
|
||||||
local layout_fixed = require "wibox.layout.fixed"
|
|
||||||
|
|
||||||
local systray = require "wibox.widget.systray"
|
|
||||||
local textclock = require "wibox.widget.textclock"
|
|
||||||
local widget = require "wibox.widget"
|
|
||||||
|
|
||||||
local mycommands = require "rc.configuration.prompt_commands"
|
|
||||||
local mymainmenu = require "rc.ui.menu.mymainmenu"
|
|
||||||
local mytaglist = require "MyTagListWidget"
|
|
||||||
|
|
||||||
local bar_widgets = require "rc.ui.desktop_decoration.bar.widgets"
|
|
||||||
local mybattery = bar_widgets.battery
|
|
||||||
local myprompt = bar_widgets.prompt
|
|
||||||
|
|
||||||
local capi = {
|
|
||||||
screen = _G.screen,
|
|
||||||
}
|
|
||||||
|
|
||||||
local abs = math.abs
|
|
||||||
local dpi = beautiful.xresources.apply_dpi
|
|
||||||
|
|
||||||
local function get_screen_id(screen)
|
|
||||||
local s = capi.screen[screen or 1]
|
|
||||||
|
|
||||||
return s.index
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Build a widget box in the bar.
|
|
||||||
-- A widget box is a combinaision of "shaped" `wibox.container/background` and
|
|
||||||
-- `wibox.container.margin` to create this nice round-colored-buttons I like.
|
|
||||||
-- @tparam args table
|
|
||||||
-- @tparam args.screen The screen where the widget will be drawn.
|
|
||||||
-- @tparam args.widget The widget to draw.
|
|
||||||
-- @tparam[opt] args.bg The box's background.
|
|
||||||
-- @tpram[opt] args.fg The box's foreground (used mainly for textbox text color).
|
|
||||||
-- @treturn wibox.container.background The builded widget.
|
|
||||||
local function build_widget(args)
|
|
||||||
local screen_id = get_screen_id(args.screen)
|
|
||||||
|
|
||||||
-- Callback for the shape function.
|
|
||||||
-- If the widget is almost a square: draw a circle. Otherwise, draw a
|
|
||||||
-- rounded_bar.
|
|
||||||
local shape_callback = function(cr, width, height)
|
|
||||||
local shape = gshape.circle
|
|
||||||
|
|
||||||
-- 10 is an arbitrary value I found after some tests :shrug:
|
|
||||||
if abs(width - height) > 10 then
|
|
||||||
shape = gshape.rounded_bar
|
|
||||||
end
|
|
||||||
|
|
||||||
return shape(cr, width, height)
|
|
||||||
end
|
|
||||||
|
|
||||||
local box_widget = widget {
|
|
||||||
{
|
|
||||||
widget = container_margin,
|
|
||||||
draw_empty = false,
|
|
||||||
top = dpi(beautiful.bar_box_padding_y, screen_id),
|
|
||||||
bottom = dpi(beautiful.bar_box_padding_y, screen_id),
|
|
||||||
right = dpi(beautiful.bar_box_padding_x, screen_id),
|
|
||||||
left = dpi(beautiful.bar_box_padding_x, screen_id),
|
|
||||||
args.widget,
|
|
||||||
},
|
|
||||||
bg = args.bg,
|
|
||||||
fg = args.fg,
|
|
||||||
shape = shape_callback,
|
|
||||||
widget = container_background,
|
|
||||||
}
|
|
||||||
|
|
||||||
return box_widget
|
|
||||||
end
|
|
||||||
|
|
||||||
local bar = { _private = { instances = {} }, mt = {} }
|
|
||||||
|
|
||||||
bar.widgets = bar_widgets
|
|
||||||
|
|
||||||
--- Get the bar instance for a given screen.
|
|
||||||
-- If no instance was found, we build a new one.
|
|
||||||
-- @tparam screen screen|integer The bar's screen.
|
|
||||||
-- @treturn wibox.wibar
|
|
||||||
function bar:instance(screen)
|
|
||||||
local screen_id = get_screen_id(screen)
|
|
||||||
local instance = self._private.instances[screen_id]
|
|
||||||
|
|
||||||
if not instance then
|
|
||||||
instance = bar.new(screen)
|
|
||||||
self._private.instances[screen_id] = instance
|
|
||||||
end
|
|
||||||
|
|
||||||
return instance
|
|
||||||
end
|
|
||||||
|
|
||||||
function bar.new(screen)
|
|
||||||
local my_bar = {}
|
|
||||||
|
|
||||||
my_bar.launcher = build_widget {
|
|
||||||
screen = screen,
|
|
||||||
bg = "#2196F3",
|
|
||||||
widget = awful.widget.launcher {
|
|
||||||
image = beautiful.icon_apps,
|
|
||||||
menu = mymainmenu(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
my_bar.textclock = build_widget {
|
|
||||||
screen = screen,
|
|
||||||
bg = "#FF5722",
|
|
||||||
fg = "#ECEFF1",
|
|
||||||
widget = textclock "%l:%M %p",
|
|
||||||
}
|
|
||||||
|
|
||||||
my_bar.promptbox = myprompt {
|
|
||||||
commands = mycommands,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- This widget needs to be reworded and integrated inside the project.
|
|
||||||
my_bar.taglist = mytaglist.new {
|
|
||||||
screen = screen,
|
|
||||||
}
|
|
||||||
|
|
||||||
my_bar.battery = build_widget {
|
|
||||||
screen = screen,
|
|
||||||
bg = "#673AB7",
|
|
||||||
widget = mybattery {
|
|
||||||
screen = screen,
|
|
||||||
device_path = battery_widget.get_BAT0_device_path(),
|
|
||||||
color = "#ECEFF1",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
my_bar.systray = build_widget {
|
|
||||||
screen = screen,
|
|
||||||
bg = "#455A64",
|
|
||||||
widget = systray(),
|
|
||||||
}
|
|
||||||
|
|
||||||
my_bar.wibar = awibar {
|
|
||||||
screen = screen,
|
|
||||||
position = "bottom",
|
|
||||||
height = dpi(beautiful.bar_height, screen),
|
|
||||||
width = beautiful.bar_width, -- Width is a percentage of the screen size
|
|
||||||
}
|
|
||||||
|
|
||||||
my_bar.wibar:setup {
|
|
||||||
-- Bar margins
|
|
||||||
{
|
|
||||||
-- Physical bar
|
|
||||||
{
|
|
||||||
-- Bar paddings
|
|
||||||
{
|
|
||||||
-- Bar content
|
|
||||||
{
|
|
||||||
-- Left side of the bar, align on the left
|
|
||||||
{
|
|
||||||
-- box margins
|
|
||||||
{
|
|
||||||
-- Left widget boxes
|
|
||||||
my_bar.launcher,
|
|
||||||
my_bar.promptbox,
|
|
||||||
spacing = dpi(
|
|
||||||
beautiful.bar_box_spacing,
|
|
||||||
screen
|
|
||||||
),
|
|
||||||
layout = layout_fixed.horizontal,
|
|
||||||
},
|
|
||||||
top = dpi(beautiful.bar_box_margin_y, screen),
|
|
||||||
bottom = dpi(beautiful.bar_box_margin_y, screen),
|
|
||||||
right = dpi(beautiful.bar_box_margin_x, screen),
|
|
||||||
left = dpi(beautiful.bar_box_margin_x, screen),
|
|
||||||
widget = container_margin,
|
|
||||||
},
|
|
||||||
halign = "left",
|
|
||||||
widget = container_place,
|
|
||||||
},
|
|
||||||
expand = "outside",
|
|
||||||
layout = layout_align.horizontal,
|
|
||||||
|
|
||||||
-- Middle widget is the custom taglist
|
|
||||||
-- it doesn't need box/margins/...
|
|
||||||
{
|
|
||||||
my_bar.taglist,
|
|
||||||
widget = container_place,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
-- Right side of the bar, align on the right
|
|
||||||
{
|
|
||||||
-- box margins
|
|
||||||
{
|
|
||||||
-- Right widget boxes
|
|
||||||
my_bar.systray,
|
|
||||||
my_bar.battery,
|
|
||||||
my_bar.textclock,
|
|
||||||
spacing = dpi(
|
|
||||||
beautiful.bar_box_spacing,
|
|
||||||
screen
|
|
||||||
),
|
|
||||||
layout = layout_fixed.horizontal,
|
|
||||||
},
|
|
||||||
top = dpi(beautiful.bar_box_margin_y, screen),
|
|
||||||
bottom = dpi(beautiful.bar_box_margin_y, screen),
|
|
||||||
right = dpi(beautiful.bar_box_margin_x, screen),
|
|
||||||
left = dpi(beautiful.bar_box_margin_x, screen),
|
|
||||||
widget = container_margin,
|
|
||||||
},
|
|
||||||
halign = "right",
|
|
||||||
widget = container_place,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
top = dpi(beautiful.bar_padding_y, screen),
|
|
||||||
bottom = dpi(beautiful.bar_padding_y, screen),
|
|
||||||
right = dpi(beautiful.bar_padding_x, screen),
|
|
||||||
left = dpi(beautiful.bar_padding_x, screen),
|
|
||||||
widget = container_margin,
|
|
||||||
},
|
|
||||||
bg = beautiful.bar_bg,
|
|
||||||
shape = function(cr, width, height)
|
|
||||||
gshape.rounded_rect(cr, width, height, 10)
|
|
||||||
end,
|
|
||||||
widget = container_background,
|
|
||||||
},
|
|
||||||
top = dpi(beautiful.bar_margin_y, screen),
|
|
||||||
bottom = dpi(beautiful.bar_margin_y, screen),
|
|
||||||
right = dpi(beautiful.bar_margin_x, screen),
|
|
||||||
left = dpi(beautiful.bar_margin_x, screen),
|
|
||||||
widget = container_margin,
|
|
||||||
}
|
|
||||||
|
|
||||||
return my_bar
|
|
||||||
end
|
|
||||||
|
|
||||||
function bar.mt:__call(...)
|
|
||||||
return self:instance(...)
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(bar, bar.mt)
|
|