From 9b943513d574c502dde80120a43884a83d24156e Mon Sep 17 00:00:00 2001
From: Surferlul <lukasabaumann@gmail.com>
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:
+-- ---
+--
+-- <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
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',
+            ['&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)
+ 
 -- }}}
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
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

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)<h;3K|Lk000e1NJLTq000>P000>X1^@s6#OZ}&00004b3#c}2nYxW
zd<bNS00009a7bBm000Fg000Fg0RaTRiU0rr8FWQhbW?9;ba!ELWdL_~cP?peYja~^
zaAhuUa%Y?FJQ@H10X0cPK~zY`?bWSMLQxoi@pHXypaueNCW-_j#Zk;eoW<luWRpO?
zg=(@8sWt<ZVsp3MVvqnEXX72P%K^4KJ~kcVW8xoh=QP5Te><PA0+j320kMMYcDovI
z;uJB)%(T|y>2z8Hj+`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
z<Pq?!BdJu1APCmO;c&3oZ0@YC#Pd8VmCCo)dTflT1HRSmDwRsV-EKFYOeW93nbm_Y
z6bgi4Xhh@{xUhPKbGaPtc6%-&@4%JS$C$}vXf~UPh<t9h+Z*fO%3`sYiHKgUR`)LF
i$pdhFn2ZPH-~9m+jnqF(&Qk*b0000<MNUMnLSTab-nz*E

literal 0
HcmV?d00001

diff --git a/themes/zenburn/taglist/squarefz.png b/themes/zenburn/taglist/squarefz.png
index 0927720449ef42f4117e0487fe6ff82b7482804e..a65608b927337512345e8ef03ea4f4ced250092c 100644
GIT binary patch
literal 4815
zcmeHLc~}$I77sh3A_7`OgfU<RWRgh;A&CT8f)XLX1C-@ybuyXY09i-|2q;#Ohe&-^
z5UU_c5ma1Qs#WSz6@|K>xPwnbT!32KKwOLHy9ucHz5e6(z5ZvuS?;~(oZq?Uch5b^
z&8o1FS)<Kt%_tPgXknlr9J~#|ZKZDjo@avvO%#ejQhH=G8IGnxN|i!NB;pX6ro<s!
zLr5tU&5cLv=U=|*JSw0)ropW)-@>x-POa<ojhz>aS_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$;uc<y$M{kK~OE?z9&-LcAi
zMqk!mpLs{vMkk^>nyq3fetlJrZ6l7h_V542%(OdXAGW-+V#lgo<hABqj{o`5C^z@*
z%>>B+bD4ErE!D<udfpnr)`I(p)X~p=(h{>#T=wWF2%7UaC%-IE-|nH!tKaO(DjU!4
zu!$S*<IG;CC;CBu?pTwF-KVyeW#{J3oFj_wF52%TWDv8@T;{#WT@?@!B<=d4@)r&H
zyrawBYw?+4qm^Y{1@PjggVr3lW*&0br?lYgocKMl5&OG6S}uoq!))2kn7)guX`2s|
z#a8^}2e;Jp6~?oP`clWy6TP20TWw?GzwLAvZSwAO8xwE+;y~Gx8`TkIn`{-~L6_{W
zBG(?WeIIZxHH@m~Smv}+mt}S}JXGf9o%E~SIH~ZbX$51q(KwsOGb~oGh@Q&7o{_is
z&Uo<~SiWT4$dPR&&{yLRIjrs9(rOZ)F(A7!8MTUSRZe+skvPM7{EHL&3y*KB-thd}
z{xpZBb9x_d3g!5JGkXKqt@hxpN~6;|eX>L`_lnatLbuK^|GDe5wZ4^G=~UWz@u@w*
zv55y<(h6<duh>}{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!u<X*qx9w@NB1`+{YjBjMD3h-`?iG*9RA|ag~KN|XY|)@zjn;Q$VIhy$+(R#L6Nj2
zKrxIK1@kb4jD|`SVw|RtDM7KMP`qYnlqi;flaLsXBjkMQlf%cT5Fz1HqdY{2Na>F+
zA_CJ@ctm<gB$l3laV69l-ez7J9srQxBnoL{iE=eh!>8(Sd7!Nwrc)uE3YoyCMvKBA
ze}xK%STq(5fde!|3X|$>26?F@QeL=V<`4wv@u`bQQpuy!Q&UrEsqQp|Dvr+Ja=CPb
zNoO))paHAX<Rq$r<!VPQ#2|(MS7RzdNfHV<q{T$Vie!>cr2;whett5gNb~_-t{!3m
z@Ilw0N;-pv&}B0Ea0@jVkODx4CiIsU>PYaNLJ!B)iewdr2c+O~(s4M11p8pGOjaf8
z!jWKfJQ0@xRW<O+_{8Nbp(yNwg_eRiLZ;MN0kS{QBnjz9vObxcR-y}M_(XvD2i#Az
z-^Z>~23jH!PoTh(wbK&{_*AWbo<xBW5}vNf#Za8X#XMoAC&q$VVle|oJv>kt!&x3u
z4ol+UE@lsd63W#iD#vgw6ac3Y0LPud!kBE#19s;~xG>9;!-P3v41+N-;(<yroGbR^
z4uc3)5g;qk#No5jLP-FWC(35J<ERw&5VP1Y3t@9%G0K&|2$Rc2#5kLaFj+b%3C5eL
zP{~lRoP-RG!|6(SoKB!6oaY-R<Wre6<l{(KB1%eu0iPO7$dff61(Addk04Pkn+!IS
z<IeR&I4p3v4>{7|&Baw}kcnDM20|N>XqSZtf&s*$+B^jSI#>`3&tHY3q(T*`P$crH
zS_nvMsY`FjYj9Bl2{q72(`Nio&PU)$gT28mkVxo65Tr|69*PY*QKKoiMCS<D4T`Wu
zs5}k_`+F#%-j5T1u~-aGCW|8lI}gX)nJ|lqvtcgE=D?^_Dq&%43Ca*-pQ5W3QZf})
z;l6PoQV<PDAYC+&vyMuaPqkAQ;aZ*$CIdz|;EF`pAVGLc)-;64Ll7!`C}6sFSHF+g
zi~c{Hc<B^|l>uNkI0niKs8;k3<!XpCEscNUXJ{?{Mh^h`i<8gd_X}NL==v-MK1=ya
zc737ivl#d+<uBRwf1}In<ADd4gI__Z;5c)Ke6|}Lg+_!0M+Sg*ZH;43d-at&%{8E-
zM}~()P<*<sga3^vdg7p20!oh2q(H5@GB8F>p_tceZ@u-?%qN0D6H+J&FzGZkHFU7q
nzCA+=J4z_<jWlh+7DC3L_ccYY&Di_^Xi<a#A%ZHug_-{aI(a3K

delta 100
zcmX@Fx`J_nga#us0|P_v8#_55#aJBV?!>U}oXkrghb_P-#C7`y<q!AQe|_4ve{!af
zg~3e@c}{s1`*f>*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
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
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+hCf<R1qN7&+_>9<VZ`sWCH_K3}E_lw|O9^>bP0
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