diff --git a/.config/awesome/rc.lua b/.config/awesome/rc.lua index d4dd1b2..fe30c5a 100644 --- a/.config/awesome/rc.lua +++ b/.config/awesome/rc.lua @@ -1,11 +1,21 @@ +-- 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") + +-- Standard awesome library local gears = require("gears") local awful = require("awful") require("awful.autofocus") +-- Widget and layout library local wibox = require("wibox") +-- Theme handling library local beautiful = require("beautiful") +-- Notification library local naughty = require("naughty") local menubar = require("menubar") +local hotkeys_popup = require("awful.hotkeys_popup") +-- Enable hotkeys help widget for VIM and other apps +-- when client with a matching name is opened: require("awful.hotkeys_popup.keys") -- {{{ Error handling @@ -41,17 +51,23 @@ end -- {{{ Variable definitions -- Themes define colours, icons, font and wallpapers. -beautiful.init(gears.filesystem.get_themes_dir() .. "default/theme.lua") +local theme = require("theme") +beautiful.init(theme) -- This is used later as the default terminal and editor to run. terminal = "kitty" -editor = os.getenv("EDITOR") or "nvim" +editor = "nvim" editor_cmd = terminal .. " -e " .. editor -mod = "Mod4" +-- Default modkey. +-- Usually, Mod4 is the key with a logo between Control and Alt. +-- If you do not like this or do not have such a key, +-- I suggest you to remap Mod4 to another key using xmodmap or other tools. +-- However, you can use another modifier like Mod1, but it may interact with others. +modkey = "Mod4" +-- Table of layouts to cover with awful.layout.inc, order matters. awful.layout.layouts = { - -- awful.layout.suit.floating, awful.layout.suit.tile, awful.layout.suit.tile.left, awful.layout.suit.tile.bottom, @@ -64,17 +80,198 @@ awful.layout.layouts = { awful.layout.suit.max.fullscreen, awful.layout.suit.magnifier, awful.layout.suit.corner.nw, + awful.layout.suit.floating, -- awful.layout.suit.corner.ne, -- awful.layout.suit.corner.sw, -- awful.layout.suit.corner.se, } +-- }}} -local tag_names = { "a", "s", "d", "f", "g", "z", "x", "c", "v", "b" } +-- {{{ Menu +-- Create a launcher widget and a main menu +myawesomemenu = { + { + "hotkeys", + function() + hotkeys_popup.show_help(nil, awful.screen.focused()) + end, + }, + { "manual", terminal .. " -e man awesome" }, + { "edit config", editor_cmd .. " " .. awesome.conffile }, + { "restart", awesome.restart }, + { + "quit", + function() + awesome.quit() + end, + }, +} + +mymainmenu = awful.menu({ + items = { + { "awesome", myawesomemenu, beautiful.awesome_icon }, + { "open terminal", terminal }, + }, +}) + +mylauncher = awful.widget.launcher({ image = beautiful.awesome_icon, menu = mymainmenu }) + +-- Menubar configuration +menubar.utils.terminal = terminal -- Set the terminal for applications that require it +-- }}} + +-- Keyboard map indicator and switcher +mykeyboardlayout = awful.widget.keyboardlayout() + +-- {{{ Wibar +-- Create a textclock widget +mytextclock = wibox.widget.textclock() + +-- Create a wibox for each screen and add it +local taglist_buttons = gears.table.join( + awful.button({}, 1, function(t) + t:view_only() + end), + awful.button({ modkey }, 1, function(t) + if client.focus then + client.focus:move_to_tag(t) + end + end), + awful.button({}, 3, awful.tag.viewtoggle), + awful.button({ modkey }, 3, function(t) + if client.focus then + client.focus:toggle_tag(t) + end + end), + awful.button({}, 4, function(t) + awful.tag.viewnext(t.screen) + end), + awful.button({}, 5, function(t) + awful.tag.viewprev(t.screen) + end) +) + +local tasklist_buttons = gears.table.join( + awful.button({}, 1, function(c) + if c == client.focus then + c.minimized = true + else + c:emit_signal("request::activate", "tasklist", { raise = true }) + end + end), + awful.button({}, 3, function() + awful.menu.client_list({ theme = { width = 250 } }) + end), + awful.button({}, 4, function() + awful.client.focus.byidx(1) + end), + awful.button({}, 5, function() + awful.client.focus.byidx(-1) + end) +) + +local function set_wallpaper(s) + -- Wallpaper + if beautiful.wallpaper then + local wallpaper = beautiful.wallpaper + -- If wallpaper is a function, call it with the screen + if type(wallpaper) == "function" then + wallpaper = wallpaper(s) + end + gears.wallpaper.maximized(wallpaper, s, true) + end +end + +-- Re-set wallpaper when a screen's geometry changes (e.g. different resolution) +screen.connect_signal("property::geometry", set_wallpaper) awful.screen.connect_for_each_screen(function(s) + -- Wallpaper + set_wallpaper(s) + -- Each screen has its own tag table. - awful.tag(tag_names, s, awful.layout.layouts[1]) + awful.tag({ " a ", " s ", " d ", " f ", " g ", " z ", " x ", " c ", " v ", " b " }, s, awful.layout.layouts[1]) + + -- Create a promptbox for each screen + s.mypromptbox = awful.widget.prompt() + -- Create an imagebox widget which will contain an icon indicating which layout we're using. + -- We need one layoutbox per screen. + s.mylayoutbox = awful.widget.layoutbox(s) + s.mylayoutbox:buttons(gears.table.join( + awful.button({}, 1, function() + awful.layout.inc(1) + end), + awful.button({}, 3, function() + awful.layout.inc(-1) + end), + awful.button({}, 4, function() + awful.layout.inc(1) + end), + awful.button({}, 5, function() + awful.layout.inc(-1) + end) + )) + -- Create a taglist widget + s.mytaglist = awful.widget.taglist({ + screen = s, + filter = awful.widget.taglist.filter.all, + buttons = taglist_buttons, + }) + + -- Create a tasklist widget + s.mytasklist = awful.widget.tasklist({ + screen = s, + filter = awful.widget.tasklist.filter.currenttags, + buttons = tasklist_buttons, + }) + + -- Create the wibox + s.mywibar = awful.wibar({ + position = "top", + screen = s, + height = 40, + }) + + local line_size = 3 + local separator_symbol = "|" + + local separator = wibox.widget({ + widget = wibox.widget.separator, + orientation = "vertical", + forced_width = line_size, + -- color = + }) + + -- Add widgets to the wibox + s.mywibar:setup({ + layout = wibox.layout.align.horizontal, + { + layout = wibox.layout.fixed.horizontal, + s.mytaglist, + }, + { + layout = wibox.layout.align.horizontal, + nil, + { + widget = wibox.container.margin, + margins = 5, + { + widget = mytextclock, + }, + }, + nil, + }, + { + layout = wibox.layout.fixed.horizontal, + spacing = 5, + separator, + mykeyboardlayout, + separator, + s.mylayoutbox, + }, + }) end) +-- }}} -- {{{ Mouse bindings root.buttons(gears.table.join( @@ -88,123 +285,126 @@ root.buttons(gears.table.join( -- {{{ Key bindings globalkeys = gears.table.join( + -- awful.key({ modkey }, "s", hotkeys_popup.show_help, { description = "show help", group = "awesome" }), + awful.key({ modkey }, "Left", awful.tag.viewprev, { description = "view previous", group = "tag" }), + awful.key({ modkey }, "Right", awful.tag.viewnext, { description = "view next", group = "tag" }), + awful.key({ modkey }, "Escape", awful.tag.history.restore, { description = "go back", group = "tag" }), - -- basics - awful.key({ mod }, "t", awesome.restart), + awful.key({ modkey }, "j", function() + awful.client.focus.byidx(1) + end, { description = "focus next by index", group = "client" }), + awful.key({ modkey }, "k", function() + awful.client.focus.byidx(-1) + end, { description = "focus previous by index", group = "client" }), + -- awful.key({ modkey }, "w", function() + -- mymainmenu:show() + -- end, { description = "show main menu", group = "awesome" }), - -- focus - awful.key({ mod }, "h", awful.client.focus.bydirection("left")), - awful.key({ mod }, "j", awful.client.focus.bydirection("down")), - awful.key({ mod }, "k", awful.client.focus.bydirection("up")), - awful.key({ mod }, "l", awful.client.focus.bydirection("right")), - - -- shift - awful.key({ mod, "Shift" }, "h", awful.client.swap.bydirection("left")), - awful.key({ mod, "Shift" }, "j", awful.client.swap.bydirection("down")), - awful.key({ mod, "Shift" }, "k", awful.client.swap.bydirection("up")), - awful.key({ mod, "Shift" }, "l", awful.client.swap.bydirection("right")), - - -- cycle - awful.key({ mod }, "m", function() + -- Layout manipulation + awful.key({ modkey, "Shift" }, "j", function() + awful.client.swap.byidx(1) + end, { description = "swap with next client by index", group = "client" }), + awful.key({ modkey, "Shift" }, "k", function() + awful.client.swap.byidx(-1) + end, { description = "swap with previous client by index", group = "client" }), + awful.key({ modkey }, "m", function() awful.screen.focus_relative(1) - end), - - -- cycle layouts - awful.key({ mod }, "space", function() - awful.layout.inc(1) - end), + end, { description = "focus the next screen", group = "screen" }), + -- awful.key({ modkey, "Control" }, "k", function() + -- awful.screen.focus_relative(-1) + -- end, { description = "focus the previous screen", group = "screen" }), + -- awful.key({ modkey }, "u", awful.client.urgent.jumpto, { description = "jump to urgent client", group = "client" }), + -- awful.key({ modkey }, "Tab", function() + -- awful.client.focus.history.previous() + -- if client.focus then + -- client.focus:raise() + -- end + -- end, { description = "go back", group = "client" }), -- Standard program - awful.key({ mod }, "Return", function() + awful.key({ modkey }, "Return", function() awful.spawn(terminal) - end), + end, { description = "open a terminal", group = "launcher" }), + awful.key({ modkey, "Control" }, "r", awesome.restart, { description = "reload awesome", group = "awesome" }), + awful.key({ modkey, "Shift" }, "q", awesome.quit, { description = "quit awesome", group = "awesome" }), - awful.key({ mod }, "l", function() + awful.key({ modkey }, "l", function() awful.tag.incmwfact(0.05) - end), - awful.key({ mod, "Control" }, "h", function() + end, { description = "increase master width factor", group = "layout" }), + awful.key({ modkey }, "h", function() awful.tag.incmwfact(-0.05) - end), - awful.key({ mod, "Shift" }, "h", function() - awful.tag.incnmaster(1, nil, true) - end), - awful.key({ mod, "Shift" }, "l", function() - awful.tag.incnmaster(-1, nil, true) - end), - awful.key({ mod, "Control" }, "h", function() - awful.tag.incncol(1, nil, true) - end), - awful.key({ mod, "Control" }, "l", function() - awful.tag.incncol(-1, nil, true) - end), - awful.key({ mod, "Shift" }, "space", function() + end, { description = "decrease master width factor", group = "layout" }), + -- awful.key({ modkey, "Shift" }, "h", function() + -- awful.tag.incnmaster(1, nil, true) + -- end, { description = "increase the number of master clients", group = "layout" }), + -- awful.key({ modkey, "Shift" }, "l", function() + -- awful.tag.incnmaster(-1, nil, true) + -- end, { description = "decrease the number of master clients", group = "layout" }), + -- awful.key({ modkey, "Control" }, "h", function() + -- awful.tag.incncol(1, nil, true) + -- end, { description = "increase the number of columns", group = "layout" }), + -- awful.key({ modkey, "Control" }, "l", function() + -- awful.tag.incncol(-1, nil, true) + -- end, { description = "decrease the number of columns", group = "layout" }), + awful.key({ modkey }, "Tab", function() + awful.layout.inc(1) + end, { description = "select next", group = "layout" }), + awful.key({ modkey, "Shift" }, "Tab", function() awful.layout.inc(-1) - end), + end, { description = "select previous", group = "layout" }), - awful.key({ mod }, "1", function() - awful.spawn("thunar") - end), - awful.key({ mod }, "2", function() - awful.spawn("firefox") - end), - awful.key({ mod }, "3", function() - awful.spawn("rofi -show calc") - end), - awful.key({ mod }, "4", function() - awful.spawn("kitty -e ncmpcpp") - end), - awful.key({ mod }, "0", function() - awful.spawn("i3lock -c 000000") - end), + -- awful.key({ modkey, "Control" }, "n", function() + -- local c = awful.client.restore() + -- -- Focus restored client + -- if c then + -- c:emit_signal("request::activate", "key.unminimize", { raise = true }) + -- end + -- end, { description = "restore minimized", group = "client" }), - awful.key({ mod, "Control" }, "n", function() - local c = awful.client.restore() - -- Focus restored client - if c then - c:emit_signal("request::activate", "key.unminimize", { raise = true }) - end - end, { description = "restore minimized", group = "client" }) + -- Prompt + awful.key({ modkey }, "space", function() + awful.spawn("rofi -show run") + end, { description = "run prompt", group = "launcher" }) + + -- awful.key({ modkey }, "x", function() + -- awful.prompt.run({ + -- prompt = "Run Lua code: ", + -- textbox = awful.screen.focused().mypromptbox.widget, + -- exe_callback = awful.util.eval, + -- history_path = awful.util.get_cache_dir() .. "/history_eval", + -- }) + -- end, { description = "lua execute prompt", group = "awesome" }), + -- Menubar + -- awful.key({ modkey }, "p", function() + -- menubar.show() + -- end, { description = "show the menubar", group = "launcher" }) ) clientkeys = gears.table.join( - -- basics - awful.key({ mod }, "w", function(c) - c:kill() - end), - - -- window attributes - awful.key({ mod, "Control" }, "e", function(c) + awful.key({ modkey, "Control" }, "w", function(c) c.fullscreen = not c.fullscreen c:raise() end), - awful.key({ mod, "Control" }, "q", awful.client.floating.toggle), - - awful.key({ mod, "Control" }, "Return", function(c) + awful.key({ modkey, "Control" }, "e", function(c) + c.floating = not c.floating + c:raise() + end), + awful.key({ modkey, "Control" }, "t", function(c) + c.sticky = not c.sticky + c:raise() + end, { description = "toggle floating", group = "client" }), + awful.key({ modkey }, "w", function(c) + c:kill() + end, { description = "close", group = "client" }), + awful.key({ modkey, "Control" }, "Return", function(c) c:swap(awful.client.getmaster()) end, { description = "move to master", group = "client" }), - awful.key({ mod }, "o", function(c) + awful.key({ modkey }, "o", function(c) c:move_to_screen() end, { description = "move to screen", group = "client" }), - awful.key({ mod }, "t", function(c) + awful.key({ modkey }, "t", function(c) c.ontop = not c.ontop - end, { description = "toggle keep on top", group = "client" }), - awful.key({ mod }, "n", function(c) - -- The client currently has the input focus, so it cannot be - -- minimized, since minimized clients can't have the focus. - c.minimized = true - end, { description = "minimize", group = "client" }), - awful.key({ mod }, "m", function(c) - c.maximized = not c.maximized - c:raise() - end, { description = "(un)maximize", group = "client" }), - awful.key({ mod, "Control" }, "m", function(c) - c.maximized_vertical = not c.maximized_vertical - c:raise() - end, { description = "(un)maximize vertically", group = "client" }), - awful.key({ mod, "Shift" }, "m", function(c) - c.maximized_horizontal = not c.maximized_horizontal - c:raise() - end, { description = "(un)maximize horizontally", group = "client" }) + end, { description = "toggle keep on top", group = "client" }) ) -- Bind all key numbers to tags. @@ -216,7 +416,7 @@ for i, tag_name in ipairs(tags) do globalkeys = gears.table.join( globalkeys, -- View tag only. - awful.key({ mod }, tag_name, function() + awful.key({ modkey }, tag_name, function() local screen = awful.screen.focused() local tag = screen.tags[i] if tag then @@ -224,7 +424,7 @@ for i, tag_name in ipairs(tags) do end end), -- Toggle tag display. - awful.key({ mod, "Control" }, tag_name, function() + awful.key({ modkey, "Control" }, tag_name, function() local screen = awful.screen.focused() local tag = screen.tags[i] if tag then @@ -232,7 +432,7 @@ for i, tag_name in ipairs(tags) do end end), -- Move client to tag. - awful.key({ mod, "Shift" }, tag_name, function() + awful.key({ modkey, "Shift" }, tag_name, function() if client.focus then local tag = client.focus.screen.tags[i] if tag then @@ -256,11 +456,11 @@ clientbuttons = gears.table.join( awful.button({}, 1, function(c) c:emit_signal("request::activate", "mouse_click", { raise = true }) end), - awful.button({ mod }, 1, function(c) + awful.button({ modkey }, 1, function(c) c:emit_signal("request::activate", "mouse_click", { raise = true }) awful.mouse.client.move(c) end), - awful.button({ mod }, 3, function(c) + awful.button({ modkey }, 3, function(c) c:emit_signal("request::activate", "mouse_click", { raise = true }) awful.mouse.client.resize(c) end) @@ -345,6 +545,21 @@ client.connect_signal("manage", function(c) end end) +-- Add a titlebar if titlebars_enabled is set to true in the rules. +client.connect_signal("request::titlebars", function(c) + -- buttons for the titlebar + local buttons = gears.table.join( + awful.button({}, 1, function() + c:emit_signal("request::activate", "titlebar", { raise = true }) + awful.mouse.client.move(c) + end), + awful.button({}, 3, function() + c:emit_signal("request::activate", "titlebar", { raise = true }) + awful.mouse.client.resize(c) + end) + ) +end) + -- Enable sloppy focus, so that focus follows mouse. client.connect_signal("mouse::enter", function(c) c:emit_signal("request::activate", "mouse_enter", { raise = false }) diff --git a/.config/awesome/theme.lua b/.config/awesome/theme.lua new file mode 100644 index 0000000..731018b --- /dev/null +++ b/.config/awesome/theme.lua @@ -0,0 +1,134 @@ +--------------------------------------------- +-- Awesome theme which follows xrdb config -- +-- by Yauhen Kirylau -- +--------------------------------------------- + +local theme_assets = require("beautiful.theme_assets") +local xresources = require("beautiful.xresources") +local dpi = xresources.apply_dpi +local xrdb = xresources.get_current_theme() +local gfs = require("gears.filesystem") +local themes_path = gfs.get_themes_dir() + +-- inherit default theme +local theme = dofile(themes_path.."default/theme.lua") +-- load vector assets' generators for this theme + +theme.font = "mononoki 12" + +theme.bg_normal = xrdb.background +theme.bg_focus = xrdb.color12 +theme.bg_urgent = xrdb.color9 +theme.bg_minimize = xrdb.color8 +theme.bg_systray = theme.bg_normal + +theme.fg_normal = xrdb.foreground +theme.fg_focus = theme.bg_normal +theme.fg_urgent = theme.bg_normal +theme.fg_minimize = theme.bg_normal + +theme.useless_gap = dpi(6) +theme.border_width = dpi(2) +theme.border_normal = xrdb.color0 +theme.border_focus = theme.bg_focus +theme.border_marked = xrdb.color10 + +-- There are other variable sets +-- overriding the default one when +-- defined, the sets are: +-- taglist_[bg|fg]_[focus|urgent|occupied|empty|volatile] +-- tasklist_[bg|fg]_[focus|urgent] +-- titlebar_[bg|fg]_[normal|focus] +-- tooltip_[font|opacity|fg_color|bg_color|border_width|border_color] +-- mouse_finder_[color|timeout|animate_timeout|radius|factor] +-- Example: +--theme.taglist_bg_focus = "#ff0000" + +theme.tooltip_fg = theme.fg_normal +theme.tooltip_bg = theme.bg_normal + +-- Variables set for theming the menu: +-- menu_[bg|fg]_[normal|focus] +-- menu_[border_color|border_width] +theme.menu_submenu_icon = themes_path.."default/submenu.png" +theme.menu_height = dpi(16) +theme.menu_width = dpi(100) + +-- You can add as many variables as +-- you wish and access them by using +-- beautiful.variable in your rc.lua +--theme.bg_widget = "#cc0000" + +-- Recolor Layout icons: +theme = theme_assets.recolor_layout(theme, theme.fg_normal) + +-- Recolor titlebar icons: +-- +local function darker(color_value, darker_n) + local result = "#" + for s in color_value:gmatch("[a-fA-F0-9][a-fA-F0-9]") do + local bg_numeric_value = tonumber("0x"..s) - darker_n + if bg_numeric_value < 0 then bg_numeric_value = 0 end + if bg_numeric_value > 255 then bg_numeric_value = 255 end + result = result .. string.format("%2.2x", bg_numeric_value) + end + return result +end +theme = theme_assets.recolor_titlebar( + theme, theme.fg_normal, "normal" +) +theme = theme_assets.recolor_titlebar( + theme, darker(theme.fg_normal, -60), "normal", "hover" +) +theme = theme_assets.recolor_titlebar( + theme, xrdb.color1, "normal", "press" +) +theme = theme_assets.recolor_titlebar( + theme, theme.fg_focus, "focus" +) +theme = theme_assets.recolor_titlebar( + theme, darker(theme.fg_focus, -60), "focus", "hover" +) +theme = theme_assets.recolor_titlebar( + theme, xrdb.color1, "focus", "press" +) + +-- Define the icon theme for application icons. If not set then the icons +-- from /usr/share/icons and /usr/share/icons/hicolor will be used. +theme.icon_theme = nil + +-- Generate Awesome icon: +theme.awesome_icon = theme_assets.awesome_icon( + theme.menu_height, theme.bg_focus, theme.fg_focus +) + +-- Generate taglist squares: +local taglist_square_size = dpi(4) +theme.taglist_squares_sel = theme_assets.taglist_squares_sel( + taglist_square_size, theme.fg_normal +) +theme.taglist_squares_unsel = theme_assets.taglist_squares_unsel( + taglist_square_size, theme.fg_normal +) + +-- Try to determine if we are running light or dark colorscheme: +local bg_numberic_value = 0; +for s in theme.bg_normal:gmatch("[a-fA-F0-9][a-fA-F0-9]") do + bg_numberic_value = bg_numberic_value + tonumber("0x"..s); +end +local is_dark_bg = (bg_numberic_value < 383) + +-- Generate wallpaper: +local wallpaper_bg = xrdb.color8 +local wallpaper_fg = xrdb.color7 +local wallpaper_alt_fg = xrdb.color12 +if not is_dark_bg then + wallpaper_bg, wallpaper_fg = wallpaper_fg, wallpaper_bg +end +theme.wallpaper = function(s) + return theme_assets.wallpaper(wallpaper_bg, wallpaper_fg, wallpaper_alt_fg, s) +end + +return theme + +-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80