Initial i3 configuration
This is derived from my Awesome configuration. Still a lot to do from a WM perspective. The organization is a bit different and I am giving it up on the per-display systemd units as it does not really work due to the fact we only have one user DBus and one environment.
78
README.md
|
@ -1,78 +0,0 @@
|
||||||
# Vincent Bernat's awesome configuration
|
|
||||||
|
|
||||||
This is my [awesome](http://awesome.naquadah.org) configuration. It
|
|
||||||
does not exactly feature the same keybindings as the default
|
|
||||||
configuration. I don't recommend using it by you can pick anything you
|
|
||||||
need in it.
|
|
||||||
|
|
||||||
This configuration is for _awesome_ 3.4. I did not update to 3.5
|
|
||||||
yet. Have a look at
|
|
||||||
[@P-EB pull request](https://github.com/vincentbernat/awesome-configuration/pull/5)
|
|
||||||
for 3.5 support.
|
|
||||||
|
|
||||||
Here some of the things you may be interested in:
|
|
||||||
|
|
||||||
- It is modular. I am using `config` as a table to pass different
|
|
||||||
things between "modules".
|
|
||||||
|
|
||||||
- I use a light transparency effect to tell if a window has the focus
|
|
||||||
or not. It needs a composite manager.
|
|
||||||
|
|
||||||
- I use a Python script `bin/build-wallpaper` to build the wallpaper
|
|
||||||
to be displayed. There is a random selection and it works with
|
|
||||||
multihead setup. It seems that classic tools are now able to change
|
|
||||||
the wallpaper per screen and therefore, the script may seem a bit
|
|
||||||
useless but I keep it.
|
|
||||||
|
|
||||||
- I am using `xss-lock` with `i3lock` as a screensaver. It relies on
|
|
||||||
standard X screensaver handling (and therefore is easy for
|
|
||||||
application to disable) and also supports systemd
|
|
||||||
inhibitors. Nothing fancy but I reuse the wallpaper built above. A
|
|
||||||
notification is sent 10 seconds before starting.
|
|
||||||
|
|
||||||
- In `rc/apparance.lua`, you may be interested by the way I configure
|
|
||||||
GTK2 and GTK3 to have an unified look. It works and it does not
|
|
||||||
need `gnome-control-center`.
|
|
||||||
|
|
||||||
- I have rebuilt my own implementation of the Quake console in
|
|
||||||
`lib/quake.lua`. The common ones didn't like when awesome was
|
|
||||||
restarted.
|
|
||||||
|
|
||||||
- I am using notifications when changing volume or brightness. I am
|
|
||||||
also using notifications to change xrandr setup. This is pretty
|
|
||||||
cool.
|
|
||||||
|
|
||||||
- Keybindings are "autodocumented". See `lib/keydoc.lua` to see how
|
|
||||||
this works. The list of key bindings can be accessed with Mod4 +
|
|
||||||
F1.
|
|
||||||
|
|
||||||
- On the debug front, I am quite happy with `dbg()` in
|
|
||||||
`rc/debug.lua`.
|
|
||||||
|
|
||||||
- Many stuff is handled by systemd. The session is still expected to
|
|
||||||
be handled by Xsession but we invoke a custom display-specific
|
|
||||||
`xsession@.target` which binds to a display-specific
|
|
||||||
`graphical-session@.target`. This is different from the
|
|
||||||
`graphical-session.target` shipped by distributions because I
|
|
||||||
wanted it to be display-specific. Also, unit activation is bundled
|
|
||||||
directly into `graphical-session@.target` while dependencies are
|
|
||||||
mostly handled in `awesome@.service`.
|
|
||||||
|
|
||||||
Also, I am using my custom terminal (`vbeterm`). You need to change
|
|
||||||
that in `rc.lua`. You can also find the sources on
|
|
||||||
[GitHub](https://github.com/vincentbernat/vbeterm).
|
|
||||||
|
|
||||||
Things in `lib/` are meant to be reused. I am using my own `loadrc()`
|
|
||||||
function to load modules and therefore, I prefix my modules with
|
|
||||||
`vbe/`. Before reusing a module, you may want to change this. Another
|
|
||||||
way to load them is to use:
|
|
||||||
|
|
||||||
require("lib/quake")
|
|
||||||
local quake = package.loaded["vbe/quake"]
|
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
Required Debian packages to make everything work can be found in my
|
|
||||||
[Puppet configuration][].
|
|
||||||
|
|
||||||
[Puppet configuration]: https://github.com/vincentbernat/puppet-workstation/blob/master/local-modules/desktop/manifests/awesome.pp
|
|
|
@ -9,8 +9,8 @@ name="$4"
|
||||||
|
|
||||||
# Load the given keymap
|
# Load the given keymap
|
||||||
xkb() {
|
xkb() {
|
||||||
xkbcomp -i ${device} -w 0 -I$HOME/.config/awesome/xkb \
|
xkbcomp -i ${device} -w 0 -I$HOME/.config/i3/dotfiles/xkb \
|
||||||
$HOME/.config/awesome/xkb/$1.xkb ${DISPLAY}
|
$HOME/.config/i3/dotfiles/xkb/$1.xkb ${DISPLAY}
|
||||||
}
|
}
|
||||||
|
|
||||||
case $event in
|
case $event in
|
||||||
|
@ -30,7 +30,7 @@ case "$event,$use,$(uname -n),$name" in
|
||||||
done
|
done
|
||||||
;;
|
;;
|
||||||
*,XISlaveKeyboard,zoro,"AT Translated Set 2 keyboard")
|
*,XISlaveKeyboard,zoro,"AT Translated Set 2 keyboard")
|
||||||
xkb x1
|
xkb x1gen2
|
||||||
;;
|
;;
|
||||||
*,XISlaveKeyboard,*,"ThinkPad Extra Buttons")
|
*,XISlaveKeyboard,*,"ThinkPad Extra Buttons")
|
||||||
xkb thinkpad-extra
|
xkb thinkpad-extra
|
||||||
|
|
|
@ -33,15 +33,12 @@ xrandr --dpi $dpi
|
||||||
|
|
||||||
# Build xsettingsd
|
# Build xsettingsd
|
||||||
{
|
{
|
||||||
cat ~/.config/awesome/xsettingsd
|
cat ~/.config/i3/xsettingsd
|
||||||
echo Xft/DPI $(( $dpi*1024 ))
|
echo Xft/DPI $(( $dpi*1024 ))
|
||||||
echo Xft/RGBA \"$( [ $dpi -gt 144 ] && echo none || echo rgb )\"
|
echo Xft/RGBA \"$( [ $dpi -gt 144 ] && echo none || echo rgb )\"
|
||||||
echo Gdk/WindowScalingFactor $(( $dpi/96 ))
|
echo Gdk/WindowScalingFactor $(( $dpi/96 ))
|
||||||
echo Gdk/UnscaledDPI $(( $dpi*1024/($dpi/96) ))
|
echo Gdk/UnscaledDPI $(( $dpi*1024/($dpi/96) ))
|
||||||
} > ~/.xsettingsd
|
} > ~/.xsettingsd
|
||||||
|
|
||||||
# Signal xsettingsd
|
|
||||||
systemctl --user reload xsettingsd@$(systemd-escape -- "$DISPLAY").service
|
|
||||||
|
|
||||||
# Also use xrdb for very old stuff (you know, LibreOffice)
|
# Also use xrdb for very old stuff (you know, LibreOffice)
|
||||||
echo Xft.dpi: $dpi | xrdb -merge
|
echo Xft.dpi: $dpi | xrdb -merge
|
||||||
|
|
|
@ -40,7 +40,7 @@ case "$1" in
|
||||||
# First, pause any music player
|
# First, pause any music player
|
||||||
playerctl -a pause
|
playerctl -a pause
|
||||||
# Then, lock screen
|
# Then, lock screen
|
||||||
i3lock -n -e -i $HOME/.cache/awesome/current-wallpaper-${display}.png -t -f
|
i3lock -n -e -i $HOME/.cache/i3/current-wallpaper.png -t -f
|
||||||
echo "lock: unlock screen"
|
echo "lock: unlock screen"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
119
config
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
# i3 config file (v4)
|
||||||
|
|
||||||
|
set $up k
|
||||||
|
set $down j
|
||||||
|
set $left h
|
||||||
|
set $right l
|
||||||
|
set $mod Mod4
|
||||||
|
set $term vbeterm
|
||||||
|
|
||||||
|
font pango:Terminus 9
|
||||||
|
|
||||||
|
# Style
|
||||||
|
default_border pixel 3
|
||||||
|
default_floating_border pixel 3
|
||||||
|
|
||||||
|
# Use pactl to adjust volume in PulseAudio.
|
||||||
|
bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10%
|
||||||
|
bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -10%
|
||||||
|
bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle
|
||||||
|
bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle
|
||||||
|
|
||||||
|
# use Mouse+$mod to drag floating windows to their wanted position
|
||||||
|
floating_modifier $mod
|
||||||
|
|
||||||
|
# start a terminal
|
||||||
|
bindsym $mod+Return exec $term
|
||||||
|
|
||||||
|
# kill focused window
|
||||||
|
bindsym $mod+x kill
|
||||||
|
|
||||||
|
# execute command
|
||||||
|
bindsym $mod+r exec --no-startup-id dmenu_run
|
||||||
|
|
||||||
|
# change focus
|
||||||
|
bindsym $mod+$left focus left
|
||||||
|
bindsym $mod+$down focus down
|
||||||
|
bindsym $mod+$up focus up
|
||||||
|
bindsym $mod+$right focus right
|
||||||
|
|
||||||
|
# move focused window
|
||||||
|
bindsym $mod+Shift+$left move left
|
||||||
|
bindsym $mod+Shift+$down move down
|
||||||
|
bindsym $mod+Shift+$up move up
|
||||||
|
bindsym $mod+Shift+$right move right
|
||||||
|
|
||||||
|
# resize focused window
|
||||||
|
bindsym $mod+Ctrl+$left resize shrink width 10 px or 10 ppt
|
||||||
|
bindsym $mod+Ctrl+$down resize grow height 10 px or 10 ppt
|
||||||
|
bindsym $mod+Ctrl+$up resize shrink height 10 px or 10 ppt
|
||||||
|
bindsym $mod+Ctrl+$right resize grow width 10 px or 10 ppt
|
||||||
|
|
||||||
|
# change split orientation
|
||||||
|
bindsym $mod+v split toggle
|
||||||
|
|
||||||
|
# enter fullscreen mode for the focused container
|
||||||
|
bindsym $mod+f fullscreen toggle
|
||||||
|
|
||||||
|
# change container layout (stacked, tabbed, toggle split)
|
||||||
|
bindsym $mod+s layout stacking
|
||||||
|
bindsym $mod+w layout tabbed
|
||||||
|
bindsym $mod+e layout toggle split
|
||||||
|
|
||||||
|
# toggle tiling / floating
|
||||||
|
bindsym $mod+Shift+space floating toggle
|
||||||
|
|
||||||
|
# change focus between tiling / floating windows
|
||||||
|
bindsym $mod+space focus mode_toggle
|
||||||
|
|
||||||
|
# focus the parent container
|
||||||
|
bindsym $mod+a focus parent
|
||||||
|
|
||||||
|
# Define names for default workspaces for which we configure key bindings later on.
|
||||||
|
# We use variables to avoid repeating the names in multiple places.
|
||||||
|
set $ws1 "1"
|
||||||
|
set $ws2 "2"
|
||||||
|
set $ws3 "3"
|
||||||
|
set $ws4 "4"
|
||||||
|
set $ws5 "5"
|
||||||
|
set $ws6 "6"
|
||||||
|
set $ws7 "7"
|
||||||
|
set $ws8 "8"
|
||||||
|
set $ws9 "9"
|
||||||
|
set $ws10 "10"
|
||||||
|
|
||||||
|
# switch to workspace
|
||||||
|
bindsym $mod+1 workspace number $ws1
|
||||||
|
bindsym $mod+2 workspace number $ws2
|
||||||
|
bindsym $mod+3 workspace number $ws3
|
||||||
|
bindsym $mod+4 workspace number $ws4
|
||||||
|
bindsym $mod+5 workspace number $ws5
|
||||||
|
bindsym $mod+6 workspace number $ws6
|
||||||
|
bindsym $mod+7 workspace number $ws7
|
||||||
|
bindsym $mod+8 workspace number $ws8
|
||||||
|
bindsym $mod+9 workspace number $ws9
|
||||||
|
bindsym $mod+0 workspace number $ws10
|
||||||
|
bindsym $mod+Tab workspace back_and_forth
|
||||||
|
|
||||||
|
# move focused container to workspace
|
||||||
|
bindsym $mod+Shift+1 move container to workspace number $ws1
|
||||||
|
bindsym $mod+Shift+2 move container to workspace number $ws2
|
||||||
|
bindsym $mod+Shift+3 move container to workspace number $ws3
|
||||||
|
bindsym $mod+Shift+4 move container to workspace number $ws4
|
||||||
|
bindsym $mod+Shift+5 move container to workspace number $ws5
|
||||||
|
bindsym $mod+Shift+6 move container to workspace number $ws6
|
||||||
|
bindsym $mod+Shift+7 move container to workspace number $ws7
|
||||||
|
bindsym $mod+Shift+8 move container to workspace number $ws8
|
||||||
|
bindsym $mod+Shift+9 move container to workspace number $ws9
|
||||||
|
bindsym $mod+Shift+0 move container to workspace number $ws10
|
||||||
|
|
||||||
|
# reload/restart
|
||||||
|
bindsym $mod+Shift+c reload
|
||||||
|
bindsym $mod+Shift+r restart
|
||||||
|
|
||||||
|
# Lock screen
|
||||||
|
bindsym XF86ScreenSaver exec --no-startup-id xset s activate
|
||||||
|
bindsym $mod+Delete exec --no-startup-id xset s activate
|
||||||
|
|
||||||
|
# start stuff
|
||||||
|
exec_always --no-startup-id systemctl --user start --no-block wallpaper.service
|
27
dotfiles/gtkrc-2.0
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
gtk-theme-name="Adwaita-dark"
|
||||||
|
gtk-icon-theme-name="Adwaita"
|
||||||
|
gtk-cursor-theme-name="Adwaita"
|
||||||
|
gtk-cursor-theme-size=0
|
||||||
|
gtk-font-name="DejaVu Sans 10"
|
||||||
|
gtk-button-images=1
|
||||||
|
gtk-menu-images=1
|
||||||
|
gtk-fallback-icon-theme="gnome"
|
||||||
|
gtk-toolbar-style=GTK_TOOLBAR_BOTH
|
||||||
|
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
||||||
|
gtk-decoration-layout=":menu"
|
||||||
|
gtk-xft-antialias=1
|
||||||
|
gtk-xft-hinting=1
|
||||||
|
gtk-xft-hintstyle="hintslight"
|
||||||
|
gtk-xft-rgba="rgb"
|
||||||
|
|
||||||
|
gtk-key-theme-name="Emacs"
|
||||||
|
binding "vbe-text-entry-bindings" {
|
||||||
|
unbind "<ctrl>b"
|
||||||
|
unbind "<shift><ctrl>b"
|
||||||
|
unbind "<ctrl>f"
|
||||||
|
unbind "<shift><ctrl>f"
|
||||||
|
unbind "<ctrl>w"
|
||||||
|
bind "<alt>BackSpace" { "delete-from-cursor" (word-ends, -1) }
|
||||||
|
}
|
||||||
|
class "GtkEntry" binding "vbe-text-entry-bindings"
|
||||||
|
class "GtkTextView" binding "vbe-text-entry-bindings"
|
44
dotfiles/gtkrc-3.0
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* Useless: we cannot override properly by unbinding some keys */
|
||||||
|
/* @import url("/usr/share/themes/Emacs/gtk-3.0/gtk-keys.css"); */
|
||||||
|
|
||||||
|
@binding-set custom-text-entry
|
||||||
|
{
|
||||||
|
bind "<alt>b" { "move-cursor" (words, -1, 0) };
|
||||||
|
bind "<shift><alt>b" { "move-cursor" (words, -1, 1) };
|
||||||
|
bind "<alt>f" { "move-cursor" (words, 1, 0) };
|
||||||
|
bind "<shift><alt>f" { "move-cursor" (words, 1, 1) };
|
||||||
|
|
||||||
|
bind "<ctrl>a" { "move-cursor" (paragraph-ends, -1, 0) };
|
||||||
|
bind "<shift><ctrl>a" { "move-cursor" (paragraph-ends, -1, 1) };
|
||||||
|
bind "<ctrl>e" { "move-cursor" (paragraph-ends, 1, 0) };
|
||||||
|
bind "<shift><ctrl>e" { "move-cursor" (paragraph-ends, 1, 1) };
|
||||||
|
|
||||||
|
bind "<ctrl>y" { "paste-clipboard" () };
|
||||||
|
|
||||||
|
bind "<ctrl>d" { "delete-from-cursor" (chars, 1) };
|
||||||
|
bind "<alt>d" { "delete-from-cursor" (word-ends, 1) };
|
||||||
|
bind "<ctrl>k" { "delete-from-cursor" (paragraph-ends, 1) };
|
||||||
|
bind "<alt>backslash" { "delete-from-cursor" (whitespace, 1) };
|
||||||
|
bind "<alt>BackSpace" { "delete-from-cursor" (word-ends, -1) };
|
||||||
|
|
||||||
|
bind "<alt>space" { "delete-from-cursor" (whitespace, 1)
|
||||||
|
"insert-at-cursor" (" ") };
|
||||||
|
bind "<alt>KP_Space" { "delete-from-cursor" (whitespace, 1)
|
||||||
|
"insert-at-cursor" (" ") };
|
||||||
|
}
|
||||||
|
|
||||||
|
entry, textview
|
||||||
|
{
|
||||||
|
-gtk-key-bindings: custom-text-entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
.window-frame, .window-frame:backdrop {
|
||||||
|
box-shadow: 0 0 0 black;
|
||||||
|
border-style: none;
|
||||||
|
margin: 0;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.titlebar {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
9
dotfiles/qt5ct.conf
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[Appearance]
|
||||||
|
custom_palette=false
|
||||||
|
icon_theme=Adwaita
|
||||||
|
standard_dialogs=gtk3
|
||||||
|
style=Adwaita-dark
|
||||||
|
|
||||||
|
[Fonts]
|
||||||
|
fixed=@Variant(\0\0\0@\0\0\0 \0\x44\0\x65\0j\0\x61\0V\0u\0 \0S\0\x61\0n\0s\0 \0M\0o\0n\0o@$\0\0\0\0\0\0\xff\xff\xff\xff\x5\x1\0\x32\x10)
|
||||||
|
general=@Variant(\0\0\0@\0\0\0\x16\0\x44\0\x65\0j\0\x61\0V\0u\0 \0S\0\x61\0n\0s@$\0\0\0\0\0\0\xff\xff\xff\xff\x5\x1\0\x32\x10)
|
|
@ -1,9 +1,8 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Configure monitors on %I
|
Description=Configure monitors
|
||||||
PartOf=graphical-session@%i.target
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStart=/usr/bin/autorandr --change --default default
|
ExecStart=/usr/bin/autorandr --change --default default
|
||||||
LimitCORE=infinity
|
LimitCORE=infinity
|
||||||
Type=oneshot
|
Type=oneshot
|
14
dotfiles/systemd/i3.service
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[Unit]
|
||||||
|
Description=i3 window manager
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
After=autorandr.service
|
||||||
|
After=picom.service
|
||||||
|
After=xsettingsd.service
|
||||||
|
After=tmux.service
|
||||||
|
After=ssh-agent.service
|
||||||
|
Before=wallpaper.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/i3
|
||||||
|
ExecStopPost=/bin/systemctl --user stop graphical-session.target
|
||||||
|
Restart=on-failure
|
8
dotfiles/systemd/inputplug.service
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[Unit]
|
||||||
|
Description=XInput event monitor
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStartPre=/usr/bin/setxkbmap us
|
||||||
|
ExecStart=%h/.local/bin/inputplug -d -0 -c %h/.config/i3/bin/input-event
|
||||||
|
Restart=on-failure
|
11
dotfiles/systemd/misc-x.service
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Miscellaneous settings for X11
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
After=ssh-agent.service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/xset -b
|
||||||
|
ExecStart=/usr/bin/xsetroot -cursor_name left_ptr
|
||||||
|
ExecStart=%h/.config/i3/bin/ssh-add
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=false
|
12
dotfiles/systemd/picom.service
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Compositor for X11
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/picom --backend glx \
|
||||||
|
--xrender-sync-fence \
|
||||||
|
--vsync \
|
||||||
|
--opacity-rule 100:fullscreen \
|
||||||
|
--opacity-rule 85:!fullscreen \
|
||||||
|
--opacity-rule 100:focused
|
||||||
|
Restart=on-failure
|
|
@ -1,8 +1,7 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=PolicyKit authentication agent on %I
|
Description=PolicyKit authentication agent
|
||||||
PartOf=graphical-session@%i.target
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStart=/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1
|
ExecStart=/usr/lib/policykit-1-gnome/polkit-gnome-authentication-agent-1
|
||||||
Restart=on-failure
|
Restart=on-failure
|
|
@ -1,8 +1,7 @@
|
||||||
[Unit]
|
[Unit]
|
||||||
Description=Set color temperature on %I
|
Description=Set color temperature
|
||||||
PartOf=graphical-session@%i.target
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStart=/usr/bin/redshift -l manual:lon=2.35:lat=48.87 -t 6500:3900
|
ExecStart=/usr/bin/redshift -l manual:lon=2.35:lat=48.87 -t 6500:3900
|
||||||
Restart=on-failure
|
Restart=on-failure
|
12
dotfiles/systemd/ssh-agent.service
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[Unit]
|
||||||
|
Description=SSH key agent
|
||||||
|
Wants=dbus.socket
|
||||||
|
After=dbus.socket
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
|
||||||
|
ExecStartPre=/usr/bin/dbus-update-activation-environment --systemd SSH_AUTH_SOCK
|
||||||
|
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK
|
||||||
|
ExecStopPost=/usr/bin/dbus-update-activation-environment --systemd SSH_AUTH_SOCK=
|
||||||
|
Restart=always
|
14
dotfiles/systemd/wallpaper.service
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Build and display wallpaper
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Environment=WALLPAPER_DIRECTORY=%h/.config/i3/wallpapers
|
||||||
|
Environment=WALLPAPER_OUTPUT=%h/.cache/i3/current-wallpaper.png
|
||||||
|
ExecStart=/usr/bin/mkdir -p %h/.cache/i3
|
||||||
|
ExecStart=%h/.config/i3/bin/build-wallpaper --crop \
|
||||||
|
--directory $WALLPAPER_DIRECTORY \
|
||||||
|
--target $WALLPAPER_OUTPUT
|
||||||
|
ExecStart=/usr/bin/fvwm-root -r $WALLPAPER_OUTPUT
|
||||||
|
Type=oneshot
|
||||||
|
RemainAfterExit=false
|
7
dotfiles/systemd/wallpaper.timer
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Wallpaper rotation
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
[Timer]
|
||||||
|
OnUnitActiveSec=2h
|
||||||
|
RandomizedDelaySec=10m
|
7
dotfiles/systemd/xiccd.service
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[Unit]
|
||||||
|
Description=X color management
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/xiccd --edid
|
||||||
|
Restart=on-failure
|
17
dotfiles/systemd/xsession.target
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
[Unit]
|
||||||
|
Description=X session
|
||||||
|
BindsTo=graphical-session.target
|
||||||
|
Wants=autorandr.service
|
||||||
|
Wants=i3.service
|
||||||
|
Wants=picom.service
|
||||||
|
Wants=inputplug.service
|
||||||
|
Wants=misc-x.service
|
||||||
|
Wants=policykit-agent.service
|
||||||
|
Wants=redshift.service
|
||||||
|
Wants=wallpaper.timer
|
||||||
|
Wants=xiccd.service
|
||||||
|
Wants=xsettingsd.service
|
||||||
|
Wants=xss-lock.service
|
||||||
|
Wants=tmux.service
|
||||||
|
Wants=ssh-agent.service
|
||||||
|
Wants=pulseaudio.service
|
11
dotfiles/systemd/xsettingsd.service
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[Unit]
|
||||||
|
Description=XSETTINGS daemon
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Environment=SKIP_RELOAD=1
|
||||||
|
ExecStartPre=%h/.config/i3/bin/xsettingsd-setup
|
||||||
|
ExecStart=/usr/bin/xsettingsd -c %h/.xsettingsd
|
||||||
|
ExecReload=%h/.config/i3/bin/xsettingsd-setup
|
||||||
|
ExecReload=/usr/bin/kill -HUP $MAINPID
|
||||||
|
Restart=on-failure
|
7
dotfiles/systemd/xss-lock.service
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[Unit]
|
||||||
|
Description=Manage X screen saver
|
||||||
|
PartOf=graphical-session.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=%h/.config/i3/bin/xss-lock start
|
||||||
|
Restart=on-failure
|
|
@ -16,6 +16,6 @@ xkb_keymap {
|
||||||
xkb_compat { include "complete" };
|
xkb_compat { include "complete" };
|
||||||
xkb_symbols { include "pc+us+inet(evdev)"
|
xkb_symbols { include "pc+us+inet(evdev)"
|
||||||
include "compose(ralt)+ctrl(nocaps)"
|
include "compose(ralt)+ctrl(nocaps)"
|
||||||
include "vbe(x1)" };
|
include "vbe(x1gen2)" };
|
||||||
xkb_geometry { include "pc(pc105)" };
|
xkb_geometry { include "pc(pc105)" };
|
||||||
};
|
};
|
38
dotfiles/xsession
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Ensure we use the appropriate gtkrc-2.0 file
|
||||||
|
export GTK2_RC_FILES=$HOME/.gtkrc-2.0
|
||||||
|
|
||||||
|
# We do not want to rely on crappy mailcap
|
||||||
|
export MAILCAPS=$HOME/.mailcap
|
||||||
|
|
||||||
|
# Make QT automatically scale according to screen DPI
|
||||||
|
export QT_AUTO_SCREEN_SCALE_FACTOR=1
|
||||||
|
export QT_QPA_PLATFORMTHEME=qt5ct
|
||||||
|
|
||||||
|
# GTK3 apps try to contact org.a11y.Bus. Disable that.
|
||||||
|
export NO_AT_BRIDGE=1
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
unset LC_ALL
|
||||||
|
[ -e ~/.zshenv ] && . ~/.zshenv
|
||||||
|
|
||||||
|
# Copy some configuration files
|
||||||
|
while read source target; do
|
||||||
|
for t in $target; do
|
||||||
|
mkdir -p $(dirname $HOME/$t)
|
||||||
|
ln -nsf ~/.config/i3/dotfiles/$source $HOME/$t
|
||||||
|
done
|
||||||
|
done <<EOF
|
||||||
|
Xresources .Xresources
|
||||||
|
gtkrc-2.0 .gtkrc-2.0
|
||||||
|
gtkrc-3.0 .config/gtk-3.0/settings.ini
|
||||||
|
qt5ct.conf .config/qt5ct/qt5ct.conf
|
||||||
|
systemd .config/systemd/user
|
||||||
|
firefox.js .mozilla/firefox/*/user.js
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Services are started with systemd
|
||||||
|
systemctl --user import-environment
|
||||||
|
systemctl --user daemon-reload
|
||||||
|
exec systemctl --user start --wait xsession.target
|
Before Width: | Height: | Size: 182 B |
Before Width: | Height: | Size: 171 B |
Before Width: | Height: | Size: 180 B |
Before Width: | Height: | Size: 176 B |
Before Width: | Height: | Size: 173 B |
Before Width: | Height: | Size: 176 B |
Before Width: | Height: | Size: 204 B |
Before Width: | Height: | Size: 177 B |
Before Width: | Height: | Size: 168 B |
Before Width: | Height: | Size: 166 B |
Before Width: | Height: | Size: 173 B |
Before Width: | Height: | Size: 169 B |
Before Width: | Height: | Size: 179 B |
Before Width: | Height: | Size: 174 B |
Before Width: | Height: | Size: 184 B |
Before Width: | Height: | Size: 187 B |
Before Width: | Height: | Size: 193 B |
Before Width: | Height: | Size: 191 B |
Before Width: | Height: | Size: 163 B |
Before Width: | Height: | Size: 191 B |
Before Width: | Height: | Size: 198 B |
Before Width: | Height: | Size: 173 B |
Before Width: | Height: | Size: 171 B |
Before Width: | Height: | Size: 199 B |
Before Width: | Height: | Size: 160 B |
Before Width: | Height: | Size: 791 B |
Before Width: | Height: | Size: 765 B |
Before Width: | Height: | Size: 203 B |
Before Width: | Height: | Size: 287 B |
Before Width: | Height: | Size: 168 B |
|
@ -1,41 +0,0 @@
|
||||||
-- Handle brightness (with brightnessctl)
|
|
||||||
|
|
||||||
local awful = require("awful")
|
|
||||||
local naughty = require("naughty")
|
|
||||||
local math = math
|
|
||||||
local tonumber = tonumber
|
|
||||||
local string = string
|
|
||||||
local os = os
|
|
||||||
local dbg = dbg
|
|
||||||
|
|
||||||
-- A bit odd, but...
|
|
||||||
require("lib/icons")
|
|
||||||
local icons = package.loaded["vbe/icons"]
|
|
||||||
|
|
||||||
module("vbe/brightness")
|
|
||||||
|
|
||||||
local nid = nil
|
|
||||||
local function change(value)
|
|
||||||
-- Set new value
|
|
||||||
os.execute("brightnessctl -m s " .. value)
|
|
||||||
|
|
||||||
-- Get and display current value
|
|
||||||
current = awful.util.pread("brightnessctl -m i")
|
|
||||||
current = tonumber(string.match(current, ",(%d+)%%,"))
|
|
||||||
|
|
||||||
local icon = icons.lookup({name = "display-brightness",
|
|
||||||
type = "status"})
|
|
||||||
|
|
||||||
nid = naughty.notify({ text = string.format("%3d %%", current),
|
|
||||||
icon = icon,
|
|
||||||
font = "Free Sans Bold 24",
|
|
||||||
replaces_id = nid }).id
|
|
||||||
end
|
|
||||||
|
|
||||||
function increase()
|
|
||||||
change("5%+")
|
|
||||||
end
|
|
||||||
|
|
||||||
function decrease()
|
|
||||||
change("5%-")
|
|
||||||
end
|
|
|
@ -1,63 +0,0 @@
|
||||||
-- Lookup function for icons
|
|
||||||
|
|
||||||
local paths = {
|
|
||||||
"/usr/share/icons/Adwaita",
|
|
||||||
"/usr/share/icons/gnome",
|
|
||||||
"/usr/share/icons/hicolor",
|
|
||||||
"/usr/share/icons/HighContrast",
|
|
||||||
"/usr/share/fvwm-crystal/fvwm/icons/Default",
|
|
||||||
}
|
|
||||||
local sizes = {
|
|
||||||
'32x32',
|
|
||||||
'24x24',
|
|
||||||
'22x22',
|
|
||||||
'16x16',
|
|
||||||
}
|
|
||||||
local types = {
|
|
||||||
'apps',
|
|
||||||
'actions',
|
|
||||||
'devices',
|
|
||||||
'status',
|
|
||||||
}
|
|
||||||
local formats = {
|
|
||||||
".png",
|
|
||||||
".xpm"
|
|
||||||
}
|
|
||||||
|
|
||||||
local assert = assert
|
|
||||||
local type = type
|
|
||||||
local pairs = pairs
|
|
||||||
local awful = require("awful")
|
|
||||||
|
|
||||||
module("vbe/icons")
|
|
||||||
|
|
||||||
-- Lookup for an icon. Return full path.
|
|
||||||
function lookup(arg)
|
|
||||||
local inames = assert(arg.name)
|
|
||||||
local isizes = arg.size or sizes
|
|
||||||
local itypes = arg.type or types
|
|
||||||
local ipaths = paths
|
|
||||||
local iformats = formats
|
|
||||||
if type(isizes) ~= "table" then isizes = { isizes } end
|
|
||||||
if type(itypes) ~= "table" then itypes = { itypes } end
|
|
||||||
if type(inames) ~= "table" then inames = { inames } end
|
|
||||||
|
|
||||||
for _, path in pairs(ipaths) do
|
|
||||||
for _, size in pairs(isizes) do
|
|
||||||
for _, t in pairs(itypes) do
|
|
||||||
for _, name in pairs(inames) do
|
|
||||||
if name then
|
|
||||||
for _, name in pairs({name, name:lower()}) do
|
|
||||||
for _, ext in pairs(iformats) do
|
|
||||||
local icon = path .. "/" .. size .. "/" .. t .. "/" .. name .. ext
|
|
||||||
if awful.util.file_readable(icon) then
|
|
||||||
return icon
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
124
lib/keydoc.lua
|
@ -1,124 +0,0 @@
|
||||||
-- Document key bindings
|
|
||||||
|
|
||||||
local awful = require("awful")
|
|
||||||
local table = table
|
|
||||||
local ipairs = ipairs
|
|
||||||
local pairs = pairs
|
|
||||||
local math = math
|
|
||||||
local string = string
|
|
||||||
local type = type
|
|
||||||
local modkey = modkey
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local naughty = require("naughty")
|
|
||||||
local theme = beautiful.get()
|
|
||||||
local capi = {
|
|
||||||
root = root,
|
|
||||||
client = client
|
|
||||||
}
|
|
||||||
|
|
||||||
module("vbe/keydoc")
|
|
||||||
|
|
||||||
local doc = { }
|
|
||||||
local currentgroup = "Misc"
|
|
||||||
local orig = awful.key.new
|
|
||||||
|
|
||||||
-- Replacement for awful.key.new
|
|
||||||
local function new(mod, key, press, release, docstring)
|
|
||||||
-- Usually, there is no use of release, let's just use it for doc
|
|
||||||
-- if it's a string.
|
|
||||||
if press and release and not docstring and type(release) == "string" then
|
|
||||||
docstring = release
|
|
||||||
release = nil
|
|
||||||
end
|
|
||||||
local k = orig(mod, key, press, release)
|
|
||||||
-- Remember documentation for this key (we take the first one)
|
|
||||||
if k and #k > 0 and docstring then
|
|
||||||
doc[k[1]] = { help = docstring,
|
|
||||||
group = currentgroup }
|
|
||||||
end
|
|
||||||
|
|
||||||
return k
|
|
||||||
end
|
|
||||||
awful.key.new = new -- monkey patch
|
|
||||||
|
|
||||||
-- Turn a key to a string
|
|
||||||
local function key2str(key)
|
|
||||||
local sym = key.key or key.keysym
|
|
||||||
local translate = {
|
|
||||||
["#14"] = "#",
|
|
||||||
[" "] = "Space",
|
|
||||||
}
|
|
||||||
sym = translate[sym] or sym
|
|
||||||
if not key.modifiers or #key.modifiers == 0 then return sym end
|
|
||||||
local result = ""
|
|
||||||
local translate = {
|
|
||||||
[modkey] = "⊞",
|
|
||||||
Shift = "⇧",
|
|
||||||
Control = "Ctrl",
|
|
||||||
}
|
|
||||||
for _, mod in pairs(key.modifiers) do
|
|
||||||
mod = translate[mod] or mod
|
|
||||||
result = result .. mod .. " + "
|
|
||||||
end
|
|
||||||
return result .. sym
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Unicode "aware" length function (well, UTF8 aware)
|
|
||||||
-- See: http://lua-users.org/wiki/LuaUnicode
|
|
||||||
local function unilen(str)
|
|
||||||
local _, count = string.gsub(str, "[^\128-\193]", "")
|
|
||||||
return count
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Start a new group
|
|
||||||
function group(name)
|
|
||||||
currentgroup = name
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
|
|
||||||
local function markup(keys)
|
|
||||||
local result = {}
|
|
||||||
|
|
||||||
-- Compute longest key combination
|
|
||||||
local longest = 0
|
|
||||||
for _, key in ipairs(keys) do
|
|
||||||
if doc[key] then
|
|
||||||
longest = math.max(longest, unilen(key2str(key)))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local curgroup = nil
|
|
||||||
for _, key in ipairs(keys) do
|
|
||||||
if doc[key] then
|
|
||||||
local help, group = doc[key].help, doc[key].group
|
|
||||||
local skey = key2str(key)
|
|
||||||
result[group] = (result[group] or "") ..
|
|
||||||
'<span font="DejaVu Sans Mono ' .. 10 * theme.scale .. '" color="' .. beautiful.fg_widget_clock .. '"> ' ..
|
|
||||||
string.format("%" .. (longest - unilen(skey)) .. "s ", "") .. skey ..
|
|
||||||
'</span> <span color="' .. beautiful.fg_widget_value .. '">' ..
|
|
||||||
help .. '</span>\n'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Display help in a naughty notification
|
|
||||||
local nid = nil
|
|
||||||
function display()
|
|
||||||
local strings = awful.util.table.join(
|
|
||||||
markup(capi.root.keys()),
|
|
||||||
capi.client.focus and markup(capi.client.focus:keys()) or {})
|
|
||||||
|
|
||||||
local result = ""
|
|
||||||
for group, res in pairs(strings) do
|
|
||||||
if #result > 0 then result = result .. "\n" end
|
|
||||||
result = result ..
|
|
||||||
'<span weight="bold" color="' .. beautiful.fg_widget_value_important .. '">' ..
|
|
||||||
group .. "</span>\n" .. res
|
|
||||||
end
|
|
||||||
nid = naughty.notify({ text = result,
|
|
||||||
replaces_id = nid,
|
|
||||||
hover_timeout = 0.1,
|
|
||||||
timeout = 30 }).id
|
|
||||||
end
|
|
140
lib/quake.lua
|
@ -1,140 +0,0 @@
|
||||||
-- Quake like console on top
|
|
||||||
-- Similar to:
|
|
||||||
-- http://git.sysphere.org/awesome-configs/tree/scratch/drop.lua
|
|
||||||
|
|
||||||
-- But uses a different implementation. The main difference is that we
|
|
||||||
-- are able to detect the Quake console from its name
|
|
||||||
-- (QuakeConsoleNeedsUniqueName by default).
|
|
||||||
|
|
||||||
-- If you have a rule like "awful.client.setslave" for your terminals,
|
|
||||||
-- ensure you use an exception for
|
|
||||||
-- QuakeConsoleNeedsUniqueName. Otherwise, you may run into problems
|
|
||||||
-- with focus.
|
|
||||||
|
|
||||||
local setmetatable = setmetatable
|
|
||||||
local string = string
|
|
||||||
local awful = require("awful")
|
|
||||||
local capi = { mouse = mouse,
|
|
||||||
screen = screen,
|
|
||||||
client = client,
|
|
||||||
timer = timer }
|
|
||||||
|
|
||||||
-- I use a namespace for my modules...
|
|
||||||
module("vbe/quake")
|
|
||||||
|
|
||||||
local QuakeConsole = {}
|
|
||||||
|
|
||||||
-- Display
|
|
||||||
function QuakeConsole:display()
|
|
||||||
-- First, we locate the terminal
|
|
||||||
local client = nil
|
|
||||||
local i = 0
|
|
||||||
for c in awful.client.cycle(function (c)
|
|
||||||
-- c.name may be changed!
|
|
||||||
return (c.instance == self.name or c.role == self.name)
|
|
||||||
end) do
|
|
||||||
client = c
|
|
||||||
client:tags({})
|
|
||||||
break
|
|
||||||
end
|
|
||||||
|
|
||||||
if not client and not self.visible then
|
|
||||||
-- The terminal is not here yet but we don't want it yet. Just do nothing.
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if not client then
|
|
||||||
-- The client does not exist, we spawn it
|
|
||||||
awful.util.spawn(self.terminal .. " " .. string.format(self.argname, self.name))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Comptute size
|
|
||||||
local geom = capi.screen[capi.mouse.screen].workarea
|
|
||||||
local width, height = self.width, self.height
|
|
||||||
if width <= 1 then width = geom.width * width end
|
|
||||||
if height <= 1 then height = geom.height * height end
|
|
||||||
local x, y
|
|
||||||
if self.horiz == "left" then x = geom.x
|
|
||||||
elseif self.horiz == "right" then x = geom.width + geom.x - width
|
|
||||||
else x = geom.x + (geom.width - width)/2 end
|
|
||||||
if self.vert == "top" then y = geom.y
|
|
||||||
elseif self.vert == "bottom" then y = geom.height + geom.y - height
|
|
||||||
else y = geom.y + (geom.height - height)/2 end
|
|
||||||
|
|
||||||
-- Resize
|
|
||||||
awful.client.floating.set(client, true)
|
|
||||||
client.border_width = 0
|
|
||||||
client.size_hints_honor = false
|
|
||||||
client:geometry({ x = x, y = y, width = width, height = height })
|
|
||||||
|
|
||||||
-- Sticky and on top
|
|
||||||
client.ontop = true
|
|
||||||
client.above = true
|
|
||||||
client.skip_taskbar = true
|
|
||||||
client.sticky = true
|
|
||||||
|
|
||||||
-- This is not a normal window, don't apply any specific keyboard stuff
|
|
||||||
client:buttons({})
|
|
||||||
client:keys({})
|
|
||||||
|
|
||||||
-- Toggle display
|
|
||||||
if self.visible then
|
|
||||||
client.hidden = false
|
|
||||||
client:raise()
|
|
||||||
capi.client.focus = client
|
|
||||||
else
|
|
||||||
client.hidden = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Create a console
|
|
||||||
function QuakeConsole:new(config)
|
|
||||||
-- The "console" object is just its configuration.
|
|
||||||
|
|
||||||
-- The application to be invoked is:
|
|
||||||
-- config.terminal .. " " .. string.format(config.argname, config.name)
|
|
||||||
config.terminal = config.terminal or "xterm" -- application to spawn
|
|
||||||
config.name = config.name or "QuakeConsoleNeedsUniqueName" -- window name
|
|
||||||
config.argname = config.argname or "-name %s" -- how to specify window name
|
|
||||||
|
|
||||||
-- If width or height <= 1 this is a proportion of the workspace
|
|
||||||
config.height = config.height or 0.25 -- height
|
|
||||||
config.width = config.width or 1 -- width
|
|
||||||
config.vert = config.vert or "top" -- top, bottom or center
|
|
||||||
config.horiz = config.horiz or "center" -- left, right or center
|
|
||||||
|
|
||||||
config.visible = config.visible or false -- Initially, not visible
|
|
||||||
|
|
||||||
local console = setmetatable(config, { __index = QuakeConsole })
|
|
||||||
capi.client.add_signal("manage",
|
|
||||||
function(c)
|
|
||||||
if (c.instance == console.name or c.role == console.name) then
|
|
||||||
console:display()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
capi.client.add_signal("unmanage",
|
|
||||||
function(c)
|
|
||||||
if (c.instance == console.name or c.role == console.name) then
|
|
||||||
console.visible = false
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- "Reattach" currently running QuakeConsole. This is in case awesome is restarted.
|
|
||||||
local reattach = capi.timer { timeout = 0 }
|
|
||||||
reattach:add_signal("timeout",
|
|
||||||
function()
|
|
||||||
reattach:stop()
|
|
||||||
console:display()
|
|
||||||
end)
|
|
||||||
reattach:start()
|
|
||||||
return console
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Toggle the console
|
|
||||||
function QuakeConsole:toggle()
|
|
||||||
self.visible = not self.visible
|
|
||||||
self:display()
|
|
||||||
end
|
|
||||||
|
|
||||||
setmetatable(_M, { __call = function(_, ...) return QuakeConsole:new(...) end })
|
|
944
lib/shifty.lua
|
@ -1,944 +0,0 @@
|
||||||
--- Shifty: Dynamic tagging library for awesome3-git
|
|
||||||
-- @author koniu <gkusnierz@gmail.com>
|
|
||||||
-- @author resixian (aka bioe007) <resixian@gmail.com>
|
|
||||||
--
|
|
||||||
-- http://awesome.naquadah.org/wiki/index.php?title=Shifty
|
|
||||||
--
|
|
||||||
-- Modified version for my own use (Vincent Bernat)
|
|
||||||
--
|
|
||||||
-- TODO:
|
|
||||||
-- - Maybe name a tag after first client.
|
|
||||||
|
|
||||||
|
|
||||||
-- environment
|
|
||||||
local type = type
|
|
||||||
local ipairs = ipairs
|
|
||||||
local table = table
|
|
||||||
local string = string
|
|
||||||
local beautiful = require("beautiful")
|
|
||||||
local awful = require("awful")
|
|
||||||
local pairs = pairs
|
|
||||||
local io = io
|
|
||||||
local tonumber = tonumber
|
|
||||||
local dbg= dbg
|
|
||||||
local capi = {
|
|
||||||
client = client,
|
|
||||||
tag = tag,
|
|
||||||
image = image,
|
|
||||||
screen = screen,
|
|
||||||
button = button,
|
|
||||||
mouse = mouse,
|
|
||||||
root = root,
|
|
||||||
timer = timer
|
|
||||||
}
|
|
||||||
|
|
||||||
module("vbe/shifty")
|
|
||||||
|
|
||||||
-- variables
|
|
||||||
config = {}
|
|
||||||
config.tags = {}
|
|
||||||
config.apps = {}
|
|
||||||
config.defaults = {}
|
|
||||||
config.guess_name = true
|
|
||||||
config.remember_index = true
|
|
||||||
config.default_name = "…"
|
|
||||||
config.prompt_sources = {
|
|
||||||
"config_tags",
|
|
||||||
"config_apps",
|
|
||||||
"existing",
|
|
||||||
"history"
|
|
||||||
}
|
|
||||||
config.prompt_matchers = {
|
|
||||||
"^",
|
|
||||||
":",
|
|
||||||
""
|
|
||||||
}
|
|
||||||
|
|
||||||
local matchp = ""
|
|
||||||
local index_cache = {}
|
|
||||||
for i = 1, capi.screen.count() do index_cache[i] = {} end
|
|
||||||
|
|
||||||
--getname: return the "user" name of a tag
|
|
||||||
-- @param t : tag
|
|
||||||
-- @return username of the tag
|
|
||||||
local function getname(t)
|
|
||||||
local name = awful.tag.getproperty(t, "shortname")
|
|
||||||
if name then
|
|
||||||
return "" .. name
|
|
||||||
end
|
|
||||||
return t.name
|
|
||||||
end
|
|
||||||
|
|
||||||
--setname: set the "user" name of a tag and update its name
|
|
||||||
-- @param t : tag
|
|
||||||
-- @param name : new name
|
|
||||||
local function setname(t, name)
|
|
||||||
if name then
|
|
||||||
local dispname = "" .. name
|
|
||||||
local pos = awful.tag.getproperty(t, "position") or "?"
|
|
||||||
awful.tag.setproperty(t, "shortname", name)
|
|
||||||
if pos then
|
|
||||||
if "" .. pos ~= "" .. dispname then
|
|
||||||
dispname = pos .. '↭' .. dispname
|
|
||||||
end
|
|
||||||
end
|
|
||||||
t.name = dispname
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--freeposition: get a free position
|
|
||||||
local function freeposition()
|
|
||||||
local positions = {1, 2, 3, 4, 5, 6, 7, 8, 9}
|
|
||||||
for k, a in pairs(config.tags) do
|
|
||||||
if a.startup then
|
|
||||||
a = awful.util.table.join(a, a.startup)
|
|
||||||
end
|
|
||||||
if a.position then
|
|
||||||
local idx = awful.util.table.hasitem(positions, a.position)
|
|
||||||
if idx then
|
|
||||||
table.remove(positions, idx)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for s = 1, capi.screen.count() do
|
|
||||||
for i, t in ipairs(capi.screen[s]:tags()) do
|
|
||||||
local pos = awful.tag.getproperty(t, "position")
|
|
||||||
if pos then
|
|
||||||
local idx = awful.util.table.hasitem(positions, pos)
|
|
||||||
if idx then
|
|
||||||
table.remove(positions, idx)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #positions > 0 then
|
|
||||||
return positions[1]
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--name2tags: matches string 'name' to tag objects
|
|
||||||
-- @param name : tag name to find
|
|
||||||
-- @param scr : screen to look for tags on
|
|
||||||
-- @return table of tag objects or nil
|
|
||||||
function name2tags(name, scr)
|
|
||||||
local ret = {}
|
|
||||||
local a, b = scr or 1, scr or capi.screen.count()
|
|
||||||
for s = a, b do
|
|
||||||
for i, t in ipairs(capi.screen[s]:tags()) do
|
|
||||||
if name == getname(t) then
|
|
||||||
table.insert(ret, t)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #ret > 0 then return ret end
|
|
||||||
end
|
|
||||||
|
|
||||||
function name2tag(name, scr, idx)
|
|
||||||
local ts = name2tags(name, scr)
|
|
||||||
if ts then return ts[idx or 1] end
|
|
||||||
end
|
|
||||||
|
|
||||||
--tag2index: finds index of a tag object
|
|
||||||
-- @param scr : screen number to look for tag on
|
|
||||||
-- @param tag : the tag object to find
|
|
||||||
-- @return the index [or zero] or end of the list
|
|
||||||
function tag2index(scr, tag)
|
|
||||||
for i, t in ipairs(capi.screen[scr]:tags()) do
|
|
||||||
if t == tag then return i end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--rename
|
|
||||||
--@param tag: tag object to be renamed
|
|
||||||
function rename(tag, no_selectall)
|
|
||||||
local theme = beautiful.get()
|
|
||||||
local t = tag or awful.tag.selected(capi.mouse.screen)
|
|
||||||
local scr = t.screen
|
|
||||||
local bg = nil
|
|
||||||
local fg = nil
|
|
||||||
local text = getname(t)
|
|
||||||
local before = getname(t)
|
|
||||||
|
|
||||||
if t == awful.tag.selected(scr) then
|
|
||||||
bg = theme.bg_focus or '#535d6c'
|
|
||||||
fg = theme.fg_urgent or '#ffffff'
|
|
||||||
else
|
|
||||||
bg = theme.bg_normal or '#222222'
|
|
||||||
fg = theme.fg_urgent or '#ffffff'
|
|
||||||
end
|
|
||||||
|
|
||||||
awful.prompt.run({
|
|
||||||
fg_cursor = fg, bg_cursor = bg, ul_cursor = "single",
|
|
||||||
text = text, selectall = not no_selectall},
|
|
||||||
taglist[scr][tag2index(scr, t) * 2],
|
|
||||||
function (name) if name:len() > 0 then setname(t, name); end end,
|
|
||||||
completion,
|
|
||||||
awful.util.getdir("cache") .. "/history_tags",
|
|
||||||
nil,
|
|
||||||
function ()
|
|
||||||
if getname(t) == before then
|
|
||||||
if awful.tag.getproperty(t, "initial") then del(t) end
|
|
||||||
else
|
|
||||||
awful.tag.setproperty(t, "initial", true)
|
|
||||||
set(t)
|
|
||||||
end
|
|
||||||
t:emit_signal("property::name")
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
--send: moves client to tag[idx]
|
|
||||||
-- maybe this isn't needed here in shifty?
|
|
||||||
-- @param idx the tag number to send a client to
|
|
||||||
function send(idx)
|
|
||||||
local scr = capi.client.focus.screen or capi.mouse.screen
|
|
||||||
local sel = awful.tag.selected(scr)
|
|
||||||
local sel_idx = tag2index(scr, sel)
|
|
||||||
local tags = capi.screen[scr]:tags()
|
|
||||||
local target = awful.util.cycle(#tags, sel_idx + idx)
|
|
||||||
awful.client.movetotag(tags[target], capi.client.focus)
|
|
||||||
awful.tag.viewonly(tags[target])
|
|
||||||
end
|
|
||||||
|
|
||||||
function send_next() send(1) end
|
|
||||||
function send_prev() send(-1) end
|
|
||||||
|
|
||||||
--pos2idx: translate shifty position to tag index
|
|
||||||
--@param pos: position (an integer)
|
|
||||||
--@param scr: screen number
|
|
||||||
function pos2idx(pos, scr)
|
|
||||||
local v = 1
|
|
||||||
if pos and scr then
|
|
||||||
for i = #capi.screen[scr]:tags() , 1, -1 do
|
|
||||||
local t = capi.screen[scr]:tags()[i]
|
|
||||||
if awful.tag.getproperty(t, "position") and
|
|
||||||
awful.tag.getproperty(t, "position") <= pos then
|
|
||||||
v = i + 1
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
|
|
||||||
--select : helper function chooses the first non-nil argument
|
|
||||||
--@param args - table of arguments
|
|
||||||
function select(args)
|
|
||||||
for i, a in pairs(args) do
|
|
||||||
if a ~= nil then
|
|
||||||
return a
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--tagtoscr : move an entire tag to another screen
|
|
||||||
--
|
|
||||||
--@param scr : the screen to move tag to
|
|
||||||
--@param t : the tag to be moved [awful.tag.selected()]
|
|
||||||
--@return the tag
|
|
||||||
function tagtoscr(scr, t)
|
|
||||||
-- break if called with an invalid screen number
|
|
||||||
if not scr or scr < 1 or scr > capi.screen.count() then return end
|
|
||||||
-- tag to move
|
|
||||||
local otag = t or awful.tag.selected()
|
|
||||||
|
|
||||||
otag.screen = scr
|
|
||||||
-- set screen and then reset tag to order properly
|
|
||||||
if #otag:clients() > 0 then
|
|
||||||
for _ , c in ipairs(otag:clients()) do
|
|
||||||
if not c.sticky then
|
|
||||||
c.screen = scr
|
|
||||||
c:tags({otag})
|
|
||||||
else
|
|
||||||
awful.client.toggletag(otag, c)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return otag
|
|
||||||
end
|
|
||||||
|
|
||||||
--set : set a tags properties
|
|
||||||
--@param t: the tag
|
|
||||||
--@param args : a table of optional (?) tag properties
|
|
||||||
--@return t - the tag object
|
|
||||||
function set(t, args)
|
|
||||||
if not t then return end
|
|
||||||
if not args then args = {} end
|
|
||||||
|
|
||||||
-- set the name
|
|
||||||
setname(t, args.name or getname(t))
|
|
||||||
|
|
||||||
-- attempt to load preset on initial run
|
|
||||||
local preset = (awful.tag.getproperty(t, "initial") and
|
|
||||||
config.tags[getname(t)]) or {}
|
|
||||||
|
|
||||||
-- pick screen and get its tag table
|
|
||||||
local scr = args.screen or
|
|
||||||
(not t.screen and preset.screen) or
|
|
||||||
t.screen or
|
|
||||||
capi.mouse.screen
|
|
||||||
|
|
||||||
local clientstomove = nil
|
|
||||||
if scr > capi.screen.count() then scr = capi.screen.count() end
|
|
||||||
if t.screen and scr ~= t.screen then
|
|
||||||
tagtoscr(scr, t)
|
|
||||||
t.screen = nil
|
|
||||||
end
|
|
||||||
local tags = capi.screen[scr]:tags()
|
|
||||||
|
|
||||||
-- allow preset.layout to be a table to provide a different layout per
|
|
||||||
-- screen for a given tag
|
|
||||||
local preset_layout = preset.layout
|
|
||||||
if preset_layout and preset_layout[scr] then
|
|
||||||
preset_layout = preset.layout[scr]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- select from args, preset, getproperty,
|
|
||||||
-- config.defaults.configs or defaults
|
|
||||||
local props = {
|
|
||||||
layout = select{args.layout, preset_layout,
|
|
||||||
awful.tag.getproperty(t, "layout"),
|
|
||||||
config.defaults.layout, awful.layout.suit.tile},
|
|
||||||
mwfact = select{args.mwfact, preset.mwfact,
|
|
||||||
awful.tag.getproperty(t, "mwfact"),
|
|
||||||
config.defaults.mwfact, 0.55},
|
|
||||||
nmaster = select{args.nmaster, preset.nmaster,
|
|
||||||
awful.tag.getproperty(t, "nmaster"),
|
|
||||||
config.defaults.nmaster, 1},
|
|
||||||
ncol = select{args.ncol, preset.ncol,
|
|
||||||
awful.tag.getproperty(t, "ncol"),
|
|
||||||
config.defaults.ncol, 1},
|
|
||||||
matched = select{args.matched, awful.tag.getproperty(t, "matched")},
|
|
||||||
exclusive = select{args.exclusive, preset.exclusive,
|
|
||||||
awful.tag.getproperty(t, "exclusive"),
|
|
||||||
config.defaults.exclusive},
|
|
||||||
persist = select{args.persist, preset.persist,
|
|
||||||
awful.tag.getproperty(t, "persist"),
|
|
||||||
config.defaults.persist},
|
|
||||||
nopopup = select{args.nopopup, preset.nopopup,
|
|
||||||
awful.tag.getproperty(t, "nopopup"),
|
|
||||||
config.defaults.nopopup},
|
|
||||||
leave_kills = select{args.leave_kills, preset.leave_kills,
|
|
||||||
awful.tag.getproperty(t, "leave_kills"),
|
|
||||||
config.defaults.leave_kills},
|
|
||||||
max_clients = select{args.max_clients, preset.max_clients,
|
|
||||||
awful.tag.getproperty(t, "max_clients"),
|
|
||||||
config.defaults.max_clients},
|
|
||||||
position = select{args.position, preset.position,
|
|
||||||
awful.tag.getproperty(t, "position"), freeposition()},
|
|
||||||
icon = select{args.icon and capi.image(args.icon),
|
|
||||||
preset.icon and capi.image(preset.icon),
|
|
||||||
awful.tag.getproperty(t, "icon"),
|
|
||||||
config.defaults.icon and capi.image(config.defaults.icon)},
|
|
||||||
icon_only = select{args.icon_only, preset.icon_only,
|
|
||||||
awful.tag.getproperty(t, "icon_only"),
|
|
||||||
config.defaults.icon_only},
|
|
||||||
sweep_delay = select{args.sweep_delay, preset.sweep_delay,
|
|
||||||
awful.tag.getproperty(t, "sweep_delay"),
|
|
||||||
config.defaults.sweep_delay},
|
|
||||||
}
|
|
||||||
|
|
||||||
-- calculate desired taglist index
|
|
||||||
local index = args.index or preset.index or config.defaults.index
|
|
||||||
local rel_index = args.rel_index or
|
|
||||||
preset.rel_index or
|
|
||||||
config.defaults.rel_index
|
|
||||||
local sel = awful.tag.selected(scr)
|
|
||||||
--TODO: what happens with rel_idx if no tags selected
|
|
||||||
local sel_idx = (sel and tag2index(scr, sel)) or 0
|
|
||||||
local t_idx = tag2index(scr, t)
|
|
||||||
local limit = (not t_idx and #tags + 1) or #tags
|
|
||||||
local idx = nil
|
|
||||||
|
|
||||||
if rel_index then
|
|
||||||
idx = awful.util.cycle(limit, (t_idx or sel_idx) + rel_index)
|
|
||||||
elseif index then
|
|
||||||
idx = awful.util.cycle(limit, index)
|
|
||||||
elseif props.position then
|
|
||||||
idx = pos2idx(props.position, scr)
|
|
||||||
if t_idx and t_idx < idx then idx = idx - 1 end
|
|
||||||
elseif config.remember_index and index_cache[scr][getname(t)] then
|
|
||||||
idx = index_cache[scr][getname(t)]
|
|
||||||
elseif not t_idx then
|
|
||||||
idx = #tags + 1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- if we have a new index, remove from old index and insert
|
|
||||||
if idx then
|
|
||||||
if t_idx then table.remove(tags, t_idx) end
|
|
||||||
table.insert(tags, idx, t)
|
|
||||||
index_cache[scr][getname(t)] = idx
|
|
||||||
end
|
|
||||||
|
|
||||||
-- set tag properties and push the new tag table
|
|
||||||
capi.screen[scr]:tags(tags)
|
|
||||||
for prop, val in pairs(props) do awful.tag.setproperty(t, prop, val) end
|
|
||||||
|
|
||||||
-- execute run/spawn
|
|
||||||
if awful.tag.getproperty(t, "initial") then
|
|
||||||
if not args.nospawn then
|
|
||||||
local spawn = args.spawn or preset.spawn or config.defaults.spawn
|
|
||||||
local run = args.run or preset.run or config.defaults.run
|
|
||||||
if spawn and args.matched ~= true then
|
|
||||||
awful.util.spawn_with_shell(spawn, scr)
|
|
||||||
end
|
|
||||||
if run then run(t) end
|
|
||||||
end
|
|
||||||
awful.tag.setproperty(t, "initial", nil)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
function shift_next() set(awful.tag.selected(), {rel_index = 1}) end
|
|
||||||
function shift_prev() set(awful.tag.selected(), {rel_index = -1}) end
|
|
||||||
|
|
||||||
--add : adds a tag
|
|
||||||
--@param args: table of optional arguments
|
|
||||||
function add(args)
|
|
||||||
if not args then args = {} end
|
|
||||||
local name = args.name or " "
|
|
||||||
|
|
||||||
-- initialize a new tag object and its data structure
|
|
||||||
local t = capi.tag{name = name}
|
|
||||||
|
|
||||||
-- tell set() that this is the first time
|
|
||||||
awful.tag.setproperty(t, "initial", true)
|
|
||||||
|
|
||||||
-- apply tag settings
|
|
||||||
set(t, args)
|
|
||||||
|
|
||||||
-- unless forbidden or if first tag on the screen, show the tag
|
|
||||||
if not (awful.tag.getproperty(t, "nopopup") or args.noswitch) or
|
|
||||||
#capi.screen[t.screen]:tags() == 1 then
|
|
||||||
awful.tag.viewonly(t)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- get the name or rename
|
|
||||||
if args.name then
|
|
||||||
setname(t, args.name)
|
|
||||||
else
|
|
||||||
-- FIXME: hack to delay rename for un-named tags for
|
|
||||||
-- tackling taglist refresh which disabled prompt
|
|
||||||
-- from being rendered until input
|
|
||||||
awful.tag.setproperty(t, "initial", true)
|
|
||||||
local tmr
|
|
||||||
local f = function() rename(t); tmr:stop() end
|
|
||||||
tmr = capi.timer({timeout = 0.01})
|
|
||||||
tmr:add_signal("timeout", f)
|
|
||||||
tmr:start()
|
|
||||||
end
|
|
||||||
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
--del : delete a tag
|
|
||||||
--@param tag : the tag to be deleted [current tag]
|
|
||||||
function del(tag)
|
|
||||||
local scr = (tag and tag.screen) or capi.mouse.screen or 1
|
|
||||||
local tags = capi.screen[scr]:tags()
|
|
||||||
local sel = awful.tag.selected(scr)
|
|
||||||
local t = tag or sel
|
|
||||||
local idx = tag2index(scr, t)
|
|
||||||
|
|
||||||
-- return if tag not empty (except sticky)
|
|
||||||
local clients = t:clients()
|
|
||||||
local sticky = 0
|
|
||||||
for i, c in ipairs(clients) do
|
|
||||||
if c.sticky then sticky = sticky + 1 end
|
|
||||||
end
|
|
||||||
if #clients > sticky then return false end
|
|
||||||
|
|
||||||
-- store index for later
|
|
||||||
index_cache[scr][getname(t)] = idx
|
|
||||||
|
|
||||||
-- remove tag
|
|
||||||
t.screen = nil
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
--is_client_tagged : replicate behavior in tag.c - returns true if the
|
|
||||||
--given client is tagged with the given tag
|
|
||||||
function is_client_tagged(tag, client)
|
|
||||||
for i, c in ipairs(tag:clients()) do
|
|
||||||
if c == client then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
--match : handles app->tag matching, a replacement for the manage hook in
|
|
||||||
-- rc.lua
|
|
||||||
--@param c : client to be matched
|
|
||||||
function match(c, startup)
|
|
||||||
local nopopup, intrusive, nofocus, run, slave
|
|
||||||
local target_tag_names, target_tags = {}, {}
|
|
||||||
local typ = c.type
|
|
||||||
local cls = c.class
|
|
||||||
local inst = c.instance
|
|
||||||
local role = c.role
|
|
||||||
local name = c.name
|
|
||||||
local target_screen = capi.mouse.screen
|
|
||||||
|
|
||||||
-- try matching client to config.apps
|
|
||||||
for i, a in ipairs(config.apps) do
|
|
||||||
if a.match then
|
|
||||||
local matched = false
|
|
||||||
-- match function
|
|
||||||
if not matched and a.match.check then
|
|
||||||
matched = a.match.check(c)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- match only class
|
|
||||||
if not matched and cls and a.match.class then
|
|
||||||
for k, w in ipairs(a.match.class) do
|
|
||||||
matched = cls:find(w)
|
|
||||||
if matched then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- match only instance
|
|
||||||
if not matched and inst and a.match.instance then
|
|
||||||
for k, w in ipairs(a.match.instance) do
|
|
||||||
matched = inst:find(w)
|
|
||||||
if matched then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- match only name
|
|
||||||
if not matched and name and a.match.name then
|
|
||||||
for k, w in ipairs(a.match.name) do
|
|
||||||
matched = name:find(w)
|
|
||||||
if matched then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- match only role
|
|
||||||
if not matched and role and a.match.role then
|
|
||||||
for k, w in ipairs(a.match.role) do
|
|
||||||
matched = (role == w)
|
|
||||||
if matched then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- match only type
|
|
||||||
if not matched and typ and a.match.type then
|
|
||||||
for k, w in ipairs(a.match.type) do
|
|
||||||
matched = typ:find(w)
|
|
||||||
if matched then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- check everything else against all attributes
|
|
||||||
if not matched then
|
|
||||||
for k, w in ipairs(a.match) do
|
|
||||||
matched = (cls and cls:find(w)) or
|
|
||||||
(inst and inst:find(w)) or
|
|
||||||
(name and name:find(w)) or
|
|
||||||
(role and (role == w)) or
|
|
||||||
(typ and typ:find(w))
|
|
||||||
if matched then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- set attributes
|
|
||||||
if matched then
|
|
||||||
if a.startup and startup then
|
|
||||||
a = awful.util.table.join(a, a.startup)
|
|
||||||
end
|
|
||||||
if a.screen then target_screen = a.screen end
|
|
||||||
if a.tag then
|
|
||||||
if type(a.tag) == "string" then
|
|
||||||
target_tag_names = {a.tag}
|
|
||||||
else
|
|
||||||
target_tag_names = a.tag
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if a.slave ~=nil then slave = a.slave end
|
|
||||||
if a.nopopup ~=nil then nopopup = a.nopopup end
|
|
||||||
if a.intrusive ~=nil then
|
|
||||||
intrusive = a.intrusive
|
|
||||||
end
|
|
||||||
if a.nofocus ~= nil then nofocus = a.nofocus end
|
|
||||||
if a.run ~= nil then run = a.run end
|
|
||||||
if a.props then
|
|
||||||
for kk, vv in pairs(a.props) do
|
|
||||||
awful.client.property.set(c, kk, vv)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local sel = awful.tag.selectedlist(target_screen)
|
|
||||||
if not target_tag_names or #target_tag_names == 0 then
|
|
||||||
-- if not matched to some names try putting
|
|
||||||
-- client in c.transient_for or current tags
|
|
||||||
if c.transient_for then
|
|
||||||
target_tags = c.transient_for:tags()
|
|
||||||
elseif #sel > 0 then
|
|
||||||
for i, t in ipairs(sel) do
|
|
||||||
local mc = awful.tag.getproperty(t, "max_clients")
|
|
||||||
if intrusive or c.type == "dialog" or
|
|
||||||
not (awful.tag.getproperty(t, "exclusive") or
|
|
||||||
(mc and mc >= #t:clients())) then
|
|
||||||
table.insert(target_tags, t)
|
|
||||||
if config.guess_name and cls then
|
|
||||||
if getname(t) == config.default_name or
|
|
||||||
getname(t) == "" .. (awful.tag.getproperty(t, "position") or "?") then
|
|
||||||
setname(t, cls:lower())
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if (not target_tag_names or #target_tag_names == 0) and
|
|
||||||
(not target_tags or #target_tags == 0) then
|
|
||||||
-- if we still don't know any target names/tags guess
|
|
||||||
-- name from class or use default
|
|
||||||
if config.guess_name and cls then
|
|
||||||
target_tag_names = {cls:lower()}
|
|
||||||
else
|
|
||||||
target_tag_names = {config.default_name}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if #target_tag_names > 0 and #target_tags == 0 then
|
|
||||||
-- translate target names to tag objects, creating
|
|
||||||
-- missing ones
|
|
||||||
for i, tn in ipairs(target_tag_names) do
|
|
||||||
local res = {}
|
|
||||||
for j, t in ipairs(name2tags(tn, target_screen) or
|
|
||||||
name2tags(tn) or {}) do
|
|
||||||
local mc = awful.tag.getproperty(t, "max_clients")
|
|
||||||
local tagged = is_client_tagged(t, c)
|
|
||||||
if intrusive or
|
|
||||||
not (mc and (((#t:clients() >= mc) and not
|
|
||||||
tagged) or
|
|
||||||
(#t:clients() > mc))) or
|
|
||||||
intrusive then
|
|
||||||
table.insert(res, t)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #res == 0 then
|
|
||||||
table.insert(target_tags,
|
|
||||||
add({name = tn,
|
|
||||||
noswitch = true,
|
|
||||||
matched = true}))
|
|
||||||
else
|
|
||||||
target_tags = awful.util.table.join(target_tags, res)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- set client's screen/tag if needed
|
|
||||||
target_screen = target_tags[1].screen or target_screen
|
|
||||||
if c.screen ~= target_screen then c.screen = target_screen end
|
|
||||||
if slave then awful.client.setslave(c) end
|
|
||||||
c:tags(target_tags)
|
|
||||||
|
|
||||||
local showtags = {}
|
|
||||||
local u = nil
|
|
||||||
if #target_tags > 0 and not startup then
|
|
||||||
-- switch or highlight
|
|
||||||
for i, t in ipairs(target_tags) do
|
|
||||||
if not (nopopup or awful.tag.getproperty(t, "nopopup")) then
|
|
||||||
table.insert(showtags, t)
|
|
||||||
elseif not startup then
|
|
||||||
c.urgent = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if #showtags > 0 then
|
|
||||||
local ident = false
|
|
||||||
-- iterate selected tags and and see if any targets
|
|
||||||
-- currently selected
|
|
||||||
for kk, vv in pairs(showtags) do
|
|
||||||
for _, tag in pairs(sel) do
|
|
||||||
if tag == vv then
|
|
||||||
ident = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not ident then
|
|
||||||
awful.tag.viewmore(showtags, c.screen)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if nofocus then
|
|
||||||
--focus and raise accordingly or lower if supressed
|
|
||||||
if (target and target ~= sel) and
|
|
||||||
(awful.tag.getproperty(target, "nopopup") or nopopup) then
|
|
||||||
awful.client.focus.history.add(c)
|
|
||||||
else
|
|
||||||
capi.client.focus = c
|
|
||||||
end
|
|
||||||
c:raise()
|
|
||||||
else
|
|
||||||
c:lower()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- execute run function if specified
|
|
||||||
if run then run(c, target) end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--sweep : hook function that marks tags as used, visited,
|
|
||||||
--deserted also handles deleting used and empty tags
|
|
||||||
function sweep()
|
|
||||||
for s = 1, capi.screen.count() do
|
|
||||||
for i, t in ipairs(capi.screen[s]:tags()) do
|
|
||||||
local clients = t:clients()
|
|
||||||
local sticky = 0
|
|
||||||
for i, c in ipairs(clients) do
|
|
||||||
if c.sticky then sticky = sticky + 1 end
|
|
||||||
end
|
|
||||||
if #clients == sticky then
|
|
||||||
if awful.tag.getproperty(t, "used") and
|
|
||||||
not awful.tag.getproperty(t, "persist") then
|
|
||||||
if awful.tag.getproperty(t, "deserted") or
|
|
||||||
not awful.tag.getproperty(t, "leave_kills") then
|
|
||||||
local delay = awful.tag.getproperty(t, "sweep_delay")
|
|
||||||
if delay then
|
|
||||||
local tmr
|
|
||||||
local f = function()
|
|
||||||
del(t)
|
|
||||||
tmr:stop()
|
|
||||||
end
|
|
||||||
tmr = capi.timer({timeout = delay})
|
|
||||||
tmr:add_signal("timeout", f)
|
|
||||||
tmr:start()
|
|
||||||
else
|
|
||||||
del(t)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if awful.tag.getproperty(t, "visited") and
|
|
||||||
not t.selected then
|
|
||||||
awful.tag.setproperty(t, "deserted", true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
awful.tag.setproperty(t, "used", true)
|
|
||||||
end
|
|
||||||
if t.selected then
|
|
||||||
awful.tag.setproperty(t, "visited", true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--getpos : returns a tag to match position
|
|
||||||
-- @param pos : the index to find
|
|
||||||
-- @return v : the tag (found or created) at position == 'pos'
|
|
||||||
function getpos(pos, args)
|
|
||||||
local v = nil
|
|
||||||
local existing = {}
|
|
||||||
local selected = nil
|
|
||||||
local scr = capi.mouse.screen or 1
|
|
||||||
local args = args or {}
|
|
||||||
|
|
||||||
-- search for existing tag assigned to pos
|
|
||||||
for i = 1, capi.screen.count() do
|
|
||||||
for j, t in ipairs(capi.screen[i]:tags()) do
|
|
||||||
if awful.tag.getproperty(t, "position") == pos then
|
|
||||||
table.insert(existing, t)
|
|
||||||
if t.selected and i == scr then
|
|
||||||
selected = #existing
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if #existing > 0 then
|
|
||||||
-- if making another of an existing tag, return the end of
|
|
||||||
-- the list the optional 2nd argument decides if we return
|
|
||||||
-- only
|
|
||||||
v = (selected and
|
|
||||||
existing[awful.util.cycle(#existing, selected + 1)]) or
|
|
||||||
existing[1]
|
|
||||||
end
|
|
||||||
if not v then
|
|
||||||
-- search for preconf with 'pos' and create it
|
|
||||||
for i, j in pairs(config.tags) do
|
|
||||||
if j.position == pos then
|
|
||||||
v = add({name = i,
|
|
||||||
position = pos,
|
|
||||||
noswitch = true,
|
|
||||||
nospawn = args.nospawn})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not v then
|
|
||||||
-- not existing, not preconfigured
|
|
||||||
v = add({position = pos,
|
|
||||||
name = pos,
|
|
||||||
noswitch = true,
|
|
||||||
nospawn = args.nospawn})
|
|
||||||
end
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
|
|
||||||
--init : search shifty.config.tags for initial set of
|
|
||||||
--tags to open
|
|
||||||
function init()
|
|
||||||
local numscr = capi.screen.count()
|
|
||||||
|
|
||||||
for i, j in pairs(config.tags) do
|
|
||||||
local scr = j.screen or {1}
|
|
||||||
if type(scr) ~= 'table' then
|
|
||||||
scr = {scr}
|
|
||||||
end
|
|
||||||
for _, s in pairs(scr) do
|
|
||||||
if j.init and (s <= numscr) then
|
|
||||||
add({name = i,
|
|
||||||
persist = true,
|
|
||||||
screen = s,
|
|
||||||
layout = j.layout,
|
|
||||||
mwfact = j.mwfact})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--count : utility function returns the index of a table element
|
|
||||||
--FIXME: this is currently used only in remove_dup, so is it really
|
|
||||||
--necessary?
|
|
||||||
function count(table, element)
|
|
||||||
local v = 0
|
|
||||||
for i, e in pairs(table) do
|
|
||||||
if element == e then v = v + 1 end
|
|
||||||
end
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
|
|
||||||
--remove_dup : used by shifty.completion when more than one
|
|
||||||
--tag at a position exists
|
|
||||||
function remove_dup(table)
|
|
||||||
local v = {}
|
|
||||||
for i, entry in ipairs(table) do
|
|
||||||
if count(v, entry) == 0 then v[#v+ 1] = entry end
|
|
||||||
end
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
|
|
||||||
--completion : prompt completion
|
|
||||||
--
|
|
||||||
function completion(cmd, cur_pos, ncomp, sources, matchers)
|
|
||||||
|
|
||||||
-- get sources and matches tables
|
|
||||||
sources = sources or config.prompt_sources
|
|
||||||
matchers = matchers or config.prompt_matchers
|
|
||||||
|
|
||||||
local get_source = {
|
|
||||||
-- gather names from config.tags
|
|
||||||
config_tags = function()
|
|
||||||
local ret = {}
|
|
||||||
for n, p in pairs(config.tags) do
|
|
||||||
table.insert(ret, n)
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end,
|
|
||||||
-- gather names from config.apps
|
|
||||||
config_apps = function()
|
|
||||||
local ret = {}
|
|
||||||
for i, p in pairs(config.apps) do
|
|
||||||
if p.tag then
|
|
||||||
if type(p.tag) == "string" then
|
|
||||||
table.insert(ret, p.tag)
|
|
||||||
else
|
|
||||||
ret = awful.util.table.join(ret, p.tag)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end,
|
|
||||||
-- gather names from existing tags, starting with the
|
|
||||||
-- current screen
|
|
||||||
existing = function()
|
|
||||||
local ret = {}
|
|
||||||
for i = 1, capi.screen.count() do
|
|
||||||
local s = awful.util.cycle(capi.screen.count(),
|
|
||||||
capi.mouse.screen + i - 1)
|
|
||||||
local tags = capi.screen[s]:tags()
|
|
||||||
for j, t in pairs(tags) do
|
|
||||||
table.insert(ret, getname(t))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return ret
|
|
||||||
end,
|
|
||||||
-- gather names from history
|
|
||||||
history = function()
|
|
||||||
local ret = {}
|
|
||||||
local f = io.open(awful.util.getdir("cache") ..
|
|
||||||
"/history_tags")
|
|
||||||
for name in f:lines() do table.insert(ret, name) end
|
|
||||||
f:close()
|
|
||||||
return ret
|
|
||||||
end,
|
|
||||||
}
|
|
||||||
|
|
||||||
-- if empty, match all
|
|
||||||
if #cmd == 0 or cmd == " " then cmd = "" end
|
|
||||||
|
|
||||||
-- match all up to the cursor if moved or no matchphrase
|
|
||||||
if matchp == "" or
|
|
||||||
cmd:sub(cur_pos, cur_pos+#matchp) ~= matchp then
|
|
||||||
matchp = cmd:sub(1, cur_pos)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- find matching commands
|
|
||||||
local matches = {}
|
|
||||||
for i, src in ipairs(sources) do
|
|
||||||
local source = get_source[src]()
|
|
||||||
for j, matcher in ipairs(matchers) do
|
|
||||||
for k, name in ipairs(source) do
|
|
||||||
if name:find(matcher .. matchp) then
|
|
||||||
table.insert(matches, name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- no matches
|
|
||||||
if #matches == 0 then return cmd, cur_pos end
|
|
||||||
|
|
||||||
-- remove duplicates
|
|
||||||
matches = remove_dup(matches)
|
|
||||||
|
|
||||||
-- cycle
|
|
||||||
while ncomp > #matches do ncomp = ncomp - #matches end
|
|
||||||
|
|
||||||
-- put cursor at the end of the matched phrase
|
|
||||||
if #matches == 1 then
|
|
||||||
cur_pos = #matches[ncomp] + 1
|
|
||||||
else
|
|
||||||
cur_pos = matches[ncomp]:find(matchp) + #matchp
|
|
||||||
end
|
|
||||||
|
|
||||||
-- return match and position
|
|
||||||
return matches[ncomp], cur_pos
|
|
||||||
end
|
|
||||||
|
|
||||||
-- signals
|
|
||||||
capi.client.add_signal("manage", match)
|
|
||||||
capi.client.add_signal("unmanage", sweep)
|
|
||||||
capi.client.remove_signal("manage", awful.tag.withcurrent)
|
|
||||||
|
|
||||||
for s = 1, capi.screen.count() do
|
|
||||||
awful.tag.attached_add_signal(s, "property::selected", sweep)
|
|
||||||
awful.tag.attached_add_signal(s, "tagged", sweep)
|
|
||||||
end
|
|
||||||
|
|
|
@ -1,76 +0,0 @@
|
||||||
-- Drive spotify through playerctl.
|
|
||||||
|
|
||||||
-- Spotify uses the MPRIS D-BUS interface. See more information here:
|
|
||||||
-- http://specifications.freedesktop.org/mpris-spec/latest/
|
|
||||||
|
|
||||||
-- To get the complete interface:
|
|
||||||
-- busctl --user introspect org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2
|
|
||||||
|
|
||||||
local awful = require("awful")
|
|
||||||
local dbg = dbg
|
|
||||||
local pairs = pairs
|
|
||||||
local os = os
|
|
||||||
local capi = {
|
|
||||||
client = client
|
|
||||||
}
|
|
||||||
|
|
||||||
module("vbe/spotify")
|
|
||||||
|
|
||||||
-- Get spotify window
|
|
||||||
local function spotify()
|
|
||||||
local clients = capi.client.get()
|
|
||||||
for k, c in pairs(clients) do
|
|
||||||
if awful.rules.match(c, { instance = "spotify",
|
|
||||||
class = "Spotify" }) then
|
|
||||||
return c
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Send a command to spotify
|
|
||||||
local function cmd(command)
|
|
||||||
awful.util.spawn("playerctl -p spotify " .. command, false)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Show spotify
|
|
||||||
function show()
|
|
||||||
local client = spotify()
|
|
||||||
if client then
|
|
||||||
if not client:isvisible() then
|
|
||||||
awful.tag.viewonly(client:tags()[1])
|
|
||||||
end
|
|
||||||
capi.client.focus = client
|
|
||||||
client:raise()
|
|
||||||
else
|
|
||||||
awful.util.spawn("spotify")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function playpause()
|
|
||||||
cmd("play-pause")
|
|
||||||
end
|
|
||||||
|
|
||||||
function play()
|
|
||||||
cmd("play")
|
|
||||||
end
|
|
||||||
|
|
||||||
function pause()
|
|
||||||
cmd("pause")
|
|
||||||
end
|
|
||||||
|
|
||||||
function stop()
|
|
||||||
cmd("stop")
|
|
||||||
end
|
|
||||||
|
|
||||||
function next()
|
|
||||||
cmd("next")
|
|
||||||
end
|
|
||||||
|
|
||||||
function previous()
|
|
||||||
cmd("previous")
|
|
||||||
end
|
|
||||||
|
|
||||||
function mixer()
|
|
||||||
awful.util.spawn("pavucontrol")
|
|
||||||
end
|
|
|
@ -1,70 +0,0 @@
|
||||||
-- Handle volume (through pulseaudio)
|
|
||||||
|
|
||||||
local awful = require("awful")
|
|
||||||
local naughty = require("naughty")
|
|
||||||
local tonumber = tonumber
|
|
||||||
local string = string
|
|
||||||
local os = os
|
|
||||||
|
|
||||||
-- A bit odd, but...
|
|
||||||
require("lib/icons")
|
|
||||||
local icons = package.loaded["vbe/icons"]
|
|
||||||
|
|
||||||
module("vbe/volume")
|
|
||||||
|
|
||||||
local volid = nil
|
|
||||||
local running = true
|
|
||||||
local function current(what)
|
|
||||||
local out = awful.util.pread("amixer -D pulse sget " .. what)
|
|
||||||
local vol, mute = out:match("([%d]+)%%.*%[([%l]*)")
|
|
||||||
return vol, mute
|
|
||||||
end
|
|
||||||
|
|
||||||
local function change(what, how)
|
|
||||||
if how ~= 0 then
|
|
||||||
local vol, mute = current(what)
|
|
||||||
how = string.format("%d%%", vol+how)
|
|
||||||
else
|
|
||||||
how = "toggle"
|
|
||||||
end
|
|
||||||
os.execute("amixer -q -D pulse sset " .. what .. " " .. how, false)
|
|
||||||
|
|
||||||
local vol, mute = current(what)
|
|
||||||
vol = tonumber(vol)
|
|
||||||
local icon = "high"
|
|
||||||
if mute ~= "on" or vol == 0 then
|
|
||||||
icon = "muted"
|
|
||||||
elseif vol < 30 then
|
|
||||||
icon = "low"
|
|
||||||
elseif vol < 60 then
|
|
||||||
icon = "medium"
|
|
||||||
end
|
|
||||||
local prefix = "audio-volume"
|
|
||||||
if what == "Capture" then
|
|
||||||
prefix = "microphone-sensitivity"
|
|
||||||
end
|
|
||||||
icon = icons.lookup({name = prefix .. "-" .. icon,
|
|
||||||
type = "status"})
|
|
||||||
|
|
||||||
volid = naughty.notify({ text = string.format("%3d %%", vol),
|
|
||||||
icon = icon,
|
|
||||||
font = "Free Sans Bold 24",
|
|
||||||
replaces_id = volid }).id
|
|
||||||
end
|
|
||||||
|
|
||||||
function increase(what)
|
|
||||||
change(what, 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
function decrease(what)
|
|
||||||
change(what, -2)
|
|
||||||
end
|
|
||||||
|
|
||||||
function toggle(what)
|
|
||||||
change(what, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- run pavucontrol
|
|
||||||
function mixer()
|
|
||||||
awful.util.spawn("pavucontrol", false)
|
|
||||||
end
|
|
75
rc.lua
|
@ -1,75 +0,0 @@
|
||||||
require("awful")
|
|
||||||
require("awful.autofocus")
|
|
||||||
require("awful.rules")
|
|
||||||
require("beautiful")
|
|
||||||
require("naughty")
|
|
||||||
|
|
||||||
-- Simple function to load additional LUA files from rc/.
|
|
||||||
function loadrc(name, mod)
|
|
||||||
local success
|
|
||||||
local result
|
|
||||||
|
|
||||||
-- Which file? In rc/ or in lib/?
|
|
||||||
local path = awful.util.getdir("config") .. "/" ..
|
|
||||||
(mod and "lib" or "rc") ..
|
|
||||||
"/" .. name .. ".lua"
|
|
||||||
|
|
||||||
-- If the module is already loaded, don't load it again
|
|
||||||
if mod and package.loaded[mod] then return package.loaded[mod] end
|
|
||||||
|
|
||||||
-- Execute the RC/module file
|
|
||||||
success, result = pcall(function() return dofile(path) end)
|
|
||||||
if not success then
|
|
||||||
naughty.notify({ title = "Error while loading an RC file",
|
|
||||||
text = "When loading `" .. name ..
|
|
||||||
"`, got the following error:\n" .. result,
|
|
||||||
preset = naughty.config.presets.critical
|
|
||||||
})
|
|
||||||
return print("E: error loading RC file '" .. name .. "': " .. result)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Is it a module?
|
|
||||||
if mod then
|
|
||||||
return package.loaded[mod]
|
|
||||||
end
|
|
||||||
|
|
||||||
return result
|
|
||||||
end
|
|
||||||
|
|
||||||
loadrc("errors") -- errors and debug stuff
|
|
||||||
|
|
||||||
-- Create cache directory
|
|
||||||
os.execute("mkdir -p " .. awful.util.getdir("cache"))
|
|
||||||
|
|
||||||
-- Setup xsettings
|
|
||||||
os.execute("~/.config/awesome/bin/xsettingsd-setup")
|
|
||||||
os.execute("systemctl --user start --no-block wallpaper@$(systemd-escape -- ${DISPLAY%.0})")
|
|
||||||
|
|
||||||
-- Global configuration
|
|
||||||
modkey = "Mod4"
|
|
||||||
config = {}
|
|
||||||
config.terminal = "vbeterm"
|
|
||||||
config.termclass = "Vbeterm"
|
|
||||||
config.layouts = {
|
|
||||||
awful.layout.suit.tile,
|
|
||||||
awful.layout.suit.tile.left,
|
|
||||||
awful.layout.suit.tile.bottom,
|
|
||||||
awful.layout.suit.fair,
|
|
||||||
awful.layout.suit.floating,
|
|
||||||
}
|
|
||||||
config.hostname = awful.util.pread('uname -n'):gsub('\n', '')
|
|
||||||
|
|
||||||
-- Remaining modules
|
|
||||||
loadrc("appearance") -- theme and appearance settings
|
|
||||||
loadrc("debug") -- debugging primitive `dbg()`
|
|
||||||
|
|
||||||
loadrc("bindings") -- keybindings
|
|
||||||
loadrc("widgets") -- widgets configuration
|
|
||||||
loadrc("tags") -- tags handling
|
|
||||||
loadrc("xlock") -- lock screen
|
|
||||||
loadrc("signals") -- window manager behaviour
|
|
||||||
loadrc("rules") -- window rules
|
|
||||||
loadrc("quake") -- quake console
|
|
||||||
loadrc("xrandr") -- xrandr menu
|
|
||||||
|
|
||||||
root.keys(config.keys.global)
|
|
|
@ -1,120 +0,0 @@
|
||||||
-- Theme
|
|
||||||
beautiful.init(awful.util.getdir("config") .. "/rc/theme.lua")
|
|
||||||
|
|
||||||
-- Also have a look at `xsettingsd` which is used for GTK 3. At some
|
|
||||||
-- point, when we don't need GTK 2, we can use only xsettingsd and
|
|
||||||
-- avoid duplication.
|
|
||||||
local gtk2 = io.open(os.getenv("HOME") .. "/.gtkrc-2.0", "w")
|
|
||||||
gtk2:write([[
|
|
||||||
gtk-theme-name="Adwaita-dark"
|
|
||||||
gtk-icon-theme-name="Adwaita"
|
|
||||||
gtk-cursor-theme-name="Adwaita"
|
|
||||||
gtk-cursor-theme-size=0
|
|
||||||
gtk-font-name="DejaVu Sans 10"
|
|
||||||
gtk-button-images=1
|
|
||||||
gtk-menu-images=1
|
|
||||||
gtk-fallback-icon-theme="gnome"
|
|
||||||
gtk-toolbar-style=GTK_TOOLBAR_BOTH
|
|
||||||
gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR
|
|
||||||
gtk-decoration-layout=":menu"
|
|
||||||
gtk-xft-antialias=1
|
|
||||||
gtk-xft-hinting=1
|
|
||||||
gtk-xft-hintstyle="hintslight"
|
|
||||||
gtk-xft-rgba="rgb"
|
|
||||||
|
|
||||||
gtk-key-theme-name="Emacs"
|
|
||||||
binding "vbe-text-entry-bindings" {
|
|
||||||
unbind "<ctrl>b"
|
|
||||||
unbind "<shift><ctrl>b"
|
|
||||||
unbind "<ctrl>f"
|
|
||||||
unbind "<shift><ctrl>f"
|
|
||||||
unbind "<ctrl>w"
|
|
||||||
bind "<alt>BackSpace" { "delete-from-cursor" (word-ends, -1) }
|
|
||||||
}
|
|
||||||
class "GtkEntry" binding "vbe-text-entry-bindings"
|
|
||||||
class "GtkTextView" binding "vbe-text-entry-bindings"
|
|
||||||
]])
|
|
||||||
gtk2:close()
|
|
||||||
|
|
||||||
os.execute("mkdir -p ~/.config/gtk-3.0")
|
|
||||||
os.execute("rm -f ~/.config/gtk-3.0/settings.ini")
|
|
||||||
local gtk3 = io.open(os.getenv("HOME") .. "/.config/gtk-3.0/gtk.css", "w")
|
|
||||||
gtk3:write([[
|
|
||||||
/* Useless: we cannot override properly by unbinding some keys */
|
|
||||||
/* @import url("/usr/share/themes/Emacs/gtk-3.0/gtk-keys.css"); */
|
|
||||||
|
|
||||||
@binding-set custom-text-entry
|
|
||||||
{
|
|
||||||
bind "<alt>b" { "move-cursor" (words, -1, 0) };
|
|
||||||
bind "<shift><alt>b" { "move-cursor" (words, -1, 1) };
|
|
||||||
bind "<alt>f" { "move-cursor" (words, 1, 0) };
|
|
||||||
bind "<shift><alt>f" { "move-cursor" (words, 1, 1) };
|
|
||||||
|
|
||||||
bind "<ctrl>a" { "move-cursor" (paragraph-ends, -1, 0) };
|
|
||||||
bind "<shift><ctrl>a" { "move-cursor" (paragraph-ends, -1, 1) };
|
|
||||||
bind "<ctrl>e" { "move-cursor" (paragraph-ends, 1, 0) };
|
|
||||||
bind "<shift><ctrl>e" { "move-cursor" (paragraph-ends, 1, 1) };
|
|
||||||
|
|
||||||
bind "<ctrl>y" { "paste-clipboard" () };
|
|
||||||
|
|
||||||
bind "<ctrl>d" { "delete-from-cursor" (chars, 1) };
|
|
||||||
bind "<alt>d" { "delete-from-cursor" (word-ends, 1) };
|
|
||||||
bind "<ctrl>k" { "delete-from-cursor" (paragraph-ends, 1) };
|
|
||||||
bind "<alt>backslash" { "delete-from-cursor" (whitespace, 1) };
|
|
||||||
bind "<alt>BackSpace" { "delete-from-cursor" (word-ends, -1) };
|
|
||||||
|
|
||||||
bind "<alt>space" { "delete-from-cursor" (whitespace, 1)
|
|
||||||
"insert-at-cursor" (" ") };
|
|
||||||
bind "<alt>KP_Space" { "delete-from-cursor" (whitespace, 1)
|
|
||||||
"insert-at-cursor" (" ") };
|
|
||||||
}
|
|
||||||
|
|
||||||
entry, textview
|
|
||||||
{
|
|
||||||
-gtk-key-bindings: custom-text-entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
.window-frame, .window-frame:backdrop {
|
|
||||||
box-shadow: 0 0 0 black;
|
|
||||||
border-style: none;
|
|
||||||
margin: 0;
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.titlebar {
|
|
||||||
border-radius: 0;
|
|
||||||
}
|
|
||||||
]])
|
|
||||||
gtk3:close()
|
|
||||||
|
|
||||||
-- For QT, use qt5ct
|
|
||||||
os.execute("mkdir -p ~/.config/qt5ct")
|
|
||||||
local qt5ct = io.open(os.getenv("HOME") .. "/.config/qt5ct/qt5ct.conf", "w")
|
|
||||||
qt5ct:write([[
|
|
||||||
[Appearance]
|
|
||||||
custom_palette=false
|
|
||||||
icon_theme=Adwaita
|
|
||||||
standard_dialogs=gtk3
|
|
||||||
style=Adwaita-dark
|
|
||||||
|
|
||||||
[Fonts]
|
|
||||||
fixed=@Variant(\0\0\0@\0\0\0 \0\x44\0\x65\0j\0\x61\0V\0u\0 \0S\0\x61\0n\0s\0 \0M\0o\0n\0o@$\0\0\0\0\0\0\xff\xff\xff\xff\x5\x1\0\x32\x10)
|
|
||||||
general=@Variant(\0\0\0@\0\0\0\x16\0\x44\0\x65\0j\0\x61\0V\0u\0 \0S\0\x61\0n\0s@$\0\0\0\0\0\0\xff\xff\xff\xff\x5\x1\0\x32\x10)
|
|
||||||
]])
|
|
||||||
qt5ct:close()
|
|
||||||
|
|
||||||
-- The systray is a bit complex. We need to configure it to display
|
|
||||||
-- the right colors. Here is a link with more background about this:
|
|
||||||
-- http://thread.gmane.org/gmane.comp.window-managers.awesome/9028
|
|
||||||
xprop = assert(io.popen("xprop -root _NET_SUPPORTING_WM_CHECK"))
|
|
||||||
wid = xprop:read():match("^_NET_SUPPORTING_WM_CHECK.WINDOW.: window id # (0x[%S]+)$")
|
|
||||||
xprop:close()
|
|
||||||
if wid then
|
|
||||||
wid = tonumber(wid) + 1
|
|
||||||
os.execute("xprop -id " .. wid .. " -format _NET_SYSTEM_TRAY_COLORS 32c " ..
|
|
||||||
"-set _NET_SYSTEM_TRAY_COLORS " ..
|
|
||||||
"65535,65535,65535,65535,8670,8670,65535,32385,0,8670,65535,8670")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set cursor theme
|
|
||||||
os.execute("xsetroot -cursor_name left_ptr")
|
|
317
rc/bindings.lua
|
@ -1,317 +0,0 @@
|
||||||
config.keys = {}
|
|
||||||
config.mouse = {}
|
|
||||||
local volume = loadrc("volume", "vbe/volume")
|
|
||||||
local brightness = loadrc("brightness", "vbe/brightness")
|
|
||||||
local keydoc = loadrc("keydoc", "vbe/keydoc")
|
|
||||||
|
|
||||||
local function screenshot()
|
|
||||||
awful.util.spawn_with_shell("flameshot gui -r | xclip -selection clipboard -t image/png",
|
|
||||||
false)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Function to toggle a given window to the currently selected and
|
|
||||||
-- focused tag. We need a filter. This function can be used to focus a
|
|
||||||
-- particular window. When the filter is unable to select something,
|
|
||||||
-- we undo previous actions (hence "toggle"). This function returns a
|
|
||||||
-- function that will effectively toggle things.
|
|
||||||
local function toggle_window(filter)
|
|
||||||
local undo = {} -- undo stack
|
|
||||||
client.add_signal('unmanage',
|
|
||||||
function(c)
|
|
||||||
-- If the client is in the undo stack, remove it
|
|
||||||
while true do
|
|
||||||
idx = awful.util.table.hasitem(undo, c)
|
|
||||||
if not idx then break end
|
|
||||||
table.remove(undo, idx)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
local toggle = function()
|
|
||||||
-- "Current" screen
|
|
||||||
local s = client.focus and client.focus.screen or mouse.screen
|
|
||||||
local cl = filter() -- Client to toggle
|
|
||||||
if cl and client.focus ~= cl then
|
|
||||||
-- So, we have a client.
|
|
||||||
if not cl:isvisible() then
|
|
||||||
-- But it is not visible. So we will add it to the current
|
|
||||||
-- tag of the screen where it currently is
|
|
||||||
local t = assert(awful.tag.selected(cl.screen))
|
|
||||||
-- Add our tag to the client
|
|
||||||
undo[#undo + 1] = { cl, t }
|
|
||||||
awful.client.toggletag(t, cl)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Focus and raise the client
|
|
||||||
if s ~= cl.screen then
|
|
||||||
mouse.screen = cl.screen
|
|
||||||
end
|
|
||||||
client.focus = cl
|
|
||||||
cl:raise()
|
|
||||||
else
|
|
||||||
-- OK, we need to restore the previously pushed window to its
|
|
||||||
-- original state.
|
|
||||||
local i = #undo
|
|
||||||
while i > 0 do
|
|
||||||
local cl, t = unpack(undo[i])
|
|
||||||
-- We only handle visible clients that are attached to the
|
|
||||||
-- appropriate tag. Otherwise, we try the next one.
|
|
||||||
if cl and cl:isvisible() and t.selected and
|
|
||||||
awful.util.table.hasitem(cl:tags(), t) then
|
|
||||||
awful.client.toggletag(t, cl)
|
|
||||||
table.remove(undo, i)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
i = i - 1
|
|
||||||
end
|
|
||||||
-- Clean up...
|
|
||||||
while #undo > 10 do
|
|
||||||
table.remove(undo, 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return toggle
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Toggle IM conversation window
|
|
||||||
local toggle_im = toggle_window(
|
|
||||||
(function ()
|
|
||||||
local adding = true
|
|
||||||
local choose = function()
|
|
||||||
local cls = client.get()
|
|
||||||
local focus = client.focus
|
|
||||||
local rules = { { class = "Pidgin",
|
|
||||||
role = "conversation" },
|
|
||||||
{ class = "Skype",
|
|
||||||
role = "ConversationsWindow" } }
|
|
||||||
-- Score. We want a Pidgin window. Then:
|
|
||||||
-- 1. Urgent, visible, not focused
|
|
||||||
-- 2. Urgent, not visible, not focused.
|
|
||||||
-- 3. Not urgent, not visible, not focused
|
|
||||||
-- 4. Focused
|
|
||||||
-- 5. Visible, not focused
|
|
||||||
local function score(cl)
|
|
||||||
local found = false
|
|
||||||
for _, rule in pairs(rules) do
|
|
||||||
if awful.rules.match(cl, rule) then
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not found then return -10 end
|
|
||||||
|
|
||||||
local urgent = cl.urgent
|
|
||||||
local focused = (focus == cl)
|
|
||||||
local visible = cl:isvisible()
|
|
||||||
if urgent and visible and not focused then return 100 end
|
|
||||||
if urgent and not visible and not focused then return 90 end
|
|
||||||
if not adding and focused then return 80 end
|
|
||||||
if adding and not urgent and not visible then return 70 end
|
|
||||||
if focused then return 50 end
|
|
||||||
if not urgent and not visible then return 40 end
|
|
||||||
return 10
|
|
||||||
end
|
|
||||||
table.sort(cls, function(c1, c2)
|
|
||||||
local s1 = score(c1)
|
|
||||||
local s2 = score(c2)
|
|
||||||
return s1 > s2
|
|
||||||
end)
|
|
||||||
local candidate = cls[1]
|
|
||||||
if candidate == nil then return nil end
|
|
||||||
local found = false
|
|
||||||
for _, rule in pairs(rules) do
|
|
||||||
if awful.rules.match(candidate, rule) then
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not found then return nil end
|
|
||||||
|
|
||||||
-- Maybe we need to switch direction
|
|
||||||
if candidate == focus and adding then adding = false
|
|
||||||
elseif candidate ~= focus and not adding then adding = true end
|
|
||||||
|
|
||||||
return candidate
|
|
||||||
end
|
|
||||||
return choose
|
|
||||||
end)())
|
|
||||||
|
|
||||||
-- Toggle urgent window
|
|
||||||
local toggle_urgent = toggle_window(awful.client.urgent.get)
|
|
||||||
|
|
||||||
-- Focus a relative screen (similar to `awful.screen.focus_relative`)
|
|
||||||
local function screen_focus(i)
|
|
||||||
local s = awful.util.cycle(screen.count(), mouse.screen + i)
|
|
||||||
local c = awful.client.focus.history.get(s, 0)
|
|
||||||
mouse.screen = s
|
|
||||||
if c then client.focus = c end
|
|
||||||
end
|
|
||||||
|
|
||||||
local music = loadrc("spotify", "vbe/spotify")
|
|
||||||
|
|
||||||
local display_nmaster_ncol =
|
|
||||||
(function()
|
|
||||||
local nid = nil
|
|
||||||
return function()
|
|
||||||
local nmaster = awful.tag.getnmaster()
|
|
||||||
local ncol = awful.tag.getncol()
|
|
||||||
nid = naughty.notify(
|
|
||||||
{ title = "Tag configuration",
|
|
||||||
timeout = 5,
|
|
||||||
text = "Number of masters: " .. nmaster ..
|
|
||||||
"\nNumber of columns: " .. ncol,
|
|
||||||
replaces_id = nid }).id
|
|
||||||
end
|
|
||||||
end)()
|
|
||||||
|
|
||||||
config.keys.global = awful.util.table.join(
|
|
||||||
keydoc.group("Focus"),
|
|
||||||
awful.key({ modkey, }, "j",
|
|
||||||
function ()
|
|
||||||
awful.client.focus.byidx( 1)
|
|
||||||
if client.focus then
|
|
||||||
client.focus:raise()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
"Focus next window"),
|
|
||||||
awful.key({ modkey, }, "k",
|
|
||||||
function ()
|
|
||||||
awful.client.focus.byidx(-1)
|
|
||||||
if client.focus then
|
|
||||||
client.focus:raise()
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
"Focus previous window"),
|
|
||||||
awful.key({ modkey, }, "u", toggle_im,
|
|
||||||
"Toggle Pidgin conversation window"),
|
|
||||||
awful.key({ modkey, "Control" }, "j", function ()
|
|
||||||
screen_focus(-1)
|
|
||||||
end,
|
|
||||||
"Jump to next screen"),
|
|
||||||
awful.key({ modkey, "Control" }, "k", function ()
|
|
||||||
screen_focus( 1)
|
|
||||||
end),
|
|
||||||
|
|
||||||
keydoc.group("Layout manipulation"),
|
|
||||||
awful.key({ modkey, }, "l", function () awful.tag.incmwfact( 0.05) end,
|
|
||||||
"Increase master-width factor"),
|
|
||||||
awful.key({ modkey, }, "h", function () awful.tag.incmwfact(-0.05) end,
|
|
||||||
"Decrease master-width factor"),
|
|
||||||
awful.key({ modkey, "Shift" }, "l", function ()
|
|
||||||
awful.tag.incnmaster(1)
|
|
||||||
display_nmaster_ncol()
|
|
||||||
end,
|
|
||||||
"Increase number of masters"),
|
|
||||||
awful.key({ modkey, "Shift" }, "h", function ()
|
|
||||||
awful.tag.incnmaster(-1)
|
|
||||||
display_nmaster_ncol()
|
|
||||||
end,
|
|
||||||
"Decrease number of masters"),
|
|
||||||
awful.key({ modkey, "Control" }, "l", function ()
|
|
||||||
awful.tag.incncol(1)
|
|
||||||
display_nmaster_ncol()
|
|
||||||
end,
|
|
||||||
"Increase number of columns"),
|
|
||||||
awful.key({ modkey, "Control" }, "h", function ()
|
|
||||||
awful.tag.incncol(-1)
|
|
||||||
display_nmaster_ncol()
|
|
||||||
end,
|
|
||||||
"Decrease number of columns"),
|
|
||||||
awful.key({ modkey, }, "space", function () awful.layout.inc(config.layouts, 1) end,
|
|
||||||
"Next layout"),
|
|
||||||
awful.key({ modkey, "Shift" }, "space", function () awful.layout.inc(config.layouts, -1) end,
|
|
||||||
"Previous layout"),
|
|
||||||
awful.key({ modkey, "Shift" }, "j", function () awful.client.swap.byidx( 1) end,
|
|
||||||
"Swap with next window"),
|
|
||||||
awful.key({ modkey, "Shift" }, "k", function () awful.client.swap.byidx( -1) end,
|
|
||||||
"Swap with previous window"),
|
|
||||||
|
|
||||||
keydoc.group("Misc"),
|
|
||||||
|
|
||||||
-- Spawn a terminal
|
|
||||||
awful.key({ modkey, }, "Return", function () awful.util.spawn(config.terminal) end,
|
|
||||||
"Spawn a terminal"),
|
|
||||||
|
|
||||||
-- Screenshot
|
|
||||||
awful.key({}, "Print", screenshot),
|
|
||||||
-- Restart awesome
|
|
||||||
awful.key({ modkey, "Control" }, "r", awesome.restart),
|
|
||||||
|
|
||||||
-- Multimedia keys
|
|
||||||
awful.key({ }, "XF86MonBrightnessUp", brightness.increase),
|
|
||||||
awful.key({ }, "XF86MonBrightnessDown", brightness.decrease),
|
|
||||||
awful.key({ }, "XF86AudioRaiseVolume", function() volume.increase("Master") end),
|
|
||||||
awful.key({ }, "XF86AudioLowerVolume", function() volume.decrease("Master") end),
|
|
||||||
awful.key({ }, "XF86AudioMute", function() volume.toggle("Master") end),
|
|
||||||
awful.key({ }, "XF86AudioMicMute", function() volume.toggle("Capture") end),
|
|
||||||
|
|
||||||
awful.key({ }, "XF86AudioPlay", music.playpause),
|
|
||||||
awful.key({ }, "XF86AudioPause", music.pause),
|
|
||||||
awful.key({ }, "XF86AudioStop", music.stop),
|
|
||||||
awful.key({ }, "XF86AudioNext", music.next),
|
|
||||||
awful.key({ }, "XF86AudioPrev", music.previous),
|
|
||||||
|
|
||||||
awful.key({ modkey }, "s", function()
|
|
||||||
keygrabber.run(function(mod, key, event)
|
|
||||||
if event == "release" then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
keygrabber.stop()
|
|
||||||
if key == "z" then music.previous()
|
|
||||||
elseif key == "x" then music.play()
|
|
||||||
elseif key == "c" then music.pause()
|
|
||||||
elseif key == "v" then music.stop()
|
|
||||||
elseif key == "b" then music.next()
|
|
||||||
elseif key == "s" then music.show()
|
|
||||||
elseif key == "m" then music.mixer()
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end)
|
|
||||||
end),
|
|
||||||
|
|
||||||
-- Help
|
|
||||||
awful.key({ modkey, }, "F1", keydoc.display)
|
|
||||||
)
|
|
||||||
|
|
||||||
config.keys.client = awful.util.table.join(
|
|
||||||
keydoc.group("Window-specific bindings"),
|
|
||||||
awful.key({ modkey, }, "f",
|
|
||||||
function (c)
|
|
||||||
c.sticky = false
|
|
||||||
c.fullscreen = not c.fullscreen
|
|
||||||
c:raise()
|
|
||||||
end,
|
|
||||||
"Fullscreen"),
|
|
||||||
awful.key({ modkey, }, "x", function (c) c:kill() end,
|
|
||||||
"Close"),
|
|
||||||
awful.key({ modkey, }, "o",
|
|
||||||
function (c)
|
|
||||||
if screen.count() == 1 then return nil end
|
|
||||||
local s = awful.util.cycle(screen.count(), c.screen + 1)
|
|
||||||
if awful.tag.selected(s) then
|
|
||||||
c.screen = s
|
|
||||||
client.focus = c
|
|
||||||
c:raise()
|
|
||||||
end
|
|
||||||
end, "Move to the other screen"),
|
|
||||||
awful.key({ modkey, "Control" }, "s", function (c) c.sticky = not c.sticky end, "Toggle stickyness"),
|
|
||||||
awful.key({ modkey, "Control" }, "space", awful.client.floating.toggle, "Toggle floating"),
|
|
||||||
awful.key({ modkey, "Control" }, "Return", function (c) c:swap(awful.client.getmaster()) end,
|
|
||||||
"Switch with master window"),
|
|
||||||
awful.key({ modkey, }, "i", dbg,
|
|
||||||
"Get client-related information"),
|
|
||||||
awful.key({ modkey, }, "m",
|
|
||||||
function (c)
|
|
||||||
c.sticky = false
|
|
||||||
c.maximized_horizontal = not c.maximized_horizontal
|
|
||||||
c.maximized_vertical = not c.maximized_vertical
|
|
||||||
c:raise()
|
|
||||||
end,
|
|
||||||
"Maximize")
|
|
||||||
)
|
|
||||||
|
|
||||||
keydoc.group("Misc")
|
|
||||||
|
|
||||||
config.mouse.client = awful.util.table.join(
|
|
||||||
awful.button({ }, 1, function (c) client.focus = c; c:raise() end),
|
|
||||||
awful.button({ modkey }, 1, awful.mouse.client.move),
|
|
||||||
awful.button({ modkey }, 3, awful.mouse.client.resize))
|
|
104
rc/debug.lua
|
@ -1,104 +0,0 @@
|
||||||
local colors = {
|
|
||||||
header = theme.fg_widget_clock,
|
|
||||||
count = theme.fg_widget_label,
|
|
||||||
index = theme.fg_widget_label,
|
|
||||||
name = theme.fg_widget_value_important,
|
|
||||||
}
|
|
||||||
|
|
||||||
local function client_info(c)
|
|
||||||
local v = ""
|
|
||||||
|
|
||||||
-- object
|
|
||||||
local c = c or client.focus
|
|
||||||
v = v .. tostring(c)
|
|
||||||
|
|
||||||
-- geometry
|
|
||||||
local cc = c:geometry()
|
|
||||||
local signx = (cc.x > 0 and "+") or ""
|
|
||||||
local signy = (cc.y > 0 and "+") or ""
|
|
||||||
v = v .. " @ " .. cc.width .. 'x' .. cc.height .. signx .. cc.x .. signy .. cc.y .. "\n\n"
|
|
||||||
|
|
||||||
local inf = {
|
|
||||||
"name", "icon_name", "type", "class", "role", "instance", "pid",
|
|
||||||
"skip_taskbar", "id", "group_window", "leader_id", "machine",
|
|
||||||
"screen", "hidden", "minimized", "size_hints_honor", "titlebar", "urgent",
|
|
||||||
"focus", "opacity", "ontop", "above", "below", "fullscreen", "transient_for",
|
|
||||||
"maximixed_horizontal", "maximixed_vertical", "sticky", "modal", "focusable"
|
|
||||||
}
|
|
||||||
|
|
||||||
for i = 1, #inf do
|
|
||||||
v = v .. string.format('%2s: <span color="%s">%-20s</span> = <span color="%s">%s</span>\n',
|
|
||||||
i,
|
|
||||||
beautiful.fg_widget_label, inf[i],
|
|
||||||
beautiful.fg_widget_value, tostring(c[inf[i]]))
|
|
||||||
end
|
|
||||||
|
|
||||||
naughty.notify{ text = string.format('<span font="' .. theme.font .. '">%s</span>', v:sub(1,#v-1)),
|
|
||||||
timeout = 0, margin = 10, screen = c.screen }
|
|
||||||
end
|
|
||||||
|
|
||||||
local function dbg_get(var, depth, indent)
|
|
||||||
local a = ""
|
|
||||||
local text = ""
|
|
||||||
local name = ""
|
|
||||||
local vtype = type(var)
|
|
||||||
local vstring = tostring(var)
|
|
||||||
|
|
||||||
if vtype == "table" or vtype == "userdata" then
|
|
||||||
if vtype == "userdata" then var = getmetatable(var) end
|
|
||||||
-- element count and longest key
|
|
||||||
local count = 0
|
|
||||||
local longest_key = 3
|
|
||||||
for k,v in pairs(var) do
|
|
||||||
count = count + 1
|
|
||||||
longest_key = math.max(#tostring(k), longest_key)
|
|
||||||
end
|
|
||||||
text = text .. vstring .. " <span color='"..colors.count.."'>#" .. count .. "</span>"
|
|
||||||
-- descend a table
|
|
||||||
if depth > 0 then
|
|
||||||
-- sort keys FIXME: messes up sorting number
|
|
||||||
local sorted = {}
|
|
||||||
for k, v in pairs(var) do table.insert(sorted, { k, v }) end
|
|
||||||
table.sort(sorted, function(a, b) return tostring(a[1]) < tostring(b[1]) end)
|
|
||||||
-- go through elements
|
|
||||||
for _, p in ipairs(sorted) do
|
|
||||||
local key = p[1]; local value = p[2]
|
|
||||||
-- don't descend _M
|
|
||||||
local d; if key ~= "_M" then d = depth - 1 else d = 0 end
|
|
||||||
-- get content and add to output
|
|
||||||
local content = dbg_get(value, d, indent + longest_key + 1)
|
|
||||||
text = text .. '\n' .. string.rep(" ", indent) ..
|
|
||||||
string.format("<span color='"..colors.index.."'>%-"..longest_key.."s</span> %s",
|
|
||||||
tostring(key), content)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if vtype == "tag" or vtype == "client" then
|
|
||||||
name = " [<span color='"..colors.name.."'>" .. (var.name or '…'):sub(1,10) .. "</span>]"
|
|
||||||
end
|
|
||||||
text = text .. vstring .. name or ""
|
|
||||||
end
|
|
||||||
|
|
||||||
return text
|
|
||||||
end
|
|
||||||
|
|
||||||
function dbg(...)
|
|
||||||
local num = table.maxn(arg)
|
|
||||||
local text = "<span color='"..colors.header.."'>dbg</span> <span color='"..colors.count.."'>#"..num.."</span>"
|
|
||||||
local depth = 2
|
|
||||||
local clients = 0
|
|
||||||
|
|
||||||
for i = 1, num do
|
|
||||||
local desc = dbg_get(arg[i], depth, 3)
|
|
||||||
text = text .. string.format("\n<span color='"..colors.index.."'>%2d</span> %s", i, desc)
|
|
||||||
if type(arg[i]) == "client" then
|
|
||||||
client_info(arg[i])
|
|
||||||
clients = clients + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Display only if we don't have only clients to be displayed
|
|
||||||
if clients ~= num then
|
|
||||||
naughty.notify{ text = text, timeout = 0, hover_timeout = 2, screen = screen.count() }
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,14 +0,0 @@
|
||||||
-- Handle runtime errors after startup
|
|
||||||
do
|
|
||||||
local in_error = false
|
|
||||||
awesome.add_signal("debug::error", function (err)
|
|
||||||
-- Make sure we don't go into an endless error loop
|
|
||||||
if in_error then return end
|
|
||||||
in_error = true
|
|
||||||
|
|
||||||
naughty.notify({ preset = naughty.config.presets.critical,
|
|
||||||
title = "Oops, an error happened!",
|
|
||||||
text = err })
|
|
||||||
in_error = false
|
|
||||||
end)
|
|
||||||
end
|
|
10
rc/quake.lua
|
@ -1,10 +0,0 @@
|
||||||
local quake = loadrc("quake", "vbe/quake")
|
|
||||||
local quakeconsole = quake({ terminal = config.terminal,
|
|
||||||
argname = "--name %s",
|
|
||||||
height = 0.3 })
|
|
||||||
|
|
||||||
config.keys.global = awful.util.table.join(
|
|
||||||
config.keys.global,
|
|
||||||
awful.key({ modkey }, "`",
|
|
||||||
function () quakeconsole:toggle() end,
|
|
||||||
"Toggle Quake console"))
|
|
62
rc/rules.lua
|
@ -1,62 +0,0 @@
|
||||||
local icons = loadrc("icons", "vbe/icons")
|
|
||||||
|
|
||||||
awful.rules.rules = {
|
|
||||||
-- All clients will match this rule.
|
|
||||||
{ rule = { },
|
|
||||||
properties = { border_width = beautiful.border_width,
|
|
||||||
border_color = beautiful.border_normal,
|
|
||||||
focus = true,
|
|
||||||
maximized_vertical = false,
|
|
||||||
maximized_horizontal = false,
|
|
||||||
keys = config.keys.client,
|
|
||||||
buttons = config.mouse.client }},
|
|
||||||
-- i3lock
|
|
||||||
{ rule = { name = "i3lock" },
|
|
||||||
properties = { ontop = true } },
|
|
||||||
-- Browser stuff
|
|
||||||
{ rule = { role = "browser" },
|
|
||||||
callback = function(c)
|
|
||||||
if not c.icon then
|
|
||||||
local icon = icons.lookup({ name = "web-browser",
|
|
||||||
type = "apps" })
|
|
||||||
if icon then
|
|
||||||
c.icon = image(icon)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end },
|
|
||||||
{ rule = { class = config.termclass },
|
|
||||||
properties = { icon = image(icons.lookup({ name = "gnome-terminal",
|
|
||||||
type = "apps" })) } },
|
|
||||||
{ rule_any = { class = { "Iceweasel", "Firefox", "Chromium", "Conkeror", "Google-chrome" } },
|
|
||||||
callback = function(c)
|
|
||||||
-- All windows should be slaves, except the browser windows.
|
|
||||||
if c.role ~= "browser" then awful.client.setslave(c) end
|
|
||||||
end },
|
|
||||||
-- See also tags.lua
|
|
||||||
-- Pidgin
|
|
||||||
{ rule = { class = "Pidgin" },
|
|
||||||
except = { role = "buddy_list" },
|
|
||||||
properties = { }, callback = awful.client.setslave },
|
|
||||||
{ rule = { class = "Pidgin", role = "buddy_list" },
|
|
||||||
properties = { }, callback = awful.client.setmaster },
|
|
||||||
-- Shadow
|
|
||||||
{ rule = { class = "Shadow" },
|
|
||||||
properties = { fullscreen = true }},
|
|
||||||
-- Zoom dialogs should not have focus
|
|
||||||
{ rule = { class = "zoom", type = "dialog" },
|
|
||||||
properties = { focus = false }},
|
|
||||||
-- Should not be master
|
|
||||||
{ rule_any = { class =
|
|
||||||
{ config.termclass,
|
|
||||||
"Transmission-gtk"
|
|
||||||
}, instance = { "Download" }},
|
|
||||||
except = { icon_name = "QuakeConsoleNeedsUniqueName" },
|
|
||||||
properties = { },
|
|
||||||
callback = awful.client.setslave },
|
|
||||||
-- Picture in picture
|
|
||||||
{ rule = { name = "Picture-in-Picture" },
|
|
||||||
properties = { floating = true, ontop = true } },
|
|
||||||
-- Floating windows
|
|
||||||
{ rule_any = { class = { "Display.im6", "Key-mon" } },
|
|
||||||
properties = { floating = true }},
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
local icons = loadrc("icons", "vbe/icons")
|
|
||||||
|
|
||||||
-- Did we get the focus because of sloppy focus?
|
|
||||||
local focus_from_mouse = false
|
|
||||||
local function mouse_follow_focus(c)
|
|
||||||
-- Move the mouse to the top left corner
|
|
||||||
if c.type ~= "dialog" then
|
|
||||||
local cc = c:geometry()
|
|
||||||
local _, x, y = awful.mouse.client.corner(nil, "top_left")
|
|
||||||
if x and y then
|
|
||||||
mouse.coords({ x = x + 20 , y = y + cc.height / 2 }, true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Signal function to execute when a new client appears.
|
|
||||||
client.add_signal("manage",
|
|
||||||
function (c, startup)
|
|
||||||
-- Enable sloppy focus
|
|
||||||
c:add_signal("mouse::enter",
|
|
||||||
function(c)
|
|
||||||
-- If magnifier suit, only give sloppy focus to master window
|
|
||||||
if ((awful.layout.get(c.screen) ~= awful.layout.suit.magnifier or
|
|
||||||
awful.client.getmaster(c.screen) == c)
|
|
||||||
-- Don't give focus to a client already having focus
|
|
||||||
and client.focus ~= c
|
|
||||||
-- Don't give focus to a window that does not want focus
|
|
||||||
and awful.client.focus.filter(c)) then
|
|
||||||
focus_from_mouse = c
|
|
||||||
client.focus = c
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- If a window change its geometry, track it with the mouse
|
|
||||||
c:add_signal("property::geometry",
|
|
||||||
function()
|
|
||||||
-- Check if the current focused client is our
|
|
||||||
if client.focus ~=c then return end
|
|
||||||
-- Check that no button is pressed
|
|
||||||
local buttons = mouse.coords().buttons
|
|
||||||
for _, state in pairs(buttons) do
|
|
||||||
if state then return end
|
|
||||||
end
|
|
||||||
mouse_follow_focus(c)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- If this is Spotify and it sets the urgent property, unset it
|
|
||||||
if c.instance == "spotify" then
|
|
||||||
c.urgent = false
|
|
||||||
c:add_signal("property::urgent",
|
|
||||||
function()
|
|
||||||
c.urgent = false
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Setup icon if none exists
|
|
||||||
if not c.icon then
|
|
||||||
local icon = icons.lookup({ name = { c.class, c.instance },
|
|
||||||
type = "apps" })
|
|
||||||
if icon then
|
|
||||||
c.icon = image(icon)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not startup then
|
|
||||||
-- Put windows in a smart way, only if they does not set an initial position.
|
|
||||||
if not c.size_hints.user_position and not c.size_hints.program_position then
|
|
||||||
awful.placement.no_overlap(c)
|
|
||||||
awful.placement.no_offscreen(c)
|
|
||||||
end
|
|
||||||
c:raise()
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
client.add_signal("focus", function(c)
|
|
||||||
c.border_color = beautiful.border_focus
|
|
||||||
c.opacity = 1
|
|
||||||
|
|
||||||
if focus_from_mouse ~= c then
|
|
||||||
mouse_follow_focus(c)
|
|
||||||
c:raise()
|
|
||||||
end
|
|
||||||
focus_from_mouse = false
|
|
||||||
end)
|
|
||||||
client.add_signal("unfocus", function(c)
|
|
||||||
c.border_color = beautiful.border_normal
|
|
||||||
if (not c.fullscreen and
|
|
||||||
not awful.rules.match_any(c, { name = { "Picture-in-Picture" },
|
|
||||||
class = { "zoom" }})) then
|
|
||||||
c.opacity = 0.85
|
|
||||||
end
|
|
||||||
end)
|
|
164
rc/tags.lua
|
@ -1,164 +0,0 @@
|
||||||
-- Tags
|
|
||||||
|
|
||||||
local shifty = loadrc("shifty", "vbe/shifty")
|
|
||||||
local keydoc = loadrc("keydoc", "vbe/keydoc")
|
|
||||||
|
|
||||||
local tagicon = function(icon)
|
|
||||||
if screen.count() > 1 then
|
|
||||||
return beautiful.icons .. "/taglist/" .. icon .. ".png"
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
shifty.config.tags = {
|
|
||||||
www = {
|
|
||||||
position = 3,
|
|
||||||
mwfact = 0.7,
|
|
||||||
exclusive = true,
|
|
||||||
max_clients = 1,
|
|
||||||
screen = math.min(screen.count(), 2),
|
|
||||||
spawn = "xdg-open about:newtab",
|
|
||||||
icon = tagicon("web")
|
|
||||||
},
|
|
||||||
emacs = {
|
|
||||||
position = 2,
|
|
||||||
mwfact = 0.6,
|
|
||||||
exclusive = true,
|
|
||||||
screen = 1,
|
|
||||||
spawn = "emacs",
|
|
||||||
icon = tagicon("dev"),
|
|
||||||
},
|
|
||||||
xterm = {
|
|
||||||
position = 1,
|
|
||||||
layout = awful.layout.suit.fair,
|
|
||||||
exclusive = true,
|
|
||||||
slave = true,
|
|
||||||
spawn = config.terminal,
|
|
||||||
icon = tagicon("main"),
|
|
||||||
},
|
|
||||||
spotify = {
|
|
||||||
screen = 1,
|
|
||||||
exclusive = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Also, see rules.lua
|
|
||||||
shifty.config.apps = {
|
|
||||||
{
|
|
||||||
match = { role = { "browser" } },
|
|
||||||
tag = "www",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match = { "emacs" },
|
|
||||||
tag = "emacs",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match = { class = { "Spotify" } },
|
|
||||||
tag = "spotify"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match = { config.termclass },
|
|
||||||
startup = {
|
|
||||||
tag = "xterm"
|
|
||||||
},
|
|
||||||
intrusive = true, -- Display even on exclusive tags
|
|
||||||
},
|
|
||||||
{
|
|
||||||
match = { class = { "Key[-]mon" },
|
|
||||||
role = { "pop[-]up" },
|
|
||||||
name = { "Firebug", "Picture-in-Picture" },
|
|
||||||
instance = { "plugin[-]container", "exe" } },
|
|
||||||
intrusive = true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
shifty.config.defaults = {
|
|
||||||
layout = config.layouts[1],
|
|
||||||
mwfact = 0.6,
|
|
||||||
ncol = 1,
|
|
||||||
sweep_delay = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
shifty.taglist = config.taglist -- Set in widget.lua
|
|
||||||
shifty.init()
|
|
||||||
|
|
||||||
local tag_del_or_rename = function(tag)
|
|
||||||
if not shifty.del(tag) then
|
|
||||||
shifty.rename(tag)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
config.keys.global = awful.util.table.join(
|
|
||||||
config.keys.global,
|
|
||||||
keydoc.group("Tag management"),
|
|
||||||
awful.key({ modkey }, "Tab", awful.tag.history.restore, "Switch to previous tag"),
|
|
||||||
awful.key({ modkey }, "Left", awful.tag.viewprev),
|
|
||||||
awful.key({ modkey }, "Right", awful.tag.viewnext),
|
|
||||||
awful.key({ modkey, "Shift"}, "o",
|
|
||||||
function()
|
|
||||||
if screen.count() == 1 then return nil end
|
|
||||||
local t = awful.tag.selected()
|
|
||||||
if t == nil then return nil end
|
|
||||||
local s = awful.util.cycle(screen.count(), t.screen + 1)
|
|
||||||
awful.tag.history.restore()
|
|
||||||
t = shifty.tagtoscr(s, t)
|
|
||||||
awful.tag.viewonly(t)
|
|
||||||
end,
|
|
||||||
"Send tag to next screen"),
|
|
||||||
awful.key({ modkey, "Control", "Shift"}, "o",
|
|
||||||
function()
|
|
||||||
if screen.count() == 1 then return nil end
|
|
||||||
local t = awful.tag.selected()
|
|
||||||
if t == nil then return nil end
|
|
||||||
local o = t.screen
|
|
||||||
local s = awful.util.cycle(screen.count(), o + 1)
|
|
||||||
for _, t in pairs(screen[o]:tags()) do
|
|
||||||
shifty.tagtoscr(s, t)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
"Send all tags to next screen"),
|
|
||||||
awful.key({ modkey }, 0, shifty.add, "Create a new tag"),
|
|
||||||
awful.key({ modkey, "Shift" }, 0, tag_del_or_rename),
|
|
||||||
awful.key({ modkey, "Control" }, 0, tag_del_or_rename, "Rename or delete tag"))
|
|
||||||
|
|
||||||
-- Bind all key numbers to tags.
|
|
||||||
-- Be careful: we use keycodes to make it works on any keyboard layout.
|
|
||||||
-- This should map on the top row of your keyboard, usually 1 to 9.
|
|
||||||
for i = 1, (shifty.config.maxtags or 9) do
|
|
||||||
config.keys.global = awful.util.table.join(
|
|
||||||
config.keys.global,
|
|
||||||
keydoc.group("Tag management"),
|
|
||||||
awful.key({ modkey }, i,
|
|
||||||
function ()
|
|
||||||
local t = shifty.getpos(i)
|
|
||||||
local s = t.screen
|
|
||||||
local c = awful.client.focus.history.get(s, 0)
|
|
||||||
awful.tag.viewonly(t)
|
|
||||||
mouse.screen = s
|
|
||||||
if c then client.focus = c end
|
|
||||||
end,
|
|
||||||
i == 5 and "Display only this tag" or nil),
|
|
||||||
awful.key({ modkey, "Control" }, i,
|
|
||||||
function ()
|
|
||||||
local t = shifty.getpos(i)
|
|
||||||
t.selected = not t.selected
|
|
||||||
end,
|
|
||||||
i == 5 and "Toggle display of this tag" or nil),
|
|
||||||
awful.key({ modkey, "Shift" }, i,
|
|
||||||
function ()
|
|
||||||
local c = client.focus
|
|
||||||
if c then
|
|
||||||
local t = shifty.getpos(i, {nospawn = true })
|
|
||||||
awful.client.movetotag(t, c)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
i == 5 and "Move window to this tag" or nil),
|
|
||||||
awful.key({ modkey, "Control", "Shift" }, i,
|
|
||||||
function ()
|
|
||||||
if client.focus then
|
|
||||||
awful.client.toggletag(shifty.getpos(i, {nospawn = true}))
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
i == 5 and "Toggle this tag on this window" or nil),
|
|
||||||
keydoc.group("Misc"))
|
|
||||||
end
|
|
74
rc/theme.lua
|
@ -1,74 +0,0 @@
|
||||||
-- Small modifications to anrxc's zenburn theme
|
|
||||||
|
|
||||||
local na = awful.util.color_strip_alpha
|
|
||||||
local icons = awful.util.getdir("config") .. "/icons"
|
|
||||||
|
|
||||||
local function scale()
|
|
||||||
local xrdb = io.popen("xrdb -query")
|
|
||||||
if xrdb then
|
|
||||||
for line in xrdb:lines() do
|
|
||||||
output = line:match("^Xft.dpi:\t(%d+)$")
|
|
||||||
if output then
|
|
||||||
xrdb:close()
|
|
||||||
return tonumber(output)/96
|
|
||||||
end
|
|
||||||
end
|
|
||||||
xrdb:close()
|
|
||||||
end
|
|
||||||
return 1
|
|
||||||
end
|
|
||||||
|
|
||||||
theme = {}
|
|
||||||
theme.scale = scale()
|
|
||||||
theme.icons = icons
|
|
||||||
theme.wallpaper_cmd = { "/bin/true" }
|
|
||||||
theme.font = "Terminus " .. 9 * theme.scale
|
|
||||||
theme.tasklist_font = "DejaVu Sans " .. 8 * theme.scale
|
|
||||||
|
|
||||||
theme.bg_normal = "#22222299"
|
|
||||||
theme.bg_focus = "#d8d8d8bb"
|
|
||||||
theme.bg_urgent = "#d02e5499"
|
|
||||||
theme.bg_minimize = "#44444499"
|
|
||||||
|
|
||||||
theme.fg_normal = "#cccccc"
|
|
||||||
theme.fg_focus = "#000000"
|
|
||||||
theme.fg_urgent = "#ffffff"
|
|
||||||
theme.fg_minimize = "#ffffff"
|
|
||||||
|
|
||||||
theme.border_width = 4
|
|
||||||
theme.border_normal = "#00000000"
|
|
||||||
theme.border_focus = "#FF7F00"
|
|
||||||
theme.border_marked = "#91231c66"
|
|
||||||
|
|
||||||
-- Widget stuff
|
|
||||||
theme.bg_widget = "#000000BB"
|
|
||||||
theme.fg_widget_label = "#737d8c"
|
|
||||||
theme.fg_widget_value = na(theme.fg_normal)
|
|
||||||
theme.fg_widget_value_important = "#E80F28"
|
|
||||||
theme.fg_widget_border = theme.fg_widget_label
|
|
||||||
theme.fg_widget_clock = na(theme.border_focus)
|
|
||||||
|
|
||||||
-- Taglist
|
|
||||||
theme.taglist_squares_sel = icons .. "/taglist/squarefw.png"
|
|
||||||
theme.taglist_squares_unsel = icons .. "/taglist/squarew.png"
|
|
||||||
|
|
||||||
-- Layout icons
|
|
||||||
for _, l in pairs(config.layouts) do
|
|
||||||
theme["layout_" .. l.name] = icons .. "/layouts/" .. l.name .. ".png"
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Naughty
|
|
||||||
naughty.config.presets.normal.bg = "#111111"
|
|
||||||
for _, preset in pairs({"normal", "low", "critical"}) do
|
|
||||||
naughty.config.presets[preset].font = "DejaVu Sans " .. 10 * theme.scale
|
|
||||||
naughty.config.presets[preset].margin = 12 * theme.scale
|
|
||||||
naughty.config.presets[preset].border_width = 3 * theme.scale
|
|
||||||
end
|
|
||||||
naughty.config.notify_callback = function(args)
|
|
||||||
if args.icon ~= nil and type(args.icon) ~= "string" then
|
|
||||||
args.icon = nil
|
|
||||||
end
|
|
||||||
return args
|
|
||||||
end
|
|
||||||
|
|
||||||
return theme
|
|
318
rc/widgets.lua
|
@ -1,318 +0,0 @@
|
||||||
-- Widgets
|
|
||||||
|
|
||||||
require("vicious")
|
|
||||||
local icons = loadrc("icons", "vbe/icons")
|
|
||||||
|
|
||||||
-- Separators
|
|
||||||
local sepopen = widget({ type = "imagebox" })
|
|
||||||
sepopen.image = image(beautiful.icons .. "/widgets/left.png")
|
|
||||||
local sepclose = widget({ type = "imagebox" })
|
|
||||||
sepclose.image = image(beautiful.icons .. "/widgets/right.png")
|
|
||||||
local spacer = widget({ type = "imagebox" })
|
|
||||||
spacer.image = image(beautiful.icons .. "/widgets/spacer.png")
|
|
||||||
|
|
||||||
-- Date
|
|
||||||
local datewidget = widget({ type = "textbox" })
|
|
||||||
local dateformat = "%a %d/%m, %H:%M"
|
|
||||||
vicious.register(datewidget, vicious.widgets.date,
|
|
||||||
'<span color="' .. beautiful.fg_widget_clock .. '">' ..
|
|
||||||
dateformat .. '</span>')
|
|
||||||
local dateicon = widget({ type = "imagebox" })
|
|
||||||
dateicon.image = image(beautiful.icons .. "/widgets/clock.png")
|
|
||||||
local cal = (
|
|
||||||
function()
|
|
||||||
local calendar = nil
|
|
||||||
local offset = 0
|
|
||||||
|
|
||||||
local remove_calendar = function()
|
|
||||||
if calendar ~= nil then
|
|
||||||
naughty.destroy(calendar)
|
|
||||||
calendar = nil
|
|
||||||
offset = 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local add_calendar = function(inc_offset)
|
|
||||||
local save_offset = offset
|
|
||||||
remove_calendar()
|
|
||||||
offset = save_offset + inc_offset
|
|
||||||
local curdate = os.date("*t")
|
|
||||||
local datespec = curdate.year * 12 + curdate.month - 1 + offset
|
|
||||||
datespec = (datespec % 12 + 1) .. " " .. math.floor(datespec / 12)
|
|
||||||
local cal = awful.util.pread("ncal -h -w -m " .. datespec)
|
|
||||||
-- Highlight the current date and month
|
|
||||||
if offset == 0 then
|
|
||||||
cal, n = cal:gsub(string.format("( %d)([ \n])", curdate.day),
|
|
||||||
string.format('<span color="%s">%%1</span>%%2',
|
|
||||||
beautiful.fg_widget_clock),
|
|
||||||
1)
|
|
||||||
end
|
|
||||||
-- Month and year
|
|
||||||
cal = cal:gsub("^( +[^ ]+ [0-9]+) *",
|
|
||||||
string.format('<span color="%s">%%1</span>',
|
|
||||||
beautiful.fg_widget_clock))
|
|
||||||
-- Turn anything other than days in labels
|
|
||||||
cal = cal:gsub("(\n[^%d ]+)",
|
|
||||||
string.format('<span color="%s">%%1</span>',
|
|
||||||
beautiful.fg_widget_label))
|
|
||||||
cal = cal:gsub("([%d ]+)\n?$",
|
|
||||||
string.format('<span color="%s">%%1</span>',
|
|
||||||
beautiful.fg_widget_label))
|
|
||||||
calendar = naughty.notify(
|
|
||||||
{
|
|
||||||
text = string.format('<span font="%s">%s</span>',
|
|
||||||
theme.font,
|
|
||||||
cal:gsub(" +\n","\n")),
|
|
||||||
timeout = 0, hover_timeout = 0.5,
|
|
||||||
width = 160 * theme.scale,
|
|
||||||
screen = mouse.screen,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
return { add = add_calendar,
|
|
||||||
rem = remove_calendar }
|
|
||||||
end)()
|
|
||||||
|
|
||||||
datewidget:add_signal("mouse::enter", function() cal.add(0) end)
|
|
||||||
datewidget:add_signal("mouse::leave", cal.rem)
|
|
||||||
datewidget:buttons(awful.util.table.join(
|
|
||||||
awful.button({ }, 3, function() cal.add(-1) end),
|
|
||||||
awful.button({ }, 1, function() cal.add(1) end)))
|
|
||||||
|
|
||||||
-- CPU usage
|
|
||||||
local cpuwidget = widget({ type = "textbox" })
|
|
||||||
vicious.register(cpuwidget, vicious.widgets.cpu,
|
|
||||||
function (widget, args)
|
|
||||||
return string.format('<span color="' .. beautiful.fg_widget_value .. '">%2d%%</span>',
|
|
||||||
args[1])
|
|
||||||
end, 7)
|
|
||||||
local cpuicon = widget({ type = "imagebox" })
|
|
||||||
cpuicon.image = image(beautiful.icons .. "/widgets/cpu.png")
|
|
||||||
|
|
||||||
-- Battery
|
|
||||||
local batwidget = { widget = "" }
|
|
||||||
if awful.util.table.hasitem({"guybrush", "zoro"}, config.hostname) then
|
|
||||||
local bat = "BAT0"
|
|
||||||
batwidget.widget = widget({ type = "textbox" })
|
|
||||||
vicious.register(batwidget.widget, vicious.widgets.bat,
|
|
||||||
function (widget, args)
|
|
||||||
local color = beautiful.fg_widget_value
|
|
||||||
local current = args[2]
|
|
||||||
if current < 10 and args[1] == "-" then
|
|
||||||
color = beautiful.fg_widget_value_important
|
|
||||||
-- Maybe we want to display a small warning?
|
|
||||||
if current ~= batwidget.lastwarn then
|
|
||||||
batwidget.lastid = naughty.notify(
|
|
||||||
{ title = "Battery low!",
|
|
||||||
preset = naughty.config.presets.critical,
|
|
||||||
timeout = 20,
|
|
||||||
text = "Battery level is currently " ..
|
|
||||||
current .. "%.\n" .. args[3] ..
|
|
||||||
" left before running out of power.",
|
|
||||||
icon = icons.lookup({name = "battery-caution",
|
|
||||||
type = "status"}),
|
|
||||||
replaces_id = batwidget.lastid }).id
|
|
||||||
batwidget.lastwarn = current
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return string.format('<span color="' .. color ..
|
|
||||||
'">%s%d%%</span>', args[1], current)
|
|
||||||
end,
|
|
||||||
59, bat)
|
|
||||||
end
|
|
||||||
local baticon = widget({ type = "imagebox" })
|
|
||||||
baticon.image = image(beautiful.icons .. "/widgets/bat.png")
|
|
||||||
|
|
||||||
-- Network
|
|
||||||
local netup = widget({ type = "textbox" })
|
|
||||||
local netdown = widget({ type = "textbox" })
|
|
||||||
local netupicon = widget({ type = "imagebox" })
|
|
||||||
netupicon.image = image(beautiful.icons .. "/widgets/up.png")
|
|
||||||
local netdownicon = widget({ type = "imagebox" })
|
|
||||||
netdownicon.image = image(beautiful.icons .. "/widgets/down.png")
|
|
||||||
|
|
||||||
local netgraph = awful.widget.graph()
|
|
||||||
netgraph:set_width(80 * theme.scale):set_height(16 * theme.scale)
|
|
||||||
netgraph:set_stack(true):set_scale(true)
|
|
||||||
netgraph:set_border_color(beautiful.fg_widget_border)
|
|
||||||
netgraph:set_stack_colors({ "#EF8171", "#cfefb3" })
|
|
||||||
netgraph:set_background_color("#00000033")
|
|
||||||
vicious.register(netup, vicious.widgets.net,
|
|
||||||
function (widget, args)
|
|
||||||
-- We sum up/down value for all interfaces
|
|
||||||
local up = 0
|
|
||||||
local down = 0
|
|
||||||
local iface
|
|
||||||
for name, value in pairs(args) do
|
|
||||||
iface = name:match("^{(%S+) down_b}$")
|
|
||||||
if iface and iface ~= "lo" then down = down + value end
|
|
||||||
iface = name:match("^{(%S+) up_b}$")
|
|
||||||
if iface and iface ~= "lo" then up = up + value end
|
|
||||||
end
|
|
||||||
-- Update the graph
|
|
||||||
netgraph:add_value(up, 1)
|
|
||||||
netgraph:add_value(down, 2)
|
|
||||||
-- Format the string representation
|
|
||||||
local format = function(val)
|
|
||||||
if val > 500000 then
|
|
||||||
return string.format("%.1f MB", val/1000000.)
|
|
||||||
elseif val > 500 then
|
|
||||||
return string.format("%.1f KB", val/1000.)
|
|
||||||
end
|
|
||||||
return string.format("%d B", val)
|
|
||||||
end
|
|
||||||
-- Down
|
|
||||||
netdown.text = string.format('<span color="' .. beautiful.fg_widget_value ..
|
|
||||||
'">%08s</span>', format(down))
|
|
||||||
-- Up
|
|
||||||
return string.format('<span color="' .. beautiful.fg_widget_value ..
|
|
||||||
'">%08s</span>', format(up))
|
|
||||||
end, 3)
|
|
||||||
|
|
||||||
-- Memory usage
|
|
||||||
local memwidget = widget({ type = "textbox" })
|
|
||||||
vicious.register(memwidget, vicious.widgets.mem,
|
|
||||||
'<span color="' .. beautiful.fg_widget_value .. '">$1%</span>',
|
|
||||||
19)
|
|
||||||
local memicon = widget({ type = "imagebox" })
|
|
||||||
memicon.image = image(beautiful.icons .. "/widgets/mem.png")
|
|
||||||
|
|
||||||
-- Volume level
|
|
||||||
local volwidget = widget({ type = "textbox" })
|
|
||||||
vicious.register(volwidget, vicious.widgets.volume,
|
|
||||||
'<span color="' .. beautiful.fg_widget_value .. '">$2 $1%</span>',
|
|
||||||
17, "-D pulse Master")
|
|
||||||
volume = loadrc("volume", "vbe/volume")
|
|
||||||
volwidget:buttons(awful.util.table.join(
|
|
||||||
awful.button({ }, 1, volume.mixer),
|
|
||||||
awful.button({ }, 3, function() volume.toggle("Master") end),
|
|
||||||
awful.button({ }, 4, function() volume.increase("Master") end),
|
|
||||||
awful.button({ }, 5, function() volume.decrease("Master") end)))
|
|
||||||
|
|
||||||
-- File systems
|
|
||||||
local fs = { "/",
|
|
||||||
"/home",
|
|
||||||
"/var",
|
|
||||||
"/usr",
|
|
||||||
"/tmp",
|
|
||||||
"/var/lib/systems" }
|
|
||||||
local fsicon = widget({ type = "imagebox" })
|
|
||||||
fsicon.image = image(beautiful.icons .. "/widgets/disk.png")
|
|
||||||
local fswidget = widget({ type = "textbox" })
|
|
||||||
vicious.register(fswidget, vicious.widgets.fs,
|
|
||||||
function (widget, args)
|
|
||||||
local result = ""
|
|
||||||
for _, path in pairs(fs) do
|
|
||||||
local used = args["{" .. path .. " used_p}"]
|
|
||||||
local color = beautiful.fg_widget_value
|
|
||||||
if used then
|
|
||||||
if used > 90 then
|
|
||||||
color = beautiful.fg_widget_value_important
|
|
||||||
end
|
|
||||||
local name = string.gsub(path, "[%w/]*/(%w+)", "%1")
|
|
||||||
if name == "/" then name = "root" end
|
|
||||||
result = string.format(
|
|
||||||
'%s%s<span color="' .. beautiful.fg_widget_label .. '">%s: </span>' ..
|
|
||||||
'<span color="' .. color .. '">%2d%%</span>',
|
|
||||||
result, #result > 0 and " " or "", name, used)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return result
|
|
||||||
end, 53, "-lx fuse -x aufs")
|
|
||||||
|
|
||||||
local notifications = widget({ type = "imagebox" })
|
|
||||||
notifications.image = image(beautiful.icons .. "/widgets/notifications-enabled.png")
|
|
||||||
notifications:buttons(awful.util.table.join(
|
|
||||||
awful.button({ }, 1,
|
|
||||||
function()
|
|
||||||
local state = "enabled"
|
|
||||||
naughty.toggle()
|
|
||||||
if naughty.is_suspended() then
|
|
||||||
state = "disabled"
|
|
||||||
end
|
|
||||||
notifications.image = image(beautiful.icons .. "/widgets/notifications-" .. state .. ".png")
|
|
||||||
end)))
|
|
||||||
|
|
||||||
local systray = widget({ type = "systray" })
|
|
||||||
|
|
||||||
-- Wibox initialisation
|
|
||||||
local wibox = {}
|
|
||||||
local promptbox = {}
|
|
||||||
local layoutbox = {}
|
|
||||||
|
|
||||||
local taglist = {}
|
|
||||||
local tasklist = {}
|
|
||||||
tasklist.buttons = awful.util.table.join(
|
|
||||||
awful.button({ }, 1, function (c)
|
|
||||||
if not c:isvisible() then
|
|
||||||
awful.tag.viewonly(c:tags()[1])
|
|
||||||
end
|
|
||||||
-- This will also un-minimize
|
|
||||||
-- the client, if needed
|
|
||||||
client.focus = c
|
|
||||||
c:raise()
|
|
||||||
end))
|
|
||||||
|
|
||||||
for s = 1, screen.count() do
|
|
||||||
promptbox[s] = awful.widget.prompt({ layout = awful.widget.layout.horizontal.leftright })
|
|
||||||
layoutbox[s] = awful.widget.layoutbox(s)
|
|
||||||
tasklist[s] = awful.widget.tasklist(
|
|
||||||
function(c)
|
|
||||||
local title, color, _, icon = awful.widget.tasklist.label.currenttags(c, s)
|
|
||||||
return title, color, nil, icon
|
|
||||||
end, tasklist.buttons)
|
|
||||||
|
|
||||||
-- Create the taglist
|
|
||||||
taglist[s] = awful.widget.taglist.new(s,
|
|
||||||
awful.widget.taglist.label.all)
|
|
||||||
-- Create the wibox
|
|
||||||
wibox[s] = awful.wibox({ screen = s,
|
|
||||||
fg = beautiful.fg_normal,
|
|
||||||
bg = beautiful.bg_widget,
|
|
||||||
position = "top",
|
|
||||||
height = 16 * theme.scale,
|
|
||||||
})
|
|
||||||
-- Add widgets to the wibox
|
|
||||||
local on = function(n, what)
|
|
||||||
if s == n or n > screen.count() then return what end
|
|
||||||
return ""
|
|
||||||
end
|
|
||||||
|
|
||||||
wibox[s].widgets = {
|
|
||||||
{
|
|
||||||
screen.count() > 1 and sepopen or "",
|
|
||||||
taglist[s],
|
|
||||||
screen.count() > 1 and spacer or "",
|
|
||||||
layoutbox[s],
|
|
||||||
screen.count() > 1 and sepclose or "",
|
|
||||||
promptbox[s],
|
|
||||||
layout = awful.widget.layout.horizontal.leftright
|
|
||||||
},
|
|
||||||
on(1, systray),
|
|
||||||
on(1, notifications),
|
|
||||||
sepclose, datewidget, screen.count() > 1 and dateicon or "", spacer,
|
|
||||||
on(2, volwidget), on(2, spacer),
|
|
||||||
|
|
||||||
on(2, batwidget.widget),
|
|
||||||
on(2, batwidget.widget ~= "" and baticon or ""),
|
|
||||||
on(2, batwidget.widget ~= "" and spacer or ""),
|
|
||||||
|
|
||||||
on(2, fswidget), screen.count() > 1 and on(2, fsicon) or "",
|
|
||||||
screen.count() > 1 and on(2, sepopen) or on(2, spacer),
|
|
||||||
|
|
||||||
screen.count() > 1 and on(1, netgraph.widget) or "",
|
|
||||||
on(1, netdownicon), on(1, netdown),
|
|
||||||
on(1, netupicon), on(1, netup), on(1, spacer),
|
|
||||||
|
|
||||||
on(1, memwidget), on(1, memicon), on(1, spacer),
|
|
||||||
on(1, cpuwidget), on(1, cpuicon), on(1, sepopen),
|
|
||||||
tasklist[s],
|
|
||||||
layout = awful.widget.layout.horizontal.rightleft }
|
|
||||||
end
|
|
||||||
|
|
||||||
config.keys.global = awful.util.table.join(
|
|
||||||
config.keys.global,
|
|
||||||
awful.key({ modkey }, "r", function () promptbox[mouse.screen]:run() end,
|
|
||||||
"Prompt for a command"))
|
|
||||||
|
|
||||||
config.taglist = taglist
|
|
10
rc/xlock.lua
|
@ -1,10 +0,0 @@
|
||||||
-- Lockscreen
|
|
||||||
|
|
||||||
local lock = function()
|
|
||||||
os.execute("xset s activate")
|
|
||||||
end
|
|
||||||
|
|
||||||
config.keys.global = awful.util.table.join(
|
|
||||||
config.keys.global,
|
|
||||||
awful.key({}, "XF86ScreenSaver", lock),
|
|
||||||
awful.key({ modkey, }, "Delete", lock))
|
|
|
@ -1,66 +0,0 @@
|
||||||
-- Menu with autorandr choices
|
|
||||||
|
|
||||||
local icons = loadrc("icons", "vbe/icons")
|
|
||||||
|
|
||||||
-- Build available choices
|
|
||||||
local function menu()
|
|
||||||
return {
|
|
||||||
{ "Autodetect", "autorandr --change" },
|
|
||||||
{ "Clone", "autorandr --load common" },
|
|
||||||
{ "Horizontal", "autorandr --load horizontal" },
|
|
||||||
{ "Vertical", "autorandr --load vertical" },
|
|
||||||
{ "Keep current configuration", nil },
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Display xrandr notifications from choices
|
|
||||||
local state = { iterator = nil,
|
|
||||||
timer = nil,
|
|
||||||
cid = nil }
|
|
||||||
local function xrandr()
|
|
||||||
-- Stop any previous timer
|
|
||||||
if state.timer then
|
|
||||||
state.timer:stop()
|
|
||||||
state.timer = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Build the list of choices
|
|
||||||
if not state.iterator then
|
|
||||||
state.iterator = awful.util.table.cycle(
|
|
||||||
menu(),
|
|
||||||
function() return true end)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Select one and display the appropriate notification
|
|
||||||
local next = state.iterator()
|
|
||||||
local label, action
|
|
||||||
if not next then
|
|
||||||
state.iterator = nil
|
|
||||||
return xrandr()
|
|
||||||
else
|
|
||||||
label, action = unpack(next)
|
|
||||||
end
|
|
||||||
state.cid = naughty.notify({ text = label,
|
|
||||||
icon = icons.lookup({ name = "display", type = "devices" }),
|
|
||||||
timeout = 4,
|
|
||||||
screen = mouse.screen, -- Important, not all screens may be visible
|
|
||||||
font = "Free Sans 18",
|
|
||||||
replaces_id = state.cid }).id
|
|
||||||
|
|
||||||
-- Setup the timer
|
|
||||||
state.timer = timer { timeout = 4 }
|
|
||||||
state.timer:add_signal("timeout",
|
|
||||||
function()
|
|
||||||
state.timer:stop()
|
|
||||||
state.timer = nil
|
|
||||||
state.iterator = nil
|
|
||||||
if action then
|
|
||||||
awful.util.spawn(action, false)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
state.timer:start()
|
|
||||||
end
|
|
||||||
|
|
||||||
config.keys.global = awful.util.table.join(
|
|
||||||
config.keys.global,
|
|
||||||
awful.key({}, "XF86Display", xrandr))
|
|
|
@ -1,16 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Awesome window manager for %I
|
|
||||||
PartOf=graphical-session@%i.target
|
|
||||||
After=autorandr@%i.service
|
|
||||||
After=picom@%i.service
|
|
||||||
After=xsettingsd@%i.service
|
|
||||||
After=tmux.service
|
|
||||||
After=ssh-agent.service
|
|
||||||
Before=nm-applet@%i.service
|
|
||||||
Before=wallpaper@%i.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStart=/usr/bin/awesome
|
|
||||||
ExecStopPost=/bin/systemctl --user stop graphical-session@%i.target
|
|
||||||
Restart=on-failure
|
|
|
@ -1,18 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Graphical user session for %I
|
|
||||||
StopWhenUnneeded=yes
|
|
||||||
Wants=autorandr@%i.service
|
|
||||||
Wants=awesome@%i.service
|
|
||||||
Wants=picom@%i.service
|
|
||||||
Wants=inputplug@%i.service
|
|
||||||
Wants=misc-x@%i.service
|
|
||||||
Wants=nm-applet@%i.service
|
|
||||||
Wants=policykit-agent@%i.service
|
|
||||||
Wants=redshift@%i.service
|
|
||||||
Wants=wallpaper@%i.timer
|
|
||||||
Wants=xiccd@%i.service
|
|
||||||
Wants=xsettingsd@%i.service
|
|
||||||
Wants=xss-lock@%i.service
|
|
||||||
Wants=tmux.service
|
|
||||||
Wants=ssh-agent.service
|
|
||||||
Wants=pulseaudio.service
|
|
|
@ -1,9 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=XInput event monitor for %I
|
|
||||||
PartOf=graphical-session@%i.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStartPre=/usr/bin/setxkbmap us
|
|
||||||
ExecStart=%h/.local/bin/inputplug -d -0 -c %h/.config/awesome/bin/input-event
|
|
||||||
Restart=on-failure
|
|
|
@ -1,11 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Miscellaneous settings for X11 on %I
|
|
||||||
PartOf=graphical-session@%i.target
|
|
||||||
After=ssh-agent.service
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStart=/usr/bin/xset -b
|
|
||||||
ExecStart=%h/.config/awesome/bin/ssh-add
|
|
||||||
Type=oneshot
|
|
||||||
RemainAfterExit=false
|
|
|
@ -1,8 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Network Manager applet for %I
|
|
||||||
PartOf=graphical-session@%i.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStart=/usr/bin/nm-applet
|
|
||||||
Restart=on-failure
|
|
|
@ -1,10 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Compositor for X11 on %I
|
|
||||||
PartOf=graphical-session@%i.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStart=/usr/bin/picom --backend glx \
|
|
||||||
--xrender-sync-fence \
|
|
||||||
--vsync
|
|
||||||
Restart=on-failure
|
|
|
@ -1,9 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=SSH key agent
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
|
|
||||||
ExecStartPre=/usr/bin/dbus-update-activation-environment SSH_AUTH_SOCK
|
|
||||||
ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK
|
|
||||||
Restart=always
|
|
|
@ -1,14 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Build a wallpaper for %I
|
|
||||||
PartOf=graphical-session@%i.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=DISPLAY=%I
|
|
||||||
Environment=WALLPAPER_DIRECTORY=%h/.config/awesome/wallpapers
|
|
||||||
Environment=WALLPAPER_OUTPUT=%h/.cache/awesome/current-wallpaper-%i.png
|
|
||||||
ExecStart=%h/.config/awesome/bin/build-wallpaper --crop \
|
|
||||||
--directory $WALLPAPER_DIRECTORY \
|
|
||||||
--target $WALLPAPER_OUTPUT
|
|
||||||
ExecStart=/usr/bin/fvwm-root -r $WALLPAPER_OUTPUT
|
|
||||||
Type=oneshot
|
|
||||||
RemainAfterExit=false
|
|
|
@ -1,7 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Wallpaper rotation for %I
|
|
||||||
PartOf=graphical-session@%i.target
|
|
||||||
|
|
||||||
[Timer]
|
|
||||||
OnUnitActiveSec=2h
|
|
||||||
RandomizedDelaySec=10m
|
|
|
@ -1,8 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=X color management for %I
|
|
||||||
PartOf=graphical-session@%i.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStart=/usr/bin/xiccd --edid
|
|
||||||
Restart=on-failure
|
|
|
@ -1,3 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=X session on %I
|
|
||||||
BindsTo=graphical-session@%i.target
|
|
|
@ -1,9 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=XSETTINGS daemon for %I
|
|
||||||
PartOf=graphical-session@%i.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStart=/usr/bin/xsettingsd -c %h/.xsettingsd
|
|
||||||
ExecReload=/usr/bin/kill -HUP $MAINPID
|
|
||||||
Restart=on-failure
|
|
|
@ -1,8 +0,0 @@
|
||||||
[Unit]
|
|
||||||
Description=Manage X screen saver on %I
|
|
||||||
PartOf=graphical-session@%i.target
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Environment=DISPLAY=%I
|
|
||||||
ExecStart=%h/.config/awesome/bin/xss-lock start
|
|
||||||
Restart=on-failure
|
|
20
xsession
|
@ -3,9 +3,6 @@
|
||||||
# Ensure we use the appropriate gtkrc-2.0 file
|
# Ensure we use the appropriate gtkrc-2.0 file
|
||||||
export GTK2_RC_FILES=$HOME/.gtkrc-2.0
|
export GTK2_RC_FILES=$HOME/.gtkrc-2.0
|
||||||
|
|
||||||
# Java incompatibility with awesome
|
|
||||||
export _JAVA_AWT_WM_NONREPARENTING=1
|
|
||||||
|
|
||||||
# We do not want to rely on crappy mailcap
|
# We do not want to rely on crappy mailcap
|
||||||
export MAILCAPS=$HOME/.mailcap
|
export MAILCAPS=$HOME/.mailcap
|
||||||
|
|
||||||
|
@ -20,9 +17,20 @@ export NO_AT_BRIDGE=1
|
||||||
unset LC_ALL
|
unset LC_ALL
|
||||||
[ -e ~/.zshenv ] && . ~/.zshenv
|
[ -e ~/.zshenv ] && . ~/.zshenv
|
||||||
|
|
||||||
|
# Copy dotfiles
|
||||||
|
while read source target; do
|
||||||
|
mkdir -p $(dirname $target)
|
||||||
|
ln -sf ~/.config/i3/dotfiles/$source $HOME/$target
|
||||||
|
done <<EOF
|
||||||
|
Xresources .Xresources
|
||||||
|
gtkrc-2.0 .gtkrc-2.0
|
||||||
|
gtkrc-3.0 .config/gtk-3.0/settings.ini
|
||||||
|
qt5ct.conf .config/qt5ct/qt5ct.conf
|
||||||
|
systemd .config/systemd/user
|
||||||
|
firefox.js .mozilla/firefox/*/user.js
|
||||||
|
EOF
|
||||||
|
|
||||||
# Services are started with systemd
|
# Services are started with systemd
|
||||||
systemctl --user import-environment
|
systemctl --user import-environment
|
||||||
mkdir -p ~/.config/systemd
|
|
||||||
ln -nsf ~/.config/awesome/systemd ~/.config/systemd/user
|
|
||||||
systemctl --user daemon-reload
|
systemctl --user daemon-reload
|
||||||
exec systemctl --user start --wait xsession@$(systemd-escape -- "$DISPLAY").target
|
exec systemctl --user start --wait xsession.target
|
||||||
|
|