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_size = 4
|
||||
indent_size = 3
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = 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 = "min"
|
||||
std = "lua54"
|
||||
|
||||
-- Get rid of "unused argument self"-warnings
|
||||
self = false
|
||||
files[".luamonrc"].std = {
|
||||
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 = {
|
||||
"awesome",
|
||||
"button",
|
||||
|
@ -21,13 +39,9 @@ read_globals = {
|
|||
"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
|
||||
globals = {
|
||||
"screen",
|
||||
"mouse",
|
||||
"root",
|
||||
"client",
|
||||
}
|
||||
|
|
|
@ -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": [
|
||||
"editorconfig.editorconfig",
|
||||
"tomblind.local-lua-debugger-vscode",
|
||||
"sumneko.lua",
|
||||
"johnnymorganz.stylua",
|
||||
"dwenegar.vscode-luacheck"
|
||||
]
|
||||
"recommendations": [
|
||||
"streetsidesoftware.code-spell-checker",
|
||||
"editorconfig.editorconfig",
|
||||
"tomblind.local-lua-debugger-vscode",
|
||||
"johnnymorganz.stylua",
|
||||
"dwenegar.vscode-luacheck",
|
||||
"sumneko.lua"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,19 +1,17 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "lua-local",
|
||||
"request": "launch",
|
||||
"name": "Debug with Xephyr",
|
||||
"program": {
|
||||
"command": "${workspaceFolder}/start-xephyr.sh"
|
||||
},
|
||||
"args": [
|
||||
"/usr/bin/Xephyr",
|
||||
"/usr/bin/awesome",
|
||||
"${workspaceFolder}/init.lua"
|
||||
],
|
||||
"postDebugTask": "Terminate All Tasks"
|
||||
}
|
||||
]
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "lua-local",
|
||||
"request": "launch",
|
||||
"name": "Debug with Xephyr",
|
||||
"program": {
|
||||
"command": "${workspaceFolder}/scripts/run.sh"
|
||||
},
|
||||
"args": ["debug"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.formatOnPaste": true,
|
||||
"[markdown]": {
|
||||
"editor.wordWrap": "on",
|
||||
"editor.renderWhitespace": "all",
|
||||
"editor.acceptSuggestionOnEnter": "off"
|
||||
}
|
||||
"Lua.runtime.path": [
|
||||
"/usr/share/awesome/lib/?.lua",
|
||||
"/usr/share/awesome/lib/?/init.lua",
|
||||
"${workspaceFolder}/src/?.lua",
|
||||
"${workspaceFolder}/src/init.lua",
|
||||
"${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.open_terminal = function()
|
||||
return applications.terminal .. " -e tmux"
|
||||
return applications.terminal .. " -e tmux"
|
||||
end
|
||||
|
||||
applications.open_editor = function(file)
|
||||
return applications.terminal .. " -e " .. applications.editor .. " " .. file
|
||||
return applications.terminal .. " -e " .. applications.editor .. " " .. file
|
||||
end
|
||||
|
||||
applications.open_man = function(file)
|
||||
return applications.terminal .. " -e man " .. file
|
||||
return applications.terminal .. " -e man " .. file
|
||||
end
|
||||
|
||||
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 config_dir = gfs.get_configuration_dir()
|
||||
local theme_dir = config_dir .. "theme/"
|
||||
local assets_dir = theme_dir .. "assets/"
|
||||
local assets_dir = config_dir .. "assets/"
|
||||
local icons_dir = assets_dir .. "icons/"
|
||||
|
||||
local theme = {}
|
||||
|
||||
--- Basic
|
||||
theme.font = "Noto Mono 9"
|
||||
theme.border_width = 0
|
||||
|
||||
--- Tags
|
||||
theme.hometag_master_width_factor = 0.65
|
||||
--- Clients
|
||||
theme.client_corner_radius_top = 9
|
||||
theme.client_corner_radius_bottom = 4
|
||||
|
||||
--- Icons
|
||||
theme.icon_hometag = icons_dir .. "home-circle.svg"
|
||||
|
@ -32,7 +33,7 @@ theme.wibar_bg = "#0000"
|
|||
|
||||
--- Spacing and margins
|
||||
-- Naming convention:
|
||||
-- <rc.ui.desktop_decoration element>_<widget element>_<property>
|
||||
-- <awesomerc.ui.desktop_decoration element>_<widget element>_<property>
|
||||
theme.spacing = 8
|
||||
theme.margin = 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_spacing = theme.spacing
|
||||
|
||||
theme.gaps_hometag = theme.padding
|
||||
|
||||
--- Widgets specific
|
||||
theme.bg_systray = "#455A64"
|
||||
theme.systray_icon_spacing = 3
|
||||
|
||||
--- Wallpaper
|
||||
theme.wallpaper = assets_dir .. "wallpapers/pizza.jpg"
|
||||
theme.wallpaper = assets_dir .. "wallpapers/poke.jpg"
|
||||
|
||||
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 imagebox = require "wibox.widget.imagebox"
|
||||
|
||||
local battery_widget = require "battery-widget"
|
||||
local battery_widget = require "awesome-battery_widget"
|
||||
|
||||
local my_battery = {}
|
||||
local mt = {}
|
||||
|
@ -27,25 +27,25 @@ local mt = {}
|
|||
-- @tparam gears.color|string color The color of the drawing.
|
||||
-- @treturn cairo.ImageSurface The generated surface for the drawing.
|
||||
function my_battery.draw_battery(percentage, color)
|
||||
local svg_handle = rsvg.Handle.new_from_file(beautiful.icon_battery_outline)
|
||||
if not svg_handle then
|
||||
return
|
||||
end
|
||||
local surface = cairo.ImageSurface.create(cairo.Format.ARGB32, 24, 24)
|
||||
local cr = cairo.Context(surface)
|
||||
svg_handle:render_cairo(cr)
|
||||
local svg_handle = rsvg.Handle.new_from_file(beautiful.icon_battery_outline)
|
||||
if not svg_handle then
|
||||
return
|
||||
end
|
||||
local surface = cairo.ImageSurface.create(cairo.Format.ARGB32, 24, 24)
|
||||
local cr = cairo.Context(surface)
|
||||
svg_handle:render_cairo(cr)
|
||||
|
||||
local max_height = 14
|
||||
local x = 8
|
||||
local width = 8
|
||||
local height = percentage / 100 * max_height
|
||||
local y = 6 + max_height - height
|
||||
local max_height = 14
|
||||
local x = 8
|
||||
local width = 8
|
||||
local height = percentage / 100 * max_height
|
||||
local y = 6 + max_height - height
|
||||
|
||||
cr:set_source(gcolor(color))
|
||||
cr:rectangle(x, y, width, height)
|
||||
cr:fill()
|
||||
cr:set_source(gcolor(color))
|
||||
cr:rectangle(x, y, width, height)
|
||||
cr:fill()
|
||||
|
||||
return surface
|
||||
return surface
|
||||
end
|
||||
|
||||
--- 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 UPowerGLib.Device device The UPower device to monitor.
|
||||
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
|
||||
|
||||
--- Give the widget template for the battery widget.
|
||||
-- (It's a basic `wibox.widget.imagebox` for my battery implementation)
|
||||
function my_battery.widget_template()
|
||||
local widget = imagebox()
|
||||
widget.resize = true
|
||||
local widget = imagebox()
|
||||
widget.resize = true
|
||||
|
||||
return widget
|
||||
return widget
|
||||
end
|
||||
|
||||
--- Constructor of my battery widget!
|
||||
|
@ -72,31 +72,32 @@ end
|
|||
-- @tparam gears.color|string args.color Color to use to draw the battery.
|
||||
-- @treturn my_battery The instantiated widget.
|
||||
function my_battery.new(args)
|
||||
local widget = battery_widget {
|
||||
screen = args.screen,
|
||||
device_path = args.device_path,
|
||||
widget_template = my_battery.widget_template(),
|
||||
instant_update = true,
|
||||
}
|
||||
local widget = battery_widget {
|
||||
screen = args.screen,
|
||||
-- device_path = args.device_path,
|
||||
use_display_device = 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)
|
||||
my_battery.update(w, device)
|
||||
end)
|
||||
widget:connect_signal("upower::update", function(w, device)
|
||||
my_battery.update(w, device)
|
||||
end)
|
||||
|
||||
widget.tooltip = atooltip {
|
||||
objects = { widget },
|
||||
timer_function = function()
|
||||
return string.format("%3d", widget.device.percentage) .. "%"
|
||||
end,
|
||||
}
|
||||
widget.tooltip = atooltip {
|
||||
objects = { widget },
|
||||
timer_function = function()
|
||||
return string.format("%3d", widget.device.percentage) .. "%"
|
||||
end,
|
||||
}
|
||||
|
||||
return widget
|
||||
return widget
|
||||
end
|
||||
|
||||
function mt:__call(...)
|
||||
return my_battery.new(...)
|
||||
function mt:__call(...) -- luacheck: ignore unused self
|
||||
return my_battery.new(...)
|
||||
end
|
||||
|
||||
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)
|