Merge branch 'master' into fixes
This commit is contained in:
commit
165a230b0a
|
@ -1,19 +1,19 @@
|
|||
package = "bling"
|
||||
version = "scm-5"
|
||||
version = "dev-1"
|
||||
|
||||
source = {
|
||||
url = "git://github.com/Nooo37/bling",
|
||||
url = "git://github.com/BlingCorp/bling",
|
||||
branch = "master",
|
||||
}
|
||||
|
||||
description = {
|
||||
summary = "Utilities for the AwesomeWM",
|
||||
detailed = [[
|
||||
This module extends the Awesome window manager with alternative layouts,
|
||||
flash focus, tabbing, a simple tiling wallpaper generator, a declarative
|
||||
This module extends the Awesome window manager with alternative layouts,
|
||||
flash focus, tabbing, a simple tiling wallpaper generator, a declarative
|
||||
wallpaper setter, window swallowing and a playerctl signal.
|
||||
]],
|
||||
homepage = "https://github.com/Nooo37/bling",
|
||||
homepage = "https://github.com/BlingCorp/bling",
|
||||
license = "MIT",
|
||||
}
|
||||
|
||||
|
@ -23,32 +23,41 @@ dependencies = {
|
|||
|
||||
build = {
|
||||
type = "builtin",
|
||||
modules = {
|
||||
modules = {
|
||||
["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.client"] = "helpers/client.lua",
|
||||
["bling.helpers.color"] = "helpers/color.lua",
|
||||
["bling.helpers.filesystem"] = "helpers/filesystem.lua",
|
||||
["bling.helpers.shape"] = "helpers/shape.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.flash_focus"] = "module/flash_focus.lua",
|
||||
["bling.module.scratchpad"] = "module/scratchpad.lua",
|
||||
["bling.module.tabbed"] = "module/tabbed.lua",
|
||||
["bling.module.tiled_wallpaper"] = "module/tiled_wallpaper.lua",
|
||||
["bling.module.wallpaper"] = "module/wallpaper.lua",
|
||||
["bling.module.window_swallowing"] = "module/window_swallowing.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.default"] = "widget/tabbar/default.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"] = "widget/init.lua",
|
||||
["bling.widget.task_preview"] = "widget/task_preview.lua",
|
||||
["bling.widget.window_switcher"] = "widget/window_switcher.lua",
|
||||
},
|
||||
}
|
|
@ -17,6 +17,7 @@
|
|||
- [Tag Preview](widgets/tag_preview.md)
|
||||
- [Task Preview](widgets/task_preview.md)
|
||||
- [Tabbed Misc](widgets/tabbed_misc.md)
|
||||
- [Window Switcher](widgets/window_switcher.md)
|
||||
|
||||
- Extra
|
||||
- [Theme Variable Template](theme.md)
|
||||
|
|
|
@ -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.
|
||||
|
||||
```Lua
|
||||
```lua
|
||||
bling.layout.mstab
|
||||
bling.layout.centered
|
||||
bling.layout.vertical
|
||||
|
@ -16,36 +16,40 @@ bling.layout.deck
|
|||
```
|
||||
|
||||
### Theme Variables
|
||||
|
||||
```lua
|
||||
-- mstab
|
||||
theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients
|
||||
theme.mstab_dont_resize_slaves = false -- whether the tabbed stack windows should be smaller than the
|
||||
-- currently focused stack window (set it to true if you use
|
||||
-- transparent terminals. False if you use shadows on solid ones
|
||||
theme.mstab_bar_padding = "default" -- how much padding there should be between clients and your tabbar
|
||||
-- by default it will adjust based on your useless gaps.
|
||||
-- If you want a custom value. Set it to the number of pixels (int)
|
||||
theme.mstab_border_radius = 0 -- border radius of the tabbar
|
||||
theme.mstab_bar_height = 40 -- height of the tabbar
|
||||
theme.mstab_tabbar_position = "top" -- position of the tabbar (mstab currently does not support left,right)
|
||||
theme.mstab_tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
|
||||
-- defaults to the tabbar_style so only change if you want a
|
||||
-- different style for mstab and tabbed
|
||||
theme.mstab_bar_ontop = false -- whether you want to allow the bar to be ontop of clients
|
||||
theme.mstab_dont_resize_slaves = false -- whether the tabbed stack windows should be smaller than the
|
||||
-- currently focused stack window (set it to true if you use
|
||||
-- transparent terminals. False if you use shadows on solid ones
|
||||
theme.mstab_bar_padding = "default" -- how much padding there should be between clients and your tabbar
|
||||
-- by default it will adjust based on your useless gaps.
|
||||
-- If you want a custom value. Set it to the number of pixels (int)
|
||||
theme.mstab_border_radius = 0 -- border radius of the tabbar
|
||||
theme.mstab_bar_height = 40 -- height of the tabbar
|
||||
theme.mstab_tabbar_position = "top" -- position of the tabbar (mstab currently does not support left,right)
|
||||
theme.mstab_tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
|
||||
-- defaults to the tabbar_style so only change if you want a
|
||||
-- different style for mstab and tabbed
|
||||
```
|
||||
|
||||
### Previews
|
||||
|
||||
#### Mstab (dynamic tabbing layout)
|
||||
|
||||
![](https://imgur.com/HZRgApE.png)
|
||||
|
||||
*screenshot by [javacafe](https://github.com/JavaCafe01)*
|
||||
*screenshot by [JavaCafe01](https://github.com/JavaCafe01)*
|
||||
|
||||
#### Centered
|
||||
|
||||
![](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
|
||||
|
||||
![](https://imgur.com/JCFFywv.png)
|
||||
|
||||
*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)
|
||||
|
||||
*screenshot by [javacafe](https://github.com/JavaCafe01)*
|
||||
*screenshot by [JavaCafe01](https://github.com/JavaCafe01)*
|
||||
|
||||
|
|
|
@ -22,8 +22,8 @@ awful.key({modkey}, "Up",
|
|||
|
||||
### Theme Variables
|
||||
```lua
|
||||
theme.flash_focus_start_opacity = 0.6 -- the starting opacity
|
||||
theme.flash_focus_step = 0.01 -- the step of animation
|
||||
theme.flash_focus_start_opacity = 0.6 -- the starting opacity
|
||||
theme.flash_focus_step = 0.01 -- the step of animation
|
||||
```
|
||||
|
||||
### Preview
|
||||
|
|
|
@ -18,7 +18,7 @@ To initalize a scratchpad you can do something like the following:
|
|||
|
||||
```lua
|
||||
local bling = require("bling")
|
||||
local rubato = require("rubato") -- Totally optional, only required if you are using animations.
|
||||
local rubato = require("rubato") -- Totally optional, only required if you are using animations.
|
||||
|
||||
-- These are example rubato tables. You can use one for just y, just x, or both.
|
||||
-- The duration and easing is up to you. Please check out the rubato docs to learn more.
|
||||
|
@ -28,7 +28,7 @@ local anim_y = rubato.timed {
|
|||
easing = rubato.quadratic,
|
||||
intro = 0.1,
|
||||
duration = 0.3,
|
||||
awestore_compat = true -- This option must be set to true.
|
||||
awestore_compat = true -- This option must be set to true.
|
||||
}
|
||||
|
||||
local anim_x = rubato.timed {
|
||||
|
@ -37,7 +37,7 @@ local anim_x = rubato.timed {
|
|||
easing = rubato.quadratic,
|
||||
intro = 0.1,
|
||||
duration = 0.3,
|
||||
awestore_compat = true -- This option must be set to true.
|
||||
awestore_compat = true -- This option must be set to true.
|
||||
}
|
||||
|
||||
local term_scratch = bling.module.scratchpad {
|
||||
|
@ -49,7 +49,7 @@ local term_scratch = bling.module.scratchpad {
|
|||
geometry = {x=360, y=90, height=900, width=1200}, -- The geometry in a floating state
|
||||
reapply = true, -- Whether all those properties should be reapplied on every new opening of the scratchpad (MUST BE TRUE FOR ANIMATIONS)
|
||||
dont_focus_before_close = false, -- When set to true, the scratchpad will be closed by the toggle function regardless of whether its focused or not. When set to false, the toggle function will first bring the scratchpad into focus and only close it on a second call
|
||||
rubato = {x = anim_x, y = anim_y} -- Optional. This is how you can pass in the rubato tables for animations. If you don't want animations, you can ignore this option.
|
||||
rubato = {x = anim_x, y = anim_y} -- Optional. This is how you can pass in the rubato tables for animations. If you don't want animations, you can ignore this option.
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -6,15 +6,15 @@ Can your window manager swallow? It probably can...
|
|||
|
||||
To activate and deactivate window swallowing here are the following functions. If you want to activate it, just call the `start` function once in your `rc.lua`.
|
||||
```lua
|
||||
bling.module.window_swallowing.start() -- activates window swallowing
|
||||
bling.module.window_swallowing.stop() -- deactivates window swallowing
|
||||
bling.module.window_swallowing.toggle() -- toggles window swallowing
|
||||
bling.module.window_swallowing.start() -- activates window swallowing
|
||||
bling.module.window_swallowing.stop() -- deactivates window swallowing
|
||||
bling.module.window_swallowing.toggle() -- toggles window swallowing
|
||||
```
|
||||
|
||||
### Theme Variables
|
||||
```lua
|
||||
theme.dont_swallow_classname_list = {"firefox", "Gimp"} -- list of class names that should not be swallowed
|
||||
theme.dont_swallow_filter_activated = true -- whether the filter above should be active
|
||||
theme.dont_swallow_classname_list = {"firefox", "Gimp"} -- list of class names that should not be swallowed
|
||||
theme.dont_swallow_filter_activated = true -- whether the filter above should be active
|
||||
```
|
||||
|
||||
### Preview
|
||||
|
|
|
@ -6,10 +6,10 @@ Tabbed implements a tab container. There are also different themes for the tabs.
|
|||
|
||||
You should bind these functions to keys in order to use the tabbed module effectively:
|
||||
```lua
|
||||
bling.module.tabbed.pick() -- picks a client with your cursor to add to the tabbing group
|
||||
bling.module.tabbed.pop() -- removes the focused client from the tabbing group
|
||||
bling.module.tabbed.iter() -- iterates through the currently focused tabbing group
|
||||
bling.module.tabbed.pick_with_dmenu() -- picks a client with a dmenu application (defaults to rofi, other options can be set with a string parameter like "dmenu")
|
||||
bling.module.tabbed.pick() -- picks a client with your cursor to add to the tabbing group
|
||||
bling.module.tabbed.pop() -- removes the focused client from the tabbing group
|
||||
bling.module.tabbed.iter() -- iterates through the currently focused tabbing group
|
||||
bling.module.tabbed.pick_with_dmenu() -- picks a client with a dmenu application (defaults to rofi, other options can be set with a string parameter like "dmenu")
|
||||
bling.module.tabbed.pick_by_direction(dir) -- picks a client based on direction ("up", "down", "left" or "right")
|
||||
```
|
||||
|
||||
|
@ -17,25 +17,29 @@ bling.module.tabbed.pick_by_direction(dir) -- picks a client based on direction
|
|||
|
||||
```lua
|
||||
-- For tabbed only
|
||||
theme.tabbed_spawn_in_tab = false -- whether a new client should spawn into the focused tabbing container
|
||||
theme.tabbed_spawn_in_tab = false -- whether a new client should spawn into the focused tabbing container
|
||||
|
||||
-- For tabbar in general
|
||||
theme.tabbar_ontop = false
|
||||
theme.tabbar_radius = 0 -- border radius of the tabbar
|
||||
theme.tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
|
||||
theme.tabbar_font = "Sans 11" -- font of the tabbar
|
||||
theme.tabbar_size = 40 -- size of the tabbar
|
||||
theme.tabbar_position = "top" -- position of the tabbar
|
||||
theme.tabbar_bg_normal = "#000000" -- background 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_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar
|
||||
theme.tabbar_disable = false -- disable the tab bar entirely
|
||||
theme.tabbar_radius = 0 -- border radius of the tabbar
|
||||
theme.tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
|
||||
theme.tabbar_font = "Sans 11" -- font of the tabbar
|
||||
theme.tabbar_size = 40 -- size of the tabbar
|
||||
theme.tabbar_position = "top" -- position of the tabbar
|
||||
theme.tabbar_bg_normal = "#000000" -- background 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_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
|
||||
|
||||
-- the following variables are currently only for the "modern" tabbar style
|
||||
theme.tabbar_color_close = "#f9929b" -- chnges the color of the close button
|
||||
theme.tabbar_color_min = "#fbdf90" -- chnges the color of the minimize button
|
||||
theme.tabbar_color_float = "#ccaced" -- chnges the color of the float button
|
||||
theme.tabbar_color_close = "#f9929b" -- chnges the color of the close button
|
||||
theme.tabbar_color_min = "#fbdf90" -- chnges the color of the minimize button
|
||||
theme.tabbar_color_float = "#ccaced" -- chnges the color of the float button
|
||||
```
|
||||
|
||||
### Preview
|
||||
|
@ -44,19 +48,19 @@ Modern theme:
|
|||
|
||||
<img src="https://imgur.com/omowmIQ.png" width="600"/>
|
||||
|
||||
*screenshot by [javacafe](https://github.com/JavaCafe01)*
|
||||
*screenshot by [JavaCafe01](https://github.com/JavaCafe01)*
|
||||
|
||||
### Signals
|
||||
The tabbed module emits a few signals for the purpose of integration,
|
||||
```lua
|
||||
-- bling::tabbed::update -- triggered whenever a tabbed object is updated
|
||||
-- tabobj -- the object that caused the update
|
||||
-- tabobj -- the object that caused the update
|
||||
-- bling::tabbed::client_added -- triggered whenever a new client is added to a tab group
|
||||
-- tabobj -- the object that the client was added to
|
||||
-- client -- the client that added
|
||||
-- tabobj -- the object that the client was added to
|
||||
-- client -- the client that added
|
||||
-- bling::tabbed::client_removed -- triggered whenever a client is removed from a tab group
|
||||
-- tabobj -- the object that the client was removed from
|
||||
-- client -- the client that was removed
|
||||
-- tabobj -- the object that the client was removed from
|
||||
-- client -- the client that was removed
|
||||
-- bling::tabbed::changed_focus -- triggered whenever a tab group's focus is changed
|
||||
-- tabobj -- the modified tab group
|
||||
-- tabobj -- the modified tab group
|
||||
```
|
||||
|
|
|
@ -4,16 +4,16 @@
|
|||
|
||||
The function to set an automatically created tiled wallpaper can be called the following way (you don't need to set every option in the table):
|
||||
```lua
|
||||
awful.screen.connect_for_each_screen(function(s) -- that way the wallpaper is applied to every screen
|
||||
bling.module.tiled_wallpaper("x", s, { -- call the actual function ("x" is the string that will be tiled)
|
||||
fg = "#ff0000", -- define the foreground color
|
||||
bg = "#00ffff", -- define the background color
|
||||
offset_y = 25, -- set a y offset
|
||||
offset_x = 25, -- set a x offset
|
||||
font = "Hack", -- set the font (without the size)
|
||||
font_size = 14, -- set the font size
|
||||
padding = 100, -- set padding (default is 100)
|
||||
zickzack = true -- rectangular pattern or criss cross
|
||||
awful.screen.connect_for_each_screen(function(s) -- that way the wallpaper is applied to every screen
|
||||
bling.module.tiled_wallpaper("x", s, { -- call the actual function ("x" is the string that will be tiled)
|
||||
fg = "#ff0000", -- define the foreground color
|
||||
bg = "#00ffff", -- define the background color
|
||||
offset_y = 25, -- set a y offset
|
||||
offset_x = 25, -- set a x offset
|
||||
font = "Hack", -- set the font (without the size)
|
||||
font_size = 14, -- set the font size
|
||||
padding = 100, -- set padding (default is 100)
|
||||
zickzack = true -- rectangular pattern or criss cross
|
||||
})
|
||||
end)
|
||||
```
|
||||
|
@ -23,3 +23,4 @@ end)
|
|||
![](https://media.discordapp.net/attachments/702548913999314964/773887721294135296/tiled-wallpapers.png?width=1920&height=1080)
|
||||
|
||||
*screenshots by [Nooo37](https://github.com/Nooo37)*
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ bling.module.wallpaper.setup {
|
|||
bling.module.wallpaper.setup {
|
||||
set_function = bling.module.wallpaper.setters.random,
|
||||
wallpaper = {"/path/to/a/folder", "/path/to/another/folder"},
|
||||
change_timer = 631, -- prime numbers are better for timers
|
||||
change_timer = 631, -- prime numbers are better for timers
|
||||
position = "fit",
|
||||
background = "#424242"
|
||||
}
|
||||
|
@ -99,14 +99,14 @@ Here are the defaults:
|
|||
```lua
|
||||
-- Default parameters
|
||||
bling.module.wallpaper.setup {
|
||||
screen = nil, -- the screen to apply the wallpaper, as seen in gears.wallpaper functions
|
||||
change_timer = nil, -- the timer in seconds. If set, call the set_function every change_timer seconds
|
||||
set_function = nil, -- the setter function
|
||||
screen = nil, -- the screen to apply the wallpaper, as seen in gears.wallpaper functions
|
||||
change_timer = nil, -- the timer in seconds. If set, call the set_function every change_timer seconds
|
||||
set_function = nil, -- the setter function
|
||||
|
||||
-- parameters used by bling.module.wallpaper.prepare_list
|
||||
wallpaper = nil, -- the wallpaper object, see simple or simple_schedule documentation
|
||||
image_formats = {"jpg", "jpeg", "png", "bmp"}, -- when searching in folder, consider these files only
|
||||
recursive = true, -- when searching in folder, search also in subfolders
|
||||
wallpaper = nil, -- the wallpaper object, see simple or simple_schedule documentation
|
||||
image_formats = {"jpg", "jpeg", "png", "bmp"}, -- when searching in folder, consider these files only
|
||||
recursive = true, -- when searching in folder, search also in subfolders
|
||||
|
||||
-- parameters used by bling.module.wallpaper.apply
|
||||
position = nil, -- use a function of gears.wallpaper when applicable ("centered", "fit", "maximized", "tiled")
|
||||
|
@ -116,8 +116,8 @@ bling.module.wallpaper.setup {
|
|||
scale = 1, -- see gears.wallpaper.centered
|
||||
|
||||
-- parameters that only apply to bling.module.wallpaper.setter.awesome (as a setter or as a wallpaper function)
|
||||
colors = { -- see beautiful.theme_assets.wallpaper
|
||||
bg = beautiful.bg_color, -- the actual default is this color but darkened or lightned
|
||||
colors = { -- see beautiful.theme_assets.wallpaper
|
||||
bg = beautiful.bg_color, -- the actual default is this color but darkened or lightned
|
||||
fg = beautiful.fg_color,
|
||||
alt_fg = beautiful.fg_focus
|
||||
}
|
||||
|
|
|
@ -24,20 +24,20 @@ To disable: `bling.signal.playerctl.disable()`
|
|||
Here are the signals available:
|
||||
|
||||
```lua
|
||||
-- bling::playerctl::status -- first line is the signal
|
||||
-- playing (boolean) -- indented lines are function parameters
|
||||
-- player_name (string)
|
||||
-- bling::playerctl::status -- first line is the signal
|
||||
-- playing (boolean) -- indented lines are function parameters
|
||||
-- player_name (string)
|
||||
-- bling::playerctl::title_artist_album
|
||||
-- title (string)
|
||||
-- artist (string)
|
||||
-- album_path (string)
|
||||
-- player_name (string)
|
||||
-- title (string)
|
||||
-- artist (string)
|
||||
-- album_path (string)
|
||||
-- player_name (string)
|
||||
-- bling::playerctl::position
|
||||
-- interval_sec (number)
|
||||
-- length_sec (number)
|
||||
-- player_name (string)
|
||||
-- interval_sec (number)
|
||||
-- length_sec (number)
|
||||
-- player_name (string)
|
||||
-- bling::playerctl::no_players
|
||||
-- (No parameters)
|
||||
-- (No parameters)
|
||||
```
|
||||
|
||||
### Example Implementation
|
||||
|
@ -122,8 +122,8 @@ By default, this module will output signals from the most recently active player
|
|||
These options can be set through a call to `bling.signal.playerctl.enable()` or these theme variables:
|
||||
```lua
|
||||
theme.playerctl_backend = "playerctl_cli"
|
||||
theme.playerctl_ignore = {}
|
||||
theme.playerctl_player = {}
|
||||
theme.playerctl_ignore = {}
|
||||
theme.playerctl_player = {}
|
||||
theme.playerctl_update_on_activity = true
|
||||
theme.playerctl_position_update_interval = 1
|
||||
```
|
||||
|
@ -140,12 +140,12 @@ bling.signal.playerctl.enable {
|
|||
-- OR in your theme file:
|
||||
-- Same config as above but with theme variables
|
||||
theme.playerctl_backend = "playerctl_lib"
|
||||
theme.playerctl_ignore = "firefox"
|
||||
theme.playerctl_player = {"ncspot", "%any"}
|
||||
theme.playerctl_ignore = "firefox"
|
||||
theme.playerctl_player = {"ncspot", "%any"}
|
||||
|
||||
-- Prioritize vlc over all other players and deprioritize spotify
|
||||
theme.playerctl_backend = "playerctl_lib"
|
||||
theme.playerctl_player = {"vlc", "%any", "spotify"}
|
||||
theme.playerctl_player = {"vlc", "%any", "spotify"}
|
||||
|
||||
-- Disable priority of most recently active players
|
||||
theme.playerctl_backend = "playerctl_lib"
|
||||
|
|
|
@ -26,15 +26,20 @@ theme.tabbed_spawn_in_tab = false -- whether a new client should spawn
|
|||
|
||||
-- tabbar general
|
||||
theme.tabbar_ontop = false
|
||||
theme.tabbar_radius = 0 -- border radius of the tabbar
|
||||
theme.tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
|
||||
theme.tabbar_font = "Sans 11" -- font of the tabbar
|
||||
theme.tabbar_size = 40 -- size of the tabbar
|
||||
theme.tabbar_position = "top" -- position of the tabbar
|
||||
theme.tabbar_bg_normal = "#000000" -- background 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_fg_focus = "#ff0000" -- foreground color of unfocused clients on the tabbar
|
||||
theme.tabbar_radius = 0 -- border radius of the tabbar
|
||||
theme.tabbar_style = "default" -- style of the tabbar ("default", "boxes" or "modern")
|
||||
theme.tabbar_font = "Sans 11" -- font of the tabbar
|
||||
theme.tabbar_size = 40 -- size of the tabbar
|
||||
theme.tabbar_position = "top" -- position of the tabbar
|
||||
theme.tabbar_bg_normal = "#000000" -- background 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_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
|
||||
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,
|
||||
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
|
||||
```
|
||||
|
|
|
@ -18,8 +18,8 @@ To use the task list indicator:
|
|||
bling.widget.tabbed_misc.titlebar_indicator(client, {
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
layout_spacing = dpi(5), -- Set spacing in between items
|
||||
icon_size = dpi(24),
|
||||
icon_margin = 0,
|
||||
icon_size = dpi(24), -- Set icon size
|
||||
icon_margin = 0, -- Set icon margin
|
||||
fg_color = "#cccccc", -- Normal color for text
|
||||
fg_color_focus = "#ffffff", -- Color for focused text
|
||||
bg_color_focus = "#282828", -- Color for the focused items
|
||||
|
@ -80,32 +80,32 @@ The module exports a function that can be added to your tasklist as a `update_ca
|
|||
### Usage
|
||||
```lua
|
||||
awful.widget.tasklist({
|
||||
screen = s,
|
||||
filter = awful.widget.tasklist.filter.currenttags,
|
||||
layout = {
|
||||
spacing = dpi(10),
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
},
|
||||
style = {
|
||||
bg_normal = "#00000000",
|
||||
},
|
||||
widget_template = {
|
||||
{
|
||||
{
|
||||
widget = wibox.widget.imagebox,
|
||||
id = "icon_role",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
},
|
||||
width = dpi(24),
|
||||
height = dpi(24),
|
||||
widget = wibox.container.constraint,
|
||||
},
|
||||
widget = wibox.container.background, -- IT MUST BE A CONTAINER WIDGET AS THAT IS WHAT THE FUNCTION EXPECTS
|
||||
update_callback = require("bling.widget.tabbed_misc").custom_tasklist,
|
||||
id = "background_role",
|
||||
},
|
||||
})
|
||||
screen = s,
|
||||
filter = awful.widget.tasklist.filter.currenttags,
|
||||
layout = {
|
||||
spacing = dpi(10),
|
||||
layout = wibox.layout.fixed.vertical,
|
||||
},
|
||||
style = {
|
||||
bg_normal = "#00000000",
|
||||
},
|
||||
widget_template = {
|
||||
{
|
||||
{
|
||||
widget = wibox.widget.imagebox,
|
||||
id = "icon_role",
|
||||
align = "center",
|
||||
valign = "center",
|
||||
},
|
||||
width = dpi(24),
|
||||
height = dpi(24),
|
||||
widget = wibox.container.constraint,
|
||||
},
|
||||
widget = wibox.container.background, -- IT MUST BE A CONTAINER WIDGET AS THAT IS WHAT THE FUNCTION EXPECTS
|
||||
update_callback = require("bling.widget.tabbed_misc").custom_tasklist,
|
||||
id = "background_role",
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
If you need to do something else, it can be used like so
|
||||
|
|
|
@ -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.
|
||||
|
||||
![](https://imgur.com/3nYe1e8.gif)
|
||||
![](https://imgur.com/zFdvs4K.gif)
|
||||
|
||||
*gif by [javacafe](https://github.com/JavaCafe01)*
|
||||
|
||||
|
@ -24,19 +24,25 @@ bling.widget.tag_preview.enable {
|
|||
top = 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
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here are the signals available:
|
||||
|
||||
```lua
|
||||
-- bling::tag_preview::update -- first line is the signal
|
||||
-- t (tag) -- indented lines are function parameters
|
||||
-- bling::tag_preview::update -- first line is the signal
|
||||
-- t (tag) -- indented lines are function parameters
|
||||
-- bling::tag_preview::visibility
|
||||
-- s (screen)
|
||||
-- v (boolean)
|
||||
-- s (screen)
|
||||
-- v (boolean)
|
||||
```
|
||||
|
||||
By default, the widget is not visible. You must implement when it will update and when it will show.
|
||||
|
@ -100,7 +106,7 @@ s.mytaglist = awful.widget.taglist {
|
|||
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()
|
||||
|
||||
|
||||
-- BLING: Only show widget when there are clients in the tag
|
||||
if #c3:clients() > 0 then
|
||||
-- BLING: Update the widget with the new tag
|
||||
|
@ -119,7 +125,7 @@ s.mytaglist = awful.widget.taglist {
|
|||
|
||||
-- BLING: Turn the widget off
|
||||
awesome.emit_signal("bling::tag_preview::visibility", s, false)
|
||||
|
||||
|
||||
if self.has_backup then self.bg = self.backup end
|
||||
end)
|
||||
end,
|
||||
|
@ -132,17 +138,18 @@ s.mytaglist = awful.widget.taglist {
|
|||
```
|
||||
|
||||
### Theme Variables
|
||||
|
||||
```lua
|
||||
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_opacity = 0.5 -- Opacity of each client
|
||||
theme.tag_preview_client_bg = "#000000" -- The bg color of each client
|
||||
theme.tag_preview_client_border_color = "#ffffff" -- The border color of each client
|
||||
theme.tag_preview_client_border_width = 3 -- The border width of each client
|
||||
theme.tag_preview_widget_bg = "#000000" -- The bg color of the widget
|
||||
theme.tag_preview_widget_border_color = "#ffffff" -- The border color of the widget
|
||||
theme.tag_preview_widget_border_width = 3 -- The border width of the widget
|
||||
theme.tag_preview_widget_margin = 0 -- The margin of the widget
|
||||
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_opacity = 0.5 -- Opacity of each client
|
||||
theme.tag_preview_client_bg = "#000000" -- The bg color of each client
|
||||
theme.tag_preview_client_border_color = "#ffffff" -- The border color of each client
|
||||
theme.tag_preview_client_border_width = 3 -- The border width of each client
|
||||
theme.tag_preview_widget_bg = "#000000" -- The bg color of the widget
|
||||
theme.tag_preview_widget_border_color = "#ffffff" -- The border color of the widget
|
||||
theme.tag_preview_widget_border_width = 3 -- The border width of the widget
|
||||
theme.tag_preview_widget_margin = 0 -- The margin of the widget
|
||||
```
|
||||
|
||||
NOTE: I recommend to only use the widget border radius theme variable when not using shadows with a compositor, as anti-aliased rounding with the outer widgets made with AwesomeWM rely on the actual bg being transparent. If you want rounding with shadows on the widget, use a compositor like [jonaburg's fork](https://github.com/jonaburg/picom).
|
||||
|
|
|
@ -12,46 +12,46 @@ To enable:
|
|||
|
||||
```lua
|
||||
bling.widget.task_preview.enable {
|
||||
x = 20, -- The x-coord of the popup
|
||||
y = 20, -- The y-coord of the popup
|
||||
height = 200, -- The height of the popup
|
||||
width = 200, -- The width of the popup
|
||||
placement_fn = function(c) -- Place the widget using awful.placement (this overrides x & y)
|
||||
x = 20, -- The x-coord of the popup
|
||||
y = 20, -- The y-coord of the popup
|
||||
height = 200, -- The height of the popup
|
||||
width = 200, -- The width of the popup
|
||||
placement_fn = function(c) -- Place the widget using awful.placement (this overrides x & y)
|
||||
awful.placement.bottom(c, {
|
||||
margins = {
|
||||
bottom = 30
|
||||
}
|
||||
})
|
||||
})
|
||||
end
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
To allow for more customization, there is also a `widget_structure` property (as seen in some default awesome widgets) which is optional. An example is as follows -
|
||||
```lua
|
||||
bling.widget.task_preview.enable {
|
||||
x = 20, -- The x-coord of the popup
|
||||
y = 20, -- The y-coord of the popup
|
||||
height = 200, -- The height of the popup
|
||||
width = 200, -- The width of the popup
|
||||
placement_fn = function(c) -- Place the widget using awful.placement (this overrides x & y)
|
||||
x = 20, -- The x-coord of the popup
|
||||
y = 20, -- The y-coord of the popup
|
||||
height = 200, -- The height of the popup
|
||||
width = 200, -- The width of the popup
|
||||
placement_fn = function(c) -- Place the widget using awful.placement (this overrides x & y)
|
||||
awful.placement.bottom(c, {
|
||||
margins = {
|
||||
bottom = 30
|
||||
}
|
||||
})
|
||||
})
|
||||
end,
|
||||
-- Your widget will automatically conform to the given size due to a constraint container.
|
||||
widget_structure = {
|
||||
{
|
||||
{
|
||||
{
|
||||
id = 'icon_role',
|
||||
id = 'icon_role',
|
||||
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,
|
||||
}
|
||||
},
|
||||
layout = wibox.layout.flex.horizontal
|
||||
},
|
||||
widget = wibox.container.margin,
|
||||
|
@ -66,16 +66,16 @@ bling.widget.task_preview.enable {
|
|||
},
|
||||
layout = wibox.layout.fixed.vertical
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here are the signals available:
|
||||
|
||||
```lua
|
||||
-- bling::task_preview::visibility -- first line is the signal
|
||||
-- s (screen) -- indented lines are function parameters
|
||||
-- v (boolean)
|
||||
-- c (client)
|
||||
-- s (screen) -- indented lines are function parameters
|
||||
-- v (boolean)
|
||||
-- c (client)
|
||||
```
|
||||
|
||||
By default, the widget is not visible. You must implement when it will update and when it will show.
|
||||
|
@ -124,7 +124,7 @@ s.mytasklist = awful.widget.tasklist {
|
|||
nil,
|
||||
create_callback = function(self, c, index, objects) --luacheck: no unused args
|
||||
self:get_children_by_id('clienticon')[1].client = c
|
||||
|
||||
|
||||
-- BLING: Toggle the popup on hover and disable it off hover
|
||||
self:connect_signal('mouse::enter', function()
|
||||
awesome.emit_signal("bling::task_preview::visibility", s,
|
||||
|
@ -142,11 +142,11 @@ s.mytasklist = awful.widget.tasklist {
|
|||
|
||||
### Theme Variables
|
||||
```lua
|
||||
theme.task_preview_widget_border_radius = 0 -- Border radius of the widget (With AA)
|
||||
theme.task_preview_widget_bg = "#000000" -- The bg color of the widget
|
||||
theme.task_preview_widget_border_color = "#ffffff" -- The border color 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_border_radius = 0 -- Border radius of the widget (With AA)
|
||||
theme.task_preview_widget_bg = "#000000" -- The bg color of the widget
|
||||
theme.task_preview_widget_border_color = "#ffffff" -- The border color 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
|
||||
```
|
||||
|
||||
NOTE: I recommend to only use the widget border radius theme variable when not using shadows with a compositor, as anti-aliased rounding with the outer widgets made with AwesomeWM rely on the actual bg being transparent. If you want rounding with shadows on the widget, use a compositor like [jonaburg's fork](https://github.com/jonaburg/picom).
|
||||
|
|
|
@ -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
|
||||
```
|
|
@ -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 = {}
|
||||
|
||||
--- Try to guess if a color is dark or light.
|
||||
|
@ -13,6 +22,14 @@ function _color.is_dark(color)
|
|||
return (numeric_value < 383)
|
||||
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.
|
||||
--
|
||||
-- @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)
|
||||
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
|
||||
|
|
|
@ -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)
|
|
@ -1,7 +1,4 @@
|
|||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local gcolor = require("gears.color")
|
||||
local beautiful = require("beautiful")
|
||||
local math = math
|
||||
|
||||
local mylayout = {}
|
||||
|
@ -58,6 +55,7 @@ function mylayout.arrange(p)
|
|||
-- iterate through slaves
|
||||
for idx = 1, nslaves do -- idx=nmaster+1,#p.clients do
|
||||
local c = p.clients[idx + nmaster]
|
||||
local g
|
||||
if idx % 2 == 0 then
|
||||
g = {
|
||||
x = area.x,
|
||||
|
@ -83,20 +81,4 @@ function mylayout.arrange(p)
|
|||
end
|
||||
end
|
||||
|
||||
local icon_raw = gears.filesystem.get_configuration_dir()
|
||||
.. 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,
|
||||
}
|
||||
return mylayout
|
||||
|
|
|
@ -1,8 +1,3 @@
|
|||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local gcolor = require("gears.color")
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
local mylayout = {}
|
||||
|
||||
mylayout.name = "deck"
|
||||
|
@ -39,20 +34,4 @@ function mylayout.arrange(p)
|
|||
end
|
||||
end
|
||||
|
||||
local icon_raw = gears.filesystem.get_configuration_dir()
|
||||
.. 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,
|
||||
}
|
||||
return mylayout
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
local gears = require("gears")
|
||||
local gcolor = require("gears.color")
|
||||
local beautiful = require("beautiful")
|
||||
local math = math
|
||||
local screen = screen
|
||||
local mylayout = {}
|
||||
|
@ -77,20 +74,4 @@ function mylayout.arrange(p)
|
|||
divide(p, g, 1, #cls, cls, mwfact, mcount)
|
||||
end
|
||||
|
||||
local icon_raw = gears.filesystem.get_configuration_dir()
|
||||
.. 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,
|
||||
}
|
||||
return mylayout
|
||||
|
|
|
@ -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 mylayout = {}
|
||||
|
@ -57,20 +53,4 @@ function mylayout.arrange(p)
|
|||
end
|
||||
end
|
||||
|
||||
local icon_raw = gears.filesystem.get_configuration_dir()
|
||||
.. 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,
|
||||
}
|
||||
return mylayout
|
||||
|
|
|
@ -1,30 +1,44 @@
|
|||
local beautiful = require("beautiful")
|
||||
local gears = require("gears")
|
||||
|
||||
local mstab = require(... .. ".mstab")
|
||||
beautiful.layout_mstab = mstab.get_icon()
|
||||
local M = {}
|
||||
local relative_lua_path = tostring(...)
|
||||
|
||||
local vertical = require(... .. ".vertical")
|
||||
beautiful.layout_vertical = vertical.get_icon()
|
||||
local function get_layout_icon_path(name)
|
||||
local relative_icon_path = relative_lua_path
|
||||
:match("^.*bling"):gsub("%.", "/")
|
||||
.. "/icons/layouts/" .. name .. ".png"
|
||||
|
||||
local horizontal = require(... .. ".horizontal")
|
||||
beautiful.layout_horizontal = horizontal.get_icon()
|
||||
for p in package.path:gmatch('([^;]+)') do
|
||||
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")
|
||||
beautiful.layout_centered = centered.get_icon()
|
||||
local function get_icon(icon_raw)
|
||||
if icon_raw ~= nil then
|
||||
return gears.color.recolor_image(icon_raw, beautiful.fg_normal)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local equalarea = require(... .. ".equalarea")
|
||||
beautiful.layout_equalarea = equalarea.get_icon()
|
||||
|
||||
local deck = require(... .. ".deck")
|
||||
beautiful.layout_deck = deck.get_icon()
|
||||
|
||||
local layout = {
|
||||
mstab = mstab.layout,
|
||||
centered = centered.layout,
|
||||
vertical = vertical.layout,
|
||||
horizontal = horizontal.layout,
|
||||
equalarea = equalarea.layout,
|
||||
deck = deck.layout,
|
||||
local layouts = {
|
||||
"mstab",
|
||||
"vertical",
|
||||
"horizontal",
|
||||
"centered",
|
||||
"equalarea",
|
||||
"deck"
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
local awful = require("awful")
|
||||
local gears = require("gears")
|
||||
local wibox = require("wibox")
|
||||
local gcolor = require("gears.color")
|
||||
local beautiful = require("beautiful")
|
||||
|
||||
local mylayout = {}
|
||||
|
@ -242,16 +241,4 @@ function mylayout.arrange(p)
|
|||
)
|
||||
end
|
||||
|
||||
local icon_raw = gears.filesystem.get_configuration_dir()
|
||||
.. 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 }
|
||||
return mylayout
|
||||
|
|
|
@ -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 mylayout = {}
|
||||
|
@ -57,20 +53,4 @@ function mylayout.arrange(p)
|
|||
end
|
||||
end
|
||||
|
||||
local icon_raw = gears.filesystem.get_configuration_dir()
|
||||
.. 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,
|
||||
}
|
||||
return mylayout
|
||||
|
|
|
@ -23,6 +23,14 @@ local bar = require(
|
|||
|
||||
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
|
||||
tabbed.iter = function(idx)
|
||||
if not idx then
|
||||
|
@ -50,6 +58,8 @@ tabbed.remove = function(c)
|
|||
awful.titlebar.hide(c, bar.position)
|
||||
end
|
||||
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)
|
||||
tabbed.switch_to(tabobj, 1)
|
||||
end
|
||||
|
@ -67,6 +77,8 @@ tabbed.add = function(c, tabobj)
|
|||
if c.bling_tabbed then
|
||||
tabbed.remove(c)
|
||||
end
|
||||
c:connect_signal("focus", update_tabbar_from)
|
||||
c:connect_signal("unfocus", update_tabbar_from)
|
||||
helpers.client.sync(c, tabobj.clients[tabobj.focused_idx])
|
||||
tabobj.clients[#tabobj.clients + 1] = c
|
||||
tabobj.focused_idx = #tabobj.clients
|
||||
|
@ -218,12 +230,15 @@ end
|
|||
|
||||
tabbed.update_tabbar = function(tabobj)
|
||||
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
|
||||
for idx, c in ipairs(tabobj.clients) do
|
||||
local buttons = gears.table.join(awful.button({}, 1, function()
|
||||
tabbed.switch_to(tabobj, idx)
|
||||
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)
|
||||
end
|
||||
-- add tabbar to each tabbed client (clients will be hided anyway)
|
||||
|
@ -240,6 +255,8 @@ end
|
|||
tabbed.init = function(c)
|
||||
local tabobj = {}
|
||||
tabobj.clients = { c }
|
||||
c:connect_signal("focus", update_tabbar_from)
|
||||
c:connect_signal("unfocus", update_tabbar_from)
|
||||
tabobj.focused_idx = 1
|
||||
tabbed.update(tabobj)
|
||||
end
|
||||
|
|
|
@ -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_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_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
|
||||
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_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
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,656 @@
|
|||
---------------------------------------------------------------------------
|
||||
--- Modified Prompt module.
|
||||
-- @author Julien Danjou <julien@danjou.info>
|
||||
-- @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)
|
|
@ -3,4 +3,5 @@ return {
|
|||
task_preview = require(... .. ".task_preview"),
|
||||
window_switcher = require(... .. ".window_switcher"),
|
||||
tabbed_misc = require(... .. ".tabbed_misc"),
|
||||
app_launcher = require(... .. ".app_launcher"),
|
||||
}
|
||||
|
|
|
@ -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 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 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 size = beautiful.tabbar_size or 40
|
||||
local position = beautiful.tabbar_position or "bottom"
|
||||
|
||||
local function create(c, focused_bool, buttons)
|
||||
local bg_temp = bg_normal
|
||||
local fg_temp = fg_normal
|
||||
local function create(c, focused_bool, buttons, inactive_bool)
|
||||
local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
|
||||
local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
|
||||
if focused_bool then
|
||||
bg_temp = bg_focus
|
||||
fg_temp = fg_focus
|
||||
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({
|
||||
{
|
||||
|
|
|
@ -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 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 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 size = beautiful.tabbar_size or 20
|
||||
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 title_temp = c.name or c.class or "-"
|
||||
local bg_temp = bg_normal
|
||||
local fg_temp = fg_normal
|
||||
local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
|
||||
local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
|
||||
if focused_bool then
|
||||
bg_temp = bg_focus
|
||||
fg_temp = fg_focus
|
||||
bg_temp = inactive_bool and bg_focus_inactive or bg_focus
|
||||
fg_temp = inactive_bool and fg_focus_inactive or fg_focus
|
||||
end
|
||||
local text_temp = wibox.widget.textbox()
|
||||
text_temp.align = "center"
|
||||
|
|
|
@ -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 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 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 size = beautiful.tabbar_size or dpi(40)
|
||||
local border_radius = beautiful.mstab_border_radius
|
||||
|
@ -66,14 +70,14 @@ local function create_title_button(c, color_focus, color_unfocus)
|
|||
return tb
|
||||
end
|
||||
|
||||
local function create(c, focused_bool, buttons)
|
||||
local function create(c, focused_bool, buttons, inactive_bool)
|
||||
-- local flexlist = wibox.layout.flex.horizontal()
|
||||
local title_temp = c.name or c.class or "-"
|
||||
local bg_temp = bg_normal
|
||||
local fg_temp = fg_normal
|
||||
local bg_temp = inactive_bool and bg_normal_inactive or bg_normal
|
||||
local fg_temp = inactive_bool and fg_normal_inactive or fg_normal
|
||||
if focused_bool then
|
||||
bg_temp = bg_focus
|
||||
fg_temp = fg_focus
|
||||
bg_temp = inactive_bool and bg_focus_inactive or bg_focus
|
||||
fg_temp = inactive_bool and fg_focus_inactive or fg_focus
|
||||
end
|
||||
local text_temp = wibox.widget.textbox()
|
||||
text_temp.align = "center"
|
||||
|
|
|
@ -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 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 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 size = beautiful.tabbar_size or 20
|
||||
local position = beautiful.tabbar_position or "top"
|
||||
|
||||
local function create(c, focused_bool, buttons)
|
||||
local bg_temp = focused_bool and bg_focus or bg_normal
|
||||
local fg_temp = focused_bool and fg_focus or fg_normal
|
||||
local function create(c, focused_bool, buttons, inactive_bool)
|
||||
local bg_temp = inactive_bool and bg_normal_inactive or bg_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({
|
||||
{
|
||||
|
|
|
@ -28,7 +28,8 @@ local function draw_widget(
|
|||
widget_border_color,
|
||||
widget_border_width,
|
||||
geo,
|
||||
margin
|
||||
margin,
|
||||
background_image
|
||||
)
|
||||
local client_list = wibox.layout.manual()
|
||||
client_list.forced_height = geo.height
|
||||
|
@ -36,15 +37,20 @@ local function draw_widget(
|
|||
local tag_screen = t.screen
|
||||
for i, c in ipairs(t:clients()) do
|
||||
if not c.hidden and not c.minimized then
|
||||
|
||||
local img_box = wibox.widget({
|
||||
image = gears.surface.load(c.icon),
|
||||
|
||||
|
||||
local img_box = wibox.widget ({
|
||||
resize = true,
|
||||
forced_height = 100 * scale,
|
||||
forced_width = 100 * scale,
|
||||
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 c.prev_content or t.selected then
|
||||
local content
|
||||
|
@ -108,22 +114,26 @@ local function draw_widget(
|
|||
end
|
||||
end
|
||||
|
||||
return {
|
||||
return wibox.widget {
|
||||
{
|
||||
background_image,
|
||||
{
|
||||
{
|
||||
{
|
||||
client_list,
|
||||
forced_height = geo.height,
|
||||
forced_width = geo.width,
|
||||
widget = wibox.container.place,
|
||||
{
|
||||
client_list,
|
||||
forced_height = geo.height,
|
||||
forced_width = geo.width,
|
||||
widget = wibox.container.place,
|
||||
},
|
||||
layout = wibox.layout.align.horizontal,
|
||||
},
|
||||
layout = wibox.layout.align.horizontal,
|
||||
layout = wibox.layout.align.vertical,
|
||||
},
|
||||
layout = wibox.layout.align.vertical,
|
||||
margins = margin,
|
||||
widget = wibox.container.margin,
|
||||
},
|
||||
margins = margin,
|
||||
widget = wibox.container.margin,
|
||||
layout = wibox.layout.stack
|
||||
},
|
||||
bg = widget_bg,
|
||||
shape_border_width = widget_border_width,
|
||||
|
@ -143,6 +153,7 @@ local enable = function(opts)
|
|||
local work_area = opts.honor_workarea or false
|
||||
local padding = opts.honor_padding or false
|
||||
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 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)
|
||||
for _, c in ipairs(t:clients()) do
|
||||
c.prev_content = gears.surface.duplicate_surface(c.content)
|
||||
end
|
||||
-- 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::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_height = scale * geo.height + margin * 2
|
||||
|
||||
-- TODO: Use a table here
|
||||
tag_preview_box:setup(draw_widget(t, tag_preview_image, scale,
|
||||
screen_radius, client_radius,
|
||||
client_opacity, client_bg,
|
||||
client_border_color,
|
||||
client_border_width, widget_bg,
|
||||
widget_border_color,
|
||||
widget_border_width, geo, margin))
|
||||
|
||||
tag_preview_box.widget = draw_widget(
|
||||
t,
|
||||
tag_preview_image,
|
||||
scale,
|
||||
screen_radius,
|
||||
client_radius,
|
||||
client_opacity,
|
||||
client_bg,
|
||||
client_border_color,
|
||||
client_border_width,
|
||||
widget_bg,
|
||||
widget_border_color,
|
||||
widget_border_width,
|
||||
geo,
|
||||
margin,
|
||||
background_image
|
||||
)
|
||||
end)
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
if v == false then
|
||||
tag_preview_box.widget = nil
|
||||
collectgarbage("collect")
|
||||
end
|
||||
|
||||
tag_preview_box.visible = v
|
||||
end)
|
||||
end
|
||||
|
|
|
@ -30,14 +30,24 @@ local function draw_widget(
|
|||
end) then
|
||||
return
|
||||
end
|
||||
local content = gears.surface(c.content)
|
||||
local cr = cairo.Context(content)
|
||||
local x, y, w, h = cr:clip_extents()
|
||||
local img = cairo.ImageSurface.create(cairo.Format.ARGB32, w - x, h - y)
|
||||
cr = cairo.Context(img)
|
||||
cr:set_source_surface(content, 0, 0)
|
||||
cr.operator = cairo.Operator.SOURCE
|
||||
cr:paint()
|
||||
|
||||
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 x, y, w, h = cr:clip_extents()
|
||||
img = cairo.ImageSurface.create(cairo.Format.ARGB32, w - x, h - y)
|
||||
cr = cairo.Context(img)
|
||||
cr:set_source_surface(content, 0, 0)
|
||||
cr.operator = cairo.Operator.SOURCE
|
||||
cr:paint()
|
||||
end
|
||||
|
||||
local widget = wibox.widget({
|
||||
(widget_template or {
|
||||
|
@ -139,6 +149,25 @@ local enable = function(opts)
|
|||
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)
|
||||
if v then
|
||||
-- Update task preview contents
|
||||
|
@ -153,6 +182,9 @@ local enable = function(opts)
|
|||
widget_width,
|
||||
widget_height
|
||||
)
|
||||
else
|
||||
task_preview_box.widget = nil
|
||||
collectgarbage("collect")
|
||||
end
|
||||
|
||||
if not placement_fn then
|
||||
|
|
|
@ -59,6 +59,8 @@ local window_switcher_hide = function(window_switcher_box)
|
|||
-- Stop and hide window_switcher
|
||||
awful.keygrabber.stop(window_switcher_grabber)
|
||||
window_switcher_box.visible = false
|
||||
window_switcher_box.widget = nil
|
||||
collectgarbage("collect")
|
||||
end
|
||||
|
||||
local function draw_widget(
|
||||
|
|
Loading…
Reference in New Issue