Merge branch 'master' into fixes

This commit is contained in:
contribuewwt 2021-11-15 18:35:30 +05:30 committed by GitHub
commit 165a230b0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 2481 additions and 376 deletions

View File

@ -1,8 +1,8 @@
package = "bling" package = "bling"
version = "scm-5" version = "dev-1"
source = { source = {
url = "git://github.com/Nooo37/bling", url = "git://github.com/BlingCorp/bling",
branch = "master", branch = "master",
} }
@ -13,7 +13,7 @@ description = {
flash focus, tabbing, a simple tiling wallpaper generator, a declarative flash focus, tabbing, a simple tiling wallpaper generator, a declarative
wallpaper setter, window swallowing and a playerctl signal. wallpaper setter, window swallowing and a playerctl signal.
]], ]],
homepage = "https://github.com/Nooo37/bling", homepage = "https://github.com/BlingCorp/bling",
license = "MIT", license = "MIT",
} }
@ -25,30 +25,39 @@ build = {
type = "builtin", type = "builtin",
modules = { modules = {
["bling"] = "init.lua", ["bling"] = "init.lua",
["bling.layout"] = "layout/init.lua",
["bling.layout.centered"] = "layout/centered.lua",
["bling.layout.equalarea"] = "layout/equalarea.lua",
["bling.layout.horizontal"] = "layout/horizontal.lua",
["bling.layout.mstab"] = "layout/mstab.lua",
["bling.layout.vertical"] = "layout/vertical.lua",
["bling.helpers"] = "helpers/init.lua", ["bling.helpers"] = "helpers/init.lua",
["bling.helpers.client"] = "helpers/client.lua", ["bling.helpers.client"] = "helpers/client.lua",
["bling.helpers.color"] = "helpers/color.lua", ["bling.helpers.color"] = "helpers/color.lua",
["bling.helpers.filesystem"] = "helpers/filesystem.lua", ["bling.helpers.filesystem"] = "helpers/filesystem.lua",
["bling.helpers.shape"] = "helpers/shape.lua", ["bling.helpers.shape"] = "helpers/shape.lua",
["bling.helpers.time"] = "helpers/time.lua", ["bling.helpers.time"] = "helpers/time.lua",
["bling.layout"] = "layout/init.lua",
["bling.layout.centered"] = "layout/centered.lua",
["bling.layout.deck"] = "layout/deck.lua",
["bling.layout.equalarea"] = "layout/equalarea.lua",
["bling.layout.horizontal"] = "layout/horizontal.lua",
["bling.layout.mstab"] = "layout/mstab.lua",
["bling.layout.vertical"] = "layout/vertical.lua",
["bling.module"] = "module/init.lua", ["bling.module"] = "module/init.lua",
["bling.module.flash_focus"] = "module/flash_focus.lua", ["bling.module.flash_focus"] = "module/flash_focus.lua",
["bling.module.scratchpad"] = "module/scratchpad.lua",
["bling.module.tabbed"] = "module/tabbed.lua", ["bling.module.tabbed"] = "module/tabbed.lua",
["bling.module.tiled_wallpaper"] = "module/tiled_wallpaper.lua", ["bling.module.tiled_wallpaper"] = "module/tiled_wallpaper.lua",
["bling.module.wallpaper"] = "module/wallpaper.lua", ["bling.module.wallpaper"] = "module/wallpaper.lua",
["bling.module.window_swallowing"] = "module/window_swallowing.lua", ["bling.module.window_swallowing"] = "module/window_swallowing.lua",
["bling.signal"] = "signal/init.lua", ["bling.signal"] = "signal/init.lua",
["bling.signal.playerctl"] = "signal/playerctl.lua", ["bling.signal.playerctl"] = "signal/playerctl/init.lua",
["bling.signal.playerctl.playerctl_cli"] = "signal/playerctl/playerctl_cli.lua",
["bling.signal.playerctl.playerctl_lib"] = "signal/playerctl/playerctl_lib.lua",
["bling.widget"] = "widget/init.lua",
["bling.widget.tabbar.boxes"] = "widget/tabbar/boxes.lua", ["bling.widget.tabbar.boxes"] = "widget/tabbar/boxes.lua",
["bling.widget.tabbar.default"] = "widget/tabbar/default.lua", ["bling.widget.tabbar.default"] = "widget/tabbar/default.lua",
["bling.widget.tabbar.modern"] = "widget/tabbar/modern.lua", ["bling.widget.tabbar.modern"] = "widget/tabbar/modern.lua",
["bling.widget.tabbed_misc"] = "widget/tabbed_misc/init.lua",
["bling.widget.tabbed_misc.custom_tasklist"] = "widget/tabbed_misc/custom_tasklist.lua",
["bling.widget.tabbed_misc.titlebar_indicator"] = "widget/tabbed_misc/titlebar_indicator.lua",
["bling.widget.tag_preview"] = "widget/tag_preview.lua", ["bling.widget.tag_preview"] = "widget/tag_preview.lua",
["bling.widget"] = "widget/init.lua", ["bling.widget.task_preview"] = "widget/task_preview.lua",
["bling.widget.window_switcher"] = "widget/window_switcher.lua",
}, },
} }

View File

@ -17,6 +17,7 @@
- [Tag Preview](widgets/tag_preview.md) - [Tag Preview](widgets/tag_preview.md)
- [Task Preview](widgets/task_preview.md) - [Task Preview](widgets/task_preview.md)
- [Tabbed Misc](widgets/tabbed_misc.md) - [Tabbed Misc](widgets/tabbed_misc.md)
- [Window Switcher](widgets/window_switcher.md)
- Extra - Extra
- [Theme Variable Template](theme.md) - [Theme Variable Template](theme.md)

View File

@ -6,7 +6,7 @@ Everyone of them supports multiple master clients and master width factor making
The mstab layout uses the tab theme from the tabbed module. The mstab layout uses the tab theme from the tabbed module.
```Lua ```lua
bling.layout.mstab bling.layout.mstab
bling.layout.centered bling.layout.centered
bling.layout.vertical bling.layout.vertical
@ -16,6 +16,7 @@ bling.layout.deck
``` ```
### Theme Variables ### Theme Variables
```lua ```lua
-- mstab -- mstab
theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients
@ -36,16 +37,19 @@ theme.mstab_tabbar_style = "default" -- style of the tabbar ("default", "
### Previews ### Previews
#### Mstab (dynamic tabbing layout) #### Mstab (dynamic tabbing layout)
![](https://imgur.com/HZRgApE.png) ![](https://imgur.com/HZRgApE.png)
*screenshot by [javacafe](https://github.com/JavaCafe01)* *screenshot by [JavaCafe01](https://github.com/JavaCafe01)*
#### Centered #### Centered
![](https://media.discordapp.net/attachments/769673106842845194/780095998239834142/unknown.png) ![](https://media.discordapp.net/attachments/769673106842845194/780095998239834142/unknown.png)
*screenshot by [branwright](https://github.com/branwright1)* *screenshot by [HeavyRain266](https://github.com/HeavyRain266)*
#### Equal area #### Equal area
![](https://imgur.com/JCFFywv.png) ![](https://imgur.com/JCFFywv.png)
*screenshot by [bysmutheye](https://github.com/bysmutheye)* *screenshot by [bysmutheye](https://github.com/bysmutheye)*
@ -56,4 +60,5 @@ The left area shows the deck layout in action. In this screenshot it is used tog
![](https://cdn.discordapp.com/attachments/635625954219261982/877957824225894430/unknown.png) ![](https://cdn.discordapp.com/attachments/635625954219261982/877957824225894430/unknown.png)
*screenshot by [javacafe](https://github.com/JavaCafe01)* *screenshot by [JavaCafe01](https://github.com/JavaCafe01)*

View File

@ -30,6 +30,10 @@ theme.tabbar_bg_normal = "#000000" -- background color of the focused c
theme.tabbar_fg_normal = "#ffffff" -- foreground color of the focused client on the tabbar theme.tabbar_fg_normal = "#ffffff" -- foreground color of the focused client on the tabbar
theme.tabbar_bg_focus = "#1A2026" -- background color of unfocused clients on the tabbar theme.tabbar_bg_focus = "#1A2026" -- background color of unfocused clients on the tabbar
theme.tabbar_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar theme.tabbar_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar
theme.tabbar_bg_focus_inactive = nil -- background color of the focused client on the tabbar when inactive
theme.tabbar_fg_focus_inactive = nil -- foreground color of the focused client on the tabbar when inactive
theme.tabbar_bg_normal_inactive = nil -- background color of unfocused clients on the tabbar when inactive
theme.tabbar_fg_normal_inactive = nil -- foreground color of unfocused clients on the tabbar when inactive
theme.tabbar_disable = false -- disable the tab bar entirely theme.tabbar_disable = false -- disable the tab bar entirely
-- the following variables are currently only for the "modern" tabbar style -- the following variables are currently only for the "modern" tabbar style
@ -44,7 +48,7 @@ Modern theme:
<img src="https://imgur.com/omowmIQ.png" width="600"/> <img src="https://imgur.com/omowmIQ.png" width="600"/>
*screenshot by [javacafe](https://github.com/JavaCafe01)* *screenshot by [JavaCafe01](https://github.com/JavaCafe01)*
### Signals ### Signals
The tabbed module emits a few signals for the purpose of integration, The tabbed module emits a few signals for the purpose of integration,

View File

@ -23,3 +23,4 @@ end)
![](https://media.discordapp.net/attachments/702548913999314964/773887721294135296/tiled-wallpapers.png?width=1920&height=1080) ![](https://media.discordapp.net/attachments/702548913999314964/773887721294135296/tiled-wallpapers.png?width=1920&height=1080)
*screenshots by [Nooo37](https://github.com/Nooo37)* *screenshots by [Nooo37](https://github.com/Nooo37)*

View File

@ -35,6 +35,11 @@ theme.tabbar_bg_normal = "#000000" -- background color of the focused c
theme.tabbar_fg_normal = "#ffffff" -- foreground color of the focused client on the tabbar theme.tabbar_fg_normal = "#ffffff" -- foreground color of the focused client on the tabbar
theme.tabbar_bg_focus = "#1A2026" -- background color of unfocused clients on the tabbar theme.tabbar_bg_focus = "#1A2026" -- background color of unfocused clients on the tabbar
theme.tabbar_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar theme.tabbar_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar
theme.tabbar_bg_focus_inactive = nil -- background color of the focused client on the tabbar when inactive
theme.tabbar_fg_focus_inactive = nil -- foreground color of the focused client on the tabbar when inactive
theme.tabbar_bg_normal_inactive = nil -- background color of unfocused clients on the tabbar when inactive
theme.tabbar_fg_normal_inactive = nil -- foreground color of unfocused clients on the tabbar when inactive
theme.tabbar_disable = false -- disable the tab bar entirely
-- mstab -- mstab
theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients
@ -87,4 +92,25 @@ theme.bling_tabbed_misc_titlebar_indicator = {
end, end,
layout = wibox.layout.fixed.horizontal layout = wibox.layout.fixed.horizontal
} }
-- window switcher widget
theme.window_switcher_widget_bg = "#000000" -- The bg color of the widget
theme.window_switcher_widget_border_width = 3 -- The border width of the widget
theme.window_switcher_widget_border_radius = 0 -- The border radius of the widget
theme.window_switcher_widget_border_color = "#ffffff" -- The border color of the widget
theme.window_switcher_clients_spacing = 20 -- The space between each client item
theme.window_switcher_client_icon_horizontal_spacing = 5 -- The space between client icon and text
theme.window_switcher_client_width = 150 -- The width of one client widget
theme.window_switcher_client_height = 250 -- The height of one client widget
theme.window_switcher_client_margins = 10 -- The margin between the content and the border of the widget
theme.window_switcher_thumbnail_margins = 10 -- The margin between one client thumbnail and the rest of the widget
theme.thumbnail_scale = false -- If set to true, the thumbnails fit policy will be set to "fit" instead of "auto"
theme.window_switcher_name_margins = 10 -- The margin of one clients title to the rest of the widget
theme.window_switcher_name_valign = "center" -- How to vertically align one clients title
theme.window_switcher_name_forced_width = 200 -- The width of one title
theme.window_switcher_name_font = "sans 11" -- The font of all titles
theme.window_switcher_name_normal_color = "#ffffff" -- The color of one title if the client is unfocused
theme.window_switcher_name_focus_color = "#ff0000" -- The color of one title if the client is focused
theme.window_switcher_icon_valign = "center" -- How to vertically align the one icon
theme.window_switcher_icon_width = 40 -- The width of one icon
``` ```

View File

@ -18,8 +18,8 @@ To use the task list indicator:
bling.widget.tabbed_misc.titlebar_indicator(client, { bling.widget.tabbed_misc.titlebar_indicator(client, {
layout = wibox.layout.fixed.vertical, layout = wibox.layout.fixed.vertical,
layout_spacing = dpi(5), -- Set spacing in between items layout_spacing = dpi(5), -- Set spacing in between items
icon_size = dpi(24), icon_size = dpi(24), -- Set icon size
icon_margin = 0, icon_margin = 0, -- Set icon margin
fg_color = "#cccccc", -- Normal color for text fg_color = "#cccccc", -- Normal color for text
fg_color_focus = "#ffffff", -- Color for focused text fg_color_focus = "#ffffff", -- Color for focused text
bg_color_focus = "#282828", -- Color for the focused items bg_color_focus = "#282828", -- Color for the focused items

View File

@ -2,7 +2,7 @@
This is a popup widget that will show a preview of a specified tag that illustrates the position, size, content, and icon of all clients. This is a popup widget that will show a preview of a specified tag that illustrates the position, size, content, and icon of all clients.
![](https://imgur.com/3nYe1e8.gif) ![](https://imgur.com/zFdvs4K.gif)
*gif by [javacafe](https://github.com/JavaCafe01)* *gif by [javacafe](https://github.com/JavaCafe01)*
@ -25,7 +25,13 @@ bling.widget.tag_preview.enable {
left = 30 left = 30
} }
}) })
end end,
background_widget = wibox.widget { -- Set a background image (like a wallpaper) for the widget
image = beautiful.wallpaper,
horizontal_fit_policy = "fit",
vertical_fit_policy = "fit",
widget = wibox.widget.imagebox
}
} }
``` ```
@ -132,6 +138,7 @@ s.mytaglist = awful.widget.taglist {
``` ```
### Theme Variables ### Theme Variables
```lua ```lua
theme.tag_preview_widget_border_radius = 0 -- Border radius of the widget (With AA) theme.tag_preview_widget_border_radius = 0 -- Border radius of the widget (With AA)
theme.tag_preview_client_border_radius = 0 -- Border radius of each client in the widget (With AA) theme.tag_preview_client_border_radius = 0 -- Border radius of each client in the widget (With AA)

View File

@ -49,9 +49,9 @@ bling.widget.task_preview.enable {
widget = awful.widget.clienticon, -- The client icon widget = awful.widget.clienticon, -- The client icon
}, },
{ {
id = 'name_role' -- The client name / title id = 'name_role', -- The client name / title
widget = wibox.widget.textbox, widget = wibox.widget.textbox,
} },
layout = wibox.layout.flex.horizontal layout = wibox.layout.flex.horizontal
}, },
widget = wibox.container.margin, widget = wibox.container.margin,

View File

@ -0,0 +1,64 @@
## 🎨 Window Switcher <!-- {docsify-ignore} -->
A popup with client previews that allows you to switch clients similar to the alt-tab menu in MacOS, GNOME, and Windows.
![](https://user-images.githubusercontent.com/70270606/133311802-8aef1012-346f-4f4c-843d-10d9de54ffeb.png)
*image by [No37](https://github.com/Nooo37)*
### Usage
To enable:
```lua
bling.widget.window_switcher.enable {
type = "thumbnail", -- set to anything other than "thumbnail" to disable client previews
-- keybindings (the examples provided are also the default if kept unset)
hide_window_switcher_key = "Escape", -- The key on which to close the popup
minimize_key = "n", -- The key on which to minimize the selected client
unminimize_key = "N", -- The key on which to unminimize all clients
kill_client_key = "q", -- The key on which to close the selected client
cycle_key = "Tab", -- The key on which to cycle through all clients
previous_key = "Left", -- The key on which to select the previous client
next_key = "Right", -- The key on which to select the next client
vim_previous_key = "h", -- Alternative key on which to select the previous client
vim_next_key = "l", -- Alternative key on which to select the next client
}
```
To run the window swicher you have to emit this signal from within your configuration (usually using a keybind).
```lua
awesome.emit_signal("bling::window_switcher::turn_on")
```
For example:
```lua
awful.key({Mod1}, "Tab", function()
awesome.emit_signal("bling::window_switcher::turn_on")
end, {description = "Window Switcher", group = "bling"})
```
### Theme Variables
```lua
theme.window_switcher_widget_bg = "#000000" -- The bg color of the widget
theme.window_switcher_widget_border_width = 3 -- The border width of the widget
theme.window_switcher_widget_border_radius = 0 -- The border radius of the widget
theme.window_switcher_widget_border_color = "#ffffff" -- The border color of the widget
theme.window_switcher_clients_spacing = 20 -- The space between each client item
theme.window_switcher_client_icon_horizontal_spacing = 5 -- The space between client icon and text
theme.window_switcher_client_width = 150 -- The width of one client widget
theme.window_switcher_client_height = 250 -- The height of one client widget
theme.window_switcher_client_margins = 10 -- The margin between the content and the border of the widget
theme.window_switcher_thumbnail_margins = 10 -- The margin between one client thumbnail and the rest of the widget
theme.thumbnail_scale = false -- If set to true, the thumbnails fit policy will be set to "fit" instead of "auto"
theme.window_switcher_name_margins = 10 -- The margin of one clients title to the rest of the widget
theme.window_switcher_name_valign = "center" -- How to vertically align one clients title
theme.window_switcher_name_forced_width = 200 -- The width of one title
theme.window_switcher_name_font = "sans 11" -- The font of all titles
theme.window_switcher_name_normal_color = "#ffffff" -- The color of one title if the client is unfocused
theme.window_switcher_name_focus_color = "#ff0000" -- The color of one title if the client is focused
theme.window_switcher_icon_valign = "center" -- How to vertically align the one icon
theme.window_switcher_icon_width = 40 -- The width of one icon
```

View File

@ -1,3 +1,12 @@
local tonumber = tonumber
local string = string
local math = math
local floor = math.floor
local max = math.max
local min = math.min
local abs = math.abs
local format = string.format
local _color = {} local _color = {}
--- Try to guess if a color is dark or light. --- Try to guess if a color is dark or light.
@ -13,6 +22,14 @@ function _color.is_dark(color)
return (numeric_value < 383) return (numeric_value < 383)
end end
function _color.is_opaque(color)
if type(color) == "string" then
color = _color.hex_to_rgba(color)
end
return color.a < 0.01
end
--- Lighten a color. --- Lighten a color.
-- --
-- @string color The color to lighten with hexadecimal HTML format `"#RRGGBB"`. -- @string color The color to lighten with hexadecimal HTML format `"#RRGGBB"`.
@ -49,4 +66,93 @@ function _color.darken(color, amount)
return _color.lighten(color, -amount) return _color.lighten(color, -amount)
end end
-- Returns a value that is clipped to interval edges if it falls outside the interval
function _color.clip(num, min_num, max_num)
return max(min(num, max_num), min_num)
end
-- Converts the given hex color to rgba
function _color.hex_to_rgba(color)
color = color:gsub("#", "")
return { r = tonumber("0x" .. color:sub(1, 2)),
g = tonumber("0x" .. color:sub(3, 4)),
b = tonumber("0x" .. color:sub(5, 6)),
a = #color == 8 and tonumber("0x" .. color:sub(7, 8)) or 255 }
end
-- Converts the given rgba color to hex
function _color.rgba_to_hex(color)
local r = _color.clip(color.r or color[1], 0, 255)
local g = _color.clip(color.g or color[2], 0, 255)
local b = _color.clip(color.b or color[3], 0, 255)
local a = _color.clip(color.a or color[4] or 255, 0, 255)
return "#" .. format("%02x%02x%02x%02x",
floor(r),
floor(g),
floor(b),
floor(a))
end
-- Converts the given hex color to hsv
function _color.hex_to_hsv(color)
local color = _color.hex2rgb(color)
local C_max = max(color.r, color.g, color.b)
local C_min = min(color.r, color.g, color.b)
local delta = C_max - C_min
local H, S, V
if delta == 0 then
H = 0
elseif C_max == color.r then
H = 60 * (((color.g - color.b) / delta) % 6)
elseif C_max == color.g then
H = 60 * (((color.b - color.r) / delta) + 2)
elseif C_max == color.b then
H = 60 * (((color.r - color.g) / delta) + 4)
end
if C_max == 0 then
S = 0
else
S = delta / C_max
end
V = C_max
return { h = H,
s = S * 100,
v = V * 100 }
end
-- Converts the given hsv color to hex
function _color.hsv_to_hex(H, S, V)
S = S / 100
V = V / 100
if H > 360 then H = 360 end
if H < 0 then H = 0 end
local C = V * S
local X = C * (1 - abs(((H / 60) % 2) - 1))
local m = V - C
local r_, g_, b_ = 0, 0, 0
if H >= 0 and H < 60 then
r_, g_, b_ = C, X, 0
elseif H >= 60 and H < 120 then
r_, g_, b_ = X, C, 0
elseif H >= 120 and H < 180 then
r_, g_, b_ = 0, C, X
elseif H >= 180 and H < 240 then
r_, g_, b_ = 0, X, C
elseif H >= 240 and H < 300 then
r_, g_, b_ = X, 0, C
elseif H >= 300 and H < 360 then
r_, g_, b_ = C, 0, X
end
local r, g, b = (r_ + m) * 255, (g_ + m) * 255, (b_ + m) * 255
return ("#%02x%02x%02x"):format(floor(r), floor(g), floor(b))
end
function _color.multiply(color, amount)
return { _color.clip(color.r * amount, 0, 255),
_color.clip(color.g * amount, 0, 255),
_color.clip(color.b * amount, 0, 255),
255 }
end
return _color return _color

134
helpers/icon_theme.lua Normal file
View File

@ -0,0 +1,134 @@
local Gio = require("lgi").Gio
local Gtk = require("lgi").Gtk
local gobject = require("gears.object")
local gtable = require("gears.table")
local helpers = require("helpers")
local setmetatable = setmetatable
local ipairs = ipairs
local icon_theme = { mt = {} }
function icon_theme:get_client_icon_path(client)
local function find_icon(class)
if self._private.client_icon_cache[class] ~= nil then
return self._private.client_icon_cache[class]
end
for _, app in ipairs(Gio.AppInfo.get_all()) do
local id = Gio.AppInfo.get_id(app)
if id:match(helpers.misc.case_insensitive_pattern(class)) then
self._private.client_icon_cache[class] = self:get_gicon_path(Gio.AppInfo.get_icon(app))
return self._private.client_icon_cache[class]
end
end
return nil
end
local class = client.class
if class == "jetbrains-studio" then
class = "android-studio"
end
local icon = self:get_icon_path("gnome-window-manager")
if class ~= nil then
class = class:gsub("[%-]", "%%%0")
icon = find_icon(class) or icon
class = client.class
class = class:gsub("[%-]", "")
icon = find_icon(class) or icon
class = client.class
class = class:gsub("[%-]", ".")
icon = find_icon(class) or icon
class = client.class
class = class:match("(.-)-") or class
class = class:match("(.-)%.") or class
class = class:match("(.-)%s+") or class
class = class:gsub("[%-]", "%%%0")
icon = find_icon(class) or icon
end
return icon
end
function icon_theme:choose_icon(icons_names)
local icon_info = Gtk.IconTheme.choose_icon(self.gtk_theme, icons_names, self.icon_size, 0);
if icon_info then
local icon_path = Gtk.IconInfo.get_filename(icon_info)
if icon_path then
return icon_path
end
end
return ""
end
function icon_theme:get_gicon_path(gicon)
if gicon == nil then
return ""
end
if self._private.icon_cache[gicon] ~= nil then
return self._private.icon_cache[gicon]
end
local icon_info = Gtk.IconTheme.lookup_by_gicon(self.gtk_theme, gicon, self.icon_size, 0);
if icon_info then
local icon_path = Gtk.IconInfo.get_filename(icon_info)
if icon_path then
self._private.icon_cache[gicon] = icon_path
return icon_path
end
end
return ""
end
function icon_theme:get_icon_path(icon_name)
if self._private.icon_cache[icon_name] ~= nil then
return self._private.icon_cache[icon_name]
end
local icon_info = Gtk.IconTheme.lookup_icon(self.gtk_theme, icon_name, self.icon_size, 0);
if icon_info then
local icon_path = Gtk.IconInfo.get_filename(icon_info)
if icon_path then
self._private.icon_cache[icon_name] = icon_path
return icon_path
end
end
return ""
end
local function new(theme_name, icon_size)
local ret = gobject{}
gtable.crush(ret, icon_theme, true)
ret._private = {}
ret._private.client_icon_cache = {}
ret._private.icon_cache = {}
ret.name = theme_name or nil
ret.icon_size = icon_size or 48
if theme_name then
ret.gtk_theme = Gtk.IconTheme.new()
Gtk.IconTheme.set_custom_theme(ret.gtk_theme, theme_name);
else
ret.gtk_theme = Gtk.IconTheme.get_default()
end
return ret
end
function icon_theme.mt:__call(...)
return new(...)
end
return setmetatable(icon_theme, icon_theme.mt)

View File

@ -1,7 +1,4 @@
local awful = require("awful") local awful = require("awful")
local gears = require("gears")
local gcolor = require("gears.color")
local beautiful = require("beautiful")
local math = math local math = math
local mylayout = {} local mylayout = {}
@ -58,6 +55,7 @@ function mylayout.arrange(p)
-- iterate through slaves -- iterate through slaves
for idx = 1, nslaves do -- idx=nmaster+1,#p.clients do for idx = 1, nslaves do -- idx=nmaster+1,#p.clients do
local c = p.clients[idx + nmaster] local c = p.clients[idx + nmaster]
local g
if idx % 2 == 0 then if idx % 2 == 0 then
g = { g = {
x = area.x, x = area.x,
@ -83,20 +81,4 @@ function mylayout.arrange(p)
end end
end end
local icon_raw = gears.filesystem.get_configuration_dir() return mylayout
.. tostring(...):match("^.*bling"):gsub("%.", "/")
.. "/icons/layouts/centered.png"
local function get_icon()
if icon_raw ~= nil then
return gcolor.recolor_image(icon_raw, beautiful.fg_normal)
else
return nil
end
end
return {
layout = mylayout,
icon_raw = icon_raw,
get_icon = get_icon,
}

View File

@ -1,8 +1,3 @@
local awful = require("awful")
local gears = require("gears")
local gcolor = require("gears.color")
local beautiful = require("beautiful")
local mylayout = {} local mylayout = {}
mylayout.name = "deck" mylayout.name = "deck"
@ -39,20 +34,4 @@ function mylayout.arrange(p)
end end
end end
local icon_raw = gears.filesystem.get_configuration_dir() return mylayout
.. tostring(...):match("^.*bling"):gsub("%.", "/")
.. "/icons/layouts/deck.png"
local function get_icon()
if icon_raw ~= nil then
return gcolor.recolor_image(icon_raw, beautiful.fg_normal)
else
return nil
end
end
return {
layout = mylayout,
icon_raw = icon_raw,
get_icon = get_icon,
}

View File

@ -1,6 +1,3 @@
local gears = require("gears")
local gcolor = require("gears.color")
local beautiful = require("beautiful")
local math = math local math = math
local screen = screen local screen = screen
local mylayout = {} local mylayout = {}
@ -77,20 +74,4 @@ function mylayout.arrange(p)
divide(p, g, 1, #cls, cls, mwfact, mcount) divide(p, g, 1, #cls, cls, mwfact, mcount)
end end
local icon_raw = gears.filesystem.get_configuration_dir() return mylayout
.. tostring(...):match("^.*bling"):gsub("%.", "/")
.. "/icons/layouts/equalarea.png"
local function get_icon()
if icon_raw ~= nil then
return gcolor.recolor_image(icon_raw, beautiful.fg_normal)
else
return nil
end
end
return {
layout = mylayout,
icon_raw = icon_raw,
get_icon = get_icon,
}

View File

@ -1,7 +1,3 @@
local awful = require("awful")
local gears = require("gears")
local gcolor = require("gears.color")
local beautiful = require("beautiful")
local math = math local math = math
local mylayout = {} local mylayout = {}
@ -57,20 +53,4 @@ function mylayout.arrange(p)
end end
end end
local icon_raw = gears.filesystem.get_configuration_dir() return mylayout
.. tostring(...):match("^.*bling"):gsub("%.", "/")
.. "/icons/layouts/horizontal.png"
local function get_icon()
if icon_raw ~= nil then
return gcolor.recolor_image(icon_raw, beautiful.fg_normal)
else
return nil
end
end
return {
layout = mylayout,
icon_raw = icon_raw,
get_icon = get_icon,
}

View File

@ -1,30 +1,44 @@
local beautiful = require("beautiful") local beautiful = require("beautiful")
local gears = require("gears")
local mstab = require(... .. ".mstab") local M = {}
beautiful.layout_mstab = mstab.get_icon() local relative_lua_path = tostring(...)
local vertical = require(... .. ".vertical") local function get_layout_icon_path(name)
beautiful.layout_vertical = vertical.get_icon() local relative_icon_path = relative_lua_path
:match("^.*bling"):gsub("%.", "/")
.. "/icons/layouts/" .. name .. ".png"
local horizontal = require(... .. ".horizontal") for p in package.path:gmatch('([^;]+)') do
beautiful.layout_horizontal = horizontal.get_icon() p = p:gsub("?.*", "")
local absolute_icon_path = p .. relative_icon_path
if gears.filesystem.file_readable(absolute_icon_path) then
return absolute_icon_path
end
end
end
local centered = require(... .. ".centered") local function get_icon(icon_raw)
beautiful.layout_centered = centered.get_icon() if icon_raw ~= nil then
return gears.color.recolor_image(icon_raw, beautiful.fg_normal)
else
return nil
end
end
local equalarea = require(... .. ".equalarea") local layouts = {
beautiful.layout_equalarea = equalarea.get_icon() "mstab",
"vertical",
local deck = require(... .. ".deck") "horizontal",
beautiful.layout_deck = deck.get_icon() "centered",
"equalarea",
local layout = { "deck"
mstab = mstab.layout,
centered = centered.layout,
vertical = vertical.layout,
horizontal = horizontal.layout,
equalarea = equalarea.layout,
deck = deck.layout,
} }
return layout for _, layout_name in ipairs(layouts) do
local icon_raw = get_layout_icon_path(layout_name)
beautiful["layout_" .. layout_name] = get_icon(icon_raw)
M[layout_name] = require(... .. "." .. layout_name)
end
return M

View File

@ -1,7 +1,6 @@
local awful = require("awful") local awful = require("awful")
local gears = require("gears") local gears = require("gears")
local wibox = require("wibox") local wibox = require("wibox")
local gcolor = require("gears.color")
local beautiful = require("beautiful") local beautiful = require("beautiful")
local mylayout = {} local mylayout = {}
@ -242,16 +241,4 @@ function mylayout.arrange(p)
) )
end end
local icon_raw = gears.filesystem.get_configuration_dir() return mylayout
.. tostring(...):match("^.*bling"):gsub("%.", "/")
.. "/icons/layouts/mstab.png"
local function get_icon()
if icon_raw ~= nil then
return gcolor.recolor_image(icon_raw, beautiful.fg_normal)
else
return nil
end
end
return { layout = mylayout, icon_raw = icon_raw, get_icon = get_icon }

View File

@ -1,7 +1,3 @@
local awful = require("awful")
local gears = require("gears")
local gcolor = require("gears.color")
local beautiful = require("beautiful")
local math = math local math = math
local mylayout = {} local mylayout = {}
@ -57,20 +53,4 @@ function mylayout.arrange(p)
end end
end end
local icon_raw = gears.filesystem.get_configuration_dir() return mylayout
.. tostring(...):match("^.*bling"):gsub("%.", "/")
.. "/icons/layouts/vertical.png"
local function get_icon()
if icon_raw ~= nil then
return gcolor.recolor_image(icon_raw, beautiful.fg_normal)
else
return nil
end
end
return {
layout = mylayout,
icon_raw = icon_raw,
get_icon = get_icon,
}

View File

@ -23,6 +23,14 @@ local bar = require(
tabbed = {} tabbed = {}
-- helper function to connect to the (un)focus signals
local function update_tabbar_from(c)
if not c or not c.bling_tabbed then
return
end
tabbed.update_tabbar(c.bling_tabbed)
end
-- used to change focused tab relative to the currently focused one -- used to change focused tab relative to the currently focused one
tabbed.iter = function(idx) tabbed.iter = function(idx)
if not idx then if not idx then
@ -50,6 +58,8 @@ tabbed.remove = function(c)
awful.titlebar.hide(c, bar.position) awful.titlebar.hide(c, bar.position)
end end
c.bling_tabbed = nil c.bling_tabbed = nil
c:disconnect_signal("focus", update_tabbar_from)
c:disconnect_signal("unfocus", update_tabbar_from)
awesome.emit_signal("bling::tabbed::client_removed", tabobj, c) awesome.emit_signal("bling::tabbed::client_removed", tabobj, c)
tabbed.switch_to(tabobj, 1) tabbed.switch_to(tabobj, 1)
end end
@ -67,6 +77,8 @@ tabbed.add = function(c, tabobj)
if c.bling_tabbed then if c.bling_tabbed then
tabbed.remove(c) tabbed.remove(c)
end end
c:connect_signal("focus", update_tabbar_from)
c:connect_signal("unfocus", update_tabbar_from)
helpers.client.sync(c, tabobj.clients[tabobj.focused_idx]) helpers.client.sync(c, tabobj.clients[tabobj.focused_idx])
tabobj.clients[#tabobj.clients + 1] = c tabobj.clients[#tabobj.clients + 1] = c
tabobj.focused_idx = #tabobj.clients tabobj.focused_idx = #tabobj.clients
@ -218,12 +230,15 @@ end
tabbed.update_tabbar = function(tabobj) tabbed.update_tabbar = function(tabobj)
local flexlist = bar.layout() local flexlist = bar.layout()
local tabobj_focused_client = tabobj.clients[tabobj.focused_idx]
local tabobj_is_focused = (client.focus == tabobj_focused_client)
-- itearte over all tabbed clients to create the widget tabbed list -- itearte over all tabbed clients to create the widget tabbed list
for idx, c in ipairs(tabobj.clients) do for idx, c in ipairs(tabobj.clients) do
local buttons = gears.table.join(awful.button({}, 1, function() local buttons = gears.table.join(awful.button({}, 1, function()
tabbed.switch_to(tabobj, idx) tabbed.switch_to(tabobj, idx)
end)) end))
wid_temp = bar.create(c, (idx == tabobj.focused_idx), buttons) local wid_temp = bar.create(c, (idx == tabobj.focused_idx), buttons,
not tabobj_is_focused)
flexlist:add(wid_temp) flexlist:add(wid_temp)
end end
-- add tabbar to each tabbed client (clients will be hided anyway) -- add tabbar to each tabbed client (clients will be hided anyway)
@ -240,6 +255,8 @@ end
tabbed.init = function(c) tabbed.init = function(c)
local tabobj = {} local tabobj = {}
tabobj.clients = { c } tabobj.clients = { c }
c:connect_signal("focus", update_tabbar_from)
c:connect_signal("unfocus", update_tabbar_from)
tabobj.focused_idx = 1 tabobj.focused_idx = 1
tabbed.update(tabobj) tabbed.update(tabobj)
end end

View File

@ -36,6 +36,10 @@ theme.tabbar_bg_normal = "#000000" -- background color of the focused client on
theme.tabbar_fg_normal = "#ffffff" -- foreground color of the focused client on the tabbar theme.tabbar_fg_normal = "#ffffff" -- foreground color of the focused client on the tabbar
theme.tabbar_bg_focus = "#1A2026" -- background color of unfocused clients on the tabbar theme.tabbar_bg_focus = "#1A2026" -- background color of unfocused clients on the tabbar
theme.tabbar_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar theme.tabbar_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar
theme.tabbar_bg_focus_inactive = nil -- background color of the focused client on the tabbar when inactive
theme.tabbar_fg_focus_inactive = nil -- foreground color of the focused client on the tabbar when inactive
theme.tabbar_bg_normal_inactive = nil -- background color of unfocused clients on the tabbar when inactive
theme.tabbar_fg_normal_inactive = nil -- foreground color of unfocused clients on the tabbar when inactive
-- mstab -- mstab
theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients
@ -76,4 +80,25 @@ theme.task_preview_widget_border_color = "#ffffff" -- The border color of the wi
theme.task_preview_widget_border_width = 3 -- The border width of the widget theme.task_preview_widget_border_width = 3 -- The border width of the widget
theme.task_preview_widget_margin = 0 -- The margin of the widget theme.task_preview_widget_margin = 0 -- The margin of the widget
-- window switcher
theme.window_switcher_widget_bg = "#000000" -- The bg color of the widget
theme.window_switcher_widget_border_width = 3 -- The border width of the widget
theme.window_switcher_widget_border_radius = 0 -- The border radius of the widget
theme.window_switcher_widget_border_color = "#ffffff" -- The border color of the widget
theme.window_switcher_clients_spacing = 20 -- The space between each client item
theme.window_switcher_client_icon_horizontal_spacing = 5 -- The space between client icon and text
theme.window_switcher_client_width = 150 -- The width of one client widget
theme.window_switcher_client_height = 250 -- The height of one client widget
theme.window_switcher_client_margins = 10 -- The margin between the content and the border of the widget
theme.window_switcher_thumbnail_margins = 10 -- The margin between one client thumbnail and the rest of the widget
theme.thumbnail_scale = false -- If set to true, the thumbnails fit policy will be set to "fit" instead of "auto"
theme.window_switcher_name_margins = 10 -- The margin of one clients title to the rest of the widget
theme.window_switcher_name_valign = "center" -- How to vertically align one clients title
theme.window_switcher_name_forced_width = 200 -- The width of one title
theme.window_switcher_name_font = "Sans 11" -- The font of all titles
theme.window_switcher_name_normal_color = "#ffffff" -- The color of one title if the client is unfocused
theme.window_switcher_name_focus_color = "#ff0000" -- The color of one title if the client is focused
theme.window_switcher_icon_valign = "center" -- How to vertically align the one icon
theme.window_switcher_icon_width = 40 -- The width of one icon
-- LuaFormatter on -- LuaFormatter on

1053
widget/app_launcher/init.lua Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,656 @@
---------------------------------------------------------------------------
--- Modified Prompt module.
-- @author Julien Danjou &lt;julien@danjou.info&gt;
-- @copyright 2008 Julien Danjou
---------------------------------------------------------------------------
local akey = require("awful.key")
local keygrabber = require("awful.keygrabber")
local gobject = require("gears.object")
local gdebug = require('gears.debug')
local gtable = require("gears.table")
local gcolor = require("gears.color")
local gstring = require("gears.string")
local gfs = require("gears.filesystem")
local wibox = require("wibox")
local beautiful = require("beautiful")
local io = io
local table = table
local math = math
local ipairs = ipairs
local unpack = unpack or table.unpack -- luacheck: globals unpack (compatibility with Lua 5.1)
local capi = { selection = selection }
local prompt = { mt = {} }
--- Private data
local data = {}
data.history = {}
local function itera(inc,a, i)
i = i + inc
local v = a[i]
if v then return i,v end
end
local function history_check_load(id, max)
if id and id ~= "" and not data.history[id] then
data.history[id] = { max = 50, table = {} }
if max then
data.history[id].max = max
end
local f = io.open(id, "r")
if not f then return end
-- Read history file
for line in f:lines() do
if gtable.hasitem(data.history[id].table, line) == nil then
table.insert(data.history[id].table, line)
if #data.history[id].table >= data.history[id].max then
break
end
end
end
f:close()
end
end
local function is_word_char(c)
if string.find(c, "[{[(,.:;_-+=@/ ]") then
return false
else
return true
end
end
local function cword_start(s, pos)
local i = pos
if i > 1 then
i = i - 1
end
while i >= 1 and not is_word_char(s:sub(i, i)) do
i = i - 1
end
while i >= 1 and is_word_char(s:sub(i, i)) do
i = i - 1
end
if i <= #s then
i = i + 1
end
return i
end
local function cword_end(s, pos)
local i = pos
while i <= #s and not is_word_char(s:sub(i, i)) do
i = i + 1
end
while i <= #s and is_word_char(s:sub(i, i)) do
i = i + 1
end
return i
end
local function history_save(id)
if data.history[id] then
gfs.make_parent_directories(id)
local f = io.open(id, "w")
if not f then
gdebug.print_warning("Failed to write the history to "..id)
return
end
for i = 1, math.min(#data.history[id].table, data.history[id].max) do
f:write(data.history[id].table[i] .. "\n")
end
f:close()
end
end
local function history_items(id)
if data.history[id] then
return #data.history[id].table
else
return -1
end
end
local function history_add(id, command)
if data.history[id] and command ~= "" then
local index = gtable.hasitem(data.history[id].table, command)
if index == nil then
table.insert(data.history[id].table, command)
-- Do not exceed our max_cmd
if #data.history[id].table > data.history[id].max then
table.remove(data.history[id].table, 1)
end
history_save(id)
else
-- Bump this command to the end of history
table.remove(data.history[id].table, index)
table.insert(data.history[id].table, command)
history_save(id)
end
end
end
local function have_multibyte_char_at(text, position)
return text:sub(position, position):wlen() == -1
end
local function prompt_text_with_cursor(args)
local char, spacer, text_start, text_end, ret
local text = args.text or ""
local _prompt = args.prompt or ""
local underline = args.cursor_ul or "none"
if args.select_all then
if #text == 0 then char = " " else char = gstring.xml_escape(text) end
spacer = " "
text_start = ""
text_end = ""
elseif #text < args.cursor_pos then
char = " "
spacer = ""
text_start = gstring.xml_escape(text)
text_end = ""
else
local offset = 0
if have_multibyte_char_at(text, args.cursor_pos) then
offset = 1
end
char = gstring.xml_escape(text:sub(args.cursor_pos, args.cursor_pos + offset))
spacer = " "
text_start = gstring.xml_escape(text:sub(1, args.cursor_pos - 1))
text_end = gstring.xml_escape(text:sub(args.cursor_pos + 1 + offset))
end
local cursor_color = gcolor.ensure_pango_color(args.cursor_color)
local text_color = gcolor.ensure_pango_color(args.text_color)
if args.highlighter then
text_start, text_end = args.highlighter(text_start, text_end)
end
ret = _prompt .. text_start .. "<span background=\"" .. cursor_color ..
"\" foreground=\"" .. text_color .. "\" underline=\"" .. underline ..
"\">" .. char .. "</span>" .. text_end .. spacer
return ret
end
local function update(self)
self.textbox:set_font(self.font)
self.textbox:set_markup(prompt_text_with_cursor{
text = self.command, text_color = self.fg_cursor, cursor_color = self.bg_cursor,
cursor_pos = self._private_cur_pos, cursor_ul = self.ul_cursor, select_all = self.select_all,
prompt = self.prompt, highlighter = self.highlighter })
end
local function exec(self, cb, command_to_history)
self.textbox:set_markup("")
history_add(self.history_path, command_to_history)
keygrabber.stop(self._private.grabber)
if cb then cb(self.command) end
if self.done_callback then
self.done_callback()
end
end
function prompt:start()
-- The cursor position
if self.reset_on_stop == true or self._private_cur_pos == nil then
self._private_cur_pos = (self.select_all and 1) or self.text:wlen() + 1
end
if self.reset_on_stop == true then self.text = "" self.command = "" end
self.textbox:set_font(self.font)
self.textbox:set_markup(prompt_text_with_cursor{
text = self.reset_on_stop and self.text or self.command, text_color = self.fg_cursor, cursor_color = self.bg_cursor,
cursor_pos = self._private_cur_pos, cursor_ul = self.ul_cursor, select_all = self.select_all,
prompt = self.prompt, highlighter = self.highlighter})
self._private.search_term = nil
history_check_load(self.history_path, self.history_max)
local history_index = history_items(self.history_path) + 1
-- The completion element to use on completion request.
local ncomp = 1
local command_before_comp
local cur_pos_before_comp
self._private.grabber = keygrabber.run(function(modifiers, key, event)
-- Convert index array to hash table
local mod = {}
for _, v in ipairs(modifiers) do mod[v] = true end
if event ~= "press" then
if self.keyreleased_callback then
self.keyreleased_callback(mod, key, self.command)
end
return
end
-- Call the user specified callback. If it returns true as
-- the first result then return from the function. Treat the
-- second and third results as a new command and new prompt
-- to be set (if provided)
if self.keypressed_callback then
local user_catched, new_command, new_prompt =
self.keypressed_callback(mod, key, self.command)
if new_command or new_prompt then
if new_command then
self.command = new_command
end
if new_prompt then
self.prompt = new_prompt
end
update(self)
end
if user_catched then
if self.changed_callback then
self.changed_callback(self.command)
end
return
end
end
local filtered_modifiers = {}
-- User defined cases
if self.hooks[key] then
-- Remove caps and num lock
for _, m in ipairs(modifiers) do
if not gtable.hasitem(akey.ignore_modifiers, m) then
table.insert(filtered_modifiers, m)
end
end
for _,v in ipairs(self.hooks[key]) do
if #filtered_modifiers == #v[1] then
local match = true
for _,v2 in ipairs(v[1]) do
match = match and mod[v2]
end
if match then
local cb
local ret, quit = v[3](self.command)
local original_command = self.command
-- Support both a "simple" and a "complex" way to
-- control if the prompt should quit.
quit = quit == nil and (ret ~= true) or (quit~=false)
-- Allow the callback to change the command
self.command = (ret ~= true) and ret or self.command
-- Quit by default, but allow it to be disabled
if ret and type(ret) ~= "boolean" then
cb = self.exe_callback
if not quit then
self._private_cur_pos = ret:wlen() + 1
update(self)
end
elseif quit then
-- No callback.
cb = function() end
end
-- Execute the callback
if cb then
exec(self, cb, original_command)
end
return
end
end
end
end
-- Get out cases
if (mod.Control and (key == "c" or key == "g"))
or (not mod.Control and key == "Escape") then
self:stop()
return false
elseif (mod.Control and (key == "j" or key == "m"))
-- or (not mod.Control and key == "Return")
-- or (not mod.Control and key == "KP_Enter")
then
exec(self, self.exe_callback, self.command)
-- We already unregistered ourselves so we don't want to return
-- true, otherwise we may unregister someone else.
return
end
-- Control cases
if mod.Control then
self.select_all = nil
if key == "v" then
local selection = capi.selection()
if selection then
-- Remove \n
local n = selection:find("\n")
if n then
selection = selection:sub(1, n - 1)
end
self.command = self.command:sub(1, self._private_cur_pos - 1) .. selection .. self.command:sub(self._private_cur_pos)
self._private_cur_pos = self._private_cur_pos + #selection
end
elseif key == "a" then
self._private_cur_pos = 1
elseif key == "b" then
if self._private_cur_pos > 1 then
self._private_cur_pos = self._private_cur_pos - 1
if have_multibyte_char_at(self.command, self._private_cur_pos) then
self._private_cur_pos = self._private_cur_pos - 1
end
end
elseif key == "d" then
if self._private_cur_pos <= #self.command then
self.command = self.command:sub(1, self._private_cur_pos - 1) .. self.command:sub(self._private_cur_pos + 1)
end
elseif key == "p" then
if history_index > 1 then
history_index = history_index - 1
self.command = data.history[self.history_path].table[history_index]
self._private_cur_pos = #self.command + 2
end
elseif key == "n" then
if history_index < history_items(self.history_path) then
history_index = history_index + 1
self.command = data.history[self.history_path].table[history_index]
self._private_cur_pos = #self.command + 2
elseif history_index == history_items(self.history_path) then
history_index = history_index + 1
self.command = ""
self._private_cur_pos = 1
end
elseif key == "e" then
self._private_cur_pos = #self.command + 1
elseif key == "r" then
self._private.search_term = self._private.search_term or self.command:sub(1, self._private_cur_pos - 1)
for i,v in (function(a,i) return itera(-1,a,i) end), data.history[self.history_path].table, history_index do
if v:find(self._private.search_term,1,true) ~= nil then
self.command=v
history_index=i
self._private_cur_pos=#self.command+1
break
end
end
elseif key == "s" then
self._private.search_term = self._private.search_term or self.command:sub(1, self._private_cur_pos - 1)
for i,v in (function(a,i) return itera(1,a,i) end), data.history[self.history_path].table, history_index do
if v:find(self._private.search_term,1,true) ~= nil then
self.command=v
history_index=i
self._private_cur_pos=#self.command+1
break
end
end
elseif key == "f" then
if self._private_cur_pos <= #self.command then
if have_multibyte_char_at(self.command, self._private_cur_pos) then
self._private_cur_pos = self._private_cur_pos + 2
else
self._private_cur_pos = self._private_cur_pos + 1
end
end
elseif key == "h" then
if self._private_cur_pos > 1 then
local offset = 0
if have_multibyte_char_at(self.command, self._private_cur_pos - 1) then
offset = 1
end
self.command = self.command:sub(1, self._private_cur_pos - 2 - offset) .. self.command:sub(self._private_cur_pos)
self._private_cur_pos = self._private_cur_pos - 1 - offset
end
elseif key == "k" then
self.command = self.command:sub(1, self._private_cur_pos - 1)
elseif key == "u" then
self.command = self.command:sub(self._private_cur_pos, #self.command)
self._private_cur_pos = 1
elseif key == "Prior" then
self._private.search_term = self.command:sub(1, self._private_cur_pos - 1) or ""
for i,v in (function(a,i) return itera(-1,a,i) end), data.history[self.history_path].table, history_index do
if v:find(self._private.search_term,1,true) == 1 then
self.command=v
history_index=i
break
end
end
elseif key == "Next" then
self._private.search_term = self.command:sub(1, self._private_cur_pos - 1) or ""
for i,v in (function(a,i) return itera(1,a,i) end), data.history[self.history_path].table, history_index do
if v:find(self._private.search_term,1,true) == 1 then
self.command=v
history_index=i
break
end
end
elseif key == "w" or key == "BackSpace" then
local wstart = 1
local wend = 1
local cword_start_pos = 1
local cword_end_pos = 1
while wend < self._private_cur_pos do
wend = self.command:find("[{[(,.:;_-+=@/ ]", wstart)
if not wend then wend = #self.command + 1 end
if self._private_cur_pos >= wstart and self._private_cur_pos <= wend + 1 then
cword_start_pos = wstart
cword_end_pos = self._private_cur_pos - 1
break
end
wstart = wend + 1
end
self.command = self.command:sub(1, cword_start_pos - 1) .. self.command:sub(cword_end_pos + 1)
self._private_cur_pos = cword_start_pos
elseif key == "Delete" then
-- delete from history only if:
-- we are not dealing with a new command
-- the user has not edited an existing entry
if self.command == data.history[self.history_path].table[history_index] then
table.remove(data.history[self.history_path].table, history_index)
if history_index <= history_items(self.history_path) then
self.command = data.history[self.history_path].table[history_index]
self._private_cur_pos = #self.command + 2
elseif history_index > 1 then
history_index = history_index - 1
self.command = data.history[self.history_path].table[history_index]
self._private_cur_pos = #self.command + 2
else
self.command = ""
self._private_cur_pos = 1
end
end
end
elseif mod.Mod1 or mod.Mod3 then
if key == "b" then
self._private_cur_pos = cword_start(self.command, self._private_cur_pos)
elseif key == "f" then
self._private_cur_pos = cword_end(self.command, self._private_cur_pos)
elseif key == "d" then
self.command = self.command:sub(1, self._private_cur_pos - 1) .. self.command:sub(cword_end(self.command, self._private_cur_pos))
elseif key == "BackSpace" then
local wstart = cword_start(self.command, self._private_cur_pos)
self.command = self.command:sub(1, wstart - 1) .. self.command:sub(self._private_cur_pos)
self._private_cur_pos = wstart
end
else
if self.completion_callback then
if key == "Tab" or key == "ISO_Left_Tab" then
if key == "ISO_Left_Tab" or mod.Shift then
if ncomp == 1 then return end
if ncomp == 2 then
self.command = command_before_comp
self.textbox:set_font(self.font)
self.textbox:set_markup(prompt_text_with_cursor{
text = command_before_comp, text_color = self.fg_cursor, cursor_color = self.bg_cursor,
cursor_pos = self._private_cur_pos, cursor_ul = self.ul_cursor, select_all = self.select_all,
prompt = self.prompt })
self._private_cur_pos = cur_pos_before_comp
ncomp = 1
return
end
ncomp = ncomp - 2
elseif ncomp == 1 then
command_before_comp = self.command
cur_pos_before_comp = self._private_cur_pos
end
local matches
self.command, self._private_cur_pos, matches = self.completion_callback(command_before_comp, cur_pos_before_comp, ncomp)
ncomp = ncomp + 1
key = ""
-- execute if only one match found and autoexec flag set
if matches and #matches == 1 and args.autoexec then
exec(self, self.exe_callback)
return
end
elseif key ~= "Shift_L" and key ~= "Shift_R" then
ncomp = 1
end
end
-- Typin cases
if mod.Shift and key == "Insert" then
local selection = capi.selection()
if selection then
-- Remove \n
local n = selection:find("\n")
if n then
selection = selection:sub(1, n - 1)
end
self.command = self.command:sub(1, self._private_cur_pos - 1) .. selection .. self.command:sub(self._private_cur_pos)
self._private_cur_pos = self._private_cur_pos + #selection
end
elseif key == "Home" then
self._private_cur_pos = 1
elseif key == "End" then
self._private_cur_pos = #self.command + 1
elseif key == "BackSpace" then
if self._private_cur_pos > 1 then
local offset = 0
if have_multibyte_char_at(self.command, self._private_cur_pos - 1) then
offset = 1
end
self.command = self.command:sub(1, self._private_cur_pos - 2 - offset) .. self.command:sub(self._private_cur_pos)
self._private_cur_pos = self._private_cur_pos - 1 - offset
end
elseif key == "Delete" then
self.command = self.command:sub(1, self._private_cur_pos - 1) .. self.command:sub(self._private_cur_pos + 1)
elseif key == "Left" then
self._private_cur_pos = self._private_cur_pos - 1
elseif key == "Right" then
self._private_cur_pos = self._private_cur_pos + 1
elseif key == "Prior" then
if history_index > 1 then
history_index = history_index - 1
self.command = data.history[self.history_path].table[history_index]
self._private_cur_pos = #self.command + 2
end
elseif key == "Next" then
if history_index < history_items(self.history_path) then
history_index = history_index + 1
self.command = data.history[self.history_path].table[history_index]
self._private_cur_pos = #self.command + 2
elseif history_index == history_items(self.history_path) then
history_index = history_index + 1
self.command = ""
self._private_cur_pos = 1
end
else
-- wlen() is UTF-8 aware but #key is not,
-- so check that we have one UTF-8 char but advance the cursor of # position
if key:wlen() == 1 then
if self.select_all then self.command = "" end
self.command = self.command:sub(1, self._private_cur_pos - 1) .. key .. self.command:sub(self._private_cur_pos)
self._private_cur_pos = self._private_cur_pos + #key
end
end
if self._private_cur_pos < 1 then
self._private_cur_pos = 1
elseif self._private_cur_pos > #self.command + 1 then
self._private_cur_pos = #self.command + 1
end
self.select_all = nil
end
update(self)
if self.changed_callback then
self.changed_callback(self.command)
end
end)
end
function prompt:stop()
keygrabber.stop(self._private.grabber)
history_save(self.history_path)
if self.done_callback then self.done_callback() end
return false
end
local function new(args)
args = args or {}
args.command = args.text or ""
args.prompt = args.prompt or ""
args.text = args.text or ""
args.font = args.font or beautiful.prompt_font or beautiful.font
args.bg_cursor = args.bg_cursor or beautiful.prompt_bg_cursor or beautiful.bg_focus or "white"
args.fg_cursor = args.fg_cursor or beautiful.prompt_fg_cursor or beautiful.fg_focus or "black"
args.ul_cursor = args.ul_cursor or nil
args.reset_on_stop = args.reset_on_stop == nil and true or args.reset_on_stop
args.select_all = args.select_all or nil
args.highlighter = args.highlighter or nil
args.hooks = args.hooks or {}
args.keypressed_callback = args.keypressed_callback or nil
args.changed_callback = args.changed_callback or nil
args.done_callback = args.done_callback or nil
args.history_max = args.history_max or nil
args.history_path = args.history_path or nil
args.completion_callback = args.completion_callback or nil
args.exe_callback = args.exe_callback or nil
args.textbox = args.textbox or wibox.widget.textbox()
-- Build the hook map
local hooks = {}
for _,v in ipairs(args.hooks) do
if #v == 3 then
local _,key,callback = unpack(v)
if type(callback) == "function" then
hooks[key] = hooks[key] or {}
hooks[key][#hooks[key]+1] = v
else
gdebug.print_warning("The hook's 3rd parameter has to be a function.")
end
else
gdebug.print_warning("The hook has to have 3 parameters.")
end
end
args.hooks = hooks
local ret = gobject({})
ret._private = {}
gtable.crush(ret, prompt)
gtable.crush(ret, args)
return ret
end
function prompt.mt:__call(...)
return new(...)
end
return setmetatable(prompt, prompt.mt)

View File

@ -3,4 +3,5 @@ return {
task_preview = require(... .. ".task_preview"), task_preview = require(... .. ".task_preview"),
window_switcher = require(... .. ".window_switcher"), window_switcher = require(... .. ".window_switcher"),
tabbed_misc = require(... .. ".tabbed_misc"), tabbed_misc = require(... .. ".tabbed_misc"),
app_launcher = require(... .. ".app_launcher"),
} }

View File

@ -8,16 +8,20 @@ local bg_normal = beautiful.tabbar_bg_normal or beautiful.bg_normal or "#ffffff"
local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000" local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000"
local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000" local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000"
local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff" local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff"
local bg_focus_inactive = beautiful.tabbar_bg_focus_inactive or bg_focus
local fg_focus_inactive = beautiful.tabbar_fg_focus_inactive or fg_focus
local bg_normal_inactive = beautiful.tabbar_bg_normal_inactive or bg_normal
local fg_normal_inactive = beautiful.tabbar_fg_normal_inactive or fg_normal
local font = beautiful.tabbar_font or beautiful.font or "Hack 15" local font = beautiful.tabbar_font or beautiful.font or "Hack 15"
local size = beautiful.tabbar_size or 40 local size = beautiful.tabbar_size or 40
local position = beautiful.tabbar_position or "bottom" local position = beautiful.tabbar_position or "bottom"
local function create(c, focused_bool, buttons) local function create(c, focused_bool, buttons, inactive_bool)
local bg_temp = bg_normal local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
local fg_temp = fg_normal local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
if focused_bool then if focused_bool then
bg_temp = bg_focus bg_temp = inactive_bool and bg_focus_inactive or bg_focus
fg_temp = fg_focus fg_temp = inactive_bool and fg_focus_inactive or fg_focus
end end
local wid_temp = wibox.widget({ local wid_temp = wibox.widget({
{ {

View File

@ -7,18 +7,22 @@ local bg_normal = beautiful.tabbar_bg_normal or beautiful.bg_normal or "#ffffff"
local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000" local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000"
local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000" local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000"
local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff" local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff"
local bg_focus_inactive = beautiful.tabbar_bg_focus_inactive or bg_focus
local fg_focus_inactive = beautiful.tabbar_fg_focus_inactive or fg_focus
local bg_normal_inactive = beautiful.tabbar_bg_normal_inactive or bg_normal
local fg_normal_inactive = beautiful.tabbar_fg_normal_inactive or fg_normal
local font = beautiful.tabbar_font or beautiful.font or "Hack 15" local font = beautiful.tabbar_font or beautiful.font or "Hack 15"
local size = beautiful.tabbar_size or 20 local size = beautiful.tabbar_size or 20
local position = beautiful.tabbar_position or "top" local position = beautiful.tabbar_position or "top"
local function create(c, focused_bool, buttons) local function create(c, focused_bool, buttons, inactive_bool)
local flexlist = wibox.layout.flex.horizontal() local flexlist = wibox.layout.flex.horizontal()
local title_temp = c.name or c.class or "-" local title_temp = c.name or c.class or "-"
local bg_temp = bg_normal local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
local fg_temp = fg_normal local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
if focused_bool then if focused_bool then
bg_temp = bg_focus bg_temp = inactive_bool and bg_focus_inactive or bg_focus
fg_temp = fg_focus fg_temp = inactive_bool and fg_focus_inactive or fg_focus
end end
local text_temp = wibox.widget.textbox() local text_temp = wibox.widget.textbox()
text_temp.align = "center" text_temp.align = "center"

View File

@ -10,6 +10,10 @@ local bg_normal = beautiful.tabbar_bg_normal or beautiful.bg_normal or "#ffffff"
local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000" local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000"
local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000" local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000"
local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff" local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff"
local bg_focus_inactive = beautiful.tabbar_bg_focus_inactive or bg_focus
local fg_focus_inactive = beautiful.tabbar_fg_focus_inactive or fg_focus
local bg_normal_inactive = beautiful.tabbar_bg_normal_inactive or bg_normal
local fg_normal_inactive = beautiful.tabbar_fg_normal_inactive or fg_normal
local font = beautiful.tabbar_font or beautiful.font or "Hack 15" local font = beautiful.tabbar_font or beautiful.font or "Hack 15"
local size = beautiful.tabbar_size or dpi(40) local size = beautiful.tabbar_size or dpi(40)
local border_radius = beautiful.mstab_border_radius local border_radius = beautiful.mstab_border_radius
@ -66,14 +70,14 @@ local function create_title_button(c, color_focus, color_unfocus)
return tb return tb
end end
local function create(c, focused_bool, buttons) local function create(c, focused_bool, buttons, inactive_bool)
-- local flexlist = wibox.layout.flex.horizontal() -- local flexlist = wibox.layout.flex.horizontal()
local title_temp = c.name or c.class or "-" local title_temp = c.name or c.class or "-"
local bg_temp = bg_normal local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
local fg_temp = fg_normal local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
if focused_bool then if focused_bool then
bg_temp = bg_focus bg_temp = inactive_bool and bg_focus_inactive or bg_focus
fg_temp = fg_focus fg_temp = inactive_bool and fg_focus_inactive or fg_focus
end end
local text_temp = wibox.widget.textbox() local text_temp = wibox.widget.textbox()
text_temp.align = "center" text_temp.align = "center"

View File

@ -8,13 +8,21 @@ local bg_normal = beautiful.tabbar_bg_normal or beautiful.bg_normal or "#ffffff"
local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000" local fg_normal = beautiful.tabbar_fg_normal or beautiful.fg_normal or "#000000"
local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000" local bg_focus = beautiful.tabbar_bg_focus or beautiful.bg_focus or "#000000"
local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff" local fg_focus = beautiful.tabbar_fg_focus or beautiful.fg_focus or "#ffffff"
local bg_focus_inactive = beautiful.tabbar_bg_focus_inactive or bg_focus
local fg_focus_inactive = beautiful.tabbar_fg_focus_inactive or fg_focus
local bg_normal_inactive = beautiful.tabbar_bg_normal_inactive or bg_normal
local fg_normal_inactive = beautiful.tabbar_fg_normal_inactive or fg_normal
local font = beautiful.tabbar_font or beautiful.font or "Hack 15" local font = beautiful.tabbar_font or beautiful.font or "Hack 15"
local size = beautiful.tabbar_size or 20 local size = beautiful.tabbar_size or 20
local position = beautiful.tabbar_position or "top" local position = beautiful.tabbar_position or "top"
local function create(c, focused_bool, buttons) local function create(c, focused_bool, buttons, inactive_bool)
local bg_temp = focused_bool and bg_focus or bg_normal local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
local fg_temp = focused_bool and fg_focus or fg_normal local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
if focused_bool then
bg_temp = inactive_bool and bg_focus_inactive or bg_focus
fg_temp = inactive_bool and fg_focus_inactive or fg_focus
end
local wid_temp = wibox.widget({ local wid_temp = wibox.widget({
{ {

View File

@ -28,7 +28,8 @@ local function draw_widget(
widget_border_color, widget_border_color,
widget_border_width, widget_border_width,
geo, geo,
margin margin,
background_image
) )
local client_list = wibox.layout.manual() local client_list = wibox.layout.manual()
client_list.forced_height = geo.height client_list.forced_height = geo.height
@ -37,14 +38,19 @@ local function draw_widget(
for i, c in ipairs(t:clients()) do for i, c in ipairs(t:clients()) do
if not c.hidden and not c.minimized then if not c.hidden and not c.minimized then
local img_box = wibox.widget ({ local img_box = wibox.widget ({
image = gears.surface.load(c.icon),
resize = true, resize = true,
forced_height = 100 * scale, forced_height = 100 * scale,
forced_width = 100 * scale, forced_width = 100 * scale,
widget = wibox.widget.imagebox, widget = wibox.widget.imagebox,
}) })
-- If fails to set image, fallback to a awesome icon
if not pcall(function() img_box.image = gears.surface.load(c.icon) end) then
img_box.image = beautiful.theme_assets.awesome_icon (24, "#222222", "#fafafa")
end
if tag_preview_image then if tag_preview_image then
if c.prev_content or t.selected then if c.prev_content or t.selected then
local content local content
@ -108,7 +114,9 @@ local function draw_widget(
end end
end end
return { return wibox.widget {
{
background_image,
{ {
{ {
{ {
@ -125,6 +133,8 @@ local function draw_widget(
margins = margin, margins = margin,
widget = wibox.container.margin, widget = wibox.container.margin,
}, },
layout = wibox.layout.stack
},
bg = widget_bg, bg = widget_bg,
shape_border_width = widget_border_width, shape_border_width = widget_border_width,
shape_border_color = widget_border_color, shape_border_color = widget_border_color,
@ -143,6 +153,7 @@ local enable = function(opts)
local work_area = opts.honor_workarea or false local work_area = opts.honor_workarea or false
local padding = opts.honor_padding or false local padding = opts.honor_padding or false
local placement_fn = opts.placement_fn or nil local placement_fn = opts.placement_fn or nil
local background_image = opts.background_widget or nil
local margin = beautiful.tag_preview_widget_margin or dpi(0) local margin = beautiful.tag_preview_widget_margin or dpi(0)
local screen_radius = beautiful.tag_preview_widget_border_radius or dpi(0) local screen_radius = beautiful.tag_preview_widget_border_radius or dpi(0)
@ -170,9 +181,22 @@ local enable = function(opts)
}) })
tag.connect_signal("property::selected", function(t) tag.connect_signal("property::selected", function(t)
-- Awesome switches up tags on startup really fast it seems, probably depends on what rules you have set
-- which can cause the c.content to not show the correct image
gears.timer
{
timeout = 0.1,
call_now = false,
autostart = true,
single_shot = true,
callback = function()
if t.selected == true then
for _, c in ipairs(t:clients()) do for _, c in ipairs(t:clients()) do
c.prev_content = gears.surface.duplicate_surface(c.content) c.prev_content = gears.surface.duplicate_surface(c.content)
end end
end
end
}
end) end)
awesome.connect_signal("bling::tag_preview::update", function(t) awesome.connect_signal("bling::tag_preview::update", function(t)
@ -184,14 +208,24 @@ local enable = function(opts)
tag_preview_box.maximum_width = scale * geo.width + margin * 2 tag_preview_box.maximum_width = scale * geo.width + margin * 2
tag_preview_box.maximum_height = scale * geo.height + margin * 2 tag_preview_box.maximum_height = scale * geo.height + margin * 2
-- TODO: Use a table here
tag_preview_box:setup(draw_widget(t, tag_preview_image, scale, tag_preview_box.widget = draw_widget(
screen_radius, client_radius, t,
client_opacity, client_bg, tag_preview_image,
scale,
screen_radius,
client_radius,
client_opacity,
client_bg,
client_border_color, client_border_color,
client_border_width, widget_bg, client_border_width,
widget_bg,
widget_border_color, widget_border_color,
widget_border_width, geo, margin)) widget_border_width,
geo,
margin,
background_image
)
end) end)
awesome.connect_signal("bling::tag_preview::visibility", function(s, v) awesome.connect_signal("bling::tag_preview::visibility", function(s, v)
@ -200,6 +234,11 @@ local enable = function(opts)
tag_preview_box.y = s.geometry.y + widget_y tag_preview_box.y = s.geometry.y + widget_y
end end
if v == false then
tag_preview_box.widget = nil
collectgarbage("collect")
end
tag_preview_box.visible = v tag_preview_box.visible = v
end) end)
end end

View File

@ -30,14 +30,24 @@ local function draw_widget(
end) then end) then
return return
end end
local content = gears.surface(c.content)
local content = nil
if c.active then
content = gears.surface(c.content)
elseif c.prev_content then
content = gears.surface(c.prev_content)
end
local img = nil
if content ~= nil then
local cr = cairo.Context(content) local cr = cairo.Context(content)
local x, y, w, h = cr:clip_extents() local x, y, w, h = cr:clip_extents()
local img = cairo.ImageSurface.create(cairo.Format.ARGB32, w - x, h - y) img = cairo.ImageSurface.create(cairo.Format.ARGB32, w - x, h - y)
cr = cairo.Context(img) cr = cairo.Context(img)
cr:set_source_surface(content, 0, 0) cr:set_source_surface(content, 0, 0)
cr.operator = cairo.Operator.SOURCE cr.operator = cairo.Operator.SOURCE
cr:paint() cr:paint()
end
local widget = wibox.widget({ local widget = wibox.widget({
(widget_template or { (widget_template or {
@ -139,6 +149,25 @@ local enable = function(opts)
bg = "#00000000", bg = "#00000000",
}) })
tag.connect_signal("property::selected", function(t)
-- Awesome switches up tags on startup really fast it seems, probably depends on what rules you have set
-- which can cause the c.content to not show the correct image
gears.timer
{
timeout = 0.1,
call_now = false,
autostart = true,
single_shot = true,
callback = function()
if t.selected == true then
for _, c in ipairs(t:clients()) do
c.prev_content = gears.surface.duplicate_surface(c.content)
end
end
end
}
end)
awesome.connect_signal("bling::task_preview::visibility", function(s, v, c) awesome.connect_signal("bling::task_preview::visibility", function(s, v, c)
if v then if v then
-- Update task preview contents -- Update task preview contents
@ -153,6 +182,9 @@ local enable = function(opts)
widget_width, widget_width,
widget_height widget_height
) )
else
task_preview_box.widget = nil
collectgarbage("collect")
end end
if not placement_fn then if not placement_fn then

View File

@ -59,6 +59,8 @@ local window_switcher_hide = function(window_switcher_box)
-- Stop and hide window_switcher -- Stop and hide window_switcher
awful.keygrabber.stop(window_switcher_grabber) awful.keygrabber.stop(window_switcher_grabber)
window_switcher_box.visible = false window_switcher_box.visible = false
window_switcher_box.widget = nil
collectgarbage("collect")
end end
local function draw_widget( local function draw_widget(