From 9b943513d574c502dde80120a43884a83d24156e Mon Sep 17 00:00:00 2001 From: Surferlul Date: Mon, 9 Aug 2021 03:38:19 +0200 Subject: [PATCH] changed to vertical layout --- menubar/icon_theme.lua | 253 ++++++++++ menubar/index_theme.lua | 168 +++++++ menubar/init.lua | 601 +++++++++++++++++++++++ menubar/menu_gen.lua | 136 +++++ menubar/utils.lua | 430 ++++++++++++++++ rc.lua | 421 ++++++++++++++-- themes/zenburn/awesome-icon.png | Bin 0 -> 4778 bytes themes/zenburn/submenu.png | Bin 0 -> 440 bytes themes/zenburn/taglist/squarefz.png | Bin 168 -> 4815 bytes themes/zenburn/taglist/squarefz_orig.png | Bin 0 -> 168 bytes themes/zenburn/taglist/squarez.png | Bin 171 -> 4886 bytes themes/zenburn/taglist/squarez_orig.png | Bin 0 -> 171 bytes themes/zenburn/theme.lua | 19 +- 13 files changed, 1974 insertions(+), 54 deletions(-) create mode 100644 menubar/icon_theme.lua create mode 100644 menubar/index_theme.lua create mode 100644 menubar/init.lua create mode 100644 menubar/menu_gen.lua create mode 100644 menubar/utils.lua create mode 100644 themes/zenburn/awesome-icon.png create mode 100644 themes/zenburn/submenu.png create mode 100644 themes/zenburn/taglist/squarefz_orig.png create mode 100644 themes/zenburn/taglist/squarez_orig.png diff --git a/menubar/icon_theme.lua b/menubar/icon_theme.lua new file mode 100644 index 0000000..358f007 --- /dev/null +++ b/menubar/icon_theme.lua @@ -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 diff --git a/menubar/index_theme.lua b/menubar/index_theme.lua new file mode 100644 index 0000000..3ede62a --- /dev/null +++ b/menubar/index_theme.lua @@ -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 diff --git a/menubar/init.lua b/menubar/init.lua new file mode 100644 index 0000000..96445e8 --- /dev/null +++ b/menubar/init.lua @@ -0,0 +1,601 @@ +--------------------------------------------------------------------------- +--- Menubar module, which aims to provide a freedesktop menu alternative. +-- +-- List of menubar keybindings: +-- --- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +-- +--
KeybindingDescription
LeftC-j select an item on the left
RightC-k select an item on the right
Backspace exit the current category if we are in any
Escape exit the current directory or exit menubar
Home select the first item
End select the last
Return execute the entry
C-Return execute the command with awful.spawn
C-M-Return execute the command in a terminal
+-- +-- @author Alexander Yakushev <yakushev.alex@gmail.com> +-- @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 "" .. s .. "" +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 diff --git a/menubar/menu_gen.lua b/menubar/menu_gen.lua new file mode 100644 index 0000000..19fb6e7 --- /dev/null +++ b/menubar/menu_gen.lua @@ -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 diff --git a/menubar/utils.lua b/menubar/utils.lua new file mode 100644 index 0000000..9c8f283 --- /dev/null +++ b/menubar/utils.lua @@ -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 diff --git a/rc.lua b/rc.lua index 8c468fa..e3ac851 100644 --- a/rc.lua +++ b/rc.lua @@ -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', + ['<']='unindent', + ['>']='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', + ["&"]='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 = ''..index..'' + --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 = ' '..index..' ' + --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) + -- }}} diff --git a/themes/zenburn/awesome-icon.png b/themes/zenburn/awesome-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..60be4f2553646a0d9f9d96aa4024fc2f2a3b502b GIT binary patch literal 4778 zcmeHKX;f3!77h<97#ygAGO01r3PNTQl0cXelqiu=1fhj{lN-2729g^R6oe;2Wl#|Z z&??VTXmJ3RbwaUV0R;zC-m3^W;DDl11ZQej;hh9TSg(Iv>-8VW9rxM$J9~e7pPihn zz!giU;cf6Z9B!J>PY?|5=K9lgGPurvH3Z>s#vbcJ!?9pUOHis5QZybRU`a}Zfap*u z4yWtr-5t667GY{;XM}G-n*F8*6}3=(CY@aCS)<99av6(~dJ3%|>rK}eDeK<%benoA z6LKBxnb*GP-t4q1w5s@iLhZA#5dX*&_l9E$-_N*dmbr|8q`ppm?fJ$+;T+_6CHNtd~ff}-I{_wqq6$6g*Vt@xVkEJ zMdlODdH1@rc%h&T*P^8O{`xIjgXkTLk;A?HlZ=uqejK=PSQ+qWO^e%mH-~&} zO42Xv98uD3){WSxQn}LZZ^G#a0}{g<7552 z2-2CQ{w;-DOcSvFgVe4zm$NvdgQ{-|_6g|sVj5%QxwMY=KfSEDu;(-L>}H8qdh?{P zS26s-a8*~}%9fHt5u&ehTAevaGbgg>n`q`y$(r^nx3gEy38*N#b31)bWk$|D<*)fU zmXy+8vxQF1t8y!z1oqVBIHN6JP)-g6@9xO+ATed9BVJu!c6fg^wr>_s+jDn$rBk_I zDYN{{;~Qbomsgtv%bNW7OXsnYcLq_`SR@`v-E}SG`yDol66wR}Z!2QmfDRw9DzGdcXGQ#HilT*BRWZIuUAEYF) z2f~kVtJpoy?kzUmIK$l4b&>BJ#}}!>?|gH$cJCfm54}rx=XtKPjCy10R-;2w>!%W* zrpI9!*PZHI(hGfR8~jsNScLT3MZfER@hAD}v9mpccD!YGC20YKBIFG8xxzd^v6|bR z^1#7Kh=0L(QRY3zenZ!p-(K2w7uRnnvS!ksCOvRC8u(kx>GX(;fmw^P#My^}YCL;> zs!Pf_w))`FR^IPs3zKBXo}S~Gc@4zf1fR5An@eTqeD)=7v6zK&19Sr>b8G#`d!i7k z%J~4^GXJ5;P!|UpY7G$8uU2X`*@1EZgR!(leHZvFUMt}phrh;yKC_LHyGf3$KNpBm?V_jRc} zEu9}z;@93YuW!2cZExq^u%QjOD5a_>ylf38>|BSR7ejF5FQC1`y( zoV%w^35nMt7y(9NQ8|y;S6xdapb{Q&6;nhNDfvho>bFjXgsfW;Dqgo%%#jd1J@D>2 zE&z}r7(~#?;^k_tjz=`$a>27+Od%2sD%e^cF_bz$5DC z=Smb}RKhhp(qR@07PC1dx(f#(xj?QA5=3LtNU+$I4pUv&9Ga_S43to=#vr*E(L(`n zG74}c90mhMBuo;_cBPVB=&+OoOK32O#b!Vpn88Ho;~)Z5D5y#(eymq|C<%aq7<4gA zqcKQQv6Kyh)NAAQIAQZ zlIbo6bA4L4AQ(U_q_0x|V331YxO^1?VG32KLJ`j+>Rlq}Ee+*Oa34;JAF2i#N&1Q( zsre8jVfbx$3B;p@Ap*frwp>U&Jc$}gM20g0?1qQLagaO~0qc9DpgzdazepApVIefw z6(Ye1ok?;*K(Zi-3%Ic93^ogaIdoT+A&gOUwL*$%Ar;~s3nB&4fC4f^LvS!q={R0n z8;9t5qS9$3DjOW3R2G-X0f!Tn&ZSa`l#zfb`c?fQVt2~_aN=%I7}ExT-LMR_7tpOJ zqwQ*hGd+!e<7Xrnf8z`QdSa4K;&+0s3A#RsflpGNsICdRK8b-(Ql6-;{~KNSj~gCD z4*msc!FJ~6kIi{tD>NBizEptg)PLdV=e0mGMd=rz2K%R*`qRkA;aeRLnqWeaugN1* z(@Ab_ZybA5frup(c!#nti_fMG4W>@U<7OFW#8_FK^UH?gjjpn7%%(cGO|rDKw9c9) jmPA literal 0 HcmV?d00001 diff --git a/themes/zenburn/submenu.png b/themes/zenburn/submenu.png new file mode 100644 index 0000000000000000000000000000000000000000..b2778e2ebe7f632abc51257e3609992bda592a83 GIT binary patch literal 440 zcmV;p0Z0CcP)P000>X1^@s6#OZ}&00004b3#c}2nYxW zd2z8Hj+`L9UQg2LG>t}MEh2;Ea(U|nQA(kdBAd<9YPAv(`2en+Ap7$9 zJe^KwE+TKhr4wXdu~;OEA~PC|UVw8a$i8y9{L}CE<2a6=fKw-kQVQSqsaC6BA~H^r zxPwnbT!32KKwOLHy9ucHz5e6(z5ZvuS?;~(oZq?Uch5b^ z&8o1FS)x-POaaS_hI-c{|TJeUF_rZuGO{>96d4 zSv%qFi2y$rfk!BJn?ck$hPv+f_kFJY!dW*j^yNl{RzLMoWh~5TewF@`{G(l!Zo@g8 zndd#>X-Y;#wZqfS!h!P_I|JtmR{I_s)!DeV=k;=$LFc^YyuGb`mff8GgtvvpH&K2! zd@bnpBfjn4mT^n7(oFX*pBm(4ur@hjZRYZlP-pvmWW4i+=dW`ON4zfBanEH}Pe{Ns z_w}dlkIpTRu!l4vY5FsV&hnCV4k@`Mj`3qI(4YFgENF46UflE;ZAz-Ds?RFep74*C z;V(>c$GL3a!=)4C4cAi|7ukpXI{I|~r8T+D&Q=DE<$;^cM7D<&S1rUHb=g}EF0ao& zXcH$_8TPE&eMz#;ZIWS(ZI4;`o1A|gXg|{Cq2fF?6n$;ucnyq3fetlJrZ6l7h_V542%(OdXAGW-+V#lgo>B+bD4ErE!D#T=wWF2%7UaC%-IE-|nH!tKaO(DjU!4 zu!$S*L`_lnatLbuK^|GDe5wZ4^G=~UWz@u@w* zv55y<(h6}{2<$v$r9Y#)s~xE(ZOTB`%Ju9M?X>f+Elu+m#x0qauUwgVY{1-j z#=RZNB_`^~?x&r-&r;JIWt9;>UzA<-9|*2H-n-B0(Yr%q-X-6CmwhySSuwv%^-j-k zz0CIN)xwh$ie47s?;j@g_kX|nz?Lh{$m0i|^s&iq-#+fUNV|v7*0rU)7>jX9S6!`3 z{VK-ACL;%*jVWR|xzN^RCe+oHH0)aO-M%XGs!ZsW!QHN|^83^&OE*}@)@x2Bjd_ys zq_Hh^*~JRvyxG4EisYOAkocYJn%nR=DvQWQR_B~^!$R`IdnPS-Y1%VDYufkb!CSju z<8O(5e4Mu6*@TtCB2;n1`1g#v&eP7g_HuhS3cqq%+HvS^@5JA?HtJtkT~zqYE2$vb zEv4pi-5yDNeMCKD&J~vhr_=YSZr$AjvL!k6?TNr|7Q}S%DknSrlrtsJqV&gXrfbdE z9rLF)_!Tu-dB62-q2~onj+(IAZe)euiidyJy}O;Ns65e;wZU3QnNMHS$IvIA=$}7y zZ;8Y7kUm3GZ-c1x)&(+(dr5gqYwSbQ`>n>bs@9^tCi5Os3_`OL&sJHNPq8*T-ajED z!uF+ zA_CJ@ctm8(Sd7!Nwrc)uE3YoyCMvKBA ze}xK%STq(5fde!|3X|$>26?F@QeL=V<`4wv@u`bQQpuy!Q&UrEsqQp|Dvr+Ja=CPb zNoO))paHAXcr2;whett5gNb~_-t{!3m z@Ilw0N;-pv&}B0Ea0@jVkODx4CiIsU>PYaNLJ!B)iewdr2c+O~(s4M11p8pGOjaf8 z!jWKfJQ0@xRW~23jH!PoTh(wbK&{_*AWbokt!&x3u z4ol+UE@lsd63W#iD#vgw6ac3Y0LPud!kBE#19s;~xG>9;!-P3v41+N-;({7|&Baw}kcnDM20|N>XqSZtf&s*$+B^jSI#>`3&tHY3q(T*`P$crH zS_nvMsY`FjYj9Bl2{q72(`Nio&PU)$gT28mkVxo65Tr|69*PY*QKKoiMCSuNkI0niKs8;k3p_tceZ@u-?%qN0D6H+J&FzGZkHFU7q nzCA+=J4z_U}oXkrghb_P-#C7`y*paMQm7sn8e>&ZV3Ff>*$GSn|)K6uaOI7lmlr>mdKI;Vst07#f2 Aa{vGU diff --git a/themes/zenburn/taglist/squarefz_orig.png b/themes/zenburn/taglist/squarefz_orig.png new file mode 100644 index 0000000000000000000000000000000000000000..0927720449ef42f4117e0487fe6ff82b7482804e GIT binary patch literal 168 zcmeAS@N?(olHy`uVBq!ia0vp^EI=&G$P6TV-`L3kDaPU;cPEB*=VV?2IcxzwA+Fmu zD1W%W{_E4W{UGU*AirP+hi5m^K%69RcNc~ZR#^`qhqJ&VvY3H^?+6GpPSxg<1`4v5 zc>21s-{g?zlvlA&x9SH9@p-y9hHzX@{&9ezv4WAIei`$@dp5^GwlR3R`njxgN@xNA DFNrJj literal 0 HcmV?d00001 diff --git a/themes/zenburn/taglist/squarez.png b/themes/zenburn/taglist/squarez.png index 9b41c26ea753665cfd295ef36083dd55e6f4ae71..0fd3c2a6e4040beed91bc1c08fe07c691742d95b 100644 GIT binary patch literal 4886 zcmeHLXIK+i7al~A1qFQwSb%S1#Db7a8X<`UgCv@$K^9PoqE2QeFhB|^5J6Z)#kwrI z*s!3ix*&pz6;u>ORKU7?77zqc#ENa#w&LCdRD8bu`bj0CU~ujY4#!@W;JbRV=mG>;9!?Go*9Rj>WQ|s>AmVYdevSqw<3>UO zLB{&Wt0PK=dGr;3h!DdTQk$iB>Er9{li#GCtH9sA5j#xH-89(ROSmMZ_u#hNvD02# zIxM}HRp+~Qle{ErBQNH|4U^rBo6aCUcJ9D!>aaW){VUtLmKYqc|?^Scp=Y&p*_J-_b{&Z=b{L0b&l@fQTTYQ{9Ikh`ckJt+U6O8Bc*-d znRWv!?&c34=s9y@fz$G7#^QBRj4fBIWRbD;+I?+B`|DTw2@H=*r@y*1Y4?J~eQ!Dr zb8zvi&i`dZFtMY6HD!Ze%`UrwgV^@%p78YY>YWa;q)c?etfn6We^SNH&8oM2?B6fs zylUY7-Hwg5!WEA54=Z~~Vw!66LMFO$%FcT^R}}<}&n|1}TVE-p%j8inXTSR8rrn{e zD{w;Vh8fq})B2R|xttpC#Pg6tT~%lO%TX=l{Xe%jd)sE-3hv#y#A5T3GuhmcrL97J zewh2kCp>S-iMY%=C6S07>)eAIxs!j}Ui`zAlVOez>UM^gil$c)h6!AoV{2B06U`0V zv(r~m>_}s#*tIC4YRah2lE|Uzh{NtF(;YXl?pj}VE)NuTjCry;_>Q%QCF%Mfb;TK^ z`b{@&6I15+GX-x7bj|T+1Z|&B-TpV}8qw#6s zfDZ<@&WDvB+}`g>@S616F19$kqIpss3xX^b5&;20(tv=EYZ$EDjj1aIl2gJ#8Mk&g zEe~~lM9$0F%8%&plu$RCv~^s*Q>1}j`qCkX?e0O#OpmLm$UVJt!Sa2@_QmPs*Os^2 z+P1Y*hNrD1MOGTmBsg@WcGNT`&AXIOKX3b!WsYjYeQaE9+qBb9!WI%4^c72Lz0kl_ z!B5?0y|Q`wo_1m1Uk^K7kHt30g+lkucn0C9?mtCcZ+$QI_9)MDqo47ft&6?%p?v=RbO2sZLwlbuWG4*$kS!a`XX`62Eni{*yFs1XPWag}h zHh$4i_q|JoOZso!lEECkXTWb!BTtXZx!~y6>3t2Dqb_fCX)Nt8kKB`vI5KJw{X-1_6?70x+JJzT{&^TOAmgCWc zNj{COpZqljZM?Z042AJ{TnS8dAS&aFkQ1b`pidqq3Ze<6#_R>i{=!mE zC_a<*MQ$dIxtyMf0QXP0Us!*v-E0i3WHP=;jT%hpNksyRDLx-lqXfn`U$PWjl!vh7 zRBsmQLuE7Maw>w;6;zho2gNWSIpU2odq7E5Iz6I7aT62(rx5@LVS8gdjEPfObW~1d zD{zDgoV}@RE}h3i7;GOlThRkzik1LfiNyEJ$^?Z0C^-}1aalenmB+z3R5pU4RD_2h zR0ab@P#*?|%jEFPP#DS|uhuFNFr9=FiN;}#D%z|t5zhAyk_sqH8vU~*C?3%(fP;WC znNS&wpB15m5)aWMCN>!yCYQzYVX(Zx+lR^dY%~qm>Od!&Fd1|jlWo?RriBlR0mLGv zJ_P_~IjDsnpv4irS{tfX#|tQ?l*lGeb9Q^$Ard z_NFpeT#SQ($(Ez&m*_gRLZ5_aasOygDX0cCkhvQ2C^MBFUs@-{;3l5vOa_(C1)oql zhtFd28Qz|BCZA5Hz}*GIrd9p1Vqf@wIPo_nS9sH;i{J0Rszta9{`|Y`YHreu6CIlO~9uC01?{letC`p@Sg% zO4DJn+SA?z2>a-zGI5`~Ha5M<4ylD#f`F*6ROBCOa}AwMwg#gSkVT`l{XuXANyUMp J;&HRn{|0DsNxuL9 delta 103 zcmbQHwwiH*ga#us0|P_v8#_55#aJBV?!>U}oXkrghb_P-#C7|I%XjXa+3V!9ck%`y z3*(y{@|+6Hhc++00aPI9>Eal|aXtCR0Ru)3dxHn83~6f2jHS<)=>jDgJYD@<);T3K F0RW|;AuIp@ diff --git a/themes/zenburn/taglist/squarez_orig.png b/themes/zenburn/taglist/squarez_orig.png new file mode 100644 index 0000000000000000000000000000000000000000..9b41c26ea753665cfd295ef36083dd55e6f4ae71 GIT binary patch literal 171 zcmeAS@N?(olHy`uVBq!ia0vp^EI=&G$P6TV-`L3kDaPU;cPEB*=VV?2IcxzwA+Fmu zT)uPX%w8v-y&&n5AirP+hi5m^K%69RcNc~ZR#^`qhqJ&VvY3H^?+6GpPSxg<1`4v5 zc>21s-{g?zRA4@|dFc(Hkf5iFV+hCf9bP0 Hl+XkKo;)j; literal 0 HcmV?d00001 diff --git a/themes/zenburn/theme.lua b/themes/zenburn/theme.lua index 75fdee7..0adfaca 100644 --- a/themes/zenburn/theme.lua +++ b/themes/zenburn/theme.lua @@ -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