changed to vertical layout

This commit is contained in:
Surferlul 2021-08-09 03:38:19 +02:00
parent 7f28a4eb85
commit 9b943513d5
13 changed files with 1974 additions and 54 deletions

253
menubar/icon_theme.lua Normal file
View File

@ -0,0 +1,253 @@
---------------------------------------------------------------------------
--- (Deprecated) class module for icon lookup for menubar
--
-- @author Kazunobu Kuriyama
-- @copyright 2015 Kazunobu Kuriyama
-- @classmod menubar.icon_theme
---------------------------------------------------------------------------
-- This implementation is based on the specifications:
-- Icon Theme Specification 0.12
-- http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-0.12.html
local beautiful = require("beautiful")
local gfs = require("gears.filesystem")
local GLib = require("lgi").GLib
local index_theme = require("menubar.index_theme")
local ipairs = ipairs
local setmetatable = setmetatable
local string = string
local table = table
local math = math
local get_pragmatic_base_directories = function()
local dirs = {}
local dir = GLib.build_filenamev({GLib.get_home_dir(), ".icons"})
if gfs.dir_readable(dir) then
table.insert(dirs, dir)
end
dir = GLib.build_filenamev({GLib.get_user_data_dir(), "icons"})
if gfs.dir_readable(dir) then
table.insert(dirs, dir)
end
for _, v in ipairs(GLib.get_system_data_dirs()) do
dir = GLib.build_filenamev({v, "icons"})
if gfs.dir_readable(dir) then
table.insert(dirs, dir)
end
end
local need_usr_share_pixmaps = true
for _, v in ipairs(GLib.get_system_data_dirs()) do
dir = GLib.build_filenamev({v, "pixmaps"})
if gfs.dir_readable(dir) then
table.insert(dirs, dir)
end
if dir == "/usr/share/pixmaps" then
need_usr_share_pixmaps = false
end
end
dir = "/usr/share/pixmaps"
if need_usr_share_pixmaps and gfs.dir_readable(dir) then
table.insert(dirs, dir)
end
return dirs
end
local get_default_icon_theme_name = function()
local icon_theme_names = { "Adwaita", "gnome", "hicolor" }
for _, dir in ipairs(get_pragmatic_base_directories()) do
for _, icon_theme_name in ipairs(icon_theme_names) do
local filename = string.format("%s/%s/index.theme", dir, icon_theme_name)
if gfs.file_readable(filename) then
return icon_theme_name
end
end
end
return "hicolor"
end
local icon_theme = { mt = {} }
local index_theme_cache = {}
--- Class constructor of `icon_theme`
-- @deprecated menubar.icon_theme.new
-- @tparam string icon_theme_name Internal name of icon theme
-- @tparam table base_directories Paths used for lookup
-- @treturn table An instance of the class `icon_theme`
icon_theme.new = function(icon_theme_name, base_directories)
icon_theme_name = icon_theme_name or beautiful.icon_theme or get_default_icon_theme_name()
base_directories = base_directories or get_pragmatic_base_directories()
local self = {}
self.icon_theme_name = icon_theme_name
self.base_directories = base_directories
self.extensions = { "png", "svg", "xpm" }
-- Instantiate index_theme (cached).
if not index_theme_cache[self.icon_theme_name] then
index_theme_cache[self.icon_theme_name] = {}
end
local cache_key = table.concat(self.base_directories, ':')
if not index_theme_cache[self.icon_theme_name][cache_key] then
index_theme_cache[self.icon_theme_name][cache_key] = index_theme(
self.icon_theme_name,
self.base_directories)
end
self.index_theme = index_theme_cache[self.icon_theme_name][cache_key]
return setmetatable(self, { __index = icon_theme })
end
local directory_matches_size = function(self, subdirectory, icon_size)
local kind, size, min_size, max_size, threshold = self.index_theme:get_per_directory_keys(subdirectory)
if kind == "Fixed" then
return icon_size == size
elseif kind == "Scalable" then
return icon_size >= min_size and icon_size <= max_size
elseif kind == "Threshold" then
return icon_size >= size - threshold and icon_size <= size + threshold
end
return false
end
local directory_size_distance = function(self, subdirectory, icon_size)
local kind, size, min_size, max_size, threshold = self.index_theme:get_per_directory_keys(subdirectory)
if kind == "Fixed" then
return math.abs(icon_size - size)
elseif kind == "Scalable" then
if icon_size < min_size then
return min_size - icon_size
elseif icon_size > max_size then
return icon_size - max_size
end
return 0
elseif kind == "Threshold" then
if icon_size < size - threshold then
return min_size - icon_size
elseif icon_size > size + threshold then
return icon_size - max_size
end
return 0
end
return 0xffffffff -- Any large number will do.
end
local lookup_icon = function(self, icon_name, icon_size)
local checked_already = {}
for _, subdir in ipairs(self.index_theme:get_subdirectories()) do
for _, basedir in ipairs(self.base_directories) do
for _, ext in ipairs(self.extensions) do
if directory_matches_size(self, subdir, icon_size) then
local filename = string.format("%s/%s/%s/%s.%s",
basedir, self.icon_theme_name, subdir,
icon_name, ext)
if gfs.file_readable(filename) then
return filename
else
checked_already[filename] = true
end
end
end
end
end
local minimal_size = 0xffffffff -- Any large number will do.
local closest_filename = nil
for _, subdir in ipairs(self.index_theme:get_subdirectories()) do
local dist = directory_size_distance(self, subdir, icon_size)
if dist < minimal_size then
for _, basedir in ipairs(self.base_directories) do
for _, ext in ipairs(self.extensions) do
local filename = string.format("%s/%s/%s/%s.%s",
basedir, self.icon_theme_name, subdir,
icon_name, ext)
if not checked_already[filename] then
if gfs.file_readable(filename) then
closest_filename = filename
minimal_size = dist
end
end
end
end
end
end
return closest_filename
end
local find_icon_path_helper -- Gets called recursively.
find_icon_path_helper = function(self, icon_name, icon_size)
local filename = lookup_icon(self, icon_name, icon_size)
if filename then
return filename
end
for _, parent in ipairs(self.index_theme:get_inherits()) do
local parent_icon_theme = icon_theme(parent, self.base_directories)
filename = find_icon_path_helper(parent_icon_theme, icon_name, icon_size)
if filename then
return filename
end
end
return nil
end
local lookup_fallback_icon = function(self, icon_name)
for _, dir in ipairs(self.base_directories) do
for _, ext in ipairs(self.extensions) do
local filename = string.format("%s/%s.%s",
dir,
icon_name, ext)
if gfs.file_readable(filename) then
return filename
end
end
end
return nil
end
--- Look up an image file based on a given icon name and/or a preferable size.
-- @deprecated menubar.icon_theme:find_icon_path
-- @tparam string icon_name Icon name to be looked up
-- @tparam number icon_size Prefereable icon size
-- @treturn string Absolute path to the icon file, or nil if not found
function icon_theme:find_icon_path(icon_name, icon_size)
icon_size = icon_size or 16
if not icon_name or icon_name == "" then
return nil
end
local filename = find_icon_path_helper(self, icon_name, icon_size)
if filename then
return filename
end
if self.icon_theme_name ~= "hicolor" then
filename = find_icon_path_helper(icon_theme("hicolor", self.base_directories), icon_name, icon_size)
if filename then
return filename
end
end
return lookup_fallback_icon(self, icon_name)
end
icon_theme.mt.__call = function(_, ...)
return icon_theme.new(...)
end
return setmetatable(icon_theme, icon_theme.mt)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

168
menubar/index_theme.lua Normal file
View File

@ -0,0 +1,168 @@
---------------------------------------------------------------------------
--- (Deprecated) class module for parsing an index.theme file
--
-- @author Kazunobu Kuriyama
-- @copyright 2015 Kazunobu Kuriyama
-- @classmod menubar.index_theme
---------------------------------------------------------------------------
-- This implementation is based on the specifications:
-- Icon Theme Specification 0.12
-- http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-0.12.html
local ipairs = ipairs
local setmetatable = setmetatable
local string = string
local table = table
local io = io
-- index.theme groups
local ICON_THEME = "Icon Theme"
-- index.theme keys
local DIRECTORIES = "Directories"
local INHERITS = "Inherits"
-- per-directory subkeys
local TYPE = "Type"
local SIZE = "Size"
local MINSIZE = "MinSize"
local MAXSIZE = "MaxSize"
local THRESHOLD = "Threshold"
local index_theme = { mt = {} }
--- Class constructor of `index_theme`
-- @deprecated menubar.index_theme.new
-- @tparam table cls Metatable that will be used. Should always be `index_theme.mt`.
-- @tparam string icon_theme_name Internal name of icon theme
-- @tparam table base_directories Paths used for lookup
-- @treturn table An instance of the class `index_theme`
index_theme.new = function(cls, icon_theme_name, base_directories)
local self = {}
setmetatable(self, { __index = cls })
-- Initialize the fields
self.icon_theme_name = icon_theme_name
self.base_directory = nil
self[DIRECTORIES] = {}
self[INHERITS] = {}
self.per_directory_keys = {}
-- base_directory
local basedir = nil
local handler = nil
for _, dir in ipairs(base_directories) do
basedir = dir .. "/" .. self.icon_theme_name
handler = io.open(basedir .. "/index.theme", "r")
if handler then
-- Use the index.theme which is found first.
break
end
end
if not handler then
return self
end
self.base_directory = basedir
-- Parse index.theme.
while true do
local line = handler:read()
if not line then
break
end
local group_header = "^%[(.+)%]$"
local group = line:match(group_header)
if group then
if group == ICON_THEME then
while true do
local item = handler:read()
if not item then
break
end
if item:match(group_header) then
handler:seek("cur", -string.len(item) - 1)
break
end
local k, v = item:match("^(%w+)=(.*)$")
if k == DIRECTORIES or k == INHERITS then
string.gsub(v, "([^,]+),?", function(match)
table.insert(self[k], match)
end)
end
end
else
-- This must be a 'per-directory keys' group
local keys = {}
while true do
local item = handler:read()
if not item then
break
end
if item:match(group_header) then
handler:seek("cur", -string.len(item) - 1)
break
end
local k, v = item:match("^(%w+)=(%w+)$")
if k == SIZE or k == MINSIZE or k == MAXSIZE or k == THRESHOLD then
keys[k] = tonumber(v)
elseif k == TYPE then
keys[k] = v
end
end
-- Size is a must. Other keys are optional.
if keys[SIZE] then
-- Set unset keys to the default values.
if not keys[TYPE] then keys[TYPE] = THRESHOLD end
if not keys[MINSIZE] then keys[MINSIZE] = keys[SIZE] end
if not keys[MAXSIZE] then keys[MAXSIZE] = keys[SIZE] end
if not keys[THRESHOLD] then keys[THRESHOLD] = 2 end
self.per_directory_keys[group] = keys
end
end
end
end
handler:close()
return self
end
--- Table of the values of the `Directories` key
-- @deprecated menubar.index_theme:get_subdirectories
-- @treturn table Values of the `Directories` key
index_theme.get_subdirectories = function(self)
return self[DIRECTORIES]
end
--- Table of the values of the `Inherits` key
-- @deprecated menubar.index_theme:get_inherits
-- @treturn table Values of the `Inherits` key
index_theme.get_inherits = function(self)
return self[INHERITS]
end
--- Query (part of) per-directory keys of a given subdirectory name.
-- @deprecated menubar.index_theme:get_per_directory_keys
-- @tparam table subdirectory Icon theme's subdirectory
-- @treturn string Value of the `Type` key
-- @treturn number Value of the `Size` key
-- @treturn number VAlue of the `MinSize` key
-- @treturn number Value of the `MaxSize` key
-- @treturn number Value of the `Threshold` key
function index_theme:get_per_directory_keys(subdirectory)
local keys = self.per_directory_keys[subdirectory]
return keys[TYPE], keys[SIZE], keys[MINSIZE], keys[MAXSIZE], keys[THRESHOLD]
end
index_theme.mt.__call = function(cls, icon_theme_name, base_directories)
return index_theme.new(cls, icon_theme_name, base_directories)
end
return setmetatable(index_theme, index_theme.mt)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

601
menubar/init.lua Normal file
View File

@ -0,0 +1,601 @@
---------------------------------------------------------------------------
--- Menubar module, which aims to provide a freedesktop menu alternative.
--
-- List of menubar keybindings:
-- ---
--
-- <table class='widget_list' border=1>
-- <tr style='font-weight: bold;'>
-- <th align='center'>Keybinding</th>
-- <th align='center'>Description</th>
-- </tr> </td></tr>
-- <tr><td><kbd>Left</kbd><kbd>C-j</kbd></td><td> select an item on the left </td></tr>
-- <tr><td><kbd>Right</kbd><kbd>C-k</kbd></td><td> select an item on the right </td></tr>
-- <tr><td><kbd>Backspace </kbd></td><td> exit the current category if we are in any </td></tr>
-- <tr><td><kbd>Escape </kbd></td><td> exit the current directory or exit menubar </td></tr>
-- <tr><td><kbd>Home </kbd></td><td> select the first item </td></tr>
-- <tr><td><kbd>End </kbd></td><td> select the last </td></tr>
-- <tr><td><kbd>Return </kbd></td><td> execute the entry </td></tr>
-- <tr><td><kbd>C-Return </kbd></td><td> execute the command with awful.spawn </td></tr>
-- <tr><td><kbd>C-M-Return </kbd></td><td> execute the command in a terminal </td></tr>
-- </table>
--
-- @author Alexander Yakushev &lt;yakushev.alex@gmail.com&gt;
-- @copyright 2011-2012 Alexander Yakushev
-- @popupmod menubar
---------------------------------------------------------------------------
-- Grab environment we need
local capi = {
client = client,
mouse = mouse,
screen = screen
}
local gmath = require("gears.math")
local awful = require("awful")
local gfs = require("gears.filesystem")
local common = require("awful.widget.common")
local theme = require("beautiful")
local wibox = require("wibox")
local gcolor = require("gears.color")
local gstring = require("gears.string")
local gdebug = require("gears.debug")
local function get_screen(s)
return s and capi.screen[s]
end
--- Menubar normal text color.
-- @beautiful beautiful.menubar_fg_normal
-- @param color
--- Menubar normal background color.
-- @beautiful beautiful.menubar_bg_normal
-- @param color
--- Menubar border width.
-- @beautiful beautiful.menubar_border_width
-- @tparam[opt=0] number menubar_border_width
--- Menubar border color.
-- @beautiful beautiful.menubar_border_color
-- @param color
--- Menubar selected item text color.
-- @beautiful beautiful.menubar_fg_focus
-- @param color
--- Menubar selected item background color.
-- @beautiful beautiful.menubar_bg_focus
-- @param color
--- Menubar font.
-- @beautiful beautiful.menubar_font
-- @param[opt=beautiful.font] font
-- menubar
local menubar = { menu_entries = {} }
menubar.menu_gen = require("menubar.menu_gen")
menubar.utils = require("menubar.utils")
local current_page = {}
-- Options section
--- When true the .desktop files will be reparsed only when the
-- extension is initialized. Use this if menubar takes much time to
-- open.
-- @tfield[opt=true] boolean cache_entries
menubar.cache_entries = true
--- When true the categories will be shown alongside application
-- entries.
-- @tfield[opt=true] boolean show_categories
menubar.show_categories = true
--- When false will hide results if the current query is empty
-- @tfield[opt=true] boolean match_empty
menubar.match_empty = true
--- Specifies the geometry of the menubar. This is a table with the keys
-- x, y, width and height. Missing values are replaced via the screen's
-- geometry. However, missing height is replaced by the font size.
-- @table geometry
-- @tfield number geometry.x A forced horizontal position
-- @tfield number geometry.y A forced vertical position
-- @tfield number geometry.width A forced width
-- @tfield number geometry.height A forced height
menubar.geometry = { width = nil,
height = nil,
x = nil,
y = nil }
--- Width of blank space left in the right side.
-- @tfield number right_margin
menubar.right_margin = theme.xresources.apply_dpi(8)
--- Label used for "Next page", default "▶▶".
-- @tfield[opt="▶▶"] string right_label
menubar.right_label = "▶▶ "
--- Label used for "Previous page", default "◀◀".
-- @tfield[opt="◀◀"] string left_label
menubar.left_label = "◀◀ "
-- awful.widget.common.list_update adds spacing of dpi(4) between items.
-- @tfield number list_spacing
local list_spacing = theme.xresources.apply_dpi(4)
--- Allows user to specify custom parameters for prompt.run function
-- (like colors). This will merge with the default parameters, overriding affected values.
-- @see awful.prompt
menubar.prompt_args = {}
-- Private section
local current_item = 1
local previous_item = nil
local current_category = nil
local shownitems = nil
local instance = nil
local common_args = { w = wibox.layout.fixed.vertical(),
data = setmetatable({}, { __mode = 'kv' }) }
--- Wrap the text with the color span tag.
-- @param s The text.
-- @param c The desired text color.
-- @return the text wrapped in a span tag.
local function colortext(s, c)
return "<span color='" .. gcolor.ensure_pango_color(c) .. "'>" .. s .. "</span>"
end
--- Get how the menu item should be displayed.
-- @param o The menu item.
-- @return item name, item background color, background image, item icon, item args.
local function label(o)
local fg_color = theme.menubar_fg_normal or theme.menu_fg_normal or theme.fg_normal
local bg_color = theme.menubar_bg_normal or theme.menu_bg_normal or theme.bg_normal
if o.focused then
fg_color = theme.menubar_fg_focus or theme.menu_fg_focus or theme.fg_focus
bg_color = theme.menubar_bg_focus or theme.menu_bg_focus or theme.bg_focus
end
return colortext(gstring.xml_escape(o.name), fg_color),
bg_color,
nil,
o.icon,
o.icon and {icon_size=20} -- TODO: dirty fix
end
local function load_count_table()
if instance.count_table then
return instance.count_table
end
instance.count_table = {}
local count_file_name = gfs.get_cache_dir() .. "/menu_count_file"
local count_file = io.open (count_file_name, "r")
if count_file then
for line in count_file:lines() do
local name, count = string.match(line, "([^;]+);([^;]+)")
if name ~= nil and count ~= nil then
instance.count_table[name] = count
end
end
count_file:close()
end
return instance.count_table
end
local function write_count_table(count_table)
count_table = count_table or instance.count_table
local count_file_name = gfs.get_cache_dir() .. "/menu_count_file"
local count_file = assert(io.open(count_file_name, "w"))
for name, count in pairs(count_table) do
local str = string.format("%s;%d\n", name, count)
count_file:write(str)
end
count_file:close()
end
--- Perform an action for the given menu item.
-- @param o The menu item.
-- @return if the function processed the callback, new awful.prompt command, new awful.prompt prompt text.
local function perform_action(o)
if not o then return end
if o.key then
current_category = o.key
local new_prompt = shownitems[current_item].name .. ": "
previous_item = current_item
current_item = 1
return true, "", new_prompt
elseif shownitems[current_item].cmdline then
awful.spawn(shownitems[current_item].cmdline)
-- load count_table from cache file
local count_table = load_count_table()
-- increase count
local curname = shownitems[current_item].name
count_table[curname] = (count_table[curname] or 0) + 1
-- write updated count table to cache file
write_count_table(count_table)
-- Let awful.prompt execute dummy exec_callback and
-- done_callback to stop the keygrabber properly.
return false
end
end
-- Cut item list to return only current page.
-- @tparam table all_items All items list.
-- @tparam str query Search query.
-- @tparam number|screen scr Screen
-- @return table List of items for current page.
local function get_current_page(all_items, query, scr)
local compute_text_width = function(text, s)
return wibox.widget.textbox.get_markup_geometry(text, s, instance.font)['width']
end
scr = get_screen(scr)
if not instance.prompt.width then
instance.prompt.width = compute_text_width(instance.prompt.prompt, scr)
end
if not menubar.left_label_width then
menubar.left_label_width = compute_text_width(menubar.left_label, scr)
end
if not menubar.right_label_width then
menubar.right_label_width = compute_text_width(menubar.right_label, scr)
end
local border_width = theme.menubar_border_width or theme.menu_border_width or 0
--local available_space = instance.geometry.width - menubar.right_margin -
-- menubar.right_label_width - menubar.left_label_width -
-- compute_text_width(query..' ', scr) - instance.prompt.width - border_width * 2
-- space character is added as input cursor placeholder
local extra_width = menubar.left_label_width
local subtracted = false
local item_height = 24
local available_space = menubar.geometry.height - item_height * 2 -- TODO: dirty fix
local width_sum = 0
current_page = {}
for i, item in ipairs(all_items) do
item.width = item.width or (
compute_text_width(label(item), scr) +
(item.icon and (item_height + list_spacing) or 0)
) -- TODO: 20 = dirty fix
local total_height = item_height * math.floor(item.width / menubar.geometry.width + 1)
if width_sum + total_height > available_space then -- TODO: 20 = dirty fix
if current_item < i then
table.insert(current_page, { name = menubar.right_label, ncon = nil })
break
end
current_page = { { name = menubar.left_label, icon = nil }, item, }
width_sum = total_height * 2 -- TODO: 20 = dirty fix
else
table.insert(current_page, item)
width_sum = width_sum + total_height -- TODO: 20 = dirty fix
end
end
return current_page
end
--- Update the menubar according to the command entered by user.
-- @tparam number|screen scr Screen
local function menulist_update(scr)
local query = instance.query or ""
shownitems = {}
local pattern = gstring.query_to_pattern(query)
-- All entries are added to a list that will be sorted
-- according to the priority (first) and weight (second) of its
-- entries.
-- If categories are used in the menu, we add the entries matching
-- the current query with high priority as to ensure they are
-- displayed first. Afterwards the non-category entries are added.
-- All entries are weighted according to the number of times they
-- have been executed previously (stored in count_table).
local count_table = load_count_table()
local command_list = {}
local PRIO_NONE = 0
local PRIO_CATEGORY_MATCH = 2
-- Add the categories
if menubar.show_categories then
for _, v in pairs(menubar.menu_gen.all_categories) do
v.focused = false
if not current_category and v.use then
-- check if current query matches a category
if string.match(v.name, pattern) then
v.weight = 0
v.prio = PRIO_CATEGORY_MATCH
-- get use count from count_table if present
-- and use it as weight
if string.len(pattern) > 0 and count_table[v.name] ~= nil then
v.weight = tonumber(count_table[v.name])
end
-- check for prefix match
if string.match(v.name, "^" .. pattern) then
-- increase default priority
v.prio = PRIO_CATEGORY_MATCH + 1
else
v.prio = PRIO_CATEGORY_MATCH
end
table.insert (command_list, v)
end
end
end
end
-- Add the applications according to their name and cmdline
local add_entry = function(entry)
entry.focused = false
if not current_category or entry.category == current_category then
-- check if the query matches either the name or the commandline
-- of some entry
if string.match(entry.name, pattern)
or string.match(entry.cmdline, pattern) then
entry.weight = 0
entry.prio = PRIO_NONE
-- get use count from count_table if present
-- and use it as weight
if string.len(pattern) > 0 and count_table[entry.name] ~= nil then
entry.weight = tonumber(count_table[entry.name])
end
-- check for prefix match
if string.match(entry.name, "^" .. pattern)
or string.match(entry.cmdline, "^" .. pattern) then
-- increase default priority
entry.prio = PRIO_NONE + 1
else
entry.prio = PRIO_NONE
end
table.insert (command_list, entry)
end
end
end
-- Add entries if required
if query ~= "" or menubar.match_empty then
for _, v in ipairs(menubar.menu_entries) do
add_entry(v)
end
end
local function compare_counts(a, b)
if a.prio == b.prio then
return a.weight > b.weight
end
return a.prio > b.prio
end
-- sort command_list by weight (highest first)
table.sort(command_list, compare_counts)
-- copy into showitems
shownitems = command_list
if #shownitems > 0 then
-- Insert a run item value as the last choice
table.insert(shownitems, { name = "Exec: " .. query, cmdline = query, icon = nil })
if current_item > #shownitems then
current_item = #shownitems
end
shownitems[current_item].focused = true
else
table.insert(shownitems, { name = "", cmdline = query, icon = nil })
end
common.list_update(common_args.w, nil, label,
common_args.data,
get_current_page(shownitems, query, scr))
end
--- Refresh menubar's cache by reloading .desktop files.
-- @tparam[opt] screen scr Screen.
-- @staticfct menubar.refresh
function menubar.refresh(scr)
scr = get_screen(scr or awful.screen.focused() or 1)
menubar.menu_gen.generate(function(entries)
menubar.menu_entries = entries
if instance then
menulist_update(scr)
end
end)
end
--- Awful.prompt keypressed callback to be used when the user presses a key.
-- @param mod Table of key combination modifiers (Control, Shift).
-- @param key The key that was pressed.
-- @param comm The current command in the prompt.
-- @return if the function processed the callback, new awful.prompt command, new awful.prompt prompt text.
local function prompt_keypressed_callback(mod, key, comm)
if key == "Up" or (mod.Control and key == "j") then
current_item = math.max(current_item - 1, 1)
return true
elseif key == "Down" or (mod.Control and key == "k") then
current_item = current_item + 1
return true
elseif key == "Left" or key == "Right" then
local tmp_sum = 0
local index = nil
local index_gen = function(tbl)
local idx = {}
for k,v in pairs(tbl) do
idx[v] = k
end
return idx
end
if current_page[1]["name"] == menubar.left_label then
tmp_sum = 1
if key == "Left" then
if not index then
index = index_gen(current_page)
end
tmp_sum = #current_page - index[shownitems[current_item]]
end
elseif key == "Left" then
tmp_sum = #current_page - current_item
end
tmp_sum = tmp_sum + 1
if current_page[#current_page]["name"] == menubar.right_label and key == "Right" then
if not index then
index = index_gen(current_page)
end
tmp_sum = index[shownitems[current_item]]
end
current_item = current_item + (#current_page - tmp_sum) * (key == "Right" and 1 or -1)
return true
elseif key == "BackSpace" then
if comm == "" and current_category then
current_category = nil
current_item = previous_item
return true, nil, "Run: "
end
elseif key == "Escape" then
if current_category then
current_category = nil
current_item = previous_item
return true, nil, "Run: "
end
elseif key == "Home" then
current_item = 1
return true
elseif key == "End" then
current_item = #shownitems
return true
elseif key == "Return" or key == "KP_Enter" then
if mod.Control then
current_item = #shownitems
if mod.Mod1 then
-- add a terminal to the cmdline
shownitems[current_item].cmdline = menubar.utils.terminal
.. " -e " .. shownitems[current_item].cmdline
end
end
return perform_action(shownitems[current_item])
end
return false
end
--- Show the menubar on the given screen.
-- @param[opt] scr Screen.
-- @staticfct menubar.show
function menubar.show(scr)
scr = get_screen(scr or awful.screen.focused() or 1)
local fg_color = theme.menubar_fg_normal or theme.menu_fg_normal or theme.fg_normal
local bg_color = theme.menubar_bg_normal or theme.menu_bg_normal or theme.bg_normal
local border_width = theme.menubar_border_width or theme.menu_border_width or 0
local border_color = theme.menubar_border_color or theme.menu_border_color
local font = theme.menubar_font or theme.font or "Monospace 10"
if not instance then
-- Add to each category the name of its key in all_categories
for k, v in pairs(menubar.menu_gen.all_categories) do
v.key = k
end
if menubar.cache_entries then
menubar.refresh(scr)
end
instance = {
wibox = wibox{
ontop = true,
bg = bg_color,
fg = fg_color,
border_width = border_width,
border_color = border_color,
font = font,
},
widget = common_args.w,
prompt = awful.widget.prompt(),
query = nil,
count_table = nil,
font = font,
}
local layout = wibox.layout.fixed.vertical()
layout:add(instance.prompt)
layout:add(instance.widget)
instance.wibox:set_widget(layout)
end
if instance.wibox.visible then -- Menu already shown, exit
return
elseif not menubar.cache_entries then
menubar.refresh(scr)
end
-- Set position and size
local scrgeom = scr.workarea
local geometry = menubar.geometry
instance.geometry = {x = geometry.x or scrgeom.x,
y = geometry.y or scrgeom.y,
height = geometry.height or gmath.round(theme.get_font_height(font) * 1.5),
width = (geometry.width or scrgeom.width) - border_width * 2}
instance.wibox:geometry(instance.geometry)
current_item = 1
current_category = nil
menulist_update(scr)
local default_prompt_args = {
prompt = "Run: ",
textbox = instance.prompt.widget,
completion_callback = awful.completion.shell,
history_path = gfs.get_cache_dir() .. "/history_menu",
done_callback = menubar.hide,
changed_callback = function(query)
instance.query = query
menulist_update(scr)
end,
keypressed_callback = prompt_keypressed_callback
}
awful.prompt.run(setmetatable(menubar.prompt_args, {__index=default_prompt_args}))
instance.wibox.visible = true
end
--- Hide the menubar.
-- @staticfct menubar.hide
function menubar.hide()
if instance then
instance.wibox.visible = false
instance.query = nil
end
end
--- Get a menubar wibox.
-- @tparam[opt] screen scr Screen.
-- @return menubar wibox.
-- @deprecated get
function menubar.get(scr)
gdebug.deprecate("Use menubar.show() instead", { deprecated_in = 5 })
menubar.refresh(scr)
-- Add to each category the name of its key in all_categories
for k, v in pairs(menubar.menu_gen.all_categories) do
v.key = k
end
return common_args.w
end
local mt = {}
function mt.__call(_, ...)
return menubar.get(...)
end
return setmetatable(menubar, mt)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

136
menubar/menu_gen.lua Normal file
View File

@ -0,0 +1,136 @@
---------------------------------------------------------------------------
--- Menu generation module for menubar
--
-- @author Antonio Terceiro
-- @copyright 2009, 2011-2012 Antonio Terceiro, Alexander Yakushev
-- @module menubar.menu_gen
---------------------------------------------------------------------------
-- Grab environment
local gtable = require("gears.table")
local gfilesystem = require("gears.filesystem")
local utils = require("menubar.utils")
local pairs = pairs
local ipairs = ipairs
local table = table
local menu_gen = {}
-- Options section
--- Get the path to the directories where XDG menu applications are installed.
local function get_xdg_menu_dirs()
local dirs = gfilesystem.get_xdg_data_dirs()
table.insert(dirs, 1, gfilesystem.get_xdg_data_home())
return gtable.map(function(dir) return dir .. 'applications/' end, dirs)
end
--- Specifies all directories where menubar should look for .desktop
-- files. The search is recursive.
menu_gen.all_menu_dirs = get_xdg_menu_dirs()
--- Specify the mapping of .desktop Categories section to the
-- categories in the menubar. If "use" flag is set to false then any of
-- the applications that fall only to this category will not be shown.
menu_gen.all_categories = {
multimedia = { app_type = "AudioVideo", name = "Multimedia",
icon_name = "applications-multimedia", use = true },
development = { app_type = "Development", name = "Development",
icon_name = "applications-development", use = true },
education = { app_type = "Education", name = "Education",
icon_name = "applications-science", use = true },
games = { app_type = "Game", name = "Games",
icon_name = "applications-games", use = true },
graphics = { app_type = "Graphics", name = "Graphics",
icon_name = "applications-graphics", use = true },
office = { app_type = "Office", name = "Office",
icon_name = "applications-office", use = true },
internet = { app_type = "Network", name = "Internet",
icon_name = "applications-internet", use = true },
science = { app_type = "Science", name="Science",
icon_name = "applications-science", use = true },
settings = { app_type = "Settings", name = "Settings",
icon_name = "applications-utilities", use = true },
tools = { app_type = "System", name = "System Tools",
icon_name = "applications-system", use = true },
utility = { app_type = "Utility", name = "Accessories",
icon_name = "applications-accessories", use = true }
}
--- Find icons for category entries.
-- @staticfct menubar.menu_gen.lookup_category_icons
function menu_gen.lookup_category_icons()
for _, v in pairs(menu_gen.all_categories) do
v.icon = utils.lookup_icon(v.icon_name)
end
end
--- Get category key name and whether it is used by its app_type.
-- @param app_type Application category as written in .desktop file.
-- @return category key name in all_categories, whether the category is used
local function get_category_name_and_usage_by_type(app_type)
for k, v in pairs(menu_gen.all_categories) do
if app_type == v.app_type then
return k, v.use
end
end
end
--- Generate an array of all visible menu entries.
-- @tparam function callback Will be fired when all menu entries were parsed
-- with the resulting list of menu entries as argument.
-- @tparam table callback.entries All menu entries.
-- @staticfct menubar.menu_gen.generate
function menu_gen.generate(callback)
-- Update icons for category entries
menu_gen.lookup_category_icons()
local result = {}
local unique_entries = {}
local dirs_parsed = 0
for _, dir in ipairs(menu_gen.all_menu_dirs) do
utils.parse_dir(dir, function(entries)
entries = entries or {}
for _, entry in ipairs(entries) do
-- Check whether to include program in the menu
if entry.show and entry.Name and entry.cmdline then
local unique_key = entry.Name .. '\0' .. entry.cmdline
if not unique_entries[unique_key] then
local target_category = nil
-- Check if the program falls into at least one of the
-- usable categories. Set target_category to be the id
-- of the first category it finds.
if entry.categories then
for _, category in pairs(entry.categories) do
local cat_key, cat_use =
get_category_name_and_usage_by_type(category)
if cat_key and cat_use then
target_category = cat_key
break
end
end
end
local name = utils.rtrim(entry.Name) or ""
local cmdline = utils.rtrim(entry.cmdline) or ""
local icon = entry.icon_path or nil
table.insert(result, { name = name,
cmdline = cmdline,
icon = icon,
category = target_category })
unique_entries[unique_key] = true
end
end
end
dirs_parsed = dirs_parsed + 1
if dirs_parsed == #menu_gen.all_menu_dirs then
callback(result)
end
end)
end
end
return menu_gen
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

430
menubar/utils.lua Normal file
View File

@ -0,0 +1,430 @@
---------------------------------------------------------------------------
--- Utility module for menubar
--
-- @author Antonio Terceiro
-- @copyright 2009, 2011-2012 Antonio Terceiro, Alexander Yakushev
-- @module menubar.utils
---------------------------------------------------------------------------
-- Grab environment
local table = table
local ipairs = ipairs
local string = string
local screen = screen
local gfs = require("gears.filesystem")
local theme = require("beautiful")
local lgi = require("lgi")
local gio = lgi.Gio
local glib = lgi.GLib
local w_textbox = require("wibox.widget.textbox")
local gdebug = require("gears.debug")
local protected_call = require("gears.protected_call")
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
local utils = {}
-- NOTE: This icons/desktop files module was written according to the
-- following freedesktop.org specifications:
-- Icons: http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-0.11.html
-- Desktop files: http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html
-- Options section
--- Terminal which applications that need terminal would open in.
-- @param[opt="xterm"] string
utils.terminal = 'xterm'
--- The default icon for applications that don't provide any icon in
-- their .desktop files.
local default_icon = nil
--- Name of the WM for the OnlyShowIn entry in the .desktop file.
-- @param[opt="awesome"] string
utils.wm_name = "awesome"
-- Maps keys in desktop entries to suitable getter function.
-- The order of entries is as in the spec.
-- https://standards.freedesktop.org/desktop-entry-spec/latest/ar01s05.html
local keys_getters
do
local function get_string(kf, key)
return kf:get_string("Desktop Entry", key)
end
local function get_strings(kf, key)
return kf:get_string_list("Desktop Entry", key, nil)
end
local function get_localestring(kf, key)
return kf:get_locale_string("Desktop Entry", key, nil)
end
local function get_localestrings(kf, key)
return kf:get_locale_string_list("Desktop Entry", key, nil, nil)
end
local function get_boolean(kf, key)
return kf:get_boolean("Desktop Entry", key)
end
keys_getters = {
Type = get_string,
Version = get_string,
Name = get_localestring,
GenericName = get_localestring,
NoDisplay = get_boolean,
Comment = get_localestring,
Icon = get_localestring,
Hidden = get_boolean,
OnlyShowIn = get_strings,
NotShowIn = get_strings,
DBusActivatable = get_boolean,
TryExec = get_string,
Exec = get_string,
Path = get_string,
Terminal = get_boolean,
Actions = get_strings,
MimeType = get_strings,
Categories = get_strings,
Implements = get_strings,
Keywords = get_localestrings,
StartupNotify = get_boolean,
StartupWMClass = get_string,
URL = get_string,
}
end
-- Private section
local do_protected_call, call_callback
do
-- Lua 5.1 cannot yield across a protected call. Instead of hardcoding a
-- check, we check for this problem: The following coroutine yields true on
-- success (so resume() returns true, true). On failure, pcall returns
-- false and a message, so resume() returns true, false, message.
local _, has_yieldable_pcall = coroutine.resume(coroutine.create(function()
return pcall(coroutine.yield, true)
end))
if has_yieldable_pcall then
do_protected_call = protected_call.call
call_callback = function(callback, ...)
return callback(...)
end
else
do_protected_call = function(f, ...)
return f(...)
end
call_callback = protected_call.call
end
end
local all_icon_sizes = {
'scalable',
'128x128',
'96x96',
'72x72',
'64x64',
'48x48',
'36x36',
'32x32',
'24x24',
'22x22',
'16x16'
}
--- List of supported icon exts.
local supported_icon_file_exts = { png = 1, xpm = 2, svg = 3 }
local icon_lookup_path = nil
--- Get a list of icon lookup paths.
-- @treturn table A list of directories, without trailing slash.
local function get_icon_lookup_path()
if icon_lookup_path then return icon_lookup_path end
local function ensure_args(t, paths)
if type(paths) == 'string' then paths = { paths } end
return t or {}, paths
end
local function add_if_readable(t, paths)
t, paths = ensure_args(t, paths)
for _, path in ipairs(paths) do
if gfs.dir_readable(path) then
table.insert(t, path)
end
end
return t
end
local function add_with_dir(t, paths, dir)
t, paths = ensure_args(t, paths)
dir = { nil, dir }
for _, path in ipairs(paths) do
dir[1] = path
table.insert(t, glib.build_filenamev(dir))
end
return t
end
icon_lookup_path = {}
local theme_priority = { 'hicolor' }
if theme.icon_theme then table.insert(theme_priority, 1, theme.icon_theme) end
local paths = add_with_dir({}, glib.get_home_dir(), '.icons')
add_with_dir(paths, {
glib.get_user_data_dir(), -- $XDG_DATA_HOME, typically $HOME/.local/share
unpack(glib.get_system_data_dirs()) -- $XDG_DATA_DIRS, typically /usr/{,local/}share
}, 'icons')
add_with_dir(paths, glib.get_system_data_dirs(), 'pixmaps')
local icon_theme_paths = {}
for _, theme_dir in ipairs(theme_priority) do
add_if_readable(icon_theme_paths,
add_with_dir({}, paths, theme_dir))
end
local app_in_theme_paths = {}
for _, icon_theme_directory in ipairs(icon_theme_paths) do
for _, size in ipairs(all_icon_sizes) do
table.insert(app_in_theme_paths,
glib.build_filenamev({ icon_theme_directory,
size, 'apps' }))
table.insert(app_in_theme_paths,
glib.build_filenamev({ icon_theme_directory,
size, 'categories' }))
end
end
add_if_readable(icon_lookup_path, app_in_theme_paths)
return add_if_readable(icon_lookup_path, paths)
end
--- Remove CR newline from the end of the string.
-- @param s string to trim
-- @staticfct menubar.utils.rtrim
function utils.rtrim(s)
if not s then return end
if string.byte(s, #s) == 13 then
return string.sub(s, 1, #s - 1)
end
return s
end
--- Lookup an icon in different folders of the filesystem.
-- @tparam string icon_file Short or full name of the icon.
-- @treturn string|boolean Full name of the icon, or false on failure.
-- @staticfct menubar.utils.lookup_icon_uncached
function utils.lookup_icon_uncached(icon_file)
if not icon_file or icon_file == "" then
return false
end
local icon_file_ext = icon_file:match(".+%.(.*)$")
if icon_file:sub(1, 1) == '/' and supported_icon_file_exts[icon_file_ext] then
-- If the path to the icon is absolute do not perform a lookup [nil if unsupported ext or missing]
return gfs.file_readable(icon_file) and icon_file or nil
else
-- Look for the requested file in the lookup path
for _, directory in ipairs(get_icon_lookup_path()) do
local possible_file = directory .. "/" .. icon_file
-- Check to see if file exists if requested with a valid extension
if supported_icon_file_exts[icon_file_ext] and gfs.file_readable(possible_file) then
return possible_file
else
-- Find files with any supported extension if icon specified without, eg: 'firefox'
for ext, _ in pairs(supported_icon_file_exts) do
local possible_file_new_ext = possible_file .. "." .. ext
if gfs.file_readable(possible_file_new_ext) then
return possible_file_new_ext
end
end
end
end
-- No icon found
return false
end
end
local lookup_icon_cache = {}
--- Lookup an icon in different folders of the filesystem (cached).
-- @param icon Short or full name of the icon.
-- @return full name of the icon.
-- @staticfct menubar.utils.lookup_icon
function utils.lookup_icon(icon)
if not lookup_icon_cache[icon] and lookup_icon_cache[icon] ~= false then
lookup_icon_cache[icon] = utils.lookup_icon_uncached(icon)
end
return lookup_icon_cache[icon] or default_icon
end
--- Parse a .desktop file.
-- @param file The .desktop file.
-- @return A table with file entries.
-- @staticfct menubar.utils.parse_desktop_file
function utils.parse_desktop_file(file)
local program = { show = true, file = file }
-- Parse the .desktop file.
-- We are interested in [Desktop Entry] group only.
local keyfile = glib.KeyFile()
if not keyfile:load_from_file(file, glib.KeyFileFlags.NONE) then
return nil
end
-- In case [Desktop Entry] was not found
if not keyfile:has_group("Desktop Entry") then
return nil
end
for _, key in pairs(keyfile:get_keys("Desktop Entry")) do
local getter = keys_getters[key] or function(kf, k)
return kf:get_string("Desktop Entry", k)
end
program[key] = getter(keyfile, key)
end
-- In case the (required) 'Name' entry was not found
if not program.Name or program.Name == '' then return nil end
-- Don't show program if NoDisplay attribute is true
if program.NoDisplay then
program.show = false
else
-- Only check these values is NoDisplay is true (or non-existent)
-- Only show the program if there is no OnlyShowIn attribute
-- or if it contains wm_name or wm_name is empty
if utils.wm_name ~= "" then
if program.OnlyShowIn then
program.show = false -- Assume false until found
for _, wm in ipairs(program.OnlyShowIn) do
if wm == utils.wm_name then
program.show = true
break
end
end
else
program.show = true
end
end
-- Only need to check NotShowIn if the program is being shown
if program.show and program.NotShowIn then
for _, wm in ipairs(program.NotShowIn) do
if wm == utils.wm_name then
program.show = false
break
end
end
end
end
-- Look up for a icon.
if program.Icon then
program.icon_path = utils.lookup_icon(program.Icon)
end
-- Make the variable lower-case like the rest of them
if program.Categories then
program.categories = program.Categories
end
if program.Exec then
-- Substitute Exec special codes as specified in
-- http://standards.freedesktop.org/desktop-entry-spec/1.1/ar01s06.html
if program.Name == nil then
program.Name = '['.. file:match("([^/]+)%.desktop$") ..']'
end
local cmdline = program.Exec:gsub('%%c', program.Name)
cmdline = cmdline:gsub('%%[fuFU]', '')
cmdline = cmdline:gsub('%%k', program.file)
if program.icon_path then
cmdline = cmdline:gsub('%%i', '--icon ' .. program.icon_path)
else
cmdline = cmdline:gsub('%%i', '')
end
if program.Terminal == true then
cmdline = utils.terminal .. ' -e ' .. cmdline
end
program.cmdline = cmdline
end
return program
end
--- Parse a directory with .desktop files recursively.
-- @tparam string dir_path The directory path.
-- @tparam function callback Will be fired when all the files were parsed
-- with the resulting list of menu entries as argument.
-- @tparam table callback.programs Paths of found .desktop files.
-- @staticfct menubar.utils.parse_dir
function utils.parse_dir(dir_path, callback)
local function get_readable_path(file)
return file:get_path() or file:get_uri()
end
local function parser(file, programs)
-- Except for "NONE" there is also NOFOLLOW_SYMLINKS
local query = gio.FILE_ATTRIBUTE_STANDARD_NAME .. "," .. gio.FILE_ATTRIBUTE_STANDARD_TYPE
local enum, err = file:async_enumerate_children(query, gio.FileQueryInfoFlags.NONE)
if not enum then
gdebug.print_warning(get_readable_path(file) .. ": " .. tostring(err))
return
end
local files_per_call = 100 -- Actual value is not that important
while true do
local list, enum_err = enum:async_next_files(files_per_call)
if enum_err then
gdebug.print_error(get_readable_path(file) .. ": " .. tostring(enum_err))
return
end
for _, info in ipairs(list) do
local file_type = info:get_file_type()
local file_child = enum:get_child(info)
if file_type == 'REGULAR' then
local path = file_child:get_path()
if path then
local success, program = pcall(utils.parse_desktop_file, path)
if not success then
gdebug.print_error("Error while reading '" .. path .. "': " .. program)
elseif program then
table.insert(programs, program)
end
end
elseif file_type == 'DIRECTORY' then
parser(file_child, programs)
end
end
if #list == 0 then
break
end
end
enum:async_close()
end
gio.Async.start(do_protected_call)(function()
local result = {}
parser(gio.File.new_for_path(dir_path), result)
call_callback(callback, result)
end)
end
-- luacov: disable
function utils.compute_textbox_width(textbox, s)
gdebug.deprecate("Use 'width, _ = textbox:get_preferred_size(s)' directly.", {deprecated_in=4})
s = screen[s or mouse.screen]
local w, _ = textbox:get_preferred_size(s)
return w
end
function utils.compute_text_width(text, s, font)
gdebug.deprecate("Use 'width = textbox.get_markup_geometry(text, s, font)['width']'.", {deprecated_in=4})
return w_textbox.get_markup_geometry(text, s, font)['width']
end
-- luacov: enable
return utils
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80

421
rc.lua
View File

@ -3,6 +3,7 @@
pcall(require, "luarocks.loader")
-- Standard awesome library
local capi = {awesome = awesome}
local gears = require("gears")
local awful = require("awful")
require("awful.autofocus")
@ -13,15 +14,191 @@ local beautiful = require("beautiful")
-- Notification library
local naughty = require("naughty")
local menubar = require("menubar")
local hotkeys_popup = require("awful.hotkeys_popup")
local menu_width = 200
local tmp_screen = { 1080, 1920 }
menubar.geometry = { height = tmp_screen[1], width = menu_width, x = tmp_screen[2] - menu_width }
--local hotkeys_popup = require("awful.hotkeys_popup")
local hotkeys = require("awful.hotkeys_popup");
--local hotkeys = require("awful.hotkeys_popup")
--local hotkeys_popup = hotkeys_popup.widget.new({ width = 100, height = 100 })
--hotkeys_popup.show_help = hotkeys_popup.widget.show_help
-- Enable hotkeys help widget for VIM and other apps
-- when client with a matching name is opened:
require("awful.hotkeys_popup.keys.vim")
--local cairo = require("lgi").cairo
--vim = require("awful.hotkeys_popup.keys.vim")
local my_hotkeys_popup = hotkeys.widget.new({ width = 1870, height = 1050});
local vim_rule_any = {name={"vim", "VIM"}}
for group_name, group_data in pairs({
["VIM: motion"] = { color="#009F00", rule_any=vim_rule_any },
["VIM: command"] = { color="#aFaF00", rule_any=vim_rule_any },
["VIM: command (insert)"] = { color="#cF4F40", rule_any=vim_rule_any },
["VIM: operator"] = { color="#aF6F00", rule_any=vim_rule_any },
["VIM: find"] = { color="#65cF9F", rule_any=vim_rule_any },
["VIM: scroll"] = { color="#659FdF", rule_any=vim_rule_any },
}) do
my_hotkeys_popup:add_group_rules(group_name, group_data)
end
local vim_keys = {
["VIM: motion"] = {{
modifiers = {},
keys = {
['`']="goto mark",
['0']='"hard" BOL',
['-']="prev line",
w="next word",
e="end word",
['[']=". misc",
[']']=". misc",
["'"]=". goto mk. BOL",
b="prev word",
["|"]='BOL/goto col',
["$"]='EOL',
["%"]='goto matching bracket',
["^"]='"soft" BOL',
["("]='sentence begin',
[")"]='sentence end',
["_"]='"soft" BOL down',
["+"]='next line',
W='next WORD',
E='end WORD',
['{']="paragraph begin",
['}']="paragraph end",
G='EOF/goto line',
H='move cursor to screen top',
M='move cursor to screen middle',
L='move cursor to screen bottom',
B='prev WORD',
}
}, {
modifiers = {"Ctrl"},
keys = {
u="half page up",
d="half page down",
b="page up",
f="page down",
o="prev mark",
}
}},
["VIM: operator"] = {{
modifiers = {},
keys = {
['=']="auto format",
y="yank",
d="delete",
c="change",
["!"]='external filter',
['&lt;']='unindent',
['&gt;']='indent',
}
}},
["VIM: command"] = {{
modifiers = {},
keys = {
['~']="toggle case",
q=". record macro",
r=". replace char",
u="undo",
p="paste after",
gg="go to the top of file",
gf="open file under cursor",
x="delete char",
v="visual mode",
m=". set mark",
['.']="repeat command",
["@"]='. play macro',
["&amp;"]='repeat :s',
Q='ex mode',
Y='yank line',
U='undo line',
P='paste before cursor',
D='delete to EOL',
J='join lines',
K='help',
[':']='ex cmd line',
['"']='. register spec',
ZZ='quit and save',
ZQ='quit discarding changes',
X='back-delete',
V='visual lines selection',
}
}, {
modifiers = {"Ctrl"},
keys = {
w=". window operations",
r="redo",
["["]="normal mode",
a="increase number",
x="decrease number",
g="file/cursor info",
z="suspend",
c="cancel/normal mode",
v="visual block selection",
}
}},
["VIM: command (insert)"] = {{
modifiers = {},
keys = {
i="insert mode",
o="open below",
a="append",
s="subst char",
R='replace mode',
I='insert at BOL',
O='open above',
A='append at EOL',
S='subst line',
C='change to EOL',
}
}},
["VIM: find"] = {{
modifiers = {},
keys = {
[';']="repeat t/T/f/F",
[',']="reverse t/T/f/F",
['/']=". find",
['?']='. reverse find',
n="next search match",
N='prev search match',
f=". find char",
F='. reverse find char',
t=". 'till char",
T=". reverse 'till char",
["*"]='find word under cursor',
["#"]='reverse find under cursor',
}
}},
["VIM: scroll"] = {{
modifiers = {},
keys = {
zt="scroll cursor to the top",
zz="scroll cursor to the center",
zb="scroll cursor to the bottom",
}
},{
modifiers = {"Ctrl"},
keys = {
e="scroll line up",
y="scroll line down",
}
}},
}
my_hotkeys_popup:add_hotkeys(vim_keys)
--my_hotkeys_popup.keys.vim = vim
--local cairo = require("lgi").cairo
-- My custom libs
local vicious = require("vicious")
@ -75,6 +252,7 @@ modkey = "Mod4"
-- Table of layouts to cover with awful.layout.inc, order matters.
awful.layout.layouts = {
awful.layout.suit.spiral,
awful.layout.suit.floating,
awful.layout.suit.tile,
awful.layout.suit.tile.left,
@ -82,7 +260,6 @@ awful.layout.layouts = {
awful.layout.suit.tile.top,
awful.layout.suit.fair,
awful.layout.suit.fair.horizontal,
awful.layout.suit.spiral,
awful.layout.suit.spiral.dwindle,
awful.layout.suit.max,
awful.layout.suit.max.fullscreen,
@ -97,7 +274,7 @@ awful.layout.layouts = {
-- {{{ Menu
-- Create a launcher widget and a main menu
myawesomemenu = {
{ "hotkeys", function() hotkeys_popup.show_help(nil, awful.screen.focused()) end },
{ "hotkeys", function() my_hotkeys_popup:show_help(nil, awful.screen.focused()) end },
{ "manual", terminal .. " -e man awesome" },
{ "edit config", editor_cmd .. " " .. awesome.conffile },
{ "restart", awesome.restart },
@ -119,7 +296,18 @@ menubar.utils.terminal = terminal -- Set the terminal for applications that requ
-- Keyboard map indicator and switcher
mykeyboardlayout = awful.widget.keyboardlayout()
--mykeyboardlayout.widget.forced_height = 20
--mykeyboardlayout.widget.text = mykeyboardlayout.widget.text:gsub("%s+", "")
--mykeyboardlayout.widget.forced_width = 20
local clean_textbox = function(w)
w.text = w.text:sub(2)
w.text = w.text:sub(1, -2)
end
capi.awesome.connect_signal("xkb::map_changed",
function () clean_textbox(mykeyboardlayout.widget) end)
capi.awesome.connect_signal("xkb::group_changed",
function () clean_textbox(mykeyboardlayout.widget) end)
clean_textbox(mykeyboardlayout.widget)
-- {{{ Wibar
-- Create a wibox for each screen and add it
@ -194,7 +382,7 @@ end
----
datewidget = wibox.widget.textbox()
vicious.register(datewidget, vicious.widgets.date, "%b %d, %R ")
vicious.register(datewidget, vicious.widgets.date, "%m %d %H %M %S", 1)
--memwidget = wibox.widget.textbox()
--vicious.cache(vicious.widgets.mem)
@ -204,16 +392,19 @@ vicious.register(datewidget, vicious.widgets.date, "%b %d, %R ")
batwidget = wibox.widget.progressbar()
batbox = wibox.layout.margin(
wibox.widget{ { max_value = 1, widget = batwidget,
border_width = 0.5, border_color = "#000000",
color = { type = "linear",
from = { 0, 0 },
to = { 0, 30 },
stops = { { 0, "#AECF96" },
{ 1, "#FF5656" } } } },
forced_height = 10, forced_width = 8,
direction = 'east', color = beautiful.fg_widget,
border_width = 0, border_color = "#000000",
color = "#FFFFFF",
background_color = "#000000"
},
--color = { type = "linear",
-- from = { 0, 0 },
-- to = { 0, 30 },
-- stops = { { 0, "#FFFFFF" },
-- { 1, "#000000" } } } },
forced_height = 1, forced_width = 1,
direction = 'south', color = beautiful.fg_widget,
layout = wibox.container.rotate },
1, 4, 1, 1)
0, 0, 0, 0)
-- Register battery widget
vicious.register(batwidget, vicious.widgets.bat, "$2", 1, "BAT1")
@ -269,11 +460,87 @@ awful.screen.connect_for_each_screen(function(s)
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
}
--s.mytaglist = awful.widget.taglist {
-- screen = s,
-- filter = awful.widget.taglist.filter.all,
-- buttons = taglist_buttons
--}
s.mytaglist = awful.widget.taglist {
screen = s,
filter = awful.widget.taglist.filter.all,
style = {
shape = function (cr, width, height) gears.shape.powerline(cr, width*8/10, height, height/4) end
},
layout = {
spacing = -14,
spacing_widget = {
color = '#dddddd',
shape = function (cr, width, height) gears.shape.powerline(cr, width/2, height, height/4) end,
widget = wibox.widget.separator,
},
layout = wibox.layout.fixed.horizontal
},
widget_template = {
{
{
{
{
--{
{
id = 'index_role',
font = "Indie Flower Bold 11",
widget = wibox.widget.textbox,
},
widget = wibox.container.place,
--},
--bg = '#55000044',
--shape = gears.shape.circle,
--widget = wibox.container.background,
},
layout = wibox.container.rotate,
direction = "east",
},
--{
-- {
-- id = 'icon_role',
-- widget = wibox.widget.imagebox,
-- },
-- margins = 2,
-- widget = wibox.container.margin,
--},
--{
-- id = 'text_role',
-- widget = wibox.widget.textbox,
--},
layout = wibox.layout.fixed.horizontal,
},
left = 5,
right = 9,
widget = wibox.container.margin
},
id = 'background_role',
widget = wibox.container.background,
-- Add support for hover colors and an index label
create_callback = function(self, c3, index, objects) --luacheck: no unused args
self:get_children_by_id('index_role')[1].markup = '<b>'..index..'</b>'
--self:connect_signal('mouse::enter', function()
-- if self.bg ~= '#ff000033' then
-- self.backup = self.bg
-- self.has_backup = true
-- end
-- self.bg = '#ff00ff55'
--end)
--self:connect_signal('mouse::leave', function()
-- if self.has_backup then self.bg = self.backup end
--end)
end,
--update_callback = function(self, c3, index, objects) --luacheck: no unused args
-- self:get_children_by_id('index_role')[1].markup = '<b> '..index..' </b>'
--end,
},
buttons = taglist_buttons
}
-- Create a tasklist widget
s.mytasklist = awful.widget.tasklist {
@ -283,29 +550,79 @@ awful.screen.connect_for_each_screen(function(s)
}
-- Create the wibox
s.mywibox = awful.wibar({ position = "bottom", screen = s })
s.mywibox = awful.wibar({ position = "left", screen = s })
-- Add widgets to the wibox
s.mywibox:setup {
layout = wibox.layout.align.horizontal,
{ -- Left widgets
layout = wibox.layout.fixed.horizontal,
mylauncher,
s.mytaglist,
s.mypromptbox,
},
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
wibox.widget.systray(),
memwidget,
swapwidget,
cpuwidget,
mykeyboardlayout,
datewidget,
batbox,
s.mylayoutbox,
},
layout = wibox.container.rotate,
direction = "west",
{
layout = wibox.layout.align.vertical,
{
layout = wibox.layout.constraint,
strategy = "max",
height = 18,
{
layout = wibox.layout.align.horizontal,
{ -- Left widgets
layout = wibox.layout.fixed.horizontal,
{
layout = wibox.container.rotate,
direction = "east",
mylauncher,
},
s.mytaglist,
s.mypromptbox,
},
s.mytasklist, -- Middle widget
{ -- Right widgets
layout = wibox.layout.fixed.horizontal,
wibox.widget.systray(),
memwidget,
swapwidget,
cpuwidget,
{
layout = wibox.container.rotate,
direction = "east",
mykeyboardlayout.widget,
},
{
forced_width = 1,
orientation = "vertical",
widget = wibox.widget.separator
},
{
thickness = 0,
forced_width = 6,
orientation = "vertical",
widget = wibox.widget.separator
},
{
layout = wibox.container.rotate,
direction = "east",
datewidget,
},
s.mylayoutbox,
},
},
},
{
layout = wibox.layout.constraint,
{
layout = wibox.layout.flex.horizontal,
{
layout = wibox.container.rotate,
direction = "north",
batbox,
},
{
layout = wibox.container.rotate,
direction = "south",
batbox,
}
}
}
}
}
end)
-- }}}
@ -320,7 +637,10 @@ root.buttons(gears.table.join(
-- {{{ Key bindings
globalkeys = gears.table.join(
awful.key({ modkey, }, "s", hotkeys_popup.show_help,
awful.key({ modkey, }, "s",
function ()
my_hotkeys_popup:show_help(nil, awful.screen.focused())
end,
{description="show help", group="awesome"}),
awful.key({ modkey, }, "Left", awful.tag.viewprev,
{description = "view previous", group = "tag"}),
@ -601,7 +921,7 @@ client.connect_signal("manage", function (c)
-- Set the windows at the slave,
-- i.e. put it at the end of others instead of setting it master.
-- if not awesome.startup then awful.client.setslave(c) end
c.shape = beautiful.shape
if awesome.startup
and not c.size_hints.user_position
and not c.size_hints.program_position then
@ -661,7 +981,16 @@ end)
client.connect_signal("mouse::enter", function(c)
c:emit_signal("request::activate", "mouse_enter", {raise = false})
end)
client.connect_signal("focus", function(c) c.border_color = beautiful.border_focus end)
client.connect_signal("unfocus", function(c) c.border_color = beautiful.border_normal end)
--beautiful.border_normal = "#00000055"
--beautiful.border_focus = "#00000000"
client.connect_signal("focus", function(c)
c.border_color = beautiful.border_focus
c.border_width = beautiful.border_width_focus
end)
client.connect_signal("unfocus", function(c)
c.border_color = beautiful.border_normal
c.border_width = beautiful.border_width
c.useless_gap = 0
end)
-- }}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
themes/zenburn/submenu.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 B

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

View File

@ -5,9 +5,10 @@
-- By Adrian C. (anrxc) --
----------------------------------------
local themes_path = require("gears.filesystem").get_themes_dir()
local themes_path = "/home/surferlul/.config/awesome/themes/"
local dpi = require("beautiful.xresources").apply_dpi
local beautiful = require("beautiful")
local gears = require("gears")
-- {{{ Main
local theme = {}
@ -34,9 +35,9 @@ theme.hotkeys_fg = "#EEEEFF"
theme.hotkeys_label_fg = "#111122"
theme.hotkeys_modifiers_fg = "#DD7777"
theme.hotkeys_description_font = "Indie Flower Bold 10"
theme.hotkeys_border_width = 1
theme.hotkeys_border_width = 2
theme.hotkeys_border_color = "#6f6f6f55"
theme.hotkeys_shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, 15) end
theme.menubar_bg_normal = "#11112299"
theme.menubar_fg_normal = "#FFBBBB"
theme.menubar_bg_focus = "#333344FF"
@ -48,10 +49,12 @@ theme.menu_bg_focus = "#333344FF"
theme.menu_fg_focus = "#BBBBFF"
-- {{{ Borders
theme.useless_gap = dpi(2)
theme.border_width = dpi(1)
theme.border_normal = "#6F6F6F55"
theme.border_focus = "#6F6F6F55"
theme.shape = function(cr, width, height) gears.shape.rounded_rect(cr, width, height, 4) end
theme.useless_gap = 2
theme.border_width = 2
theme.border_width_focus = 2
theme.border_normal = "#00000077" -- basically no border
theme.border_focus = "#00000000" -- slightly more lit up than the shadow
theme.border_marked = "#CC939355"
-- }}}
@ -103,7 +106,7 @@ theme.taglist_squares_unsel = themes_path .. "zenburn/taglist/squarez.png"
-- {{{ Misc
theme.awesome_icon = themes_path .. "zenburn/awesome-icon.png"
theme.menu_submenu_icon = themes_path .. "default/submenu.png"
theme.menu_submenu_icon = themes_path .. "zenburn/submenu.png"
-- }}}
-- {{{ Layout